/* -*- c++ -*- rcp.h Received-Based TCP (Receiver Side) Two agents: RcpAgent (receiver side) and RcpTap (sender side) */ #ifndef __rcp_h__ #define __rcp_h__ #include "tcp.h" /* * The following definition can be put in tcp.h */ #define REPN (NSA*2) // 3 blocks #ifdef NDEBUG #undef NDEBUG #endif /* * Racker should ideally deal with only reliability & sequence of pkt to send */ class Racker { struct PKI { int seen; int req; double sent; int later; }; public: Racker(); ~Racker(); void reset(double wnd); virtual int resequence(Packet *pkt); // receive one packet int request(int fid,int seq,double *t,int force=0);// request a token int nextseq(); // next to send int islost(int seq); // loss detection void timeout(); // notify timeout inline int pipe() {return pipe_;} inline int buflen() {return int(blength_);} inline double buffer() {return (npacket_ ? blength_/npacket_ : 0.0);} protected: void loseit(int seq); // mark loss int wndmask_, rcvnext_, maxseen_, maxreq_, bufsize_; int pipe_; PKI *buf_; #define pki_(i) buf_[(i) & wndmask_] /* * statistics */ double blength_; int npacket_; }; class RcpAgent : public TcpAgent { public: RcpAgent(Racker *); virtual void reset(); virtual int command(int argc, const char*const* argv); virtual void sendmsg(int sz, AppData*, const char* flags = 0); virtual void recv(Packet *p, Handler *h); virtual void resume(); protected: virtual void delay_bind_init_all(); virtual int delay_bind_dispatch(const char *, const char *, TclObject *); virtual void send_one(void); virtual void send_much(int force, int reason, int maxburst); virtual void output(int seqno, int reason = 0); virtual void dupack_action(); virtual void timeout(int tno); int send_allowed(int seq); int sendpkt(int seqno, int reason=0, int force=0); void rcp_eln(Packet *pkt); Racker *racker_; TracedInt r_seqno_,o_seqno_,b_length_; enum {NORMAL_=0, FASTRECOV_, PASSIVE_, SLEEP_} state_; u_char timeout_, firstpkt_; // double pdrop_[1024]; int rpq_[REPN], repnxt_; #define rep_(i) rpq_[(i) % REPN] }; #endif/*__rcp_h__*/