/*
*******************************************************************************
* Copyright (c) 1996-97 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************

// config.h implementation file

*/
typedef u_long u_int;

class CTraceSheet;
class CX25TraceSheet;
class CFRTraceSheet;

class CStatDoc;
class CX25StatDoc;
class CFRStatDoc;

// this header file contains the definitions for most of the code
// that handles stats and trace. the rest in the in 'trace.h/cpp'

// abstract bases class representing an adapter containing
// data sources. The adapters job is to create and hold on to
// CDataSource derived classes.
class CAdapter;
// CAdapter derived class representing the SyncPort adapter

// abstract base class for perfroming a trace using the
// Sxb driver. CTracer is totally Sxb specific but is totally
// protocol independant. A CTracer derived class is created whenever
// a trace is started. CTracer creates a second thread used to send 
// requests to the Sxb driver. When a frame comes back it is processed
// immmediately in that second thread by the CTraceData class
class CTracer;
// CTracer derived class that enables tracing with using Spider commands
class CLAPBTracer;
// CTracer derived class that enables tracing with using Spider commands
// CX25Tracer is currently not in use all X.25 traces are actually LAPB traces
class CX25Tracer;
// CTracer derived class that enables tracing with using 
// harrison jefferies commands
class CFRTracer;
class CSdlcTracer;

// abstract base class for the trace frame. that is a frame of data sent up
// by the firmware, it contains the interface to routines that get the data
// display in the list frame window panes. i.e. data in the ListCtrl and TreeCtrl
// it is totally protocol independant. A CFrame class is a "pointer class" it
// does not contain any data of it's own. The CTraceData class holds all the trace
// data and has only one CTrace class that is used to access the data for any
// frame stored in CTraceData's buffer. 
class CFrame;
// CFrame derived class that supplies the X.25/LAPB specific data
// is dependant on the data coming from the Spider commands used to get the
// data from the firmware
class CX25Frame;
// CFrame derived class that supplies the Frame Relay specific data
// is dependant on the data coming from the Harrison Jefferies commands
// used to get the data from the firmware
class CFRFrame;

// CTraceData abstract base class which contains the interface which
// the trace panes use to get the data they display. It is totally
// protocol independant. A CTraceData derived class is created whenever
// a trace is started. CTraceData processes the trace frames as they come
// in from the CTracer class. CTraceData contains the circular buffer used
// to store all trace frames. A CTraceData dervied class is written entirely
// to disk when the user wants to save the trace.
class CTraceData;
// CTraceData dervied class containing the Frame Replay specific trace data
// panes displaying this data cast the a CTraceData class to a CFRTraceData
// class
class CFRTraceData;

// CTraceData dervied class containing the X.25/LAPB specific trace data
// panes displaying this data cast the a CTraceData class to a CX25TraceData
// class
class CX25TraceData;

// CDataSource abstract base class used to represent something you can get
// stat and trace data from. it contains the interface to routines that know
// how to get statistics and start/stop traces, what drivers/firmware are
// used, and what panes the stat and trace frame windows are to create
// themselves with
class CDataSource;
// CDataSource derived class contains Frame Relay specific data and information
// to init Frame Relay data panes and starting/stopping/processing Frame Relay
// traces
class CFRDataSource;
// CDataSource derived class contains X.25/LAPB specific data and information
// to init X.25/LAPB data panes and starting/stopping/processing X.25/LAPB
// traces
class CX25DataSource;

// some constants used for stat aquisition routines
// names the protocol specific device to open in the firmware
// to get the stats from
enum eSourceType
{
	stWANS,	// SyncPort, Sync 2000
	stFR,		// Syncport, Sync 2000
	stX25,	// Syncport, Sync 2000
	stLAPB,	// Syncport, Sync 2000
	stMGMT,	// HLC
	stLAPD,	// DataFire Prime, Houston, London
	stT1,		// DataFire Prime
	stIWAN,	// DataFire Prime
	stInit
};

typedef enum {
   NORMAL,
   FORCE
} ENUM_STOP_TYPE;


class CSXB_IOCTL
{
protected :
	// Attributes
	virtual ULONG GetIOCTLCmd() const = 0;

	virtual LPVOID GetIOCTLData() const = 0;
	virtual DWORD GetIOCTLSize() const = 0;

	virtual LPVOID GetResultData() const { return NULL; };
	virtual DWORD GetResultDataSize() const { return 0; };

public :
	BOOL DeviceIoControl(HANDLE File, LPOVERLAPPED lpOV) const
		{ DWORD dwBW;
			return ::DeviceIoControl(	File, 
																GetIOCTLCmd(),
																GetIOCTLData(),
																GetIOCTLSize(),
																GetResultData(),
																GetResultDataSize(), 
																&dwBW, 
																lpOV); 
		};
};

class CPurgeRequest : public CSXB_IOCTL
{
	DS_PURGE m_Purge;
public :
	CPurgeRequest(HANDLE hStream, ULONG Flags = DS_PURGE_ALL)
		{ m_Purge.hStream = hStream; m_Purge.Flags = Flags; };

protected :
	virtual ULONG GetIOCTLCmd() const { return (ULONG)IOCTL_DS_PURGE; };

	virtual LPVOID GetIOCTLData() const { return (LPVOID)&m_Purge; };
	virtual DWORD GetIOCTLSize() const { return sizeof(DS_PURGE); };
};

class CSOpen : public CSXB_IOCTL
{
	LPWSTR GetDataAccessName() const;
	DS_OPEN m_Open;
	eSourceType m_Type;

public :
	CSOpen(eSourceType type);

protected :
	virtual ULONG GetIOCTLCmd() const { return (ULONG)IOCTL_DS_OPEN; };

	virtual LPVOID GetIOCTLData() const { return (LPVOID)&m_Open; };
	virtual DWORD GetIOCTLSize() const { return sizeof(DS_OPEN); };

	virtual LPVOID GetResultData() const { return (LPVOID)&m_Open; };
	virtual DWORD GetResultDataSize() const { return sizeof(DS_OPEN); };

public :
	HANDLE GetVCObject() { return m_Open.hStream;   };
	LONG   GetError()    { return m_Open.ErrorCode; };
};

class CSClose : public CSXB_IOCTL
{
	DS_CLOSE m_Close;

public :
	CSClose(HANDLE hStream) { m_Close.hStream = hStream; }

protected :
	virtual ULONG GetIOCTLCmd() const { return (ULONG)IOCTL_DS_CLOSE; };

	virtual LPVOID GetIOCTLData() const { return (HANDLE)&m_Close; };
	virtual DWORD GetIOCTLSize() const { return sizeof(DS_CLOSE); };

	virtual LPVOID GetResultData() const { return (LPVOID)&m_Close; };
	virtual DWORD GetResultDataSize() const { return sizeof(DS_CLOSE); };
};

class CSXB_USER_IOCTL : public CSXB_IOCTL
{
public :
	// Operations
	virtual void SetVCObject(HANDLE) = 0;

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stInit; };
	virtual GetStatCount() const { return 0; };
	virtual ULONG GetReturnCode() const = 0;
};

template<class TData>
class CStat : public CSXB_USER_IOCTL, protected DS_IOCTL, protected TData
{
protected :
	CStat(ULONG COMMAND)
		{ memset(&hStream, 0, sizeof(DS_IOCTL) + sizeof(TData)); 
			Command = COMMAND; cbDataIn = cbMaxDataOut = sizeof(TData);
	      pDataIn = pDataOut = (PUCHAR)&hStream + sizeof(DS_IOCTL); };

public :
	// Operations
	virtual void SetVCObject(HANDLE vc) { ASSERT(vc != NULL); hStream = vc; };

protected :
	// Attributes
	virtual ULONG GetIOCTLCmd() const { return (ULONG)IOCTL_DS_IOCTL; };

