/*
 *   DIS/x : An implementation of the IEEE 1278.1 protocol
 *
 *   Copyright (C) 1997, Riley Rainey (rrainey@ix.netcom.com)
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of either:
 *
 *   a) the GNU Library General Public License as published by the Free
 *   Software Foundation; either version 2 of the License, or (at your
 *   option) any later version.  A description of the terms and conditions
 *   of the GLPL may be found in the "COPYING.LIB" file.
 *
 *   b) the "Artistic License" which comes with this Kit.  Information
 *   about this license may be found in the "Artistic" file.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Library General Public License or the Artistic License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free
 *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *   Information describing how to contact the author can be found in the
 *   README file.
 */

/**
 * DIS types and data structure and basic access routines.
 * Basically compliant with IEEE 1278.1-1995, but some more declaration added
 * for future upgrade of this compliance.
 * 
 * @file
 * @author Riley Rainey
 * @version $Date: 2017/10/28 10:41:22 $
 */

#ifndef DIS_H
#define DIS_H

#ifdef WINNT
#include <stdint.h>
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif

#include "earth.h"
#include "../../V/Vlibmath.h" // needs VMatrix type

#ifdef dis_IMPORT
	#define EXTERN
#else
	#define EXTERN extern
#endif

// FI = field information
#define PDUTypeOther                    0
#define PDUTypeEntityState              1
#define PDUTypeFire                     2
#define PDUTypeDetonation               3
#define PDUTypeCollision                4
#define PDUTypeServiceRequest           5
#define PDUTypeResupplyOffer            6
#define PDUTypeResupplyReceived         7
#define PDUTypeResupplyCancel           8
#define PDUTypeRepairComplete           9
#define PDUTypeRepairResponse           10
#define PDUTypeCreateEntity             11
#define PDUTypeRemoveEntity             12
#define PDUTypeStartResume              13
#define PDUTypeStopFreeze               14
#define PDUTypeAcknowledge              15
#define PDUTypeActionRequest            16
#define PDUTypeActionResponse           17
#define PDUTypeDataQuery                18
#define PDUTypeSetData                  19
#define PDUTypeData                     20
#define PDUTypeEventReport              21
#define PDUTypeComment                  22
#define PDUTypeEmission                 23
#define PDUTypeDesignator               24
#define PDUTypeTransmitter              25
#define PDUTypeSignal                   26
#define PDUTypeReceiver                 27
#define PDUTypeAnnounceObject          129 
#define PDUTypeDeleteObject            130 
#define PDUTypeDescribeApplication     131 
#define PDUTypeDescribeEvent           132 
#define PDUTypeDescribeObject          133 
#define PDUTypeRequestEvent            134 
#define PDUTypeRequestObject           135 
#define PDUTypeTimeSpacePositionIndicatorFI 140 
#define PDUTypeAppearanceFI            141 
#define PDUTypeArticulatedPartsFI      142 
#define PDUTypeFireFI                  143 
#define PDUTypeDetonationFI            144 
#define PDUTypePointObjectState        150 
#define PDUTypeLinearObjectState       151 
#define PDUTypeArealObjectState        152 
#define PDUTypeEnvironment             153 
#define PDUTypeTransferControlRequest  155 
#define PDUTypeTransferControl         156 
#define PDUTypeTransferControlAcknowledge 157 
#define PDUTypeIntercomControl         160 
#define PDUTypeIntercomSignal          161 
#define PDUTypeAggregate               170 

//#define PDUTypeExperimentalRequestControl 150
//#define PDUTypeExperimentalGrantControl   151
//#define PDUTypeTransferControl  36

#define PDUFamilyOther                            0
#define PDUFamilyEntityInformation                1
#define PDUFamilyWarfare                          2
#define PDUFamilyLogistics                        3
#define PDUFamilyRadioCommunications              4
#define PDUFamilySimulationManagement             5
#define PDUFamilyDistributedEmissionRegeneration  6
#define PDUFamilyExperimentalCGF                129
#define PDUFamilyExperimentalEntityInteractionInformationFI 130
#define PDUFamilyExperimentalWarfareFI          131
#define PDUFamilyExperimentalEnvironmentObjectInformationInteraction 132
#define PDUFamilyExperimentalEntityManagement   133




typedef enum {
	/** Version 1.0 Draft (1992). */
	DISProtocolVersionMay92 = 1,
	/** IEEE 1278-1993. */
	DISProtocolVersionIEEE1278_93 = 2,
	/** Version 2.0 Third Draft (May 1993). */
	DISProtocolVersionMay93 = 3,
	/** Version 2.0 Fourth Draft (March 1994). */
	DISProtocolVersion2_04 = 4,
	/** IEEE 1278.1-1995, the target compliance of this module. */
	DISProtocolVersionIEEE1278_95 = 5,
	/** IEEE 1278.1a-1998 (amendment to IEEE 1278.1-1995). */
	DISProtocolVersionIEEE1278_98 = 6,
	/** IEEE 1278.1-2012. */
	DISProtocolVersionIEEE1278_2012
} DISProtocolVersion;

/**
 * Force the entity belongs to. See also handy conversion routines from
 * force to string and vice-versa dis_parseForce() and dis_forceToString().
 */
