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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [Utils/] [common/] [eCosSocket.cpp] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 unneback
//####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
//        eCosSocket.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 "eCosSocket.h"
45
#include "eCosSerial.h"
46
#include "eCosThreadUtils.h"
47
#include "eCosTrace.h"
48
#include <map>
49
 
50
enum {ERR_TIMEOUT=20000, ERR_READ_AFTER_CLOSE=20001};
51
 
52
// Blocking read on one or other of the data sources:
53
// Result:  -1 - socket error occurred
54
//           1 - data read from socket
55
//          -2 - serial error occurred
56
//           2 - data read from serial
57
 
58
CeCosSocket::SSReadResult CeCosSocket::SSRead (CeCosSerial &serial,CeCosSocket &socket,void *pBuf,unsigned int nSize,unsigned int &nRead,bool *pbStop)
59
{
60
  SSReadResult rc=SS_STOPPED;
61
  bool bBlocking=serial.GetBlockingReads();
62
  bool bBlockingModified=false;
63
  while(0==pbStop || !(*pbStop)){
64
    if(!socket.Peek(nRead)){
65
      rc=SS_SOCKET_ERROR;
66
      break;
67
    } else if(nRead){
68
      nRead=MIN(nRead,nSize);
69
      rc=socket.recv(pBuf,nRead)?SS_SOCKET_READ:SS_SOCKET_ERROR;
70
      break;
71
    } else {
72
      if(bBlocking){
73
        serial.SetBlockingReads(false);
74
        bBlockingModified=true;
75
        bBlocking=false;
76
      }
77
      if(serial.Read(pBuf,nSize,nRead)){
78
        if(nRead>0){
79
          rc=SS_SERIAL_READ;
80
          break;
81
        }
82
      } else {
83
        rc=SS_SERIAL_ERROR;
84
        break;
85
      }
86
    }
87
    CeCosThreadUtils::Sleep(10);
88
  }
89
  if(bBlockingModified){
90
    serial.SetBlockingReads(true);
91
  }
92
  return rc;
93
}
94
 
95
// ctors and dtors
96
 
97
CeCosSocket::CeCosSocket ():
98
m_nDefaultTimeout(10*1000),
99
m_nSock(-1),
100
m_nClient(0)
101
{
102
  VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
103
}
104
 
105
CeCosSocket::CeCosSocket (int sock /*result of previous call of Listen*/, bool *pbStop):
106
m_nDefaultTimeout(10*1000),
107
m_nSock(-1),
108
m_nClient(0)
109
{
110
  VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
111
  Accept(sock,pbStop);
112
}
113
 
114
CeCosSocket::CeCosSocket (LPCTSTR pszHostPort,Duration dTimeout):
115
m_nDefaultTimeout(10*1000),
116
m_nSock(-1),
117
m_nClient(0)
118
{
119
  VTRACE(_T("Create socket instance %08x\n"),(unsigned int)this);
120
  Connect(pszHostPort,dTimeout);
121
}
122
 
123
bool CeCosSocket::Accept(int sock /*result of previous call of Listen*/, bool *pbStop)
124
{
125
  m_nSock=-1;
126
  while(0==pbStop||!*pbStop){
127
    struct sockaddr cli_addr;
128
#ifndef _WIN32
129
    unsigned
130
#endif
131
      int clilen=sizeof(struct sockaddr);
132
    m_nSock=::accept(sock, (struct sockaddr *) &cli_addr, &clilen);
133
    SaveError();
134
    if(-1==m_nSock){
135
      if(WOULDBLOCK==SocketError()){
136
        CeCosThreadUtils::Sleep(100);
137
        continue;
138
      }
139
    } else {
140
      memcpy(&m_nClient,cli_addr.sa_data+2,4);
141
      TRACE(_T("Connection accepted from %s - socket %d\n"),(LPCTSTR )ClientName(m_nClient),m_nSock);
142
      SetSocketOptions();
143
      break;
144
    }
145
  }
146
  return -1!=m_nSock;
147
}
148
 