	virtual LPVOID GetIOCTLData() const { return (LPVOID)&hStream; };
	virtual DWORD GetIOCTLSize() const { return sizeof(DS_IOCTL); };

	virtual LPVOID GetResultData() const { return (LPVOID)&hStream; };
	virtual DWORD GetResultDataSize() const { return sizeof(DS_IOCTL); };

public :
	virtual ULONG GetReturnCode() const { return ErrorCode; };
};

class CWANTUNE : public CStat<wan_tnioc>
{
public :
	CWANTUNE(uint32 SNID = -1) : CStat<wan_tnioc>(W_GETTUNE)
		{ lli_type = LI_WANTUNE; lli_snid = SNID; };

	// Operations
	void SetSNID(uint32 SNID) { lli_snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(lli_snid != -1); return stWANS; };

	const wantune_t *operator->() const { return &wan_tune; };
};

class CWAN : public CStat<wan_stioc>
{
public :
	CWAN(uint32 SNID = -1) : CStat<wan_stioc>(L_GETSTATS)
		{ lli_type = LI_WANSTATS; lli_snid = SNID; };

	// Operations
	void SetSNID(uint32 SNID) { lli_snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(lli_snid != -1); return stWANS; };
	virtual GetStatCount() const { return sizeof(hdlc_stats) / sizeof(uint32); };

	const hdlcstats_t *operator->() const { return &hdlc_stats; };
	uint32& operator[](int index) { return ((uint32 *)&hdlc_stats)[index]; };
	uint32 operator[](int index) const { return ((uint32 *)&hdlc_stats)[index]; };
};

class CLAPB : public CStat<lapb_stioc>
{
public :
	CLAPB(uint32 SNID = -1) : CStat<lapb_stioc>(L_GETSTATS)
		{ lli_type = LI_STATS; lli_snid = SNID; };

	// Operations
	void SetSNID(uint32 SNID) { lli_snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(lli_type != -1); return stLAPB; };
	virtual GetStatCount() const { return lapbstatmax; };

	uint32& operator[](int index) { return lli_stats.lapbmonarray[index]; };
	uint32 operator[](int index) const { return lli_stats.lapbmonarray[index]; };

	CString GetState() const
		{ CString State; State.LoadString(IDS_LAPBStateBase + state); return State; };
};

class CX25 : public CStat<Ngstat>
{
public :
	CX25(uint32 SNID = -1) : CStat<Ngstat>(N_getstats)
		{ snid = SNID; };

	// Operations
	void SetSNID(uint32 SNID) { snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(snid != -1); return stX25; };
	virtual GetStatCount() const { return mon_size; };

	uint32& operator[](int index) { return starray[index]; };
	uint32 operator[](int index) const { return starray[index]; };
};

class CFR_LINK_ERRORS : public CStat<FRI_GetLinkErrors_struct>
{
public :
	CFR_LINK_ERRORS(DWORD Snid = -1) : 
		CStat<FRI_GetLinkErrors_struct>(FRI_GetLinkErrors)
		{ snid = Snid; };

	// Operations

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetLinkErrors_t) - sizeof(u_long)) / sizeof(u_long); };

	const FRI_GetLinkErrors_t *operator->() const { return this; };
	u_long& operator[](int index) { return ((u_long *)&rcvframe_inv)[index]; };
	u_long operator[](int index) const { return ((u_long *)&rcvframe_inv)[index]; };
};

class CFR_LINK_STATS : public CStat<FRI_GetLinkStatistics_struct>
{
public :
	CFR_LINK_STATS(DWORD Snid = -1) : 
		CStat<FRI_GetLinkStatistics_struct>(FRI_GetLinkStatistics)
		{ snid = Snid; };

	// Operations

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetLinkStatistics_t) - sizeof(u_long)) / sizeof(u_long); };

	const FRI_GetLinkStatistics_t *operator->() const { return this; };
	u_long& operator[](int index) { return ((u_long *)&sendframes)[index]; };
	u_long operator[](int index) const { return ((u_long *)&sendframes)[index]; };
};

class CFR_LMI_STATS : public CStat<FRI_GetLMIStatistics_struct>
{
public :
	CFR_LMI_STATS(DWORD Snid = -1) : 
		CStat<	FRI_GetLMIStatistics_struct>(FRI_GetLMIStatistics)
		{ snid = Snid; };

	// Operations

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetLMIStatistics_t) - sizeof(u_long)) / sizeof(u_int); };

	const FRI_GetLMIStatistics_t *operator->() const { return this; };
	u_int& operator[](int index) { return ((u_int *)&lmi_net_seq_num)[index]; };
	u_int operator[](int index) const { return ((u_int *)&lmi_net_seq_num)[index]; };
};

class CFR_PROTOCOL_ERRORS : public CStat<FRI_GetProtocolErrorStats_struct>
{
public :
	CFR_PROTOCOL_ERRORS(DWORD Snid = -1, u_short DLCI = 0) : 
		CStat<FRI_GetProtocolErrorStats_struct>(FRI_GetProtocolErrorStats)
		{ snid = Snid; dlci = DLCI; };

	// Operations
	void SetDLCI(u_short DLCI) { dlci = DLCI; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetProtocolErrorStats_t) - 2 * sizeof(u_long)) / sizeof(u_long); };

	const FRI_GetProtocolErrorStats_t *operator->() const { return this; };
	u_long& operator[](int index) { return ((u_long *)&rcv_unkprot)[index]; };
	u_long operator[](int index) const { return ((u_long *)&rcv_unkprot)[index]; };
};

class CFR_INJ_MANG : public CStat<FRI_GetInjectionMangStats_struct>
{
public :
	CFR_INJ_MANG(DWORD Snid = -1, u_short DLCI = 0) : 
		CStat<FRI_GetInjectionMangStats_struct>(FRI_GetInjectionMangStats)
		{ snid = Snid; dlci = DLCI; };

	// Operations
	void SetDLCI(u_short DLCI) { dlci = DLCI; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetInjectionMangStats_t) - 2 * sizeof(u_long)) / sizeof(u_long); };

	const FRI_GetInjectionMangStats_t *operator->() const { return this; };
	u_long& operator[](int index) { return ((u_long *)&InjNormalFrames)[index]; };
	u_long operator[](int index) const { return ((u_long *)&InjNormalFrames)[index]; };
};

class CFR_PLL_STATS : public CStat<FRI_GetPLLStatistics_struct>
{
public :
	CFR_PLL_STATS(DWORD Snid = -1, u_short DLCI = 0) : 
		CStat<FRI_GetPLLStatistics_struct>(FRI_GetPLLStatistics)
		{ snid = Snid; dlci = DLCI; };

	// Operations
	void SetDLCI(u_short DLCI) { dlci = DLCI; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stFR; };
	virtual GetStatCount() const
		{ return (sizeof(FRI_GetPLLStatistics_t) - 2 * sizeof(u_long)) / sizeof(u_long); };

	const FRI_GetPLLStatistics_t *operator->() const { return this; };
	u_long& operator[](int index) { return ((u_long *)&ccb_rev_count)[index]; };
	u_long operator[](int index) const { return ((u_long *)&ccb_rev_count)[index]; };
};

// driver info struct
struct sDriverInfo
{
	CString m_DriverName;
	CString m_DriverVersion;
	CString m_DriverBuildNumber;
	CString m_DriverDate;
};

// session trace stats are created and maintained by the derived class
struct sSession
{
	DWORD EndPoint; // cicuit or channel number
	DWORD Frames[2]; // frame count
	CString Remote; // X.25 remote address
};

struct sMCM // MCM is minimus/current/maximum
{
	DWORD Min;
	DWORD Cur;
	DWORD Max;
};
	
	// frame relay specific virtual circuit trace stats
struct sFRVCStats
{
	DWORD Frames[2];
	DWORD Bytes[2];
	DWORD DE[2];
	DWORD BECN[2];
	DWORD FECN[2];
	sMCM LU[2];
	sMCM FPS[2];
	sMCM Th[2];
};

