[Sumover-dev] [svn commit] r4804 - in vic/branches/cc: rtp

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Sun May 9 02:16:39 BST 2010


Author: soohyunc
Date: Sun May  9 02:16:38 2010
New Revision: 4804

Modified:
   vic/branches/cc/cc/tfrc_rcvr.h
   vic/branches/cc/cc/tfrc_sndr.h
   vic/branches/cc/cc/tfwc_rcvr.h
   vic/branches/cc/cc/tfwc_sndr.h
   vic/branches/cc/rtp/session.cpp
   vic/branches/cc/rtp/session.h
   vic/branches/cc/rtp/transmitter.cpp
   vic/branches/cc/rtp/transmitter.h

Log:
added TFRC sending and receiving mechanisms
(currently, TFRC's send rate calculation is omitted)




Modified: vic/branches/cc/cc/tfrc_rcvr.h
==============================================================================
--- vic/branches/cc/cc/tfrc_rcvr.h	(original)
+++ vic/branches/cc/cc/tfrc_rcvr.h	Sun May  9 02:16:38 2010
@@ -42,8 +42,18 @@
 public:
 	TfrcRcvr();
 
+	// receive AoA
 	void recv_aoa(u_int16_t type, u_int16_t *chunk);
+	// receive RTP data 
 	void recv_seqno(u_int16_t seqno);
+    // AckVec clone
+    inline u_int16_t getvec(int i) { return tfrcAV[i]; }
+    // AckVec begin seqno
+    inline u_int16_t begins() { return begins_; }
+    // AckVec end seqno plus one
+    inline u_int16_t ends() { return ends_; }
+    // number of AckVec array
+    inline u_int16_t numvec() { return numVec_; }
 
 	// TfrcRcvr instance
 	static inline TfrcRcvr& instance() { return instance_; }

Modified: vic/branches/cc/cc/tfrc_sndr.h
==============================================================================
--- vic/branches/cc/cc/tfrc_sndr.h	(original)
+++ vic/branches/cc/cc/tfrc_sndr.h	Sun May  9 02:16:38 2010
@@ -40,7 +40,6 @@
 #include "cc_timer.h"
 
 class TfrcSndr;
-class Transmitter;
 
 // TFRC sender class
 class TfrcSndr {
@@ -62,6 +61,9 @@
 	void recv(u_int16_t, u_int16_t, u_int16_t,
 		u_int16_t*, double, bool, pktbuf*);
 
+	// return ackofack
+	inline u_int16_t get_aoa() { return aoa_; }
+
 	u_int16_t seqno_;	// packet sequence number
 	double x_rate_;		// send rate
 

Modified: vic/branches/cc/cc/tfwc_rcvr.h
==============================================================================
--- vic/branches/cc/cc/tfwc_rcvr.h	(original)
+++ vic/branches/cc/cc/tfwc_rcvr.h	Sun May  9 02:16:38 2010
@@ -41,8 +41,12 @@
 class TfwcRcvr {
 public:
 	TfwcRcvr();
+
+	// receive AoA
 	void recv_aoa(u_int16_t type, u_int16_t *chunk);
+	// receive RTP data
 	void recv_seqno(u_int16_t seqno);
+
 	// AckVec clone
 	inline u_int16_t getvec(int i) { return tfwcAV[i]; }
 	// ts echo

Modified: vic/branches/cc/cc/tfwc_sndr.h
==============================================================================
--- vic/branches/cc/cc/tfwc_sndr.h	(original)
+++ vic/branches/cc/cc/tfwc_sndr.h	Sun May  9 02:16:38 2010
@@ -44,7 +44,6 @@
 #define TFWC_TIMER_RESET	1
 
 class TfwcSndr;
-class Transmitter;
 
 // re-transmission timer
 class TfwcRtxTimer : public CcTimerHandler {

Modified: vic/branches/cc/rtp/session.cpp
==============================================================================
--- vic/branches/cc/rtp/session.cpp	(original)
+++ vic/branches/cc/rtp/session.cpp	Sun May  9 02:16:38 2010
@@ -450,9 +450,9 @@
 
 void SessionManager::transmit(pktbuf* pb, bool recv_by_ch)
 {
-	//mh_.msg_iov = pb->iov;
-	//	dh_[.net()->send(mh_);
-		//debug_msg("L %d,",pb->layer);
+	// mh_.msg_iov = pb->iov;
+	// dh_[.net()->send(mh_);
+	// debug_msg("L %d,",pb->layer);
 
 	// receive XR before sending
 	if(!recv_by_ch)
@@ -474,9 +474,10 @@
 		// upon every RTP data packet transmission.
 		switch (cc_type_) {
 		case WBCC:
-			ch_[0].send_aoa();	// send ack of ack
+			ch_->send_aoa();	// send ack of ack
 			break;
 		case RBCC:
+			ch_->send_aoa();	// send ack of ack
 			break;
 		}
 	}
@@ -680,64 +681,85 @@
 	u_int16_t *chunks = NULL;
 	u_int16_t num_chunks = 0;
 
-	// i am an RTP data sender
+	// -----------------------------------------------------------------*
+	// i am an RTP data sender                                          *
+	// -----------------------------------------------------------------*
 	if (am_i_sender()) {
 		if(bt == XR_BT_1) {
-			num_chunks = 1;
-			chunks = (u_int16_t *) malloc(num_chunks * sizeof(u_int16_t));
+		num_chunks = 1;
+		chunks = (u_int16_t *) malloc(num_chunks * sizeof(u_int16_t));
 
-			switch (cc_type_) {
-			case WBCC:
-				// this block is used for giving ackofack
-				// set AckofAck
-				chunks[num_chunks-1] = tfwc_sndr_.get_aoa();
-
-				// send_xreport (sender's report)
-				// - just sending ackofack information
-				send_xreport(ch, XR_BT_1, 0, 0, 0, 0, chunks, num_chunks, 0);
-				break;
+		switch (cc_type_) {
+		  case WBCC:
+			// this block is used for giving ackofack
+			chunks[num_chunks-1] = tfwc_sndr_.get_aoa();
+		  break;
+
+		  case RBCC:
+			// this block is used for giving ackofack
+			chunks[num_chunks-1] = tfrc_sndr_.get_aoa();
+			break;
+		  } // switch (cc_type_)
 
-			case RBCC:
-				// for TFRC, no action needed here.
-				break;
-			}
+		  // send_xreport (sender's report)
+		  // - just sending ackofack information
+		  send_xreport(ch, XR_BT_1, 0, 0, 0, 0, chunks, num_chunks, 0);
 		}
 		else if (bt == XR_BT_3) {
 			/*XXX*/
 		} 
-	} 
-	// i am an RTP data receiver
+	}
+	// -----------------------------------------------------------------*
+	// i am an RTP data receiver                                        *
+	// -----------------------------------------------------------------*
 	else {
 		// this block is used for giving ackvec
 		if (bt == XR_BT_1) {
-			switch (cc_type_) {
-			case WBCC:
-				// get the number of required chunks for giving AckVec
-				num_chunks = tfwc_rcvr_.numvec();
-				chunks = (u_int16_t *) 
-					malloc(num_chunks * sizeof(u_int16_t));
+		switch (cc_type_) {
+		  case WBCC:
+		  // get the number of required chunks for giving AckVec
+		  num_chunks = tfwc_rcvr_.numvec();
+		  chunks = (u_int16_t *)malloc(num_chunks * sizeof(u_int16_t));
 			
-				// set/printing chunks
-				//fprintf(stderr, "\t   printing chunks: ");
-				for (int i = 0; i < num_chunks; i++) {
-					chunks[i] = tfwc_rcvr_.getvec(i);
-				//	fprintf(stderr, "[%d:%x] ", i, chunks[i]);
-				} 
-				//fprintf(stderr, "...........%s +%d\n",__FILE__,__LINE__);
-				break;
-
-			case RBCC:
-				break;
-			}
-			// send_xreport (receiver's report)
-			// - sending AckVec
-			send_xreport(ch, XR_BT_1, 0, 0, tfwc_rcvr_.begins(), 
-					tfwc_rcvr_.ends(), chunks, num_chunks, 0);
+		  // set/printing chunks
+		  //fprintf(stderr, "\t   printing chunks: ");
+		  for (int i = 0; i < num_chunks; i++) {
+		  	chunks[i] = tfwc_rcvr_.getvec(i);
+			//	fprintf(stderr, "[%d:%x] ", i, chunks[i]);
+		  } 
+		  //fprintf(stderr, "...........%s +%d\n",__FILE__,__LINE__);
+
+		  // send_xreport (receiver's report)
+		  // - sending AckVec
+		  send_xreport(ch, XR_BT_1, 0, 0, tfwc_rcvr_.begins(), 
+		  tfwc_rcvr_.ends(), chunks, num_chunks, 0);
+		  break;
+
+		  case RBCC:
+		  // get the number of required chunks for giving AckVec
+		  num_chunks = tfrc_rcvr_.numvec();
+		  chunks = (u_int16_t *)malloc(num_chunks * sizeof(u_int16_t));
+
+		  // set/printing chunks
+		  //fprintf(stderr, "\t   printing chunks: ");
+		  for (int i = 0; i < num_chunks; i++) {
+			chunks[i] = tfrc_rcvr_.getvec(i);
+			//	fprintf(stderr, "[%d:%x] ", i, chunks[i]);
+		  }
+		  //fprintf(stderr, "...........%s +%d\n",__FILE__,__LINE__);
+
+		  // send_xreport (receiver's report)
+		  // - sending AckVec
+		  send_xreport(ch, XR_BT_1, 0, 0, tfrc_rcvr_.begins(), 
+		  tfrc_rcvr_.ends(), chunks, num_chunks, 0);
+		  break;
+		  } // switch (cc_type_)
 		}
 		else if (bt == XR_BT_3) {
 			/*XXX*/
 		} 
 	} // end of if (am_i_sender())
+	// -----------------------------------------------------------------*
 }
 
 // New version
@@ -1049,18 +1071,19 @@
 
 		switch (cc_type_) {
 		case WBCC:
-			// pass seqno to tfwc receiver to build up AckVec
-			tfwc_rcvr_.recv_seqno(seqno);
-			fprintf(stderr, "\n\treceived seqno: %d\n\n", seqno);
-
-			// send receiver side XR report (AckVec)
-			ch_->send_ackv();
-			//ch_[0].send_ts_echo();
-			break;
+		  // pass seqno to tfwc receiver to build up AckVec
+		  fprintf(stderr, "\n\treceived seqno: %d\n\n", seqno);
+		  tfwc_rcvr_.recv_seqno(seqno);
+		  break;
 		case RBCC:
-			ch_->send_p();
-			break;
+		  // pass seqno to tfrc receiver to build up AckVec
+		  fprintf(stderr, "\n\treceived seqno: %d\n\n", seqno);
+		  tfrc_rcvr_.recv_seqno(seqno);
+		  break;
 		}
+
+		// send receiver side XR report (AckVec)
+		ch_->send_ackv();
 	}
 	
 	//bp += sizeof(*rh);
@@ -1335,45 +1358,54 @@
 		// parse XR chunks
 		u_int16_t *chunk = (u_int16_t *) ++xr1;
 
-		// i am an RTP data sender, so do the sender stuffs (AoA)
+		// -----------------------------------------------------------------*
+		// i am an RTP data sender (AoA)                                    *
+		// -----------------------------------------------------------------*
 		if (am_i_sender()) {
-			fprintf(stderr, ">>> parse_xr - i_am_sender\n");
-			//sender_xr_info(begin, end, xr1, xrlen);
-			switch (cc_type_) {
+  		  fprintf(stderr, ">>> parse_xr - i_am_sender\n");
+		  fprintf(stderr, "\tincomingXR\tnow: %f\n", recv_ts_);
+		  //sender_xr_info(__FILE__,__LINE__,begin, end, xr1, xrlen);
+		  switch (cc_type_) {
 			case WBCC:
-				fprintf(stderr, "\tincomingXR\tnow: %f\n", recv_ts_);
-				// SO_TIMESTAMP
-				//so_rtime = ch_[0].net()->recv_so_time();
-				//sender_xr_ts_info(so_rtime);
-
-				// TFWC sender (getting AckVec)
-				tfwc_sndr_.recv(xr->BT, begin, end, chunk, recv_ts_, recv_by_ch, pb);
-
-				// we need to call Transmitter::output(pb) to make Ack driven
-				if(recv_by_ch)
-				tfwc_output(recv_by_ch);
-				break;
+			// SO_TIMESTAMP
+			//so_rtime = ch_[0].net()->recv_so_time();
+			//sender_xr_ts_info(so_rtime);
+
+			// TFWC sender (getting AckVec)
+			tfwc_sndr_.recv(xr->BT,begin,end,chunk,recv_ts_,recv_by_ch,pb);
+
+			// we need to call Transmitter::output(pb) to make Ack driven
+			if(recv_by_ch)
+			tfwc_output(recv_by_ch);
+			break;
 
 			case RBCC:
-				break;
-			}
+			// TFRC sender (getting AckVec)
+			tfrc_sndr_.recv(xr->BT,begin,end,chunk,recv_ts_,recv_by_ch,pb);
+
+			if(recv_by_ch)
+			tfrc_output(recv_by_ch);
+			break;
+		  } // switch (cc_type_)
 		}
-		// i am an RTP data receiver, so receive ackofack 
+		// -----------------------------------------------------------------*
+		// i am an RTP data receiver (receive ackofack)                     *
+		// -----------------------------------------------------------------*
 		else {
+			fprintf(stderr, ">>> parse_xr - i_am_receiver\n");
+			receiver_xr_info(__FILE__,__LINE__,chunk);
 			switch (cc_type_) {
+			// TFWC receiver (getting ackofack)
 			case WBCC:
-				fprintf(stderr, ">>> parse_xr - i_am_receiver\n");
-				receiver_xr_info(chunk);
-
-				// TFWC receiver (getting ackofack)
-				tfwc_rcvr_.recv_aoa(xr->BT, chunk);
-				break;
-
+			  tfwc_rcvr_.recv_aoa(xr->BT, chunk);
+			  break;
+			// TFRC receiver
 			case RBCC:
-				// do nothing
-				break;
+			  tfrc_rcvr_.recv_aoa(xr->BT, chunk);
+			  break;
 			}
 		} // end of XR block type 1
+		// -----------------------------------------------------------------*
 	} else {
 		// XXX
 		debug_msg("UNKNOWN RTCP XR Packet: BT:%d\n", xr->BT);

Modified: vic/branches/cc/rtp/session.h
==============================================================================
--- vic/branches/cc/rtp/session.h	(original)
+++ vic/branches/cc/rtp/session.h	Sun May  9 02:16:38 2010
@@ -244,18 +244,15 @@
 	}
 	inline void print_rtp_seqno(pktbuf* pb) {
 	rtphdr* rh = (rtphdr *) pb->data;
-	fprintf(stderr, "\n\tnow: %f\tseqno: %d\n\n",
-		tx_get_now(),ntohs(rh->rh_seqno));
+	fprintf(stderr, "\n\tnow: %f\tseqno: %d\n\n",tx_get_now(),ntohs(rh->rh_seqno));
 	}
 
 	// print sender's XR info