typedef enum {
	DISForceOther = 0,
	DISForceFriendly = 1,
	DISForceOpposing = 2,
	DISForceNeutral = 3
} DISForce;

typedef enum {
	DISRequestStatusOther = 0,
	DISRequestStatusPending = 1,
	DISRequestStatusExecuting = 2,
	DISRequestStatusPartiallyComplete = 3,
	DISRequestStatusComplete = 4
} DISRequestStatus;

typedef enum {
	DISAcknowledgeFlagCreateEntity = 1,
	DISAcknowledgeFlagRemoveEntity = 2,
	DISAcknowledgeFlagStart = 3,
	DISAcknowledgeFlagStop = 4
} DISAcknowledgeFlag;

typedef enum {
	DISStopReasonOther = 0,
	DISStopReasonRecess = 1,
	DISStopReasonTermination = 2,
	DISStopReasonSystemFailure = 3,
	DISStopReasonSecurityViolation = 4,
	DISStopReasonEntityReconstitution = 5
} DISStopReason;

#define DISFrozenBehaviorRunClock (1<<0)
#define DISFrozenBehaviorTransmit (1<<1)
#define DISFrozenBehaviorReceive  (1<<2)

typedef enum {
	DISTransferTypeOther = 0,
	DISTransferTypeEntityControllerRequest = 1,
	DISTransferTypeEntityRequest = 2,
	DISTransferTypeEntityMutualExchange = 3,
	DISTransferTypeEnvironmentalControllerRequest = 4,
	DISTransferTypeEnvironmentalRequest = 5,
	DISTransferTypeEnvironmentalMutualExchange = 6
} DISTransferType;


/*
 * From IEEE 1278.1-1995
 */

#define ALL_APPLIC            0xFFFF
#define ALL_ENTITIES          0xFFFF
#define ALL_SITES             0xFFFF
#define COLLISION_THRSH_DFLT  0.1
#define DRA_ORIENT_THRSH_DFLT 3.0
#define DRA_POS_THRSH_DFLT    1.0
#define NO_APPLIC             0x0000
#define NO_ENTITY             0x0000
#define NO_SITE               0x0000
#define NOR_FIRE_MISSION      0x0000
#define RQST_ASSIGN_ID        0xFFFE



#define DISAppearancePaintUniform			0
#define DISAppearancePaintCamouflage		1
#define DISAppearancePaintMask				1

#define DISAppearanceMobilityNormal		(0 << 1)
#define DISAppearanceMobilityDisabled		(1 << 1)

#define DISAppearanceFirepowerNormal		(0 << 2)
#define DISAppearanceFirepowerDisabled		(1 << 2)

#define DISAppearanceDamageNone			(0 << 3)
#define DISAppearanceDamageSlight		(1 << 3)
#define DISAppearanceDamageModerate		(2 << 3)
#define DISAppearanceDamageDestroyed		(3 << 3)
#define DISAppearanceDamageMask		(3 << 3)

#define DISAppearanceSmokeNone			(0 << 5)
#define DISAppearanceSmokePlume			(1 << 5)
#define DISAppearanceSmokeEngine		(2 << 5)
#define DISAppearanceSmokePlumeAndEngine	(3 << 5)
#define DISAppearanceSmokeMask			(3 << 5)

#define DISAppearanceSmokeTrailingNone		(0 << 7)
#define DISAppearanceSmokeTrailingSmall		(1 << 7)
#define DISAppearanceSmokeTrailingMedium	(2 << 7)
#define DISAppearanceSmokeTrailingLarge		(3 << 7)
#define DISAppearanceSmokeTrailingMask		(3 << 7)

#define DISAppearanceHatchNA			(0 << 9)
#define DISAppearanceHatchClosed		(1 << 9)
#define DISAppearanceHatchPopped		(2 << 9)
#define DISAppearanceHatchPoppedPerson	(3 << 9)
#define DISAppearanceHatchOpen			(4 << 9)
#define DISAppearanceHatchOpenPerson	(5 << 9)
#define DISAppearanceHatchMask			(7 << 9)

#define DISLightsNone				(0 << 12)
#define DISLightsRunning			(1 << 12)
#define DISLightsNavigation			(2 << 12)
#define DISLightsFormation			(3 << 12)
#define DISLightsMask				(3 << 12)

#define DISNoFlames				(0 << 15)
#define DISFlamesPresent			(1 << 15)

#define DISAppearancePlatformNotFrozen		(0 << 21)
#define DISAppearancePlatformFrozen		(1 << 21)
#define DISAppearancePlatformPowerplantOff	(0 << 22)
#define DISAppearancePlatformPowerplantOn	(1 << 22)
#define DISAppearancePlatformActive		(0 << 23)
#define DISAppearancePlatformDeactivated	(1 << 23)

#define DISAppearanceAirAfterburnerOn		(1 << 16)

#define DISAppearanceLandLauncherRaised		(1 << 16)

#define DISAppearanceLandCammouflageDesert	(0 << 17)
#define DISAppearanceLandCammouflageWinter	(1 << 17)
#define DISAppearanceLandCammouflageForest	(2 << 17)
#define DISAppearanceLandCammouflageMask	(3 << 17)