// X.25 specific virtual circuit trace stats
struct sX25VCStats
{
	DWORD Frames[2];
	DWORD Bytes[2];
	sMCM LU[2];
	sMCM FPS[2];
	sMCM Th[2];
};

enum eLMIFlagBits {
	FRS_LINK_FLAGS_LMI_REV1 = 0x0004,	// Only 1 of these may be set
	FRS_LINK_FLAGS_GANG_OF_4 = 0x0008,	// Only 1 of these may be set
	FRS_LINK_FLAGS_ANNEX_D = 0x0010,	// Only 1 of these may be set
	FRS_LINK_FLAGS_ANNEX_A = 0x4000	// Only 1 of these may be set
};

// each channel number kept by the CDataSource will
// have the high byte used for protocol specific flags
// the CTraceData will store the flags another way
enum eChannelFlags
{
	cfNone,
	cfX25PVC = 0x80000000
};
const DWORD ChannelMask = 0x00FFFFFF;

// Frame relay LMI Type
enum eLMIType
{
	lmiNone,
	lmiRevision1,
	lmiStrataCom,
	lmiAnnexD,
	lmiAnnexA
};

// LAPB will either be DCE or DTE
enum eDXE
{
	DTE,
	DCE
};

// LABP Command or Response
enum eLABPCR
{
	lapbcrNone,
	lapbcrCommand,
	lapbcrResponse
};

// LAPB frame format
enum eLAPBFrameFormat
{
	lapbffI,
	lapbffS,
	lapbffU
};

// response to routines getting data from firmware
// disabled = "None" configure on a port
// NotAvailable = driver open failed
// Running = UpdateDataSourceStats works 
enum eDataSourceStatus
{
	dssNone = -1,
	dssDisabled = 0,
	dssNotAvailable,
	dssRunning
};

	// positive values are number of errors
const __int64 dseNoError = 0;
const __int64 dseNotAvailable = _UI64_MAX;
const __int64 dseLinkDown = _UI64_MAX - 1;	

// some constants used for readability
// NOTE: when you see something like this "DWORD Frames[2]" in the code
// Frames[0] are the frames trasmitted and
// Frames[1] are the frames received
enum
{
	TRANSMIT,
	RECIEVE,
	MIN = 0,
	CURRENT,
	MAX
};

// these are the protocol specific filter bits. when a frame is
// processed it's m_TraceFlag is set with some combo of these bits
enum eFilterMask
{
	// X25
	fmLAPB     = 0x01,
	fmX25PROTO = 0x02,
	fmUSERDATA = 0x04,

	// Frame Relay
	fmLMI      = 0x01,
	fmIP       = 0x02,
	fmIPX      = 0x04,
	fmEth      = 0x08,
	fmFRF9     = 0x10,
	fmCiscoIP  = 0x20,
	fmALLPROTO = 0x1E,

	// Isdn
	fmLapd     = 0x01,
	fmIl3      = 0x02,

	// All
	fmALL      = 0xFF
};

// X.25 call state constants used to implement the session trace stat
// pane
enum eCallState
{
	csNothing,
	csCallRequest,
	csCallAccept,
	csClearRequest,
	csClearAccept
};

// the is a bookmark struct. no instance of the struct is ever created
// it is the way the CFrame class accesses the frame it is pointing to.
// the m_Data is the location of the first byte of the frame data returned
// by the firmware during a trace. m_DataLen + m_ControlLen is the size of
// the frame. m_TraceFlag is the protocol specific flags used to implement
// filtering. The m_FrameNum is not set until trace is stopped. The frames
// are numbered by the firmware but it is only a 2 byte number. The frames
// are renumbered after trace is stopped with numbers from 1..n
const int sFrameBaseSize = 12;
struct sFrameBase
{
	short m_DataLen;
	short m_ControlLen;
	DWORD m_TraceFlag;
	DWORD m_FrameNum;
	UCHAR m_Data[1];
};

// CTraceFrameBuffer class is used by the CTraceData class to hold
// the frames captured. This class also read/write the frames to a file
// The code to renumber the frames from 1..n is here also

class CTraceFrameBuffer
{
// ************************************************
// these params are set by the capture buffer settings dialog box
// they are kept in the registry
	DWORD m_BufferSize; // size of frame buffer to allocate

	// amount of frame to place in buffer, this value should not be set too small
	// the current minimum is 64 bytes it could be made lower but... not much
	DWORD m_FrameSize;
// ************************************************

	DWORD m_BytesInBuffer;
	PUCHAR m_Buffer;

	// this array holds to offsets to the start of every frame in the buffer
	CDWordArray m_FrameOffset;

public :
	CTraceFrameBuffer();
	~CTraceFrameBuffer();

// Attributes
	DWORD GetNumBytes() const { return m_BytesInBuffer; };
	int GetNumFrames() const { return m_FrameOffset.GetSize() - 1; };
	DWORD GetFrameOffset(DWORD i) const { return m_FrameOffset[i]; };
	sFrameBase *GetFrameData(DWORD index) const { return (sFrameBase *)&m_Buffer[GetFrameOffset(index)]; };

// Operations
	// adds a frame to the buffer and returns a bookmark pointing to that frame
	sFrameBase *AddFrame(const strbuf&, const strbuf&);

	// read/write frames to disk
	void Serialize(CArchive&);
	
	// renumber frames from 1..n, and free extra buffer memory
	BOOL RenumberFrames(CFrame *);

	void NewFilter(CFrame *, CDWordArray&, DWORD, CDWordArray *);
};

inline HTREEITEM 
InsertTreeItem(CTreeCtrl& tree, LPCSTR title, HTREEITEM hParent = TVI_ROOT, int selStart = 0, int selEnd = 0)
{
	HTREEITEM item = tree.InsertItem(title, hParent);
	tree.SetItemData(item, (selEnd << 16) + selStart);
	return item;
}


class CFrame
{
	sFrameBase *m_FrameData;
protected :
	const CTraceData *m_TraceData;

public :

protected:
	PUCHAR GetControl() const { return m_FrameData->m_Data + m_FrameData->m_DataLen; };
	int GetControlLen() const { return m_FrameData->m_ControlLen; };
	
	CFrame(const CTraceData *td) { m_FrameData = NULL; m_TraceData = td; };
public :
// operations
	void SetData(sFrameBase *frame) { m_FrameData = frame; };
	void SetFilterMask(eFilterMask mask) { m_FrameData->m_TraceFlag = mask; };
	void SetFrameNum(DWORD num) { m_FrameData->m_FrameNum = num; };

	// the code to add all items in a TreeCtrl
	virtual void DisplayTreeData(CTreeCtrl&, const CTraceData *, CFrame *);

// attributes
	BOOL FilterTest(DWORD mask, CDWordArray *circuit = NULL) const;

	PUCHAR GetData() const { return m_FrameData->m_Data; };
	int GetDataLen() const { return m_FrameData->m_DataLen; };

	UCHAR operator[](int index) const
		{ ASSERT(index >= 0 && index < m_FrameData->m_DataLen); return m_FrameData->m_Data[index]; };
	operator PUCHAR() const { return GetData(); };
	operator int() const { return GetDataLen(); };

//	virtual DWORD GetSNID() const = 0;
	virtual DWORD GetSeqNum() const = 0; // the frame number assigned by firmware
	virtual DWORD GetTimeStamp() const = 0; // timestamp set by firmware

	// thses routines get data displayed in the ListCtrl
	DWORD GetFrameNum() const { return m_FrameData->m_FrameNum; };
	virtual DWORD GetTxRx() const = 0;
	virtual DWORD GetCircuit() const = 0;
	virtual LPCSTR GetProtocol() const = 0;
	virtual void GetDescription(CString&) const = 0;
};