149
int CeCosSocket::Listen(int nTcpPort)
150
{
151
  // Create socket
152
  int sock=::socket(AF_INET, SOCK_STREAM, 0);
153
  if (sock == -1) {
154
    ERROR(_T("Couldn't create socket\n"));
155
  } else {
156
    VTRACE(_T("Created socket %d listening on port %d\n"),sock,nTcpPort);
157
    // Bind socket to address
158
    struct sockaddr_in serv_addr;
159
    memset(&serv_addr, 0, sizeof serv_addr);
160
 
161
    serv_addr.sin_family = AF_INET;
162
    serv_addr.sin_port=htons((short)nTcpPort);
163
    serv_addr.sin_addr.s_addr = INADDR_ANY;
164
 
165
    if (::bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
166
      TRACE(_T("Couldn't bind socket on port %d\n"),nTcpPort);
167
      CloseSocket(sock);
168
    } else if (-1==::listen(sock, SOMAXCONN)){
169
      CloseSocket(sock);
170
      TRACE(_T("socket error on listen - port %d\n"),nTcpPort);
171
    } else {
172
#ifdef _WIN32
173
      int nTrue=1;
174
      bool rc=(0==::ioctlsocket(sock, FIONBIO, (unsigned long *)&nTrue));
175
#else //UNIX
176
      int flags=::fcntl(sock,F_GETFL);
177
      flags|=O_NONBLOCK;
178
      bool rc=(0==::fcntl (sock, F_SETFL, flags));
179
#endif
180
      if(!rc){
181
        TRACE(_T("Failed to set socket options on socket %d\n"),sock);
182
      }
183
    }
184
  }
185
  return sock;
186
}
187
 
