rtp.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:6k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *  This product includes software developed by the MASH Research
  17.  *  Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. #ifndef lint
  35. static const char rcsid[] =
  36.     "@(#) $Header: /cvsroot/nsnam/ns-2/apps/rtp.cc,v 1.27 2005/08/22 05:08:32 tomh Exp $";
  37. #endif
  38. #include <stdlib.h>
  39. #include "config.h"
  40. #include "agent.h"
  41. #include "random.h"
  42. #include "rtp.h"
  43. int hdr_rtp::offset_;
  44. class RTPHeaderClass : public PacketHeaderClass {
  45. public: 
  46.         RTPHeaderClass() : PacketHeaderClass("PacketHeader/RTP",
  47.      sizeof(hdr_rtp)) {
  48. bind_offset(&hdr_rtp::offset_);
  49. }
  50. } class_rtphdr;
  51. static class RTPAgentClass : public TclClass {
  52. public:
  53. RTPAgentClass() : TclClass("Agent/RTP") {}
  54. TclObject* create(int, const char*const*) {
  55. return (new RTPAgent());
  56. }
  57. } class_rtp_agent;
  58. RTPAgent::RTPAgent() : Agent(PT_RTP), session_(0), lastpkttime_(-1e6), 
  59.     running_(0), rtp_timer_(this)
  60. {
  61. bind("seqno_", &seqno_);
  62. bind_time("interval_", &interval_);
  63. bind("packetSize_", &size_);
  64. bind("maxpkts_", &maxpkts_);
  65. bind("random_", &random_);
  66. }
  67. void RTPAgent::start()
  68. {
  69.         running_ = 1;
  70.         sendpkt();
  71.         rtp_timer_.resched(interval_);
  72. }
  73. void RTPAgent::stop()
  74. {
  75.         rtp_timer_.force_cancel();
  76.         finish();
  77. }
  78. void RTPAgent::sendmsg(int nbytes, const char* /*flags*/)
  79. {
  80.         Packet *p;
  81.         int n;
  82. assert (size_ > 0);
  83.         if (++seqno_ < maxpkts_) {
  84. n = nbytes / size_;
  85.                 if (nbytes == -1) {
  86.                         start();
  87.                         return;
  88.                 }
  89.                 while (n-- > 0) {
  90.                         p = allocpkt();
  91.                         hdr_rtp* rh = hdr_rtp::access(p);
  92.                         rh->seqno() = seqno_;
  93.                         target_->recv(p);
  94.                 }
  95.                 n = nbytes % size_;
  96.                 if (n > 0) {
  97.                         p = allocpkt();
  98.                         hdr_rtp* rh = hdr_rtp::access(p);
  99.                         rh->seqno() = seqno_;
  100.                         target_->recv(p);
  101.                 }
  102.                 idle();
  103.         } else {
  104.                 finish();
  105.                 // xxx: should we deschedule the timer here? */
  106.         };
  107. }
  108. void RTPAgent::timeout(int) 
  109. {
  110. if (running_) {
  111. sendpkt();
  112. if (session_)
  113. session_->localsrc_update(size_);
  114. double t = interval_;
  115. if (random_)
  116. /* add some zero-mean white noise */
  117. t += interval_ * Random::uniform(-0.5, 0.5);
  118. rtp_timer_.resched(t);
  119. }
  120. }
  121. /*
  122.  * finish() is called when we must stop (either by request or because
  123.  * we're out of packets to send.
  124.  */
  125. void RTPAgent::finish()
  126. {
  127.         running_ = 0;
  128.         Tcl::instance().evalf("%s done", this->name());
  129. }
  130. void RTPAgent::advanceby(int delta)
  131. {
  132.         maxpkts_ += delta;
  133.         if (seqno_ < maxpkts_ && !running_)
  134.                 start();
  135. }               
  136. void RTPAgent::recv(Packet* p, Handler*)
  137. {
  138. if (session_)
  139. session_->recv(p, 0);
  140. else
  141. Packet::free(p);
  142. }
  143. int RTPAgent::command(int argc, const char*const* argv)
  144. {
  145. if (argc == 2) {
  146. if (strcmp(argv[1], "rate-change") == 0) {
  147. rate_change();
  148. return (TCL_OK);
  149. } else if (strcmp(argv[1], "start") == 0) {
  150.                         start();
  151.                         return (TCL_OK);
  152.                 } else if (strcmp(argv[1], "stop") == 0) {
  153.                         stop();
  154.                         return (TCL_OK);
  155.                 }
  156. } else if (argc == 3) {
  157. if (strcmp(argv[1], "session") == 0) {
  158. session_ = (RTPSession*)TclObject::lookup(argv[2]);
  159. return (TCL_OK);
  160. } else if (strcmp(argv[1], "advance") == 0) {
  161.                         int newseq = atoi(argv[2]);
  162.                         advanceby(newseq - seqno_);
  163.                         return (TCL_OK); 
  164.                 } else if (strcmp(argv[1], "advanceby") == 0) {
  165.                         advanceby(atoi(argv[2]));
  166.                         return (TCL_OK);
  167.                 }       
  168. }
  169. return (Agent::command(argc, argv));
  170. }
  171. /* 
  172.  * We modify the rate in this way to get a faster reaction to the a rate
  173.  * change since a rate change from a very low rate to a very fast rate may 
  174.  * take an undesireably long time if we have to wait for timeout at the old
  175.  * rate before we can send at the new (faster) rate.
  176.  */
  177. void RTPAgent::rate_change()
  178. {
  179. rtp_timer_.force_cancel();
  180. double t = lastpkttime_ + interval_;
  181. double now = Scheduler::instance().clock();
  182. if ( t > now)
  183. rtp_timer_.resched(t - now);
  184. else {
  185. sendpkt();
  186. rtp_timer_.resched(interval_);
  187. }
  188. }
  189. void RTPAgent::sendpkt()
  190. {
  191. Packet* p = allocpkt();
  192. lastpkttime_ = Scheduler::instance().clock();
  193. makepkt(p);
  194. target_->recv(p, (Handler*)0);
  195. }
  196. void RTPAgent::makepkt(Packet* p)
  197. {
  198. hdr_rtp *rh = hdr_rtp::access(p);
  199. /* Fill in srcid_ and seqno */
  200. rh->seqno() = seqno_++;
  201. rh->srcid() = session_ ? session_->srcid() : 0;
  202. }
  203. void RTPTimer::expire(Event* /*e*/) {
  204.         a_->timeout(0);
  205. }