class CIP
{
protected :
	int TreeDataIP(CTreeCtrl&, PUCHAR, int, HTREEITEM, int);
	CString MakeIPStr(PUCHAR);
};

class CIPX
{
protected :
	int TreeDataIPX(CTreeCtrl&, PUCHAR, HTREEITEM, int);
	CString MakeIPXStr(PUCHAR);
};

class CFRFrame : public CFrame, protected CIP, protected CIPX
{
	void TreeDataFR(CTreeCtrl&);
	void TreeDataIFrame(CTreeCtrl&, PUCHAR , int, HTREEITEM);
	void TreeDataLMI(CTreeCtrl&, PUCHAR, int, HTREEITEM);
	int TreeDataFRF9(CTreeCtrl&, PUCHAR, int, HTREEITEM, int);

public :
	CFRFrame(const CTraceData *td) : CFrame(td) { };

	virtual DWORD GetSeqNum() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_seq; };
	virtual DWORD GetTimeStamp() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_time; };
	virtual DWORD GetTxRx() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_rcv; };
	virtual DWORD GetCircuit() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_dlci; };
//	virtual DWORD GetSNID() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_snid; };
	DWORD GetDLCI() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_dlci; };
	DWORD GetLMI() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_lmi; };
	DWORD GetOptions() const { return ((fr_trc_msg_t *)GetControl())->fr_trc_opts; };
	virtual LPCSTR GetProtocol() const;
	virtual void GetDescription(CString&) const;
	virtual void DisplayTreeData(CTreeCtrl&, const CTraceData *, CFrame *);

// lmi type; Annex A,D, Stratacom, etc...
	eLMIType GetLMIType() const;
};

class CX25Frame : public CFrame
{
	void TreeDataLAPB(CTreeCtrl&);
	void TreeDataX25(CTreeCtrl&, HTREEITEM pitem, int offset);
	void TreeDataGFI(CTreeCtrl& tree, HTREEITEM pitem, int offset);
	void TreeDataChannelNumber(CTreeCtrl& tree, HTREEITEM pitem, int offset);

	int TreeDataAddr(CTreeCtrl&, PUCHAR, HTREEITEM, int, BOOL, UCHAR);
	int TreeDataFacility(CTreeCtrl&, PUCHAR, HTREEITEM, int);
	void TreeDataUserData(CTreeCtrl&, HTREEITEM, int, UCHAR);

	void TreeDataX29(CTreeCtrl&, PUCHAR, int, HTREEITEM);

	const CX25TraceData *GetTraceData() const
		{ ASSERT(m_TraceData != NULL);  return (CX25TraceData *)m_TraceData; };

public :
	CX25Frame(const CTraceData *td) : CFrame(td) { };

	virtual DWORD GetSeqNum() const { return ((trc_types *)GetControl())->trc_hdr.trc_seq; };
	virtual DWORD GetTimeStamp() const { return ((trc_types *)GetControl())->trc_hdr.trc_time; };
	virtual DWORD GetTxRx() const { return ((trc_types *)GetControl())->trc_hdr.trc_rcv; };
	virtual DWORD GetCircuit() const
		{ int index = 2 + (GetModulus() == G_128);
			return FilterTest(fmLAPB) ? (DWORD)-1 : ((GetData()[index] & 0xF) << 8) + GetData()[index+1];
		};
//	virtual DWORD GetSNID() const { return ((trc_types *)GetControl())->trc_hdr.trc_snid; };
	virtual LPCSTR GetProtocol() const { return FilterTest(fmLAPB) ? c_pszKeyLAPB : c_pszValueX25Protocol; };
	virtual void GetDescription(CString& str) const { FilterTest(fmLAPB) ? GetLAPBDescription(str) : GetX25Description(str); };

	CString GetX25Address(DWORD, eCallState);
	CString GetX25Diagnostic(UCHAR) const;
	void GetX25Description(CString&) const;
	void GetLAPBDescription(CString&) const;
	eLABPCR GetLAPBCommandOrResponce() const; // true if command
	virtual void DisplayTreeData(CTreeCtrl&, const CTraceData *, CFrame *);

	// lapb modulus value NOT the X.25 one
	// this is a special exception data member for a CFrame class
	// the lapb modulus value CANNOT be determined by looking at frame data
	// G_128 for modulus 128 lapb, G_8 for modulus 8 lapb
	// the lapb data terminal type value CANNOT be determined by looking at frame data
	DWORD GetModulus() const;
	// Are we LAPB DTE or DCE
	eDXE GetDXE() const;
};

class CTraceData : public CObject
{
// ************************************************
// panes that display this data
	friend class CTraceStatView;
	friend class CSessionListCtrl;
	friend class CSessionStatView;
	friend class CPacketListView;
// ************************************************

	DECLARE_SERIAL(CTraceData);

private :
// ************************************************
// data displayed in the capture summary diaglog box
	CString m_Machine;
	CString m_DataSourceName;
	CString m_Protocol;
	CTime m_DateTime;
	CArray<sDriverInfo, const sDriverInfo&> m_Drivers;
	CString m_FirmwareVersion;
	CString m_Comment;
// ************************************************

	DWORD FC[2]; // frame count since beginning to trace
	DWORD BC[2]; // byte count since beginning to trace

	sMCM LU[2]; // line utilization
	sMCM FPS[2]; // frames per second
	sMCM Th[2]; // thoughput (bps)

// ************************************************
protected:
	// some data is cleared in a different thread than it is processed
	CCriticalSection m_Section;

	CTraceFrameBuffer m_FrameBuffer; // only one frame buffer per trace

	// only one CFrame derived class needed, is used by everyone who need access to frame data
	CFrame *m_ScratchFrame; // refernces to this variable should never be kept around

	DWORD m_FirstTimeStamp; // time stamp from firmware for first trace frame processed
	CTimeSpan m_Elapsed;

// ************************************************
// session trace stats are created and maintained by the derived class
	CArray<sSession *, sSession *> m_Sessions; // array of sessions since start of trace
	friend void AFXAPI SerializeElements(CArchive& ar, sSession **pElements, int nCount);

	// map containing refernces to sessions where frames are actively coming in on
	CMap<DWORD, DWORD, sSession *, sSession *> m_LiveSessions; 
// ************************************************

// ************************************************
// used to calculate FPS/BPS/TH
	_timeb m_LastTime; // last time the per second stats where cleared
	DWORD m_ByteRate; // line speed in bytes per second
// ************************************************

// some functions are pure virtual even though they don't look that
// way. CTraceData contains as much data and functionality as possible
// to be protocol independant.

// creates protocol dependant CFrame derived class
	virtual CFrame *CreateFrame() const { VERIFY(FALSE); return NULL; };

public:
// ************************************************
// constructor/destructors
	CTraceData() : CObject(), m_Sessions(), m_Drivers() { }; // never use this

	// CTraceData must know the byte rate of the data source and
	// the array of circuits the data source has 
	CTraceData(DWORD baud); 
	virtual ~CTraceData();
// ************************************************

// attributes
	CString GetDataSourceName() const { return m_DataSourceName; };

// this is how everyone gets to access a frame in the buffer
// frames are maintained in the buffer by number 0..n-1
// this number is NOT the frame number stored in the frame itself
	CFrame *GetTempFrame(DWORD i)
		{ m_ScratchFrame->SetData(m_FrameBuffer.GetFrameData(i));
			return m_ScratchFrame; };

// a new frame is created and pointed at a frame in the buffer
// frames are maintained in the buffer by number 0..n-1
// this number is NOT the frame number stored in the frame itself	
	CFrame *GetNewFrame(DWORD i) const
		{ CFrame *frame = CreateFrame();
			frame->SetData(m_FrameBuffer.GetFrameData(i));
			return frame; };

// the ListCtrl pane uses this routine to set its list of frame
// the filter params are always used, the lparam of each item added
// is the number used to a call to GetTempFrame()
	void GetFilteredFrames(CDWordArray&, DWORD, CDWordArray *);