-	inline void sender_xr_info(u_int16_t b, 
-		u_int16_t e, 
-		rtcp_xr_BT_1_hdr* xrh,
-		u_int16_t l) 
+	inline void sender_xr_info(const char* str, const int i,
+	u_int16_t b, u_int16_t e, rtcp_xr_BT_1_hdr* xrh, u_int16_t l) 
 	{
-		debug_msg("beg:%d, end:%d, xr1len:%d (xrlen:%d)\n",
-		b,e,ntohs(xrh->xr_len),l);
+	fprintf(stderr, "  [%s +%d] beg:%d, end:%d, xr1len:%d (xrlen:%d)\n",
+		str, i, b, e, ntohs(xrh->xr_len),l);
 	}
 	// print sender's XR info
 	inline void sender_xr_ts_info(double ts) {
@@ -263,8 +260,8 @@
 		recv_ts_, ts, recv_ts_-ts);
 	}
 	// print receiver's XR info
-	inline void receiver_xr_info(u_int16_t *c) {
-		debug_msg("chunk[0]:%d\n", ntohs(c[0]));
+	inline void receiver_xr_info(const char* str, const int i, u_int16_t *c) {
+	fprintf(stderr, "  [%s +%d] chunk[0]:%d\n",str, i, ntohs(c[0]));
 	}
 	// print parse XR banner
 	inline void parse_xr_banner_top() {

Modified: vic/branches/cc/rtp/transmitter.cpp
==============================================================================
--- vic/branches/cc/rtp/transmitter.cpp	(original)
+++ vic/branches/cc/rtp/transmitter.cpp	Sun May  9 02:16:38 2010
@@ -244,114 +244,114 @@
 	// window-based congestion control (TFWC)
 	//
 	case WBCC:
-		// pb is empty - try sending a packet
-		if(is_buf_empty_) {
-			if (head_ != 0) {
-				tail_->next = pb;
-				tail_ = pb;
-			} else
-				tail_ = head_ = pb;
-			pb->next = 0;
-			tfwc_output();
-			is_buf_empty_ = false;
-		} 
-		// if not, check if cwnd allows send this packet
-		else {
-			if (head_ != 0) {
-				tail_->next = pb;
-				tail_ = pb;
-			} else
-				tail_ = head_ = pb;
-			pb->next = 0;
-			tfwc_output(pb);
-		}
-		break;
+	  // pb is empty - try sending a packet
+  	  if(is_buf_empty_) {
+		if (head_ != 0) {
+		  tail_->next = pb;
+		  tail_ = pb;
+		} else
+		  tail_ = head_ = pb;
+		pb->next = 0;
+		tfwc_output();
+		is_buf_empty_ = false;
+	  } 
+	  // if not, check if cwnd allows send this packet
+	  else {
+		if (head_ != 0) {
+		  tail_->next = pb;
+		  tail_ = pb;
+		} else
+		  tail_ = head_ = pb;
+		pb->next = 0;
+		tfwc_output(pb);
+	  }
+	  break;
 
 	//
 	// rate-based congestion control (TFRC)
 	//
 	case RBCC:
-		// pb is empty
-		if(is_buf_empty_) {
-			if (head_ != 0) {
-				tail_->next = pb;
-				tail_ = pb;
-			} else
-				tail_ = head_ = pb;
-			pb->next = 0;
-			cc_tfrc_output();
-			is_buf_empty_ = false;
-		}
-		// pb is not emtpy
-		else {
-			if (head_ != 0) {
-				tail_->next = pb;
-				tail_ = pb;
-			} else
-				tail_ = head_ = pb;
-			pb->next = 0;
-		}
-		break;
+	  // pb is empty
+	  if(is_buf_empty_) {
+		if (head_ != 0) {
+		  tail_->next = pb;
+		  tail_ = pb;
+		} else
+		  tail_ = head_ = pb;
+		pb->next = 0;
+		tfrc_output();
+		is_buf_empty_ = false;
+	  }
+	  // pb is not emtpy
+	  else {
+		if (head_ != 0) {
+		  tail_->next = pb;
+		  tail_ = pb;
+		} else
+		  tail_ = head_ = pb;
+		pb->next = 0;
+		tfrc_output(pb);
+	  }
+	  break;
 
 	//
 	// without congestion control
 	//
 	case NOCC:
 	default:
-		// CC is not active, so just go for the normal operation
-		if (!busy_) {
-			double delay = txtime(pb);
-			nextpkttime_ = gettimeofday_secs() + delay;
-			output(pb);
-			/*
-			 * emulate a transmit interrupt --
-			 * assume we will have more to send.
-			 */
-			msched(int(delay * 1e-3));
-			busy_ = 1;
-		} else {
-			if (head_ != 0) {
-				tail_->next = pb;
-				tail_ = pb;
-			} else
-				tail_ = head_ = pb;
-			pb->next = 0;
-		}
+	  // CC is not active, so just go for the normal operation
+	  if (!busy_) {
+		double delay = txtime(pb);
+		nextpkttime_ = gettimeofday_secs() + delay;
+		output(pb);
+		/*
+		 * emulate a transmit interrupt --
+		 * assume we will have more to send.
+		 */
+		msched(int(delay * 1e-3));
+		busy_ = 1;
+	  } else {
+		if (head_ != 0) {
+		  tail_->next = pb;
+		  tail_ = pb;
+		} else
+		  tail_ = head_ = pb;
+		pb->next = 0;
+	  }
 	} // switch (cc_type)
 }
 
 void Transmitter::tfwc_output(pktbuf* pb) 
 {
-	//cc_output_banner_top();
-	
+	//cc_output_banner_top("tfwc");
 	// byte mode? or packet mode?
 	switch (cwnd_mode_) {
 	case BYM:
 	{
-		int len = 0;
-		if(pb->len < tfwc_sndr_.b_magic() - len) {
-			len += pb->len;
-			// move head pointer
-			head_ = pb->next;
-			// call Transmitter::output_data_only w/ XR reception
-			output_data_only(pb, XR_RECV);
-		}
+	  int len = 0;
+	  if(pb->len < tfwc_sndr_.b_magic() - len) {
+		len += pb->len;
+		// move head pointer
+		head_ = pb->next;
+		// call Transmitter::output_data_only w/ XR reception
+		output_data_only(pb, XR_RECV);
+	  }
 	}
 	break;
 	case PKM:
 	{
-		// pb is not null, hence parse it.
-		rtphdr* rh = (rtphdr *) pb->data;
+	  // pb is not null, hence parse it.
+	  rtphdr* rh = (rtphdr *) pb->data;
 
-		if (ntohs(rh->rh_seqno) <= tfwc_sndr_.magic() + tfwc_sndr_.jacked()) {
-			//debug_msg("cwnd: %d\n", tfwc_sndr_.magic());
-			//debug_msg("jack: %d\n", tfwc_sndr_.jacked());
+	  if (ntohs(rh->rh_seqno) <= tfwc_sndr_.magic() + tfwc_sndr_.jacked()) {
+		//debug_msg("cwnd: %d\n", tfwc_sndr_.magic());
+		//debug_msg("jack: %d\n", tfwc_sndr_.jacked());
 			
-			// move head pointer
-			head_ = pb->next;
-			// call Transmitter::output_data_only w/ XR reception
-			output_data_only(pb, XR_RECV);
-		}
+		// move head pointer
+		head_ = pb->next;
+		// call Transmitter::output_data_only w/ XR reception
+		output_data_only(pb, XR_RECV);
+	  }
 	}
 	break;
 	} // switch (cwnd_mode_)
@@ -380,45 +380,45 @@
 	switch (cwnd_mode_) {
 	case BYM:
 	{
-		int len = 0;
-		while(pb->len < tfwc_sndr_.b_magic() - len) {
-			len += pb->len;
-			// move head pointer
-			head_ = pb->next;
-			// call Transmitter::output(pb)
-			output(pb, recv_by_ch);
-
-			if (head_ != 0)
-				pb = head_;
-			else
-				break;
-		}
+	  int len = 0;
+	  while(pb->len < tfwc_sndr_.b_magic() - len) {
+		len += pb->len;
+		// move head pointer
+		head_ = pb->next;
+		// call Transmitter::output(pb)
+		output(pb, recv_by_ch);
+
+		if (head_ != 0)
+			pb = head_;
+		else
+			break;
+	  }
 	}
 	break;
 	case PKM:
 	{
-		// pb is not null, hence parse it.
-		rtphdr* rh = (rtphdr *) pb->data;
+	  // pb is not null, hence parse it.
+	  rtphdr* rh = (rtphdr *) pb->data;
 
-		// while packet seqno is within "cwnd + jack", send that packet
-		while (ntohs(rh->rh_seqno) <= tfwc_sndr_.magic() + tfwc_sndr_.jacked()) {
-			//debug_msg("cwnd: %d\n", tfwc_sndr_.magic());
-			//debug_msg("jack: %d\n", tfwc_sndr_.jacked());
-
-			// move head pointer
-			head_ = pb->next;
-			// call Transmitter::output(pb)
-			output(pb, recv_by_ch);
-
-			// if the moved head pointer is not null, parse packet buffer.
-			// otherwise, break while statement.
-			if (head_ != 0) {
-				pb = head_;
-				rh = (rtphdr *) pb->data;
-			} else {
-				break;
-			}
-		} // end while ()
+	  // while packet seqno is within "cwnd + jack", send that packet
+	  while (ntohs(rh->rh_seqno) <= tfwc_sndr_.magic() + tfwc_sndr_.jacked()) {
+		//debug_msg("cwnd: %d\n", tfwc_sndr_.magic());
+		//debug_msg("jack: %d\n", tfwc_sndr_.jacked());
+
+		// move head pointer
+		head_ = pb->next;
+		// call Transmitter::output(pb)
+		output(pb, recv_by_ch);
+
+		// if the moved head pointer is not null, parse packet buffer.
+		// otherwise, break while statement.
+		if (head_ != 0) {
+			pb = head_;
+			rh = (rtphdr *) pb->data;
+		} else {
+			break;
+		}
+	  } // end while ()
 	}
 	break;
 	} // switch (cwnd_mode_)
@@ -452,8 +452,40 @@
 /*
  * main TFRC CC output
  */
-void Transmitter::cc_tfrc_output() {
-	// TBA
+void Transmitter::tfrc_output(pktbuf* pb) {
+	cc_output_banner_top("tfrc");
+	// move head pointer
+	head_ = pb->next;
+	// call Transmitter::output_data_only w/ XR reception
+	output_data_only(pb, XR_RECV);
+	cc_output_banner_bottom();
+}
+
+void Transmitter::tfrc_output(bool recv_by_ch) {
+	cc_output_banner_top("tfrc");
+	// head of the RTP data packet buffer
+	pktbuf* pb = head_;
+
+	// if pb is null, then set the next available packet as the first packet of
+	// the packet buffer. and then, return - i.e., do not try sending packets.
+	if (pb == 0) {
+		is_buf_empty_ = true;
+		return;
+	}
+
+	while ( pb != 0) {
+		// move head pointer
+		head_ = pb->next;
+		// call Transmitter::output(pb)
+		output(pb, recv_by_ch);
+
+		if (head_ != 0) {
+			pb = head_;
+		} else {
+			break;
+		}
+	}
+	cc_output_banner_bottom();
 }
 
 void Transmitter::timeout()

Modified: vic/branches/cc/rtp/transmitter.h
==============================================================================
--- vic/branches/cc/rtp/transmitter.h	(original)
+++ vic/branches/cc/rtp/transmitter.h	Sun May  9 02:16:38 2010
@@ -100,10 +100,13 @@
 	void flush();
 	void send(pktbuf*);
 	inline bool is_cc_on() { return is_cc_active_; }
+	// TFWC output
 	virtual void tfwc_output(bool recv_by_ch=0);
 	virtual void tfwc_output(pktbuf*);
 	virtual void cc_tfwc_trigger(pktbuf*);
-	void cc_tfrc_output();
+	// TFRC output
+	virtual void tfrc_output(bool recv_by_ch=0);
+	virtual void tfrc_output(pktbuf*);
 
 	/*
 	 * Buffer allocation hooks.



More information about the Sumover-dev mailing list