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

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