	// returns number of frames in frame buffer
	int GetNumFrames() const { return m_FrameBuffer.GetNumFrames(); };

// frames in the ListCtrl display time in seconds starting from when the trace was
// started. You pass the frames time stamp set by firmware and get get back
// the time in seconds back
	virtual double TimeInSeconds(DWORD) const { VERIFY(FALSE); return 0.f; }; 

	const CTime& GetStartTime() const { return m_DateTime; };

// protocol specific name for a circuit of channel
	virtual LPCSTR GetEndPointName() const { VERIFY(FALSE); return NULL; }

// when CTraceData class is created it need to init the the
// data source data written to disk
	virtual void SetCaptureSummaryInfo(const CDataSource *);

// Operations
	virtual CTraceSheet *CreateTraceSheet();
	virtual void Serialize(CArchive&); // read/write data to disk

	// when trace is stopped frames are renumbered from 1..n
	BOOL RenumberFrames();

	// called to calculate per second data
	void NextSecond();

	// called to calculate per second data for the vircuit circuits
	virtual void DoVCNextSecond(DWORD) { VERIFY(FALSE); };

	// brings up protocol specific filter dialog box and set filter params
	virtual BOOL DoFilterOptions(DWORD&, CDWordArray *) { VERIFY(FALSE); return FALSE; };

	// every frame that comes up from firmware is processes as soon as it comes up
	// this routine is where all the trace data is incremented
	// it is not called in the main GUI thread.
	virtual void ProcessFrame(const strbuf& control, const strbuf& data);

	// display capture summary dialog box
	BOOL DoCaptureSummaryDlg(CWnd *);

	// handles the clear statistics menu item
	// not all trace stats are cleared
	virtual void ClearTraceStats();
};

class CFRTraceData : public CTraceData
{
	friend class CFRLineStatView;
	friend class CFRVCStatView;
	friend class CFRVCListCtrl;
	friend class CFRFrame;

	DECLARE_SERIAL(CFRTraceData);

private :
// ************************************************
// frame relay specific virtual circuit trace stats
	CMap<DWORD, DWORD, sFRVCStats *, sFRVCStats *> m_VCStats;
// ************************************************

// lmi type; Annex A,D, Stratacom, etc...
	eLMIType m_LMIType;

// ************************************************
// frame relay specific trace stats
	DWORD DE[2];
	DWORD BECN[2];
	DWORD FECN[2];
	DWORD LMISM[2];
	DWORD LMISE[2];
	DWORD LMIUS[2];
	DWORD IP[2];
	DWORD CiscoIP[2];
	DWORD IPX[2];
	DWORD FRF9[2];
	DWORD Ethernet[2];
	DWORD Other[2];
// ************************************************

// creates a CFRFrame
	virtual CFrame *CreateFrame() const { return new CFRFrame(this); };

// ************************************************
// frame relay only helper functions
	BOOL BumpFRPktType(CFRFrame *);
	eFilterMask GetFRProtocol(PUCHAR Payload) const;
// ************************************************

public:
	CFRTraceData() : CTraceData() {};
	CFRTraceData(DWORD baud, CDWordArray&);
	~CFRTraceData();

// attributes
	virtual double TimeInSeconds(DWORD t) const;
	virtual LPCSTR GetEndPointName() const { return c_pszValueDLCI; };

// operations
	virtual CTraceSheet *CreateTraceSheet();
	virtual void Serialize(CArchive&);
	virtual void DoVCNextSecond(DWORD);
	void SetCaptureSummaryInfo(const CDataSource *);
	virtual BOOL DoFilterOptions(DWORD&, CDWordArray *);
	virtual void ProcessFrame(const strbuf& control, const strbuf& data);
	virtual void ClearTraceStats();
};

class CX25TraceData : public CTraceData
{
	friend class CLAPBLineView;
	friend class CX25LineStatView;
	friend class CX25VCStatView;
	friend class CX25VCListCtrl;
	friend class CX25Frame;

	DECLARE_SERIAL(CX25TraceData);

private :
	// lapb modulus value NOT the X.25
	DWORD m_Modulus; // G_128 for modulus 128 lapb, G_8 for midulus 8 lapb
	eDXE m_DXE; // are we DTE or DCE

// array of channels which are pvc's
	CDWordArray m_ChannelPVC;

// ************************************************
// X.25 specific virtual circuit trace stats
	CMap<DWORD, DWORD, sX25VCStats *, sX25VCStats *> m_VCStats;
// ************************************************

// ************************************************
// lapb specific trace stats
	DWORD LAPBData[2];
	DWORD LAPBRR[2];
	DWORD LAPBRNR[2];
	DWORD LAPBREJ[2];
	DWORD LAPBFRMR[2];
	DWORD LAPBUA[2];
	DWORD LAPBDM[2];
	DWORD LAPBDISC[2];
	DWORD LAPBSABM[2];
	DWORD LAPBSABME[2];
// ************************************************

// ************************************************
// X.25 specific trace stats
	DWORD X25Data[2];
	DWORD X25RR[2];
	DWORD X25RNR[2];
	DWORD X25Reject[2];
	DWORD X25CallRq[2];
	DWORD X25CallAc[2];
	DWORD X25ClrRq[2];
	DWORD X25ClrCf[2];
	DWORD X25RstRq[2];
	DWORD X25RstCf[2];
	DWORD X25RrtRq[2];
	DWORD X25RrtCf[2];
	DWORD X25Int[2];
	DWORD X25IntCf[2];
	DWORD X25RegRq[2];
	DWORD X25RegCf[2];
	DWORD X25Diag[2];
	DWORD X25Unkn[2];
// ************************************************

	// create a CX25Frame
	virtual CFrame *CreateFrame() const { return new CX25Frame(this); };

// ************************************************
// x.25 specific helper functions
	eCallState BumpX25PktType(DWORD dir, UCHAR c, BOOL&);
	BOOL BumpLAPBControl(DWORD dir, UCHAR c);
// ************************************************

public:
	CX25TraceData() : CTraceData() {};
	CX25TraceData(DWORD baud, CDWordArray&);
	~CX25TraceData();

// attributes
	virtual double TimeInSeconds(DWORD t) const;
	virtual LPCSTR GetEndPointName() const { return c_pszValueChannel; };

// operations
	virtual CTraceSheet *CreateTraceSheet();
	virtual void Serialize(CArchive&);
	virtual void DoVCNextSecond(DWORD);
	virtual BOOL DoFilterOptions(DWORD&, CDWordArray *);
	virtual void ProcessFrame(const strbuf& control, const strbuf& data);
	virtual void SetCaptureSummaryInfo(const CDataSource *);
	virtual void ClearTraceStats();
};

class CWANLINESTATUS : public CStat<wan_linestatus_t>
{
public :
	CWANLINESTATUS( uint32 SNID = -1 ) : CStat<wan_linestatus_t>(W_LINESTATUS)
		{ wan_linestatus_snid = SNID; };

	// Operations
	void SetSNID(uint32 SNID) { wan_linestatus_snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stWANS; };
	virtual GetStatCount() const { return sizeof(wan_linestatus_stats) / sizeof(uint32); };

	const wan_linestatus_t *operator->() const { return this; };

};

class CWANTRACE : public CStat<wan_trace_config_t>
{
public :
	CWANTRACE(uint32 SNID = -1) : CStat<wan_trace_config_t>(W_TRACEON)
		{ wan_trace_snid = SNID; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { return stWANS; };

	const wan_trace_config_t *operator->() const { return this; };
};

inline void IncrementError(__int64& Err, DWORD Errors)
{
	if (Err == dseNotAvailable)
		Err = Errors;
	else if (Err != dseLinkDown)
		Err += Errors;
}

class CDataSource
{
protected :
	// determines how to handle a GetStatus call
	eDataSourceStatus m_Status;
	CString m_Device;
	CString m_RegPath; // registry line path to DataSource config
	CString m_ParameterRegPath; // registry paramters path to DataSource config
	CString m_LineNumber; // Line Number of the Data Sources
	DWORD   m_SNID; // firmware Port identifier

private:
	CEvent m_Event;
	HANDLE m_hFile; // handle to Sxb driver, opened only once and kept open
	OVERLAPPED m_Overlapped;

