Homepage
Demos
Overview
Downloads
Tutorials
Reference
Credits

Wireless.cc

Go to the documentation of this file.
00001 #include "Wireless.h"
00002 #include "Socket.h"
00003 #include <cstring>
00004 
00005 Wireless *wireless=NULL;
00006 
00007 #ifdef PLATFORM_APERIOS
00008 #  include <OPENR/OSyslog.h>
00009 #  include <OPENR/OPENRAPI.h>
00010 #  include <ant.h>
00011 #  include <EndpointTypes.h>
00012 #  include <TCPEndpointMsg.h>
00013 #  include <UDPEndpointMsg.h>
00014 #  include "aperios/MMCombo/entry.h"
00015 
00016 using namespace SocketNS;
00017 using namespace std;
00018 
00019 Wireless::Wireless ()
00020   : ipstackRef(), myOID(), freeSockets(), usedSockets()
00021 {
00022   ipstackRef = antStackRef("IPStack");
00023   WhoAmI(&myOID);
00024 
00025   sockets[0]=new DummySocket(0);
00026   for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
00027     sockets[sock]=NULL;
00028     freeSockets.push_back(sock);
00029   }
00030 }    
00031 
00032 Wireless::~Wireless ()
00033 {
00034   if(usedSockets.size()>0) {
00035     cerr << "WARNING: Wireless deleted with open Sockets" << endl;
00036     for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
00037       delete sockets[*it];
00038       sockets[*it]=NULL;
00039     }
00040     freeSockets.insert(freeSockets.end(),usedSockets.begin(),usedSockets.end());
00041     usedSockets.clear();
00042   }
00043 }
00044 
00045 Socket* Wireless::socket(TransportType_t ttype)
00046 {
00047   return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
00048 }
00049 
00050 Socket* Wireless::socket(TransportType_t ttype, int recvsize, int sendsize)
00051 {
00052   if (freeSockets.empty()
00053       || (recvsize + sendsize) <= 256) return sockets[0];
00054   int sock_num=freeSockets.front();
00055   freeSockets.pop_front();
00056   usedSockets.push_back(sock_num);
00057 
00058   sockets[sock_num]=new Socket(sock_num);
00059   sockets[sock_num]->sendBufSize=sendsize;
00060   sockets[sock_num]->recvBufSize=recvsize;
00061   sockets[sock_num]->setTransport(ttype);
00062 
00063   // setup send buffer
00064   antEnvCreateSharedBufferMsg sendBufferMsg(sendsize*2);
00065   sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
00066   if (sendBufferMsg.error != ANT_SUCCESS) return sockets[0];
00067 
00068   sockets[sock_num]->sendBuffer = sendBufferMsg.buffer;
00069   sockets[sock_num]->sendBuffer.Map();
00070   sockets[sock_num]->sendData = ( byte * ) ( sockets[sock_num]->sendBuffer.GetAddress() );
00071 
00072   // setup receive buffer
00073   antEnvCreateSharedBufferMsg recvBufferMsg(recvsize*2);
00074   recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
00075   if (recvBufferMsg.error != ANT_SUCCESS) return sockets[0];
00076 
00077   sockets[sock_num]->recvBuffer = recvBufferMsg.buffer;
00078   sockets[sock_num]->recvBuffer.Map();
00079   sockets[sock_num]->recvData = ( byte * ) ( sockets[sock_num]->recvBuffer.GetAddress() );
00080 
00081   sockets[sock_num]->readData = sockets[sock_num]->recvData + recvsize;
00082   sockets[sock_num]->writeData = sockets[sock_num]->sendData + sendsize;
00083 
00084   return sockets[sock_num]; 
00085 }
00086 
00087 int Wireless::listen(int sock, int port)
00088 {
00089   if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00090        || sockets[sock]->state != CONNECTION_CLOSED )return -1;
00091 
00092   sockets[sock]->server_port = port;
00093   sockets[sock]->init();
00094 
00095   if (sockets[sock]->trType==SocketNS::SOCK_STREAM) {
00096     // create endpoint
00097     antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
00098     tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
00099     if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
00100     sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
00101 
00102     // listen
00103     TCPEndpointListenMsg listenMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
00104     listenMsg.continuation = ( void * ) sock;
00105 
00106     listenMsg.Send( ipstackRef, myOID, Extra_Entry[entryListenCont], sizeof( listenMsg ) );
00107 
00108     sockets[sock]->state = CONNECTION_LISTENING;
00109     return 0;
00110   } else if (sockets[sock]->trType==SOCK_DGRAM) {
00111     // create endpoint
00112     antEnvCreateEndpointMsg udpCreateMsg( EndpointType_UDP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
00113     udpCreateMsg.Call( ipstackRef, sizeof( udpCreateMsg ) );
00114     if ( udpCreateMsg.error != ANT_SUCCESS ) return -1;
00115 
00116     // bind socket
00117     sockets[sock]->endpoint = udpCreateMsg.moduleRef;
00118     UDPEndpointBindMsg bindMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
00119     bindMsg.Call( ipstackRef, sizeof( bindMsg ) );
00120     bindMsg.continuation = ( void * ) sock;
00121 
00122     sockets[sock]->state = CONNECTION_CONNECTING;
00123 
00124     receive( sock );
00125 
00126     return 0;
00127 
00128   }
00129 
00130   else
00131     return -1;
00132 }
00133 
00134 /** Tell the ipstack we want to recieve messages with this function. */
00135 
00136 int Wireless::connect( int sock, const char * ipaddr, int port )
00137 {
00138   if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00139        || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CLOSED ) ) return -1;
00140 
00141   sockets[sock]->init();
00142   if (sockets[sock]->trType==SOCK_STREAM) {
00143     // create endpoint
00144     antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
00145     tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
00146     if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
00147     sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
00148 
00149     // connect
00150     TCPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, IP_ADDR_ANY, IP_PORT_ANY, ipaddr, port );
00151     connectMsg.continuation = ( void * ) sock;
00152 
00153     connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
00154     sockets[sock]->peer_addr=connectMsg.fAddress.Address();
00155     sockets[sock]->peer_port=connectMsg.fPort;
00156 
00157     sockets[sock]->state = CONNECTION_CONNECTING;
00158     return 0;
00159   }
00160 
00161   else if ( sockets[sock]->trType == SOCK_DGRAM )
00162     {
00163       // connect
00164       UDPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, ipaddr, port );
00165 
00166       connectMsg.continuation = ( void * ) sock;
00167 
00168       connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
00169       sockets[sock]->peer_addr=connectMsg.address.Address();
00170       sockets[sock]->peer_port=connectMsg.port;
00171 
00172       sockets[sock]->state = CONNECTION_CONNECTED;
00173       //std::cout << "Sock " << sock << " connected via UDP to IP " << ipaddr << " port " << port << std::flush << std::endl;
00174 
00175       return 0;
00176     }
00177 
00178   else
00179     {
00180       return -1;
00181     }
00182 }
00183 
00184 void
00185 Wireless::ListenCont(void* msg)
00186 {
00187   antEnvMsg * Msg = ( antEnvMsg * ) msg;
00188   int sock = ( int )( Msg->continuation );
00189 
00190   if ( sockets[sock]->trType == SOCK_STREAM )
00191     {
00192       TCPEndpointListenMsg * listenMsg = ( TCPEndpointListenMsg * ) msg;
00193 
00194       if ( listenMsg->error != TCP_SUCCESS )
00195         {
00196           sockets[sock]->state = CONNECTION_ERROR;
00197 
00198           // no use recycling since its a resource issue
00199           return;
00200         }
00201       sockets[sock]->peer_addr=listenMsg->fAddress.Address();
00202       sockets[sock]->peer_port=listenMsg->fPort;
00203 
00204       sockets[sock]->state = CONNECTION_CONNECTED;
00205       //sockets[sock]->local_ipaddr = listenMsg->lAddress.Address();
00206       //cout << "Listen set lip: " << local_ipaddr << endl;
00207       receive( sock );
00208     }
00209 }
00210 
00211 void
00212 Wireless::ConnectCont(void *msg)
00213 {
00214   antEnvMsg * Msg = ( antEnvMsg * ) msg;
00215   int sock = ( int )( Msg->continuation );
00216 
00217   if ( sockets[sock]->trType == SOCK_STREAM )
00218     {
00219       TCPEndpointConnectMsg * connectMsg = ( TCPEndpointConnectMsg * ) msg;
00220       if ( connectMsg->error != TCP_SUCCESS )
00221         {
00222           sockets[sock]->state = CONNECTION_ERROR;
00223           return;
00224         }
00225 
00226       sockets[sock]->state = CONNECTION_CONNECTED;
00227       //sockets[sock]->local_ipaddr = connectMsg->lAddress.Address();
00228       //cout << "Connect set lip: " << local_ipaddr << endl;
00229       receive( sock );
00230     }
00231 }
00232 
00233 void
00234 Wireless::BindCont(void *msg)
00235 {
00236   UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*)msg;
00237   int sock = (int)bindMsg->continuation;
00238 
00239   if (bindMsg->error != UDP_SUCCESS) {
00240     sockets[sock]->state = CONNECTION_ERROR;
00241     return;
00242   }
00243 
00244   sockets[sock]->state = CONNECTION_CONNECTED;
00245   /*  if(bindMsg->address.Address()!=0) {
00246     //sockets[sock]->local_ipaddr = bindMsg->address.Address();
00247     //cout << "Bind set lip: " << local_ipaddr << endl;
00248   } else {
00249     //cout << "Bind got 0" << endl;
00250     }*/
00251 }
00252 
00253 void
00254 Wireless::send(int sock)
00255 {
00256   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
00257        || sockets[sock]->sendSize <= 0 ) return;
00258 
00259   if ( sockets[sock]->trType == SOCK_STREAM )
00260     {
00261       TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
00262       sendMsg.continuation = ( void * ) sock;
00263 
00264       sockets[sock]->tx = true;
00265       sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( TCPEndpointSendMsg ) );
00266       sockets[sock]->sendSize = 0;
00267     }
00268 
00269   else if ( sockets[sock]->trType == SOCK_DGRAM )
00270     {
00271       UDPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
00272 
00273       // this field is just hijacked to id the socket # this message is being sent across
00274       sendMsg.continuation = ( void * ) sock;
00275 
00276       sockets[sock]->tx = true;
00277       sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( UDPEndpointSendMsg ) );
00278       sockets[sock]->sendSize = 0;
00279     }
00280 }
00281 
00282 void
00283 Wireless::SendCont(void* msg)
00284 {
00285   antEnvMsg * Msg = ( antEnvMsg * ) msg;
00286   int sock = ( int )( Msg->continuation );
00287 
00288   if ( sockets[sock]->trType == SOCK_STREAM )
00289     {
00290       TCPEndpointSendMsg * sendMsg = ( TCPEndpointSendMsg * ) msg;
00291       sockets[sock]->tx = false;
00292       if ( sendMsg->error != TCP_SUCCESS )
00293         {
00294           sockets[sock]->state = CONNECTION_ERROR;
00295           close( sock );
00296           return;
00297         }
00298     }
00299 
00300   else if ( sockets[sock]->trType == SOCK_DGRAM )
00301     {
00302       UDPEndpointSendMsg * sendMsg = ( UDPEndpointSendMsg * ) msg;
00303       sockets[sock]->tx = false;
00304       if ( sendMsg->error != UDP_SUCCESS )
00305         {
00306           sockets[sock]->state = CONNECTION_ERROR;
00307           close( sock );
00308           return;
00309         }
00310     }
00311 
00312   sockets[sock]->flush();
00313 }
00314 
00315 /*! @bug This doesn't actually seem to block until the message is
00316 * fully sent... a crash immediately after this will still cause a
00317 * line or two to be dropped.  This is still less dropped than
00318 * regular send, but doesn't do much good for debugging until we fix
00319 * this. (if we can...) */
00320 void
00321 Wireless::blockingSend(int sock)
00322 {
00323   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
00324        || sockets[sock]->sendSize <= 0 ) return;
00325 
00326   if ( sockets[sock]->trType == SOCK_STREAM )
00327     {
00328       TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
00329       sendMsg.continuation = ( void * ) sock;
00330 
00331       sockets[sock]->tx=true;
00332       sockets[sock]->sendSize = 0;
00333       sendMsg.Call( ipstackRef, sizeof( TCPEndpointSendMsg ) );
00334       sockets[sock]->tx = false;
00335     }
00336 
00337   // no double buffering
00338 }
00339 
00340 void
00341 Wireless::setReceiver(int sock, int (*rcvcbckfn) (char*, int) )
00342 {
00343   if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL) return;
00344 
00345   sockets[sock]->rcvcbckfn=rcvcbckfn;
00346 }
00347 
00348 void
00349 Wireless::receive(int sock)
00350 {
00351   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00352        || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CONNECTED ) )
00353     return;
00354 
00355   if ( sockets[sock]->trType == SOCK_STREAM )
00356     {
00357       TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
00358       receiveMsg.continuation = ( void * ) sock;
00359       receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
00360     }
00361 
00362   else if ( sockets[sock]->trType == SOCK_DGRAM )
00363     {
00364       UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
00365       receiveMsg.continuation = ( void * ) sock;
00366       receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
00367     }
00368 
00369   sockets[sock]->rx = true;
00370 }
00371 
00372 void
00373 Wireless::receive(int sock, int (*rcvcbckfn) (char*, int) )
00374 {
00375   if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
00376       || sockets[sock]->state != CONNECTION_CONNECTED) return;
00377 
00378   sockets[sock]->rcvcbckfn = rcvcbckfn;
00379 
00380   if ( sockets[sock]->trType == SOCK_STREAM )
00381     {
00382       TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
00383       receiveMsg.continuation = ( void * ) sock;
00384       receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
00385     }
00386 
00387   else if ( sockets[sock]->trType == SOCK_DGRAM )
00388     {
00389       UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
00390       receiveMsg.continuation = ( void * ) sock;
00391       receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
00392     }
00393 
00394   sockets[sock]->rx = true;
00395 }
00396 
00397 void
00398 Wireless::ReceiveCont(void* msg)
00399 {
00400   // get the socket index before casting the message into UDP or TCP form
00401   antEnvMsg * Msg = ( antEnvMsg * ) msg;
00402   int sock = ( int )( Msg->continuation );
00403 
00404   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00405        || ( sockets[sock]->state != CONNECTION_CONNECTED && sockets[sock]->state != CONNECTION_CONNECTING ) )
00406     return;
00407 
00408   if ( sockets[sock]->trType == SOCK_STREAM )
00409     {
00410       TCPEndpointReceiveMsg * receiveMsg = ( TCPEndpointReceiveMsg * ) msg;
00411       if ( receiveMsg->error != TCP_SUCCESS )
00412         {
00413           sockets[sock]->state = CONNECTION_ERROR;
00414           close( sock );
00415           return;
00416         }
00417 
00418       sockets[sock]->recvSize = receiveMsg->sizeMin;
00419       if ( sockets[sock]->rcvcbckfn != NULL )
00420         sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
00421       sockets[sock]->recvSize = 0;
00422 
00423     }
00424 
00425   else if ( sockets[sock]->trType == SOCK_DGRAM )
00426     {
00427       UDPEndpointReceiveMsg * receiveMsg;
00428       receiveMsg = ( UDPEndpointReceiveMsg * ) antEnvMsg::Receive( msg );
00429       sockets[sock]->recvSize = receiveMsg->size;
00430 
00431       if ( receiveMsg->error == UDP_SUCCESS )
00432         {
00433           // if this UDP connection is not connected yet, connect it
00434           // to the address & port of the computer that sent this message.
00435           // This allows us to send UDP messages to any address instead of
00436           // hard-coding a specific address beforehand
00437 
00438           sockets[sock]->peer_addr=receiveMsg->address.Address();
00439           sockets[sock]->peer_port=receiveMsg->port;
00440           if ( !strncmp( "connection request", ( char * ) sockets[sock]->recvData, 18 ) )
00441             {
00442               // clear this message from the receiving buffer
00443               sockets[sock]->recvData += sockets[sock]->recvSize;
00444 
00445               if ( sockets[sock]->state != CONNECTION_CONNECTED )
00446                 {
00447                   char caller[14];
00448                   receiveMsg->address.GetAsString( caller );
00449                   connect( sock, caller, receiveMsg->port );
00450                 }
00451             }
00452 
00453           else if ( sockets[sock]->rcvcbckfn != NULL )
00454             sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
00455 
00456         }
00457 
00458       sockets[sock]->recvSize = 0;
00459 
00460     }
00461 
00462   receive( sock );
00463 }
00464 
00465 void
00466 Wireless::close(int sock)
00467 {
00468   if (sockets[sock]->state == CONNECTION_CLOSED ||
00469       sockets[sock]->state == CONNECTION_CLOSING) return;
00470 
00471   if (!(sockets[sock]->server_port>0 && sockets[sock]->daemon)) {
00472     sockets[sock]->recvBuffer.UnMap();
00473     antEnvDestroySharedBufferMsg receiveBufferMsg(sockets[sock]->recvBuffer);
00474     receiveBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
00475     sockets[sock]->sendBuffer.UnMap();
00476     antEnvDestroySharedBufferMsg sendBufferMsg(sockets[sock]->sendBuffer);
00477     sendBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
00478   }
00479 
00480   if ( sockets[sock]->trType == SOCK_STREAM )
00481     {
00482       TCPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
00483       closeMsg.continuation = ( void * ) sock;
00484       closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
00485     }
00486 
00487   else if ( sockets[sock]->trType == SOCK_DGRAM )
00488     {
00489       UDPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
00490       closeMsg.continuation = ( void * ) sock;
00491       closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
00492     }
00493 
00494   sockets[sock]->peer_addr=sockets[sock]->peer_port=-1;
00495 
00496   sockets[sock]->state = CONNECTION_CLOSING;
00497 }
00498 
00499 uint32
00500 Wireless::getIPAddress(unsigned int /*idx=0*/) {
00501   uint32 local_ipaddr=0;
00502   //from OPEN-R sample ERA201D1Info:
00503   antEnvInitGetParamMsg getParamMsg("ETHER_IP");
00504   getParamMsg.Call(ipstackRef, sizeof(getParamMsg));
00505   if (getParamMsg.error == ANT_SUCCESS && getParamMsg.paramType == antEnv_InitParam_String) {
00506     //cout << "******** RECEIVED " << getParamMsg.value.str << endl;
00507     unsigned int i=0;
00508     for(int j=3; j>=0; j--) {
00509       unsigned int b=0;
00510       while(i<ANTENV_VALUE_LENGTH_MAX && getParamMsg.value.str[i]!='.' && getParamMsg.value.str[i]!='\0')
00511         b=b*10+(getParamMsg.value.str[i++]-'0');
00512       i++; //skip over '.'
00513       local_ipaddr+=b<<(j*8);
00514       //cout << j << ": " << b << ' ' << local_ipaddr << endl;
00515     }
00516   } else {
00517     OSYSLOG1((osyslogERROR,"getParamMsg.Call() FAILED %d", getParamMsg.error));
00518   }
00519   return local_ipaddr;
00520 }
00521 
00522 void
00523 Wireless::CloseCont(void* msg)
00524 {
00525   antEnvMsg * closeMsg = ( antEnvMsg * ) msg;
00526   int sock = ( int )( closeMsg->continuation );
00527   if ( sockets[sock] == NULL )
00528     return;
00529 
00530   sockets[sock]->state = CONNECTION_CLOSED;
00531   sockets[sock]->peer_addr=sockets[sock]->peer_port=-1;
00532   if ( sockets[sock]->server_port > 0 && sockets[sock]->daemon )
00533     {
00534       // recycle if server
00535       listen( sock, sockets[sock]->server_port );
00536     }
00537 
00538   else
00539     {
00540       delete( sockets[sock] );
00541       sockets[sock] = NULL;
00542       freeSockets.push_back( sock );
00543       for(list<int>::iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it)
00544         if(*it==sock) {
00545           usedSockets.erase(it);
00546           break;
00547         }
00548     }
00549 }
00550 
00551 #else // PLATFORM_LOCAL
00552 #  include "IPC/Thread.h"
00553 #  include <sys/types.h>
00554 #  include <sys/socket.h>
00555 #  include <netinet/in.h>
00556 #  include <netdb.h>
00557 #  include <arpa/inet.h>
00558 #  include <fcntl.h>
00559 #  include <unistd.h>
00560 #  include <iostream>
00561 #  include <errno.h>
00562 
00563 using namespace std;
00564 
00565 
00566 Wireless::Wireless ()
00567 : interruptChk(-1), interruptCtl(-1), rfds(), wfds(), efds(), fdsMax(0), freeSockets(), usedSockets()
00568 {
00569   sockets[0]=new DummySocket(0);
00570   for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
00571     sockets[sock]=NULL;
00572     freeSockets.push_back(sock);
00573   }
00574   int p[2];
00575   pipe(p);
00576   interruptChk=p[0];
00577   interruptCtl=p[1];
00578   fdsMax=interruptChk;
00579   if( ::fcntl(interruptChk,F_SETFL,O_NONBLOCK) ==-1 ) {
00580     perror("Wireless::Wireless(): fcntl");
00581   }
00582   FD_ZERO(&rfds);
00583   FD_SET(interruptChk,&rfds);
00584   FD_ZERO(&wfds);
00585   FD_ZERO(&efds);
00586 }
00587 
00588 Wireless::~Wireless ()
00589 {
00590   ThreadNS::Lock l(getLock());
00591 	::close(interruptChk);
00592 	::close(interruptCtl);
00593   interruptChk=interruptCtl=-1;
00594   if(usedSockets.size()>0) {
00595     cerr << "WARNING: Wireless deleted with open Sockets" << endl;
00596     for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
00597       delete sockets[*it];
00598       sockets[*it]=NULL;
00599     }
00600     freeSockets.insert(freeSockets.end(),usedSockets.begin(),usedSockets.end());
00601     usedSockets.clear();
00602   }
00603 }
00604 
00605 void Wireless::setReceiver(int sock, int (*rcvcbckfn) (char*, int) ) {
00606   sockets[sock]->rcvcbckfn=rcvcbckfn;
00607 }
00608 
00609 void Wireless::close(int sock) {
00610   ThreadNS::Lock l(getLock());
00611   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL)
00612     return;
00613   sockets[sock]->flush();
00614   sockets[sock]->peer_port = sockets[sock]->peer_addr = -1;
00615   if(sockets[sock]->daemon) {
00616     if(::close(sockets[sock]->endpoint)==-1)
00617       perror("Wireless::close(): close");
00618     sockets[sock]->endpoint=-1;
00619     sockets[sock]->state = CONNECTION_CLOSED;
00620     listen(sock,sockets[sock]->server_port);
00621   } else {
00622     bool found=false;
00623     for(list<int>::iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
00624       if(*it==sock) {
00625         usedSockets.erase(it);
00626         found=true;
00627         break;
00628       }
00629     }
00630     if(!found) {
00631       cerr << "WARNING: Could not find socket " << sock << " in usedSockets list of size " << usedSockets.size() << endl;
00632       return;
00633     }
00634     Socket * s=sockets[sock];
00635     sockets[sock] = NULL;
00636     wakeup(s); //avoid select giving error about bad FD
00637     freeSockets.push_back( sock );
00638   }
00639 }
00640 
00641 int Wireless::connect(int sock, const char* ipaddr, int port) {
00642   ThreadNS::Lock l(getLock());
00643   if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS
00644        || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CLOSED && sockets[sock]->trType!=SocketNS::SOCK_DGRAM )
00645     return -1;
00646   
00647   if(sockets[sock]->endpoint==-1)
00648     sockets[sock]->init();
00649   int endpoint=sockets[sock]->endpoint;
00650 
00651   sockaddr_in m_addr;
00652   m_addr.sin_family = AF_INET;
00653   m_addr.sin_port = htons ( port );
00654   struct hostent* hostips = gethostbyname(ipaddr);
00655   if ( hostips==NULL) {
00656     cerr << "Wireless::connect(): gethostbyname returned NULL, h_errno==" << h_errno;
00657     switch(h_errno) {
00658     case HOST_NOT_FOUND: cerr << " (HOST_NOT_FOUND)" << endl; break;
00659     case NO_ADDRESS: cerr << " (NO_ADDRESS)" << endl; break;
00660       //case NO_DATA: cerr << " (NO_DATA)" << endl; break; //NO_DATA==NO_ADDRESS
00661     case NO_RECOVERY: cerr << " (NO_RECOVERY)" << endl; break;
00662     case TRY_AGAIN: cerr << " (TRY_AGAIN)" << endl; break;
00663     default: cerr << " (unknown error code!)" << endl; break;
00664     }   
00665     return -1;
00666   }
00667   memcpy(&m_addr.sin_addr,hostips->h_addr_list[0],sizeof(m_addr.sin_addr));
00668   
00669   int status = ::connect ( endpoint, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );
00670   if ( status == 0 )
00671     sockets[sock]->state=CONNECTION_CONNECTED;
00672   else if(errno==EINPROGRESS)
00673     sockets[sock]->state=CONNECTION_CONNECTING;
00674   else {
00675     perror("Wireless::connect(): connect");
00676     return -1;
00677   }
00678   sockets[sock]->peer_port = port;
00679   sockets[sock]->peer_addr = ntohl(m_addr.sin_addr.s_addr);
00680   //cout << "connecting " << sockets[sock]->getPeerAddressAsString() << ' ' << sockets[sock]->getPeerPort() << "... " <<status << endl;
00681   //this will allow sock to be added to wfds so we can tell when the connection goes through
00682   wakeup();
00683   return 0;
00684 }
00685 
00686 int Wireless::listen(int sock, int port) {
00687   ThreadNS::Lock l(getLock());
00688   if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS
00689        || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CLOSED )
00690     return -1;
00691   sockets[sock]->server_port = port;
00692   sockets[sock]->init();
00693   int endpoint=sockets[sock]->endpoint;
00694   if ( endpoint<0 )
00695   return -1;
00696   sockaddr_in m_addr;
00697   m_addr.sin_family = AF_INET;
00698   m_addr.sin_addr.s_addr = INADDR_ANY;
00699   m_addr.sin_port = htons ( port );
00700   
00701   int bind_return = ::bind ( endpoint,( struct sockaddr * ) &m_addr,sizeof ( m_addr ) );
00702   if ( bind_return == -1 ) {
00703     perror("Wireless::listen: bind");
00704     return -1;
00705   }
00706   if(sockets[sock]->trType==SocketNS::SOCK_STREAM) {
00707     int listen_return = ::listen ( endpoint, MAXCONNECTIONS );
00708     if ( listen_return == -1 ) {
00709       perror("Wireless::listen: listen");
00710       return -1;
00711     }
00712   }
00713   sockets[sock]->state = CONNECTION_LISTENING;
00714   //this will allow sock to be added to rfds so we can tell when a connection is available
00715   wakeup();
00716   return 0;
00717 }
00718 
00719 Socket* Wireless::socket(TransportType_t ttype) {
00720   return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
00721 }
00722 Socket* Wireless::socket(TransportType_t ttype, int recvsize, int sendsize) {
00723   ThreadNS::Lock l(getLock());
00724   if (freeSockets.empty()
00725       || (recvsize + sendsize) <= 256) return sockets[0];
00726   int sock_num=freeSockets.front();
00727   freeSockets.pop_front();
00728   usedSockets.push_back(sock_num);
00729   
00730   sockets[sock_num]=new Socket(sock_num);
00731   
00732   sockets[sock_num]->sendBufSize=sendsize;
00733   sockets[sock_num]->sendBuffer=new char[sockets[sock_num]->sendBufSize*2];
00734   //double buffered sending
00735   sockets[sock_num]->sendData=(byte*)sockets[sock_num]->sendBuffer;
00736   sockets[sock_num]->writeData=(byte*)sockets[sock_num]->sendBuffer+sockets[sock_num]->sendBufSize;
00737 
00738   sockets[sock_num]->recvBufSize=recvsize;
00739   sockets[sock_num]->recvBuffer = new char[sockets[sock_num]->recvBufSize];
00740   sockets[sock_num]->recvData=(byte*)sockets[sock_num]->recvBuffer; //reading is single buffered
00741   
00742   sockets[sock_num]->setTransport(ttype);
00743   
00744   return sockets[sock_num]; 
00745 }
00746 
00747 /*! There's probably better ways to implement this...
00748  *  (run through the interface list?  How does ifconfig do it?) */
00749 uint32 Wireless::getIPAddress(unsigned int idx/*=0*/) {
00750   char buf[ 255 ];
00751   if(gethostname( buf, 255)!=0) {
00752     perror("Wireless::getIPAddress(): gethostname");
00753     return 0;
00754   }
00755   struct hostent * h = gethostbyname( buf );
00756   if(h==NULL) {
00757     herror("Wireless::getIPAddress(): gethostbyname");
00758     return 0;
00759   }
00760   //check to make sure 'idx' is valid
00761   for(unsigned int x=0; x<=idx; x++)
00762     if(h->h_addr_list[x]==NULL)
00763       return 0;
00764   //if we got here, it's valid
00765   return *(uint32*)h->h_addr_list[idx];
00766 }
00767 
00768 void
00769 Wireless::send(int sock)
00770 {
00771   ThreadNS::Lock l(getLock());
00772   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00773       || sockets[sock]->state != CONNECTION_CONNECTED || sockets[sock]->sendSize <= 0 )
00774     return;
00775   
00776   //we could defer all sending to the poll, but let's give a shot at sending it out right away to reduce latency
00777   int s=sockets[sock]->endpoint;
00778   int sent=::send(s,sockets[sock]->sendData+sockets[sock]->sentSize,sockets[sock]->sendSize-sockets[sock]->sentSize,0);
00779   if(sent==-1) {
00780     perror("Wireless::pollProcess(): send");
00781     sockets[sock]->tx = false;
00782     sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
00783   } else {
00784     sockets[sock]->sentSize+=sent;
00785     if(sockets[sock]->sentSize==sockets[sock]->sendSize) {
00786       sockets[sock]->tx = false;
00787       sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
00788       sockets[sock]->flush();
00789     } else {
00790       sockets[sock]->tx = true;
00791       //more work will be done in poll()
00792       //this will wake up the poll thread to make it check for pending writes (signaled by tx flag)
00793       wakeup();
00794     }
00795   }
00796 }
00797 
00798 void
00799 Wireless::blockingSend(int sock)
00800 {
00801   ThreadNS::Lock l(getLock());
00802   if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
00803       || sockets[sock]->state != CONNECTION_CONNECTED || sockets[sock]->sendSize <= 0 )
00804     return;
00805   
00806   while(sockets[sock]->sentSize<sockets[sock]->sendSize) {
00807     fd_set bs_wfds;
00808     FD_ZERO(&bs_wfds);
00809     FD_SET(sockets[sock]->endpoint, &bs_wfds);
00810     int retval = select(sockets[sock]->endpoint+1, NULL, &bs_wfds, NULL, NULL);
00811     if(retval==0)
00812       continue;
00813     if(retval==-1) {
00814       perror("Wireless::poll(): select");
00815       return;
00816     }
00817     if(sockets[sock]->tx) //block on leftover non-blocking send
00818       continue;
00819     int sent=::send(sockets[sock]->endpoint,sockets[sock]->sendData+sockets[sock]->sentSize,sockets[sock]->sendSize-sockets[sock]->sentSize,0);
00820     if(sent==-1) {
00821       if(errno==EAGAIN) {
00822         cerr << "Wireless::blockingSend(): send() was not ready, even though select() said it was" << endl;
00823         continue;
00824       }
00825       perror("Wireless::blockingSend(): send");
00826       sockets[sock]->tx = false;
00827       sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
00828       return;
00829     }
00830     sockets[sock]->sentSize+=sent;
00831   }
00832   sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
00833 }
00834 
00835 void Wireless::pollSetup() {
00836   FD_ZERO(&rfds);
00837   FD_ZERO(&wfds);
00838   FD_ZERO(&efds);
00839   FD_SET(interruptChk, &rfds);
00840 
00841   fdsMax=interruptChk;
00842   ThreadNS::Lock l(getLock());
00843   //cout << "pollSetup " << usedSockets.size() << endl;
00844   for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
00845     if(sockets[*it]==NULL) {
00846       cerr << "ERROR: Wireless::pollSetup() encountered NULL socket " << *it << endl;
00847       continue;
00848     }
00849     if(sockets[*it]->endpoint==-1) {
00850       cerr << "ERROR Wireless::pollSetup() encountered bad endpoint " << *it << endl;
00851       continue;
00852     }
00853     if(sockets[*it]->state!=CONNECTION_CLOSED && sockets[*it]->state!=CONNECTION_ERROR)
00854       FD_SET(sockets[*it]->endpoint, &rfds);
00855     if(sockets[*it]->state==CONNECTION_CONNECTING || sockets[*it]->tx)
00856       FD_SET(sockets[*it]->endpoint, &wfds);
00857     FD_SET(sockets[*it]->endpoint, &efds);
00858     if(sockets[*it]->endpoint>fdsMax)
00859       fdsMax=sockets[*it]->endpoint;
00860   }
00861 }
00862 
00863 /*! @param tv  how long to wait -- NULL will wait indefinitely until a socket event occurs
00864  *  @return true if there was a socket event to process, false if timed out */
00865 bool Wireless::pollTest(struct timeval* tv) {
00866   int retval = select(fdsMax+1, &rfds, &wfds, &efds, tv);
00867   if(retval==-1)
00868     perror("Wireless::pollTest(): select");
00869   return (retval!=0);
00870 }
00871 
00872 void Wireless::pollProcess() {
00873   ThreadNS::Lock l(getLock());
00874   if(FD_ISSET(interruptChk,&rfds)) {
00875     //wakeup sent to handle non-blocking write
00876     int res=1;
00877     //cout << "Clearing interrupts..." << flush;
00878     while(res>0) {
00879       Socket * del=NULL;
00880       res=::read(interruptChk,&del,sizeof(del));
00881       //cout << ' ' << del << flush;
00882       if(del!=NULL)
00883         delete del;
00884     }
00885     //cout << " done" << endl;
00886   }
00887   for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
00888     if(sockets[*it]==NULL) {
00889       cerr << "NULL socket " << *it << endl;
00890       continue;
00891     }
00892     if(sockets[*it]->endpoint==-1) {
00893       cerr << "bad endpoint " << *it << endl;
00894       continue;
00895     }
00896     int s=sockets[*it]->endpoint;
00897     if(FD_ISSET(s,&rfds)) {
00898       //cout << *it << " set in read" << endl;
00899       if(sockets[*it]->state==CONNECTION_CONNECTING) {
00900         //cout << "Wireless::pollProcess(): read set on connecting" << endl;
00901         sockets[*it]->state=CONNECTION_CONNECTED;
00902       }
00903       if(sockets[*it]->state==CONNECTION_LISTENING) {
00904         if(sockets[*it]->trType==SocketNS::SOCK_STREAM) {
00905           sockaddr_in m_addr;
00906           socklen_t addrlen=sizeof(m_addr);
00907           int n=accept(s,(sockaddr*)&m_addr,&addrlen);
00908           if(n==-1) {
00909             perror("Wireless::pollProcess(): accept");
00910             continue;
00911           }
00912           sockets[*it]->peer_addr=ntohl(m_addr.sin_addr.s_addr);
00913           sockets[*it]->peer_port=ntohs(m_addr.sin_port);
00914           //this closes the server socket -- we'll want to address this
00915           if(::close(s)==-1)
00916             perror("Wireless::pollProcess(): close");
00917           s=sockets[*it]->endpoint=n;
00918           sockets[*it]->state=CONNECTION_CONNECTED;
00919           //cout << "Accepted connection" << endl;
00920         } else {
00921           //cout << "UDP accept" << endl;
00922           sockaddr_in m_addr;
00923           socklen_t addrlen=sizeof(m_addr);
00924           sockets[*it]->recvSize = recvfrom(s,sockets[*it]->recvData,sockets[*it]->recvBufSize,0,(sockaddr*)&m_addr,&addrlen);
00925           if(sockets[*it]->recvSize==-1) {
00926             perror("Wireless::pollProcess(): acception recvfrom");
00927             continue;
00928           }
00929           /* //this can cause trouble for broadcasts... we'll make the user call 'connect' themselves if they want to send back
00930            //cout << "connecting..." << endl;
00931           int ret = ::connect ( s, (sockaddr*) &m_addr, sizeof ( m_addr ) );
00932           if ( ret==-1 && errno!=EINPROGRESS ) {
00933             perror("Wireless::pollProcess(): connect");
00934             continue;
00935           }
00936           //cout << "UDP accepted!" << endl;
00937           sockets[*it]->state=CONNECTION_CONNECTING;
00938            */
00939           sockets[*it]->peer_addr=ntohl(m_addr.sin_addr.s_addr);
00940           sockets[*it]->peer_port=ntohs(m_addr.sin_port);
00941           if(sockets[*it]->recvSize!=0) {
00942             //cout << "Read " << sockets[*it]->recvSize << " bytes " << sockets[*it]->rcvcbckfn << endl;
00943             if ( !strncmp( "connection request", ( char * ) sockets[*it]->recvData, 18 ) ) {
00944               // clear this message from the receiving buffer
00945               if ( sockets[*it]->state != CONNECTION_CONNECTED )
00946                 connect( *it, sockets[*it]->getPeerAddressAsString().c_str(), sockets[*it]->getPeerPort() );
00947             } else if ( sockets[*it]->rcvcbckfn != NULL )
00948               sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
00949             sockets[*it]->recvSize = 0;
00950           }
00951         }
00952       } else  if(sockets[*it]->state==CONNECTION_CONNECTED || sockets[*it]->state==CONNECTION_CLOSING) {
00953         sockets[*it]->recvSize = recvfrom(s,sockets[*it]->recvData,sockets[*it]->recvBufSize,0,NULL,NULL);
00954         if(sockets[*it]->recvSize==-1) {
00955           if(errno!=EAGAIN) { //may have just completed connection, not a problem
00956             if(errno==ECONNREFUSED) {
00957               cerr << "connection refused: endpoint=" << s << " sock=" << *it << " Socket=" << sockets[*it] << endl;
00958               list<int>::const_iterator tmp=it;
00959               //a UDP server could come in here
00960               if(!sockets[*it]->daemon) //don't decrement if the socket is going to stay open
00961                 --it;
00962               close(*tmp);
00963               continue;
00964             }
00965             perror("Wireless::pollProcess(): recvfrom");
00966           }
00967         } else if(sockets[*it]->recvSize==0) {
00968           list<int>::const_iterator tmp=it--;
00969           close(*tmp);
00970           //cout << "closed connection" << endl;
00971           continue;
00972         } else {
00973           //cout << "Read " << sockets[*it]->recvSize << " bytes " << sockets[*it]->rcvcbckfn << endl;
00974           if ( sockets[*it]->rcvcbckfn != NULL )
00975             sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
00976           sockets[*it]->recvSize = 0;
00977         }
00978       } else {
00979         int dropped=0,n=0;
00980         char buf[100];
00981         while((n=recvfrom(s,buf,100,0,NULL,NULL))>0)
00982           dropped+=n;
00983         cerr << "Wireless::pollProcess(): socket (sys=" << s << ", tk="<<*it<<") read flag in bad state (" << sockets[*it]->state << "), " << dropped << " bytes were dropped, ending with:" << endl;
00984         for(int i=0; i<n; i++)
00985           if(isprint(buf[i]))
00986             cerr << buf[i];
00987           else
00988             cerr << '.';
00989         cerr << endl;
00990       }
00991     }
00992     if(FD_ISSET(s,&wfds)) {
00993       //cout << *it << " set in write" << endl;
00994       if(sockets[*it]->state==CONNECTION_CONNECTING) {
00995         sockets[*it]->state=CONNECTION_CONNECTED;
00996       } else if(sockets[*it]->state==CONNECTION_CONNECTED) {
00997         if(!sockets[*it]->tx) {
00998           //cerr << "Wireless::pollProcess(): write available on non-tx socket??" << endl;
00999           //can happen on a refused connection
01000         } else {
01001           int sent=::send(s,sockets[*it]->sendData+sockets[*it]->sentSize,sockets[*it]->sendSize-sockets[*it]->sentSize,0);
01002           if(sent==-1) {
01003             perror("Wireless::pollProcess(): send");
01004             sockets[*it]->tx = false;
01005             sockets[*it]->sendSize = sockets[*it]->sentSize = 0;
01006           } else {
01007             sockets[*it]->sentSize+=sent;
01008             if(sockets[*it]->sentSize==sockets[*it]->sendSize) {
01009               sockets[*it]->tx = false;
01010               sockets[*it]->sendSize = sockets[*it]->sentSize = 0;
01011               sockets[*it]->flush();
01012             }
01013           }
01014         }
01015       } else {
01016         cerr << "Wireless::pollProcess(): socket write flag in bad state" << endl;
01017       }
01018     }
01019     if(FD_ISSET(s,&efds)) {
01020       cerr << "Socket exception: " << flush;
01021       int err=0;
01022       socklen_t errlen=sizeof(err);
01023       if ( ::getsockopt ( s, SOL_SOCKET, SO_ERROR, &err, &errlen ) == -1 ) {
01024         perror("Wireless::processPoll(): getsockopt");
01025       }
01026       cerr << err << " endpoint=" << s << " sock=" << *it << " Socket=" << sockets[*it] << endl;
01027     }
01028   }
01029 }
01030 
01031 /*! @param del if non-NULL, will cause the socket to be closed and deleted */
01032 void Wireless::wakeup(Socket * del/*=NULL*/) {
01033   ::write(interruptCtl,&del,sizeof(del)); 
01034 }
01035 
01036 ThreadNS::Lock& Wireless::getLock() {
01037   static ThreadNS::Lock lock;
01038   return lock;
01039 }
01040 
01041 #endif
01042 
01043 /*! @file
01044  * @brief Interacts with the system to provide networking services
01045  * @author alokl (Creator)
01046  * @author Erik Berglund and Bryan Johnson (UDP support)
01047  * 
01048  * @verbinclude CMPack_license.txt
01049  *
01050  * $Author: ejt $
01051  * $Name: tekkotsu-2_4 $
01052  * $Revision: 1.25 $
01053  * $State: Exp $
01054  * $Date: 2005/08/01 23:17:59 $
01055  */
01056 

Tekkotsu v2.4
Generated Wed Aug 10 11:04:40 2005 by Doxygen 1.4.4