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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * diff_sink.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: diff_sink.cc,v 1.7 2005/08/25 18:58:03 johnh Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. /********************************************************************/
  46. /* diff_sink.cc : Chalermek Intanagonwiwat (USC/ISI)  08/21/99      */
  47. /********************************************************************/
  48. #include <stdlib.h>
  49. #include "diff_sink.h"
  50. #include "diffusion.h"
  51. #include "diff_rate.h"
  52. #include "hash_table.h"
  53. #include "agent.h"
  54. #include "packet.h"
  55. #include "tclcl.h"
  56. #include "random.h"
  57. #include "god.h"
  58. #define REPORT_PERIOD    1.0
  59. extern char* MsgStr[];
  60. void Report_Timer::expire(Event *) {
  61.   a_->report();
  62. }
  63. void Sink_Timer::expire(Event *) {
  64.   a_->timeout(0);
  65. }
  66. void Periodic_Timer::expire(Event *) {
  67.   a_->bcast_interest();
  68. }
  69. static class SinkClass : public TclClass {
  70. public:
  71.   SinkClass() : TclClass("Agent/Diff_Sink") {}
  72.   TclObject* create(int , const char*const* ) {
  73.     return(new SinkAgent());
  74.   }
  75. } class_sink;
  76. SinkAgent::SinkAgent() : Agent(PT_DIFF), data_type_(0), 
  77.   running_(0), random_(0), sink_timer_(this), periodic_timer_(this),
  78.   report_timer_(this)
  79. {
  80.   // set option first.
  81.   APP_DUP_ = true;
  82.   periodic_ = true;
  83.   always_max_rate_ = false;
  84.   // Bind Tcl and C++ Variables
  85.   bind("data_type_", &data_type_);
  86.   bind_time("interval_", &interval_);
  87.   bind("packetSize_", &size_);
  88.   bind("random_", &random_);
  89.   bind("maxpkts_", &maxpkts_);
  90.   // Initialize variables.
  91.   // maxpkts_ = 2;
  92.   pk_count=0;
  93.   num_recv=0;
  94.   num_send=0;
  95.   RecvPerSec=0;
  96.   cum_delay=0.0;
  97.   data_counter = 0;
  98.   simple_report_rate = ORIGINAL;
  99.   last_arrival_time = -1.0;
  100. }
  101. void SinkAgent::start()
  102. {
  103. running_ = 1;
  104. sendpkt();
  105. sink_timer_.resched(interval_);
  106. }
  107. void SinkAgent::stop()
  108. {
  109.   if (running_) {
  110. running_ = 0;
  111.   }
  112.   
  113.   if (periodic_ == true) {
  114.     periodic_ = false;
  115.     periodic_timer_.force_cancel();
  116.   }
  117. }
  118. void SinkAgent::report()
  119. {
  120.   //  printf("SK %d: RecvPerSec %d at time %lfn", here_.addr_, RecvPerSec, NOW);
  121.   report_timer_.resched(REPORT_PERIOD);
  122.   RecvPerSec = 0;
  123. }
  124. void SinkAgent::timeout(int)
  125. {
  126. if (running_) {
  127. sendpkt();
  128. double t = interval_;
  129. if (random_)
  130. /* add some zero-mean white noise */
  131. t += interval_ * Random::uniform(-0.5, 0.5);
  132. sink_timer_.resched(t);
  133. }
  134. }
  135. void SinkAgent::sendpkt()
  136. {
  137.       if (pk_count >=  maxpkts_) {
  138.         running_ = 0;
  139.         return;
  140.       }
  141.       Packet* pkt = create_packet();
  142.       hdr_cdiff* dfh = HDR_CDIFF(pkt);
  143.       hdr_ip* iph = HDR_IP(pkt);
  144.       hdr_cmn*  cmh = HDR_CMN(pkt);
  145.       data_counter = (data_counter + SUB_SAMPLED)% ORIGINAL;
  146.       if (data_counter == SUB_SAMPLED) {
  147. dfh->report_rate = SUB_SAMPLED;
  148.       } else {
  149. dfh->report_rate = ORIGINAL;
  150.       }
  151.       if (simple_report_rate < dfh->report_rate) {
  152. Packet::free(pkt);
  153. return;
  154.       }
  155.       
  156.       cmh->size() = size_;
  157.       dfh->mess_type = DATA;
  158.       dfh->pk_num = pk_count;
  159.       pk_count++;
  160.       dfh->sender_id = here_;
  161.       dfh->data_type = data_type_;
  162.       dfh->forward_agent_id = here_; 
  163.       dfh->num_next = 1;
  164.       dfh->next_nodes[0] = here_.addr_;
  165.       iph->src_ = here_;
  166.       iph->dst_.addr_ = here_.addr_;
  167.       iph->dst_.port_ = ROUTING_PORT;
  168.        
  169.       // Send the packet
  170.       // printf("Source %s send packet (%x, %d) at %lf.n", name(), 
  171.       //    dfh->sender_id, dfh->pk_num, NOW);
  172.       num_send++;
  173.       dfh->attr[0] = data_type_;
  174.       if (APP_DUP_ == true)
  175. dfh->attr[1] = 0;             // Represent detection of the same animal
  176.       else
  177. dfh->attr[1] = here_.addr_;   // Detect a different animal. 
  178.       dfh->attr[2] = num_send;       
  179.       God::instance()->CountNewData(dfh->attr);
  180.       send(pkt, 0);
  181. }
  182. void SinkAgent::bcast_interest()
  183. {
  184.       Packet* pkt = create_packet();
  185.       hdr_cdiff* dfh = HDR_CDIFF(pkt);
  186.       hdr_ip* iph = HDR_IP(pkt);
  187.       // Set message type, packet number and sender ID
  188.       dfh->mess_type = INTEREST;
  189.       dfh->pk_num = pk_count;
  190.       pk_count++;
  191.       dfh->sender_id = here_;
  192.       dfh->data_type = data_type_;
  193.       dfh->forward_agent_id = here_; 
  194.       dfh->report_rate = SUB_SAMPLED;
  195.       dfh->num_next = 1;
  196.       dfh->next_nodes[0] = here_.addr_;
  197.       iph->src_ = here_;
  198.       iph->dst_.addr_ = here_.addr_;
  199.       iph->dst_.port_ = ROUTING_PORT;
  200.  
  201.  
  202.       // Send the packet
  203.       // printf("Sink %s send packet (%x, %d) at %f to %x.n", 
  204.       //    name_, dfh->sender_id,
  205.       //     dfh->pk_num, 
  206.       //     NOW,
  207.       //     iph->dst_);
  208.       send(pkt, 0);
  209.       if (periodic_ == true)
  210. periodic_timer_.resched(INTEREST_PERIODIC);
  211. }
  212. void SinkAgent::data_ready()
  213. {
  214.       // Create a new packet
  215.       Packet* pkt = create_packet();
  216.       // Access the Sink header for the new packet:
  217.       hdr_cdiff* dfh = HDR_CDIFF(pkt);
  218.       hdr_ip* iph = HDR_IP(pkt);
  219.       // Set message type, packet number and sender ID
  220.       dfh->mess_type = DATA_READY;
  221.       dfh->pk_num = pk_count;
  222.       pk_count++;
  223.       dfh->sender_id = here_;
  224.       dfh->data_type = data_type_;
  225.       dfh->forward_agent_id = here_; 
  226.       dfh->num_next = 1;
  227.       dfh->next_nodes[0] = here_.addr_;
  228.       iph->src_ = here_;
  229.       iph->dst_.addr_ = here_.addr_;
  230.       iph->dst_.port_ = ROUTING_PORT;
  231.  
  232.       send(pkt, 0);
  233. }
  234. void SinkAgent::Terminate() 
  235. {
  236. #ifdef DEBUG_OUTPUT
  237.   printf("SINK %d : TYPE %d : terminates (send %d, recv %d, cum_delay %f)n", 
  238.  here_.addr_, data_type_, num_send, num_recv, cum_delay);
  239. #endif
  240. }
  241. int SinkAgent::command(int argc, const char*const* argv)
  242. {
  243.   if (argc == 2) {
  244.     if (strcmp(argv[1], "enable-duplicate") == 0) {
  245.       APP_DUP_ = true;
  246.       return TCL_OK;
  247.     }
  248.     if (strcmp(argv[1], "disable-duplicate") == 0) {
  249.       APP_DUP_ = false;
  250.       return TCL_OK;
  251.     }
  252.     if (strcmp(argv[1], "always-max-rate") == 0) {
  253.       always_max_rate_ = true;
  254.       return TCL_OK;
  255.     }
  256.     if (strcmp(argv[1], "terminate") == 0) {
  257.       Terminate();
  258.       return TCL_OK;
  259.     }
  260.     if (strcmp(argv[1], "announce") == 0) {
  261.       bcast_interest();
  262.       report_timer_.resched(REPORT_PERIOD);
  263.       return (TCL_OK);
  264.     }
  265.     if (strcmp(argv[1], "ready") == 0) {
  266.       God::instance()->data_pkt_size = size_;
  267.       data_ready();
  268.       return (TCL_OK);
  269.     }
  270.     if (strcmp(argv[1], "send") == 0) {
  271.       sendpkt();   
  272.       return (TCL_OK);
  273.     }
  274.     if (strcmp(argv[1], "cbr-start") == 0) {
  275.        start();
  276.        return (TCL_OK);
  277.     }
  278.     if (strcmp(argv[1], "stop") == 0) {
  279. stop();
  280.         report_timer_.force_cancel();
  281. return (TCL_OK);
  282.     }
  283.   }
  284.   if (argc == 3) {
  285.     if (strcmp(argv[1], "data-type") == 0) {
  286.       data_type_ = atoi(argv[2]);
  287.       return (TCL_OK);
  288.     }
  289.   }
  290.   return (Agent::command(argc, argv));
  291. }
  292. void SinkAgent::recv(Packet* pkt, Handler*)
  293. {
  294.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  295.   /*
  296.   printf("SK %d recv (%x, %x, %d) %s size %d at time %lfn", here_.addr_, 
  297.  (dfh->sender_id).addr_, (dfh->sender_id).port_,
  298.  dfh->pk_num, MsgStr[dfh->mess_type], cmh->size(), NOW);
  299.   */
  300.   if (data_type_ != dfh->data_type) {
  301.       printf("Hey, What are you doing? I am not a sink for %d. I'm a sink for %d. n", dfh->data_type, data_type_);
  302.       Packet::free(pkt);
  303.       return;
  304.   }
  305.   switch(dfh->mess_type) {
  306.     case DATA_REQUEST :
  307.       if (always_max_rate_ == false)
  308. simple_report_rate = dfh->report_rate;
  309.       
  310.       if (!running_) start();
  311.       //      printf("I got a data request for data rate %d at %lf. Will send it right away.n",
  312.       //      simple_report_rate, NOW);
  313.       break;
  314.     case DATA_STOP :
  315.       if (running_) stop();
  316.       break;
  317.     case DATA :
  318.       if (APP_DUP_ == true) {
  319. if (DataTable.GetHash(dfh->attr) != NULL) {
  320.   Packet::free(pkt);
  321.   return;
  322. } else {
  323.   DataTable.PutInHash(dfh->attr);
  324. }
  325.       }
  326.       cum_delay = cum_delay + (NOW - dfh->ts_);
  327.       num_recv++;
  328.       RecvPerSec++;
  329.       God::instance()->IncrRecv();
  330.       /*
  331.       if (last_arrival_time > 0.0) {
  332. printf("SK %d: Num_Recv %d, InterArrival %lfn", here_.addr_, 
  333.        num_recv, (NOW)-last_arrival_time);
  334.       }
  335.       */
  336.       last_arrival_time = NOW;
  337.       break;
  338.     default:
  339.       break;
  340.   }
  341.   Packet::free(pkt);
  342. }
  343. void SinkAgent::reset()
  344. {
  345. }
  346. void SinkAgent:: set_addr(ns_addr_t address)
  347. {
  348.   here_=address;
  349. }
  350. int SinkAgent:: get_pk_count()
  351. {
  352.   return pk_count;
  353. }
  354. void SinkAgent:: incr_pk_count()
  355. {
  356.   pk_count++;
  357. }
  358. Packet * SinkAgent:: create_packet()
  359. {
  360.   Packet *pkt = allocpkt();
  361.   if (pkt==NULL) return NULL;
  362.   hdr_cmn*  cmh = HDR_CMN(pkt);
  363.   cmh->size() = 36;
  364.   hdr_cdiff* dfh = HDR_CDIFF(pkt);
  365.   dfh->ts_ = NOW; 
  366.   return pkt;
  367. }