Commit 8d184eed authored by Jonathon Duerig's avatar Jonathon Duerig

Added sensors, commands, peer communication, etc.

parent 34587863
......@@ -49,6 +49,8 @@ class ConnectionModelCommand : public Command
protected:
virtual void runConnect(Connection * conn,
std::multimap<Time, Connection *> &);
int type;
int value;
};
class SensorCommand : public Command
......
......@@ -20,9 +20,20 @@ public:
{
return currentCommand.get();
}
virtual void nextCommand(fd_set & readable)=0;
virtual void nextCommand(fd_set * readable)=0;
virtual int getMonitorSocket(void)=0;
virtual void disconnect(void)=0;
protected:
std::auto_ptr<Command> currentCommand;
};
class NullCommandInput : public CommandInput
{
public:
virtual ~NullCommandInput() {}
virtual void nextCommand(fd_set *) {}
virtual int getMonitorSocket(void) { return -1; }
virtual void disconnect(void) {}
};
#endif
......@@ -10,14 +10,34 @@
class CommandOutput
{
public:
enum
{
SENDING_MESSAGE = 0,
DISCARDING_MESSAGE
}
public:
virtual ~CommandOutput() {}
void eventMessage(std::string const & message, Order const & key)
void eventMessage(std::string const & message, Order const & key,
char direction)
{
if (message.size() <= 0xffff && message.size() > 0)
{
writeHeader(EVENT_TO_MONITOR, message.size(), key);
writeMessage(message.c_str(), message.size());
Header prefix;
prefix.type = EVENT_TO_MONITOR;
prefix.size = message.size();
prefix.key = key;
char headerBuffer[Header::headerSize];
saveHeader(headerBuffer, prefix);
int result = startMessage(Header::headerSize + sizeof(direction)
+ message.size());
if (result == SENDING_MESSAGE)
{
writeMessage(headerBuffer, Header::headerSize);
writeMessage(&direction, sizeof(direction));
writeMessage(message.c_str(), message.size());
finishMessage();
}
}
else
{
......@@ -25,45 +45,20 @@ public:
"Size: %ud", message.size());
}
}
private:
void writeHeader(int type, unsigned short size, Order const & key)
{
int bufferSize = sizeof(unsigned char)*2 + sizeof(unsigned short)*3
+ sizeof(unsigned long);
char buffer[bufferSize];
char * pos = buffer;
pos = saveChar(pos, type);
pos = saveShort(pos, size);
pos = saveChar(pos, key.transport);
pos = saveInt(pos, key.ip);
pos = saveShort(pos, key.localPort);
pos = saveShort(pos, key.remotePort);
writeMessage(buffer, bufferSize);
}
char * saveChar(char * buffer, unsigned char value)
{
memcpy(buffer, &value, sizeof(value));
return buffer + sizeof(value);
}
char * saveShort(char * buffer, unsigned short value)
{
unsigned short ordered = htons(value);
memcpy(buffer, &ordered, sizeof(ordered));
return buffer + sizeof(ordered);
}
char * saveInt(char * buffer, unsigned short value)
{
unsigned int ordered = htonl(value);
memcpy(buffer, &ordered, sizeof(ordered));
return buffer + sizeof(ordered);
}
protected:
virtual int startMessage(int size)=0;
virtual void endMessage(void)=0;
virtual void writeMessage(char const * message, int count)=0;
};
class NullCommandOutput : public CommandOutput
{
public:
virtual ~NullCommandOutput() {}
protected:
virtual int startMessage(int size) { return DISCARDING_MESSAGE; }
virtual void endMessage(void) {}
virtual void writeMessage(char const *, int) {}
};
#endif
......@@ -52,11 +52,33 @@ void Connection::setTraffic(std::auto_ptr<TrafficModel> newTraffic)
traffic = newTraffic;
}
void Connection::addConnectionModelParam(ConnectionModelCommand const & param)
{
if (peer.get() != NULL)
{
peer->addParam(param);
}
else
{
logWrite(ERROR, "Connection model has not been initialized before an "
"addConnectionModelParam call");
}
}
void Connection::connect(void)
{
if (peer.get() != NULL)
{
peer->connect();
planet.transport = TCP_CONNECTION;
planet.ip = elab.ip;
planet.remotePort = global::peerServerPort;
// planet is modified by ConnectionModel::connect()
peer->connect(planet);
isConnected = peer->isConnected();
if (isConnected)
{
global::planetMap.insert(make_pair(planet, this));
}
}
else
{
......@@ -89,25 +111,31 @@ void Connection::addSensor(SensorCommand const & newSensor)
measurements.addSensor(newSensor);
}
void Connection::captureSend(Time & packetTime, struct tcp_info * kernel,
struct tcphdr * tcp)
void Connection::captureSend(PacketInfo * packet)
{
Sensor * head = measurements.getHead();
if (head != NULL && isConnected)
{
head->captureSend(packetTime, kernel, tcp, elab, bufferFull);
packet->elab = elab;
packet->bufferFull = bufferFull;
head->captureSend(packet);
}
}
void Connection::captureAck(Time & packetTime, struct tcp_info * kernel,
struct tcphdr * tcp)
void Connection::captureAck(PacketInfo * packet)
{
Sensor * head = measurements.getHead();
if (head != NULL && isConnected)
{
head->captureAck(packetTime, kernel, tcp, elab, bufferFull);
packet->elab = elab;
packet->bufferFull = bufferFull;
head->captureAck(packet);
}
}
ConnectionModel const * Connection::getConnectionModel(void)
{
return peer.get();
}
Time Connection::writeToConnection(Time const & previousTime)
{
......
......@@ -38,11 +38,11 @@ public:
// Adds a particular kind of sensor when requested by the monitor.
void addSensor(SensorCommand const & newSensor);
// Notifies the sensors of a data packet which was sent.
void captureSend(Time & packetTime, struct tcp_info * kernel,
struct tcphdr * tcp);
void captureSend(PacketInfo * packet);
// Notifies the sensors of an acknowledged packet which was received.
void captureAck(Time & packetTime, struct tcp_info * kernel,
struct tcphdr * tcp);
void captureAck(PacketInfo * packet);
// Allows the connection model to be viewed.
ConnectionModel const * getConnectionModel(void);
// Notifies the traffic model that a timer has expired on the
// scheduler.
Time writeToConnection(Time const & previousTime);
......
......@@ -3,12 +3,45 @@
#ifndef CONNECTION_MODEL_H_PELAB_2
#define CONNECTION_MODEL_H_PELAB_2
class ConnectionModelCommand;
class ConnectionModel
{
public:
virtual ~ConnectionModel() {}
virtual std::auto_ptr<ConnectionModel> clone(void)=0;
virtual void connect(void)=0;
virtual void addParam(ConnectionModelCommand const & param)=0;
// Returns the number of bytes actually written or -1 if there was
// an error. Errno is not preserved.
virtual int writeMessage(int size, WriteResult & result)=0;
virtual bool isConnected(void)=0;
};
class ConnectionModelNull : public ConnectionModel
{
public:
virtual ~ConnectionModelNull() {}
virtual std::auto_ptr<ConnectionModel> clone(void)
{
return std::auto_ptr<ConnectionModel>(new ConnectionModelNull());
}
virtual void connect(void) {}
virtual void addParam(ConnectionModelCommand const &) {}
static void init(void) {}
static void addNewPeer(fd_set *) {}
static void readFromPeers(fd_set *) {}
static void packetCapture(fd_set *) {}
virtual void writeMessage(int, WriteResult & result)
{
result.isConnected = false;
result.bufferFull = false;
}
virtual bool isConnected(void)
{
return false;
}
};
#endif
This diff is collapsed.
......@@ -8,24 +8,40 @@
enum ConnectionState
{
DISCONNECTED,
SOCKETED,
CONNECTED
DISCONNECTED,
CONNECTED
};
class KernelTcp : public ConnectionModel
{
ConnectionState state;
int peersock;
int sendBufferSize;
int receiveBufferSize;
int maxSegmentSize;
bool useNagles;
};
public:
KernelTcp();
virtual ~KernelTcp();
virtual std::auto_ptr<ConnectionModel> clone(void);
virtual void connect(Order & planet);
virtual void addParam(ConnectionModelCommand const & param);
virtual int writeMessage(int size, WriteResult & result);
virtual bool isConnected(void);
int getSock(void) const;
private:
ConnectionState state;
int peersock;
int sendBufferSize;
int receiveBufferSize;
int maxSegmentSize;
int useNagles;
public:
static pcap_t * pcapDescriptor;
static int pcapfd;
static void init(void);
static void addNewPeer(fd_set * readable);
static void readFromPeers(fd_set * readable);
static void packetCapture(fd_set * readable);
void kernelTcp_init(void);
void kernelTcp_addNewPeer(fd_set * readable);
void kernelTcp_readFromPeers(fd_set * readable);
void kernelTcp_packetCapture(fd_set * readable);
private:
static bool changeSocket(int sockfd, int level, int optname, int value,
std::string optstring)
};
#endif
......@@ -7,66 +7,63 @@
#ifndef SENSOR_H_STUB_2
#define SENSOR_H_STUB_2
#include "log.h"
class Sensor
{
public:
virtual ~Sensor() {}
Sensor * getTail(void)
{
if (next.get() == NULL)
{
return this;
}
else
{
return next->getTail();
}
if (next.get() == NULL)
{
return this;
}
else
{
return next->getTail();
}
}
void addNode(std::auto_ptr<Sensor> node)
{
next=node;
}
void captureSend(Time const & packetTime, struct tcp_info const * kernel,
struct tcphdr const * tcp, Order const & elab,
bool bufferFull)
{
localSend(packetTime, kernel, tcp, elab, bufferFull);
if (next.get() != NULL)
{
next->captureSend(packetTime, kernel, tcp, elab, bufferFull);
}
next = node;
}
void captureAck(Time const & packetTime, struct tcp_info * kernel,
struct tcphdr * tcp, Order const & elab,
bool bufferFull)
void captureSend(PacketInfo * packet)
{
localAck(packetTime, kernel, tcp, elab, bufferFull);
if (next.get() != NULL)
{
next->captureAck(packetTime, kernel, tcp, elab, bufferFull);
}
localSend(packet);
if (next.get() != NULL)
{
next->captureSend(packet);
}
}
std::auto_ptr<Sensor> clone(void) const
void captureAck(PacketInfo * packet)
{
std::auto_ptr<Sensor> result(localClone());
if (next.get() != NULL)
{
result->next = next->clone();
}
return result;
localAck(packet);
if (next.get() != NULL)
{
next->captureAck(packet);
}
}
private:
std::auto_ptr<Sensor> next;
protected:
virtual void localSend(Time const & packetTime,
struct tcp_info const * kernel,
struct tcphdr const * tcp, Order const & elab,
bool bufferFull)=0;
virtual void localAck(Time const & packetTime,
struct tcp_info const * kernel,
struct tcphdr const * tcp, Order const & elab,
bool bufferFull)=0;
virtual std::auto_ptr<Sensor> localClone(void) const=0;
virtual void localSend(PacketInfo * packet)=0;
virtual void localAck(PacketInfo * packet)=0;
};
class NullSensor : public Sensor
{
public:
virtual ~NullSensor() {}
protected:
virtual void localSend(PacketInfo *)
{
logWrite(SENSOR, "Send received");
}
virtual void localAck(PacketInfo *)
{
logWrite(SENSOR, "Ack received");
}
};
#endif
......@@ -10,13 +10,18 @@ using namespace std;
SensorList::SensorList()
{
tail = NULL;
// Dependency = NULL here
reset();
}
SensorList::SensorList(SensorList const & right)
{
*this = right;
if (right.head.get() != NULL)
{
logWrite(ERROR, "SensorList copy constructed after setup. "
"This shouldn't have been able to happen. "
"Sensors have been lost.");
}
reset();
}
SensorList & SensorList::operator=(SensorList const & right)
......@@ -25,15 +30,11 @@ SensorList & SensorList::operator=(SensorList const & right)
{
if (right.head.get() != NULL)
{
head = right.head->clone();
tail = head->getTail();
logWrite(ERROR, "SensorList assigned after setup. "
"This shouldn't have been able to happen. "
"Sensors have been lost.");
}
else
{
head.reset(NULL);
tail = NULL;
}
// Copy dependency pointers here.
reset();
}
return *this;
}
......@@ -43,6 +44,9 @@ void SensorList::addSensor(SensorCommand const & newSensor)
// Add dependency type demux here.
switch(newSensor.type)
{
case NULL_SENSOR:
pushNullSensor(newSensor);
break;
default:
logWrite(ERROR,
"Incorrect sensor type (%d). Ignoring add sensor command.",
......@@ -56,6 +60,14 @@ Sensor * SensorList::getHead(void)
return head.get();
}
void reset(void)
{
head.reset(NULL);
tail = NULL;
// Dependency = NULL here
depNullSensor = NULL;
}
void SensorList::pushSensor(std::auto_ptr<Sensor> newSensor)
{
if (tail != NULL)
......@@ -71,3 +83,18 @@ void SensorList::pushSensor(std::auto_ptr<Sensor> newSensor)
// Add individual pushSensor functions here.
void SensorList::pushNullSensor(SensorCommand const &)
{
// Dependency list
// Example dependency check
if (depNullSensor == NULL)
{
NullSensor * newSensor = new NullSensor();
std::auto_ptr<Sensor> current(newSensor);
pushSensor(current);
// Example dependency set
depNullSensor = newSensor;
}
}
......@@ -16,6 +16,8 @@
class Sensor;
class SensorCommand;
class NullSensor;
class SensorList
{
public:
......@@ -29,9 +31,13 @@ private:
std::auto_ptr<Sensor> head;
Sensor * tail;
private:
// Functions for creating sensors and pushing them onto the list.
void reset(void);
void pushSensor(std::auto_ptr<Sensor> newSensor);
// Functions for creating sensors and pushing them onto the list.
void pushNullSensor(SensorCommand const & command);
private:
// Example dependency
NullSensor * depNullSensor;
// Dependency pointers.
};
......
......@@ -27,6 +27,24 @@ struct timeval * Time::getTimeval(void)
return &data;
}
Time Time::operator+(int const & right) const
{
Time result;
result.data.tv_sec = data.tv_sec + right/1000;
result.data.tv_usec = data.tv_usec + (right%1000)*1000;
if (result.data.tv_usec < 0)
{
--(result.data.tv_sec);
result.data.tv_usec += 1000000;
}
if (result.data.tv_usec >= 1000000)
{
++(result.data.tv_sec);
result.data.tv_usec -= 1000000;
}
return result;
}
Time Time::operator-(Time const & right) const
{
Time result;
......
......@@ -10,6 +10,7 @@ public:
Time(struct timeval const & newData);
long long toMilliseconds(void) const;
struct timeval * getTimeval(void);
Time operator+(int const & right) const;
Time operator-(Time const & right) const;
bool operator<(Time const & right) const;
bool operator==(Time const & right) const;
......
......@@ -17,4 +17,28 @@ public:
Time const & previousTime)=0;
};
class NullTrafficModel : public TrafficModel
{
public:
virtual ~NullTrafficModel() {}
virtual std::auto_ptr<TrafficModel> clone(void)
{
return std::auto_ptr<TrafficModel>(new NullTrafficModel());
}
virtual Time addWrite(TrafficWriteCommand const &,
Time const &)
{
return Time();
}
virtual WriteResult writeToPeer(ConnectionModel * peer,
Time const & previousTime)
{
WriteResult result;
result.isConnected = false;
result.bufferFull = false;
result.nextWrite = Time();
return result;
}
};
#endif
......@@ -55,6 +55,11 @@ enum TransportProtocol
UDP_CONNECTION = 1
};
enum SensorType
{
NULL_SENSOR
};
struct Order
{
TransportProtocol transport;
......@@ -111,9 +116,35 @@ struct WriteResult
Time nextWrite;
};
struct PacketInfo
{
Time packetTime;
int packetLength;
struct tcp_info const * kernel;
IpHeader const * ip;
struct tcphdr const * tcp;
Order elab;
bool bufferFull;
};
enum
{
FORWARD_EDGE = 0,
BACKWARD_EDGE
};
enum
{
CONNECTION_SEND_BUFFER_SIZE = 0,
CONNECTION_RECEIVE_BUFFER_SIZE,
CONNECTION_MAX_SEGMENT_SIZE,
CONNECTION_USE_NAGLES
};
enum
{
CONNECTION_MODEL_KERNEL = 0
CONNECTION_MODEL_NULL = 0,
CONNECTION_MODEL_KERNEL = 1
};
class ConnectionModel;
......@@ -124,6 +155,9 @@ class CommandOutput;
namespace global
{
extern int connectionModelArg;
extern unsigned short peerServerPort;
extern unsigned short monitorServerPort;
extern int peerAccept;
extern std::auto_ptr<ConnectionModel> connectionModelExemplar;
extern std::string interface;
......@@ -141,7 +175,8 @@ namespace global
extern std::auto_ptr<CommandOutput> output;
}
void addDescriptor(int fd);
void setDescriptor(int fd);
void clearDescriptor(int fd);
std::string ipToString(unsigned int ip);
#endif
......@@ -42,6 +42,10 @@ static void logPrefix(int flags)
{
fprintf(logFile, "PEER_CYCLE ");
}
if (flags & SENSOR)
{
fprintf(logFile, "SENSOR ");
}
if (logTimestamp)
{
struct timeval now;
......
......@@ -3,11 +3,6 @@
#ifndef _LOG_H
#define _LOG_H
#ifdef __cplusplus
extern "C"
{
#endif
// The logging framework. Use logInit() during initialization to set
// up logging. Then use log() to generate messages. logCleanup()
// should be called during program shutdown.
......@@ -46,13 +41,10 @@ enum LOG_TYPE
ERROR = 0x01,
EXCEPTION = 0x02,
PEER_CYCLE = 0x04,
SENSOR = 0x08,
// Shortcuts for common cases.
LOG_NOTHING = 0x00,
LOG_EVERYTHING = 0x07
LOG_EVERYTHING = 0x0f
};
#ifdef __cplusplus
}
#endif
#endif
......@@ -17,6 +17,9 @@ using namespace std;
namespace global
{
int connectionModelArg = 0;
unsigned short peerServerPort = 0;
unsigned short monitorServerPort = 0;
int peerAccept = -1;
string interface;
auto_ptr<ConnectionModel> connectionModelExemplar;
......@@ -41,7 +44,7 @@ void addNewPeer(fd_set * readable);
void readFromPeers(fd_set * readable);
void packetCapture(fd_set * readable);
int main(int /*argc*/, char * /*argv*/[])
int main(int argc, char * argv[])
{
processArgs(argc, argv);
init();
......@@ -51,15 +54,21 @@ int main(int /*argc*/, char * /*argv*/[])
void processArgs(int argc, char * argv[])
{
// TODO: Add argument-processing code
global::connectionModelArg = CONNECTION_MODEL_NULL;
global::peerServerPort = 3491;
global::monitorServerPort = 4200;
}
void init(void)
{
srandom(getpid());
switch (global::connectionModelArg)