188
bool CeCosSocket::Connect(LPCTSTR pszHostPort,Duration dTimeout)
189
{
190
  dTimeout=TimeoutDuration(dTimeout);
191
  struct sockaddr_in serv_addr;
192
 
193
  VTRACE(_T("Connect: %s timeout=%d\n"),pszHostPort,dTimeout);
194
 
195
  // Get the target host address
196
  String strHost;
197
  int nPort;
198
  CeCosSocket::ParseHostPort(pszHostPort,strHost,nPort);
199
  String strErr;
200
 
201
  char *ip=GetHostByName(strHost).GetCString();
202
  memset(&serv_addr, 0, sizeof serv_addr);
203
  // Create socket
204
  m_nSock = ::socket(AF_INET, SOCK_STREAM, 0);
205
  if (-1 == m_nSock) {
206
    TRACE(_T("Could not create socket [%s]\n"),pszHostPort);
207
  } else {
208
#ifdef _WIN32
209
    SetSocketOptions();
210
#endif
211
    VTRACE(_T("Created socket %d connected to %s\n"),m_nSock,pszHostPort);
212
    // Bind socket to address
213
    serv_addr.sin_family = AF_INET;
214
    serv_addr.sin_port=htons((short)nPort);
215
    SaveError();
216
    serv_addr.sin_addr.s_addr = inet_addr(ip);
217
 
218
    // Connect to server
219
    VTRACE(_T("Connect() : connecting to server\n"));
220
    int cc=::connect(m_nSock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
221
    SaveError();
222
    String strMsg;
223
    if(-1==cc){
224
      if(
225
#ifdef _WIN32
226
        WOULDBLOCK==SocketError()
227
#else // UNIX
228
        EINPROGRESS==SocketError()
229
#endif
230
        ){
231
        // Allow dTimeout milliseconds for connect to complete
232
        fd_set set;
233
        FD_ZERO(&set);
234
#ifdef _WIN32
235
#pragma warning( push )
236
#pragma warning( disable : 4127 ) // conditional expression is constant
237
#endif
238
        FD_SET((unsigned)m_nSock, &set);
239
#ifdef _WIN32
240
#pragma warning( pop )
241
#endif
242
        struct timeval tv;
243
        tv.tv_sec = dTimeout/1000;
244
        tv.tv_usec = 1000*(dTimeout % 1000);
245
        switch(::select(m_nSock, NULL, &set , NULL, &tv)){
246
        case 0:
247
          m_nErr=ERR_TIMEOUT;
248
          strMsg.Format(_T("attempt timed out after %d seconds"),dTimeout/1000);
249
          break;
250
        case -1:
251
          SaveError();
252
          strMsg=SocketErrString();
253
          break;
254
        default:
255
          cc=0;
256
        }
257
      } else {
258
        strMsg=SocketErrString();
259
      }
260
    }
261
 
262
    if(-1==cc){
263
      TRACE(_T("Could not connect to %s - %s\n"),pszHostPort,(LPCTSTR)strMsg);
264
      CloseSocket(m_nSock);
265
    }  else {
266
#ifndef _WIN32
267
      SetSocketOptions();
268
#endif
269
    }
270
  }
271
  delete [] ip;
272
  return -1!=m_nSock;
273
}
274
 
275
bool CeCosSocket::sendrecv(bool bSend,const void *pData,unsigned int nLength,
276
                           LPCTSTR pszMsg,Duration dTimeout,CeCosSocket::StopFunc pFnStop,void *pParam)
277
{
278
 
279
  dTimeout=TimeoutDuration(dTimeout);
280
 
281
  LPCTSTR pszSR=(bSend?_T("sending"):_T("receiving"));
282
  LPTSTR c=(LPTSTR )pData;
283
  Time ft0=Now();
284
  int nTodo=nLength;
285
  while((nTodo>0) && ((0==pFnStop) || (!pFnStop(pParam)))){
286
    int s=bSend?::send(m_nSock, (const char *)c, nTodo, 0): ::recv(m_nSock, (char *)c, nTodo, 0);
287
    if(0==s && !bSend){
288
      m_nErr=ERR_READ_AFTER_CLOSE;
289
    } else {
290
      SaveError();
291
    }
292
    if(-1==s && WOULDBLOCK==SocketError()){
293
      Duration d=Duration(Now()-ft0);
294
      if(d>dTimeout){
295
        TRACE(_T("%d/%d mSec timeout on socket %d %s %s - processed %d/%d bytes\n") ,
296
          d,dTimeout,m_nSock,pszSR,pszMsg,
297
          nLength-nTodo,nLength);
298
        m_nErr=ERR_TIMEOUT;
299
        break;
300
      }
301
      CeCosThreadUtils::Sleep(100);
302
    } else if (s>0) {
303
      c+=s;
304
      nTodo-=s;
305
      ft0=Now();
306
    } else {
307
      TRACE(_T("Error on socket %d %s %s - %s\n") ,m_nSock, pszSR, pszMsg, (LPCTSTR )SocketErrString());
308
      break;
309
    }
310
  }
311
  return 0==nTodo;
312
}
313
 
314
// Graceful socket closedown
315
CeCosSocket::~CeCosSocket()
316
{
317
  Close();
318
  VTRACE(_T("Delete socket instance %08x\n"),(unsigned int)this);
319
}
320
 
321
bool CeCosSocket::CloseSocket(int &sock)
322
{
323
  bool rc=false;
324
  if(-1!=sock){
325
    VTRACE(_T("Closing socket %d\n"),sock);
326
    try{
327
      shutdown(sock,0);// SD_BOTH
328
#ifdef _WIN32
329
      rc=(0==closesocket(sock));
330
#else // UNIX
331
      rc=(0==close(sock));
332
#endif
333
    }
334
    catch(...) {
335
      TRACE(_T("!!! Exception caught in CeCosSocket::CloseSocket!!!\n"));
336
    }
337
    sock=-1;
338
  }
339
  return rc;
340
}
341
 
342
bool CeCosSocket::SetSocketOptions()
343
{
344
  bool rc;
345
#ifdef _WIN32
346
  int nTrue=1;
347
  rc=(0==::ioctlsocket(m_nSock, FIONBIO, (unsigned long *)&nTrue));
348
  SaveError();
349
#else // UNIX
350
  int flags=::fcntl(m_nSock,F_GETFL);
351
  SaveError();
352
  flags|=O_NONBLOCK;
353
  rc=(0==::fcntl (m_nSock, F_SETFL, flags));
354
  SaveError();
355
#endif
356
  int bLinger=0;
357
  setsockopt(m_nSock,SOL_SOCKET,SO_LINGER,(const char *)&bLinger, sizeof(bLinger));
358
  if(!rc){
359
    TRACE(_T("Failed to set socket options socket %d - %s\n"),m_nSock,(LPCTSTR )SocketErrString());
360
  }
361
  return rc;
362
}
363
 
364
String CeCosSocket::SocketErrString(int nErr)
365
{
366
  String str;
367
#ifdef _WIN32
368
  switch(nErr){
369
  case ERR_TIMEOUT: str=_T("Read operation timed out");break;
370
  case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break;
371
 
372
  case WSAEACCES: str=_T("Permission denied");break;
373
  case WSAEADDRINUSE: str=_T("Address already in use");break;
374
  case WSAEADDRNOTAVAIL: str=_T("Cannot assign requested address");break;
375
  case WSAEAFNOSUPPORT: str=_T("Address family not supported by protocol family");break;
376
  case WSAEALREADY: str=_T("Operation already in progress");break;
377
  case WSAECONNABORTED: str=_T("Software caused connection abort");break;
378
  case WSAECONNREFUSED: str=_T("Connection refused");break;
379
  case WSAECONNRESET: str=_T("Connection reset by peer");break;
380
  case WSAEDESTADDRREQ: str=_T("Destination address required");break;
381
  case WSAEFAULT: str=_T("Bad address");break;
382
  case WSAEHOSTDOWN: str=_T("Host is down");break;
383
  case WSAEHOSTUNREACH: str=_T("No route to host");break;
384
  case WSAEINPROGRESS: str=_T("Operation now in progress");break;
385
  case WSAEINTR: str=_T("Interrupted function call");break;
386
  case WSAEINVAL: str=_T("Invalid argument");break;
387
  case WSAEISCONN: str=_T("Socket is already connected");break;
388
  case WSAEMFILE: str=_T("Too many open files");break;
389
  case WSAEMSGSIZE: str=_T("Message too long");break;
390
  case WSAENETDOWN: str=_T("Network is down");break;
391
  case WSAENETRESET: str=_T("Network dropped connection on reset");break;
392
  case WSAENETUNREACH: str=_T("Network is unreachable");break;
393
  case WSAENOBUFS: str=_T("No buffer space available");break;
394
  case WSAENOPROTOOPT: str=_T("Bad protocol option");break;
395
  case WSAENOTCONN: str=_T("Socket is not connected");break;
396
  case WSAENOTSOCK: str=_T("Socket operation on non-socket");break;
397
  case WSAEOPNOTSUPP: str=_T("Operation not supported");break;
398
  case WSAEPFNOSUPPORT: str=_T("Protocol family not supported");break;
399
  case WSAEPROCLIM: str=_T("Too many processes");break;
400
  case WSAEPROTONOSUPPORT: str=_T("Protocol not supported");break;
401
  case WSAEPROTOTYPE: str=_T("Protocol wrong type for socket");break;
402
  case WSAESHUTDOWN: str=_T("Cannot send after socket shutdown");break;
403
  case WSAESOCKTNOSUPPORT: str=_T("Socket type not supported");break;
404
  case WSAETIMEDOUT: str=_T("Connection timed out");break;
405
  case WSATYPE_NOT_FOUND: str=_T("Class type not found");break;
406
  case WSAEWOULDBLOCK: str=_T("Resource temporarily unavailable");break;
407
  case WSAHOST_NOT_FOUND: str=_T("Host not found");break;
408
  case WSA_INVALID_HANDLE: str=_T("Specified event object handle is invalid");break;
409
  case WSA_INVALID_PARAMETER: str=_T("One or more parameters are invalid");break;
410
    //case WSAINVALIDPROCTABLE: str=_T("Invalid procedure table from service provider");break;
411
    //case WSAINVALIDPROVIDER: str=_T("Invalid service provider version number");break;
412
  case WSA_IO_INCOMPLETE: str=_T("Overlapped I/O event object not in signaled state");break;
413
  case WSA_IO_PENDING: str=_T("Overlapped operations will complete later");break;
414
  case WSA_NOT_ENOUGH_MEMORY: str=_T("Insufficient memory available");break;
415
  case WSANOTINITIALISED: str=_T("Successful case WSAStartup not yet:performed");break;
416
  case WSANO_DATA: str=_T("Valid name, no data record of requested type");break;
417
  case WSANO_RECOVERY: str=_T("This is a non-recoverable error");break;
418
    //case WSAPROVIDERFAILEDINIT: str=_T("Unable to initialize a service provider");break;
419
  case WSASYSCALLFAILURE: str=_T("System call failure");break;
420
  case WSASYSNOTREADY: str=_T("Network subsystem is unavailable");break;
421
  case WSATRY_AGAIN: str=_T("Non-authoritative host not found");break;
422
  case WSAVERNOTSUPPORTED: str=_T("WINSOCK.DLL version out of range");break;
423
  case WSAEDISCON: str=_T("Graceful shutdown in progress");break;
424
  case WSA_OPERATION_ABORTED: str=_T("Overlapped operation aborted");break;
425
  default:
426
    str.Format(_T("Unknown error %d (0x%08x)"),nErr,nErr);
427
  }
428
#else // UNIX
429
  switch(nErr){
430
  case ERR_TIMEOUT: str=_T("Read operation timed out");break;
431
  case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break;
432
  default:
433
    str=strerror(errno);
434
  }
435
#endif
436
  return str;
437
}
438
 
439
bool CeCosSocket::sendInteger(int n,LPCTSTR pszMsg,Duration dTimeout)
440
{
441
  // This has to support cross-architectural endianness
442
  unsigned char c[sizeof(int)];
443
  for(unsigned int i=0;i<sizeof(int);i++){
444
    c[i]=(unsigned char)(n&0xff);
445
    n>>=8;
446
  }
447
  return send (c, sizeof(int),pszMsg,dTimeout);
448
}
449
 
450
bool CeCosSocket::recvInteger(int & n,LPCTSTR pszMsg,Duration dTimeout)
451
{
452
  // This has to support cross-architectural endianness
453
  unsigned char c[sizeof(int)];
454
  bool rc=recv (c, sizeof(int),pszMsg,dTimeout);
455
  n=0;
456
  if(rc){
457
    for(int i=sizeof(int)-1;i>=0;--i){
458
      n<<=8;
459
      n|=c[i];
460
    }
461
  }
462
  return rc;
463
}
464
 
465
// Socket communications for strings are always non-UNICODE:
466
bool CeCosSocket::recvString  (String &str,LPCTSTR pszMsg,Duration dTimeout)
467
{
468
  int nLength;
469
  bool rc=false;
470
  if(recvInteger(nLength,pszMsg,dTimeout)){
471
    if(0==nLength){
472
      rc=true;
473
    } else {
474
      Buffer b(1+nLength);
475
      char *c=(char *)b.Data();
476
      if(c){
477
        rc=recv(c,nLength,pszMsg,dTimeout);
478
        c[nLength]='\0';
479
        str=String::CStrToUnicodeStr(c);
480
      }
481
    }
482
  }
483
  return rc;
484
}
485
 
486
// Socket communications for strings are always non-UNICODE:
487
bool CeCosSocket::sendString  (const String &str,LPCTSTR pszMsg,Duration dTimeout)
488
{
489
  char *psz=str.GetCString();
490
  int nLength=strlen(psz);
491
  bool rc=sendInteger(nLength,pszMsg,dTimeout) && (0==nLength || send(psz,nLength,pszMsg,dTimeout));
492
  delete [] psz;
493
  return rc;
494
}
495
 
496
 
497
// Give indication of bytes available to be read (but don't read them)
498
bool CeCosSocket::Peek (unsigned int &nAvail)
499
{
500
  char buf[8192];
501
  int n=::recv(m_nSock, buf, sizeof buf, MSG_PEEK);
502
  nAvail=0;
503
  bool rc=false;
504
  switch(n) {
505
  case -1:
506
    SaveError();
507
    if(WOULDBLOCK==SocketError()){
508
      rc=true; // nAvail stays==0
509
    } else {
510
      ERROR(_T("Peek: err=%d %s\n"),SocketError(),(LPCTSTR)SocketErrString());
511
    }
512
    break;
513
  case 0:
514
    m_nErr=ERR_READ_AFTER_CLOSE;
515
    break;
516
  default:
517
    rc=true;
518
    nAvail=n;
519
  }
520
  return rc;
521
}
522
 
523
// Connect tcp/ip port and serial port together.
524
// Traffic is passed through pFunc, passed parameter pParam.
525
// The pFunc function:
526
//    may reallocate pBuf (using malloc/realloc etc...)
527
//    must leave pBuf allocated on exit
528
//    should not close either serial or socket
529
//    should leave writing to its caller
530
//    should return false if it wishes to terminate the connection (after caller has written output)
531
bool CeCosSocket::ConnectSocketToSerial (CeCosSocket &socket,CeCosSerial &serial,FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,bool *pbStop/*=0*/)
532
{
533
  serial.ClearError();
534
  enum {BUFSIZE=8192};
535
  void *pBuf=malloc(BUFSIZE);
536
  TRACE(_T("ConnectSocketToSerial: connected\n"));
537
  bool rc=true;
538
  try {
539
  /*
540
  { //hack
541
  unsigned int nWritten;//hack
542
  serial.Write(_T("+"),1,nWritten);//hack
543
  }//hack
544
    */
545
    while(rc && (0==pbStop || !(*pbStop))){
546
      unsigned int nRead=0;
547
      switch(SSRead (serial,socket,pBuf,BUFSIZE,nRead,pbStop)){
548
      case SS_SERIAL_READ:
549
        VTRACE(_T("Serial:%d\n"),nRead);
550
        if(pSerialToSocketFilterFunc){
551
          rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,socket,pSerialParam);
552
        }
553
        if(nRead && !socket.send(pBuf,nRead)){
554
          TRACE(_T("Failed to write to socket\n"));
555
          rc=false;
556
        }
557
        break;
558
      case SS_SOCKET_READ:
559
        unsigned int nWritten;
560
        VTRACE(_T("Socket:%d\n"),nRead);
561
        if(pSocketToSerialFilterFunc){
562
          rc=pSocketToSerialFilterFunc(pBuf,nRead,serial,socket,pSocketParam);
563
        }
564
        {
565
          LPTSTR c=(LPTSTR )pBuf;
566
          int nToWrite=nRead;
567
          while(nToWrite>0){
568
            if(!serial.Write(pBuf,nRead,nWritten)){
569
              TRACE(_T("Failed to write to serial\n"));
570
              rc=false;
571
              break;
572
            }
573
            nToWrite-=nWritten;
574
            c+=nWritten;
575
          }
576
        }
577
        break;
578
      // Error conditions:
579
      case SS_SERIAL_ERROR:
580
        TRACE(_T("SSRead serial error - %s\n"),(LPCTSTR)serial.ErrString());
581
        rc=false;
582
        break;
583
      case SS_SOCKET_ERROR:
584
        TRACE(_T("SSRead socket error - %s\n"),(LPCTSTR)socket.SocketErrString());
585
        rc=false;
586
        break;
587
      case SS_STOPPED:
588
        TRACE(_T("SSRead stopped\n"));
589
        rc=false;
590
        break;
591
      }
592
    }
593
  }
594
  catch (...){
595
    ERROR(_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 CeCosSocket::ConnectSocketToSocket (CeCosSocket &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 CeCosSocket::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
    CeCosSerial 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
      CeCosSocket 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 CeCosSocket::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 CeCosSocket::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 CeCosSocket::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 CeCosSocket::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 CeCosSocket::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
String CeCosSocket::SocketErrString() {
744
  return SocketErrString(m_nErr);
745
}
746
 
747
 
748
bool CeCosSocket::SameHost(LPCTSTR host1, LPCTSTR host2)
749
{
750
  return 0==_tcscmp(host1,host2) || (GetHostByName(host1)==GetHostByName(host2));
751
}
752
 
753
bool CeCosSocket::Init()
754
{
755
#ifdef _WIN32
756
  WSADATA wsaData;
757
  WORD wVersionRequested = MAKEWORD( 2, 0 );
758
  WSAStartup( wVersionRequested, &wsaData );
759
#endif
760
  return true;
761
}
762
 
763
void CeCosSocket::Term()
764
{
765
#ifdef _WIN32
766
  WSACleanup();
767
#endif
768
}
769
 
770
LPCTSTR CeCosSocket::MyHostName()
771
{
772
  static String str;
773
  if(str.empty()){
774
    char szMyname[256];
775
    if(0==gethostname(szMyname,sizeof szMyname)){
776
      str=String::CStrToUnicodeStr(szMyname);
777
    }
778
  }
779
  return str;
780
}
781
 
782
LPCTSTR CeCosSocket::MySimpleHostName()
783
{
784
  static String str;
785
  if(str.empty()){
786
    str=MyHostName();
787
    // Remove all after a '.'
788
    LPCTSTR c=_tcschr(str,_TCHAR('.'));
789
    if(c){
790
      str.resize(c-(LPCTSTR)str);
791
    }
792
  }
793
  return str;
794
}
795
 
796
const String CeCosSocket::GetHostByName(LPCTSTR pszHost)
797
{
798
  typedef std::map<String,String> MapStringToString;
799
  static MapStringToString hostmap;
800
  MapStringToString::iterator it=hostmap.find(pszHost);
801
  if(hostmap.end()==it){
802
    char *h=0; // avoid erroneous gcc warning message
803
    h=String(pszHost).GetCString();
804
    char ip[16];
805
    struct hostent* host_dat;
806
    if (0!=(host_dat=::gethostbyname(h))){
807
      char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] )  );
808
      if(c){
809
        strcpy(ip,c);
810
        hostmap[pszHost]=String::CStrToUnicodeStr(ip);
811
      }
812
    }
813
    delete [] h;
814
    return String::CStrToUnicodeStr(ip);
815
  } else {
816
    return it->second;
817
  }
818
}

powered by: WebSVN 2.1.0

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