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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * srm.cc
  4.  * Copyright (C) 1997 by the University of Southern California
  5.  * $Id: srm.cc,v 1.27 2005/08/25 18:58:08 johnh Exp $
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License,
  9.  * version 2, as published by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  * The copyright of this module includes the following
  22.  * linking-with-specific-other-licenses addition:
  23.  *
  24.  * In addition, as a special exception, the copyright holders of
  25.  * this module give you permission to combine (via static or
  26.  * dynamic linking) this module with free software programs or
  27.  * libraries that are released under the GNU LGPL and with code
  28.  * included in the standard release of ns-2 under the Apache 2.0
  29.  * license or under otherwise-compatible licenses with advertising
  30.  * requirements (or modified versions of such code, with unchanged
  31.  * license).  You may copy and distribute such a system following the
  32.  * terms of the GNU GPL for this module and the licenses of the
  33.  * other code concerned, provided that you include the source code of
  34.  * that other code when and as the GNU GPL requires distribution of
  35.  * source code.
  36.  *
  37.  * Note that people who make modified versions of this module
  38.  * are not obligated to grant this special exception for their
  39.  * modified versions; it is their choice whether to do so.  The GNU
  40.  * General Public License gives permission to release a modified
  41.  * version without this exception; this exception also makes it
  42.  * possible to release a modified version which carries forward this
  43.  * exception.
  44.  *
  45.  */
  46. //
  47. // Maintainer: Kannan Varadhan <kannan@isi.edu>
  48. // Version Date: Tue Jul 22 15:41:16 PDT 1997
  49. //
  50. #ifndef lint
  51. static const char rcsid[] =
  52.     "@(#) $Header: /cvsroot/nsnam/ns-2/mcast/srm.cc,v 1.27 2005/08/25 18:58:08 johnh Exp $ (USC/ISI)";
  53. #endif
  54. #include <stdlib.h>
  55. #include <assert.h>
  56. #include "config.h"
  57. #include "agent.h"
  58. #include "ip.h"
  59. #include "srm.h"
  60. #include "trace.h"
  61. #include "rtp.h"
  62. int hdr_srm::offset_;
  63. int hdr_asrm::offset_;
  64. static class SRMHeaderClass : public PacketHeaderClass {
  65. public:
  66. SRMHeaderClass() : PacketHeaderClass("PacketHeader/SRM",
  67.      sizeof(hdr_srm)) {
  68. bind_offset(&hdr_srm::offset_);
  69. }
  70. } class_srmhdr;
  71. static class ASRMHeaderClass : public PacketHeaderClass {
  72. public:
  73. ASRMHeaderClass() : PacketHeaderClass("PacketHeader/aSRM",
  74.       sizeof(hdr_asrm)) {
  75. bind_offset(&hdr_asrm::offset_);
  76. }
  77. } class_adaptive_srmhdr;
  78. static class SRMAgentClass : public TclClass {
  79. public:
  80. SRMAgentClass() : TclClass("Agent/SRM") {}
  81. TclObject* create(int, const char*const*) {
  82. return (new SRMAgent());
  83. }
  84. } class_srm_agent;
  85. static class ASRMAgentClass : public TclClass {
  86. public:
  87. ASRMAgentClass() : TclClass("Agent/SRM/Adaptive") {}
  88. TclObject* create(int, const char*const*) {
  89. return (new ASRMAgent());
  90. }
  91. } class_adaptive_srm_agent;
  92. SRMAgent::SRMAgent() 
  93. : Agent(PT_SRM), dataCtr_(-1), sessCtr_(-1), siphash_(0), seqno_(-1),
  94.     app_type_(PT_NTYPE)
  95. {
  96. sip_ = new SRMinfo(-1);
  97. bind("packetSize_", &packetSize_);
  98. bind("groupSize_", &groupSize_);
  99. bind("app_fid_", &app_fid_);
  100. }
  101. SRMAgent::~SRMAgent()
  102. {
  103. cleanup();
  104. }
  105. int SRMAgent::command(int argc, const char*const* argv)
  106. {
  107. Tcl& tcl = Tcl::instance();
  108. if (strcmp(argv[1], "send") == 0) {
  109. if (strcmp(argv[2], "session") == 0) {
  110. send_sess();
  111. return TCL_OK;
  112. }
  113. if (strcmp(argv[2], "request") == 0) {
  114. int round = atoi(argv[3]);
  115. int sender = atoi(argv[4]);
  116. int msgid  = atoi(argv[5]);
  117. send_ctrl(SRM_RQST, round, sender, msgid, 0);
  118. return TCL_OK;
  119. }
  120. if (strcmp(argv[2], "repair") == 0) {
  121. int round = atoi(argv[3]);
  122. int sender = atoi(argv[4]);
  123. int msgid  = atoi(argv[5]);
  124. send_ctrl(SRM_REPR, round, sender, msgid, packetSize_);
  125. return TCL_OK;
  126. }
  127. tcl.resultf("%s: invalid send request %s", name_, argv[2]);
  128. return TCL_ERROR;
  129. }
  130. if (argc == 2) {
  131. if (strcmp(argv[1], "distances?") == 0) {
  132. tcl.result("");
  133. if (sip_->sender_ >= 0) {  // i.e. this agent is active
  134. for (SRMinfo* sp = sip_; sp; sp = sp->next_) {
  135. tcl.resultf("%s %d %f", tcl.result(),
  136.     sp->sender_,
  137.     sp->distance_);
  138. }
  139. }
  140. return TCL_OK;
  141. }
  142. if (strcmp(argv[1], "start") == 0) {
  143. start();
  144. return TCL_OK;
  145. }
  146. }
  147. if (argc == 3) {
  148. if (strcmp(argv[1], "distance?") == 0) {
  149. int sender = atoi(argv[2]);
  150. SRMinfo* sp = get_state(sender);
  151. tcl.resultf("%lf", sp->distance_);
  152. return TCL_OK;
  153. }
  154.      if (strcmp(argv[1], "eventtrace") == 0) {
  155.        return (TCL_OK);
  156.      }
  157. }
  158. return Agent::command(argc, argv);
  159. }
  160. void SRMAgent::recv(Packet* p, Handler* h)
  161. {
  162. hdr_ip*  ih = hdr_ip::access(p);
  163. hdr_srm* sh = hdr_srm::access(p);
  164. if (ih->daddr() == -1) {
  165. // Packet from local agent.  Add srm headers, set dst, and fwd
  166. sh->type() = SRM_DATA;
  167. sh->sender() = addr();
  168. sh->seqnum() = ++dataCtr_;
  169. addExtendedHeaders(p);
  170. ih->dst() = dst_;
  171. target_->recv(p, h);
  172. } else {
  173. #if 0
  174.   static char *foo[] = {"NONE", "DATA", "SESS", "RQST", "REPR"};
  175.   fprintf(stderr, "%7.4f %s %d recvd SRM_%s <%d, %d> from %dn",
  176. Scheduler::instance().clock(), name_, addr_,
  177. foo[sh->type()],
  178. sh->sender(), sh->seqnum(), ih->src());
  179. #endif
  180. parseExtendedHeaders(p);
  181. switch (sh->type()) {
  182. case SRM_DATA:
  183. recv_data(sh->sender(), sh->seqnum(), p->accessdata());
  184. break;
  185. case SRM_RQST:
  186. recv_rqst(ih->saddr(),
  187.   sh->round(), sh->sender(), sh->seqnum());
  188. break;
  189. case SRM_REPR:
  190. recv_repr(sh->round(), sh->sender(), sh->seqnum(),
  191.   p->accessdata());
  192. break;
  193. case SRM_SESS:
  194. // This seqnum() is the session sequence number,
  195. // not the data packet sequence numbers seen before.
  196. recv_sess(p, sh->seqnum(), (int*) p->accessdata());
  197. break;
  198. }
  199. Packet::free(p);
  200. }
  201. }
  202. void SRMAgent::sendmsg(int nbytes, const char* /*flags*/)
  203. {
  204. if (nbytes == -1) {
  205. printf("Error:  sendmsg() for SRM should not be -1n");
  206. return;
  207. }
  208. // The traffic generator may have reset our payload type when it
  209. // initialized.  If so, save the current payload type as app_type_,
  210. // and set type_ to PT_SRM.  Use app_type_ for all app. packets
  211. // 
  212. if (type_ != PT_SRM) {
  213. app_type_ = type_;
  214. type_ = PT_SRM;
  215. }
  216. size_ = nbytes;
  217. Packet *p;
  218. p = allocpkt();
  219.         hdr_ip*  ih = hdr_ip::access(p);
  220.         hdr_srm* sh = hdr_srm::access(p);
  221. hdr_rtp* rh = hdr_rtp::access(p);
  222. hdr_cmn* ch = hdr_cmn::access(p);
  223. //hdr_cmn* ch = hdr_cmn::access(p);
  224. ch->ptype() = app_type_;
  225. ch->size() =  size_;
  226. ih->flowid() = app_fid_;
  227. rh->seqno() = ++seqno_;
  228. // Add srm headers, set dst, and fwd
  229. sh->type() = SRM_DATA;
  230. sh->sender() = addr();
  231. sh->seqnum() = ++dataCtr_;
  232. addExtendedHeaders(p);
  233. ih->dst() = dst_;
  234. target_->recv(p);
  235. }
  236. void SRMAgent::send_ctrl(int type, int round, int sender, int msgid, int size)
  237. {
  238. Packet* p = Agent::allocpkt();
  239. hdr_srm* sh = hdr_srm::access(p);
  240. sh->type() = type;
  241. sh->sender() = sender;
  242. sh->seqnum() = msgid;
  243. sh->round() = round;
  244. addExtendedHeaders(p);
  245. hdr_cmn* ch = hdr_cmn::access(p);
  246. ch->size() = sizeof(hdr_srm) + size;
  247. target_->recv(p);
  248. }
  249. void SRMAgent::recv_data(int sender, int msgid, u_char*)
  250. {
  251. Tcl& tcl = Tcl::instance();
  252. SRMinfo* sp = get_state(sender);
  253. if (msgid > sp->ldata_) {
  254. (void) request(sp, msgid - 1);
  255. sp->setReceived(msgid);
  256. sp->ldata_ = msgid;
  257. } else {
  258. tcl.evalf("%s recv data %d %d", name_, sender, msgid);
  259. }
  260. }
  261. void SRMAgent::recv_rqst(int requestor, int round, int sender, int msgid)
  262. {
  263. Tcl& tcl = Tcl::instance();
  264. SRMinfo* sp = get_state(sender);
  265. if (msgid > sp->ldata_) {
  266. (void) request(sp, msgid); // request upto msgid
  267. sp->ldata_ = msgid;
  268. } else {
  269. tcl.evalf("%s recv request %d %d %d %d", name_,
  270.   requestor, round, sender, msgid);
  271. }
  272. }
  273. void SRMAgent::recv_repr(int round, int sender, int msgid, u_char*)
  274. {
  275. Tcl& tcl = Tcl::instance();
  276. SRMinfo* sp = get_state(sender);
  277. if (msgid > sp->ldata_) {
  278. (void) request(sp, msgid - 1); // request upto msgid - 1
  279. sp->setReceived(msgid);
  280. sp->ldata_ = msgid;
  281. } else {
  282. tcl.evalf("%s recv repair %d %d %d", name_,
  283.   round, sender, msgid);
  284. }
  285. // Notice that we currently make no provisions for a listener
  286. // agent to receive the data.
  287. }
  288. void SRMAgent::send_sess()
  289. {
  290. int size = (1 + groupSize_ * 4) * sizeof(int);
  291. Packet* p = Agent::allocpkt(size);
  292. hdr_srm* sh = hdr_srm::access(p);
  293. sh->type() = SRM_SESS;
  294. sh->sender() = addr();
  295. sh->seqnum() = ++sessCtr_;
  296. addExtendedHeaders(p);
  297. int* data = (int*) p->accessdata();
  298. *data++ = groupSize_;
  299. for (SRMinfo* sp = sip_; sp; sp = sp->next_) {
  300. *data++ = sp->sender_;
  301. *data++ = sp->ldata_;
  302. *data++ = sp->recvTime_;
  303. *data++ = sp->sendTime_;
  304. }
  305. data = (int*) p->accessdata();
  306. data[4] = (int) (Scheduler::instance().clock()*1000);
  307. hdr_cmn* ch = hdr_cmn::access(p);
  308. ch->size() = size+ sizeof(hdr_srm);
  309. target_->recv(p, (Handler*)NULL);
  310. }
  311. #define GET_SESSION_INFO
  312. sender = *data++;
  313. dataCnt = *data++;
  314. rtime = *data++;
  315. stime = *data++
  316. void SRMAgent::recv_sess(Packet*, int sessCtr, int* data)
  317. {
  318. SRMinfo* sp;
  319. int sender, dataCnt, rtime, stime;
  320. int now, sentAt, sentBy;
  321. int cnt = *data++;
  322. int i;
  323. /* The first block contains the sender's own state */
  324. GET_SESSION_INFO;
  325. if (sender == addr()) // sender's own session message
  326. return;
  327. sp = get_state(sender);
  328. if (sp->lsess_ > sessCtr) // older session message recd.
  329. return;
  330. now = (int) (Scheduler::instance().clock() * 1000);
  331. sentBy = sender; // to later compute rtt
  332. sentAt = stime;
  333. sp->lsess_ = sessCtr;
  334. sp->recvTime_ = now;
  335. sp->sendTime_ = stime;
  336. (void) request(sp, dataCnt);
  337. if (sp->ldata_ < dataCnt)
  338. sp->ldata_ = dataCnt;
  339. for (i = 1; i < cnt; i++) {
  340. GET_SESSION_INFO;
  341. if (sender == addr() && now) {
  342. //
  343. //    This session message from sender sentBy:
  344. //   vvvvv
  345. //     now <=======+ sentAt
  346. //  |     |
  347. //   stime +=======> rtime
  348. //   ^^^^^
  349. //   Earlier session message sent by ``this'' agent
  350. //
  351.                         int rtt = (now - sentAt) + (rtime - stime);
  352. sp = get_state(sentBy);
  353. sp->distance_ = (double) rtt / 2 / 1000;
  354. #if 0
  355. fprintf(stderr,
  356. "%7.4f %s compute distance to %d: %fn",
  357. Scheduler::instance().clock(), name_,
  358. sentBy, sp->distance_);
  359. #endif
  360. continue;
  361. }
  362. sp = get_state(sender);
  363. (void) request(sp, dataCnt);
  364. if (sp->ldata_ < dataCnt)
  365. sp->ldata_ = dataCnt;
  366. }
  367. }