Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

rtp.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the MASH Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Research Group may be
00019  *    used to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  * 
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 #ifndef lint
00036 static const char rcsid[] =
00037     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/apps/rtp.cc,v 1.26 2000/08/18 18:34:01 haoboy Exp $";
00038 #endif
00039 
00040 
00041 #include <stdlib.h>
00042 
00043 #include "config.h"
00044 #include "agent.h"
00045 #include "random.h"
00046 #include "rtp.h"
00047 
00048 int hdr_rtp::offset_;
00049 
00050 class RTPHeaderClass : public PacketHeaderClass {
00051 public: 
00052         RTPHeaderClass() : PacketHeaderClass("PacketHeader/RTP",
00053                                              sizeof(hdr_rtp)) {
00054                 bind_offset(&hdr_rtp::offset_);
00055         }
00056 } class_rtphdr;
00057 
00058 static class RTPAgentClass : public TclClass {
00059 public:
00060         RTPAgentClass() : TclClass("Agent/RTP") {}
00061         TclObject* create(int, const char*const*) {
00062                 return (new RTPAgent());
00063         }
00064 } class_rtp_agent;
00065 
00066 RTPAgent::RTPAgent() : Agent(PT_RTP), session_(0), lastpkttime_(-1e6), 
00067     running_(0), rtp_timer_(this)
00068 {
00069         bind("seqno_", &seqno_);
00070         bind_time("interval_", &interval_);
00071         bind("packetSize_", &size_);
00072         bind("maxpkts_", &maxpkts_);
00073         bind("random_", &random_);
00074 }
00075 
00076 void RTPAgent::start()
00077 {
00078         running_ = 1;
00079         sendpkt();
00080         rtp_timer_.resched(interval_);
00081 }
00082 
00083 void RTPAgent::stop()
00084 {
00085         rtp_timer_.force_cancel();
00086         finish();
00087 }
00088 
00089 void RTPAgent::sendmsg(int nbytes, const char* /*flags*/)
00090 {
00091         Packet *p;
00092         int n;
00093 
00094         if (++seqno_ < maxpkts_) {
00095                 if (size_)
00096                         n = nbytes / size_;
00097                 else
00098                         printf("Error: RTPAgent size = 0\n");
00099 
00100                 if (nbytes == -1) {
00101                         start();
00102                         return;
00103                 }
00104                 while (n-- > 0) {
00105                         p = allocpkt();
00106                         hdr_rtp* rh = hdr_rtp::access(p);
00107                         rh->seqno() = seqno_;
00108                         target_->recv(p);
00109                 }
00110                 n = nbytes % size_;
00111                 if (n > 0) {
00112                         p = allocpkt();
00113                         hdr_rtp* rh = hdr_rtp::access(p);
00114                         rh->seqno() = seqno_;
00115                         target_->recv(p);
00116                 }
00117                 idle();
00118         } else {
00119                 finish();
00120                 // xxx: should we deschedule the timer here? */
00121         };
00122 }
00123 
00124 void RTPAgent::timeout(int) 
00125 {
00126         if (running_) {
00127                 sendpkt();
00128                 if (session_)
00129                         session_->localsrc_update(size_);
00130                 double t = interval_;
00131                 if (random_)
00132                         /* add some zero-mean white noise */
00133                         t += interval_ * Random::uniform(-0.5, 0.5);
00134                 rtp_timer_.resched(t);
00135         }
00136 }
00137 
00138 /*
00139  * finish() is called when we must stop (either by request or because
00140  * we're out of packets to send.
00141  */
00142 void RTPAgent::finish()
00143 {
00144         running_ = 0;
00145         Tcl::instance().evalf("%s done", this->name());
00146 }
00147 
00148 void RTPAgent::advanceby(int delta)
00149 {
00150         maxpkts_ += delta;
00151         if (seqno_ < maxpkts_ && !running_)
00152                 start();
00153 }               
00154 
00155 
00156 void RTPAgent::recv(Packet* p, Handler*)
00157 {
00158         if (session_)
00159                 session_->recv(p, 0);
00160         else
00161                 Packet::free(p);
00162 }
00163 
00164 int RTPAgent::command(int argc, const char*const* argv)
00165 {
00166         if (argc == 2) {
00167                 if (strcmp(argv[1], "rate-change") == 0) {
00168                         rate_change();
00169                         return (TCL_OK);
00170                 } else if (strcmp(argv[1], "start") == 0) {
00171                         start();
00172                         return (TCL_OK);
00173                 } else if (strcmp(argv[1], "stop") == 0) {
00174                         stop();
00175                         return (TCL_OK);
00176                 }
00177         } else if (argc == 3) {
00178                 if (strcmp(argv[1], "session") == 0) {
00179                         session_ = (RTPSession*)TclObject::lookup(argv[2]);
00180                         return (TCL_OK);
00181                 } else if (strcmp(argv[1], "advance") == 0) {
00182                         int newseq = atoi(argv[2]);
00183                         advanceby(newseq - seqno_);
00184                         return (TCL_OK); 
00185                 } else if (strcmp(argv[1], "advanceby") == 0) {
00186                         advanceby(atoi(argv[2]));
00187                         return (TCL_OK);
00188                 }       
00189         }
00190         return (Agent::command(argc, argv));
00191 }
00192 
00193 /* 
00194  * We modify the rate in this way to get a faster reaction to the a rate
00195  * change since a rate change from a very low rate to a very fast rate may 
00196  * take an undesireably long time if we have to wait for timeout at the old
00197  * rate before we can send at the new (faster) rate.
00198  */
00199 void RTPAgent::rate_change()
00200 {
00201         rtp_timer_.force_cancel();
00202         
00203         double t = lastpkttime_ + interval_;
00204         
00205         double now = Scheduler::instance().clock();
00206         if ( t > now)
00207                 rtp_timer_.resched(t - now);
00208         else {
00209                 sendpkt();
00210                 rtp_timer_.resched(interval_);
00211         }
00212 }
00213 
00214 void RTPAgent::sendpkt()
00215 {
00216         Packet* p = allocpkt();
00217         lastpkttime_ = Scheduler::instance().clock();
00218         makepkt(p);
00219         target_->recv(p, (Handler*)0);
00220 }
00221 
00222 void RTPAgent::makepkt(Packet* p)
00223 {
00224         hdr_rtp *rh = hdr_rtp::access(p);
00225         /* Fill in srcid_ and seqno */
00226         rh->seqno() = seqno_++;
00227         rh->srcid() = session_ ? session_->srcid() : 0;
00228 }
00229 
00230 void RTPTimer::expire(Event* /*e*/) {
00231         a_->timeout(0);
00232 }
00233 

Generated on Tue Apr 20 12:14:30 2004 for NS2.26SourcesOriginal by doxygen 1.3.3