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

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:54 2012 by Doxygen 1.6.3