00001
00035 #include <stdlib.h>
00036 #include "config.h"
00037 #include "agent.h"
00038 #include "random.h"
00039 #include "rtp.h"
00040
00041
00042 int hdr_rtp::offset_;
00044 class RTPHeaderClass : public PacketHeaderClass {
00045 public:
00046 RTPHeaderClass() : PacketHeaderClass("PacketHeader/RTP",
00047 sizeof(hdr_rtp)) {
00048 bind_offset(&hdr_rtp::offset_);
00049 }
00050 } class_rtphdr;
00054 static class RTPAgentClass : public TclClass {
00055 public:
00056 RTPAgentClass() : TclClass("Agent/RTP") {}
00057 TclObject* create(int, const char*const*) {
00058 return (new RTPAgent());
00059
00060 }
00061 } class_rtp_agent;
00062
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 timestamp_ = 0;
00075
00076 }
00078 void RTPAgent::start()
00079 {
00080 running_ = 1;
00081 sendpkt();
00082 rtp_timer_.resched(interval_);
00083 }
00084
00086 void RTPAgent::stop()
00087 {
00088
00089 rtp_timer_.force_cancel();
00090 finish();
00091 }
00092
00094 void RTPAgent::sendmsg(int nbytes, const char* )
00095 {
00096 Packet *p;
00097 int n;
00098
00099 assert (size_ > 0);
00100
00101 if (++seqno_ < maxpkts_) {
00102 n = nbytes / size_;
00103
00104 if (nbytes == -1) {
00105 start();
00106 return;
00107 }
00108 while (n-- > 0) {
00109 p = allocpkt();
00110 hdr_rtp* rh = hdr_rtp::access(p);
00111 rh->seqno() = seqno_;
00112 target_->recv(p);
00113 }
00114 n = nbytes % size_;
00115 if (n > 0) {
00116 p = allocpkt();
00117 hdr_rtp* rh = hdr_rtp::access(p);
00118 rh->seqno() = seqno_;
00119 target_->recv(p);
00120 }
00121 idle();
00122 } else {
00123 finish();
00124
00125 };
00126 }
00127
00132 void RTPAgent::timeout(int)
00133 {
00134 if (running_) {
00135 sendpkt();
00136 if (session_)
00137 session_->localsrc_update(size_);
00138 session_->localsrc_update_nbytes(size_);
00139
00140 double t = interval_;
00141 if (random_)
00142
00143 t += interval_ * Random::uniform(-0.5, 0.5);
00144 rtp_timer_.resched(t);
00145 }
00146 }
00147
00152 void RTPAgent::finish()
00153 {
00154 running_ = 0;
00155 Tcl::instance().evalf("%s done", this->name());
00156 }
00157
00162 void RTPAgent::advanceby(int delta)
00163 {
00164 maxpkts_ += delta;
00165 if (seqno_ < maxpkts_ && !running_)
00166 start();
00167 }
00168
00173 void RTPAgent::recv(Packet* p, Handler*)
00174 {
00175 if (session_)
00176 session_->recv(p, 0);
00177 else
00178 Packet::free(p);
00179 }
00180
00181 int RTPAgent::command(int argc, const char*const* argv)
00182 {
00183 if (argc == 2) {
00184 if (strcmp(argv[1], "rate-change") == 0) {
00185 rate_change();
00186 return (TCL_OK);
00187 } else if (strcmp(argv[1], "start") == 0) {
00188 start();
00189 return (TCL_OK);
00190 } else if (strcmp(argv[1], "stop") == 0) {
00191 stop();
00192 return (TCL_OK);
00193 }
00194 } else if (argc == 3) {
00195 if (strcmp(argv[1], "session") == 0) {
00196 session_ = (RTPSession*)TclObject::lookup(argv[2]);
00197 return (TCL_OK);
00198 } else if (strcmp(argv[1], "advance") == 0) {
00199 int newseq = atoi(argv[2]);
00200 advanceby(newseq - seqno_);
00201 return (TCL_OK);
00202 } else if (strcmp(argv[1], "advanceby") == 0) {
00203 advanceby(atoi(argv[2]));
00204 return (TCL_OK);
00205 }
00206 }
00207 return (Agent::command(argc, argv));
00208 }
00209
00216 void RTPAgent::rate_change()
00217 {
00218 rtp_timer_.force_cancel();
00219
00220 double t = lastpkttime_ + interval_;
00221
00222 double now = Scheduler::instance().clock();
00223 if ( t > now)
00224 rtp_timer_.resched(t - now);
00225 else {
00226 sendpkt();
00227 rtp_timer_.resched(interval_);
00228 }
00229 }
00231 void RTPAgent::sendpkt()
00232 {
00233 Packet* p = allocpkt();
00234 lastpkttime_ = Scheduler::instance().clock();
00235 timestamp_ = lastpkttime_;
00236 makepkt(p);
00237 target_->recv(p, (Handler*)0);
00238 }
00240 void RTPAgent::makepkt(Packet* p)
00241 {
00242
00243 hdr_rtp *rh = hdr_rtp::access(p);
00244
00245 rh->seqno() = seqno_++;
00246 rh->srcid() = session_ ? session_->srcid() : 0;
00247 rh->timestamp()= timestamp_;
00248
00249
00250 }
00251
00252 void RTPTimer::expire(Event* ) {
00253 a_->timeout(0);
00254 }
00255
00256