#define DISAppearanceLandConcealed		(1 << 19)



#define DISKindOther		0
#define DISKindPlatform		1
#define DISKindMunition		2
#define DISKindLifeForm		3
#define DISKindEnvironmental	4
#define DISKindCultural		5
#define DISKindSupply		6
#define DISKindRadio		7

#define DISDomainOther		0
#define DISDomainLand		1
#define DISDomainAir		2
#define DISDomainSurface	3
#define DISDomainSubsurface	4
#define DISDomainSpace		5

#define DISCategoryLandOther	0
#define DISCategoryLandTank	1
#define DISCategoryLandAFV	2
#define DISCategoryLandAUV	3
#define DISCategorySPA		4
#define DISCategoryTowedArty	5
#define DISCategorySmallWUV	6
#define DISCategoryLargeWUV	7

#define DISTargetDomainOther			0
#define DISTargetDomainAntiAir			1
#define DISTargetDomainAntiArmor		2
#define DISTargetDomainAntiGuidedMunition	3
#define DISTargetDomainAntiRadar		4
#define DISTargetDomainAntiSatellite		5
#define DISTargetDomainAntiShip			6
#define DISTargetDomainAntiSubmarine		7
#define DISTargetDomainBattlefieldSupport	8
#define DISTargetDomainStrategic		8
#define DISTargetDomainMisc			10

#define DISDRMethodOther		0
#define DISDRMethodStatic		1
#define DISDRMethodFPW			2
#define DISDRMethodRPW			3
#define DISDRMethodRVW			4
#define DISDRMethodFVW			5
#define DISDRMethodFPB			6
#define DISDRMethodRPB			7
#define DISDRMethodRVB			8
#define DISDRMethodFVB			9
#define DISDRMethodRPW_2		10
#define DISDRMethodRVW_2		11

#define DISCharSetUnused	0
#define DISCharSetASCII		1

#define DISCapabilityAmmunitionSupply	1
#define DISCapabilityFuelSupply		2
#define DISCapabilityMiscSupply		4
#define DISCapabilityRepair		8

#define DISWarheadOther			0
#define DISWarheadHE			1000
#define DISWarheadHEPlastic		1100
#define DISWarheadHEIncendiary		1200
#define DISWarheadHEFragment		1300
#define DISWarheadHEAntiTank		1400
#define DISWarheadHEBomblets		1500
#define DISWarheadHEShapedCharge	1600
#define DISWarheadSmoke			2000
#define DISWarheadIllumination		3000
#define DISWarheadPractice		4000
#define DISWarheadKinetic		5000
#define DISWarheadUnused		6000
#define DISWarheadNuclear		7000
#define DISWarheadChemGeneral		8000
#define DISWarheadChemBlister		8100
#define DISWarheadChemBlood		8200
#define DISWarheadChemNerve		8300
#define DISWarheadBiologicalGeneral	9000

#define DISFuzeOther			0
#define DISFuzeContact			1000
#define DISFuzeContactInstant		1100
#define DISFuzeContactDelayed		1200
#define DISFuzeContactElectronic	1300
#define DISFuzeContactGraze		1400
#define DISFuzeContactCrush		1500
#define DISFuzeContactHydrostatic	1600
#define DISFuzeContactMechanical	1700
#define DISFuzeContactChemical		1800
#define DISFuzeTimed			2000
#define DISFuzeProximity		3000
#define DISFuzeProximityActiveLaser	3100
#define DISFuzeProximityMagnetic	3200
#define DISFuzeProximityRadar		3300
#define DISFuzeProximityRF		3400
#define DISFuzeProximityProgrammable	3500
#define DISFuzeProximityInfrared	3700
#define DISFuzeCommand			4000
#define DISFuzeCommandElectronicRS	4100
#define DISFuzeAltitude			5000
#define DISFuzeAltitudeRadioAltimeter	5100
#define DISFuzeAltitudeRadioAirBurst	5100
#define DISFuzeDepth			6000
#define DISFuzeAcoustic			7000
#define DISFuzePressure			8000
#define DISFuzePyrotechnic		9000

#define DISDetonationResultOther		0
#define DISDetonationResultEntityImpact		1
#define DISDetonationResultEntityProxDetonation 2
#define DISDetonationResultGroundImpact		3
#define DISDetonationResultGroundProxDetonation 4
#define DISDetonationResultDetonation		5
#define DISDetonationResultNone			6
#define DISDetonationResultHESmall		7
#define DISDetonationResultHEMedium		8
#define DISDetonationResultHELarge		9
#define DISDetonationResultAP			10
#define DISDetonationResultDBSmall		11
#define DISDetonationResultDBMedium		12
#define DISDetonationResultDBLarge		13
#define DISDetonationResultAirHit		17
#define DISDetonationResultBuildingHitSmall		18
#define DISDetonationResultBuildingHitMedium		19
#define DISDetonationResultBuildingHitLarge		20
#define DISDetonationResultMineClearingLineCharge		21

#define DISServiceTypeOther					0
#define DISServiceTypeResupply				1
#define DISServiceTypeRepair				2

#define DISRepairTypeNone					0
#define DISRepairTypeAll					1

