#ifndef _MGEN
#define _MGEN
#include "protokit.h"
#include "mgenFlow.h"
#include "mgenMsg.h"
class DrecGroupList
{
public:
DrecGroupList();
~DrecGroupList();
// (TBD) make socketList argument of constructor or Init() method ???
void Destroy(MgenSocketList& socketList);
bool JoinGroup(MgenSocketList& socketList,
const ProtoAddress& groupAddress,
const char* interfaceName = NULL,
unsigned short thePort = 0,
bool deferred = false);
bool LeaveGroup(MgenSocketList& socketList,
const ProtoAddress& groupAddress,
const char* interfaceName = NULL,
unsigned short thePort = 0);
bool JoinDeferredGroups(MgenSocketList& socketList);
private:
class Item
{
friend class DrecGroupList;
public:
Item(const ProtoAddress& groupAddr,
const char* interfaceName,
unsigned short thePort);
~Item();
void SetInterface(const char* interfaceName)
{
if (interfaceName)
strncpy(interface_name, interfaceName, 16);
else
interface_name[0] = '\0';
}
const char* GetInterface()
{return (('\0' != interface_name[0]) ? interface_name : NULL);}
bool IsActive() {return (NULL != socket_item);}
bool Activate(MgenSocketList& socketList)
{
const char* iface = GetInterface();
socket_item = socketList.JoinGroup(group_addr, iface, port);
return IsActive();
}
unsigned short GetPort() {return port;}
private:
MgenSocketList::Item* socket_item;
ProtoAddress group_addr;
char interface_name[16];
unsigned short port;
Item* prev;
Item* next;
}; // end class DrecGroupList::Item
Item* FindItemByGroup(const ProtoAddress& groupAddr,
const char* interfaceName = NULL,
unsigned short thePort = 0);
void Append(Item* item);
void Remove(Item* item);
Item* head;
Item* tail;
}; // end class DrecGroupList
class MgenController
{
public:
virtual ~MgenController();
virtual void OnMsgReceive(const MgenMsg& msg,
const ProtoAddress& src,
const struct timeval& currentTime) = 0;
protected:
MgenController();
}; // end class MgenController
class Mgen
{
public:
enum {SCRIPT_LINE_MAX = 512}; // maximum script line length
enum LogEvent
{
INVALID_EVENT = 0,
RECV_EVENT,
RERR_EVENT,
SEND_EVENT,
LISTEN_EVENT,
IGNORE_EVENT,
JOIN_EVENT,
LEAVE_EVENT,
START_EVENT,
STOP_EVENT
};
Mgen(ProtoTimerMgr& timerMgr,
ProtoSocket::Notifier& socketNotifier);
~Mgen();
// MGEN "global command" set
enum Command
{
INVALID_COMMAND,
EVENT,
START, // specify absolute start time
INPUT, // input and parse an MGEN script
OUTPUT, // open output (log) file
LOG, // open log file for appending
NOLOG, // no output
TXLOG, // turn transmit logging on
DLOG, // set debug log file
SAVE, // save pending flow state/offset info on exit.
DEBUG, // specify debug level
OFFSET, // time offset into script
TXBUFFER, // Tx socket buffer size
RXBUFFER, // Rx socket buffer size
LABEL, // IPv6 flow label
TOS, // IPV4 Type-Of-Service
TTL, // IPV4 Time-To-Live
INTERFACE, //Multicast Interface
BINARY, // turn binary logfile mode on
FLUSH, // flush log after _each_ event
CHECKSUM, // turn on _both_ tx and rx checksum options
TXCHECKSUM,// include checksums in transmitted MGEN messages
RXCHECKSUM // force checksum validation at receiver _always_
};
static Command GetCommandFromString(const char* string);
enum CmdType {CMD_INVALID, CMD_ARG, CMD_NOARG};
static CmdType GetCmdType(const char* cmd);
bool OnCommand(Mgen::Command cmd, const char* arg, bool override = false);
void SetController(MgenController* theController)
{controller = theController;}
MgenSink* GetSink() {return sink;}
void SetSink(MgenSink* theSink)
{
sink = theSink;
flow_list.SetSink(theSink);
}
void HandleMgenMessage(char* buffer,
unsigned int len,
const ProtoAddress& srcAddr);
bool OpenLog(const char* path, bool append, bool binary);
void CloseLog();
void SetLogFile(FILE* filePtr);
typedef int (*LogFunction)(FILE*, const char*, ...);
#ifndef _WIN32_WCE
static LogFunction Log;
#else
static LogFunction Log;
// Alternative logging function for WinCE debug window when logging to stdout/stderr
static int Mgen::LogToDebug(FILE* filePtr, const char* format, ...);
#endif // if/else _WIN32_WCE
bool ParseScript(const char* path);
bool ParseEvent(const char* lineBuffer, unsigned int lineCount);
double GetCurrentOffset() const;
void InsertDrecEvent(DrecEvent* event);
void SetDefaultSocketType(ProtoAddress::Type addrType)
{addr_type = addrType;}
ProtoAddress::Type GetDefaultSocketType() {return addr_type;}
void SetPositionCallback(MgenPositionFunc* callback,
const void* clientData)
{
get_position = callback;
get_position_data = clientData;
}
void SetHostAddress(const ProtoAddress hostAddr)
{
host_addr = hostAddr;
flow_list.SetHostAddress(hostAddr);
}
void ClearHostAddress()
{
host_addr.Invalidate();
flow_list.ClearHostAddress();
}
#ifdef HAVE_GPS
void SetPayloadHandle(GPSHandle payloadHandle)
{
payload_handle = payloadHandle;
}
#endif // HAVE_GPS
bool Start();
void Stop();
bool DelayedStart() {return start_timer.IsActive();}
void GetStartTime(char* buffer)
{
sprintf(buffer, "%02d:%02d:%02.0f%s",
start_hour, start_min, start_sec,
(start_gmt ? "GMT" : ""));
}
bool ConvertBinaryLog(const char* path);
// A little utility class for reading script files line by line
class FastReader
{
public:
enum Result {OK, ERROR_, DONE}; // trailing '_' for WIN32
FastReader();
FastReader::Result Read(FILE* filePtr, char* buffer, unsigned int* len);
FastReader::Result Readline(FILE* filePtr, char* buffer,
unsigned int* len);
FastReader::Result ReadlineContinue(FILE* filePtr, char* buffer,
unsigned int* len,
unsigned int* lineCount = NULL);
private:
enum {BUFSIZE = 1024};
char savebuf[BUFSIZE];
char* saveptr;
unsigned int savecount;
}; // end class FastReader
private:
// MGEN script command types ("global" commands)
// for mapping protocol types from script line fields
static const StringMapper COMMAND_LIST[];
bool OnStartTimeout(ProtoTimer& theTimer);
bool OnDrecEventTimeout(ProtoTimer& theTimer);
void ProcessDrecEvent(const DrecEvent& event);
void LogDrecEvent(LogEvent eventType,
const DrecEvent& event,
unsigned short portNumber);
void OnSocketEvent(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
// Common state
MgenController* controller; // optional MgenController
ProtoTimerMgr& timer_mgr;
MgenSocketList socket_list;
MgenSink* sink;
FILE* log_file;
bool log_binary;
bool log_flush;
bool log_file_lock;
bool log_tx;
bool log_open;
bool log_empty;
char* save_path;
bool save_path_lock;
bool started;
ProtoTimer start_timer;
unsigned int start_hour; // absolute start time
unsigned int start_min;
double start_sec;
bool start_gmt;
bool start_time_lock;
double offset;
bool offset_lock;
bool offset_pending;
// (TBD) move these two to MgenSocketList ???
UINT32 default_flow_label;
bool default_label_lock;
ProtoAddress host_addr;
bool checksum_enable;
MgenFlowList flow_list;
// Drec state
ProtoTimer drec_event_timer;
MgenEventList drec_event_list;
DrecEvent* next_drec_event; // for iterating drec_event_list
DrecGroupList drec_group_list;
ProtoAddress::Type addr_type;
bool checksum_force; // force checksum validation at rcvr
MgenPositionFunc* get_position;
const void* get_position_data;
#ifdef HAVE_GPS
GPSHandle payload_handle;
#endif // HAVE_GPS
}; // end class Mgen
#endif // _MGEN
syntax highlighted by Code2HTML, v. 0.9.1