OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [tools/] [Utils/] [common/] [eCosSocket.cpp] - Blame information for rev 790

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.