#define DISRepairResultOther				0
#define DISRepairResultEnded				1
#define DISRepairResultInvalid				2
#define DISRepairResultInterrupted			3
#define DISRepairResultCancelled			4

#define DISAckFlagOther				0
#define DISAckFlagCreateEntity		1
#define DISAckFlagRemoveEntity		2
#define DISAckFlagStartResume		3
#define DISAckFlagStopFreeze		4

#define DISActionOther				0
#define DISActionLocalStorage		1
#define DISActionOutOfAmmunition	2
#define DISActionKIA				3
#define DISActionDamage				4
#define DISActionMobilityDisabled	5
#define DISActionFireDisabled		6

#define DISResponseOther			0
#define DISResponsePending			1
#define DISResponseExecuting		2
#define DISResponsePartiallyComplete	3
#define DISResponseComplete			4

#define DISActivateReasonOther		0
#define DISActivateReasonStart		1
#define DISActivateReasonRestart	2
#define DISActivateReasonEntry		3
#define DISActivateReasonReconstite	4

#define DISActivateResultOther				0
#define DISActivateResultRequestAccepted	1
#define DISActivateResultInvalidParam		2
#define DISActivateResultUnexpectedParam	3

#define DISDeactivateReasonOther			0
#define DISDeactivateReasonEnd				1
#define DISDeactivateReasonWithdrawn		2
#define DISDeactivateReasonDestroyed		3

#define DISDeactivateResultOther			0
#define DISDeactivateResultReqAccepted		1
#define DISDeactivateResultInvalidParam		2
#define DISDeactivateResultUnexpectedReason	3
#define DISDeactivateResultNotActive		4

#define DISFrozenSimulationClock	(1<<0)
#define DISFrozenTransmitPDUs		(1<<1)
#define DISFrozenReceivePDUs		(1<<2)

#define DISInputSourceOther		0
#define DISInputSourcePilot		1
#define DISInputSourceCopilot		2
#define DISInputSourceFirstOfficer	3

#define DISReceiverStateOff		0
#define DISReceiverStateOnNotReceiving	1
#define DISReceiverStateOnReceiving	2

#define DISEmitterFuncUnknown			0
#define DISEmitterFuncLandBasedAirDefense	1
#define DISEmitterFuncBattlefieldAndGroundSurveillance 2
#define DISEmitterFuncNavalSurveillanceAndNavigation 3
#define DISEmitterFuncNavalFireControl		4
#define DISEmitterFuncAirborneSurveillance	5
#define DISEmitterFuncAirborneFireControl	6
#define DISEmitterFuncSpaceborne		7
#define DISEmitterFuncATCInstrumentationAndRanging 8
#define DISEmitterFuncWeather			9
#define DISEmitterFuncMissileGuidance		10
#define DISEmitterFuncJamming			11

#define DISBeamFuncUnknown	0
#define DISBeamFuncSearch 1
#define DISBeamFuncHeightFinder 2
#define DISBeamFuncAcquisition 3
#define DISBeamFuncTracking 4
#define DISBeamFuncAcquisitionAndTracking 5
#define DISBeamFuncCommandGuidance 6
#define DISBeamFuncIlluminator 7
#define DISBeamFuncRangeOnlyRadar 8
#define DISBeamFuncMissileBeacon 9
#define DISBeamFuncMissileFuze	10
#define DISBeamFuncActiveRadarMissileSeeker 11
#define DISBeamFuncJammer		12

#define DISPRITypeUnknown	0
#define DISPRITypeSteady	1
#define DISPRITypeStaggered	2
#define DISPRITypeJitter	3
#define DISPRITypePulseGroup	4
#define DISPRITypeCW		5
#define DISPRITypePulseDoppler	6

#define DISScanTypeUnknown	0
#define DISScanTypeSteady	1
#define DISScanTypeUnidirectional	2
#define DISScanTypeBidirectional	3
#define DISScanTypeConical	4
#define DISScanTypeTwoBar	5
#define DISScanTypeThreeBar	6
#define DISScanTypeFourBar	7
#define DISScanTypeOneBar	8

typedef struct {
	float x;
	float y;
	float z;
} dis_float_vector;

typedef struct  {
	float x;
	float y;
	float z;
} dis_angular_vel_vector;


typedef struct {
	float x;
	float y;
	float z;
} dis_linear_acc_vector;


typedef struct {
	float x;
	float y;
	float z;
} dis_linear_vel_vector;


typedef struct {
	float x;
	float y;
	float z;
} dis_entity_coord_vector;


/**
 * DIS entity type.
 * See also: dis_entityTypeToString(), dis_parseEntityType().
 */
typedef struct {
	unsigned char kind;
	unsigned char domain;
	uint16_t country;
	unsigned char category;
	unsigned char subcategory;
	unsigned char specific;
	unsigned char extra;
} dis_entity_type;


typedef struct {
	unsigned char charset;
	unsigned char marking[11];
} dis_entity_marking;


typedef struct {
	uint32_t datum_id;
	uint32_t value;
} dis_fixed_datum;


typedef struct {
	uint32_t datum_id;
	uint32_t value_length;
	union {
		double double_value;
		dis_entity_type entity_type_value;
		unsigned char *ptr_value;
	} value;
} dis_variable_datum;

