comparison host/tools/ecostest/common/eCosTestSocket.cpp @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children
comparison
equal deleted inserted replaced
75:41bf073c0c32 76:435cced73e2f
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 // more details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //
24 //####COPYRIGHTEND####
25 //=================================================================
26 //
27 // eCosTestSocket.cpp
28 //
29 // Socket test class
30 //
31 //=================================================================
32 //=================================================================
33 //#####DESCRIPTIONBEGIN####
34 //
35 // Author(s): sdf
36 // Contributors: sdf
37 // Date: 1999-04-01
38 // Description: This class abstracts tcp/ip sockets for use in the testing infrastructure
39 // Usage:
40 //
41 //####DESCRIPTIONEND####
42
43 #include "eCosStd.h"
44 #include "eCosTestSocket.h"
45 #include "eCosTestSerial.h"
46 #include "eCosTrace.h"
47
48 enum {ERR_TIMEOUT=20000, ERR_READ_AFTER_CLOSE=20001};
49
50 // Blocking read on one or other of the data sources:
51 // Result: 0 - error occurred
52 // 1 - data read from socket
53 // 2 - data read from serial
54 int CeCosTestSocket::SSRead (CeCosTestSerial &serial,CeCosTestSocket &socket,void *pBuf,unsigned int nSize,unsigned int &nRead,bool *pbStop)
55 {
56 int rc=0;
57 bool bBlocking=serial.GetBlockingReads();
58 bool bBlockingModified=false;
59 while(0==pbStop || !(*pbStop)){
60 if(!socket.Peek(nRead)){
61 break;
62 } else if(nRead){
63 nRead=MIN(nRead,nSize);
64 rc=socket.recv(pBuf,nRead)?1:0;
65 break;
66 } else {
67 if(bBlocking){
68 serial.SetBlockingReads(false);
69 bBlockingModified=true;
70 bBlocking=false;
71 }
72 if(serial.Read(pBuf,nSize,nRead)){
73 if(nRead>0){
74 rc=2;
75 break;
76 }
77 } else {
78 break;
79 }
80 }
81 Sleep(1);
82 }
83 if(bBlockingModified){
84 serial.SetBlockingReads(true);
85 }
86 return rc;
87 }
88
89 // ctors and dtors
90
91 CeCosTestSocket::CeCosTestSocket ():
92 m_nDefaultTimeout(10*1000),
93 m_nSock(-1),
94 m_nClient(0)
95 {
96 TRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
97 }
98
99 CeCosTestSocket::CeCosTestSocket (int sock /*result of previous call of Listen*/, bool *pbStop):
100 m_nDefaultTimeout(10*1000),
101 m_nSock(-1),
102 m_nClient(0)
103 {
104 TRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
105 Accept(sock,pbStop);
106 }
107
108 CeCosTestSocket::CeCosTestSocket (String strHost,int port,Duration dTimeout):
109 m_nDefaultTimeout(10*1000),
110 m_nSock(-1),
111 m_nClient(0)
112 {
113 TRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
114 Connect(strHost,port,dTimeout);
115 }
116
117 bool CeCosTestSocket::Accept(int sock /*result of previous call of Listen*/, bool *pbStop)
118 {
119 m_nSock=-1;
120 while(0==pbStop||!*pbStop){
121 struct sockaddr cli_addr;
122 #ifndef _WIN32
123 unsigned
124 #endif
125 int clilen=sizeof(struct sockaddr);
126 m_nSock=::accept(sock, (struct sockaddr *) &cli_addr, &clilen);
127 SaveError();
128 if(-1==m_nSock){
129 if(WOULDBLOCK==SocketError()){
130 Sleep(100);
131 continue;
132 }
133 } else {
134 memcpy(&m_nClient,cli_addr.sa_data+2,4);
135 TRACE(_T("Connection accepted from %s - socket %d\n"),(LPCTSTR )ClientName(m_nClient),m_nSock);
136 SetSocketOptions();
137 break;
138 }
139 }
140 return -1!=m_nSock;
141 }
142
143 int CeCosTestSocket::Listen(int nTcpPort)
144 {
145 // Create socket
146 int sock=::socket(AF_INET, SOCK_STREAM, 0);
147 if (sock == -1) {
148 ERROR(_T("Couldn't create socket\n"));
149 } else {
150 TRACE(_T("Created socket %d listening on port %d\n"),sock,nTcpPort);
151 // Bind socket to address
152 struct sockaddr_in serv_addr;
153 memset(&serv_addr, 0, sizeof serv_addr);
154
155 serv_addr.sin_family = AF_INET;
156 serv_addr.sin_port=htons((short)nTcpPort);
157 serv_addr.sin_addr.s_addr = INADDR_ANY;
158
159 if (::bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
160 TRACE(_T("Couldn't bind socket on port %d\n"),nTcpPort);
161 CloseSocket(sock);
162 } else if (-1==::listen(sock, SOMAXCONN)){
163 CloseSocket(sock);
164 TRACE(_T("socket error on listen - port %d\n"),nTcpPort);
165 } else {
166 #ifdef _WIN32
167 int nTrue=1;
168 bool rc=(0==::ioctlsocket(sock, FIONBIO, (unsigned long *)&nTrue));
169 #else //UNIX
170 int flags=::fcntl(sock,F_GETFL);
171 flags|=O_NONBLOCK;
172 bool rc=(0==::fcntl (sock, F_SETFL, flags));
173 #endif
174 if(!rc){
175 TRACE(_T("Failed to set socket options on socket %d\n"),sock);
176 }
177 }
178 }
179 return sock;
180 }
181
182 bool CeCosTestSocket::Connect(String strHost,int port,Duration dTimeout)
183 {
184 dTimeout=TimeoutDuration(dTimeout);
185 struct sockaddr_in serv_addr;
186
187 struct hostent* host_dat;
188
189 char ip[16]; // for nnn.nnn.nnn.nnn
190
191 VTRACE(_T("Connect: %s:%d timeout=%d\n"),(LPCTSTR )strHost,port,dTimeout);
192
193 // Get the target host address
194 String strErr;
195 char *pszHost=strHost.GetCString();
196 if (0==(host_dat=::gethostbyname(pszHost))){
197 SaveError();
198 TRACE(_T("Could not get IP address for host %s - %s\n"),(LPCTSTR )strHost,(LPCTSTR )SocketErrString());
199 } else {
200 char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) );
201 if(0==c){
202 SaveError();
203 TRACE(_T("Could inet_ntoa %s - %s\n"),(LPCTSTR )strHost,(LPCTSTR )SocketErrString());
204 } else {
205
206 strcpy(ip, c);
207 memset(&serv_addr, 0, sizeof serv_addr);
208
209 // Create socket
210 m_nSock = ::socket(AF_INET, SOCK_STREAM, 0);
211 if (-1 == m_nSock) {
212 TRACE(_T("Could not create socket [%s:%d]\n"),(LPCTSTR )strHost,port);
213 } else {
214 #ifdef _WIN32
215 SetSocketOptions();
216 #endif
217 TRACE(_T("Created socket %d connected to %s:%d\n"),m_nSock,(LPCTSTR )strHost,port);
218 // Bind socket to address
219 serv_addr.sin_family = AF_INET;
220 serv_addr.sin_port=htons((short)port);
221 SaveError();
222 serv_addr.sin_addr.s_addr = inet_addr(ip);
223
224 // Connect to server
225 VTRACE(_T("Connect() : connecting to server\n"));
226 int cc=::connect(m_nSock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
227 SaveError();
228 String strMsg;
229 if(-1==cc){
230 if(
231 #ifdef _WIN32
232 WOULDBLOCK==SocketError()
233 #else // UNIX
234 EINPROGRESS==SocketError()
235 #endif
236 ){
237 // Allow dTimeout milliseconds for connect to complete
238 fd_set set;
239 FD_ZERO(&set);
240 #ifdef _WIN32
241 #pragma warning( push )
242 #pragma warning( disable : 4127 ) // conditional expression is constant
243 #endif
244 FD_SET((unsigned)m_nSock, &set);
245 #ifdef _WIN32
246 #pragma warning( pop )
247 #endif
248 struct timeval tv;
249 tv.tv_sec = dTimeout/1000;
250 tv.tv_usec = 1000*(dTimeout % 1000);
251 switch(::select(m_nSock, NULL, &set , NULL, &tv)){
252 case 0:
253 m_nErr=ERR_TIMEOUT;
254 strMsg.Format(_T("attempt timed out after %d seconds"),dTimeout/1000);
255 break;
256 case -1:
257 SaveError();
258 strMsg=SocketErrString();
259 break;
260 default:
261 cc=0;
262 }
263 } else {
264 strMsg=SocketErrString();
265 }
266 }
267
268 if(-1==cc){
269 TRACE(_T("Could not connect to %s:%d - %s\n"),(LPCTSTR )strHost,port,(LPCTSTR )strMsg);
270 CloseSocket(m_nSock);
271 } else {
272 #ifndef _WIN32
273 SetSocketOptions();
274 #endif
275 }
276 }
277 }
278 }
279 delete [] pszHost;
280 return -1!=m_nSock;
281 }
282
283 bool CeCosTestSocket::sendrecv(bool bSend,const void *pData,unsigned int nLength,
284 LPCTSTR pszMsg,Duration dTimeout,CeCosTestSocket::StopFunc pFnStop,void *pParam)
285 {
286
287 dTimeout=TimeoutDuration(dTimeout);
288
289 LPCTSTR pszSR=(bSend?_T("sending"):_T("receiving"));
290 LPTSTR c=(LPTSTR )pData;
291 Time ft0=Now();
292 int nTodo=nLength;
293 while((nTodo>0) && ((0==pFnStop) || (!pFnStop(pParam)))){
294 int s=bSend?::send(m_nSock, (const char *)c, nTodo, 0): ::recv(m_nSock, (char *)c, nTodo, 0);
295 if(0==s && !bSend){
296 m_nErr=ERR_READ_AFTER_CLOSE;
297 } else {
298 SaveError();
299 }
300 if(-1==s && WOULDBLOCK==SocketError()){
301 Duration d=Duration(Now()-ft0);
302 if(d>dTimeout){
303 TRACE(_T("%d/%d mSec timeout on socket %d %s %s - processed %d/%d bytes\n") ,
304 d,dTimeout,m_nSock,pszSR,pszMsg,
305 nLength-nTodo,nLength);
306 m_nErr=ERR_TIMEOUT;
307 break;
308 }
309 Sleep(100);
310 } else if (s>0) {
311 c+=s;
312 nTodo-=s;
313 ft0=Now();
314 } else {
315 TRACE(_T("Error on socket %d %s %s - %s\n") ,m_nSock, pszSR, pszMsg, (LPCTSTR )SocketErrString());
316 break;
317 }
318 }
319 return 0==nTodo;
320 }
321
322 // Graceful socket closedown
323 CeCosTestSocket::~CeCosTestSocket()
324 {
325 Close();
326 TRACE(_T("Delete socket instance %08x\n"),(unsigned int)this);
327 }
328
329 bool CeCosTestSocket::CloseSocket(int &sock)
330 {
331 bool rc=false;
332 if(-1!=sock){
333 TRACE(_T("Closing socket %d\n"),sock);
334 try{
335 shutdown(sock,0);// SD_BOTH
336 #ifdef _WIN32
337 rc=(0==closesocket(sock));
338 #else // UNIX
339 rc=(0==close(sock));
340 #endif
341 }
342 catch(...) {
343 TRACE(_T("!!! Exception caught in CeCosTestSocket::CloseSocket!!!\n"));
344 }
345 sock=-1;
346 }
347 return rc;
348 }
349
350 bool CeCosTestSocket::SetSocketOptions()
351 {
352 bool rc;
353 #ifdef _WIN32
354 int nTrue=1;
355 rc=(0==::ioctlsocket(m_nSock, FIONBIO, (unsigned long *)&nTrue));
356 SaveError();
357 #else // UNIX
358 int flags=::fcntl(m_nSock,F_GETFL);
359 SaveError();
360 flags|=O_NONBLOCK;
361 rc=(0==::fcntl (m_nSock, F_SETFL, flags));
362 SaveError();
363 #endif
364 //LINGER linger;
365 //setsockopt(m_nSock,SOL_SOCKET,SO_LINGER,(LPCTSTR )linger, sizeof(LINGER));
366 if(!rc){
367 TRACE(_T("Failed to set socket options socket %d - %s\n"),m_nSock,(LPCTSTR )SocketErrString());
368 }
369 return rc;
370 }
371
372 String CeCosTestSocket::SocketErrString(int nErr)
373 {
374 String str;
375 #ifdef _WIN32
376 switch(nErr){
377 case ERR_TIMEOUT: str=_T("Read operation timed out");break;
378 case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break;
379
380 case WSAEACCES: str=_T("Permission denied");break;
381 case WSAEADDRINUSE: str=_T("Address already in use");break;
382 case WSAEADDRNOTAVAIL: str=_T("Cannot assign requested address");break;
383 case WSAEAFNOSUPPORT: str=_T("Address family not supported by protocol family");break;
384 case WSAEALREADY: str=_T("Operation already in progress");break;
385 case WSAECONNABORTED: str=_T("Software caused connection abort");break;
386 case WSAECONNREFUSED: str=_T("Connection refused");break;
387 case WSAECONNRESET: str=_T("Connection reset by peer");break;
388 case WSAEDESTADDRREQ: str=_T("Destination address required");break;
389 case WSAEFAULT: str=_T("Bad address");break;
390 case WSAEHOSTDOWN: str=_T("Host is down");break;
391 case WSAEHOSTUNREACH: str=_T("No route to host");break;
392 case WSAEINPROGRESS: str=_T("Operation now in progress");break;
393 case WSAEINTR: str=_T("Interrupted function call");break;
394 case WSAEINVAL: str=_T("Invalid argument");break;
395 case WSAEISCONN: str=_T("Socket is already connected");break;
396 case WSAEMFILE: str=_T("Too many open files");break;
397 case WSAEMSGSIZE: str=_T("Message too long");break;
398 case WSAENETDOWN: str=_T("Network is down");break;
399 case WSAENETRESET: str=_T("Network dropped connection on reset");break;
400 case WSAENETUNREACH: str=_T("Network is unreachable");break;
401 case WSAENOBUFS: str=_T("No buffer space available");break;
402 case WSAENOPROTOOPT: str=_T("Bad protocol option");break;
403 case WSAENOTCONN: str=_T("Socket is not connected");break;
404 case WSAENOTSOCK: str=_T("Socket operation on non-socket");break;
405 case WSAEOPNOTSUPP: str=_T("Operation not supported");break;
406 case WSAEPFNOSUPPORT: str=_T("Protocol family not supported");break;
407 case WSAEPROCLIM: str=_T("Too many processes");break;
408 case WSAEPROTONOSUPPORT: str=_T("Protocol not supported");break;
409 case WSAEPROTOTYPE: str=_T("Protocol wrong type for socket");break;
410 case WSAESHUTDOWN: str=_T("Cannot send after socket shutdown");break;
411 case WSAESOCKTNOSUPPORT: str=_T("Socket type not supported");break;
412 case WSAETIMEDOUT: str=_T("Connection timed out");break;
413 case WSATYPE_NOT_FOUND: str=_T("Class type not found");break;
414 case WSAEWOULDBLOCK: str=_T("Resource temporarily unavailable");break;
415 case WSAHOST_NOT_FOUND: str=_T("Host not found");break;
416 case WSA_INVALID_HANDLE: str=_T("Specified event object handle is invalid");break;
417 case WSA_INVALID_PARAMETER: str=_T("One or more parameters are invalid");break;
418 //case WSAINVALIDPROCTABLE: str=_T("Invalid procedure table from service provider");break;
419 //case WSAINVALIDPROVIDER: str=_T("Invalid service provider version number");break;
420 case WSA_IO_INCOMPLETE: str=_T("Overlapped I/O event object not in signaled state");break;
421 case WSA_IO_PENDING: str=_T("Overlapped operations will complete later");break;
422 case WSA_NOT_ENOUGH_MEMORY: str=_T("Insufficient memory available");break;
423 case WSANOTINITIALISED: str=_T("Successful case WSAStartup not yet:performed");break;
424 case WSANO_DATA: str=_T("Valid name, no data record of requested type");break;
425 case WSANO_RECOVERY: str=_T("This is a non-recoverable error");break;
426 //case WSAPROVIDERFAILEDINIT: str=_T("Unable to initialize a service provider");break;
427 case WSASYSCALLFAILURE: str=_T("System call failure");break;
428 case WSASYSNOTREADY: str=_T("Network subsystem is unavailable");break;
429 case WSATRY_AGAIN: str=_T("Non-authoritative host not found");break;
430 case WSAVERNOTSUPPORTED: str=_T("WINSOCK.DLL version out of range");break;
431 case WSAEDISCON: str=_T("Graceful shutdown in progress");break;
432 case WSA_OPERATION_ABORTED: str=_T("Overlapped operation aborted");break;
433 default:
434 str.Format(_T("Unknown error %d (0x%08x)"),nErr,nErr);
435 }
436 #else // UNIX
437 switch(nErr){
438 case ERR_TIMEOUT: str=_T("Read operation timed out");break;
439 case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break;
440 default:
441 str=strerror(errno);
442 }
443 #endif
444 return str;
445 }
446
447 bool CeCosTestSocket::sendInteger(int n,LPCTSTR pszMsg,Duration dTimeout)
448 {
449 // This has to support cross-architectural endianness
450 unsigned char c[sizeof(int)];
451 for(unsigned int i=0;i<sizeof(int);i++){
452 c[i]=(unsigned char)(n&0xff);
453 n>>=8;
454 }
455 return send (c, sizeof(int),pszMsg,dTimeout);
456 }
457
458 bool CeCosTestSocket::recvInteger(int & n,LPCTSTR pszMsg,Duration dTimeout)
459 {
460 // This has to support cross-architectural endianness
461 unsigned char c[sizeof(int)];
462 bool rc=recv (c, sizeof(int),pszMsg,dTimeout);
463 n=0;
464 if(rc){
465 for(int i=sizeof(int)-1;i>=0;--i){
466 n<<=8;
467 n|=c[i];
468 }
469 }
470 return rc;
471 }
472
473 // Socket communications for strings are always non-UNICODE:
474 bool CeCosTestSocket::recvString (String &str,LPCTSTR pszMsg,Duration dTimeout)
475 {
476 int nLength;
477 bool rc=false;
478 if(recvInteger(nLength,pszMsg,dTimeout)){
479 if(0==nLength){
480 rc=true;
481 } else {
482 Buffer b(1+nLength);
483 char *c=(char *)b.Data();
484 if(c){
485 rc=recv(c,nLength,pszMsg,dTimeout);
486 c[nLength]='\0';
487 str=String::CStrToUnicodeStr(c);
488 }
489 }
490 }
491 return rc;
492 }
493
494 // Socket communications for strings are always non-UNICODE:
495 bool CeCosTestSocket::sendString (const String &str,LPCTSTR pszMsg,Duration dTimeout)
496 {
497 char *psz=str.GetCString();
498 int nLength=strlen(psz);
499 bool rc=sendInteger(nLength,pszMsg,dTimeout) && (0==nLength || send(psz,nLength,pszMsg,dTimeout));
500 delete [] psz;
501 return rc;
502 }
503
504
505 // Give indication of bytes available to be read (but don't read them)
506 bool CeCosTestSocket::Peek (unsigned int &nAvail)
507 {
508 char buf[8192];
509 int n=::recv(m_nSock, buf, sizeof buf, MSG_PEEK);
510 nAvail=0;
511 bool rc=false;
512 switch(n) {
513 case -1:
514 SaveError();
515 if(WOULDBLOCK==SocketError()){
516 rc=true; // nAvail stays==0
517 } else {
518 ERROR(_T("Peek: err=%d %s\n"),SocketError(),(LPCTSTR )SocketErrString());
519 }
520 break;
521 case 0:
522 m_nErr=ERR_READ_AFTER_CLOSE;
523 break;
524 default:
525 rc=true;
526 nAvail=n;
527 }
528 return rc;
529 }
530
531 // Connect tcp/ip port and serial port together.
532 // Traffic is passed through pFunc, passed parameter pParam.
533 // The pFunc function:
534 // may reallocate pBuf (using malloc/realloc etc...)
535 // must leave pBuf allocated on exit
536 // should not close either serial or socket
537 // should leave writing to its caller
538 // should return false if it wishes to terminate the connection (after caller has written output)
539 bool CeCosTestSocket::ConnectSocketToSerial (CeCosTestSocket &socket,CeCosTestSerial &serial,FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,bool *pbStop/*=0*/)
540 {
541 serial.ClearError();
542 enum {BUFSIZE=8192};
543 void *pBuf=malloc(BUFSIZE);
544 TRACE(_T("ConnectSocketToSerial: connected\n"));
545 bool rc=true;
546 try {
547 /*
548 { //hack
549 unsigned int nWritten;//hack
550 serial.Write(_T("+"),1,nWritten);//hack
551 }//hack
552 */
553 while(rc && (0==pbStop || !(*pbStop))){
554 unsigned int nRead=0;
555 switch(SSRead (serial,socket,pBuf,BUFSIZE,nRead,pbStop)){
556 case 2:
557 VTRACE(_T("Serial:%d\n"),nRead);
558 if(pSerialToSocketFilterFunc){
559 rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,socket,pSerialParam);
560 }
561 if(nRead && !socket.send(pBuf,nRead)){
562 TRACE(_T("Failed to write to socket\n"));
563 rc=false;
564 }
565 break;
566 case 1:
567 unsigned int nWritten;
568 VTRACE(_T("Socket:%d\n"),nRead);
569 if(pSocketToSerialFilterFunc){
570 rc=pSocketToSerialFilterFunc(pBuf,nRead,serial,socket,pSocketParam);
571 }
572 {
573 LPTSTR c=(LPTSTR )pBuf;
574 int nToWrite=nRead;
575 while(nToWrite>0){
576 if(!serial.Write(pBuf,nRead,nWritten)){
577 TRACE(_T("Failed to write to serial\n"));
578 rc=false;
579 break;
580 }
581 nToWrite-=nWritten;
582 c+=nWritten;
583 }
584 }
585 break;
586 case 0:
587 TRACE(_T("SSRead returned error indication\n"));
588 rc=false;
589 break;
590 // Error
591 }
592 }
593 }
594 catch (...){
595 TRACE(_T("!!! ConnectSocketToSerial exception caught!!!\n"));
596 free(pBuf);
597 throw;
598 }
599 free(pBuf);
600 return rc;
601 }
602
603 // Connect two tcp/ip ports together.
604 // Traffic is passed through pFunc, passed parameter pParam.
605 // The pFunc function:
606 // may reallocate pBuf (using malloc/realloc etc...)
607 // must leave pBuf allocated on exit
608 // should not close either serial or socket
609 // should leave writing to its caller
610 // should return false if it wishes to terminate the connection (after caller has written output)
611 bool CeCosTestSocket::ConnectSocketToSocket (CeCosTestSocket &o,FilterFunc *pSocketToSocketFilterFunc1,FilterFunc *pSocketToSocketFilterFunc2,void *pParam,bool *pbStop)
612 {
613 enum {BUFSIZE=8192};
614 void *pBuf=malloc(BUFSIZE);
615 TRACE(_T("ConnectSocketToSocket: connected\n"));
616 bool rc=true;
617 try {
618 while(rc && (0==pbStop || !(*pbStop))){
619 fd_set set;
620 FD_ZERO(&set);
621 FD_SET((unsigned)m_nSock, &set);
622 FD_SET((unsigned)o.m_nSock, &set);
623 struct timeval tv;
624 tv.tv_sec = 1;
625 tv.tv_usec = 0;
626 switch(::select(m_nSock,&set,0,0,&tv)){
627 case -1:
628 rc=false;
629 break;
630 case 1:
631 case 2:
632 {
633 unsigned int nAvail=0;
634 if(FD_ISSET((unsigned)m_nSock, &set) && Peek(nAvail) && recv(pBuf,nAvail)){
635 //rc=pSocketToSocketFilterFunc1(pBuf,nAvail,socket,this,o);
636 o.send(pBuf,nAvail);
637 }
638 if(FD_ISSET((unsigned)o.m_nSock, &set) && o.Peek(nAvail) && o.recv(pBuf,nAvail)){
639 //rc=pSocketToSocketFilterFunc2(pBuf,nAvail,socket,o,this);
640 send(pBuf,nAvail);
641 }
642 }
643 case 0:
644 break;
645 }
646 }
647 }
648 catch (...){
649 TRACE(_T("!!! ConnectSocketToSocket exception caught!!!\n"));
650 rc=false;
651 }
652 free(pBuf);
653 return rc;
654 }
655
656 bool CeCosTestSocket::ConnectSocketToSerial (
657 int nListenSock,LPCTSTR pszPort, int nBaud,
658 FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,
659 bool *pbStop)
660 {
661 bool rc=false;
662 try{
663 TRACE(_T("ConnectSocketToSerial : socket %d <--> %s\n"),nListenSock,pszPort);
664
665 CeCosTestSerial serial;
666 serial.SetBlockingReads(false);
667 // Open serial device.
668 if (!serial.Open(pszPort,nBaud)){
669 ERROR(_T("Couldn't open port %s\n"),pszPort);
670 } else {
671 // Flush the serial buffer.
672 serial.Flush();
673
674 TRACE(_T("ConnectSocketToSerial: waiting for connection...\n"));
675 CeCosTestSocket socket;
676 if(!socket.Accept(nListenSock,pbStop)){
677 ERROR(_T("ConnectSocketToSerial - couldn't accept\n"));
678 } else {
679 rc=ConnectSocketToSerial (socket,serial,pSerialToSocketFilterFunc,pSerialParam,pSocketToSerialFilterFunc,pSocketParam,pbStop);
680 }
681 }
682 TRACE(_T("ConnectSocketToSerial : done\n"));
683 }
684 catch(...){
685 TRACE(_T("ConnectSocketToSerial !!!exception handled!!!\n"));
686 }
687 return rc;
688 }
689
690 String CeCosTestSocket::ClientName(int nClient)
691 {
692 char ip[4];
693 memcpy(ip,&nClient,4);
694 struct hostent *he=::gethostbyaddr((const char *)ip,4,AF_INET);
695 String str;
696 if(he){
697 str=String::CStrToUnicodeStr(he->h_name);
698 } else {
699 str.Format(_T("%u.%u.%u.%u"),ip[0],ip[1],ip[2],ip[3]);
700 }
701 return str;
702 }
703
704 String CeCosTestSocket::HostPort(LPCTSTR pszHost,int nPort)
705 {
706 String str;
707 str.Format(_T("%s:%d"),pszHost,nPort);
708 return str;
709 }
710
711 // Split the string into host:port parts. Result tells us whether it was successful.
712 bool CeCosTestSocket::ParseHostPort (LPCTSTR pszHostPort, String &strHost, int &nPort)
713 {
714 int n=_stscanf(pszHostPort,_T("%[^:]:%d"),strHost.GetBuffer(_tcslen(pszHostPort)),&nPort);
715 strHost.ReleaseBuffer();
716 return 2==n && nPort>0 && nPort<=0xffff;
717 }
718
719 // Is the string in the form host:port?
720 bool CeCosTestSocket::IsLegalHostPort (LPCTSTR pszHostPort)
721 {
722 int nPort=0;
723 String strHost;
724 return ParseHostPort(pszHostPort,strHost,nPort);
725 }
726
727 // Translate a timeout that may be one of the special values DEFAULTTIMEOUT or NOTIMEOUT to a value in milliseconds.
728 Duration CeCosTestSocket::TimeoutDuration(Duration dTimeout)
729 {
730 switch(dTimeout){
731 case DEFAULTTIMEOUT:
732 dTimeout=m_nDefaultTimeout;
733 break;
734 case NOTIMEOUT:
735 dTimeout=0x7fffffff;
736 break;
737 default:
738 break;
739 }
740 return dTimeout;
741 }
742
743 bool CeCosTestSocket::IsSocketError(int n)
744 {
745 #ifdef _WIN32
746 return n>=WSABASEERR && n<30000; // include our own (e.g. ERR_READ_AFTER_CLOSE)
747 #else // UNIX
748 return true;
749 #endif
750 }
751
752 String CeCosTestSocket::SocketErrString() {
753 return SocketErrString(m_nErr);
754 }
755
756
757 bool CeCosTestSocket::SameHost(LPCTSTR host1, LPCTSTR host2)
758 {
759 char *h1=String(host1).GetCString();
760 char *h2=String(host2).GetCString();
761 char ip1[16],ip2[16];
762 struct hostent* host_dat;
763 bool rc=(0==_tcscmp(host1,host2));
764 if (0!=(host_dat=::gethostbyname(h1))){
765 char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) );
766 if(c){
767 strcpy(ip1,c);
768 if (0!=(host_dat=::gethostbyname(h2))){
769 char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) );
770 if(c){
771 strcpy(ip2,c);
772 }
773 }
774 rc=(0==strcmp(ip1,ip2));
775 }
776 }
777 delete [] h1;
778 delete [] h2;
779 return rc;
780 }