/ Tekkotsu / Wireless / Wireless.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.33 - (show annotations) (download) (as text)
Thu Mar 16 20:24:24 2006 UTC (4 years, 5 months ago) by ejt
Branch: MAIN
Changes since 1.32: +9 -9 lines
File MIME type: text/x-c++src
patches from crm5 at lehigh -- thanks!
1 #include "Wireless.h"
2 #include "Socket.h"
3 #include <cstring>
4 #include "Shared/ProjectInterface.h"
5
6 Wireless *wireless=NULL;
7
8 #ifdef PLATFORM_APERIOS
9 # include <OPENR/OSyslog.h>
10 # include <OPENR/OPENRAPI.h>
11 # include <ant.h>
12 # include <EndpointTypes.h>
13 # include <TCPEndpointMsg.h>
14 # include <UDPEndpointMsg.h>
15 # include "aperios/MMCombo/entry.h"
16
17 using namespace SocketNS;
18 using namespace std;
19
20 Wireless::Wireless ()
21 : ipstackRef(), myOID(), freeSockets(), usedSockets()
22 {
23 ipstackRef = antStackRef("IPStack");
24 WhoAmI(&myOID);
25
26 sockets[0]=new DummySocket(0);
27 for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
28 sockets[sock]=NULL;
29 freeSockets.push_back(sock);
30 }
31 }
32
33 Wireless::~Wireless ()
34 {
35 if(usedSockets.size()>0) {
36 cerr << "WARNING: Wireless deleted with open Sockets" << endl;
37 for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
38 delete sockets[*it];
39 sockets[*it]=NULL;
40 }
41 freeSockets.insert(freeSockets.end(),usedSockets.begin(),usedSockets.end());
42 usedSockets.clear();
43 }
44 }
45
46 Socket* Wireless::socket(TransportType_t ttype)
47 {
48 return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
49 }
50
51 Socket* Wireless::socket(TransportType_t ttype, int recvsize, int sendsize)
52 {
53 if (freeSockets.empty()
54 || (recvsize + sendsize) <= 256) return sockets[0];
55 int sock_num=freeSockets.front();
56 freeSockets.pop_front();
57 usedSockets.push_back(sock_num);
58
59 sockets[sock_num]=new Socket(sock_num);
60 sockets[sock_num]->sendBufSize=sendsize;
61 sockets[sock_num]->recvBufSize=recvsize;
62 sockets[sock_num]->setTransport(ttype);
63
64 // setup send buffer
65 antEnvCreateSharedBufferMsg sendBufferMsg(sendsize*2);
66 sendBufferMsg.Call(ipstackRef, sizeof(sendBufferMsg));
67 if (sendBufferMsg.error != ANT_SUCCESS) return sockets[0];
68
69 sockets[sock_num]->sendBuffer = sendBufferMsg.buffer;
70 sockets[sock_num]->sendBuffer.Map();
71 sockets[sock_num]->sendData = ( byte * ) ( sockets[sock_num]->sendBuffer.GetAddress() );
72
73 // setup receive buffer
74 antEnvCreateSharedBufferMsg recvBufferMsg(recvsize*2);
75 recvBufferMsg.Call(ipstackRef, sizeof(recvBufferMsg));
76 if (recvBufferMsg.error != ANT_SUCCESS) return sockets[0];
77
78 sockets[sock_num]->recvBuffer = recvBufferMsg.buffer;
79 sockets[sock_num]->recvBuffer.Map();
80 sockets[sock_num]->recvData = ( byte * ) ( sockets[sock_num]->recvBuffer.GetAddress() );
81
82 sockets[sock_num]->readData = sockets[sock_num]->recvData + recvsize;
83 sockets[sock_num]->writeData = sockets[sock_num]->sendData + sendsize;
84
85 return sockets[sock_num];
86 }
87
88 int Wireless::listen(int sock, int port)
89 {
90 if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
91 || sockets[sock]->state != CONNECTION_CLOSED )return -1;
92
93 sockets[sock]->server_port = port;
94 sockets[sock]->init();
95
96 if (sockets[sock]->trType==SocketNS::SOCK_STREAM) {
97 // create endpoint
98 antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
99 tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
100 if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
101 sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
102
103 // listen
104 TCPEndpointListenMsg listenMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
105 listenMsg.continuation = ( void * ) sock;
106
107 listenMsg.Send( ipstackRef, myOID, Extra_Entry[entryListenCont], sizeof( listenMsg ) );
108
109 sockets[sock]->state = CONNECTION_LISTENING;
110 return 0;
111 } else if (sockets[sock]->trType==SOCK_DGRAM) {
112 // create endpoint
113 antEnvCreateEndpointMsg udpCreateMsg( EndpointType_UDP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
114 udpCreateMsg.Call( ipstackRef, sizeof( udpCreateMsg ) );
115 if ( udpCreateMsg.error != ANT_SUCCESS ) return -1;
116
117 // bind socket
118 sockets[sock]->endpoint = udpCreateMsg.moduleRef;
119 UDPEndpointBindMsg bindMsg( sockets[sock]->endpoint, IP_ADDR_ANY, port );
120 bindMsg.Call( ipstackRef, sizeof( bindMsg ) );
121 bindMsg.continuation = ( void * ) sock;
122
123 sockets[sock]->state = CONNECTION_CONNECTING;
124
125 receive( sock );
126
127 return 0;
128
129 }
130
131 else
132 return -1;
133 }
134
135 /** Tell the ipstack we want to recieve messages with this function. */
136
137 int Wireless::connect( int sock, const char * ipaddr, int port )
138 {
139 if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
140 || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CLOSED ) ) return -1;
141
142 sockets[sock]->init();
143 if (sockets[sock]->trType==SOCK_STREAM) {
144 // create endpoint
145 antEnvCreateEndpointMsg tcpCreateMsg( EndpointType_TCP, ( sockets[sock]->recvBufSize + sockets[sock]->sendBufSize ) * 3 );
146 tcpCreateMsg.Call( ipstackRef, sizeof( tcpCreateMsg ) );
147 if ( tcpCreateMsg.error != ANT_SUCCESS ) return -1;
148 sockets[sock]->endpoint = tcpCreateMsg.moduleRef;
149
150 // connect
151 TCPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, IP_ADDR_ANY, IP_PORT_ANY, ipaddr, port );
152 connectMsg.continuation = ( void * ) sock;
153
154 connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
155 sockets[sock]->peer_addr=connectMsg.fAddress.Address();
156 sockets[sock]->peer_port=connectMsg.fPort;
157
158 sockets[sock]->state = CONNECTION_CONNECTING;
159 return 0;
160 }
161
162 else if ( sockets[sock]->trType == SOCK_DGRAM )
163 {
164 // connect
165 UDPEndpointConnectMsg connectMsg( sockets[sock]->endpoint, ipaddr, port );
166
167 connectMsg.continuation = ( void * ) sock;
168
169 connectMsg.Send( ipstackRef, myOID, Extra_Entry[entryConnectCont], sizeof( connectMsg ) );
170 sockets[sock]->peer_addr=connectMsg.address.Address();
171 sockets[sock]->peer_port=connectMsg.port;
172
173 sockets[sock]->state = CONNECTION_CONNECTED;
174 //std::cout << "Sock " << sock << " connected via UDP to IP " << ipaddr << " port " << port << std::flush << std::endl;
175
176 return 0;
177 }
178
179 else
180 {
181 return -1;
182 }
183 }
184
185 void
186 Wireless::ListenCont(void* msg)
187 {
188 try {
189 antEnvMsg * Msg = ( antEnvMsg * ) msg;
190 int sock = ( int )( Msg->continuation );
191
192 if ( sockets[sock]->trType == SOCK_STREAM )
193 {
194 TCPEndpointListenMsg * listenMsg = ( TCPEndpointListenMsg * ) antEnvMsg::Receive( msg );
195
196 if ( listenMsg->error != TCP_SUCCESS )
197 {
198 sockets[sock]->state = CONNECTION_ERROR;
199
200 // no use recycling since its a resource issue
201 return;
202 }
203 sockets[sock]->peer_addr=listenMsg->fAddress.Address();
204 sockets[sock]->peer_port=listenMsg->fPort;
205
206 sockets[sock]->state = CONNECTION_CONNECTED;
207 //sockets[sock]->local_ipaddr = listenMsg->lAddress.Address();
208 //cout << "Listen set lip: " << local_ipaddr << endl;
209 receive( sock );
210 }
211
212 } catch(const std::exception& ex) {
213 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",&ex))
214 throw;
215 } catch(...) {
216 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",NULL))
217 throw;
218 }
219 }
220
221 void
222 Wireless::ConnectCont(void *msg)
223 {
224 try {
225 antEnvMsg * Msg = ( antEnvMsg * ) msg;
226 int sock = ( int )( Msg->continuation );
227
228 if ( sockets[sock]->trType == SOCK_STREAM )
229 {
230 TCPEndpointConnectMsg * connectMsg = ( TCPEndpointConnectMsg * ) antEnvMsg::Receive( msg );
231 if ( connectMsg->error != TCP_SUCCESS )
232 {
233 sockets[sock]->state = CONNECTION_ERROR;
234 return;
235 }
236
237 sockets[sock]->state = CONNECTION_CONNECTED;
238 //sockets[sock]->local_ipaddr = connectMsg->lAddress.Address();
239 //cout << "Connect set lip: " << local_ipaddr << endl;
240 receive( sock );
241 }
242
243 } catch(const std::exception& ex) {
244 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",&ex))
245 throw;
246 } catch(...) {
247 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",NULL))
248 throw;
249 }
250 }
251
252 void
253 Wireless::BindCont(void *msg)
254 {
255 try {
256 UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*) antEnvMsg::Receive( msg );
257 int sock = (int)bindMsg->continuation;
258
259 if (bindMsg->error != UDP_SUCCESS) {
260 sockets[sock]->state = CONNECTION_ERROR;
261 return;
262 }
263
264 sockets[sock]->state = CONNECTION_CONNECTED;
265 /* if(bindMsg->address.Address()!=0) {
266 //sockets[sock]->local_ipaddr = bindMsg->address.Address();
267 //cout << "Bind set lip: " << local_ipaddr << endl;
268 } else {
269 //cout << "Bind got 0" << endl;
270 }*/
271
272 } catch(const std::exception& ex) {
273 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",&ex))
274 throw;
275 } catch(...) {
276 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",NULL))
277 throw;
278 }
279 }
280
281 void
282 Wireless::send(int sock)
283 {
284 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
285 || sockets[sock]->sendSize <= 0 ) return;
286
287 if ( sockets[sock]->trType == SOCK_STREAM )
288 {
289 TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
290 sendMsg.continuation = ( void * ) sock;
291
292 sockets[sock]->tx = true;
293 sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( TCPEndpointSendMsg ) );
294 sockets[sock]->sendSize = 0;
295 }
296
297 else if ( sockets[sock]->trType == SOCK_DGRAM )
298 {
299 UDPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
300
301 // this field is just hijacked to id the socket # this message is being sent across
302 sendMsg.continuation = ( void * ) sock;
303
304 sockets[sock]->tx = true;
305 sendMsg.Send( ipstackRef, myOID, Extra_Entry[entrySendCont], sizeof( UDPEndpointSendMsg ) );
306 sockets[sock]->sendSize = 0;
307 }
308 }
309
310 void
311 Wireless::SendCont(void* msg)
312 {
313 try {
314 antEnvMsg * Msg = ( antEnvMsg * ) msg;
315 int sock = ( int )( Msg->continuation );
316
317 if ( sockets[sock]->trType == SOCK_STREAM )
318 {
319 TCPEndpointSendMsg * sendMsg = ( TCPEndpointSendMsg * ) antEnvMsg::Receive( msg );
320 sockets[sock]->tx = false;
321 if ( sendMsg->error != TCP_SUCCESS )
322 {
323 sockets[sock]->state = CONNECTION_ERROR;
324 close( sock );
325 return;
326 }
327 }
328
329 else if ( sockets[sock]->trType == SOCK_DGRAM )
330 {
331 UDPEndpointSendMsg * sendMsg = ( UDPEndpointSendMsg * ) antEnvMsg::Receive( msg );
332 sockets[sock]->tx = false;
333 if ( sendMsg->error != UDP_SUCCESS )
334 {
335 sockets[sock]->state = CONNECTION_ERROR;
336 close( sock );
337 return;
338 }
339 }
340
341 sockets[sock]->flush();
342
343 } catch(const std::exception& ex) {
344 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",&ex))
345 throw;
346 } catch(...) {
347 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",NULL))
348 throw;
349 }
350 }
351
352 /*! @bug This doesn't actually seem to block until the message is
353 * fully sent... a crash immediately after this will still cause a
354 * line or two to be dropped. This is still less dropped than
355 * regular send, but doesn't do much good for debugging until we fix
356 * this. (if we can...) */
357 void
358 Wireless::blockingSend(int sock)
359 {
360 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CONNECTED
361 || sockets[sock]->sendSize <= 0 ) return;
362
363 if ( sockets[sock]->trType == SOCK_STREAM )
364 {
365 TCPEndpointSendMsg sendMsg( sockets[sock]->endpoint, sockets[sock]->sendData, sockets[sock]->sendSize );
366 sendMsg.continuation = ( void * ) sock;
367
368 sockets[sock]->tx=true;
369 sockets[sock]->sendSize = 0;
370 sendMsg.Call( ipstackRef, sizeof( TCPEndpointSendMsg ) );
371 sockets[sock]->tx = false;
372 }
373
374 // no double buffering
375 }
376
377 void
378 Wireless::setReceiver(int sock, int (*rcvcbckfn) (char*, int) )
379 {
380 if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL) return;
381
382 sockets[sock]->rcvcbckfn=rcvcbckfn;
383 }
384
385 void
386 Wireless::receive(int sock)
387 {
388 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
389 || ( sockets[sock]->trType == SOCK_STREAM && sockets[sock]->state != CONNECTION_CONNECTED ) )
390 return;
391
392 if ( sockets[sock]->trType == SOCK_STREAM )
393 {
394 TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
395 receiveMsg.continuation = ( void * ) sock;
396 receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
397 }
398
399 else if ( sockets[sock]->trType == SOCK_DGRAM )
400 {
401 UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
402 receiveMsg.continuation = ( void * ) sock;
403 receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
404 }
405
406 sockets[sock]->rx = true;
407 }
408
409 void
410 Wireless::receive(int sock, int (*rcvcbckfn) (char*, int) )
411 {
412 if (sock<=0 || sock>=WIRELESS_MAX_SOCKETS || sockets[sock]==NULL
413 || sockets[sock]->state != CONNECTION_CONNECTED) return;
414
415 sockets[sock]->rcvcbckfn = rcvcbckfn;
416
417 if ( sockets[sock]->trType == SOCK_STREAM )
418 {
419 TCPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, 1, sockets[sock]->recvBufSize );
420 receiveMsg.continuation = ( void * ) sock;
421 receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
422 }
423
424 else if ( sockets[sock]->trType == SOCK_DGRAM )
425 {
426 UDPEndpointReceiveMsg receiveMsg( sockets[sock]->endpoint, sockets[sock]->recvData, sockets[sock]->recvBufSize );
427 receiveMsg.continuation = ( void * ) sock;
428 receiveMsg.Send( ipstackRef, myOID, Extra_Entry[entryReceiveCont], sizeof( receiveMsg ) );
429 }
430
431 sockets[sock]->rx = true;
432 }
433
434 void
435 Wireless::ReceiveCont(void* msg)
436 {
437 try {
438 // get the socket index before casting the message into UDP or TCP form
439 antEnvMsg * Msg = ( antEnvMsg * ) msg;
440 int sock = ( int )( Msg->continuation );
441
442 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
443 || ( sockets[sock]->state != CONNECTION_CONNECTED && sockets[sock]->state != CONNECTION_CONNECTING ) )
444 return;
445
446 if ( sockets[sock]->trType == SOCK_STREAM )
447 {
448 TCPEndpointReceiveMsg * receiveMsg = ( TCPEndpointReceiveMsg * ) antEnvMsg::Receive( msg );
449 if ( receiveMsg->error != TCP_SUCCESS )
450 {
451 sockets[sock]->state = CONNECTION_ERROR;
452 close( sock );
453 return;
454 }
455
456 sockets[sock]->recvSize = receiveMsg->sizeMin;
457 if ( sockets[sock]->rcvcbckfn != NULL )
458 sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
459 sockets[sock]->recvSize = 0;
460
461 }
462
463 else if ( sockets[sock]->trType == SOCK_DGRAM )
464 {
465 UDPEndpointReceiveMsg * receiveMsg;
466 receiveMsg = ( UDPEndpointReceiveMsg * ) antEnvMsg::Receive( msg );
467 sockets[sock]->recvSize = receiveMsg->size;
468
469 if ( receiveMsg->error == UDP_SUCCESS )
470 {
471 // if this UDP connection is not connected yet, connect it
472 // to the address & port of the computer that sent this message.
473 // This allows us to send UDP messages to any address instead of
474 // hard-coding a specific address beforehand
475
476 sockets[sock]->peer_addr=receiveMsg->address.Address();
477 sockets[sock]->peer_port=receiveMsg->port;
478 if ( !strncmp( "connection request", ( char * ) sockets[sock]->recvData, 18 ) )
479 {
480 // clear this message from the receiving buffer
481 sockets[sock]->recvData += sockets[sock]->recvSize;
482
483 if ( sockets[sock]->state != CONNECTION_CONNECTED )
484 {
485 char caller[14];
486 receiveMsg->address.GetAsString( caller );
487 connect( sock, caller, receiveMsg->port );
488 }
489 }
490
491 else if ( sockets[sock]->rcvcbckfn != NULL )
492 sockets[sock]->rcvcbckfn( ( char * ) sockets[sock]->recvData, sockets[sock]->recvSize );
493
494 }
495
496 sockets[sock]->recvSize = 0;
497
498 }
499
500 receive( sock );
501
502 } catch(const std::exception& ex) {
503 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",&ex))
504 throw;
505 } catch(...) {
506 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",NULL))
507 throw;
508 }
509 }
510
511 void
512 Wireless::close(int sock)
513 {
514 if (sockets[sock]->state == CONNECTION_CLOSED ||
515 sockets[sock]->state == CONNECTION_CLOSING) return;
516
517 if (!(sockets[sock]->server_port>0 && sockets[sock]->daemon)) {
518 sockets[sock]->recvBuffer.UnMap();
519 antEnvDestroySharedBufferMsg receiveBufferMsg(sockets[sock]->recvBuffer);
520 receiveBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
521 sockets[sock]->sendBuffer.UnMap();
522 antEnvDestroySharedBufferMsg sendBufferMsg(sockets[sock]->sendBuffer);
523 sendBufferMsg.Call(ipstackRef, sizeof(antEnvDestroySharedBufferMsg));
524 }
525
526 if ( sockets[sock]->trType == SOCK_STREAM )
527 {
528 TCPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
529 closeMsg.continuation = ( void * ) sock;
530 closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
531 }
532
533 else if ( sockets[sock]->trType == SOCK_DGRAM )
534 {
535 UDPEndpointCloseMsg closeMsg( sockets[sock]->endpoint );
536 closeMsg.continuation = ( void * ) sock;
537 closeMsg.Send( ipstackRef, myOID, Extra_Entry[entryCloseCont], sizeof( closeMsg ) );
538 }
539
540 sockets[sock]->peer_addr=sockets[sock]->peer_port=-1;
541
542 sockets[sock]->state = CONNECTION_CLOSING;
543 }
544
545 uint32
546 Wireless::getIPAddress(unsigned int /*idx=0*/) {
547 uint32 local_ipaddr=0;
548 //from OPEN-R sample ERA201D1Info:
549 antEnvInitGetParamMsg getParamMsg("ETHER_IP");
550 getParamMsg.Call(ipstackRef, sizeof(getParamMsg));
551 if (getParamMsg.error == ANT_SUCCESS && getParamMsg.paramType == antEnv_InitParam_String) {
552 //cout << "******** RECEIVED " << getParamMsg.value.str << endl;
553 unsigned int i=0;
554 for(int j=3; j>=0; j--) {
555 unsigned int b=0;
556 while(i<ANTENV_VALUE_LENGTH_MAX && getParamMsg.value.str[i]!='.' && getParamMsg.value.str[i]!='\0')
557 b=b*10+(getParamMsg.value.str[i++]-'0');
558 i++; //skip over '.'
559 local_ipaddr+=b<<(j*8);
560 //cout << j << ": " << b << ' ' << local_ipaddr << endl;
561 }
562 } else {
563 OSYSLOG1((osyslogERROR,"getParamMsg.Call() FAILED %d", getParamMsg.error));
564 }
565 return local_ipaddr;
566 }
567
568 void
569 Wireless::CloseCont(void* msg)
570 {
571 try {
572 antEnvMsg * closeMsg = ( antEnvMsg * ) antEnvMsg::Receive( msg );
573 int sock = ( int )( closeMsg->continuation );
574 if ( sockets[sock] == NULL )
575 return;
576
577 sockets[sock]->state = CONNECTION_CLOSED;
578 sockets[sock]->peer_addr=sockets[sock]->peer_port=-1;
579 if ( sockets[sock]->server_port > 0 && sockets[sock]->daemon )
580 {
581 // recycle if server
582 listen( sock, sockets[sock]->server_port );
583 }
584
585 else
586 {
587 delete( sockets[sock] );
588 sockets[sock] = NULL;
589 freeSockets.push_back( sock );
590 for(list<int>::iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it)
591 if(*it==sock) {
592 usedSockets.erase(it);
593 break;
594 }
595 }
596
597 } catch(const std::exception& ex) {
598 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",&ex))
599 throw;
600 } catch(...) {
601 if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",NULL))
602 throw;
603 }
604 }
605
606 #else // PLATFORM_LOCAL
607 # include "IPC/Thread.h"
608 # include <sys/types.h>
609 # include <sys/socket.h>
610 # include <netinet/in.h>
611 # include <netdb.h>
612 # include <arpa/inet.h>
613 # include <fcntl.h>
614 # include <unistd.h>
615 # include <iostream>
616 # include <errno.h>
617
618 using namespace std;
619
620
621 Wireless::Wireless ()
622 : callbackLock(), interruptChk(-1), interruptCtl(-1), rfds(), wfds(), efds(), fdsMax(0), freeSockets(), usedSockets()
623 {
624 sockets[0]=new DummySocket(0);
625 for (int sock = 1; sock < WIRELESS_MAX_SOCKETS; sock++) {
626 sockets[sock]=NULL;
627 freeSockets.push_back(sock);
628 }
629 int p[2];
630 pipe(p);
631 interruptChk=p[0];
632 interruptCtl=p[1];
633 fdsMax=interruptChk;
634 if( ::fcntl(interruptChk,F_SETFL,O_NONBLOCK) ==-1 ) {
635 perror("Wireless::Wireless(): fcntl");
636 }
637 FD_ZERO(&rfds);
638 FD_SET(interruptChk,&rfds);
639 FD_ZERO(&wfds);
640 FD_ZERO(&efds);
641 }
642
643 Wireless::~Wireless ()
644 {
645 ThreadNS::Lock l(getLock());
646 ::close(interruptChk);
647 ::close(interruptCtl);
648 interruptChk=interruptCtl=-1;
649 if(usedSockets.size()>0) {
650 cerr << "WARNING: Wireless deleted with open Sockets" << endl;
651 for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
652 delete sockets[*it];
653 sockets[*it]=NULL;
654 }
655 freeSockets.insert(freeSockets.end(),usedSockets.begin(),usedSockets.end());
656 usedSockets.clear();
657 }
658 delete sockets[0]; // DummySocket
659 }
660
661 void Wireless::setReceiver(int sock, int (*rcvcbckfn) (char*, int) ) {
662 sockets[sock]->rcvcbckfn=rcvcbckfn;
663 }
664
665 void Wireless::close(int sock) {
666 ThreadNS::Lock l(getLock());
667 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL)
668 return;
669 sockets[sock]->flush();
670 sockets[sock]->peer_port = sockets[sock]->peer_addr = -1;
671 if(sockets[sock]->daemon) {
672 sockets[sock]->init();
673 listen(sock,sockets[sock]->server_port);
674 } else {
675 bool found=false;
676 for(list<int>::iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
677 if(*it==sock) {
678 usedSockets.erase(it);
679 found=true;
680 break;
681 }
682 }
683 if(!found) {
684 cerr << "WARNING: Could not find socket " << sock << " in usedSockets list of size " << usedSockets.size() << endl;
685 return;
686 }
687 Socket * s=sockets[sock];
688 sockets[sock] = NULL; //we don't delete the socket here -- wakeup() will cause pollProcess to do that
689 wakeup(s); //avoid select giving error about bad FD
690 freeSockets.push_back( sock );
691 }
692 }
693
694 int Wireless::connect(int sock, const char* ipaddr, int port) {
695 ThreadNS::Lock l(getLock());
696 if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS
697 || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CLOSED && sockets[sock]->trType!=SocketNS::SOCK_DGRAM )
698 return -1;
699
700 if(sockets[sock]->endpoint==-1)
701 sockets[sock]->init();
702 int endpoint=sockets[sock]->endpoint;
703
704 sockaddr_in m_addr;
705 m_addr.sin_family = AF_INET;
706 m_addr.sin_port = htons ( port );
707 struct hostent* hostips = gethostbyname(ipaddr);
708 if ( hostips==NULL) {
709 cerr << "Wireless::connect(): gethostbyname returned NULL, h_errno==" << h_errno;
710 switch(h_errno) {
711 case HOST_NOT_FOUND: cerr << " (HOST_NOT_FOUND)" << endl; break;
712 case NO_ADDRESS: cerr << " (NO_ADDRESS)" << endl; break;
713 //case NO_DATA: cerr << " (NO_DATA)" << endl; break; //NO_DATA==NO_ADDRESS
714 case NO_RECOVERY: cerr << " (NO_RECOVERY)" << endl; break;
715 case TRY_AGAIN: cerr << " (TRY_AGAIN)" << endl; break;
716 default: cerr << " (unknown error code!)" << endl; break;
717 }
718 return -1;
719 }
720 memcpy(&m_addr.sin_addr,hostips->h_addr_list[0],sizeof(m_addr.sin_addr));
721
722 int status = ::connect ( endpoint, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );
723 if ( status == 0 )
724 sockets[sock]->state=CONNECTION_CONNECTED;
725 else if(errno==EINPROGRESS)
726 sockets[sock]->state=CONNECTION_CONNECTING;
727 else {
728 perror("Wireless::connect(): connect");
729 return -1;
730 }
731 sockets[sock]->peer_port = port;
732 sockets[sock]->peer_addr = ntohl(m_addr.sin_addr.s_addr);
733 //cout << "connecting " << sockets[sock]->getPeerAddressAsString() << ' ' << sockets[sock]->getPeerPort() << "... " <<status << endl;
734 //this will allow sock to be added to wfds so we can tell when the connection goes through
735 wakeup();
736 return 0;
737 }
738
739 int Wireless::listen(int sock, int port) {
740 ThreadNS::Lock l(getLock());
741 if ( port <= 0 || port >= 65535 || sock <= 0 || sock >= WIRELESS_MAX_SOCKETS
742 || sockets[sock] == NULL || sockets[sock]->state != CONNECTION_CLOSED )
743 return -1;
744 sockets[sock]->server_port = port;
745 sockets[sock]->init();
746 int endpoint=sockets[sock]->endpoint;
747 if ( endpoint<0 )
748 return -1;
749 sockaddr_in m_addr;
750 m_addr.sin_family = AF_INET;
751 m_addr.sin_addr.s_addr = INADDR_ANY;
752 m_addr.sin_port = htons ( port );
753
754 int bind_return = ::bind ( endpoint,( struct sockaddr * ) &m_addr,sizeof ( m_addr ) );
755 if ( bind_return == -1 ) {
756 perror("Wireless::listen: bind");
757 return -1;
758 }
759 if(sockets[sock]->trType==SocketNS::SOCK_STREAM) {
760 int listen_return = ::listen ( endpoint, MAXCONNECTIONS );
761 if ( listen_return == -1 ) {
762 perror("Wireless::listen: listen");
763 return -1;
764 }
765 }
766 sockets[sock]->state = CONNECTION_LISTENING;
767 //this will allow sock to be added to rfds so we can tell when a connection is available
768 wakeup();
769 return 0;
770 }
771
772 Socket* Wireless::socket(TransportType_t ttype) {
773 return socket(ttype, WIRELESS_DEF_RECV_SIZE, WIRELESS_DEF_SEND_SIZE);
774 }
775 Socket* Wireless::socket(TransportType_t ttype, int recvsize, int sendsize) {
776 ThreadNS::Lock l(getLock());
777 if (freeSockets.empty()
778 || (recvsize + sendsize) <= 256) return sockets[0];
779 int sock_num=freeSockets.front();
780 freeSockets.pop_front();
781 usedSockets.push_back(sock_num);
782
783 sockets[sock_num]=new Socket(sock_num);
784
785 sockets[sock_num]->sendBufSize=sendsize;
786 sockets[sock_num]->sendBuffer=new char[sockets[sock_num]->sendBufSize*2];
787 //double buffered sending
788 sockets[sock_num]->sendData=(byte*)sockets[sock_num]->sendBuffer;
789 sockets[sock_num]->writeData=(byte*)sockets[sock_num]->sendBuffer+sockets[sock_num]->sendBufSize;
790
791 sockets[sock_num]->recvBufSize=recvsize;
792 sockets[sock_num]->recvBuffer = new char[sockets[sock_num]->recvBufSize];
793 sockets[sock_num]->recvData=(byte*)sockets[sock_num]->recvBuffer; //reading is single buffered
794
795 sockets[sock_num]->setTransport(ttype);
796
797 return sockets[sock_num];
798 }
799
800 /*! There's probably better ways to implement this...
801 * (run through the interface list? How does ifconfig do it?) */
802 uint32 Wireless::getIPAddress(unsigned int idx/*=0*/) {
803 char buf[ 255 ];
804 if(gethostname( buf, 255)!=0) {
805 perror("Wireless::getIPAddress(): gethostname");
806 return 0;
807 }
808 struct hostent * h = gethostbyname( buf );
809 if(h==NULL) {
810 herror("Wireless::getIPAddress(): gethostbyname");
811 return 0;
812 }
813 //check to make sure 'idx' is valid
814 for(unsigned int x=0; x<=idx; x++)
815 if(h->h_addr_list[x]==NULL)
816 return 0;
817 //if we got here, it's valid
818 return *(uint32*)h->h_addr_list[idx];
819 }
820
821 void
822 Wireless::send(int sock)
823 {
824 ThreadNS::Lock l(getLock());
825 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
826 || sockets[sock]->state != CONNECTION_CONNECTED || sockets[sock]->sendSize <= 0 )
827 return;
828
829 //we could defer all sending to the poll, but let's give a shot at sending it out right away to reduce latency
830 int s=sockets[sock]->endpoint;
831 int sent=::send(s,sockets[sock]->sendData+sockets[sock]->sentSize,sockets[sock]->sendSize-sockets[sock]->sentSize,0);
832 if(sent==-1) {
833 perror("Wireless::pollProcess(): send");
834 sockets[sock]->tx = false;
835 sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
836 } else {
837 sockets[sock]->sentSize+=sent;
838 if(sockets[sock]->sentSize==sockets[sock]->sendSize) {
839 sockets[sock]->tx = false;
840 sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
841 sockets[sock]->flush();
842 } else {
843 sockets[sock]->tx = true;
844 //more work will be done in poll()
845 //this will wake up the poll thread to make it check for pending writes (signaled by tx flag)
846 wakeup();
847 }
848 }
849 }
850
851 void
852 Wireless::blockingSend(int sock)
853 {
854 ThreadNS::Lock l(getLock());
855 if ( sock <= 0 || sock >= WIRELESS_MAX_SOCKETS || sockets[sock] == NULL
856 || sockets[sock]->state != CONNECTION_CONNECTED || sockets[sock]->sendSize <= 0 )
857 return;
858
859 while(sockets[sock]->sentSize<sockets[sock]->sendSize) {
860 fd_set bs_wfds;
861 FD_ZERO(&bs_wfds);
862 FD_SET(sockets[sock]->endpoint, &bs_wfds);
863 int retval = select(sockets[sock]->endpoint+1, NULL, &bs_wfds, NULL, NULL);
864 if(retval==0)
865 continue;
866 if(retval==-1) {
867 perror("Wireless::poll(): select");
868 return;
869 }
870 if(sockets[sock]->tx) //block on leftover non-blocking send
871 continue;
872 int sent=::send(sockets[sock]->endpoint,sockets[sock]->sendData+sockets[sock]->sentSize,sockets[sock]->sendSize-sockets[sock]->sentSize,0);
873 if(sent==-1) {
874 if(errno==EAGAIN) {
875 cerr << "Wireless::blockingSend(): send() was not ready, even though select() said it was" << endl;
876 continue;
877 }
878 perror("Wireless::blockingSend(): send");
879 sockets[sock]->tx = false;
880 sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
881 return;
882 }
883 sockets[sock]->sentSize+=sent;
884 }
885 sockets[sock]->sendSize = sockets[sock]->sentSize = 0;
886 }
887
888 void Wireless::pollSetup() {
889 FD_ZERO(&rfds);
890 FD_ZERO(&wfds);
891 FD_ZERO(&efds);
892 FD_SET(interruptChk, &rfds);
893
894 fdsMax=interruptChk;
895 ThreadNS::Lock l(getLock());
896 //cout << "pollSetup " << usedSockets.size() << endl;
897 for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
898 if(sockets[*it]==NULL) {
899 cerr << "ERROR: Wireless::pollSetup() encountered NULL socket " << *it << endl;
900 continue;
901 }
902 if(sockets[*it]->endpoint==-1) {
903 cerr << "ERROR Wireless::pollSetup() encountered bad endpoint " << *it << endl;
904 continue;
905 }
906 if(sockets[*it]->state!=CONNECTION_CLOSED && sockets[*it]->state!=CONNECTION_ERROR)
907 FD_SET(sockets[*it]->endpoint, &rfds);
908 if(sockets[*it]->state==CONNECTION_CONNECTING || sockets[*it]->tx)
909 FD_SET(sockets[*it]->endpoint, &wfds);
910 FD_SET(sockets[*it]->endpoint, &efds);
911 if(sockets[*it]->endpoint>fdsMax)
912 fdsMax=sockets[*it]->endpoint;
913 }
914 }
915
916 /*! @param tv how long to wait -- NULL will wait indefinitely until a socket event occurs
917 * @return true if there was a socket event to process, false if timed out */
918 bool Wireless::pollTest(struct timeval* tv) {
919 int retval = select(fdsMax+1, &rfds, &wfds, &efds, tv);
920 if(retval==-1)
921 perror("Wireless::pollTest(): select");
922 return (retval!=0);
923 }
924
925 void Wireless::pollProcess() {
926 ThreadNS::Lock cl(callbackLock); //note how this will go out of scope and release the lock if an exception occurs... sexy!
927 ThreadNS::Lock l(getLock());
928 if(FD_ISSET(interruptChk,&rfds)) {
929 //wakeup sent to handle non-blocking write
930 int res=1;
931 //cout << "Clearing interrupts..." << flush;
932 while(res>0) {
933 Socket * del=NULL;
934 res=::read(interruptChk,&del,sizeof(del));
935 //cout << ' ' << del << flush;
936 if(del!=NULL)
937 delete del;
938 }
939 //cout << " done" << endl;
940 }
941 for(list<int>::const_iterator it=usedSockets.begin(); it!=usedSockets.end(); ++it) {
942 if(sockets[*it]==NULL) {
943 cerr << "NULL socket " << *it << endl;
944 continue;
945 }
946 if(sockets[*it]->endpoint==-1) {
947 cerr << "bad endpoint " << *it << endl;
948 continue;
949 }
950 int s=sockets[*it]->endpoint;
951 if(FD_ISSET(s,&rfds)) {
952 //cout << *it << " set in read" << endl;
953 if(sockets[*it]->state==CONNECTION_CONNECTING) {
954 //cout << "Wireless::pollProcess(): read set on connecting" << endl;
955 sockets[*it]->state=CONNECTION_CONNECTED;
956 }
957 if(sockets[*it]->state==CONNECTION_LISTENING) {
958 if(sockets[*it]->trType==SocketNS::SOCK_STREAM) {
959 sockaddr_in m_addr;
960 socklen_t addrlen=sizeof(m_addr);
961 int n=accept(s,(sockaddr*)&m_addr,&addrlen);
962 if(n==-1) {
963 if(errno!=EAGAIN) //EAGAIN indicates we were woken due to some other issue, like a previous close completing
964 perror("Wireless::pollProcess(): accept");
965 continue;
966 }
967 sockets[*it]->peer_addr=ntohl(m_addr.sin_addr.s_addr);
968 sockets[*it]->peer_port=ntohs(m_addr.sin_port);
969 //this closes the server socket -- we'll want to address this
970 if(::close(s)==-1)
971 perror("Wireless::pollProcess(): close");
972 s=sockets[*it]->endpoint=n;
973 sockets[*it]->state=CONNECTION_CONNECTED;
974 //cout << "Accepted connection" << endl;
975 } else {
976 //cout << "UDP accept" << endl;
977 sockaddr_in m_addr;
978 socklen_t addrlen=sizeof(m_addr);
979 sockets[*it]->recvSize = recvfrom(s,sockets[*it]->recvData,sockets[*it]->recvBufSize,0,(sockaddr*)&m_addr,&addrlen);
980 if(sockets[*it]->recvSize==-1) {
981 perror("Wireless::pollProcess(): acception recvfrom");
982 continue;
983 }
984 /* //this can cause trouble for broadcasts... we'll make the user call 'connect' themselves if they want to send back
985 //cout << "connecting..." << endl;
986 int ret = ::connect ( s, (sockaddr*) &m_addr, sizeof ( m_addr ) );
987 if ( ret==-1 && errno!=EINPROGRESS ) {
988 perror("Wireless::pollProcess(): connect");
989 continue;
990 }
991 //cout << "UDP accepted!" << endl;
992 sockets[*it]->state=CONNECTION_CONNECTING;
993 */
994 sockets[*it]->peer_addr=ntohl(m_addr.sin_addr.s_addr);
995 sockets[*it]->peer_port=ntohs(m_addr.sin_port