/**
 * Timestamp associated to the packet. If absolute, the host participating in
 * the simulation is synchronized with all the other hosts, typically via NTP.
 * If relative, the host is not synchronized and the other participating hosts
 * must (should...) take care of this using this value only to perform time
 * differences with other timestamps coming from that same host.
 * Note that the time field only carries the lowest 31 bits of the timestamp
 * measured in units of 3600/2^31 seconds; this value is not monotonic and
 * returns to 0 after reaching (2^31-1).
 * 
 * NOTE. Currently src/acm/dis_if.c simply ignores the timestamp from incoming
 * DIS packets and always assumes our timestamp instead.
 * 
 * 2017-04-26 XDR routines fail to encode/decode this data as originally defined
 * with separated time and type fields on 64 bits platform. Fixed declaring a
 * single field "timexxx"; the highest bit is the absolute time flag. This value
 * is set by ACM but it is otherwise ignored, only internal clock matters. [U.S.]
 */
typedef struct {
	///** 3600/2^31 = 1.676... usec units. */
	//unsigned time:31;
	///** Type: 0=relative, 1=absolute. */
	//unsigned type:1;
	uint32_t timexxx;
} dis_timestamp;

typedef struct {
	uint16_t site_id;
	uint16_t application_id;
} dis_simulation_addr;


typedef struct {
	uint16_t name;
	unsigned char function;
	unsigned char id;
} dis_emitter_system;


typedef struct {
	dis_simulation_addr sim_id;
	uint16_t entity_id;
} dis_entity_id;


typedef struct {
	float psi;
	float theta;
	float phi;
} dis_euler_angles;


typedef struct {
	dis_simulation_addr sim_id;
	uint16_t event_id;
} dis_event_id;


typedef struct {
	float freq;
	float freq_range;
	float erp;
	float prf;
	float pulse_width;
	float beam_azimuth_center;
	float beam_azimuth_sweep;
	float beam_elev_center;
	float beam_elev_sweep;
	float beam_sweep_sync;
} dis_fundamental_parameters;


typedef struct {
	uint16_t spread_spectrum;
	uint16_t major_type;
	uint16_t detail;
	uint16_t system;
} dis_modulation_type;


typedef struct {
	unsigned char protocol_version;
	unsigned char exercise_id;
	unsigned char pdu_type;
	unsigned char protocol_family;
	dis_timestamp time_stamp;
	uint16_t length;
	uint16_t padding;
} dis_pdu_header;


typedef struct {
	double x;
	double y;
	double z;
} dis_double_vector;


typedef struct dis_relative_coordinates {
	float x;
	float y;
	float z;
} dis_relative_coordinates;


typedef struct {
	VPoint ant_location;
	dis_relative_coordinates relative;
} dis_antenna_location;


typedef struct {
	dis_euler_angles direction;
	float azimuth_width;
	float elev_width;
	unsigned char reference_system;
	unsigned char pad[3];
	float Ez;
	float Ex;
	float phase;
} dis_beam_antenna_pattern;


typedef struct {
	unsigned char pattern;
	float coefficients;
	unsigned char ref_system;
} dis_spherical_harmonic_antenna_pattern;


typedef union {
	double d;
	float f[2];
	char c[8];
	uint32_t l[2];
	uint16_t s[4];
} dis_parm_value;


typedef struct {
	unsigned char type;
	unsigned char change;
	uint16_t attachment_id;
	uint32_t attached_part;
	uint32_t articulated_part;
	dis_parm_value value;
} dis_articulation_parm;


typedef struct {
	uint32_t hour;
	dis_timestamp rel;
} dis_time;


typedef struct {
	dis_entity_type munition;
	uint16_t warhead;
	uint16_t fuze;
	uint16_t quantity;
	uint16_t rate;
} dis_burst_descriptor;


typedef struct {
	unsigned char algorithm;
	unsigned char other[15];
	dis_linear_acc_vector linear_acc;
	dis_angular_vel_vector angular_vel;
} dis_dead_reckoning;


typedef uint32_t dis_capabilities;


typedef struct {
	dis_entity_type entity;
	float quantity;
} dis_supply_quantity;


typedef uint32_t dis_entity_appearance;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id id;
	unsigned char force_id;
	unsigned char art_parm_count;
	dis_entity_type type;
	dis_entity_type alt_type;
	dis_linear_vel_vector vel;
	VPoint pos;
	dis_euler_angles orientation;
	dis_entity_appearance appearance;
	dis_dead_reckoning dr_parm;
	dis_entity_marking marking;
	dis_capabilities capabilities;
	dis_articulation_parm *art_parm;
} dis_entity_state_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id id;
	dis_entity_id collision_id;
	dis_event_id event;
	dis_linear_vel_vector vel;
	uint32_t mass;
	dis_entity_coord_vector loc;
} dis_collision_pdu;


typedef struct  {
	dis_pdu_header hdr;
	dis_entity_id firing_id;
	dis_entity_id target_id;
	dis_entity_id munition_id;
	dis_event_id event;
	uint32_t fire_mission_index;
	VPoint pos;
	dis_burst_descriptor burst;
	dis_linear_vel_vector vel;
	float range;
} dis_fire_pdu;