	// handle to protocol specific device
	// attempt are made to minimize the number of times a firmwave device is
	// opened and closed. a better way to do this would be to keep every
	// device open like the file handle but this is not done
	HANDLE m_VCObject;
	
	ULONG m_LastFirmwareError;

	// helper variable to minimize device opens/closes
	CMap<eSourceType, eSourceType&, HANDLE, HANDLE> m_VCObjectMap;

	// asyncronous call to talk to driver, times out in one second
	BOOL DeviceIoControl(CSXB_IOCTL *) const;

	// opens firmware device
	BOOL SOpen(eSourceType) const;

protected:
	// array of circuits on this datasource
	// passed on to a CTraceData
	CDWordArray m_Circuits;

	// state used for enabled/disable state of menus and toolbar butttons
	// the menu items updated are stop/pause/start trace
	int m_TraceState;
	int m_TracePPPSNA;

	// ************************************************
	// protocol specific routines to control a trace
	virtual CTracer *CreateTracer() { return NULL; };
	virtual CTraceData *CreateTraceData(DWORD, CDWordArray&) { return NULL; };

	CTracer *m_Tracer;
	CTraceData *m_TraceData;
	// ************************************************

	friend class CTraceData;
	friend class CDiagDoc;
	friend class CTracePage;

	// ************************************************
	// info obtains when data source was created
	// this is hardwired to hold only two drivers but can be changed
	// to resizable array when Dxb and more drivers get in the picture
	CArray<sDriverInfo, const sDriverInfo&> m_Drivers;
	CString m_FirmwareVersion;

	DWORD m_BaudRate; // passed on to a CTraceData
	// ************************************************

	static sDriverInfo GetDriverInfo(const CString& keyName);
	CTraceData *GetTraceData() { return m_TraceData; };

	// data source view data
	friend class CDataSourceView;
	
	__int64 m_Tx;
	__int64 m_ClearTx;

	__int64 m_Rx;
	__int64 m_ClearRx;

	__int64 m_Err;
	__int64 m_ClearErr;
	
	CString m_Name;
	CString m_Alarms;

	CWAN m_WanStats;
	_timeb m_UpdateTime;

	CWANLINESTATUS m_WanLineStatus;

public:
	CDataSource(const HKEY hkLine, const CString& DeviceName);
	CDataSource();
	virtual ~CDataSource();

// Attributes
	BOOL IsTracing() const { return m_TraceState != 0; };
	BOOL IsPaused() const { return m_TraceState == 2; };
	BOOL IsTracePPPSNA() const { return m_TracePPPSNA == 1; };	//Added by Vijay
	DWORD GetByteRate() const { return m_BaudRate >> 3; };
	LPCTSTR GetName() const { return m_Name; };

	virtual const CSXB_USER_IOCTL *GetStatType(const type_info&, int = -1) const;

	// ************************************************
	// protocol specific support
	CTraceSheet *CreateTraceSheet()
		{ ASSERT(m_TraceData); return m_TraceData->CreateTraceSheet(); };
	virtual CRuntimeClass *GetStatDocClass() const;

	int GetNumCircuits() const { return m_Circuits.GetSize(); };
	DWORD GetCircuitNum(int index) const { return m_Circuits[index] & ChannelMask; };

	DWORD GetSNID() const { return m_SNID; }; // sub network id , usually 'A' or 'B'

	// Sxb device name used to open file handle to Sxb driver
	CString GetDeviceName() const
		{ return "\\\\.\\" + m_Device; };

	virtual LPCSTR GetProtocol() const { return c_pszKeyProtocolNone; };
	eDataSourceStatus GetStatus(eSourceType FirmareDevice);
	virtual eSourceType GetDefaultFirmwareDevice() = 0;
	virtual BOOL UpdateDataSourceStats();
	const _timeb& GetUpdateTime() const { return m_UpdateTime; };
	ULONG GetLastFirmwareError() const { return m_LastFirmwareError; };

	// ************************************************

	const CTraceData *GetTraceData() const { return m_TraceData; };
	BOOL TraceDataExists() const { return m_TraceData != NULL; };
// Operations

	void AddDriverInfo(LPCTSTR DriverServiceName) 
		{ sDriverInfo Info = GetDriverInfo(DriverServiceName); if (Info.m_DriverName.GetLength()) m_Drivers.Add(Info); };

	void NextSecond() { m_TraceData->NextSecond(); };

	void SetName(CString AdapterName, CString VAdapterNum, int LineNum)
		{ m_Name.Format(" - Line %d", LineNum); m_Name = "[" + VAdapterNum + "] " + AdapterName + m_Name; };

	void SetLineKeyName(CString KeyName)
		{ m_RegPath = KeyName; };

	void SetParametersKeyName(CString KeyParameters)
		{ m_ParameterRegPath = KeyParameters; };

	void SetLineNumber(DWORD LineNumber)
		{ m_LineNumber.Format("%d",LineNumber); };

	// ************************************************
	// operations used to init data source
	virtual void LoadConfigCircuits();
	void DeleteCircuits() { m_Circuits.RemoveAll(); };
	virtual void LoadSummaryInfo(const CString&);
	BOOL TestDataSource(eSourceType FirmareDevice);
	// ************************************************

	// this routine gets stats 
	eDataSourceStatus GetData(CSXB_USER_IOCTL *);

	void ClearTraceStats(); // clear trace stats only when a trace is running
	void ClearStatistics(); // clear data source stats

	// data source summary dialog box
	// not the same as capture summary dialog box
	void DoSummaryDlg() const;

	// pass through routine to CTraceData to process every frame returned
	// by firmware. Called in CTracers thread
	void ProcessFrame(const strbuf& control, const strbuf& data)
		{ ASSERT(m_TraceData); m_TraceData->ProcessFrame(control, data); };

	void StopStats(ENUM_STOP_TYPE eStopType); // closes open handles left open by stats

	BOOL StartTrace(); // you guessed it starts a trace, returns success/failure
	void StopTrace(); // stop trace
	void ToggleTrace(); // pause/continue trace

	// when the user views a trace the datasource refernce to the tracedata
	// is moved to the document. this is done only after a trace is stopped
	void TraceDataToDoc(CDiagDoc *doc) const;
};

typedef CDataSource *PDataSource;

class CX25DataSource : public CDataSource
{
	virtual CTracer *CreateTracer();
	virtual CTraceData *CreateTraceData(DWORD, CDWordArray&);

	// lapb modulus value NOT the X.25
	DWORD m_Modulus; // G_128 for modulus 128 lapb, G_8 for midulus 8 lapb
	eDXE m_DXE; // Are we LAPB DTE or DCE

	CLAPB m_LAPBStats;
	CX25 m_X25Stats;

public:
	CX25DataSource(const HKEY hkLine, const CString& DeviceName);

// Attributes
	virtual const CSXB_USER_IOCTL *GetStatType(const type_info&, int = -1) const;
	virtual CRuntimeClass *GetStatDocClass() const;

	virtual LPCSTR GetProtocol() const { return c_pszValueX25Protocol; };
	virtual eSourceType GetDefaultFirmwareDevice() {return stWANS;}
	virtual BOOL UpdateDataSourceStats();

