00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "agent.h"
00026 #include "app.h"
00027 #include "tcpapp.h"
00028
00029
00030
00031
00032 CBuf::CBuf(AppData *c, int nbytes)
00033 {
00034 nbytes_ = nbytes;
00035 size_ = c->size();
00036 if (size_ > 0)
00037 data_ = c;
00038 else
00039 data_ = NULL;
00040 next_ = NULL;
00041 }
00042
00043 CBufList::~CBufList()
00044 {
00045 while (head_ != NULL) {
00046 tail_ = head_;
00047 head_ = head_->next_;
00048 delete tail_;
00049 }
00050 }
00051
00052 void CBufList::insert(CBuf *cbuf)
00053 {
00054 if (tail_ == NULL)
00055 head_ = tail_ = cbuf;
00056 else {
00057 tail_->next_ = cbuf;
00058 tail_ = cbuf;
00059 }
00060 #ifdef TCPAPP_DEBUG
00061 num_++;
00062 #endif
00063 }
00064
00065 CBuf* CBufList::detach()
00066 {
00067 if (head_ == NULL)
00068 return NULL;
00069 CBuf *p = head_;
00070 if ((head_ = head_->next_) == NULL)
00071 tail_ = NULL;
00072 #ifdef TCPAPP_DEBUG
00073 num_--;
00074 #endif
00075 return p;
00076 }
00077
00078
00079
00080
00081 class TcpAppString : public AppData {
00082 private:
00083 int size_;
00084 char* str_;
00085 public:
00086 TcpAppString() : AppData(TCPAPP_STRING), size_(0), str_(NULL) {}
00087 TcpAppString(TcpAppString& d) : AppData(d) {
00088 size_ = d.size_;
00089 if (size_ > 0) {
00090 str_ = new char[size_];
00091 strcpy(str_, d.str_);
00092 } else
00093 str_ = NULL;
00094 }
00095 virtual ~TcpAppString() {
00096 if (str_ != NULL)
00097 delete []str_;
00098 }
00099
00100 char* str() { return str_; }
00101 virtual int size() const { return AppData::size() + size_; }
00102
00103
00104 void set_string(const char* s) {
00105 if ((s == NULL) || (*s == 0))
00106 str_ = NULL, size_ = 0;
00107 else {
00108 size_ = strlen(s) + 1;
00109 str_ = new char[size_];
00110 assert(str_ != NULL);
00111 strcpy(str_, s);
00112 }
00113 }
00114 virtual AppData* copy() {
00115 return new TcpAppString(*this);
00116 }
00117 };
00118
00119
00120 static class TcpCncClass : public TclClass {
00121 public:
00122 TcpCncClass() : TclClass("Application/TcpApp") {}
00123 TclObject* create(int argc, const char*const* argv) {
00124 if (argc != 5)
00125 return NULL;
00126 Agent *tcp = (Agent *)TclObject::lookup(argv[4]);
00127 if (tcp == NULL)
00128 return NULL;
00129 return (new TcpApp(tcp));
00130 }
00131 } class_tcpcnc_app;
00132
00133 TcpApp::TcpApp(Agent *tcp) :
00134 Application(), curdata_(0), curbytes_(0)
00135 {
00136 agent_ = tcp;
00137 agent_->attachApp(this);
00138 }
00139
00140 TcpApp::~TcpApp()
00141 {
00142
00143
00144 agent_->attachApp(NULL);
00145 }
00146
00147
00148 void TcpApp::send(int nbytes, AppData *cbk)
00149 {
00150 CBuf *p = new CBuf(cbk, nbytes);
00151 #ifdef TCPAPP_DEBUG
00152 p->time() = Scheduler::instance().clock();
00153 #endif
00154 cbuf_.insert(p);
00155 Application::send(nbytes);
00156 }
00157
00158
00159 void TcpApp::recv(int size)
00160 {
00161
00162
00163 if (curdata_ == 0)
00164 curdata_ = dst_->rcvr_retrieve_data();
00165 if (curdata_ == 0) {
00166 fprintf(stderr, "[%g] %s receives a packet but no callback!\n",
00167 Scheduler::instance().clock(), name_);
00168 return;
00169 }
00170 curbytes_ += size;
00171 #ifdef TCPAPP_DEBUG
00172 fprintf(stderr, "[%g] %s gets data size %d, %s\n",
00173 Scheduler::instance().clock(), name(), curbytes_,
00174 curdata_->data());
00175 #endif
00176 if (curbytes_ == curdata_->bytes()) {
00177
00178
00179 process_data(curdata_->size(), curdata_->data());
00180
00181 delete curdata_;
00182 curdata_ = NULL;
00183 curbytes_ = 0;
00184 } else if (curbytes_ > curdata_->bytes()) {
00185
00186
00187 while (curbytes_ >= curdata_->bytes()) {
00188 process_data(curdata_->size(), curdata_->data());
00189 curbytes_ -= curdata_->bytes();
00190 #ifdef TCPAPP_DEBUG
00191 fprintf(stderr,
00192 "[%g] %s gets data size %d(left %d)\n",
00193 Scheduler::instance().clock(),
00194 name(),
00195 curdata_->bytes(), curbytes_);
00196
00197 #endif
00198 delete curdata_;
00199 curdata_ = dst_->rcvr_retrieve_data();
00200 if (curdata_ != 0)
00201 continue;
00202 if ((curdata_ == 0) && (curbytes_ > 0)) {
00203 fprintf(stderr, "[%g] %s gets extra data!\n",
00204 Scheduler::instance().clock(), name_);
00205 Tcl::instance().eval("[Simulator instance] flush-trace");
00206 abort();
00207 } else
00208
00209 break;
00210 }
00211 }
00212 }
00213
00214 void TcpApp::resume()
00215 {
00216
00217 }
00218
00219 int TcpApp::command(int argc, const char*const* argv)
00220 {
00221 Tcl& tcl = Tcl::instance();
00222
00223 if (strcmp(argv[1], "connect") == 0) {
00224 dst_ = (TcpApp *)TclObject::lookup(argv[2]);
00225 if (dst_ == NULL) {
00226 tcl.resultf("%s: connected to null object.", name_);
00227 return (TCL_ERROR);
00228 }
00229 dst_->connect(this);
00230 return (TCL_OK);
00231 } else if (strcmp(argv[1], "send") == 0) {
00232
00233
00234
00235 int size = atoi(argv[2]);
00236 if (argc == 3)
00237 send(size, NULL);
00238 else {
00239 TcpAppString *tmp = new TcpAppString();
00240 tmp->set_string(argv[3]);
00241 send(size, tmp);
00242 }
00243 return (TCL_OK);
00244 } else if (strcmp(argv[1], "dst") == 0) {
00245 tcl.resultf("%s", dst_->name());
00246 return TCL_OK;
00247 }
00248 return Application::command(argc, argv);
00249 }
00250
00251 void TcpApp::process_data(int size, AppData* data)
00252 {
00253 if (data == NULL)
00254 return;
00255
00256
00257 if (target())
00258 send_data(size, data);
00259 else if (data->type() == TCPAPP_STRING) {
00260 TcpAppString *tmp = (TcpAppString*)data;
00261 Tcl::instance().eval(tmp->str());
00262 }
00263 }