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.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* )
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
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
00133 t += interval_ * Random::uniform(-0.5, 0.5);
00134 rtp_timer_.resched(t);
00135 }
00136 }
00137
00138
00139
00140
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
00195
00196
00197
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
00226 rh->seqno() = seqno_++;
00227 rh->srcid() = session_ ? session_->srcid() : 0;
00228 }
00229
00230 void RTPTimer::expire(Event* ) {
00231 a_->timeout(0);
00232 }
00233