typedef struct  {
	dis_pdu_header hdr;
	dis_entity_id firing_id;
	dis_entity_id target_id;
	dis_entity_id munition_id;
	dis_event_id event;
	dis_linear_vel_vector vel;
	VPoint pos;
	dis_burst_descriptor burst;
	dis_entity_coord_vector loc;
	unsigned char result;
	unsigned char num_art_parms;
	uint16_t pad;
	dis_articulation_parm *art_parm;
} dis_detonation_pdu;


typedef unsigned char dis_service_type;


typedef uint16_t dis_repair_type;


typedef unsigned char dis_repair_result;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id requestor_id;
	dis_entity_id server_id;
	dis_service_type requested_service;
	unsigned char num_supply_types;
	uint16_t pad;
	dis_supply_quantity *supplies;
} dis_service_request_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id receiver_id;
	dis_entity_id supplier_id;
	unsigned char num_supply_types;
	unsigned char pad[3];
	dis_supply_quantity *supplies;
} dis_resupply_offer_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id receiver_id;
	dis_entity_id supplier_id;
	unsigned char num_supply_types;
	unsigned char pad[3];
	dis_supply_quantity *supplies;
} dis_resupply_received_pdu;


typedef struct  {
	dis_pdu_header hdr;
	dis_entity_id receiver_id;
	dis_entity_id supplier_id;
} dis_resupply_cancel_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id receiver_id;
	dis_entity_id supplier_id;
	dis_repair_type repair;
	uint16_t pad;
} dis_repair_complete_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id receiver_id;
	dis_entity_id supplier_id;
	dis_repair_result result;
	unsigned char pad[3];
} dis_repair_response_pdu;


typedef uint32_t dis_request_id;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_request_id request_id;
} dis_create_entity_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_request_id request_id;
} dis_remove_entity_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_time real_time;
	dis_time sim_time;
	dis_request_id request_id;
} dis_start_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_time real_time;
	unsigned char reason;
	unsigned char behavior;
	unsigned char pad[2];
	dis_request_id request_id;
} dis_stop_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	uint16_t acknowledge_flag;
	uint16_t resp_flag;
	dis_request_id request_id;
} dis_acknowledge_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_time interval;
	dis_request_id request_id;
	uint32_t num_fixed_data;
	uint32_t num_variable_data;
	uint32_t *fixed_datum_id;
	uint32_t *variable_datum_id;
} dis_data_query_pdu;


typedef struct {
	uint32_t num_fixed_data;
	uint32_t num_variable_data;
	dis_fixed_datum *fixed_datum;
	dis_variable_datum *variable_datum;
} dis_datum_spec_record;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_request_id request_id;
	dis_datum_spec_record datum_info;
} dis_set_data_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_request_id request_id;
	dis_datum_spec_record datum_info;
} dis_data_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	dis_event_id event_type;
	dis_datum_spec_record datum_info;
} dis_event_report_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	uint32_t num_fixed_data;
	uint32_t num_variable_data;
	dis_fixed_datum *fixed_datum;
	dis_variable_datum *variable_datum;
} dis_comment_pdu;


typedef struct {
	dis_entity_id target;
	unsigned char emitter_id;
	unsigned char beam_id;
} dis_track_info;


typedef struct {
	unsigned char beam_data_length;
	unsigned char beam_id;
	uint16_t beam_parm_index;
	dis_fundamental_parameters fundamental;
	unsigned char beam_function;
	unsigned char num_targets;
	unsigned char high_density_track_jam;
	unsigned char pad;
	uint32_t jamming_mode;
	dis_track_info *tracked_target;
} dis_beam_info;


typedef struct {
	unsigned char sys_data_length;
	unsigned char num_beams;
	uint16_t pad;
	dis_emitter_system emitter_system;
	dis_entity_coord_vector location;
	dis_beam_info *beam;
} dis_em_system_info;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id emitter_id;
	dis_event_id event;
	unsigned char state_update;
	unsigned char num_systems;
	uint16_t pad;
	dis_em_system_info *system;
} dis_em_emission_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id designating_id;
	uint16_t code_name;
	dis_entity_id designated_id;
	unsigned char pad;
	unsigned char code;
	float power;
	float wavelength;
	dis_entity_coord_vector spot_rel;
	VPoint spot_pos;
} dis_designator_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id requesting_id;
	dis_entity_id control_target_id;
} dis_experimental_request_control_pdu;



typedef struct {
	dis_pdu_header hdr;
	dis_entity_id granting_id;
	dis_entity_id control_target_id;
} dis_experimental_grant_control_pdu;


typedef struct {
	dis_pdu_header hdr;
	dis_entity_id orig_id;
	dis_entity_id recv_id;
	uint32_t request_id;
	unsigned char reliability_service;
	unsigned char transfer_type;
	dis_entity_id target_id;
	uint32_t num_record_sets;
} dis_transfer_control_pdu;


