[Sumover-dev] [svn commit] r4487 - vic/branches/cc/rtp
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Wed Jul 22 15:31:26 BST 2009
Author: soohyunc
Date: Wed Jul 22 15:31:26 2009
New Revision: 4487
Modified:
vic/branches/cc/rtp/session.cpp
vic/branches/cc/rtp/session.h
vic/branches/cc/rtp/transmitter.cpp
Log:
This is joint work with Piers O'Hanlon and Soo-Hyun Choi
o Added ECN marking bit using RTCP XR report
o new version of sending XR reports (more generic version to be flexible)
o modified parse_xr_records()
o moved cc_output() from session.cpp to transmitter.cpp
Modified: vic/branches/cc/rtp/session.cpp
==============================================================================
--- vic/branches/cc/rtp/session.cpp (original)
+++ vic/branches/cc/rtp/session.cpp Wed Jul 22 15:31:26 2009
@@ -489,14 +489,14 @@
{
// RTCP XR (Loss RLE Report Block)
// (it is XR_BT_1 defined in rtp/rtp.h)
- send_xreport(ch, XR_BT_1, 0);
+ build_xreport(ch, XR_BT_1);
}
void SessionManager::build_ts_pkt(CtrlHandler* ch)
{
// RTCP XR (Packet Receipt Times Report Block)
// (it is XR_BT_3 defined in rtp/rtp.h)
- send_xreport(ch, XR_BT_3, 0);
+ build_xreport(ch, XR_BT_3);
}
u_char* SessionManager::build_sdes_item(u_char* p, int code, Source& s)
@@ -604,15 +604,24 @@
int pad = 4 - (len & 3);
while( --pad >= 0 )
*p++ = 0;
- len = p - (u_char*)rh;
+ len = p - (u_char*)rh;
// set the length now that it's known
- rh->rh_len = htons((len >> 2) - 1);
+ rh->rh_len = htons((len >> 2) - 1);
return (len);
}
-/*void SessionManager::send_report()
+void SessionManager::send_ECNXreport(CtrlHandler* ch,
+ u_int8_t tos, u_int16_t begin_seq)
+{
+ u_int16_t chunk = (tos & 0x03) << 14;
+ send_Xreport(ch, XR_BT_1, XR_BT_ECN, 0,
+ begin_seq, begin_seq, &chunk, 1, 0);
+}
+
+/*
+void SessionManager::send_report()
{
send_report(0);
}
@@ -620,7 +629,8 @@
void SessionManager::send_bye()
{
send_report(1);
-}*/
+}
+*/
// SessionManager is no longer used as Timer - Each
// CtrlHandler has its own Timer which calls this;
@@ -632,82 +642,29 @@
/*
* Send an RTP extended report packet.
*/
-void SessionManager::send_xreport(CtrlHandler* ch, int bt, int bye)
+void SessionManager::build_xreport(CtrlHandler* ch, int bt)
{
- UNUSED(bye);
-
- SourceManager& sm = SourceManager::instance();
- Source& s = *sm.localsrc();
- rtcphdr* rh = (rtcphdr*)pktbuf_;
- rh->rh_ssrc = s.srcid();
- int flags = RTP_VERSION << 14; // RTCP flags
- int layer = ch - ch_; //LLL
- Source::Layer& sl = s.layer(layer);
- timeval now = unixtime();
- sl.lts_ctrl(now);
-
- // set RTCP flag to XR packet
- flags |= RTCP_PT_XR;
-
-
- // declare XR packet
- rtcp_xr_BT_1_hdr* xr = (rtcp_xr_BT_1_hdr*)(rh + 1);
-
- // number of XR block contents (initialization)
- int num_ssrc; // number of ssrc entry
- int num_begins; // number of begin_seq entry
- int num_ends; // number of end_seq entry
- int num_chunks; // number of block chunks
-
- // declare XR report block
- // (type specific report block)
- u_char *rb;
-
- int xrssrc; // it is currently unused
+ printf("\tentering build_xreport().................. %s +%d\n",
+ __FILE__,__LINE__);
+ u_int16_t num_chunks;
+ u_int16_t *chunks;
// i am an RTP data sender, so i convey a packet seqno and ackofack
if (am_i_sender()) {
// this block is used for giving seqno and ackofack
if(bt == XR_BT_1) {
- debug_msg("About to send RTCP XR: AofA\n");
- // number of block entries
- //num_ssrc = 1;
- //num_begins = 1;
- //num_ends = 1;
+ printf("\t>> about to send RTCP XR (seqno, AoA)\n");
+ // get the number of chunks (currently 1 chunk)
num_chunks = 1;
-
- // set XR block flags (block type and length)
- //xr->xr_flags = htons(XR_BT_1 << 8);
- xr->BT = XR_BT_1;
- xr->xr_flags.rsvd = 0x00;
- xr->xr_flags.T = 0x00;
-
- // allocate report block in memory
- //rb = (u_char *) malloc(sizeof(xr) + num_ssrc*4
- // + (num_begins + num_ends + num_chunks)*2);
-
- // set report block entry pointer
- //rtcp_xr_BT_1_hdr *ent = (rtcp_xr_BT_1_hdr *) (sizeof(xr) + rb);
-
- // ssrc of XR source (currently unused)
- xrssrc = 255;
- //ent[0] = xrssrc;
- xr->ssrc = htonl(xrssrc);
-
- // get current RTP data packet seqno from TfwcSndr
- //ent[1] = 0; ent[1] |= htons(tfwc_sndr_get_seqno());
- xr->begin_seq = htons(tfwc_sndr_get_seqno());
- //ent[1] <<= 16; ent[1] |= htons(tfwc_sndr_get_seqno() + 1);
- xr->end_seq = htons(tfwc_sndr_get_seqno() + 1);
-
- debug_msg("Sending beg_seq: %d, end: %d\n",ntohs(xr->begin_seq),ntohs(xr->end_seq) );
-
- // set ack of ack
- //ent[2] = 0; ent[2] |= htons(tfwc_sndr_get_aoa()); ent[2] <<= 16;
- u_int16_t *chunks = (u_int16_t *) (xr + 1);
- chunks[0] = htons(tfwc_sndr_get_aoa());
-
- //debug_msg(" SeqNo: %d\n", tfwc_sndr_get_seqno());
+ chunks = (u_int16_t *)malloc(num_chunks * sizeof(u_int16_t));
+ // set AckofAck
+ chunks[num_chunks-1] = tfwc_sndr_get_aoa();
+
+ // send_Xreport (sender's report)
+ // Note: begin_seq (== tfwc_sndr_get_seqno()) is
+ // actually the seqno of the last sent data packet
+ send_Xreport(ch, XR_BT_1, 0, 0, tfwc_sndr_get_seqno(),
+ tfwc_sndr_get_seqno() + 1, chunks, num_chunks, 0);
}
else if (bt == XR_BT_3) {
/*XXX*/
@@ -717,74 +674,37 @@
else {
// this block is used for giving ackvec
if (bt == XR_BT_1) {
- // number of block entries
- //num_ssrc = 1;
- //num_begins = 1;
- //num_ends = 1;
-
- // set XR block type
- //xr->xr_flags = htons(XR_BT_1 << 8);
- xr->BT = XR_BT_1;
-
- // number of AckVec array
+ printf("\t>> about to send RTCP XR (AckVec)\n");
+ // get the number of chunks
num_chunks = tfwc_rcvr_numvec();
- // Added second check as it seems that sometimes num_chunks >> 1 ???
- if (num_chunks<1 || num_chunks> 128 ) num_chunks=1;
+ if (num_chunks > 4 ) num_chunks = 1;
+
+ // declare chunks
+ chunks = (u_int16_t *)malloc(num_chunks * sizeof(u_int16_t));
- // allocate report block in memory
- //rb = (u_char *) malloc(sizeof(xr) + num_ssrc
- // + num_begins + num_ends + num_chunks);
-
- // set report block entry pointer
- //u_int32_t *ent = (u_int32_t *) (sizeof(xr) + rb);
-
- // ssrc of XR source (currently unused)
- xrssrc = 0;
- //ent[0] = xrssrc;
- xr->ssrc = htonl(xrssrc);
-
- // begin/end for AckVec
- //ent[1] = 0; ent[1] |= htons(tfwc_rcvr_begins());
- xr->begin_seq = htons(tfwc_rcvr_begins());
- //ent[1] <<= 16; ent[1] |= htons(tfwc_rcvr_ends());
- xr->end_seq = htons(tfwc_rcvr_ends());
-
- // clone AckVec from TfwcRcvr
- u_int16_t *chunks = (u_int16_t *) (xr + 1);
-
- debug_msg("About to send RTCP XR AckVec(%d chunks):",num_chunks);
- for (int i = 0; i <= num_chunks; i++) {
- chunks[i] = htons(tfwc_rcvr_getvec(i));
- printf("%d:%x,",i,chunks[i]);
- }printf("\n");
+ // printing chunks
+ printf("\t printing chunks: ");
+ for (int i = 0; i < num_chunks; i++) {
+ chunks[i] = tfwc_rcvr_getvec(i);
+ printf("[%d:%x] ", i, chunks[i]);
+ } printf("...........%s +%d\n",__FILE__,__LINE__);
+
+ // send_Xreport (receiver's report)
+ send_Xreport(ch, XR_BT_1, 0, 0, tfwc_rcvr_begins(),
+ tfwc_rcvr_ends(), chunks, num_chunks, 0);
}
else if (bt == XR_BT_3) {
/*XXX*/
}
} // end of if (am_i_sender())
-
- //++xr;
-
- // XR report block length in bytes
- int xrlen = sizeof(rtcp_xr_BT_1_hdr) + num_chunks*2;
- // Convert XR report block length to multiples of 32 bit-words minus 1
- xr->xr_len = htons((xrlen >> 2) - 1);
-
- // RTCP header flags (this is not the XR header flags)
- rh->rh_flags = htons(flags);
-
- // RTCP packet length
- int len = (u_char *) ++xr + num_chunks*2 - pktbuf_;
- debug_msg("RTCP XR: len: %d, xrlen=%d\n", len, xrlen);
- len = sizeof(rtcphdr) + sizeof(rtcp_xr_BT_1_hdr) + num_chunks*2;
- rh->rh_len = htons((len >> 2) - 1);
-
- // send XR report block
- ch->send(pktbuf_, len);
}
// New version
-void SessionManager::send_Xreport(CtrlHandler* ch, uint8_t bt, uint8_t rsvd, uint8_t thin, uint16_t begin_seq, uint16_t end_seq, uint16_t *chunks, uint16_t num_chunks, uint32_t xrssrc)
+void SessionManager::send_Xreport(CtrlHandler* ch, u_int8_t bt,
+ u_int8_t rsvd, u_int8_t thin,
+ u_int16_t begin_seq, u_int16_t end_seq,
+ u_int16_t *chunks, u_int16_t num_chunks,
+ u_int32_t xrssrc)
{
SourceManager& sm = SourceManager::instance();
Source& s = *sm.localsrc();
@@ -795,18 +715,20 @@
Source::Layer& sl = s.layer(layer);
timeval now = unixtime();
sl.lts_ctrl(now);
+ int i;
// set RTCP flag to XR packet
flags |= RTCP_PT_XR;
+ // check XR block type
switch (bt) {
- case XR_BT_1:
- case XR_BT_3:
- case XR_BT_ECN:
- break;
- default:
- debug_msg("ERROR: Unknown XR packet type: %d\n",bt);
- return;
+ case XR_BT_1:
+ case XR_BT_3:
+ case XR_BT_ECN:
+ break;
+ default:
+ debug_msg("ERROR: Unknown XR packet type: %d\n", bt);
+ return;
}
// set xr pointer to XR packet
@@ -818,27 +740,41 @@
xr->xr_flags.T = thin;
xr->ssrc = htonl(xrssrc);
- // get current RTP data packet seqno from TfwcSndr
+ // get current RTP data packet seqno
xr->begin_seq = htons(begin_seq);
xr->end_seq = htons(end_seq);
- debug_msg("About to send RTCP XR: %d, beg_seq: %d, end: %d\n",bt,ntohs(xr->begin_seq),ntohs(xr->end_seq));
+ printf("\t>> sending RTCP XR: BT:%d, begin:%d, end:%d\n",
+ bt, ntohs(xr->begin_seq), ntohs(xr->end_seq));
+ // XXX XR num_chunks too large??
if (num_chunks > 512) {
- debug_msg("ERROR num_chunks too large:%d\n",num_chunks);
- return;
+ debug_msg("ERROR: num_chunks too large:%d \
+ - NOT sending pkt\n", num_chunks);
+ num_chunks = 1;
+ //return;
}
-
- debug_msg("About to send RTCP XR AckVec(%d chunks):",num_chunks);
+
+ // declare XR report chunks
u_int16_t *xrchunks = (u_int16_t *) (xr + 1);
- for (int i=0; i<num_chunks; i++) {
- printf("%d:%x,",i,chunks[i]);
- xrchunks[i] = htons(chunks[i]);
+
+ // copy XR chunks and printing
+ printf("\t printing chunks: ");
+ for (i = 0; i < num_chunks; i++) {
+ printf("[%d:%x] ", i, chunks[i]);
+ xrchunks[i] = htons(chunks[i]);
+ } printf("...........%s +%d\n",__FILE__,__LINE__);
+
+ // if num_chunks is odd then increment it by one as packet size is
+ // measured in 32-bits pieces. And add Null chunk onto the end.
+ if (num_chunks % 2) {
+ num_chunks++;
+ xrchunks[i] = 0;
}
// XR report block length in bytes
- int xrlen = sizeof(rtcp_xr_BT_1_hdr) + num_chunks*2;
-
+ int xrlen = sizeof(rtcp_xr_BT_1_hdr) + (num_chunks * 2);
+
// Convert XR report block length to multiples of 32 bit-words minus 1
xr->xr_len = htons((xrlen >> 2) - 1);
@@ -846,9 +782,9 @@
rh->rh_flags = htons(flags);
// RTCP packet length
- int len = (u_char *) ++xr + num_chunks*2 - pktbuf_;
- debug_msg("RTCP XR: len: %d, xrlen=%d\n", len, xrlen);
- len = sizeof(rtcphdr) + sizeof(rtcp_xr_BT_1_hdr) + num_chunks*2;
+ int len = (u_char *) ++xr + (num_chunks * 2) - pktbuf_;
+ printf("\t RTCP XR: len: %d, xrlen: %d\n", len, xrlen);
+ len = sizeof(rtcphdr) + sizeof(rtcp_xr_BT_1_hdr) + (num_chunks * 2);
rh->rh_len = htons((len >> 2) - 1);
// send XR report block
@@ -1117,6 +1053,8 @@
pb->release();
return;
}
+ //send_ECNXreport(ch_,dh_[0].net()->recv_tos(),rh->rh_seqno);
+
/* inform this source of the mbus */
s->mbus(&mb_);
@@ -1312,9 +1250,9 @@
}
void SessionManager::parse_xr_records(u_int32_t ssrc, rtcp_xr* xr, int cnt,
- const u_char* ep, Address & addr)
+ const u_char* ep, Address & addr)
{
- rtcp_xr_BT_1_hdr *xr1;
+ printf("~~~~~~~~~~~~~~~~~~entering parse_xr_records()~~~~~~~~~~~~~~~~~~\n");
UNUSED(ssrc);
UNUSED(cnt);
UNUSED(ep);
@@ -1324,49 +1262,65 @@
u_int16_t xrlen = ntohs(xr->xr_len);
// XR repport block
- //u_int32_t *rb = (u_int32_t *) malloc(xrlen);
-
- if ( xr->BT == XR_BT_1 ) {
- xr1 = ( rtcp_xr_BT_1_hdr *) xr;
+ rtcp_xr_BT_1_hdr *xr1;
- // parse XR information (xrssrc, begin, end)
- u_int32_t xrssrc = ntohl(xr1->ssrc); UNUSED(xrssrc);
- u_int16_t begin = ntohs(xr1->begin_seq);
- u_int16_t end = ntohs(xr1->end_seq);
-
- // declare chunks
- int num_chunks = 0;
- u_int16_t *chunk = (u_int16_t *) ++xr1;
-
- // num_chunks = xrlen - sizeof(xr_BT_1_hr)[=3] + 1(countering -1 in hdr calc)
- num_chunks = (xrlen - 2)*2;
- //chunk = (u_int32_t *) malloc(sizeof(u_int32_t) * num_chunks);
-
- // parse chunks information (AckVec)
- //for (int i = 0; i < num_chunks; i++)
- // chunk[i] = rb[i+2];
-
- // i am an RTP data sender, so do the sender stuffs
- if (am_i_sender()) {
- // parse XR chunks
- printf("\tparse_xr - i_am_sender \n");
- printf("num_chunks:%d, beg:%d, end:%d\n",num_chunks, begin, end);
- tfwc_sndr_recv(xr->BT, begin, end, chunk, num_chunks);
- // we need to call Transmitter::output(pb) to make Ack driven
- cc_output();
- }
- // i am an RTP data receiver, so do the receiver stuffs
- else {
- printf("\tparse_xr - i_am_recvr \n");
- printf("num_chunks:%d, beg:%d, end:%d\n",num_chunks, begin, end);
- // parse XR chunks
- tfwc_rcvr_recv(xr->BT, begin, chunk, num_chunks);
- // send receiver side XR report
- ch_[0].send_ackv();
- //ch_[0].send_ts_echo();
- }
- } else
- debug_msg("UNKNOWN RTCP-XR packet:BT:%d\n",xr->BT);
+ if ( xr->BT == XR_BT_1 && xr->xr_flag == 0 ) {
+ // XR block type 1
+ xr1 = (rtcp_xr_BT_1_hdr *) xr;
+
+ // parse XR information (xrssrc, begin, end)
+ u_int32_t xrssrc = ntohl(xr1->ssrc); UNUSED(xrssrc);
+ u_int16_t begin = ntohs(xr1->begin_seq);
+ u_int16_t end = ntohs(xr1->end_seq);
+
+ // i am an RTP data sender, so do the sender stuffs (AoA)
+ if (am_i_sender()) {
+ printf(">>> parse_xr - i_am_sender\n");
+ // num_chunks = xrlen - sizeof(xr_BT_1_hr)[=3*32bit] +
+ // 1 (counteracting -1 in hdr calc)
+ //int num_chunks = (xrlen + 1 - 3) * 2;
+ //printf("\tnum_chunks:%d, beg:%d, end:%d\n", num_chunks, begin, end);
+
+
+ // use seqno space to work out length
+ // (add one to num unless exactly divisible by 16
+ // - so it is large enough to accommodate all the bits )
+ int num_chunks = (end - begin)/16 + ((end - begin)%16 > 0);
+
+ // this is just a double check - it should be the same as
+ // the above num_chunks calculation
+ printf(" [%s +%d] num_chunks:%d, beg:%d, end:%d, xr1len:%d (xrlen:%d)\n",
+ __FILE__,__LINE__, num_chunks, begin, end, ntohs(xr1->xr_len), xrlen);
+
+ // parse XR chunks
+ u_int16_t *chunk = (u_int16_t *) ++xr1;
+ tfwc_sndr_recv(xr->BT, begin, end, chunk, num_chunks);
+
+ // we need to call Transmitter::output(pb) to make Ack driven
+ cc_output();
+ }
+ // i am an RTP data receiver, so do the receiver stuffs (build AckVec)
+ else {
+ int num_chunks = 1;
+ printf(">>> parse_xr - i_am_receiver\n");
+ printf(" [%s +%d] num_chunks:%d, beg:%d, end:%d\n",
+ __FILE__,__LINE__,num_chunks, begin, end);
+
+ // parse XR chunks
+ u_int16_t *chunk = (u_int16_t *) ++xr1;
+ printf(" [%s +%d] begin:%d, chunk[0]:%d\n",
+ __FILE__,__LINE__, begin, chunk[0]);
+ tfwc_rcvr_recv(xr->BT, begin, chunk, num_chunks);
+
+ // send receiver side XR report
+ ch_[0].send_ackv();
+ //ch_[0].send_ts_echo();
+ } // end of XR block type 1
+ } else {
+ // XXX
+ debug_msg("UNKNOWN RTCP XR Packet: BT:%d\n", xr->BT);
+ }
+ printf("-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
}
/*void SessionManager::cc_output()
@@ -1434,14 +1388,14 @@
{
// RTCP XR (block type 1)
// this block contains ackvec
- send_xreport(ch, XR_BT_1, 0);
+ build_xreport(ch, XR_BT_1);
}
void SessionManager::build_ts_echo_pkt(CtrlHandler* ch)
{
// RTCP XR (block type 3)
// this block contains timestamp echo
- send_xreport(ch, XR_BT_3, 0);
+ build_xreport(ch, XR_BT_3);
}
int SessionManager::sdesbody(u_int32_t* p, u_char* ep, Source* ps,
Modified: vic/branches/cc/rtp/session.h
==============================================================================
--- vic/branches/cc/rtp/session.h (original)
+++ vic/branches/cc/rtp/session.h Wed Jul 22 15:31:26 2009
@@ -138,8 +138,12 @@
virtual inline void send_bye() { send_report(&ch_[0], 1); }
// virtual void send_report();
virtual void send_report(CtrlHandler*, int bye, int app = 0);
- virtual void send_xreport(CtrlHandler*, int bt, int bye);
- virtual void send_Xreport(CtrlHandler* ch, uint8_t bt, uint8_t rsvd, uint8_t thin, uint16_t begin_seq, uint16_t end_seq, uint16_t *chunks, uint16_t num_chunks, uint32_t xrssrc);
+ virtual void build_xreport(CtrlHandler*, int bt);
+ virtual void send_Xreport(CtrlHandler* ch,
+ u_int8_t bt, u_int8_t rsvd, u_int8_t thin,
+ u_int16_t begin_seq, u_int16_t end_seq,
+ u_int16_t *chunks, u_int16_t num_chunks,
+ u_int32_t xrssrc);
void build_aoa_pkt(CtrlHandler* ch);
void build_ts_pkt(CtrlHandler* ch);
@@ -156,6 +160,7 @@
virtual int check_format(int fmt) const = 0;
virtual void transmit(pktbuf* pb);
void send_report(int bye);
+ void send_ECNXreport(CtrlHandler* ch, u_int8_t tos, u_int16_t begin_seq);
int build_bye(rtcphdr* rh, Source& local);
u_char* build_sdes_item(u_char* p, int code, Source&);
int build_sdes(rtcphdr* rh, Source& s);
Modified: vic/branches/cc/rtp/transmitter.cpp
==============================================================================
--- vic/branches/cc/rtp/transmitter.cpp (original)
+++ vic/branches/cc/rtp/transmitter.cpp Wed Jul 22 15:31:26 2009
@@ -218,9 +218,6 @@
if (is_cc_on()) {
// if it is the very first packet, just send it.
if(is_first_) {
- //tfwc_sndr_send(pb);
- //debug_msg("sending RTP packet\n");
- //output(pb);
if (head_ != 0) {
tail_->next = pb;
tail_ = pb;
@@ -260,60 +257,65 @@
tail_ = head_ = pb;
pb->next = 0;
}
- } // if (is_cc_active_)
+ } // if (is_cc_on())
}
+/*
+ * main CC output routines
+ */
void Transmitter::cc_output()
{
- printf("\tentering cc_output()\n");
- pktbuf* pb = head_; // head of the packet queue
- rtphdr* rh; // declare rtp header
-
- // if pb is not 0, then parse rtp header
- if (pb == 0) {
- is_first_ = true;
- return;
- }
-
- printf("\tThere is a packet available to send cc_output()\n");
-
- rh = (rtphdr *) pb->data;
-
- // cwnd value
- int magic = (int) tfwc_magic();
- debug_msg("cwnd: %d\n", magic);
-
- // just acked seqno
- int jack = (int) tfwc_sndr_jacked();
- debug_msg("jack: %d\n", jack);
-
- debug_msg("seqno: %d\n", ntohs(rh->rh_seqno));
- // while packet seqno is within "cwnd + jack", send that packet
- while (ntohs(rh->rh_seqno) <= magic + jack) {
- debug_msg("Sending RTP pkt seqno: %d\n", ntohs(rh->rh_seqno));
- // record seqno and timestamp at TfwcSndr side
- tfwc_sndr_send(pb);
-
- // declare the next packet
- //pktbuf* nx = pb->next;
- head_ = pb->next;
-
- // call Transmitter::output(pb)
- output(pb);
-
- // move packet pointer
- //pb = nx;
-
- // if pb is not 0,
- // then move head pointer and parse rtp header
- if (head_ != 0) {
- pb = head_;
- //head_ = pb;
- rh = (rtphdr *) pb->data;
- } else {
- break;
+ printf("\t------------entering cc_output()------------\n");
+ printf("\t| |\n");
+ printf("\tV V\n");
+
+ // head of the RTP data packet buffer (pb)
+ 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_first_ = true;
+ printf("\t=========== PACKET NOT AVAILABLE ===========\n\n");
+ return;
+ }
+ printf("\tthere are packets available to send in cc_output()\n");
+
+ // pb is not null, hence parse it.
+ rtphdr* rh = (rtphdr *) pb->data;
+
+ // cwnd value
+ int magic = (int) tfwc_magic();
+ debug_msg("cwnd: %d\n", magic);
+
+ // just acked seqno
+ int jack = (int) tfwc_sndr_jacked();
+ debug_msg("jack: %d\n", jack);
+ debug_msg("seqno: %d\n", ntohs(rh->rh_seqno));
+
+ // while packet seqno is within "cwnd + jack", send that packet
+ while (ntohs(rh->rh_seqno) <= magic + jack) {
+ // record seqno and timestamp at TfwcSndr side
+ tfwc_sndr_send(pb);
+
+ // move head pointer
+ head_ = pb->next;
+
+ // call Transmitter::output(pb)
+ output(pb);
+
+ // 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
+ } // end while ()
+ printf("\t^ ^\n");
+ printf("\t| |\n");
+ printf("\t============================================\n");
}
void Transmitter::timeout()
More information about the Sumover-dev
mailing list