Commit 84da2a61 authored by Jonathon Duerig's avatar Jonathon Duerig

magent is now compilable. Added all the extra files I've added which I forgot to do before.

parent 139af9f6
// CircularTraffic.cc
#include "lib.h"
#include "log.h"
#include "CircularTraffic.h"
#include "Command.h"
#include "ConnectionModel.h"
using namespace std;
CircularTraffic::CircularTraffic()
{
begin = 0;
usedCount = 0;
current = 0;
writes.resize(DEFAULT_SIZE);
}
CircularTraffic::~CircularTraffic()
{
}
auto_ptr<TrafficModel> CircularTraffic::clone(void)
{
auto_ptr<CircularTraffic> result;
result->begin = begin;
result->usedCount = usedCount;
result->current = current;
result->writes = writes;
auto_ptr<TrafficModel> model(result.release());
return model;
}
Time CircularTraffic::addWrite(TrafficWriteCommand const & newWrite,
Time const & deadline)
{
if (usedCount < static_cast<int>(writes.size()))
{
writes[usedCount] = newWrite;
++usedCount;
}
else
{
writes[begin] = newWrite;
begin = (begin + 1) % writes.size();
}
if (deadline == Time())
{
return getCurrentTime() + writes[current].delta;
}
else
{
return Time();
}
}
WriteResult CircularTraffic::writeToPeer(ConnectionModel * peer,
Time const & previousTime)
{
if (usedCount > 0)
{
WriteResult result;
current = (current + 1) % usedCount;
peer->writeMessage(writes[current].size, result);
result.nextWrite = previousTime + writes[current].delta;
return result;
}
else
{
logWrite(ERROR, "writeToPeer() called without addWrite() being "
"called first. This should be impossible.");
WriteResult result;
result.isConnected = peer->isConnected();
result.bufferFull = false;
result.nextWrite = Time();
return result;
}
}
// CircularTraffic.h
#ifndef CIRCULAR_TRAFFIC_H_STUB_2
#define CIRCULAR_TRAFFIC_H_STUB_2
#include "TrafficModel.h"
class CircularTraffic : public TrafficModel
{
public:
enum { DEFAULT_SIZE = 20 };
public:
CircularTraffic();
virtual ~CircularTraffic();
virtual std::auto_ptr<TrafficModel> clone(void);
virtual Time addWrite(TrafficWriteCommand const & newWrite,
Time const & deadline);
virtual WriteResult writeToPeer(ConnectionModel * peer,
Time const & previousTime);
private:
int begin;
int usedCount;
int current;
std::vector<TrafficWriteCommand> writes;
};
#endif
......@@ -6,6 +6,7 @@
#include "Connection.h"
#include "ConnectionModel.h"
#include "TrafficModel.h"
#include "CircularTraffic.h"
using namespace std;
......@@ -30,6 +31,8 @@ void NewConnectionCommand::runConnect(Connection *,
void TrafficModelCommand::runConnect(Connection * conn,
std::multimap<Time, Connection *> &)
{
std::auto_ptr<TrafficModel> model(new CircularTraffic());
conn->setTraffic(model);
}
//-----------------------
......
......@@ -22,6 +22,7 @@ protected:
virtual void runConnect(Connection * conn,
std::multimap<Time, Connection *> & schedule)=0;
public:
// We use a key here and look up the connection only on a run()
// because some commands delete a connection and we don't want later
// commands to keep the reference around.
......@@ -49,6 +50,7 @@ class ConnectionModelCommand : public Command
protected:
virtual void runConnect(Connection * conn,
std::multimap<Time, Connection *> &);
public:
int type;
int value;
};
......@@ -60,7 +62,7 @@ protected:
std::multimap<Time, Connection *> &);
public:
int type;
std::vector<char> parameters;
// std::vector<char> parameters;
};
class ConnectCommand : public Command
......
......@@ -8,6 +8,9 @@
#ifndef COMMAND_OUTPUT_H_STUB_2
#define COMMAND_OUTPUT_H_STUB_2
#include "log.h"
#include "saveload.h"
class CommandOutput
{
public:
......@@ -15,28 +18,38 @@ public:
{
SENDING_MESSAGE = 0,
DISCARDING_MESSAGE
}
};
enum PathDirection
{
FORWARD_PATH,
BACKWARD_PATH
};
public:
virtual ~CommandOutput() {}
void eventMessage(std::string const & message, Order const & key,
char direction)
PathDirection dir=FORWARD_PATH)
{
if (message.size() <= 0xffff && message.size() > 0)
{
Header prefix;
prefix.type = EVENT_TO_MONITOR;
if (dir == FORWARD_PATH)
{
prefix.type = EVENT_FORWARD_PATH;
}
else
{
prefix.type = EVENT_BACKWARD_PATH;
}
prefix.size = message.size();
prefix.key = key;
char headerBuffer[Header::headerSize];
saveHeader(headerBuffer, prefix);
int result = startMessage(Header::headerSize + sizeof(direction)
+ message.size());
int result = startMessage(Header::headerSize + message.size());
if (result == SENDING_MESSAGE)
{
writeMessage(headerBuffer, Header::headerSize);
writeMessage(&direction, sizeof(direction));
writeMessage(message.c_str(), message.size());
finishMessage();
endMessage();
}
}
else
......
......@@ -10,7 +10,7 @@ class ConnectionModel
public:
virtual ~ConnectionModel() {}
virtual std::auto_ptr<ConnectionModel> clone(void)=0;
virtual void connect(void)=0;
virtual void connect(Order & planet)=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.
......@@ -26,17 +26,18 @@ public:
{
return std::auto_ptr<ConnectionModel>(new ConnectionModelNull());
}
virtual void connect(void) {}
virtual void connect(Order &) {}
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)
virtual int writeMessage(int, WriteResult & result)
{
result.isConnected = false;
result.bufferFull = false;
return 0;
}
virtual bool isConnected(void)
{
......
// DelaySensor.cc
#include "lib.h"
#include "DelaySensor.h"
#include "PacketSensor.h"
#include "Time.h"
using namespace std;
DelaySensor::DelaySensor(PacketSensor * newPacketHistory)
{
lastDelay = 0;
packetHistory = newPacketHistory;
}
int DelaySensor::getLastDelay(void) const
{
return lastDelay;
}
void DelaySensor::localSend(PacketInfo *)
{
}
void DelaySensor::localAck(PacketInfo * packet)
{
Time diff = packet->packetTime - packetHistory->getAckedSendTime();
lastDelay = diff.toMilliseconds();
}
// DelaySensor.h
#ifndef DELAY_SENSOR_H_STUB_2
#define DELAY_SENSOR_H_STUB_2
#include "Sensor.h"
class PacketSensor;
class DelaySensor : public Sensor
{
public:
DelaySensor(PacketSensor * newPacketHistory);
int getLastDelay(void) const;
protected:
virtual void localSend(PacketInfo * packet);
virtual void localAck(PacketInfo * packet);
private:
int lastDelay;
PacketSensor * packetHistory;
};
#endif
// DirectInput.cc
#include "lib.h"
#include "log.h"
#include "DirectInput.h"
using namespace std;
DirectInput::DirectInput()
: state(ACCEPTING)
, monitorAccept(-1)
, monitorSocket(-1)
, index(0)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
logWrite(ERROR, "Unable to generate a command accept socket. "
"No incoming command connections will ever be accepted: %s",
strerror(errno));
}
else
{
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(global::monitorServerPort);
address.sin_addr.s_addr = INADDR_ANY;
int error = bind(sockfd, reinterpret_cast<struct sockaddr *>(&address),
sizeof(struct sockaddr));
if (error == -1)
{
logWrite(ERROR, "Unable to bind a command accept socket. "
"No incoming command connections will ever be accepted: %s",
strerror(errno));
close(sockfd);
}
else
{
setDescriptor(sockfd);
monitorAccept = sockfd;
}
}
}
DirectInput::~DirectInput()
{
if (monitorAccept != -1)
{
close(monitorAccept);
}
if (monitorSocket != -1)
{
close(monitorSocket);
}
}
void DirectInput::nextCommand(fd_set * readable)
{
if (state == ACCEPTING && monitorAccept != -1
&& FD_ISSET(monitorAccept, readable))
{
}
if (monitorSocket == -1)
{
state = ACCEPTING;
}
if (state == HEADER && FD_ISSET(monitorSocket, readable))
{
int error = recv(monitorSocket, headerBuffer + index,
Header::headerSize - index, 0);
if (error == Header::headerSize - index)
{
loadHeader(headerBuffer, &commandHeader);
index = 0;
state = BODY;
}
else if (error > 0)
{
index += error;
}
else if (error == 0)
{
disconnect();
}
else if (error == -1)
{
logWrite(EXCEPTION, "Failed read on monitorSocket state HEADER: %s",
strerror(errno));
}
}
if (state == BODY && FD_ISSET(monitorSocket, readable))
{
int error = recv(monitorSocket, bodyBuffer + index,
commandHeader.size - index, 0);
if (error == commandHeader.size - index)
{
currentCommand = loadCommand(&commandHeader, bodyBuffer);
index = 0;
state = HEADER;
}
else if (error > 0)
{
index += error;
}
else if (error == 0)
{
disconnect();
}
else if (error == -1)
{
logWrite(EXCEPTION, "Failed read on monitorSocket state BODY: %s",
strerror(errno));
}
}
}
int DirectInput::getMonitorSocket(void)
{
return monitorSocket;
}
void DirectInput::disconnect(void)
{
if (monitorSocket != -1)
{
clearDescriptor(monitorSocket);
close(monitorSocket);
}
index = 0;
state = ACCEPTING;
}
// DirectInput.h
#ifndef DIRECT_INPUT_H_STUB_2
#define DIRECT_INPUT_H_STUB_2
#include "CommandInput.h"
#include "saveload.h"
class DirectInput : public CommandInput
{
public:
DirectInput();
virtual ~DirectInput();
virtual void nextCommand(fd_set * readable);
virtual int getMonitorSocket(void);
virtual void disconnect(void);
private:
enum MonitorState
{
ACCEPTING,
HEADER,
BODY
};
private:
MonitorState state;
int monitorAccept;
int monitorSocket;
int index;
char headerBuffer[Header::headerSize];
Header commandHeader;
enum { bodyBufferSize = 0xffff };
char bodyBuffer[bodyBufferSize];
};
#endif
......@@ -3,9 +3,28 @@
#include "lib.h"
#include "log.h"
#include "KernelTcp.h"
#include "Command.h"
using namespace std;
namespace
{
bool changeSocket(int sockfd, int level, int optname, int value,
string optstring);
void kernelTcpCallback(unsigned char *,
struct pcap_pkthdr const * pcapInfo,
unsigned char const * packet);
int getLinkLayer(struct pcap_pkthdr const * pcapInfo,
unsigned char const * packet);
void handleTcp(struct pcap_pkthdr const * pcapInfo,
IpHeader const * ipPacket,
struct tcphdr const * tcpPacket);
void handleKernel(Connection * conn, struct tcp_info * kernel);
}
pcap_t * KernelTcp::pcapDescriptor = NULL;
int KernelTcp::pcapfd = -1;
KernelTcp::KernelTcp()
: state(DISCONNECTED)
, peersock(-1)
......@@ -27,11 +46,13 @@ KernelTcp::~KernelTcp()
auto_ptr<ConnectionModel> KernelTcp::clone(void)
{
auto_ptr<KernelTcp> result(new KernelTcp());
result.sendBufferSize = sendBufferSize;
result.receiveBufferSize = receiveBufferSize;
result.maxSegmentSize = maxSegmentSize;
result.useNagles = useNagles;
return result;
result->sendBufferSize = sendBufferSize;
result->receiveBufferSize = receiveBufferSize;
result->maxSegmentSize = maxSegmentSize;
result->useNagles = useNagles;
result->state = state;
auto_ptr<ConnectionModel> modelResult(result.release());
return modelResult;
}
void KernelTcp::connect(Order & planet)
......@@ -47,7 +68,7 @@ void KernelTcp::connect(Order & planet)
// Set up all parameters
if ((sendBufferSize != 0 && !changeSocket(sockfd, SOL_SOCKET, SO_SNDBUF,
sendBufferSize, "SO_SNDBUF"))
sendBufferSize, "SO_SNDBUF"))
|| (receiveBufferSize != 0 && !changeSocket(sockfd, SOL_SOCKET,
SO_RCVBUF,
receiveBufferSize,
......@@ -93,7 +114,7 @@ void KernelTcp::connect(Order & planet)
}
error = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
if (error == =1)
if (error == -1)
{
logWrite(EXCEPTION, "Cannot set fcntl flags (nonblocking) "
"on a peer socket: %s", strerror(errno));
......@@ -120,6 +141,12 @@ void KernelTcp::connect(Order & planet)
void KernelTcp::addParam(ConnectionModelCommand const & param)
{
if (state == CONNECTED)
{
logWrite(ERROR, "A ConnectionModelCommand was received after connection. "
"It will not be applied unless the connection dies and is "
"re-established.");
}
switch (param.type)
{
case CONNECTION_SEND_BUFFER_SIZE:
......@@ -139,28 +166,6 @@ void KernelTcp::addParam(ConnectionModelCommand const & param)
}
}
bool KernelTcp::changeSocket(int sockfd, int optname, int value,
string optstring)
{
int error = setsockopt(sockfd, SOL_SOCKET, optname, &value, sizeof(value));
if (error == -1)
{
logWrite(ERROR, "Cannot set socket option %s", optstring.c_str());
return false;
}
int newValue = 0;
int newValueLength = sizeof(newValue);
error = getsockopt(sockfd, SOL_SOCKET, optname, &newValue, &newValueLength);
if (error == -1)
{
logWrite(ERROR, "Cannot read back socket option %s", optstring.c_str());
return false;
}
logWrite(CONNECTION_MODEL, "Socket option %s is now %d", optstring.c_str(),
newValue);
return true;
}
int KernelTcp::writeMessage(int size, WriteResult & result)
{
if (state == DISCONNECTED)
......@@ -184,7 +189,7 @@ int KernelTcp::writeMessage(int size, WriteResult & result)
close(peersock);
peersock = -1;
state = DISCONNECTED;
result.fullBuffer = false;
result.bufferFull = false;
result.isConnected = false;
return 0;
}
......@@ -198,7 +203,7 @@ int KernelTcp::writeMessage(int size, WriteResult & result)
return error;
}
}
result.fullBuffer = false;
result.bufferFull = false;
result.isConnected = false;
return -1;
}
......@@ -208,6 +213,11 @@ bool KernelTcp::isConnected(void)
return state == CONNECTED;
}
int KernelTcp::getSock(void) const
{
return peersock;
}
enum { SNIFF_WAIT = 10 };
void KernelTcp::init(void)
......@@ -232,7 +242,7 @@ void KernelTcp::init(void)
if (error == -1)
{
logWrite(ERROR, "Unable to bind peer accept socket. "
"No incoming peer connections will ever be accepted: %s",,
"No incoming peer connections will ever be accepted: %s",
strerror(errno));
close(sockfd);
}
......@@ -247,7 +257,7 @@ void KernelTcp::init(void)
global::connectionModelExemplar.reset(new KernelTcp());
// Set up packet capture
char errorbuf[PCAP_ERRBUF_SIZE];
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp; /* hold compiled program */
bpf_u_int32 maskp; /* subnet mask */
bpf_u_int32 netp; /* ip */
......@@ -265,23 +275,28 @@ void KernelTcp::init(void)
{
logWrite(ERROR, "pcap_open_live() failed: %s", errbuf);
}
// Lets try and compile the program, optimized
else if(pcap_compile(pcapDescriptor, &fp, filter, 1, maskp) == -1)
else if(pcap_compile(pcapDescriptor, &fp,
const_cast<char *>(filter.str().c_str()),
1, maskp) == -1)
{
logWrite(ERROR, "pcap_compile() failed");
logWrite(ERROR, "pcap_compile() failed: %s", pcap_geterr(pcapDescriptor));
pcap_close(pcapDescriptor);
}
// set the compiled program as the filter
else if(pcap_setfilter(pcapDescriptor,&fp) == -1)
{
logWrite(ERROR, "pcap_filter() failed");
logWrite(ERROR, "pcap_filter() failed: %s", pcap_geterr(pcapDescriptor));
pcap_close(pcapDescriptor);
}
else
{
pcapfd = pcap_get_selectable_fd(pcapDescriptor);
if (pcapfd == -1)
{
logWrite(ERROR, "Failed to get a selectable file descriptor for pcap");
logWrite(ERROR, "Failed to get a selectable file descriptor "
"for pcap: %s", pcap_geterr(pcapDescriptor));
pcap_close(pcapDescriptor);
}