	DWORD GetModulus() const { return m_Modulus; };
	eDXE GetDXE() const { return m_DXE; };

// Operations
	virtual void LoadConfigCircuits();
	virtual void LoadSummaryInfo(const CString&);
};

//------------------------------------------------------------ MLZ 7/20/98 {
class CDS1_STATUS : public CStat<ds1_status_t>
{
	ULONG m_Snid;
public :
	CDS1_STATUS( uint32 Snid = -1 ) : CStat<ds1_status_t>(GET_DS1_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the snid,
		// get back a ds1_status_t struct!
		{ m_Snid = Snid;pDataIn = &m_Snid; cbDataIn = sizeof(m_Snid); }

	// Operations
	void SetSNID(uint32 Snid) { m_Snid = Snid; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_Snid != -1); return stMGMT; };
	virtual GetStatCount() const { return 0; };	// No counters that wrap

	const ds1_status_t *operator->() const { return this; };
};


class CDS1_EXT_STATUS : public CStat<ds1_ext_status_t>
{
	friend class CHlcStatDoc;
	ULONG m_Snid;
public :
	CDS1_EXT_STATUS( uint32 Snid = -1 ) : CStat<ds1_ext_status_t>(GET_DS1_EXT_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the snid,
		// get back a ds1_ext_status_t struct!
		{ m_Snid = Snid;pDataIn = &m_Snid; cbDataIn = sizeof(m_Snid); }

	// Operations
	void SetSNID(uint32 Snid) { m_Snid = Snid; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_Snid != -1); return stMGMT; };

//	virtual GetStatCount() const { return sizeof(ds1_ext_status_t) / sizeof(uint32); };
	const ds1_ext_status_t *operator->() const { return this; };
//	uint32& operator[](int index) { return ((uint32 *)&errored_seconds)[index]; };
//	uint32 operator[](int index) const { return ((uint32 *)&errored_seconds)[index]; };
};


class CBRI_STATUS : public CStat<bri_status_t>
{
	friend class CHlcStatDoc;
	ULONG m_Snid;
public :
	CBRI_STATUS( uint32 Snid = -1 ) : CStat<bri_status_t>(GET_BRI_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the snid,
		// get back a bri_status_t struct!
		{ m_Snid = Snid;pDataIn = &m_Snid; cbDataIn = sizeof(m_Snid); }

	// Operations
	void SetSNID(uint32 Snid) { m_Snid = Snid; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_Snid != -1); return stMGMT; };

//	virtual GetStatCount() const { return 2; };	// Last two counters wrap
	const bri_status_t *operator->() const { return this; };
//	uint32& operator[](int index) { return ((uint32 *)&loss_of_sync)[index]; };
//	uint32 operator[](int index) const { return ((uint32 *)&loss_of_sync)[index]; };
};


class CMODEM_STATUS : public CStat<modem_status_t>
{
	friend class CHlcStatDoc;
	ULONG m_channel;
public :
	CMODEM_STATUS( uint32 channel = -1 ) : CStat<modem_status_t>(GET_MODEM_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the channel,
		// get back a modem_status_t struct!
		{ m_channel = channel;pDataIn = &m_channel; cbDataIn = sizeof(m_channel); }

	// Operations
	void SetChannel(uint32 channel) { m_channel = channel; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_channel != -1); return stMGMT; };

//	virtual GetStatCount() const { return 0; };	// No counters that wrap
	const modem_status_t *operator->() const { return this; };
};


class CMODEM_EXT_STATUS : public CStat<modem_ext_status_t>
{
	friend class CHlcStatDoc;
	ULONG m_channel;
public :
	CMODEM_EXT_STATUS( uint32 channel = -1 ) : CStat<modem_ext_status_t>(GET_MODEM_EXT_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the channel,
		// get back a modem_ext_status_t struct!
		{ m_channel = channel;pDataIn = &m_channel; cbDataIn = sizeof(m_channel); }

	// Operations
	void SetChannel(uint32 channel) { m_channel = channel; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_channel != -1); return stMGMT; };

//	virtual GetStatCount() const { return 0; };	// No counters that wrap
//	const modem_ext_status_t *operator->() const { return this; };
};
//------------------------------------------------------------ MLZ 7/20/98 }

class CDCHAN_EXT_STATUS : public CStat<dchan_ext_status_t>
{
	friend class CHlcStatDoc;
	ULONG m_Snid;
public :
	CDCHAN_EXT_STATUS( uint32 Snid = -1 ) : CStat<dchan_ext_status_t>(GET_DCHAN_EXT_STATUS)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the snid,
		// get back a dchan_ext_status_t struct!
		{ m_Snid = Snid;pDataIn = &m_Snid; cbDataIn = sizeof(m_Snid); }

	// Operations
	void SetSNID(uint32 Snid) { m_Snid = Snid; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_Snid != -1); return stMGMT; };

	const dchan_ext_status_t *operator->() const { return this; };
};

class CBRI_CONFIG : public CStat<bri_config_t>
{
	friend class CHlcStatDoc;
	ULONG m_Snid;
public :
	CBRI_CONFIG( uint32 Snid = -1 ) : CStat<bri_config_t>(GET_BRI_CONFIG)
		// Goofy mgmthlc api's have different struct for tx/rx.  Send down the snid,
		// get back a bri_config_t struct!
		{ m_Snid = Snid;pDataIn = &m_Snid; cbDataIn = sizeof(m_Snid); }

	// Operations
	void SetSNID(uint32 Snid) { m_Snid = Snid; };

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT( m_Snid != -1); return stMGMT; };

	const bri_config_t *operator->() const { return this; };
};

// class CSdlcTraceSheet;
// class CSdlcTracer;
// class CSdlcTraceData;
// class CSdlcDataSource;

class CSdlcFrame : public CFrame
{
	void TreeDataSdlc(CTreeCtrl&, HTREEITEM hParentNode);
	void TreeDataSdlcAddress(CTreeCtrl&, HTREEITEM hParentNode);
	void TreeDataSdlcSupervisoryFrame(CTreeCtrl&, HTREEITEM hParentNode);
	void TreeDataSdlcUnnumberedFrame(CTreeCtrl&, HTREEITEM hParentNode);
	void TreeDataSdlcInfoFrame(CTreeCtrl&, HTREEITEM hParentNode);
	void AddSFrameType(CString& msg) const;
	void AddUFrameType(CString& msg) const;

public :
	CSdlcFrame(const CTraceData *td) : CFrame(td) { };

	virtual DWORD GetSeqNum()    const { return ((wan_trace_t *)GetControl())->wan_trace_sequence; }
	virtual DWORD GetTimeStamp() const { return ((wan_trace_t *)GetControl())->wan_trace_time; }
	virtual DWORD GetTxRx()      const { return ((wan_trace_t *)GetControl())->wan_trace_direction; }

	virtual DWORD GetCircuit()   const { return (GetData()[1] & 0xFE) >> 1; }

	virtual LPCSTR GetProtocol() const;
	virtual void GetDescription(CString&) const;
	virtual void DisplayTreeData(CTreeCtrl&, const CTraceData *, CFrame *);
};


class CSdlcTraceData : public CTraceData
{
	friend class CSdlcFrame;

	// DECLARE_SERIAL(CSdlcTraceData);

private :

// ************************************************
// Sdlc specific trace stats
//	DWORD DE[2];

//	BOOL BumpLapdControl(DWORD dir, UCHAR c);
// ************************************************

// creates a CSdlcFrame
	virtual CFrame *CreateFrame() const { return new CSdlcFrame(this); };

// ************************************************
// Sdlc only helper functions
// ************************************************

public:
	CSdlcTraceData() : CTraceData() {};
	CSdlcTraceData(DWORD baud, CDWordArray&);
	~CSdlcTraceData();

// attributes
	virtual double TimeInSeconds(DWORD t) const {return (t - m_FirstTimeStamp) / 1000.0f;}
	virtual LPCSTR GetEndPointName() const { return "TEI"; };

// operations
	virtual CTraceSheet *CreateTraceSheet();
	virtual void Serialize(CArchive&);
	virtual void DoVCNextSecond(DWORD) {};
	virtual BOOL DoFilterOptions(DWORD&, CDWordArray *);
	virtual void ProcessFrame(const strbuf& control, const strbuf& data);
	virtual void ClearTraceStats();
};


