Main Page | Class Hierarchy | Class List | File List | Class Members

/Users/baford/proj/netsteria/sst/lib/flow.h

00001 #ifndef SST_FLOW_H
00002 #define SST_FLOW_H
00003 
00004 #include <QTime>
00005 #include <QTimer>
00006 
00007 #include "ident.h"
00008 #include "sock.h"
00009 #include "timer.h"
00010 
00011 // XXX for specific armor methods - break into separate module
00012 #include "chk32.h"
00013 #include "aes.h"
00014 #include "hmac.h"
00015 
00016 
00017 namespace SST {
00018 
00019 class Host;
00020 class Ident;
00021 class Endpoint;
00022 class Socket;
00023 class FlowCC;
00024 class KeyInitiator;     // XXX
00025 
00026 
00027 // Abstract base class for flow encryption and authentication schemes.
00028 class FlowArmor
00029 {
00030         friend class Flow;
00031 
00032 protected:
00033         // The pseudo-header is a header logically prepended to each packet
00034         // for authentication purposes but not actually transmitted.
00035         // XX probably can't always be static const
00036         //static const int phlen = 4;
00037 
00038         // The encryption offset defines the offset in the transmitted packet
00039         // at which encrypted data begins (after authenticate-only data).
00040         static const int encofs = 4;
00041 
00042         virtual QByteArray txenc(qint64 pktseq, const QByteArray &pkt) = 0;
00043         virtual bool rxdec(qint64 pktseq, QByteArray &pkt) = 0;
00044 
00045         virtual ~FlowArmor();
00046 };
00047 
00048 // Abstract base class representing a flow
00049 // between a local Socket and a remote endpoint.
00050 class Flow : public SocketFlow
00051 {
00052         friend class KeyInitiator;      // XXX
00053         Q_OBJECT
00054 
00055 private:
00056         Host *const h;
00057         FlowArmor *armr;        // Encryption/authentication method
00058         FlowCC *cc;             // Congestion control method
00059 
00060 
00061 public:
00062         // Amount of space client must leave at the beginning of a packet
00063         // to be transmitted with flowTransmit() or received via flowReceive().
00064         // XX won't always be static const.
00065         static const int hdrlen = 8;
00066 
00067         // Layout of the first header word: channel number, tx sequence
00068         // Transmitted in cleartext.
00069         static const quint32 chanBits = 8;      // 31-24: channel number
00070         static const quint32 chanMask = (1 << chanBits) - 1;
00071         static const quint32 chanMax = chanMask;
00072         static const quint32 chanShift = 24;
00073         static const quint32 seqBits = 24;      // 23-0: tx sequence number
00074         static const quint32 seqMask = (1 << seqBits) - 1;
00075 
00076         // Layout of the second header word: ACK count/sequence number
00077         // Encrypted for transmission.
00078         static const quint32 resvBits = 4;      // 31-28: reserved field
00079         static const quint32 ackctBits = 4;     // 27-24: ack count
00080         static const quint32 ackctMask = (1 << ackctBits) - 1;
00081         static const quint32 ackctMax = ackctMask;
00082         static const quint32 ackctShift = 24;
00083         static const quint32 ackSeqBits = 24;   // 23-0: ack sequence number
00084         static const quint32 ackSeqMask = (1 << ackSeqBits) - 1;
00085 
00086 
00087         Flow(Host *host, QObject *parent = NULL);
00088 
00089         inline Host *host() { return h; }
00090 
00091         // Set the encryption/authentication method for this flow.
00092         // This MUST be set before a new flow can be activated.
00093         inline void setArmor(FlowArmor *armor) { this->armr = armor; }
00094         inline FlowArmor *armor() { return armr; }
00095 
00096         // Set the congestion controller for this flow.
00097         // This must be set if the client wishes to call mayTransmit().
00098         inline void setCongestionController(FlowCC *cc) { this->cc = cc; }
00099         inline FlowCC *congestionController() { return cc; }
00100 
00101         // Start and stop the flow.
00102         virtual void start();
00103         virtual void stop();
00104 
00105 
00106 protected:
00107 
00108         // Size of rxmask and txackmask fields in bits
00109         static const int maskBits = 32;
00110 
00111         // Transmit state
00112         quint64 txseq;          // Next sequence number to transmit
00113         quint64 txdatseq;       // Seqno of last real data packet transmitted
00114         quint64 txackseq;       // Highest transmit sequence number ACK'd
00115         quint64 recovseq;       // Sequence at which fast recovery finishes
00116         quint64 markseq;        // Transmit sequence number of "marked" packet
00117         quint64 markbase;       // Snapshot of txackseq at time mark was placed
00118         Time marktime;          // Time at which marked packet was sent
00119         quint32 txackmask;      // Mask of packets transmitted and ACK'd
00120         quint32 markacks;       // Number of ACK'd packets since last mark
00121         quint32 marksent;       // Number of ACKs expected after last mark
00122         quint32 cwnd;           // Current congestion window
00123         bool cwndlim;           // We were cwnd-limited this round-trip
00124 
00125         // TCP congestion control
00126         quint32 ssthresh;       // Slow start threshold
00127 
00128         // Aggressive congestion control
00129         quint32 ssbase;         // Slow start baseline
00130 
00131         // Low-delay congestion control
00132         int cwndinc;
00133         int lastrtt;            // Measured RTT of last round-trip
00134         float lastpps;          // Measured PPS of last round-trip
00135         quint32 basewnd;
00136         float basertt, basepps, basepwr;
00137 
00138         // TCP Vegas-like congestion control
00139         float cwndmax;
00140 
00141         // Retransmit state
00142         Timer rtxtimer;         // Retransmit timer
00143 
00144         // Receive state
00145         quint64 rxseq;          // Last sequence number received
00146         quint32 rxmask;         // Mask of packets recently received
00147         quint8 rxackct;         // # contiguous packets received before rxseq
00148         quint8 rxunacked;       // # contiguous packets not yet ACKed
00149 
00150         // Delayed ACK state
00151         bool delayack;          // Enable delayed acknowledgments
00152         Timer acktimer;         // Delayed ACK timer
00153 
00154         // Statistics gathering
00155         float cumrtt;           // Cumulative measured RTT in milliseconds
00156         float cumrttvar;        // Cumulative variation in RTT
00157         float cumpps;           // Cumulative measured packets per second
00158         float cumppsvar;        // Cumulative variation in PPS
00159         float cumpwr;           // Cumulative measured network power (pps/rtt)
00160         float cumbps;           // Cumulative measured bytes per second
00161         float cumloss;          // Cumulative measured packet loss ratio
00162         Timer statstimer;
00163 
00164 
00165         // Transmit a packet across the flow.
00166         // Caller must leave hdrlen bytes at the beginning for the header.
00167         // The packet is armored in-place in the provided QByteArray.
00168         // It is the caller's responsibility to transmit
00169         // only when flow control says it's OK (mayTransmit())
00170         // or upon getting a readyTransmit() callback.
00171         // Provides in 'pktseq' the transmit sequence number
00172         // that was assigned to the packet.
00173         // Returns true if the transmit was successful,
00174         // or false if it failed (e.g., due to lack of buffer space);
00175         // a sequence number is assigned even on failure however.
00176         bool flowTransmit(const QByteArray &pkt, quint64 &pktseq);
00177 
00178         // Check congestion control state and return the number of new packets,
00179         // if any, that flow control says we may transmit now.
00180         int mayTransmit();
00181 
00182         // Compute current number of transmitted but un-acknowledged packets.
00183         // This count may include raw ACK packets,
00184         // for which we expect no acknowledgments
00185         // unless they happen to be piggybacked on data coming back.
00186         inline qint64 unackedPackets()
00187                 { return txseq - txackseq; }
00188 
00189         // Compute current number of un-acknowledged data packets.
00190         // Note that txackseq might be greater than txdatseq
00191         // if we have sent ACKs since our last real data transmission
00192         // and the other side has ACKed some of those ACKs
00193         // (e.g., piggybacked on data packets it is sending us).
00194         inline qint64 unackedDataPackets()
00195                 { return (txdatseq > txackseq) ? (txdatseq - txackseq) : 0; }
00196 
00197         // Compute the time elapsed since the mark in microseconds.
00198         qint64 markElapsed();
00199 
00200 public:
00201         inline bool deleyedAcks() const { return delayack; }
00202         inline void setDelayedAcks(bool enabled) { delayack = enabled; }
00203 
00204 protected:
00205         // Main method for upper-layer subclass to receive a packet on a flow.
00206         virtual void flowReceive(qint64 pktseq, QByteArray &pkt) = 0;
00207 
00208         virtual void readyTransmit();
00209         virtual void acked(qint64 txseq, int npackets);
00210         virtual void missed(qint64 txseq, int npackets);
00211         virtual void failed();
00212 
00213 
00214 private:
00215         // Called by Socket to dispatch a received packet to this flow.
00216         virtual void receive(QByteArray &msg, const SocketEndpoint &src);
00217 
00218         // Internal transmit methods.
00219         bool tx(const QByteArray &pkt, quint32 packseq,
00220                         quint64 &pktseq);
00221         bool txack(quint32 seq, unsigned ackct);
00222         inline void flushack()
00223                 { if (rxunacked) { rxunacked = 0; txack(rxseq, rxackct); }
00224                   acktimer.stop(); }
00225 
00226         inline void rtxstart()
00227                 { rtxtimer.start((int)(cumrtt * 2.0)); }
00228 
00229 
00230 private slots:
00231         void rtxTimeout(bool failed);   // Retransmission timeout
00232         void ackTimeout();      // Delayed ACK timeout
00233         void statsTimeout();
00234 };
00235 
00236 
00237 
00238 // XX break this stuff into separate module
00239 
00240 // Simple 32-bit keyed checksum protection with no encryption,
00241 // to defend only against off-the-path attackers
00242 // who can inject forged packets but not monitor the flow.
00243 class ChecksumArmor : public FlowArmor
00244 {
00245         const uint32_t txkey, rxkey;
00246 
00247 public:
00248         ChecksumArmor(uint32_t txkey, uint32_t rxkey);
00249 
00250         virtual QByteArray txenc(qint64 pktseq, const QByteArray &pkt);
00251         virtual bool rxdec(qint64 pktseq, QByteArray &pkt);
00252 };
00253 
00254 
00255 class AESArmor : public FlowArmor
00256 {
00257         const AES txaes, rxaes;
00258         const HMAC txmac, rxmac;
00259 
00260         union ivec {
00261                 quint8 b[AES_BLOCK_SIZE];
00262                 quint32 l[4];
00263         } ivec;
00264 
00265 public:
00266         AESArmor(const QByteArray &txenckey, const QByteArray &txmackey,
00267                 const QByteArray &rxenckey, const QByteArray &rxmackey);
00268 
00269         virtual QByteArray txenc(qint64 pktseq, const QByteArray &pkt);
00270         virtual bool rxdec(qint64 pktseq, QByteArray &pkt);
00271 };
00272 
00273 } // namespace SST
00274 
00275 #endif  // SST_FLOW_H

Generated on Wed Mar 28 11:48:05 2007 for SST by doxygen 1.3.4