typedef union {
	dis_pdu_header hdr;
	dis_entity_state_pdu entity_state;
	dis_collision_pdu collision;

	dis_fire_pdu fire;
	dis_detonation_pdu detonation;

	dis_create_entity_pdu create_entity;
	dis_remove_entity_pdu remove_entity;
	dis_start_pdu start;
	dis_stop_pdu stop;
	dis_acknowledge_pdu acknowledge;
	dis_data_query_pdu data_query;
	dis_set_data_pdu set_data;
	dis_data_pdu data;
	dis_event_report_pdu event_report;
	dis_comment_pdu message;

	dis_em_emission_pdu em_emission;
	dis_designator_pdu designator;
	dis_transfer_control_pdu transfer_control;
	dis_experimental_request_control_pdu request_control;
	dis_experimental_grant_control_pdu grant_control;
} dis_pdu;


typedef struct {
	double    timeThreshold;        /* [ seconds ]  */
	double    locationThreshold;    /* [ meters ]  */
	double    orientationThreshold; /* [ radians ] */
	double    omega;      /* angular velocity magnitude */
	VMatrix R0;      /* orientation based on Euler angles in entity state */
	VMatrix   skew;
	VMatrix   aat;
	dis_entity_state_pdu pdu;	/* saved entity state PDU */
} dis_dr_parameters;


typedef enum {
	dis_RESULT_OK = 0,
	dis_RESULT_ERROR = 1,
	dis_RESULT_NO_MEMORY = 2
} dis_Result;

/**
 * In broadcasting mode, local interface to send packets;
 * in unicast mode, the destination relay server.
 */
typedef struct {
	/** Local interface or relay server. */
	struct sockaddr_in addr;
	/** 0=broadcast; 1=other (unicast?). */
	int    type;               /* 0=broadcast; 1=other */
} dis_DestinationAddress;

/**
 * All destinations of our packets.
 */
typedef struct {
	/** Socket. */
	int       s;
	dis_DestinationAddress dest[32];
	int       num_dest;
} dis_Transceiver;


/**
 * Parses the force type.
 * @param s Force type string, one of "Other", "Friendly", "Opposing", "Neutral".
 * @return Parsed force, or -1 if the string is NULL or invalid.
 */
EXTERN DISForce dis_parseForce(char *s);

/**
 * Returns the name of the force.
 * @param force Type of the force. Fatal error if the value is invalid.
 * @return Pointer to statically allocated string describing the force.
 */
EXTERN char * dis_forceToString(DISForce force);

/**
 * Compare an incoming DIS entity type against a wildcarded entity type;
 * returns non-zero value if they match.
 */
EXTERN int dis_entityWildcardMatch(const dis_entity_type *in,
	const dis_entity_type *pattern,
	const dis_entity_type *pattern_mask);

/**
 * Add articulation parameter to the Entity State PDU.
 */
EXTERN dis_Result dis_addArticulationParm(dis_entity_state_pdu * esp,
	dis_articulation_parm * parm, int *parmID);

EXTERN int dis_setNBIOState(dis_Transceiver *, int);

/**
 * Establishes a connection to the DIS network. It should be called only once by
 * a user application. There are two modes: relay server and client. In server
 * mode the port parameter sets the port of the server, the host name parameter
 * is ignored. In client mode, if a relay server and port are set, sends packets
 * to that relay server; if no host name is defined, uses broadcasting.
 * When broadcasting is required on UNIX systems, this function automatically
 * locates all active broadcast-compatible network interfaces and configures the
 * DIS library to automatically transmit broadcast PDU’s on each of those
 * interfaces.
 * 
 * The socket is created in blocking mode; the disx module will set it to non-
 * blocking mode.
 * 
 * See Also: dis_closeTransceiver().
 * @param isServer Set to false for client connection, true for relay server.
 * @param host_name If client, name or network address of the relay server if
 * available, or NULL or empty to use broadcasting. If server, it is ignored.
 * @param host_port If client, the UDP port to use in broadcast mode, or the port
 * of the relay server if available. If server, the UDP port of the server.
 * @return Pointer to DISTransceiver on success, NULL otherwise (and a message
 * is sent to stderr).
 */
EXTERN dis_Transceiver *dis_openTransceiver(int isServer,
		char *host_name, int host_port);

/**
 * Does nothing if xcvr is NULL.
 * @param xcvr
 */
EXTERN void dis_closeTransceiver(dis_Transceiver *xcvr);

/**
 * Returns the next PDU received from the DIS network. Some PDU structures
 * contain variable length fields (for example, the emitter systems field of an
 * electromagnetic emission PDU). Space required to hold those variable length
 * components will be dynamically allocated. Before discarding the PDU, call
 * dis_freePDUComponents() to release this dynamically allocated storage.
 * See Also: dis_openTransceiver(), dis_writePDU(), dis_freePDUComponents().
 * @param xcvr
 * @param pdu
 * @return True if a DIS PDU is available. False if no more packets are
 * available. Invalid packets are skipped and an error message is logged.
 */
EXTERN int dis_readPDU(dis_Transceiver *xcvr, dis_pdu *pdu);

/**
 * Broadcasts the specified PDU onto the DIS network.
 * See Also: dis_openTransceiver(), dis_readPDU().
 * @param xcvr
 * @param pdu
 * @return True on success. False if either failed encoding the PDU (should
 * never happen) or failed sending the packet to at least one destination
 * address.
 */
EXTERN int dis_writePDU(dis_Transceiver *xcvr, dis_pdu *pdu);

