#include "agent.h"
#include "app.h"
#include "TCPSocketApp.h"
static class TcpAppIntClass : public TclClass {
public:
TcpAppIntClass() : TclClass("Application/TCPSocketApp") {}
TclObject* create(int argc, const char*const* argv) {
if (argc != 5)
return NULL;
Agent *tcp = (Agent *)TclObject::lookup(argv[4]);
if (tcp == NULL)
return NULL;
return (new TCPSocketApp(tcp));
}
} class_TCPSocketApp;
TCPSocketApp::TCPSocketApp(Agent *tcp) :
Application(), curdata_(0), readOffset(0), bytesSent_(0), curbytes_(0) {
setTCPAgent(tcp);
}
TCPSocketApp::~TCPSocketApp() {
agent_->attachApp(NULL);
}
void TCPSocketApp::setTCPAgent(Agent *tcp) {
agent_ = tcp;
agent_->attachApp(this);
}
TcpData* TCPSocketApp::receiveDataFromClient() {
PLOG(PL_DEBUG, "LJT Entering TCPSocketApp:: receiveDataFromClient\n");
TcpData* data = (TcpData*)tcpDataList_.getTail();
if (data!=NULL) tcpDataList_.remove((ListItem *)data);
PLOG(PL_DEBUG, "LJT Leaving TCPSocketApp:: receiveDataFromClient\n");
return data;
}
AppData* TCPSocketApp::get_data(int&, AppData*) {
PLOG(PL_FATAL, "TCPSokcetApp: get_data called - aborting ...\n");
abort();
return NULL;
}
void TCPSocketApp::send(AppData *cbk) {
PLOG(PL_DEBUG, "TCPSocketApp:: Send Called\n");
TcpData *tcpData = (TcpData*)cbk;
int nbytes = tcpData->getDataSize();
PLOG(PL_DEBUG, "TCPSocketApp:: Send Called after cast\n");
tcpDataList_.prepend(tcpData);
PLOG(PL_DETAIL, "TCPSocketApp:: Send Called, sending %i bytes\n", tcpData->getDataSize());
PLOG(PL_DETAIL, "TCPSocketApp sending: %s\n", tcpData->getData());
PLOG(PL_DEBUG, "TCPSocketApp:: Sending bytes now \n");
Application::send(nbytes);
if (connectedSocketApp==NULL) {
PLOG(PL_ERROR, "TCPSocketApp::getDataFromOtherSocket, Destination for SocketApp is NULL -> the setup is incorrect. Check the code\n");
exit(0);
}
connectedSocketApp->setBytesSent(nbytes);
PLOG(PL_DEBUG, "TCPSocketApp:: Send Called \n");
}
void TCPSocketApp::getDataFromOtherSocket() {
if (connectedSocketApp==NULL) {
PLOG(PL_ERROR, "TCPSocketApp::getDataFromOtherSocket, Destination for SocketApp is NULL -> the setup is incorrect. Check the code\n");
exit(0);
}
curdata_ = connectedSocketApp->receiveDataFromClient();
if ((curdata_ == 0) || (curdata_->getDataSize()==0)) {
PLOG(PL_DEBUG, "TCPSocketApp::getDataFromOtherSocket, received data from TCP but no data to read!\n");
abort();
}
}
void TCPSocketApp::recv(int tcpDataArrivedSize) {
PLOG(PL_DEBUG, "TCPSocketApp::recv, tcpDataArrivedSize = %i, cur - %i\n", tcpDataArrivedSize, curbytes_);
if (curdata_ == 0)
getDataFromOtherSocket();
if (curdata_ == 0) {
fprintf(stderr, "[%g] %s receives a packet but no callback!\n",
Scheduler::instance().clock(), name_);
return;
}
curbytes_ += tcpDataArrivedSize;
if (curbytes_ == curdata_->getDataSize()) {
PLOG(PL_DEBUG, "TCPSocketApp::recv, equal and buffered data size = %i\n", curdata_->getDataSize());
upcallToApp(curdata_->getData(), curdata_->getDataSize());
delete curdata_;
curdata_ = NULL;
curbytes_ = 0;
} else if (curbytes_ > curdata_->getDataSize()) {
PLOG(PL_DEBUG, "TCPSocketApp::recv, not equal and buffered data size = %i\n", curdata_->getDataSize());
while (curbytes_ >= curdata_->getDataSize()) {
upcallToApp(curdata_->getData(), curdata_->getDataSize());
curbytes_ -= curdata_->getDataSize();
delete curdata_;
getDataFromOtherSocket();
if (curdata_ != 0)
continue;
if ((curdata_ == 0) && (curbytes_ > 0)) {
fprintf(stderr, "[%g] %s gets extra data!\n",
Scheduler::instance().clock(), name_);
Tcl::instance().eval("[Simulator instance] flush-trace");
abort();
} else
break;
}
}
}
void TCPSocketApp::upcallToApp(char* data, unsigned int size)
{
PLOG(PL_DEBUG, "TCPSocketApp:: upcallToApp called \n");
if (data == NULL)
return;
PLOG(PL_DEBUG, "TCPSocketApp:: upcallToApp, receiving size %i \n", size);
if (target()) {
TcpData *tcpdata = new TcpData();
tcpdata->setData(data,size);
PLOG(PL_DETAIL, "TCPSocketApp:: upcallToApp, Sending to Target\n");
send_data(size, tcpdata);
PLOG(PL_DETAIL, "TCPSocketApp: upcallToApp, finished Sending Data to Target\n");
} else if (tcpSocketListenerAgent) { PLOG(PL_DETAIL, "TCPSocketApp:: upcallToApp, Sending to Listener\n");
char* datasend = new char[size];
memcpy(datasend, data, size);
tcpSocketListenerAgent->tcpEventReceived(new TCPEvent(TCPEvent::RECEIVE, NULL, datasend, size));
PLOG(PL_DETAIL, "TCPSocketApp: upcallToApp, finished Callback\n");
}
else {
PLOG(PL_INFO, "TCPSocketApp: Receiving %i of size %i at node %i\n", data, size, getTCPAgent()->addr());
}
}
void TCPSocketApp::resume()
{
}
int TCPSocketApp::command(int argc, const char*const* argv)
{
Tcl& tcl = Tcl::instance();
if (strcmp(argv[1], "connect") == 0) {
connectedSocketApp = (TCPSocketApp *)TclObject::lookup(argv[2]);
if (connectedSocketApp == NULL) {
tcl.resultf("%s: connected to null object.", name_);
return (TCL_ERROR);
}
connectedSocketApp->connect(this);
return (TCL_OK);
} else if (strcmp(argv[1], "send") == 0) {
const char *bytes = argv[3];
int size = atoi(argv[2]);
if (argc > 3) {
TcpData *tmp = new TcpData();
tmp->setData(bytes, size);
send(tmp);
}
return (TCL_OK);
} else if (strcmp(argv[1], "dst") == 0) {
tcl.resultf("%s", connectedSocketApp->name());
return TCL_OK;
}
return Application::command(argc, argv);
}