Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EchoBehavior.cc

Go to the documentation of this file.
00001 #include "EchoBehavior.h"
00002 #include "Wireless/Wireless.h"
00003 #include "Shared/string_util.h"
00004 #include "Events/TextMsgEvent.h"
00005 #include <vector>
00006 #include <string>
00007 
00008 using namespace std;
00009 
00010 EchoBehavior* EchoBehavior::theOne=NULL;
00011 unsigned short EchoBehavior::port=11011;
00012 const char * const EchoBehavior::routeNames[EchoBehavior::NUM_ROUTE] = 
00013 {
00014   "TCP Server", "UDP Server","TCP Client","UDP Client"
00015 };
00016 
00017 void EchoBehavior::DoStart() {
00018   BehaviorBase::DoStart(); // do this first (required)
00019   setupNetwork();
00020   erouter->addListener(this,EventBase::textmsgEGID);
00021 }
00022 
00023 void EchoBehavior::DoStop() {
00024   erouter->removeListener(this);
00025   teardownNetwork();
00026   BehaviorBase::DoStop(); // do this last (required)
00027 }
00028 
00029 void EchoBehavior::setupNetwork() {
00030   sockets[STCP]=wireless->socket(Socket::SOCK_STREAM);
00031   sockets[SUDP]=wireless->socket(Socket::SOCK_DGRAM);
00032   socks[STCP]=sockets[STCP]->sock;
00033   socks[SUDP]=sockets[SUDP]->sock;
00034   wireless->setDaemon(sockets[STCP],true);
00035   wireless->setDaemon(sockets[SUDP],true);
00036   wireless->setReceiver(sockets[STCP]->sock, server_callbackT);
00037   wireless->setReceiver(sockets[SUDP]->sock, server_callbackU);
00038   wireless->listen(sockets[STCP]->sock, port);
00039   wireless->listen(sockets[SUDP]->sock, port);
00040 }
00041 
00042 void EchoBehavior::teardownNetwork() {
00043   wireless->setDaemon(sockets[STCP],false);
00044   wireless->setDaemon(sockets[SUDP],false);
00045   wireless->close(sockets[STCP]);
00046   wireless->close(sockets[SUDP]);
00047   if(sockets[CTCP]!=NULL && wireless->isConnected(socks[CTCP]))
00048     wireless->close(sockets[CTCP]);
00049   if(sockets[CUDP]!=NULL && wireless->isConnected(socks[CUDP]))
00050     wireless->close(sockets[CUDP]);
00051   for(unsigned int i=0; i<NUM_ROUTE; i++)
00052     sockets[i]=NULL;
00053 }
00054 
00055 void EchoBehavior::processEvent(const EventBase& e) {
00056   //Check for connections which have just been closed
00057   for(unsigned int i=0; i<NUM_ROUTE; i++)
00058     if(sockets[i]!=NULL && !sockets[i]->getDaemon() && !wireless->isConnected(socks[i]))
00059       sockets[i]=NULL;
00060 
00061   //handle the event
00062   if(const TextMsgEvent * msg = dynamic_cast<const TextMsgEvent*>(&e)) {
00063     vector<string> args;
00064     vector<unsigned int> offs;
00065     string_util::parseArgs(msg->getText(),args,offs);
00066     if(args.size()==0)
00067       return;
00068     if(args[0]=="open") {
00069       if(args.size()<4) {
00070         serr->printf("syntax: %s (tcp|udp) host port\n",args[0].c_str());
00071         return;
00072       }
00073       if(string_util::makeLower(args[1])=="tcp") {
00074         if(sockets[CTCP]==NULL) {
00075           sockets[CTCP]=wireless->socket(Socket::SOCK_STREAM);
00076           socks[CTCP]=sockets[CTCP]->sock;
00077           wireless->setReceiver(sockets[CTCP], client_callbackT);
00078         }
00079         wireless->connect(sockets[CTCP],args[2].c_str(),atoi(args[3].c_str()));
00080       } else if(string_util::makeLower(args[1])=="udp") {
00081         if(sockets[CUDP]==NULL) {
00082           sockets[CUDP]=wireless->socket(Socket::SOCK_DGRAM);
00083           socks[CUDP]=sockets[CUDP]->sock;
00084           wireless->setReceiver(sockets[CUDP], client_callbackU);
00085         }
00086         wireless->connect(sockets[CUDP],args[2].c_str(),atoi(args[3].c_str()));
00087       } else {
00088         serr->printf("syntax: %s (tcp|udp) host port\n",args[0].c_str());
00089         serr->printf("  first argument '%s' must be either 'tcp' or 'udp'\n",args[1].c_str());
00090         return;
00091       }
00092     } else if(args[0]=="status") {
00093       cout << "Listening on port " << port << endl;
00094       for(unsigned int i=0; i<NUM_ROUTE; i++)
00095         cout << routeNames[i] << ": " << (sockets[i]!=NULL && wireless->isConnected(socks[i]) ? "Connected" : "Not Connected") << endl;
00096       for(unsigned int i=0; i<NUM_ROUTE; i++) {
00097         cout << "Route from " << routeNames[i] << ": ";
00098         for(unsigned int j=0; j<NUM_ROUTE; j++)
00099           cout << route[i][j] << ' ';
00100         cout << endl;
00101       }
00102     } else if(args[0]=="relay" || args[0]=="unlink") {
00103       unsigned char from=(unsigned char)-1U;
00104       unsigned char to=(unsigned char)-1U;
00105       bool val = (args[0]=="relay");
00106       unsigned int i=1;
00107       for(; i<args.size(); i++) {
00108         if(string_util::makeLower(args[i])=="to")
00109           break;
00110         intersect(from,args[i]);
00111       }
00112       if(i==args.size()) {
00113         serr->printf("syntax: %s [udp|tcp|client|server]* to [udp|tcp|client|server]*\n",args[0].c_str());
00114         return;
00115       }
00116       i++;
00117       for(; i<args.size(); i++)
00118         intersect(to,args[i]);
00119       for(unsigned int r=0; r<NUM_ROUTE; r++) {
00120         if(from & (1<<r))
00121           for(unsigned int j=0; j<NUM_ROUTE; j++)
00122             if(to & (1<<j))
00123               route[r][j]=val;
00124       }
00125     } else if(args[0]=="port") {
00126       int p=atoi(args[1].c_str());
00127       if(p==0) {
00128         serr->printf("invalid port value\n");
00129         return;
00130       }
00131       port=p;
00132       teardownNetwork();
00133       setupNetwork();
00134     } else {
00135       for(unsigned int i=0; i<NUM_ROUTE; i++)
00136         if(sockets[i]!=NULL)
00137           sockets[i]->printf("%s\n",msg->getText().c_str());
00138     }
00139   } else {
00140     serr->printf("Bad event received: %s\n",e.getName().c_str());
00141   }
00142 }
00143 
00144 void EchoBehavior::intersect(unsigned char& bits, std::string arg) {
00145   arg=string_util::makeLower(arg);
00146   unsigned char mask=0;
00147   if(arg=="server")
00148     mask = (1<<SUDP) | (1<<STCP) ;
00149   else if(arg=="client")
00150     mask = (1<<CUDP) | (1<<CTCP) ;
00151   else if(arg=="tcp")
00152     mask = (1<<STCP) | (1<<CTCP) ;
00153   else if(arg=="udp")
00154     mask = (1<<SUDP) | (1<<CUDP) ;
00155   else
00156     cerr << "Unknown argument '" << arg << "'" << endl;
00157   bits&=mask;
00158 }
00159 
00160 void EchoBehavior::processCallback(EchoBehavior::routeIndex_t src, char *buf, int bytes) {
00161   buf[bytes]='\0'; //hack - better hope it's not a full buffer
00162   sout->printf("From %s:%d\n",sockets[src]->getPeerAddressAsString().c_str(),sockets[src]->getPeerPort());
00163   sout->printf("Message is: '%s'\n",buf);
00164   
00165   //udp server doesn't automatically connect
00166   if(src==SUDP && sockets[SUDP]!=NULL && !wireless->isConnected(socks[SUDP])) {
00167     for(unsigned int i=0; i<NUM_ROUTE; i++)
00168       if(route[i][SUDP]) {
00169         //we found someone who wants to send output to the udp server, so we'd better connect it
00170         wireless->connect(sockets[SUDP],sockets[SUDP]->getPeerAddressAsString().c_str(),sockets[SUDP]->getPeerPort());
00171         break;
00172       }
00173   } 
00174   
00175   for(unsigned int i=0; i<NUM_ROUTE; i++) {
00176     if(route[src][i] && sockets[i]!=NULL) {
00177       if(wireless->isConnected(socks[i]))
00178         sockets[i]->write((byte*)buf,bytes);
00179       else if(!sockets[i]->getDaemon())
00180         sockets[i]=NULL;
00181     }
00182   }
00183 }
00184 int EchoBehavior::server_callbackT(char *buf, int bytes) {
00185   cout << "TCP Server received " << bytes << " bytes" << endl;
00186   theOne->processCallback(STCP,buf,bytes);
00187   return 0;
00188 }
00189 int EchoBehavior::client_callbackT(char *buf, int bytes) {
00190   cout << "TCP Client received " << bytes << " bytes" << endl;
00191   theOne->processCallback(CTCP,buf,bytes);
00192   return 0;
00193 }
00194 int EchoBehavior::server_callbackU(char *buf, int bytes) {
00195   cout << "UDP Server received " << bytes << " bytes" << endl;
00196   theOne->processCallback(SUDP,buf,bytes);
00197   return 0;
00198 }
00199 int EchoBehavior::client_callbackU(char *buf, int bytes) {
00200   cout << "UDP Client received " << bytes << " bytes" << endl;
00201   theOne->processCallback(CUDP,buf,bytes);
00202   return 0;
00203 }
00204 
00205 
00206 /*! @file
00207  * @brief 
00208  * @author Ethan Tira-Thompson (ejt) (Creator)
00209  *
00210  * $Author: ejt $
00211  * $Name: tekkotsu-4_0 $
00212  * $Revision: 1.5 $
00213  * $State: Exp $
00214  * $Date: 2007/05/21 20:51:20 $
00215  */

Tekkotsu v4.0
Generated Thu Nov 22 00:54:52 2007 by Doxygen 1.5.4