#include "mgenEvent.h"
#include "mgen.h" // for Mgen::SCRIPT_LINE_MAX
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h> // for toupper()
MgenBaseEvent::MgenBaseEvent(Category theCategory)
: category(theCategory), event_time(-1.0),
prev(NULL), next(NULL)
{
}
MgenEvent::MgenEvent()
: MgenBaseEvent(MGEN), flow_id(0), event_type(INVALID_TYPE), src_port(0),
protocol(INVALID_PROTOCOL), tos(0), ttl(255), option_mask(0)
{
interface_name[0] = '\0';
flow_label = 0;
}
const StringMapper MgenEvent::TYPE_LIST[] =
{
{"ON", ON},
{"MOD", MOD},
{"OFF", OFF},
{"XXXX", INVALID_TYPE}
};
MgenEvent::Type MgenEvent::GetTypeFromString(const char* string)
{
// Make comparison case-insensitive
char upperString[16];
unsigned int len = strlen(string);
len = len < 15 ? len : 15;
unsigned int i;
for (i =0 ; i < len; i++)
upperString[i] = toupper(string[i]);
upperString[i] = '\0';
const StringMapper* m = TYPE_LIST;
unsigned matchCount = 0;
Type eventType = INVALID_TYPE;
while (INVALID_TYPE != (*m).key)
{
if (!strncmp(upperString, (*m).string, len))
{
matchCount++;
eventType = ((Type)((*m).key));
}
m++;
}
if (matchCount > 1)
{
DMSG(0, "MgenEvent::GetTypeFromString() Error: ambiguous event type\n");
return INVALID_TYPE;
}
else
{
return eventType;
}
} // end MgenEvent::GetTypeFromString()
const StringMapper MgenBaseEvent::PROTOCOL_LIST[] =
{
{"UDP", UDP},
{"TCP", TCP},
{"SINK", SINK},
{"XXX", INVALID_PROTOCOL}
};
MgenBaseEvent::Protocol MgenBaseEvent::GetProtocolFromString(const char* string)
{
// Make comparison case-insensitive
char upperString[16];
unsigned int len = strlen(string);
len = len < 15 ? len : 15;
unsigned int i;
for (i =0 ; i < len; i++)
upperString[i] = toupper(string[i]);
upperString[i] = '\0';
unsigned int matchCount = 0;
Protocol protocolType = INVALID_PROTOCOL;
const StringMapper* m = PROTOCOL_LIST;
while (INVALID_PROTOCOL != (*m).key)
{
if (!strncmp(upperString, (*m).string, len))
{
protocolType = ((Protocol)((*m).key));
matchCount++;
}
m++;
}
if (matchCount > 1)
{
DMSG(0, "Event::GetProtocolFromString() Error: ambiguous protocol\n");
return INVALID_PROTOCOL;
}
else
{
return protocolType;
}
} // end MgenBaseEvent::GetProtocolFromString()
const char* MgenBaseEvent::GetStringFromProtocol(MgenBaseEvent::Protocol protocol)
{
const StringMapper* m = PROTOCOL_LIST;
while (INVALID_PROTOCOL != (*m).key)
{
if (protocol == (*m).key)
return (*m).string;
}
return "UNKNOWN";
} // end MgenBaseEvent::GetStringFromProtocol()
const StringMapper MgenEvent::OPTION_LIST[] =
{
{"PROTOCOL", PROTOCOL},
{"DST", DST},
{"SRC", SRC},
{"PATTERN", PATTERN},
{"TOS", TOS},
{"RSVP", RSVP},
{"INTERFACE", INTERFACE},
{"TTL", TTL},
{"SEQUENCE", SEQUENCE},
{"LABEL",LABEL},
{"TXBUFFER",TXBUFFER},
{"XXXX", INVALID_OPTION}
};
const unsigned int MgenEvent::ON_REQUIRED_OPTIONS =
(MgenEvent::PROTOCOL | MgenEvent::DST | MgenEvent::PATTERN);
MgenEvent::Option MgenEvent::GetOptionFromString(const char* string)
{
// Make comparison case-insensitive
char upperString[16];
unsigned int len = strlen(string);
len = len < 15 ? len : 15;
unsigned int i;
for (i =0 ; i < len; i++)
upperString[i] = toupper(string[i]);
upperString[i] = '\0';
unsigned int matchCount = 0;
Option optionType = INVALID_OPTION;
const StringMapper* m = OPTION_LIST;
while (INVALID_OPTION != (*m).key)
{
if (!strncmp(upperString, (*m).string, len))
{
optionType = ((Option)((*m).key));
matchCount++;
}
m++;
}
if (matchCount > 1)
{
DMSG(0, "MgenEvent::GetOptionFromString() Error: ambiguous option\n");
return INVALID_OPTION;
}
else
{
return optionType;
}
} // end MgenEvent::GetOptionFromString()
const char* MgenEvent::GetStringFromOption(Option option)
{
const StringMapper* m = OPTION_LIST;
while (INVALID_OPTION != m->key)
{
if (option == (Option)(m->key))
return m->string;
else
m++;
}
return "INVALID";
} // end MgenEvent::GetStringFromOption()
bool MgenEvent::InitFromString(const char* string)
{
// format: <time> <flowId> <type> [options ...]
const char* ptr = string;
// Skip any leading white space
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// 1) Get the first string (eventTime or eventType)
char fieldBuffer[Mgen::SCRIPT_LINE_MAX];
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: empty string\n");
return false;
}
// Check for eventTime
if (1 == sscanf(fieldBuffer, "%lf", &event_time))
{
// Read next field (eventType), skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <eventType>\n");
return false;
}
}
else
{
event_time = -1.0; // an "immediate" event
}
// 2) Determine event type
event_type = GetTypeFromString(fieldBuffer);
if (INVALID_TYPE == event_type)
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <eventType>: \"%s\"\n",
fieldBuffer);
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// 3) parse flow id
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <flowId>\n");
return false;
}
if (1 != sscanf(fieldBuffer, "%lu", &flow_id))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <flowId>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// Finally, iterate through any options
option_mask = 0;
while ('\0' != *ptr)
{
Option option = INVALID_OPTION;
// Read option label
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: event option parse error\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// 1) Is it an implicitly labeled "PROTOCOL" type?
if (INVALID_PROTOCOL != GetProtocolFromString(fieldBuffer))
option = PROTOCOL;
// 2) Is it an implicitly labeled "PATTERN" spec?
else if (MgenPattern::INVALID_TYPE != MgenPattern::GetTypeFromString(fieldBuffer))
option = PATTERN;
// 3) Or is it one of our explicitly labeled options?
else
option = GetOptionFromString(fieldBuffer);
switch (option)
{
case PROTOCOL: // protocol type (UDP or TCP)
protocol = GetProtocolFromString(fieldBuffer);
if (INVALID_PROTOCOL == protocol)
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid protocol type\n");
return false;
}
break;
case DST: // destination address/port
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <dstAddr>\n");
return false;
}
char* portPtr= strchr(fieldBuffer, '/');
if (portPtr)
{
*portPtr++ = '\0';
}
else
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <dstPort>\n");
return false;
}
if (!dst_addr.ResolveFromString(fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <dstAddr>\n");
return false;
}
int dstPort;
if (1 != sscanf(portPtr, "%d", &dstPort))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <dstPort>\n");
return false;
}
if ((dstPort < 1) || (dstPort > 65535))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <dstPort>\n");
return false;
}
dst_addr.SetPort(dstPort);
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer) + strlen(portPtr) + 1;
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case SRC: // source port
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <srcPort>\n");
return false;
}
int srcPort;
if (1 != sscanf(fieldBuffer, "%d", &srcPort))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <srcPort>\n");
return false;
}
if ((srcPort < 1) || (srcPort > 65535))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <dstPort>\n");
return false;
}
src_port = srcPort;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
case PATTERN:
{
MgenPattern::Type patternType
= MgenPattern::GetTypeFromString(fieldBuffer);
// Point to beginning of pattern parameters
const char* pptr = ptr;
// Find end of pattern parameter set
unsigned int nested = 1;
while (nested)
{
ptr++;
if ('[' == *ptr)
nested++;
else if (']' == *ptr)
nested--;
if ('\0' == *ptr)
{
DMSG(0, "MgenEvent::InitFromString() Error: non-terminated <patternParams>\n");
return false;
}
}
if ((*pptr != '[') || !ptr)
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <patternParams>\n");
return false;
}
strncpy(fieldBuffer, pptr+1, ptr - pptr - 1);
fieldBuffer[ptr - pptr - 1] = '\0';
if (!pattern.InitFromString(patternType, fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <patternParams>\n");
return false;
}
// Set ptr to next field, skipping any white space
ptr++;
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case TOS: // tos spec
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <tosValue>\n");
return false;
}
int tosValue;
if (1 != sscanf(fieldBuffer, "%i", &tosValue))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <tosValue>\n");
return false;
}
if ((tosValue < 0) || (tosValue > 255))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <tosValue>\n");
return false;
}
tos = tosValue;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case LABEL: // IPv6 traffic class/ flow label
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <flowLabel>\n");
return false;
}
int flowLabel;
if (1 != sscanf(fieldBuffer, "%i", &flowLabel))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <flowLabel>\n");
return false;
}
// (TBD) check validity
flow_label = flowLabel;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case TXBUFFER:
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <socket Tx buffer size>\n");
return false;
}
unsigned int txBuffer;
if (1 != sscanf(fieldBuffer, "%u", &txBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <socket Tx buffer size>\n");
return false;
}
// (TBD) check validity
tx_buffer_size = txBuffer;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
case RSVP:
// (TBD)
DMSG(0, "MgenEvent::InitFromString() Error: RSVP option not yet supported\n");
return false;
break;
case INTERFACE: // multicast interface name
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <interfaceName>\n");
return false;
}
strncpy(interface_name, fieldBuffer, 15);
interface_name[15] = '\0';
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
case TTL: // multicast ttl value
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: finding <ttlValue>\n");
return false;
}
unsigned int ttlValue;
if (1 != sscanf(fieldBuffer, "%u", &ttlValue))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <ttlValue>\n");
return false;
}
if (ttlValue > 255)
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <ttlValue>\n");
return false;
}
ttl = ttlValue;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case SEQUENCE: // sequence number initialization
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: finding <seqNum>\n");
return false;
}
unsigned long seqTemp;
if (1 != sscanf(fieldBuffer, "%lu", &seqTemp))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <seqNum>\n");
return false;
}
sequence = seqTemp;
// Set ptr to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
}
case INVALID_OPTION:
DMSG(0, "MgenEvent::InitFromString() Error: invalid event option: \"%s\"\n",
fieldBuffer);
return false;
} // end switch (option)
option_mask |= option;
} // end while ('\0' != *ptr)
// Validate option_mask depending upon event_type
switch (event_type)
{
case ON:
{
unsigned int mask = option_mask & ON_REQUIRED_OPTIONS;
if (mask != ON_REQUIRED_OPTIONS)
{
DMSG(0, "MgenEvent::InitFromString() Error: incomplete \"ON\" event:\n"
" (missing");
// Incomplete "ON" event. What are we missing?
// mask = ON_REQUIRED_OPTIONS - option_mask
mask = ON_REQUIRED_OPTIONS & ~option_mask;
unsigned int flag = 0x01;
while (mask)
{
if (0 != (flag & mask))
{
const char* optionString = GetStringFromOption((Option)flag);
mask &= ~flag;
DMSG(0, ": %s ", optionString);
}
flag <<= 1;
}
DMSG(0, ")\n");
return false;
}
// TBD check against ON_VALID_OPTIONS
break;
}
case MOD:
// TBD check against MOD_VALID_OPTIONS
break;
case OFF:
break;
case INVALID_TYPE:
ASSERT(0); // this should never occur
return false;
}
return true;
} // end MgenEvent::InitFromString()
DrecEvent::DrecEvent()
: MgenBaseEvent(DREC), event_type(INVALID_TYPE), protocol(INVALID_PROTOCOL),
port_count(0), port_list(NULL), rx_buffer_size(0)
{
interface_name[0] = '\0';
}
const StringMapper DrecEvent::TYPE_LIST[] =
{
{"JOIN", JOIN},
{"LEAVE", LEAVE},
{"LISTEN", LISTEN},
{"IGNORE", IGNORE_},
{"XXXX", INVALID_TYPE}
};
DrecEvent::Type DrecEvent::GetTypeFromString(const char* string)
{
// Make comparison case-insensitive
char upperString[16];
unsigned int len = strlen(string);
len = len < 15 ? len : 15;
unsigned int i;
for (i =0 ; i < len; i++)
upperString[i] = toupper(string[i]);
upperString[i] = '\0';
unsigned int matchCount = 0;
Type eventType = INVALID_TYPE;
const StringMapper* m = TYPE_LIST;
while (INVALID_TYPE != (*m).key)
{
if (!strncmp(upperString, (*m).string, len))
{
eventType = ((Type)((*m).key));
matchCount++;
}
m++;
}
if (matchCount > 1)
{
DMSG(0, "DrecEvent::GetTypeFromString() Error: ambiguous event type\n");
return INVALID_TYPE;
}
else
{
return eventType;
}
} // end DrecEvent::GetTypeFromString()
const StringMapper DrecEvent::OPTION_LIST[] =
{
{"INTERFACE", INTERFACE},
{"PORT", PORT},
{"RXBUFFER", RXBUFFER},
{"XXXX", INVALID_OPTION}
};
DrecEvent::Option DrecEvent::GetOptionFromString(const char* string)
{
// Make comparison case-insensitive
char upperString[16];
unsigned int len = strlen(string);
len = len < 15 ? len : 15;
unsigned int i;
for (i =0 ; i < len; i++)
upperString[i] = toupper(string[i]);
upperString[i] = '\0';
unsigned int matchCount = 0;
Option optionType = INVALID_OPTION;
const StringMapper* m = OPTION_LIST;
while (INVALID_OPTION != (*m).key)
{
if (!strncmp(upperString, (*m).string, len))
{
optionType = ((Option)((*m).key));
matchCount++;
}
m++;
}
if (matchCount > 1)
{
DMSG(0, "DrecEvent::GetOptionFromString() Error: ambiguous option\n");
return INVALID_OPTION;
}
else
{
return optionType;
}
} // end DrecEvent::GetOptionFromString()
bool DrecEvent::InitFromString(const char* string)
{
// script lines are of format "<eventTime> <eventType> [params ...]"
const char* ptr = string;
// Skip any leading white space
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// First, read first string
char fieldBuffer[Mgen::SCRIPT_LINE_MAX];
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: empty string\n");
return false;
}
// Check for eventTime
if (1 == sscanf(fieldBuffer, "%lf", &event_time))
{
// Read next field (eventType), skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <eventType>\n");
return false;
}
}
else
{
event_time = -1.0; // an "immediate" event
}
event_type = GetTypeFromString(fieldBuffer);
if (INVALID_TYPE == event_type)
{
DMSG(0, "DrecEvent::InitFromString() Error: invalid <eventType>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
switch(event_type)
{
case JOIN: // "{JOIN|LEAVE} <groupAddr> [<interfaceName>][PORT <port>]"
case LEAVE:
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <groupAddress>\n");
return false;
}
if (!group_addr.ResolveFromString(fieldBuffer) ||
!group_addr.IsMulticast())
{
DMSG(0, "DrecEvent::InitFromString() Error: invalid <groupAddress>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// Look for options [INTERFACE <interfaceName>] or [PORT <port>]
while ('\0' != *ptr)
{
// Read option label
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error invalid JOIN/LEAVE option.\n");
return false;
}
Option option = GetOptionFromString(fieldBuffer);
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
switch (option)
{
case INTERFACE:
// Read <interfaceName>
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <interfaceName>\n");
return false;
}
strncpy(interface_name, fieldBuffer, 15);
interface_name[15] = '\0'; // 16 char max
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
case PORT:
// Read <portNumber>
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <portNumber>\n");
return false;
}
if (1 != sscanf(ptr, "%hu", &port_count))
{
DMSG(0, "DrecEvent::InitFromString() Error: invalid <portNumber>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
break;
case RXBUFFER:
break; //RXBUFFER is not a leave option, however this case gets rid of a compiler warning.
case INVALID_OPTION:
DMSG(0, "DrecEvent::InitFromString() Error: invalid option: %s\n",
fieldBuffer);
return false;
break;
}
} // end while ('\0' != *ptr)
break;
case LISTEN: // "{LISTEN|IGNORE} <protocol> <portList>"
case IGNORE_:
// Get <protocol>
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <protocolType>\n");
return false;
}
protocol = GetProtocolFromString(fieldBuffer);
if (INVALID_PROTOCOL == protocol)
{
DMSG(0, "DrecEvent::InitFromString() Error: invalid <protocolType>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
// Get <portList>
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "DrecEvent::InitFromString() Error: missing <portList>\n");
return false;
}
// Parse port list and build array
if (!(port_list = CreatePortArray(fieldBuffer, &port_count)))
{
DMSG(0, "DrecEvent::InitFromString() Error: invalid <portList>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
//Is rx socket buffer size specified?
if (1 != sscanf(ptr, "%s", fieldBuffer))
break; // No Rx socket buffer size specified.
if (!strcmp("RXBUFFER",fieldBuffer))
{
if (1 != sscanf(ptr, "%s", fieldBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: missing <socket Rx buffer size>\n");
return false;
}
// Point to next field, skipping any white space
ptr += strlen(fieldBuffer);
while ((' ' == *ptr) || ('\t' == *ptr)) ptr++;
unsigned int rxBuffer;
if (1 != sscanf(ptr, "%u", &rxBuffer))
{
DMSG(0, "MgenEvent::InitFromString() Error: invalid <socket rx buffer size>\n");
return false;
}
// (TBD) check validity
rx_buffer_size = rxBuffer;
}
break;
case INVALID_TYPE:
ASSERT(0); // this should never occur
return false;
} // end switch(event_type)
return true;
} // end DrecEvent::InitFromString()
unsigned short* DrecEvent::CreatePortArray(const char* portList,
unsigned short* portCount)
{
unsigned short count = 0;
unsigned int arraySize = 0;
unsigned short* array = NULL;
const char* ptr = portList;
while (*ptr != '\0')
{
// 1) Find and copy the next field
const char* commaPtr = strchr(ptr, ',');
unsigned long len;
if (commaPtr)
{
len = commaPtr - ptr;
commaPtr++;
}
else
{
len = strlen(ptr);
commaPtr = ptr + len;
}
char fieldBuffer[32];
len = len < 31 ? len : 31;
strncpy(fieldBuffer, ptr, len);
fieldBuffer[len] = '\0';
ptr = commaPtr;
// 2) Is this a value or a range?
char* dashPtr = strchr(fieldBuffer, '-');
if (dashPtr) *dashPtr++ = '\0';
unsigned short lowValue;
if (1 != sscanf(fieldBuffer, "%hu", &lowValue))
{
DMSG(0, "DrecEvent::CreatePortArray() Error: invalid <portList>\n");
*portCount = 0;
return (unsigned short*)NULL;
}
unsigned short highValue;
if (dashPtr)
{
if (1 != sscanf(dashPtr, "%hu", &highValue))
{
DMSG(0, "DrecEvent::CreatePortArray() Error: invalid <portList> upper range bound\n");
*portCount = 0;
return (unsigned short*)NULL;
}
}
else
{
highValue = lowValue;
}
if (highValue < lowValue)
{
DMSG(0, "DrecEvent::CreatePortArray() Error: invalid <portList> range\n");
*portCount = 0;
return (unsigned short*)NULL;
}
unsigned short range = highValue - lowValue + 1;
if (range > (arraySize - count))
{
arraySize += range;
unsigned short* newArray = new unsigned short[arraySize];
if (!newArray)
{
delete array;
DMSG(0, "DrecEvent::CreatePortArray() Error: memory allocation error: %s\n",
GetErrorString());
*portCount = 0;
return (unsigned short*)NULL;
}
memcpy(newArray, array, count*sizeof(unsigned short));
delete array;
array = newArray;
}
for (unsigned short p = lowValue; p <= highValue; p++)
array[count++] = p;
} // end while (*ptr |= '\0')
*portCount = count;
return array;
} // end DrecEvent::CreatePortArray()
MgenEventList::MgenEventList()
: head(NULL), tail(NULL)
{
}
MgenEventList::~MgenEventList()
{
Destroy();
}
void MgenEventList::Destroy()
{
MgenBaseEvent* next = head;
while (next)
{
MgenBaseEvent* current = next;
next = next->next;
delete current;
}
head = tail = NULL;
} // end MgenEventList::Destroy()
// time-ordered insertion of event
void MgenEventList::Insert(MgenBaseEvent* theEvent)
{
MgenBaseEvent* next = head;
double eventTime = theEvent->GetTime();
while(next)
{
if (eventTime < next->GetTime())
{
theEvent->next = next;
if ((theEvent->prev = next->prev))
theEvent->prev->next = theEvent;
else
head = theEvent;
next->prev = theEvent;
return;
}
else
{
next = next->next;
}
}
// Fell to end of list
if ((theEvent->prev = tail))
{
tail->next = theEvent;
}
else
{
head = theEvent;
theEvent->prev = NULL;
}
tail = theEvent;
theEvent->next = NULL;
} // end MgenEventList::Insert()
// This places "theEvent" _before_ "nextEvent" in the list.
// (If "nextEvent" is NULL, "theEvent" goes to the end of the list)
void MgenEventList::Precede(MgenBaseEvent* nextEvent,
MgenBaseEvent* theEvent)
{
if ((theEvent->next = nextEvent))
{
if ((theEvent->prev = nextEvent->prev))
theEvent->prev->next = theEvent;
else
head = theEvent;
nextEvent->prev = theEvent;
}
else
{
if ((theEvent->prev = tail))
tail->next = theEvent;
else
head = theEvent;
tail = theEvent;
}
} // end MgenEventList::Precede()
void MgenEventList::Remove(MgenBaseEvent* theEvent)
{
if (theEvent->prev)
theEvent->prev->next = theEvent->next;
else
head = theEvent->next;
if (theEvent->next)
theEvent->next->prev = theEvent->prev;
else
tail = theEvent->prev;
} // end MgenEventList::Remove()
syntax highlighted by Code2HTML, v. 0.9.1