/**
 * Release storage occupied by the variable-length fields of a PDU. Some PDU
 * structures contain variable length fields (e.g. the emitter systems field of
 * an electromagnetic emission PDU). Space required to hold those variable length
 * components is dynamically allocated through during a call to dis_readPDU (or
 * DISxReadPDU). Before discarding a PDU, call this function to release this
 * dynamically allocated storage. See Also: disx_readPDU(), dis_readPDU().
 * @param pdu DIS PDU whose variable length components have to be released.
 * Does nothing if NULL.
 */
EXTERN void dis_freePDUComponents(dis_pdu *pdu);

EXTERN void dis_addPDUSizes(dis_pdu *);

/**
 * Returns the current relative time based on the local system’s clock.
 * See Also: dis_getTimestamp().
 * @param result
 * @return Currently always returns zero.
 */
EXTERN int dis_getRealTime(dis_time * result);

/**
 * Returns a DIS absolute timestamp based on the local system’s clock. Absolute
 * timestamps are interpreted by other DIS applications to be based on UTC time.
 * This normally assumes that the clocks of all systems participating in this
 * DIS exercise have been somehow synchronized with Coordinated Universal
 * Time (UTC).
 * See Also: dis_getRealTime().
 * @param result Relative DIS timestamp.
 * @return Currently always returns zero.
 */
EXTERN int dis_getTimestamp(dis_timestamp * result);

EXTERN void dis_timeToTimeval(dis_time * in, struct timeval *out);

EXTERN void dis_timestampToTimeval(dis_timestamp * in, struct timeval *out);

/**
 * Bits for the DR test status mask telling for which reason the state of a
 * entity needs to be updated and then a new state packet should be send.
 * The words "too much" that follow should be read "beyond the configured DR
 * threshold".
 */
typedef enum {
	/** Stale entity state: too much time elapsed since last packet sent. */
	dis_DR_TIME        = 0x01,
	/** Entity moved too much. */
	dis_DR_LOCATION    = 0x02,
	/** Entity rotates too much. */
	dis_DR_ORIENTATION = 0x04,
} dis_DR_FLAGS;


EXTERN void dis_processNewDRParameters(dis_entity_state_pdu * pdu,
		dis_dr_parameters * dr);

EXTERN void dis_generateDRParameters(dis_entity_state_pdu * pdu,
		dis_dr_parameters * dr);

/**
 * Updates the state of the remote entity using the specified dead reckoning
 * algorithm. Updates the current state vectors accordingly.
 * @param dr Dead reckoning parameters.
 * @param dT Time elapsed since last update (s).
 * @param pos Last known position.
 * @param vel Last known velocity.
 * @param orientation Last known orientation.
 */
EXTERN void dis_computeDRPosition(dis_dr_parameters * dr, double dT,
		VPoint * pos, dis_linear_vel_vector * vel,
		VMatrix * orientation);

EXTERN void dis_getDRThresholds(dis_dr_parameters *, double *time,
		double *location, double *orientation);

EXTERN void dis_setDRThresholds(dis_dr_parameters *, double time,
		double location, double orientation);

/**
 * Updates the DR state and returns a bit mask with the DR test result.
 * @param dr
 * @param deltaT
 * @param current_location
 * @param current_orientation
 * @return Result of the test.
 */
EXTERN dis_DR_FLAGS dis_testDRThresholds(dis_dr_parameters *dr, double deltaT,
		VPoint *current_location, dis_euler_angles *current_orientation);

/**
 * Generate a DIS entity ID from a string.
 * C-style hexadecimal numbers may be used in the input stream:
 *
 *   1/1/0xfffe, and 0xff/0xff/0x1 are both valid
 *
 * Example invalid strings:
 *
 *   1/1/1,000    Entity ID field contains an invalid character
 *   1/1/1000000  Entity ID field > 0xffff
 *
 * @param p Resulting parsed entity.
 * @param buf Buffer to parse -- BEWARE: overwritten!
 * @param bufsize Length of the buffer, including terminating zero if any.
 * @param delim List of delimiter characters, typically ".:/".
 * @return
 *   0: success,
 *   1: parse error,
 *   2: incoming string buffer too large (max is 64 characters),
 *   3: one or more of the fields contains an invalid value (&lt;0 or &gt;0xffff),
 *   4: invalid character in string.
 */
EXTERN int dis_parseEntityID (dis_entity_id *p, char * buf, int bufsize,
	char *delim);

/**
 * Parse entity type string of the form "9.9.9.9.9.9.9". Each value must be an
 * integer number in the range [0,255], except country which is [0,65535].
 * Ignores leading and trailing white spaces.
 * @param s String to parse.
 * @param et Here returns the parsed entity type.
 * @return True on success. False if the string is NULL or does not contain
 * a valid entity type.
 */
EXTERN int dis_parseEntityType(char *s, dis_entity_type *et);

/**
 * Returns the entity type as a string of the form "9.9.9.9.9.9.9".
 * @param et Subject entity type.
 * @return Pointer to a statically allocated string buffer with the formatted
 * entity type.
 */
EXTERN char * dis_entityTypeToString(dis_entity_type *et);

#undef EXTERN
#endif