class CSnaDataSource : public CDataSource
{
	virtual CTracer *CreateTracer();
	virtual CTraceData *CreateTraceData(DWORD, CDWordArray&);

public:
	CSnaDataSource(const HKEY hkLine, const CString& DeviceName);

// Attributes
	virtual const CSXB_USER_IOCTL *GetStatType(const type_info&, int = -1) const;
	virtual CRuntimeClass *GetStatDocClass() const;

	virtual LPCSTR GetProtocol() const { return "SNA"; };
	virtual eSourceType GetDefaultFirmwareDevice() {return stWANS;}
	virtual BOOL UpdateDataSourceStats();

	const CWANLINESTATUS& GetLineStatus() const {return m_WanLineStatus;}

// Operations
	virtual void LoadConfigCircuits() 
	{
		CWANTUNE WanTune(GetSNID());
		if (GetData(&WanTune) == dssRunning )
			m_BaudRate = WanTune->WAN_hd.WAN_baud;
	}
	virtual void LoadSummaryInfo(const CString&);
	virtual eDataSourceStatus GetStatus(eSourceType FirmwareDevice = stWANS) {return CDataSource::GetStatus( FirmwareDevice );}
};



/*
For the next two classes to really work, need to include file HDLCTrace.cpp in the build project
The file is checked in sourcesafe but currently not part of the project
We are not doing PPP traces until we can decode something meaningful.
Netmon and other system utilities already provide deep PPP tracing.  The only reason
to do PPP tracing would be to be consistent with rest of the protocols
*/
class CHdlcFrame : public CFrame
{
public :
	CHdlcFrame(const CTraceData *td) : CFrame(td) { };

	virtual DWORD GetSeqNum()    const { return ((wan_trace_t *)GetControl())->wan_trace_sequence; }
	virtual DWORD GetTimeStamp() const { return ((wan_trace_t *)GetControl())->wan_trace_time; }
	virtual DWORD GetTxRx()      const { return ((wan_trace_t *)GetControl())->wan_trace_direction; } 

	virtual DWORD GetCircuit()   const { return (GetData()[1] & 0xFE) >> 1; }

	virtual LPCSTR GetProtocol() const;
	virtual void GetDescription(CString&) const;
	virtual void DisplayTreeData(CTreeCtrl&, const CTraceData *, CFrame *);
};


class CHdlcTraceData : public CTraceData
{
	friend class CHdlcFrame;

	// DECLARE_SERIAL(CHdlcTraceData);

private :

// creates a CSdlcFrame
	virtual CFrame *CreateFrame() const { return new CHdlcFrame(this); };


public:
	CHdlcTraceData() : CTraceData() {};
	CHdlcTraceData(DWORD baud, CDWordArray&);
	~CHdlcTraceData();

// attributes
	virtual double TimeInSeconds(DWORD t) const {return (t - m_FirstTimeStamp) / 1000.0f;}
	virtual LPCSTR GetEndPointName() const { return "TEI"; };

// operations
	virtual CTraceSheet *CreateTraceSheet();
	virtual void Serialize(CArchive&);
	virtual void DoVCNextSecond(DWORD) {};
	virtual BOOL DoFilterOptions(DWORD&, CDWordArray *);
	virtual void ProcessFrame(const strbuf& control, const strbuf& data);
	virtual void ClearTraceStats();
};


inline void HandleClearStats(__int64& Stat, __int64& ClearStat)
{
	if (Stat != dseNotAvailable && Stat != dseLinkDown) {
		if (ClearStat == -1)
			ClearStat = Stat;

		Stat -= ClearStat;
		}
}

void AFXAPI SerializeElements(CArchive& ar, sDriverInfo *pElements, int nCount);

// The idea of 'm_Registry' is the make the support of different types
// of adapters modular. You make a CAdapter derived class and add it the
// the adapter registry. The string to which you register the runtime class is
// the Option value stored in the adapter service key in the registry. If
// you want multiple Option strings to map to the same CAdapter derived
// class then just add one registry entry for each ProductName string.

inline void AFXAPI DestructElements(CDataSource ** pElements, int nCount)
{
	for (int i = 0; i < nCount; i++)
		delete pElements[i];
}


class CAdapter : public CObject
{
	DECLARE_DYNCREATE(CAdapter);
	static CTypedPtrMap<CMapStringToPtr,CString,CRuntimeClass *> m_Registry;
	CString m_DriverName;

protected:
	CArray<CDataSource *, CDataSource *> m_DataSource;

	CAdapter() : CObject(), m_DataSource() {};

// Attributes
	int GetAdapterNumber(const CString& keyName) const
		{	return atoi(LPCTSTR(keyName) + strlen(m_DriverName)); };

// Operations
	virtual void LoadSummaryInfo(CDataSource *ds)
		{ ds->AddDriverInfo(m_DriverName); };

public:
	virtual ~CAdapter() {};

// Attributes
	const PDataSource operator[](int index) const { return GetDataSource(index); };
	const PDataSource GetDataSource(int index) const { return m_DataSource[index]; };
	int GetNumDataSource() const { return m_DataSource.GetSize(); };

// Operations
	void SetDriverName(const CString& Name) {m_DriverName = Name;}

// read registry data, get line speed etc...
	virtual BOOL LoadConfig(const CString& strDeviceName, const CString& Option, const HKEY hkParams, const CString& ParamsPath );
// update for the the DataSource Dialog list ctrl
	virtual void UpdateDataSource();

	static void AddAdapter(CString Option, CRuntimeClass *rtc) { m_Registry.SetAt(Option, rtc); };
	static CRuntimeClass *RegistryLookUp(const CString& key) { return m_Registry[key]; };
};

class CSXBAdapter : public CAdapter
{
	DECLARE_DYNCREATE(CSXBAdapter);
};

/*
class C570LLDAdapter : public CAdapter
{
	DECLARE_DYNCREATE(C570LLDAdapter);

// Attributes
	virtual LPCTSTR GetProductName() { return "Digi570LLD"; };

// Operations
	virtual void LoadSummaryInfo(CDataSource *ds)
		{ CAdapter::LoadSummaryInfo(ds); 
			ds->AddDriverInfo("DigiDibs");
		}
};
*/

///////////////////////////////////////////////////////////////////////////////
// DataFire PRIme stats
///////////////////////////////////////////////////////////////////////////////

#undef FRAME_D4
#undef FRAME_ESF
#undef JITTER_AUTO
#undef JITTER_TX
#undef JITTER_RX
#undef JITTER_NONE
#include "t1_api.h"

class CIfaceState : public CStat<IfaceState_t>
{
public:
	CIfaceState( uint32 Snid = -1 ) : CStat<IfaceState_t>( GET_IFACE_STATE ) { Header.Interface = Snid; Header.Command = GET_IFACE_STATE; }

	// Operations
	void SetSNID( uint32 Snid ) { Header.Interface = Snid; }

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(Header.Interface != -1); return stT1;}
	virtual GetStatCount() const {return 0;}

	const IfaceState_t *operator->() const {return this;}
};

class CRfc1406 : public CStat<RFC1406_t>
{
public:
	CRfc1406( uint32 Snid = -1 ) : CStat<RFC1406_t>( GET_RFC1406 ) { Header.Interface = Snid; }

	// Operations
	void SetSNID( uint32 Snid ) { Header.Command = GET_RFC1406; Header.Interface = Snid; }

	// Attributes
	virtual eSourceType GetFirmwareType() const { ASSERT(Header.Interface != -1); return stT1;}
	virtual GetStatCount() const {return 0;}

	const RFC1406_t *operator->() const {return this;}
};
