Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Wireless.cc

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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:53 2016 by Doxygen 1.6.3