00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/apps/rtp.cc,v 1.27 2005/08/22 05:08:32 tomh 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* )
00090 {
00091 Packet *p;
00092 int n;
00093
00094 assert (size_ > 0);
00095
00096 if (++seqno_ < maxpkts_) {
00097 n = nbytes / size_;
00098
00099 if (nbytes == -1) {
00100 start();
00101 return;
00102 }
00103 while (n-- > 0) {
00104 p = allocpkt();
00105 hdr_rtp* rh = hdr_rtp::access(p);
00106 rh->seqno() = seqno_;
00107 target_->recv(p);
00108 }
00109 n = nbytes % size_;
00110 if (n > 0) {
00111 p = allocpkt();
00112 hdr_rtp* rh = hdr_rtp::access(p);
00113 rh->seqno() = seqno_;
00114 target_->recv(p);
00115 }
00116 idle();
00117 } else {
00118 finish();
00119
00120 };
00121 }
00122
00123 void RTPAgent::timeout(int)
00124 {
00125 if (running_) {
00126 sendpkt();
00127 if (session_)
00128 session_->localsrc_update(size_);
00129 double t = interval_;
00130 if (random_)
00131
00132 t += interval_ * Random::uniform(-0.5, 0.5);
00133 rtp_timer_.resched(t);
00134 }
00135 }
00136
00137
00138
00139
00140
00141 void RTPAgent::finish()
00142 {
00143 running_ = 0;
00144 Tcl::instance().evalf("%s done", this->name());
00145 }
00146
00147 void RTPAgent::advanceby(int delta)
00148 {
00149 maxpkts_ += delta;
00150 if (seqno_ < maxpkts_ && !running_)
00151 start();
00152 }
00153
00154
00155 void RTPAgent::recv(Packet* p, Handler*)
00156 {
00157 if (session_)
00158 session_->recv(p, 0);
00159 else
00160 Packet::free(p);
00161 }
00162
00163 int RTPAgent::command(int argc, const char*const* argv)
00164 {
00165 if (argc == 2) {
00166 if (strcmp(argv[1], "rate-change") == 0) {
00167 rate_change();
00168 return (TCL_OK);
00169 } else if (strcmp(argv[1], "start") == 0) {
00170 start();
00171 return (TCL_OK);
00172 } else if (strcmp(argv[1], "stop") == 0) {
00173 stop();
00174 return (TCL_OK);
00175 }
00176 } else if (argc == 3) {
00177 if (strcmp(argv[1], "session") == 0) {
00178 session_ = (RTPSession*)TclObject::lookup(argv[2]);
00179 return (TCL_OK);
00180 } else if (strcmp(argv[1], "advance") == 0) {
00181 int newseq = atoi(argv[2]);
00182 advanceby(newseq - seqno_);
00183 return (TCL_OK);
00184 } else if (strcmp(argv[1], "advanceby") == 0) {
00185 advanceby(atoi(argv[2]));
00186 return (TCL_OK);
00187 }
00188 }
00189 return (Agent::command(argc, argv));
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 void RTPAgent::rate_change()
00199 {
00200 rtp_timer_.force_cancel();
00201
00202 double t = lastpkttime_ + interval_;
00203
00204 double now = Scheduler::instance().clock();
00205 if ( t > now)
00206 rtp_timer_.resched(t - now);
00207 else {
00208 sendpkt();
00209 rtp_timer_.resched(interval_);
00210 }
00211 }
00212
00213 void RTPAgent::sendpkt()
00214 {
00215 Packet* p = allocpkt();
00216 lastpkttime_ = Scheduler::instance().clock();
00217 makepkt(p);
00218 target_->recv(p, (Handler*)0);
00219 }
00220
00221 void RTPAgent::makepkt(Packet* p)
00222 {
00223 hdr_rtp *rh = hdr_rtp::access(p);
00224
00225 rh->seqno() = seqno_++;
00226 rh->srcid() = session_ ? session_->srcid() : 0;
00227 }
00228
00229 void RTPTimer::expire(Event* ) {
00230 a_->timeout(0);
00231 }
00232