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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /* 
  3.  * Copyright 2002, Statistics Research, Bell Labs, Lucent Technologies and
  4.  * The University of North Carolina at Chapel Hill
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without 
  7.  * modification, are permitted provided that the following conditions are met:
  8.  * 
  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. The name of the author may not be used to endorse or promote 
  15.  * products derived from this software without specific prior written 
  16.  * permission.
  17.  * 
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  21.  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 
  22.  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  23.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  24.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  25.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  26.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  27.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  28.  * POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30. /*
  31.  * Reference
  32.  *     Stochastic Models for Generating Synthetic HTTP Source Traffic 
  33.  *     J. Cao, W.S. Cleveland, Y. Gao, K. Jeffay, F.D. Smith, and M.C. Weigle 
  34.  *     IEEE INFOCOM 2004.
  35.  *
  36.  * Documentation available at http://dirt.cs.unc.edu/packmime/
  37.  * 
  38.  * Contacts: Michele Weigle (mcweigle@cs.unc.edu),
  39.  *           Kevin Jeffay (jeffay@cs.unc.edu)
  40.  */
  41. #include <tclcl.h>
  42. #include "lib/bsd-list.h"
  43. #include "random.h"
  44. #include "tcp-full.h"
  45. #include "packmime_HTTP.h"
  46. #define MbPS2BPS_FACTOR 125000
  47. /*::::::::::::::::::::::::::::::: PACKMIME ::::::::::::::::::::::::::::::::::*/
  48. static class PackMimeHTTPClass : public TclClass {
  49. public:
  50. PackMimeHTTPClass() : TclClass("PackMimeHTTP") {}
  51. TclObject* create(int, const char*const*) {
  52. return (new PackMimeHTTP);
  53. }
  54. } class_packmime;
  55. PackMimeHTTP::PackMimeHTTP() :
  56. TclObject(), timer_(this), connection_interval_(0), 
  57. next_client_ind_(0), next_server_ind_(0), total_nodes_(0),
  58. current_node_(0), outfp_(NULL), fileszfp_(NULL), 
  59. samplesfp_(NULL), rate_(0), segsize_(0), segsperack_(0),
  60. interval_(0), ID_(-1), run_(0), debug_(0), 
  61. cur_pairs_(0), warmup_(0), http_1_1_(false), 
  62. use_pm_persist_rspsz_(true), use_pm_persist_reqsz_(true),
  63. active_connections_(0), total_connections_(-1), running_(0), 
  64. flowarrive_rv_(NULL), reqsize_rv_(NULL), rspsize_rv_(NULL), 
  65. persist_rspsize_rv_(NULL), persistent_rv_(NULL), num_pages_rv_(NULL),
  66. single_obj_rv_(NULL), objs_per_page_rv_(NULL), time_btwn_pages_rv_(NULL),
  67. time_btwn_objs_rv_(NULL), server_delay_rv_(NULL), 
  68. flowarrive_rng_(NULL), reqsize_rng_(NULL), rspsize_rng_(NULL), 
  69. persist_rspsize_rng_(NULL), persistent_rng_(NULL), num_pages_rng_(NULL), 
  70. single_obj_rng_(NULL), objs_per_page_rng_(NULL), time_btwn_pages_rng_(NULL),
  71. time_btwn_objs_rng_(NULL), server_delay_rng_(NULL)
  72. {
  73. int i;
  74. strcpy (tcptype_, "Reno");
  75. for (i=0; i<MAX_NODES; i++) {
  76. server_[i] = NULL;
  77. }
  78. for (i=0; i<MAX_NODES; i++) {
  79. client_[i] = NULL;
  80. }
  81. }
  82. PackMimeHTTP::~PackMimeHTTP()
  83. {
  84. Tcl& tcl = Tcl::instance();
  85. // output stats
  86. if (debug_ > 0) {
  87. fprintf (stderr, "total connections created: %d ", 
  88.  total_connections_+1);
  89. fprintf (stderr, "in pool: %d  active: %dn", 
  90.  (int) serverAppPool_.size(), 
  91.  (int) serverAppActive_.size());
  92. }
  93. // delete timer
  94. timer_.force_cancel();
  95. // delete active clients in the pool
  96. map<string, PackMimeHTTPClientApp*>::iterator ca_iter;
  97. for (ca_iter = clientAppActive_.begin(); 
  98.      ca_iter != clientAppActive_.end(); ca_iter++) {
  99. ca_iter->second->stop();
  100. tcl.evalf ("delete %s", ca_iter->second->name());
  101. clientAppActive_.erase (ca_iter);
  102. }
  103. // delete active servers in the pool
  104. map<string, PackMimeHTTPServerApp*>::iterator sa_iter;
  105. for (sa_iter = serverAppActive_.begin(); 
  106.      sa_iter != serverAppActive_.end(); sa_iter++) {
  107. sa_iter->second->stop();
  108. tcl.evalf ("delete %s", sa_iter->second->name());
  109. serverAppActive_.erase (sa_iter);
  110. }
  111. // delete clients in pool
  112. PackMimeHTTPClientApp* cli;
  113. while (!clientAppPool_.empty()) {
  114. cli = clientAppPool_.front();
  115. cli->stop();
  116. tcl.evalf ("delete %s", cli->name());
  117. clientAppPool_.pop();
  118. }
  119. // delete servers in pool
  120. PackMimeHTTPServerApp* srv;
  121. while (!serverAppPool_.empty()) {
  122. srv = serverAppPool_.front();
  123. srv->stop();
  124. tcl.evalf ("delete %s", srv->name());
  125. serverAppPool_.pop();
  126. }
  127. // delete agents in the pool
  128. FullTcpAgent* tcp;
  129. while (!tcpPool_.empty()) {
  130. tcp = tcpPool_.front();
  131. tcl.evalf ("delete %s", tcp->name());
  132. tcpPool_.pop();
  133. }
  134. // delete RNGs and Random Variables
  135. cleanup();
  136. // close output files
  137. if (outfp_)
  138. fclose(outfp_);
  139.   if (fileszfp_)
  140.   fclose(fileszfp_);
  141.   if (samplesfp_)
  142.   fclose(samplesfp_);
  143. }
  144. FullTcpAgent* PackMimeHTTP::picktcp()
  145. {
  146. FullTcpAgent* a;
  147. Tcl& tcl = Tcl::instance();
  148. if (tcpPool_.empty()) {
  149. tcl.evalf ("%s alloc-tcp %s", name(), tcptype_);
  150. a = (FullTcpAgent*) lookup_obj (tcl.result());
  151. if (a == NULL) {
  152. fprintf (stderr, "Failed to allocate a TCP agentn");
  153. abort();
  154. }
  155. if (debug_ > 1) {
  156. fprintf (stderr, 
  157.  "tflow %d created new TCPAgent %sn",
  158.  total_connections_, a->name());
  159. }
  160. } else {
  161. a = tcpPool_.front();  // grab top of the queue
  162. tcpPool_.pop();         // remove top from queue
  163. if (debug_ > 1) {
  164. fprintf (stderr, "tflow %d got TCPAgent %s", 
  165.  total_connections_, a->name());
  166. fprintf (stderr, " from pool (%d in pool)n",
  167.  (int) tcpPool_.size());
  168. }
  169. }
  170. return a;
  171. }
  172. PackMimeHTTPServerApp* PackMimeHTTP::pickServerApp()
  173. {
  174. PackMimeHTTPServerApp* a;
  175. if (serverAppPool_.empty()) {
  176. Tcl& tcl = Tcl::instance();
  177. tcl.evalf ("%s alloc-server-app", name());
  178. a = (PackMimeHTTPServerApp*) lookup_obj (tcl.result());
  179. if (a == NULL) {
  180. fprintf (stderr, 
  181. "Failed to allocate a PackMimeHTTP server appn");
  182. abort();
  183. }
  184. if (debug_ > 1)
  185. fprintf (stderr, "tflow %d created new ",
  186.  total_connections_);
  187. } else {
  188. a = serverAppPool_.front();   // grab top of the queue
  189. serverAppPool_.pop();         // remove top from queue
  190. if (debug_ > 1)
  191. fprintf (stderr, "tflow %d got ", 
  192.  total_connections_);
  193. }
  194. // initialize server app
  195. a->set_id(total_connections_);
  196. a->set_mgr(this);
  197. if (debug_ > 1)
  198. fprintf (stderr, "ServerApp %s (%d in pool, %d active)n",
  199.  a->name(), (int) serverAppPool_.size(), 
  200.  (int) serverAppActive_.size()+1);
  201. return a;
  202. }
  203. PackMimeHTTPClientApp* PackMimeHTTP::pickClientApp()
  204. {
  205. PackMimeHTTPClientApp* a;
  206. if (clientAppPool_.empty()) {
  207. Tcl& tcl = Tcl::instance();
  208. tcl.evalf ("%s alloc-client-app", name());
  209. a = (PackMimeHTTPClientApp*) lookup_obj (tcl.result());
  210. if (a == NULL) {
  211. fprintf (stderr, 
  212. "Failed to allocate a PackMimeHTTP client appn");
  213. abort();
  214. }
  215. if (debug_ > 1)
  216. fprintf (stderr, "tflow %d created new ",
  217.  total_connections_);
  218. } else {
  219. a = clientAppPool_.front();   // grab top of the queue
  220. clientAppPool_.pop();         // remove top from queue
  221. if (debug_ > 1)
  222. fprintf (stderr, "tflow %d got ", 
  223.  total_connections_);
  224. }
  225. // initialize client app
  226. a->set_id(total_connections_);
  227. a->set_mgr(this);
  228. if (debug_ > 1)
  229. fprintf (stderr, "ClientApp %s (%d in pool, %d active)n",
  230.  a->name(), (int) clientAppPool_.size(), 
  231.  (int) clientAppActive_.size()+1);
  232. return a;
  233. }
  234. void PackMimeHTTP::recycle(FullTcpAgent* agent)
  235. {
  236. /*
  237.  * Problem is that server apps are "done" before client apps,
  238.  * so server agents and apps get recycled and re-used before
  239.  * client apps & agents that were attached to them are
  240.  *
  241.  */
  242. if (agent == NULL) {
  243. fprintf (stderr, "recycle> agent is nulln");
  244. return;
  245. }
  246. // reinitialize FullTcp agent
  247. agent->reset();
  248. // add to the inactive agent pool
  249. tcpPool_.push (agent);
  250. if (debug_ > 2) {
  251. fprintf (stderr, "tTCPAgent %s moved to pool ", 
  252.  agent->name());
  253. fprintf (stderr, "(%d in pool)n", (int) tcpPool_.size());
  254. }
  255. }
  256. void PackMimeHTTP::recycle(PackMimeHTTPClientApp* app)
  257. {
  258. if (app == NULL)
  259. return;
  260. // find the client app in the active pool
  261. map<string, PackMimeHTTPClientApp*>::iterator ca_iter = 
  262. clientAppActive_.find(app->get_agent_name());
  263. if (ca_iter == clientAppActive_.end()) 
  264. return;
  265. // remove the client app from the active pool
  266. clientAppActive_.erase(ca_iter);
  267. // insert the client app into the inactive pool
  268. clientAppPool_.push (app);
  269. if (debug_ > 2) {
  270. fprintf (stderr, "tClientApp %s (%d) moved to pool ", 
  271.  app->name(), app->get_id());
  272. fprintf (stderr, "(%d in pool, %d active)n", 
  273.  (int) clientAppPool_.size(), 
  274.  (int) clientAppActive_.size());
  275. }
  276. // recycle app
  277. app->recycle();
  278. }
  279. void PackMimeHTTP::recycle(PackMimeHTTPServerApp* app)
  280. {
  281. if (app == NULL)
  282. return;
  283. // find the server app in the active pool
  284. map<string, PackMimeHTTPServerApp*>::iterator sa_iter = 
  285. serverAppActive_.find(app->get_agent_name());
  286. if (sa_iter == serverAppActive_.end()) 
  287. return;
  288. // remove the server app from the active pool
  289. serverAppActive_.erase(sa_iter);
  290. // insert the server app into the inactive pool
  291. serverAppPool_.push (app);
  292. if (debug_ > 2) {
  293. fprintf (stderr, "tServerApp %s (%d) moved to pool ",
  294.  app->name(), app->get_id());
  295. fprintf (stderr, "(%d in pool, %d active)n", 
  296.  (int) serverAppPool_.size(), 
  297.  (int) serverAppActive_.size());
  298. }
  299. // recycle app
  300. app->recycle();
  301. }
  302. double PackMimeHTTP::connection_interval() 
  303. {
  304. return connection_interval_;
  305. }
  306. /* HTTP 1.0 functions */
  307. int PackMimeHTTP::get_reqsize() 
  308. {
  309. return (int) (reqsize_rv_->value());
  310. }
  311. int PackMimeHTTP::get_rspsize() 
  312. {
  313. return (int) (rspsize_rv_->value());
  314. }
  315. double PackMimeHTTP::get_server_delay() 
  316. return server_delay_rv_->value();
  317. }
  318. /* HTTP 1.1 functions */
  319. bool PackMimeHTTP::is_persistent()
  320. {
  321. double val = persistent_rv_->value();
  322. if (val == 0) {
  323. return false;
  324. } else {
  325. return true;
  326. }
  327. }
  328. int PackMimeHTTP::get_num_pages()
  329. {
  330. return (int) ceil(num_pages_rv_->value());
  331. }
  332. int PackMimeHTTP::get_num_objs (int pages)
  333. {
  334. int p_singleobj = 0;
  335. int objs = 1;
  336. if (pages > 1) {
  337. // find probabilty there's only one obj in this page
  338. p_singleobj = (int) single_obj_rv_->value();
  339. }
  340. if (p_singleobj == 0) {
  341. objs = (int) ceil(objs_per_page_rv_->value());
  342. if (objs == 1) {
  343. // should be at least 2 objs at this point
  344. objs++;
  345. }
  346. }
  347. return objs;
  348. }
  349. double PackMimeHTTP::get_reqgap (int page, int obj)
  350. {
  351. double val;
  352. if (page == 0 && obj == 0) {
  353. // first request
  354. val = 0;
  355. }
  356. else if (page != 0 && obj == 0) {
  357. // main page (between-page requests)
  358. val = time_btwn_pages_rv_->value();
  359. }
  360. else {
  361. // embedded objects (within-page requests)
  362. val = time_btwn_objs_rv_->value();
  363. }
  364. return val;
  365. }
  366. int PackMimeHTTP::adjust_persist_rspsz()
  367. {
  368. return (int) persist_rspsize_rv_->value();
  369. }
  370. void PackMimeHTTP::reset_persist_rspsz()
  371. {
  372. persist_rspsize_rv_->reset_loc_scale();
  373. }
  374. void PackMimeHTTP::incr_pairs()
  375. /*
  376.  * Keep track of the number of req/rsp pairs 
  377.  */
  378. {
  379. cur_pairs_++;
  380. }
  381. void PackMimeHTTP::setup_connection()
  382. /*
  383.  * Setup a new connection, including creation of Agents and Apps
  384.  */
  385. {
  386. Tcl& tcl = Tcl::instance();
  387. // incr count of connections
  388. active_connections_++;
  389. total_connections_++;
  390. if (debug_ > 1) {
  391. fprintf (stderr, 
  392.  "nPackMimeHTTP %s> new flow %d  total active: %d at %fn",
  393.  name(), total_connections_, active_connections_, now());
  394. }
  395. // pick tcp agent for client and server
  396. FullTcpAgent* ctcp = picktcp();
  397. FullTcpAgent* stcp = picktcp();
  398. // rotate through nodes assigning connections
  399. current_node_++;
  400. if (current_node_ >= total_nodes_)
  401. current_node_ = 0;
  402. // attach agents to nodes (server_ client_)
  403. tcl.evalf ("%s attach %s", server_[current_node_]->name(), 
  404.    stcp->name());
  405. tcl.evalf ("%s attach %s", client_[current_node_]->name(), 
  406.    ctcp->name());
  407. // set TCP options
  408. tcl.evalf ("%s setup-tcp %s %d", name(), stcp->name(), 
  409.    total_connections_);
  410. tcl.evalf ("%s setup-tcp %s %d", name(), ctcp->name(),
  411.    total_connections_);
  412. // setup connection between client and server
  413. tcl.evalf ("set ns [Simulator instance]");
  414. tcl.evalf ("$ns connect %s %s", ctcp->name(), stcp->name());
  415. tcl.evalf ("%s listen", stcp->name());
  416. // create PackMimeHTTPApps
  417. PackMimeHTTPClientApp* client_app = pickClientApp();
  418. PackMimeHTTPServerApp* server_app = pickServerApp();
  419. // attach TCPs to PackMimeHTTPApps
  420. ctcp->attachApp ((Application*) client_app);
  421. stcp->attachApp ((Application*) server_app);
  422. client_app->set_server(server_app);
  423. client_app->set_agent(ctcp);
  424. server_app->set_agent(stcp);
  425. // put apps in active list
  426. clientAppActive_[ctcp->name()] = client_app;
  427. serverAppActive_[stcp->name()] = server_app;
  428. // start PackMimeHTTPApps
  429. client_app->start();
  430. server_app->start();
  431. // set time for next connection to start
  432. connection_interval_ = flowarrive_rv_->value();
  433. }
  434. void PackMimeHTTP::start()
  435. {            
  436. int i;
  437. // make sure that we have the same number of server nodes
  438. // and client nodes
  439. if (next_client_ind_ != next_server_ind_) {
  440. fprintf (stderr, "Error: %d clients and %d servers", 
  441.  next_client_ind_, next_server_ind_);
  442. exit(-1);
  443. }
  444. total_nodes_ = next_client_ind_;
  445. running_ = 1;
  446. // initialize PackMimeHTTP random variables
  447. if (flowarrive_rv_ == NULL) {
  448. flowarrive_rng_ = (RNG*) new RNG();
  449. // select proper substream
  450. for (i=0; i<run_; i++) {
  451. flowarrive_rng_->reset_next_substream();
  452. }
  453. flowarrive_rv_ = (PackMimeHTTPFlowArriveRandomVariable*) new
  454. PackMimeHTTPFlowArriveRandomVariable (rate_,
  455.       flowarrive_rng_);
  456. if (debug_ > 1) {
  457. fprintf (stderr, "Created FlowArrive RNG and RVn");
  458. }
  459. }
  460. if (reqsize_rv_ == NULL) {
  461. reqsize_rng_ = (RNG*) new RNG();
  462. // select proper substream
  463. for (i=0; i<run_; i++) {
  464. reqsize_rng_->reset_next_substream();
  465. }
  466. reqsize_rv_ = (PackMimeHTTPFileSizeRandomVariable*) new
  467. PackMimeHTTPFileSizeRandomVariable (rate_, 
  468. PACKMIME_REQ_SIZE,
  469.     reqsize_rng_);
  470. if (debug_ > 1) {
  471. fprintf (stderr, "Created ReqSize RNG and RVn");
  472. }
  473. }
  474. if (rspsize_rv_ == NULL) {
  475. rspsize_rng_ = (RNG*) new RNG();
  476. // select proper substream
  477. for (i=0; i<run_; i++) {
  478. rspsize_rng_->reset_next_substream();
  479. }
  480. rspsize_rv_ = (PackMimeHTTPFileSizeRandomVariable*) new
  481. PackMimeHTTPFileSizeRandomVariable (rate_, 
  482. PACKMIME_RSP_SIZE,
  483.     rspsize_rng_);
  484. if (debug_ > 1) {
  485. fprintf (stderr, "Created RspSize RNG and RVn");
  486. }
  487. }
  488. if (server_delay_rv_ == NULL) {
  489. server_delay_rng_ = (RNG*) new RNG();
  490. // select proper substream
  491. for (i=0; i<run_; i++) {
  492. server_delay_rng_->reset_next_substream();
  493. }
  494. server_delay_rv_ = (PackMimeHTTPServerDelayRandomVariable*) new 
  495. PackMimeHTTPServerDelayRandomVariable 
  496. (PackMimeHTTPServerDelayRandomVariable::SERVER_DELAY_SHAPE, 
  497.  PackMimeHTTPServerDelayRandomVariable::SERVER_DELAY_SCALE, 
  498.  server_delay_rng_);
  499. if (debug_ > 1) {
  500. fprintf (stderr, "Created ServerDelay RNG and RVn");
  501. }
  502. }
  503. if (persist_rspsize_rv_ == NULL) {
  504. persist_rspsize_rng_ = (RNG*) new RNG();
  505. // select proper substream
  506. for (i=0; i<run_; i++) {
  507. persist_rspsize_rng_->reset_next_substream();
  508. }
  509. persist_rspsize_rv_ = (PackMimeHTTPPersistRspSizeRandomVariable*) new 
  510. PackMimeHTTPPersistRspSizeRandomVariable(persist_rspsize_rng_);
  511. if (debug_ > 1) {
  512. fprintf (stderr, "Created Persistent RspSz RNG and RVn");
  513. }
  514. }
  515. if (persistent_rv_ == NULL) {
  516. persistent_rng_ = (RNG*) new RNG();
  517. // select proper substream
  518. for (i=0; i<run_; i++) {
  519. persistent_rng_->reset_next_substream();
  520. }
  521. persistent_rv_ = (PackMimeHTTPPersistentRandomVariable*) new 
  522. PackMimeHTTPPersistentRandomVariable
  523. (PackMimeHTTPPersistentRandomVariable::P_PERSISTENT,
  524.  persistent_rng_);
  525. if (debug_ > 1) {
  526. fprintf (stderr, "Created Persistent RNG and RVn");
  527. }
  528. }
  529. if (num_pages_rv_ == NULL) {
  530. num_pages_rng_ = (RNG*) new RNG();
  531. // select proper substream
  532. for (i=0; i<run_; i++) {
  533. num_pages_rng_->reset_next_substream();
  534. }
  535. num_pages_rv_ = (PackMimeHTTPNumPagesRandomVariable*) new 
  536. PackMimeHTTPNumPagesRandomVariable
  537. (PackMimeHTTPNumPagesRandomVariable::P_1PAGE,
  538.  PackMimeHTTPNumPagesRandomVariable::SHAPE_NPAGE,
  539.  PackMimeHTTPNumPagesRandomVariable::SCALE_NPAGE,
  540.  num_pages_rng_);
  541. if (debug_ > 1) {
  542. fprintf (stderr, "Created Number of Pages RNG and RVn");
  543. }
  544. }
  545. if (single_obj_rv_ == NULL) {
  546. single_obj_rng_ = (RNG*) new RNG();
  547. // select proper substream
  548. for (i=0; i<run_; i++) {
  549. single_obj_rng_->reset_next_substream();
  550. }
  551. single_obj_rv_ = (PackMimeHTTPSingleObjRandomVariable*) new 
  552. PackMimeHTTPSingleObjRandomVariable
  553. (PackMimeHTTPSingleObjRandomVariable::P_1TRANSFER,
  554.  single_obj_rng_);
  555. if (debug_ > 1) {
  556. fprintf (stderr, "Created Single Objects RNG and RVn");
  557. }
  558. }
  559. if (objs_per_page_rv_ == NULL) {
  560. objs_per_page_rng_ = (RNG*) new RNG();
  561. // select proper substream
  562. for (i=0; i<run_; i++) {
  563. objs_per_page_rng_->reset_next_substream();
  564. }
  565. objs_per_page_rv_ = (PackMimeHTTPObjsPerPageRandomVariable*) new 
  566. PackMimeHTTPObjsPerPageRandomVariable
  567. (PackMimeHTTPObjsPerPageRandomVariable::SHAPE_NTRANSFER,
  568.  PackMimeHTTPObjsPerPageRandomVariable::SCALE_NTRANSFER,
  569.  objs_per_page_rng_);
  570. if (debug_ > 1) {
  571. fprintf (stderr, "Created Objects Per Page RNG and RVn");
  572. }
  573. }
  574. if (time_btwn_pages_rv_ == NULL) {
  575. time_btwn_pages_rng_ = (RNG*) new RNG();
  576. // select proper substream
  577. for (i=0; i<run_; i++) {
  578. time_btwn_pages_rng_->reset_next_substream();
  579. }
  580. time_btwn_pages_rv_ = (PackMimeHTTPTimeBtwnPagesRandomVariable*) new 
  581. PackMimeHTTPTimeBtwnPagesRandomVariable(time_btwn_pages_rng_);
  582. if (debug_ > 1) {
  583. fprintf (stderr, "Created Time Btwn Pages RNG and RVn");
  584. }
  585. }
  586. if (time_btwn_objs_rv_ == NULL) {
  587. time_btwn_objs_rng_ = (RNG*) new RNG();
  588. // select proper substream
  589. for (i=0; i<run_; i++) {
  590. time_btwn_objs_rng_->reset_next_substream();
  591. }
  592. time_btwn_objs_rv_ = (PackMimeHTTPTimeBtwnObjsRandomVariable*) new 
  593. PackMimeHTTPTimeBtwnObjsRandomVariable(time_btwn_objs_rng_);
  594. if (debug_ > 1) {
  595. fprintf (stderr, "Created Time Btwn Objs RNG and RVn");
  596. }
  597. }
  598. // schedule first connection
  599. timer_.sched (0);
  600. }
  601. void PackMimeHTTP::stop()
  602. {
  603. running_ = 0;
  604. }
  605. void PackMimeHTTP::cleanup()
  606. {
  607. // delete all 'new'ed variables
  608. if (reqsize_rv_ != NULL) {
  609. delete reqsize_rv_;
  610. }
  611. if (rspsize_rv_ != NULL) {
  612. delete rspsize_rv_;
  613. }
  614. if (persist_rspsize_rv_ != NULL) {
  615. delete persist_rspsize_rv_;
  616. }
  617. if (flowarrive_rv_ != NULL) {
  618. delete flowarrive_rv_;
  619. }
  620. if (server_delay_rv_ != NULL) {
  621. delete server_delay_rv_;
  622. }
  623. if (persistent_rv_ != NULL) {
  624. delete persistent_rv_;
  625. }
  626. if (num_pages_rv_ != NULL) {
  627. delete num_pages_rv_;
  628. }
  629. if (single_obj_rv_ != NULL) {
  630. delete single_obj_rv_;
  631. }
  632. if (objs_per_page_rv_ != NULL) {
  633. delete objs_per_page_rv_;
  634. }
  635. if (time_btwn_pages_rv_ != NULL) {
  636. delete time_btwn_pages_rv_;
  637. }
  638. if (time_btwn_objs_rv_ != NULL) {
  639. delete time_btwn_objs_rv_;
  640. }
  641. if (flowarrive_rng_ != NULL) {
  642. delete flowarrive_rng_;
  643. }
  644. if (reqsize_rng_ != NULL) {
  645. delete reqsize_rng_;
  646. }
  647. if (rspsize_rng_ != NULL) {
  648. delete rspsize_rng_;
  649. }
  650. if (server_delay_rng_ != NULL) {
  651. delete server_delay_rng_;
  652. }
  653. if (persistent_rng_ != NULL) {
  654. delete persistent_rng_;
  655. }
  656. if (num_pages_rng_ != NULL) {
  657. delete num_pages_rng_;
  658. }
  659. if (single_obj_rng_ != NULL) {
  660. delete single_obj_rng_;
  661. }
  662. if (objs_per_page_rng_ != NULL) {
  663. delete objs_per_page_rng_;
  664. }
  665. if (time_btwn_pages_rng_ != NULL) {
  666. delete time_btwn_pages_rng_;
  667. }
  668. if (time_btwn_objs_rng_ != NULL) {
  669. delete time_btwn_objs_rng_;
  670. }
  671. }
  672. int PackMimeHTTP::command(int argc, const char*const* argv) {
  673. if (argc == 2) {
  674. if (!strcmp (argv[1], "start")) {
  675. start();
  676. return (TCL_OK);
  677. }
  678. else if (!strcmp (argv[1], "stop")) {
  679. stop();
  680. return (TCL_OK);
  681. }
  682. else if ((!strcmp (argv[1], "set-1.1")) ||
  683.  (!strcmp (argv[1], "set-http-1.1"))) {
  684. http_1_1_ = true;
  685. return (TCL_OK);
  686. }
  687. else if (!strcmp (argv[1], "active-connections")) {
  688. if (outfp_) {
  689. fprintf (outfp_, "%d ", active_connections_);
  690. fflush (outfp_);
  691. }
  692. else
  693. fprintf (stderr, "%d ", active_connections_);
  694. return (TCL_OK);
  695. }
  696. else if (!strcmp (argv[1], "total-connections")) {
  697. fprintf (stderr, "%d ", total_connections_);
  698. return (TCL_OK);
  699. }
  700. else if (strcmp (argv[1], "get-pairs") == 0) {
  701. Tcl &tcl = Tcl::instance();
  702. tcl.resultf("%d", cur_pairs_);
  703. return (TCL_OK);
  704. }
  705. else if (!strcmp (argv[1], "no-pm-persistent-reqsz")) {
  706. use_pm_persist_reqsz_ = false;
  707. return (TCL_OK);
  708. }
  709. else if (!strcmp (argv[1], "no-pm-persistent-rspsz")) {
  710. use_pm_persist_rspsz_ = false;
  711. return (TCL_OK);
  712. }
  713. }
  714. else if (argc == 3) {
  715. if ((!strcmp (argv[1], "set-client")) 
  716.     || (!strcmp (argv[1], "client"))) {
  717. if (next_client_ind_ >= MAX_NODES) {
  718. return (TCL_ERROR);
  719. }
  720. client_[next_client_ind_] = (Node*) 
  721. lookup_obj(argv[2]);
  722. if (client_[next_client_ind_] == NULL) {
  723. return (TCL_ERROR);
  724. }
  725. next_client_ind_++;
  726. return (TCL_OK);
  727. }
  728. else if ((!strcmp (argv[1], "set-server")) || 
  729.  (!strcmp (argv[1], "server"))) {
  730. if (next_server_ind_ >= MAX_NODES) {
  731. return (TCL_ERROR);
  732. }
  733. server_[next_server_ind_] = (Node*) 
  734. lookup_obj(argv[2]);
  735. if (server_[next_server_ind_] == NULL)
  736. return (TCL_ERROR);
  737. next_server_ind_++;
  738. return (TCL_OK);
  739. }
  740. else if (!strcmp (argv[1], "set-TCP")) {
  741. strcpy (tcptype_, argv[2]);
  742. return (TCL_OK);
  743. }
  744. else if ((!strcmp (argv[1], "set-rate")) ||
  745.  (!strcmp (argv[1], "rate"))) {
  746. rate_ = (double) atof (argv[2]);
  747. return (TCL_OK);
  748. }
  749. else if (!strcmp (argv[1], "set-outfile")) {
  750. outfp_ = fopen (argv[2], "w");
  751. if (outfp_)
  752. return (TCL_OK);
  753. else 
  754. return (TCL_ERROR);
  755. }
  756. else if (!strcmp (argv[1], "set-filesz-outfile")) {
  757.   fileszfp_ = fopen (argv[2], "w");
  758.   if (fileszfp_) 
  759.   return (TCL_OK);
  760.   else 
  761.   return (TCL_ERROR);
  762.   }
  763.   else if (!strcmp (argv[1], "set-samples-outfile")) {
  764.   samplesfp_ = fopen (argv[2], "w");
  765.   if (samplesfp_) 
  766.   return (TCL_OK);
  767.   else 
  768.   return (TCL_ERROR);
  769.   }
  770. else if (strcmp (argv[1], "set-req_size") == 0) {
  771. int res = lookup_rv (reqsize_rv_, argv[2]);
  772. if (res == TCL_ERROR) {
  773. fprintf (stderr, "Invalid req size ");
  774. fprintf (stderr, "random variablen");
  775. cleanup();
  776. return (TCL_ERROR);
  777. }
  778. return (TCL_OK);
  779. }
  780. else if (strcmp (argv[1], "set-rsp_size") == 0) {
  781. int res = lookup_rv (rspsize_rv_, argv[2]);
  782. if (res == TCL_ERROR) {
  783. fprintf (stderr, "Invalid rsp size ");
  784. fprintf (stderr, "random variablen");
  785. cleanup();
  786. return (TCL_ERROR);
  787. }
  788. return (TCL_OK);
  789. }
  790. else if (strcmp (argv[1], "set-flow_arrive") == 0) {
  791. int res = lookup_rv (flowarrive_rv_, argv[2]);
  792. if (res == TCL_ERROR) {
  793. fprintf (stderr,"Invalid flow arrive ");
  794. fprintf (stderr, "random variablen");
  795. cleanup();
  796. return (TCL_ERROR);
  797. }
  798. return (TCL_OK);
  799. }
  800. else if (strcmp (argv[1], "set-server_delay") == 0) {
  801. int res = lookup_rv (server_delay_rv_, argv[2]);
  802. if (res == TCL_ERROR) {
  803. fprintf (stderr,"Invalid server delay ");
  804. fprintf (stderr, "random variablen");
  805. cleanup();
  806. return (TCL_ERROR);
  807. }
  808. return (TCL_OK);
  809. }
  810. else if (!strcmp (argv[1], "set-prob_persistent")) {
  811. int res = lookup_rv (persistent_rv_, argv[2]);
  812. if (res == TCL_ERROR) {
  813. fprintf (stderr,"Invalid percent persistent ");
  814. fprintf (stderr, "random variablen");
  815. cleanup();
  816. return (TCL_ERROR);
  817. }
  818. return (TCL_OK);
  819. }
  820. else if (!strcmp (argv[1], "set-num_pages")) {
  821. int res = lookup_rv (num_pages_rv_, argv[2]);
  822. if (res == TCL_ERROR) {
  823. fprintf (stderr,"Invalid number of pages ");
  824. fprintf (stderr, "random variablen");
  825. cleanup();
  826. return (TCL_ERROR);
  827. }
  828. return (TCL_OK);
  829. }
  830. else if (!strcmp (argv[1], "set-prob_single_obj")) {
  831. int res = lookup_rv (single_obj_rv_, argv[2]);
  832. if (res == TCL_ERROR) {
  833. fprintf (stderr,"Invalid probability single obj ");
  834. fprintf (stderr, "random variablen");
  835. cleanup();
  836. return (TCL_ERROR);
  837. }
  838. return (TCL_OK);
  839. }
  840. else if (!strcmp (argv[1], "set-objs_per_page")) {
  841. int res = lookup_rv (objs_per_page_rv_, argv[2]);
  842. if (res == TCL_ERROR) {
  843. fprintf (stderr,"Invalid objects per page ");
  844. fprintf (stderr, "random variablen");
  845. cleanup();
  846. return (TCL_ERROR);
  847. }
  848. return (TCL_OK);
  849. }
  850. else if (!strcmp (argv[1], "set-time_btwn_pages")) {
  851. int res = lookup_rv (time_btwn_pages_rv_, argv[2]);
  852. if (res == TCL_ERROR) {
  853. fprintf (stderr,"Invalid time between pages ");
  854. fprintf (stderr, "random variablen");
  855. cleanup();
  856. return (TCL_ERROR);
  857. }
  858. return (TCL_OK);
  859. }
  860. else if (!strcmp (argv[1], "set-time_btwn_objs")) {
  861. int res = lookup_rv (time_btwn_objs_rv_, argv[2]);
  862. if (res == TCL_ERROR) {
  863. fprintf (stderr,"Invalid time between objs ");
  864. fprintf (stderr, "random variablen");
  865. cleanup();
  866. return (TCL_ERROR);
  867. }
  868. return (TCL_OK);
  869. }
  870. else if (strcmp (argv[1], "set-ID") == 0) {
  871. ID_ = (int) atoi (argv[2]);
  872. return (TCL_OK);
  873. }
  874. else if (strcmp (argv[1], "set-run") == 0) {
  875. run_ = (int) atoi (argv[2]);
  876. return (TCL_OK);
  877. }
  878. else if (strcmp (argv[1], "set-debug") == 0) {
  879. debug_ = (int) atoi (argv[2]);
  880. return (TCL_OK);
  881. }
  882. else if (strcmp (argv[1], "set-warmup") == 0) {
  883. warmup_ = (int) atoi (argv[2]);
  884. return (TCL_OK);
  885. }
  886. else if (strcmp (argv[1], "recycle") == 0) {
  887. FullTcpAgent* tcp = (FullTcpAgent*) 
  888. lookup_obj(argv[2]);
  889. /*
  890.  * Need to wait to recycle server until client
  891.  * is done.  Fortunately, client has
  892.  * a handle to the server.
  893.  */
  894. // find client app associated with this agent
  895. map<string, PackMimeHTTPClientApp*>::iterator ca_iter = 
  896. clientAppActive_.find(tcp->name());
  897. if (ca_iter == clientAppActive_.end()) {
  898. // this isn't a client app, but a server app
  899. return (TCL_OK);
  900. }
  901. PackMimeHTTPClientApp* ca = ca_iter->second;
  902. PackMimeHTTPServerApp* sa = ca->get_server();
  903. FullTcpAgent* stcp = (FullTcpAgent*) 
  904. lookup_obj(sa->get_agent_name());
  905. if (debug_ > 1)
  906.       fprintf (stderr, "client %s (%d)> DONE at %fn",
  907.  ca->name(), ca->get_id(), now());
  908. // remove apps from active pools and put 
  909. // in inactive pools
  910. recycle ((FullTcpAgent*) tcp);
  911. recycle ((FullTcpAgent*) stcp);
  912. recycle (ca);
  913. recycle (sa);
  914. active_connections_--;   // one less active conn
  915. return (TCL_OK);
  916. }
  917. }
  918. return TclObject::command(argc, argv);
  919. }
  920. /*:::::::::::::::::::::::::::: PACKMIMETIMER ::::::::::::::::::::::::::::::::*/
  921. void PackMimeHTTPTimer::expire(Event* = 0) 
  922. {
  923. }
  924. void PackMimeHTTPTimer::handle(Event* e)
  925. {
  926. if (!mgr_->running()) {
  927. if (mgr_->get_active() != 0) {
  928. TimerHandler::handle(e);
  929. sched (1);              // check back in 1 second...
  930. }
  931. return;
  932. }
  933. // setup new connection
  934. mgr_->setup_connection();
  935. TimerHandler::handle(e);
  936. // schedule time for next connection
  937. if (mgr_->debug() > 1) {
  938. fprintf (stderr, "tnext connection scheduled in %f s...n", 
  939.  mgr_->connection_interval());
  940. }
  941. sched (mgr_->connection_interval());
  942. }
  943. /*:::::::::::::::::::::::::: PACKMIMECLIENTAPP ::::::::::::::::::::::::::::::*/
  944. void PackMimeHTTPClientAppTimer::expire(Event* = 0)
  945. {
  946. }
  947. void PackMimeHTTPClientAppTimer::handle(Event* e)
  948. {
  949. t_->timeout();
  950. TimerHandler::handle(e);
  951. }
  952. static class PackMimeHTTPClientAppClass : public TclClass {
  953. public:
  954. PackMimeHTTPClientAppClass() : TclClass("Application/PackMimeHTTP/Client") {}
  955. TclObject* create(int, const char*const*) {
  956. return (new PackMimeHTTPClientApp);
  957. }
  958. } class_app_packmime_client;
  959. PackMimeHTTPClientApp::~PackMimeHTTPClientApp()
  960. {
  961. Tcl& tcl = Tcl::instance();
  962. if (agent_ != NULL) {
  963. tcl.evalf ("delete %s", agent_->name());
  964. }
  965. if (reqsize_array_ != NULL) {
  966. delete []reqsize_array_;
  967. }
  968. if (rspsize_array_ != NULL) {
  969. delete []rspsize_array_;
  970. }
  971. if (reqgap_array_ != NULL) {
  972. delete []reqgap_array_;
  973. }
  974. }
  975. void PackMimeHTTPClientApp::start()
  976. {
  977. running_ = 1;
  978. timer_.sched(0);   // send data now
  979. }
  980. void PackMimeHTTPClientApp::stop()
  981. {
  982. running_ = 0;
  983. }
  984. void PackMimeHTTPClientApp::recycle()
  985. {
  986. id_ = 0;
  987. rspsize_ = 0;
  988. totalbytes_ = 0;
  989. agent_ = NULL;
  990. server_ = NULL;
  991. reqs_ = 0;
  992. array_ind_ = 0;
  993. if (reqsize_array_ != NULL) {
  994. delete []reqsize_array_;
  995. }
  996. if (rspsize_array_ != NULL) {
  997. delete []rspsize_array_;
  998. }
  999. if (reqgap_array_ != NULL) {
  1000. delete []reqgap_array_;
  1001. }
  1002. reqsize_array_ = NULL;
  1003. rspsize_array_ = NULL;
  1004. reqgap_array_ = NULL;
  1005. }
  1006. void PackMimeHTTPClientApp::timeout()
  1007. {
  1008. /* Time to generate a new request */
  1009. int i, j, pages, objs, ind;
  1010. int* objs_per_page;
  1011. int reqsz, rspsz;
  1012. if (!running_) {
  1013. return;
  1014. }
  1015. /*
  1016.  * Client should get reqsize and rspsize so that for the same
  1017.  * seed, there will be the same request/response pairs.
  1018.  */
  1019. if (mgr_->using_http_1_1() && reqs_ == 0) {
  1020. // determine if this connection is persistent
  1021. persistent_ = mgr_->is_persistent();
  1022. }
  1023. if (persistent_ && reqs_ == 0) {
  1024. // need to sample the request gaps and file sizes
  1025. // get number of pages in this connection
  1026. pages = mgr_->get_num_pages();
  1027. objs_per_page = new int[pages];
  1028. for (i=0; i<pages; i++) {
  1029. // get number of objects on this page
  1030. objs = mgr_->get_num_objs(pages);
  1031. objs_per_page[i] = objs;
  1032. reqs_ += objs;
  1033. }
  1034. // allocate space for request gaps and file sizes
  1035. if (reqgap_array_ == NULL) {
  1036. reqgap_array_ = new double[reqs_];
  1037. }
  1038. if (reqsize_array_ == NULL) {
  1039. reqsize_array_ = new int[reqs_];
  1040. }
  1041. if (rspsize_array_ == NULL) {
  1042. rspsize_array_ = new int[reqs_];
  1043. }
  1044. // fill the arrays
  1045. ind = 0;
  1046. reqsz = mgr_->get_reqsize();
  1047. rspsz = mgr_->get_rspsize();
  1048. for (i=0; i<pages; i++) {
  1049. for (j=0; j<objs_per_page[i]; j++) {
  1050. // sample inter-request time
  1051. reqgap_array_[ind] = mgr_->get_reqgap(i,j);
  1052. // all requests are same size
  1053. reqsize_array_[ind] = reqsz;
  1054. if (!mgr_->use_pm_persist_reqsz() && ind > 0) {
  1055. reqsize_array_[ind] = mgr_->get_reqsize();
  1056. }
  1057. // all responses start out as same size
  1058. rspsize_array_[ind] = rspsz;
  1059. // for non-PM rspsz, choose new response size
  1060. if (!mgr_->use_pm_persist_rspsz() && ind > 0) {
  1061. rspsize_array_[ind] = mgr_->get_rspsize();
  1062. }
  1063. ind++;
  1064. }
  1065. }
  1066. if (mgr_->use_pm_persist_rspsz()) {
  1067. // adjust response sizes
  1068. if (reqs_ > 1 && 
  1069.     rspsz > 
  1070.     PackMimeHTTPPersistRspSizeRandomVariable::FSIZE_CACHE_CUTOFF) {
  1071. for (i=1; i<reqs_; i++) {
  1072. // leave rspsize_array_[0] alone
  1073. rspsize_array_[i] = 
  1074. mgr_->adjust_persist_rspsz();
  1075. }
  1076. }
  1077. mgr_->reset_persist_rspsz();
  1078. }
  1079. array_ind_ = 0;
  1080. delete [] objs_per_page;
  1081. }
  1082. if (persistent_) {
  1083. // get the current request size
  1084. reqsize_ = reqsize_array_[array_ind_];
  1085. // get the current response size
  1086. rspsize_ = rspsize_array_[array_ind_++];
  1087. }
  1088. else {
  1089. reqs_ = 1;
  1090. // get request size
  1091. reqsize_ = mgr_->get_reqsize();
  1092. // get response size
  1093. rspsize_ = mgr_->get_rspsize();
  1094. }
  1095. // check for 0-byte request or response
  1096. if (reqsize_ == 0) 
  1097. reqsize_ = 1;
  1098. if (rspsize_ == 0) 
  1099. rspsize_ = 1;
  1100. server_->set_reqs(reqs_);
  1101. if (reqs_ == 1 || array_ind_ == reqs_) {
  1102. server_->set_last_req();
  1103. }
  1104. server_->set_reqsize(reqsize_);
  1105. server_->set_rspsize(rspsize_);
  1106. // save time of request
  1107. time_of_req_ = mgr_->now();
  1108. // dump request size and response size
  1109.   FILE* fp = mgr_->get_samplesfp();
  1110.   if (fp) {
  1111.   char* nodeaddr = 
  1112.   Address::instance().print_nodeaddr(agent_->daddr());
  1113.   char* portaddr = 
  1114.   Address::instance().print_nodeaddr(agent_->dport());
  1115.   fprintf (fp, "%-11.6f %-10d %-10d %s.%-6sn",
  1116.    time_of_req_, reqsize_, rspsize_, nodeaddr, portaddr);
  1117.   fflush (fp);
  1118.   }
  1119. // send request
  1120. agent_->sendmsg(reqsize_);
  1121. if (mgr_->debug() > 1)
  1122. fprintf (stderr, "client %s (%d)> sent %d-byte req (%d-byte rsp) at %fn",
  1123.  name(), id_, reqsize_, rspsize_, time_of_req_);
  1124. }
  1125. void PackMimeHTTPClientApp::recv(int bytes)
  1126. {
  1127. // we've received a packet
  1128. if (mgr_->debug() > 3)
  1129. fprintf (stderr, "client %s (%d)> received %d bytes at %fn", 
  1130.  name(), id_, bytes, mgr_->now());
  1131. totalbytes_ += bytes;
  1132. if (totalbytes_ == rspsize_) {
  1133. // we've received all packets from server
  1134. if (mgr_->debug() > 1) {
  1135. fprintf (stderr, "client %s (%d)> received ",
  1136.  name(), id_);
  1137. fprintf (stderr, "total of %d bytes at %fn", 
  1138.  rspsize_, mgr_->now());
  1139. }
  1140. if (reqs_ == 1 || array_ind_ == reqs_) {
  1141. // either only 1 request or we've sent all requests
  1142. stop();
  1143. }
  1144. else {
  1145. // schedule next request time
  1146. timer_.sched(reqgap_array_[array_ind_]);
  1147. }
  1148. if (time_of_req_ >= mgr_->get_warmup()) {
  1149. // if we're dumping output, dump now
  1150. double now = mgr_->now();
  1151. FILE* fp = mgr_->get_outfp();
  1152. char* dst_nodeaddr = 
  1153.     Address::instance().print_nodeaddr(agent_->daddr());
  1154. char* dst_portaddr = 
  1155.     Address::instance().print_nodeaddr(agent_->dport());
  1156. if (fp) {
  1157. fprintf (fp, "%-11.6f %-10d %-10d %-10.3f %s.%-6s %-7dn",
  1158.  now, reqsize_, rspsize_, 
  1159.  (now - time_of_req_) * 1000.0, 
  1160.  dst_nodeaddr, dst_portaddr,
  1161.  mgr_->get_active());
  1162. fflush (fp);
  1163. }
  1164. }
  1165. // increment number of pairs completed
  1166. mgr_->incr_pairs();
  1167. // reset totalbytes
  1168. totalbytes_ = 0;
  1169. }
  1170. }
  1171. /*:::::::::::::::::::::::::: PACKMIMESERVERAPP ::::::::::::::::::::::::::::::*/
  1172. void PackMimeHTTPServerAppTimer::expire(Event* = 0)
  1173. {
  1174. }
  1175. void PackMimeHTTPServerAppTimer::handle(Event* e)
  1176. {
  1177. t_->timeout();
  1178. TimerHandler::handle(e);
  1179. }
  1180. static class PackMimeHTTPServerAppClass : public TclClass {
  1181. public:
  1182. PackMimeHTTPServerAppClass() : TclClass("Application/PackMimeHTTP/Server") {}
  1183. TclObject* create(int, const char*const*) {
  1184. return (new PackMimeHTTPServerApp);
  1185. }
  1186. } class_app_packmime_server;
  1187. PackMimeHTTPServerApp::~PackMimeHTTPServerApp()
  1188. {
  1189. Tcl& tcl = Tcl::instance();
  1190. if (agent_ != NULL) {
  1191. tcl.evalf ("delete %s", agent_->name());
  1192. }
  1193. }
  1194. void PackMimeHTTPServerApp::timeout()
  1195. {
  1196. if (!running_) {
  1197. return;
  1198. }
  1199. if (mgr_->debug() > 1) {
  1200. fprintf(stderr,"server %s (%d)> sent %d-byte response at %fn",
  1201. name(), id_, rspsize_, mgr_->now());
  1202. }
  1203. // dump all request size and response sizes
  1204.   double now = mgr_->now();
  1205.   FILE* fp = mgr_->get_fileszfp();
  1206.   if (fp) {
  1207.   char* nodeaddr = 
  1208.   Address::instance().print_nodeaddr(agent_->addr());
  1209.   char* portaddr = 
  1210.   Address::instance().print_nodeaddr(agent_->port());
  1211. fprintf (fp, "%-11.6f %-10d %-10d %s.%-6sn",
  1212.    now, reqsize_, rspsize_, nodeaddr, portaddr);
  1213.   fflush (fp);
  1214.   }
  1215. // send response
  1216. if (reqs_ == 1 || lastreq_) {
  1217. // this is the last message
  1218. agent_->sendmsg(rspsize_, "MSG_EOF");
  1219. stop();
  1220. }
  1221. else {
  1222. agent_->sendmsg(rspsize_);
  1223. }
  1224. }
  1225. void PackMimeHTTPServerApp::stop()
  1226. {
  1227. running_ = 0;
  1228. }
  1229. void PackMimeHTTPServerApp::recycle()
  1230. {
  1231. id_ = 0;
  1232. reqsize_ = 0;
  1233. rspsize_ = 0;
  1234. totalbytes_ = 0;
  1235. agent_ = NULL;
  1236. reqs_ = 0;
  1237. lastreq_ = false;
  1238. }
  1239. void PackMimeHTTPServerApp::recv(int bytes)
  1240. {
  1241. double delay;
  1242. if (!running_) {
  1243. return;
  1244. }
  1245. totalbytes_ += bytes;
  1246. // we've received a packet
  1247. if (mgr_->debug() > 3)
  1248. fprintf (stderr, "server %s (%d)> received %d bytes at %fn", 
  1249.  name(), id_, bytes, mgr_->now());
  1250. if (totalbytes_ == reqsize_) {
  1251. // generate waiting time
  1252. delay = mgr_->get_server_delay();
  1253. if (mgr_->debug() > 1) {
  1254. fprintf (stderr, 
  1255.  "server %s (%d)> received total of %d bytes from clientn",
  1256.  name(), id_, reqsize_);
  1257. fprintf (stderr, 
  1258.  "server %s (%d)> waiting %f s before responding at %fn", 
  1259.  name(), id_, delay, mgr_->now());
  1260. }
  1261. // send data after waiting server delay seconds
  1262. timer_.sched(delay);   
  1263. // reset totalbytes_
  1264. totalbytes_ = 0;
  1265. }
  1266. }