/* TCP-HyblaS.h v7.1 (13 January 2006)
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *
 * This software is developed by Rosario Firrincieli
 * ARCES-University of Bologna, Italy.
 * rfirrincieli@arces.unibo.it
 *
 * TCP-HyblaS is builded over the SACK TCP Agent; comments in the original SACK script (tcp-sack1.cc) are left 
 * unaltered. Detailed description of all the added non-standard procedures
 * can be found in the authors' publications.
 */



#ifndef tcp_hyblaS_h
#define tcp_hyblaS_h

#include "scoreboard.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <math.h>
#include "packet.h"
#include "ip.h"
#include "tcp.h"
#include "flags.h"
#include "random.h"
#include <iostream>

using namespace std;
 
class HyblaSTcpAgent : public virtual RenoTcpAgent {

public:
	HyblaSTcpAgent();
	virtual void recv(Packet *pkt, Handler*);			/* major modifications with respect to the original version */
	void reset();							/* unaltered with respect to the original version */
	virtual void timeout(int tno);					/* unaltered with respect to the original version */
	virtual void dupack_action();					/* minor modifications with respect to the original version */
	void plot();							/* unaltered with respect to the original version */
	virtual void send_much(int force, int reason, int maxburst);	/* major modifications with respect to the original version */ 
	virtual void partialnewack_helper(Packet* pkt);			/* minor modifications with respect to the original version */
	virtual void new_opencwnd();					/* this function implement the Hybla congestion window alghorithm! */					
	virtual void recv_newack_helper(Packet *pkt);			/* minor modifications with respect to the original version */
	virtual double del_calc();					/* used to calculate the interpacket delay given a certain packet
									 * spreading tecnique 
									 */

protected:
	virtual ~HyblaSTcpAgent();
	int bdp_fix_;			/* if 1, tcp-hybla cwnd algorithm does not apply when cwnd > BDP*/
	double rho_;			/* ratio between estimated RTT and the reference RTT (RTT_REF_) */
	double bdp_;			/* bandwidth-delay product */
	double k_thresh_;		/* used in the initial ssthresh estimation*/
	double k_cwnd_;			/* used in the maxcwnd estimation*/
	int PKT_SPREADING_;		/* its value determines which packet spreading techique must be used (0 means no packet spreading) */
	int ACK_size_;			/* length in byte of an ACK packet */
	int TCP_size_;			/* length in byte of a TCP packet */
	int SS_state_;			/* if 1 the connection is in Slow Start phase */
	int SS_first_;			/* used to monitor the first Slow Start length, set to 1 to ignore
					 * this monitoring */
	int pkt_count_;			/* used in the Progressive packet spacing tecnique */
	int newreno_changes_;		/* 0 for fixing unnecessary fast retransmits, 1 for additional code from Allman, 
					 * to implement other algorithms from Hoe's paper, including sending a new 
					 * packet for every two duplicate ACKs and bandwidth-delay product estimation. Hybla sets it to 1 */
	int newreno_changes1_;  	/* Newreno_changes1_ set to 0 gives the Slow-but-Steady variant of NewReno from 
					 * RFC 2582, with the retransmit timer reset after each partial new ack. 
					 * Newreno_changes1_ set to 1 gives the Impatient variant of NewReno from 
					 * RFC 2582, with the retransmit timer reset only for the first partial new ack. The default is set to 0 */
	void partialnewack(Packet *pkt);			/* unaltered with respect to the original version */	
	int allow_fast_retransmit(int last_cwnd_action_);	/* unaltered with respect to the original version */
	int acked_,new_ssthresh_;      				/* used if newreno_changes_ = 1 */
	double ack2_, ack3_, basertt_; 				/* used if newreno_changes_ = 1 */
	int firstpartial_; 					/* first partial ACK. */
	int partial_window_deflation_; 				/* 0 if set cwnd to ssthresh upon partial
								 * new ack (default) 1 if deflate (cwnd + dupwnd) by
								 * amount of data acked "Partial window deflation" is discussed in RFC 2582. 
								 */
	int exit_recovery_fix_;					/* 0 for setting cwnd to ssthresh upon leaving fast recovery (default) 
					 			 * 1 for setting cwnd to min(ssthresh, amnt. of data in network) when leaving */
	u_char timeout_;					/* boolean: sent pkt from timeout? */
	u_char fastrecov_;					/* boolean: doing fast recovery? */
	int pipe_;						/* estimate of pipe size (fast recovery) */
	ScoreBoard* scb_;
	static const int SBSIZE=64; 				/* Initial scoreboard size */
};



#endif
