Files correlati : Ricompilazione Demo : [ ] Commento :correzioni dovute al passaggio al nuovo compilatore git-svn-id: svn://10.65.10.50/trunk@14698 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			982 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			982 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #define XVT_INCL_NATIVE
 | ||
| #include <xvt.h>
 | ||
| #include <progind.h>
 | ||
| #include <config.h>
 | ||
| #include <agasys.h>
 | ||
| #include <utility.h>
 | ||
| 
 | ||
| // skstream.h
 | ||
| // Copyright (C) 1995, 1996 by John C. Wang. All Rights Reserved.
 | ||
| //
 | ||
| // You may distribute this file with your product in either of two ways:
 | ||
| // IN SOURCE CODE FORM: You must include this file in its entirety.
 | ||
| // IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
 | ||
| //   of this program. This may take the form of credits on the start-up screen.
 | ||
| //
 | ||
| // IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
 | ||
| // IMPLICIT WARRANTIES AND THE AUTHORS ARE NOT RESPONSIBLE FOR ANY EVENTS THAT
 | ||
| // OCCURS AS A RESULT OF USING THIS SOFTWARE.
 | ||
| //
 | ||
| // History:
 | ||
| // [JCW 95-Dec-04] created
 | ||
| // [JCW 95-Dec-20] comments added for distribution 95a
 | ||
| // [JCW 96-Jan-01] removed UDP capabilities from skstream
 | ||
| 
 | ||
| #ifdef INCSTR_H
 | ||
| #include <incstr.h>
 | ||
| #endif
 | ||
| 
 | ||
| #ifdef WIN32
 | ||
| #include "winsock.h"
 | ||
| #else
 | ||
| #include <sys/types.h>
 | ||
| #include <sys/socket.h>
 | ||
| #include <netinet/in.h>
 | ||
| #include <arpa/inet.h>
 | ||
| #include <netdb.h>
 | ||
| #include <unistd.h>
 | ||
| #define SOCKET int
 | ||
| #define INVALID_SOCKET -1
 | ||
| #define SOCKET_ERROR -1
 | ||
| #define SOCKADDR_IN sockaddr_in
 | ||
| #define closesocket close
 | ||
| #define BYTE byte
 | ||
| #endif
 | ||
| 
 | ||
| //
 | ||
| // sockbuf
 | ||
| //
 | ||
| class sockbuf : public streambuf
 | ||
| {
 | ||
| public:
 | ||
|   sockbuf( SOCKET & );
 | ||
|   sockbuf( SOCKET &, char *, int );
 | ||
| 
 | ||
|   virtual ~sockbuf();
 | ||
| 
 | ||
|   virtual int overflow(int =EOF) ;
 | ||
|   virtual int underflow() ;
 | ||
| 
 | ||
|     virtual int sync();
 | ||
| 
 | ||
| protected:
 | ||
|   char *_buffer ;
 | ||
| 
 | ||
|   // sockbuf specific
 | ||
|   SOCKET &_socket ;
 | ||
| } ;
 | ||
| 
 | ||
| 
 | ||
| //
 | ||
| // skstream
 | ||
| //
 | ||
| class skstream : public iostream {
 | ||
| public:
 | ||
|   // constants
 | ||
|   enum service
 | ||
|   {
 | ||
|     ftp         =      21, //tcp
 | ||
|     telnet      =      23, //tcp
 | ||
|     smtp        =      25, //tcp       mail
 | ||
|     time        =      37, //tcp       timserver
 | ||
|     name        =      42, //tcp       nameserver
 | ||
|     nameserver  =      53, //tcp       domain        # name-domain server
 | ||
|     finger      =      79, //tcp
 | ||
|     http        =      80, //tcp
 | ||
|     pop         =     109, //tcp       postoffice
 | ||
|     pop2        =     109, //tcp                     # Post Office
 | ||
|     pop3        =     110, //tcp       postoffice
 | ||
|     nntp        =     119  //tcp       usenet        # Network News Transfer
 | ||
|   } ;
 | ||
| 
 | ||
|   enum role
 | ||
|   {
 | ||
|     server ,
 | ||
|     client
 | ||
|   } ;
 | ||
| 
 | ||
|   // methods
 | ||
|   skstream( void );
 | ||
|   skstream( const char *addr, const service, const role = client ) ;
 | ||
|   skstream( SOCKET );
 | ||
|   ~skstream( void );
 | ||
| 
 | ||
|   void open( const char *addr, const service, const role = client ) ;
 | ||
|   void close( void ) ;
 | ||
|   int is_open( void ) const ;
 | ||
|   void attach( SOCKET = NULL );
 | ||
|   SOCKET getsocket() const ;
 | ||
| 
 | ||
|   char *getpeername( char *, int ) const ;
 | ||
|   unsigned short getport( void ) const ;
 | ||
| protected:
 | ||
|   SOCKET _socket ;
 | ||
|   sockbuf _sockbuf ;
 | ||
| 
 | ||
|   // platform dependent library housekeeping
 | ||
|   int init( void ) ;
 | ||
|   int shutdown( void ) ;
 | ||
| };
 | ||
| 
 | ||
| // skstream.cpp
 | ||
| // Copyright (C) 1996, 1995 by John C. Wang <jcwang@csie.ntu.edu.tw>
 | ||
| // All Rights Reserved.
 | ||
| //
 | ||
| // You may distribute this file with your product in either of two ways:
 | ||
| // IN SOURCE CODE FORM: You must include this file in its entirety.
 | ||
| // IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
 | ||
| //   of this program. This may take the form of credits on the start-up screen.
 | ||
| //
 | ||
| // IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
 | ||
| // IMPLICIT WARRANTY AND THE AUTHOR(S) ARE NOT RESPONSIBLE FOR ANY EVENT THAT
 | ||
| // OCCURS DUE TO THE USE OR MISUSE OF THIS SOFTWARE.
 | ||
| //
 | ||
| // History:
 | ||
| // [JCW 95-Dec-04] created.
 | ||
| // [JCW 95-Dec-20] comments added for distribution 95a.
 | ||
| // [JCW 96-Jan-01] removed UDP capabilities from skstream.
 | ||
| // [JCW 96-Mar-14] exceptions made optional.
 | ||
| // [JCW 96-Oct-20] protected skstream::init and ::shutdown changed.
 | ||
| //                 char( 255 ) == EOF bug fixed.
 | ||
| 
 | ||
| #ifdef _UNIX
 | ||
| #define INVALID_SOCKET -1
 | ||
| // Add definitions here
 | ||
| #endif
 | ||
| 
 | ||
| // Machine independent macros
 | ||
| #ifdef DBG
 | ||
|   #define dassert(x) assert(x)
 | ||
|   #define debug(x) x
 | ||
| #else
 | ||
|   #define dassert(x)
 | ||
|   #define debug(x)
 | ||
| #endif //def _DEBUG
 | ||
| 
 | ||
| //
 | ||
| // skstream
 | ||
| //
 | ||
| 
 | ||
| int skstream::init( void )
 | ||
| {
 | ||
|   // platform dependent initialization
 | ||
| #ifdef WIN32
 | ||
|   const WORD wMinVer = 0x0101;  // request WinSock v1.1 (at least)
 | ||
|   WSADATA wsaData;
 | ||
|   if( 0 == WSAStartup( wMinVer, &wsaData ) )
 | ||
|     return TRUE ;
 | ||
|   return FALSE ;
 | ||
| #else
 | ||
| 	return TRUE;
 | ||
| #endif
 | ||
| }
 | ||
| 
 | ||
| int skstream::shutdown( void )
 | ||
| {
 | ||
|   // platform dependent shutdown
 | ||
| #ifdef WIN32
 | ||
|   if( 0 == WSACleanup() )
 | ||
|     return TRUE ;
 | ||
|   return FALSE ;
 | ||
| #else
 | ||
| 	return TRUE;
 | ||
| #endif
 | ||
| }
 | ||
| 
 | ||
| skstream::skstream( void ) : iostream( &_sockbuf ), _sockbuf( _socket )
 | ||
| {
 | ||
|   if( init() )
 | ||
|     attach( INVALID_SOCKET ) ;
 | ||
| }
 | ||
| 
 | ||
| skstream::skstream( const char *addr, const service port, const role side )
 | ||
|  : iostream( &_sockbuf ), _sockbuf( _socket )
 | ||
| {
 | ||
|   if( init() )
 | ||
|   {
 | ||
|     attach( INVALID_SOCKET ) ;
 | ||
|     open( addr, port, side ) ;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| skstream::skstream( SOCKET sock ) : iostream( &_sockbuf ), _sockbuf( _socket )
 | ||
| {
 | ||
|   if( init() )
 | ||
|     attach( sock ) ;
 | ||
| }
 | ||
| 
 | ||
| skstream::~skstream( void )
 | ||
| {
 | ||
|   close() ;
 | ||
|   shutdown() ;
 | ||
| }
 | ||
| 
 | ||
| int skstream::is_open( void ) const
 | ||
| {
 | ||
|   return ( INVALID_SOCKET != getsocket() ) ;
 | ||
| }
 | ||
| 
 | ||
| void skstream::open( const char *addr, const service port, const role side )
 | ||
| {
 | ||
|   // in case of error condition, user finds out by testing is_open()
 | ||
| 
 | ||
|   if( is_open() )
 | ||
|     close() ;
 | ||
|   
 | ||
|   // 1. Create socket
 | ||
|   if( INVALID_SOCKET == ( _socket = ::socket( PF_INET, SOCK_STREAM, 0 ) ) )
 | ||
|     // Cannot create socket
 | ||
|     return ;
 | ||
| 
 | ||
|   // 2. Bind
 | ||
|   SOCKADDR_IN sa ;
 | ||
|   sa.sin_family = AF_INET ;
 | ||
| #ifdef WIN32
 | ||
|   sa.sin_addr.S_un.S_addr = INADDR_ANY ;
 | ||
| #else  
 | ||
|   sa.sin_addr.s_addr = INADDR_ANY ;
 | ||
| #endif  
 | ||
|   sa.sin_port = side == client ? 0 : htons( (unsigned short)port ) ;
 | ||
|     // rationale: no client requires fixed port number, so let system assign
 | ||
|   if( SOCKET_ERROR == ::bind( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
 | ||
|   {
 | ||
|     // Cannot bind to the chosen port
 | ||
|     close() ;
 | ||
|     return ;
 | ||
|   }
 | ||
| 
 | ||
|   // From now on the two sides are very much different
 | ||
|   if( side == skstream::client )
 | ||
|   {
 | ||
|     // 3(cli). Connect
 | ||
|     SOCKADDR_IN sa ; memset(&sa,0,sizeof(sa));
 | ||
|     sa.sin_family = AF_INET ;
 | ||
|                                
 | ||
|     unsigned long indirizzo = 0xFFFFFFFF;
 | ||
|     
 | ||
|     int ip[4];
 | ||
| //e' un indirizzo numerico?
 | ||
| //si...    
 | ||
|     if (sscanf( addr, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4)
 | ||
|     {
 | ||
|       indirizzo = ::inet_addr(addr);
 | ||
|     }
 | ||
| //no...
 | ||
|     else
 | ||
|     { 
 | ||
|       hostent* he = ::gethostbyname( addr );    
 | ||
|       if( NULL != he )
 | ||
|         indirizzo = *(unsigned long *)( he->h_addr_list[ 0 ] );
 | ||
|     }
 | ||
|     
 | ||
|     if (indirizzo == 0 || indirizzo == 0xFFFFFFFF)
 | ||
|     {
 | ||
|       close();
 | ||
|       return;
 | ||
|     }
 | ||
|     
 | ||
| #ifdef WIN32
 | ||
|     sa.sin_addr.S_un.S_addr = indirizzo;
 | ||
|     sa.sin_port = ::htons( port ) ;
 | ||
| #else
 | ||
|     sa.sin_addr.s_addr = indirizzo;
 | ||
|     sa.sin_port = htons( port ) ;
 | ||
| #endif
 | ||
| 
 | ||
|     if( SOCKET_ERROR == ::connect( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
 | ||
|     {
 | ||
|       // Connection error
 | ||
|       close() ;
 | ||
|       return ;
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     // 3(svr). Listen
 | ||
|     if( SOCKET_ERROR == ::listen( _socket, 5 ) )  // max backlog
 | ||
|     {
 | ||
|       // Error listening
 | ||
|       close() ;
 | ||
|       return ;
 | ||
|     }
 | ||
| 
 | ||
|     // 4. Accept
 | ||
|     SOCKET commsock ;
 | ||
|     if( INVALID_SOCKET == ( commsock = ::accept( _socket, NULL, NULL ) ) )
 | ||
|     {
 | ||
|       // Accepting error
 | ||
|       close() ;
 | ||
|       return ;
 | ||
|     }
 | ||
| 
 | ||
|     // rationale: after we accept a connection, close the server port
 | ||
|     //   so another process may become a server
 | ||
|     if( SOCKET_ERROR == ::closesocket( _socket ) )
 | ||
|     {
 | ||
|       // Cannot close service port, resource may be occupied
 | ||
|       close() ;
 | ||
|       return ;
 | ||
|     }
 | ||
|     _socket = commsock ;
 | ||
|   }
 | ||
|   // success!
 | ||
| }
 | ||
| 
 | ||
| void skstream::close( void )
 | ||
| {
 | ||
|   if( is_open() )
 | ||
|   {
 | ||
|     _sockbuf.sync() ;
 | ||
|     if( SOCKET_ERROR == ::closesocket( _socket ) )
 | ||
|       // Cannot close. Leave _socket as it was
 | ||
|       return ;
 | ||
|   }
 | ||
| 
 | ||
|   _socket = INVALID_SOCKET ;
 | ||
| }
 | ||
| 
 | ||
| void skstream::attach( SOCKET sock )
 | ||
| {
 | ||
|   _socket = sock ;
 | ||
| }
 | ||
| 
 | ||
| SOCKET skstream::getsocket() const
 | ||
| {
 | ||
|   return _socket ;
 | ||
| }
 | ||
| 
 | ||
| char *skstream::getpeername( char *buf, int size ) const
 | ||
| {
 | ||
|   SOCKADDR_IN sa ;
 | ||
|   int sasize = sizeof( sa ) ;
 | ||
| #ifdef WIN32
 | ||
|   if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
 | ||
| #else
 | ||
|   if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, (socklen_t *) &sasize ) )
 | ||
| #endif
 | ||
|     // Cannot get peer name
 | ||
|     return NULL ;
 | ||
|   strncpy( buf, ::inet_ntoa( sa.sin_addr ), size - 1 ) ;
 | ||
|   return buf ;
 | ||
| }
 | ||
| 
 | ||
| unsigned short skstream::getport( void ) const
 | ||
| {
 | ||
|   SOCKADDR_IN sa ;
 | ||
|   int sasize = sizeof( sa ) ;
 | ||
| #ifdef WIN32
 | ||
|   if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
 | ||
|     // Cannot get peer port
 | ||
|     return ::ntohs( IPPORT_RESERVED ); 
 | ||
|   return ::ntohs( sa.sin_port ) ;
 | ||
| #else
 | ||
|   if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, (socklen_t *) &sasize ) )
 | ||
|     // Cannot get peer port
 | ||
|     return ntohs( IPPORT_RESERVED ); 
 | ||
|   return ntohs( sa.sin_port ) ;
 | ||
| #endif
 | ||
| }
 | ||
| 
 | ||
| //
 | ||
| //  sockbuf
 | ||
| //
 | ||
| sockbuf::sockbuf( SOCKET &sock ) : _socket( sock ) 
 | ||
| {
 | ||
|   const int insize = 0x2000 ;   // allocate 16k buffer each for input and output
 | ||
|   const int outsize = 0x2000 ;
 | ||
|   const int bufsize = insize + outsize ;
 | ||
| 
 | ||
|   _buffer = new char [ bufsize ] ;
 | ||
| 
 | ||
|   if( this != setbuf( _buffer, bufsize ) )
 | ||
|     _buffer = NULL ;
 | ||
|   else
 | ||
|   {
 | ||
|     setp( _buffer, _buffer + insize ) ;
 | ||
|     setg( _buffer + insize, _buffer + bufsize, _buffer + bufsize ) ;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| sockbuf::sockbuf( SOCKET &sock, char *buf, int length ) : _socket( sock )
 | ||
| {
 | ||
|   _buffer = NULL ;
 | ||
| 
 | ||
|   if( this == setbuf( buf, length ) )
 | ||
| 	{
 | ||
|   	setp( buf, buf + length / 2 ) ;
 | ||
|   	setg( buf + length / 2, buf + length, buf + length ) ;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| sockbuf::~sockbuf()
 | ||
| {
 | ||
|   delete[] _buffer ;
 | ||
|   _buffer = NULL ;
 | ||
| }
 | ||
| 
 | ||
| int sockbuf::overflow( int nCh )
 | ||
| {
 | ||
|   // in case of error, user finds out by testing fail()
 | ||
|   if( _socket == INVALID_SOCKET )
 | ||
|     // Invalid socket
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   if( pptr() - pbase() <= 0 )
 | ||
|     // nothing to send
 | ||
|     return 0 ;
 | ||
| 
 | ||
|   int size ;
 | ||
|   if( SOCKET_ERROR == ( size = ::send( _socket, pbase(), pptr() - pbase(), 0 ) ) )
 | ||
|     // (TCP) Cannot send
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   if( size == 0 )
 | ||
|     // remote site has closed this connection
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   if( nCh != EOF )  // size >= 1 at this point
 | ||
|   {
 | ||
|     size-- ;
 | ||
|     *( pbase() + size ) = nCh ;
 | ||
|   }
 | ||
| 
 | ||
|   // move remaining pbase() + size .. pptr() - 1 => pbase() .. pptr() - size - 1
 | ||
|   for( char *p = pbase() + size; p < pptr(); p++ )
 | ||
|     *( p - size ) = *p ;
 | ||
|   const int newlen = ( pptr() - pbase() ) - size ;
 | ||
| 
 | ||
|   setp( pbase(), epptr() ) ;
 | ||
|   pbump( newlen ) ;
 | ||
| 
 | ||
|   return 0 ;
 | ||
| }
 | ||
| 
 | ||
| int sockbuf::underflow()
 | ||
| {
 | ||
|   // if get area not empty, return first character
 | ||
|   // else fill up get area and return 1st character
 | ||
| 
 | ||
|   // in case of error, user finds out by testing eof()
 | ||
| 
 | ||
|   if( _socket == INVALID_SOCKET )
 | ||
|     // Invalid socket!
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   if( egptr() - gptr() > 0 )
 | ||
|     return (int)(unsigned char)(*gptr()) ;
 | ||
| 
 | ||
|   // fill up from eback to egptr
 | ||
|   int size ;
 | ||
|   if( SOCKET_ERROR == ( size = ::recv( _socket, eback(), egptr() - eback(), 0 ) ) )
 | ||
|     // (TCP) Receive error
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   if( size == 0 )
 | ||
|     // remote site has closed this connection
 | ||
|     return EOF ;
 | ||
| 
 | ||
|   // move rcvd data from eback() .. eback() + size to egptr() - size .. egptr()
 | ||
|   const int delta = egptr() - ( eback() + size ) ;
 | ||
|   for( char *p = eback() + size - 1; p >= eback(); p-- )
 | ||
|   {
 | ||
|     CHECK( p + delta >= eback(), "Socket underflow" ) ;
 | ||
|     CHECK( p + delta < egptr(), "Socket underflow" ) ;
 | ||
|     *( p + delta ) = *p ;
 | ||
|   }
 | ||
| 
 | ||
|   setg( eback(), egptr() - size, egptr() ) ;
 | ||
| 
 | ||
|   return (int)(unsigned char)(*gptr()) ;
 | ||
| }
 | ||
| 
 | ||
| int sockbuf::sync()
 | ||
| {
 | ||
|   if( EOF == overflow() )
 | ||
|     return EOF ;  // ios will set the fail bit
 | ||
|   else
 | ||
|   {
 | ||
|     // empty put and get areas
 | ||
|     setp( pbase(), epptr() ) ;
 | ||
|     setg( eback(), egptr(), egptr() ) ;
 | ||
|     
 | ||
|     return 0 ;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // end of skstreams
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| #include "netsock.h"
 | ||
| 
 | ||
| class TSocket_connection : public TConnection
 | ||
| {
 | ||
| 	TString _server;
 | ||
|   skstream::service _service;
 | ||
| 
 | ||
|   skstream* _socket;
 | ||
| 
 | ||
| protected:
 | ||
|   bool connect();
 | ||
|  
 | ||
| public:
 | ||
| 	const TString & Server() const { return _server; }
 | ||
|   virtual bool Execute(const char* cmd);
 | ||
| 
 | ||
|   bool WriteLine(const char* cmd);
 | ||
|   bool ReadLine(TString& str);
 | ||
|   bool Read(byte* buf, size_t size);
 | ||
| 
 | ||
|   skstream* GetSocket();
 | ||
| 
 | ||
| 	TSocket_connection(TLanManager* lm, const char* service, const char* server);
 | ||
| 	~TSocket_connection();
 | ||
| };
 | ||
| 
 | ||
| bool TSocket_connection::Execute(const char* cmd)
 | ||
| {
 | ||
| 	skstream* calza = GetSocket();
 | ||
| 	bool ok = calza != NULL;
 | ||
|   if (ok)
 | ||
| 	{
 | ||
|     const size_t buflen = strlen(cmd)+1;
 | ||
|     calza->sync();
 | ||
|     calza->write(cmd, buflen);
 | ||
|     calza->flush();
 | ||
|     ok = calza->good() != 0;
 | ||
| 	}
 | ||
| 	return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TSocket_connection::WriteLine(const char* cmd)
 | ||
| {
 | ||
| 	skstream* calza = GetSocket();
 | ||
| 	bool ok = calza != NULL;
 | ||
|   if (ok)
 | ||
| 	{
 | ||
|     const size_t buflen = strlen(cmd); // Unica differenza da Execute
 | ||
|     calza->sync();
 | ||
|     calza->write(cmd, buflen);
 | ||
|     calza->flush();
 | ||
|     ok = calza->good() != 0;
 | ||
| 	}
 | ||
| 	return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TSocket_connection::ReadLine(TString& str)
 | ||
| {
 | ||
| 	skstream* calza = GetSocket();
 | ||
| 	bool ok = calza != NULL;
 | ||
| 	if (ok)
 | ||
| 	{
 | ||
|     char *buf = str.get_buffer(4096);
 | ||
|     calza->getline(buf, str.size(), '\n');
 | ||
| 	}
 | ||
| 	return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TSocket_connection::Read(byte* buf, size_t size)
 | ||
| {
 | ||
| 	skstream* calza = GetSocket();
 | ||
| 	bool ok = calza != NULL;
 | ||
| 	if (ok)
 | ||
| 	{
 | ||
|     calza->read((char *)buf, size);
 | ||
| 		ok = calza->good() != 0;
 | ||
| 	}
 | ||
| 	return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TSocket_connection::connect()
 | ||
| { 
 | ||
| 	if (_socket != NULL)
 | ||
| 		delete _socket;
 | ||
|   _socket = new skstream(_server, _service);
 | ||
| 	if (_socket->is_open())
 | ||
| 	  SetId((CONNID)_socket);
 | ||
|   else
 | ||
|   {
 | ||
|     delete _socket;
 | ||
|     _socket = NULL;
 | ||
| 	  SetId(0);
 | ||
|   }  
 | ||
| 
 | ||
| 	return _socket != NULL;
 | ||
| }
 | ||
| 
 | ||
| skstream* TSocket_connection::GetSocket()
 | ||
| {
 | ||
| 	if (_socket == NULL || !_socket->is_open())
 | ||
| 		connect();
 | ||
| 	return _socket;
 | ||
| }
 | ||
| 
 | ||
| TSocket_connection::TSocket_connection(TLanManager* lm, 
 | ||
| 																			 const char* service, const char* server) 
 | ||
|                   : TConnection(lm, 0), _socket(NULL)
 | ||
| {
 | ||
|   _service = (skstream::service)((service && *service) ? atoi(service) : 0);
 | ||
| 
 | ||
|   _server = server;
 | ||
|   int pos = _server.find("://");
 | ||
|   if (pos > 0)
 | ||
|     _server.ltrim(pos+3);
 | ||
| 
 | ||
|   pos = _server.rfind(':');
 | ||
|   if (pos >= 0)
 | ||
|   {
 | ||
|     _service = (skstream::service)atoi(_server.mid(pos+1));
 | ||
|     _server.cut(pos);
 | ||
|   }
 | ||
| 
 | ||
|   if (_server.blank() || xvt_str_compare_ignoring_case(_server, "localhost") == 0)
 | ||
|     _server = "127.0.0.1";           
 | ||
| 
 | ||
| 	connect();
 | ||
| }
 | ||
| 
 | ||
| TSocket_connection::~TSocket_connection()
 | ||
| {
 | ||
| 	if (_socket)
 | ||
| 		delete _socket;
 | ||
| }
 | ||
| 
 | ||
| TSocketClient::TSocketClient() 
 | ||
|       : m_pData(NULL), m_dwSize(0)
 | ||
| { }
 | ||
| 
 | ||
| TSocketClient::~TSocketClient()
 | ||
| { 
 | ||
|   ReleaseBuffer();
 | ||
|   RemoveAllConnections();
 | ||
| }
 | ||
| 
 | ||
| TConnection* TSocketClient::OnQueryConnection(const char* service, const char* server)
 | ||
| {
 | ||
|   TSocket_connection* pConnection = new TSocket_connection(this, service, server);
 | ||
| 	if (pConnection->Id() == 0)
 | ||
| 	{
 | ||
| 		delete pConnection;
 | ||
| 		pConnection = NULL;
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
|   return pConnection;
 | ||
| }
 | ||
| 
 | ||
| bool TSocketClient::Request(CONNID id, const char* cmd)
 | ||
| {   
 | ||
|   static bool semaphore = FALSE;
 | ||
|   bool ok = FALSE;
 | ||
| 
 | ||
|   if (!semaphore)
 | ||
|   {
 | ||
|     semaphore = TRUE;
 | ||
|     
 | ||
|     ReleaseBuffer();
 | ||
|     ok = Execute(id, cmd);
 | ||
|     if (ok)
 | ||
|     {                                  
 | ||
| 			TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
|       m_dwSize = 0;
 | ||
|       conn->Read((byte*)&m_dwSize, sizeof(m_dwSize));
 | ||
|       ok = m_dwSize > 0;
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         m_pData = new byte[m_dwSize];
 | ||
|         ok = conn->Read(m_pData, m_dwSize);
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     semaphore = FALSE;
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| byte* TSocketClient::GetBuffer(size_t& dwSize)
 | ||
| {
 | ||
|   dwSize = m_dwSize;
 | ||
|   return m_pData;
 | ||
| }
 | ||
| 
 | ||
| bool TSocketClient::WriteLine(CONNID id, const char* str)
 | ||
| {
 | ||
| 	TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
| 	if (conn)
 | ||
|     return conn->WriteLine(str);
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TSocketClient::ReadLine(CONNID id, TString& str)
 | ||
| {
 | ||
| 	TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
| 	if (conn)
 | ||
|     return conn->ReadLine(str);
 | ||
| 	return FALSE;
 | ||
| }
 | ||
| 
 | ||
| void TSocketClient::ReleaseBuffer()
 | ||
| {
 | ||
|   if (m_pData)
 | ||
|   {
 | ||
|     delete m_pData;
 | ||
|     m_pData = NULL;
 | ||
|     m_dwSize = 0;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TSocketClient::HttpGetFile(CONNID id, const char* remote, const char* local, const char* authorization)
 | ||
| 
 | ||
| {
 | ||
|   bool ok = FALSE;
 | ||
| 	TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
|    
 | ||
|   TString buf(8*1024);
 | ||
|   buf << "GET " << remote << " HTTP/1.1\r\n"
 | ||
|       << "User-Agent: Campo\r\n"
 | ||
|       << "Host: " << conn->Server()	<< "\r\n";
 | ||
|   if (authorization && *authorization)
 | ||
|     buf << "Authorization: " << authorization << "\r\n";
 | ||
|   buf << "\r\n";
 | ||
| 
 | ||
|   if (WriteLine(id, buf))
 | ||
|   {
 | ||
|     long size = 0;
 | ||
|     for (int r = 0; ; r++)
 | ||
|     {
 | ||
| 			ReadLine(id, buf);
 | ||
|       if (buf.blank())
 | ||
|         break;
 | ||
|       if (r == 0 && buf.find("200 OK") < 0)
 | ||
|         return FALSE;    // File not found
 | ||
|       if (buf.compare("Content-length:", 15, TRUE) == 0)
 | ||
|       {
 | ||
|         const int colon = buf.find(':');
 | ||
|         size = atol(buf.mid(colon+1));
 | ||
|       }
 | ||
|     }
 | ||
|     ofstream outfile(local, ios::out | ios::binary);
 | ||
|     if (outfile.good())
 | ||
|     {    
 | ||
|       buf.cut(0) << remote << " - " << (size / 1024 + 1) << " KBytes"; 
 | ||
|       TProgind pi(size, buf, TRUE, TRUE);
 | ||
|       long total = 0;
 | ||
|       skstream* cur_socket = conn->GetSocket();
 | ||
| 
 | ||
|       while (!cur_socket->eof())
 | ||
|       {
 | ||
| 				int nchars = buf.size();
 | ||
| 
 | ||
| 				if (size >0 && nchars > size - total)
 | ||
| 					nchars = size - total;
 | ||
|         cur_socket->read(buf.get_buffer(), nchars);
 | ||
|         const int count = cur_socket->gcount();
 | ||
|         if (count > 0)
 | ||
|         {
 | ||
|           outfile.write(buf, count);  
 | ||
|           total += count;
 | ||
| 					pi.setstatus(total);
 | ||
| 		      if (pi.iscancelled())
 | ||
| 						break;
 | ||
| 					if (size > 0 && total >= size)
 | ||
| 						break;
 | ||
|         }
 | ||
|       }
 | ||
| 			ok  = size = 0 ? cur_socket->eof() != 0 : total >= size;
 | ||
|     } 
 | ||
|     else 
 | ||
|       error_box("Impossibile scrivere il file %s", local);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN int find_href(const TString& riga)
 | ||
| {
 | ||
|   int href = -1;
 | ||
|   int img = riga.find("<img");
 | ||
|   if (img >= 0)
 | ||
|     href = riga.find("href=", img+4);
 | ||
|   else
 | ||
|   {
 | ||
|     img = riga.find("<IMG");
 | ||
|     if (img >= 0)
 | ||
|       href = riga.find("HREF=", img+4);
 | ||
|   }
 | ||
|   return href;
 | ||
| }
 | ||
|  
 | ||
| bool TSocketClient::HttpGetDir(CONNID id, const char* remote, TString_array& list)
 | ||
| {
 | ||
|   TFilename local; local.temp();
 | ||
|   const bool ok = HttpGetFile(id, remote, local);
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     ifstream s(local);
 | ||
|     TString riga(256);
 | ||
|     while (!s.eof())
 | ||
|     {
 | ||
|       s.getline(riga.get_buffer(), riga.size());
 | ||
|       const int href = find_href(riga);
 | ||
|       if (href > 0)
 | ||
|       {
 | ||
|         const int start = riga.find('"', href) + 1;
 | ||
|         if (start > href && isalnum(riga[start + 1]))
 | ||
|         {
 | ||
|           const int stop  = riga.find('"', start);
 | ||
|           if (stop > start)
 | ||
|           {
 | ||
|             const TString& name = riga.sub(start, stop);
 | ||
|             list.add(name);
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     s.close();
 | ||
|     ::remove(local);
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TSocketClient::HttpSoap(CONNID id, const char* cmd)
 | ||
| {
 | ||
|   bool ok = false;
 | ||
| 
 | ||
| 	TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
|   if (conn == NULL)
 | ||
|     return ok;
 | ||
|   
 | ||
|   if (cmd == NULL || *cmd == '\0')
 | ||
|     return ok;
 | ||
| 
 | ||
| 	char hostname[256];
 | ||
|   xvt_sys_get_host_name(hostname, sizeof(hostname));
 | ||
| 
 | ||
| 	TString content(256);
 | ||
| 	content = cmd;
 | ||
| 	if (content.find("<SOAP-ENV") < 0)  // Controllo se c'<27> tutto
 | ||
| 	{
 | ||
| 	  content.insert("<SOAP-ENV:Envelope>\n<SOAP-ENV:Body>\n");
 | ||
| 		content << "</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\r\n";
 | ||
| 	}
 | ||
| 
 | ||
|   TString buf(4096);
 | ||
| 	buf << "POST / HTTP/1.1\n"
 | ||
| 		  << "User-Agent: Campo\n"
 | ||
| 	    << "Host: " << hostname << "\n"
 | ||
| 		  << "Content-Type: text/xml; charset=utf-8\n"
 | ||
| 		  << "Content-length: " << content.len() << "\n"
 | ||
| 	    << "SOAPAction: \"/\"\r\n\r\n"
 | ||
| 			<< content;
 | ||
| 
 | ||
|   if (conn->WriteLine(buf))
 | ||
|   {
 | ||
| 		skstream* cur_socket = conn->GetSocket();
 | ||
| 
 | ||
|     unsigned long size = 0;
 | ||
|     for (int r = 0; !cur_socket->eof(); r++)
 | ||
|     {
 | ||
| 			conn->ReadLine(buf);
 | ||
|       if (buf.blank())
 | ||
|         break;
 | ||
|       if (buf.compare("Content-length:", 15, TRUE) == 0)
 | ||
|       {
 | ||
|         const int colon = buf.find(':');
 | ||
|         size = atol(buf.mid(colon+1));
 | ||
|       }
 | ||
|     }
 | ||
|     if (size > 0)
 | ||
| 		{
 | ||
| 			if (size >= m_dwSize)
 | ||
| 			{
 | ||
| 			  ReleaseBuffer();
 | ||
| 			  m_dwSize = size+1;
 | ||
|         m_pData = new BYTE[m_dwSize];
 | ||
| 			}
 | ||
| 			memset(m_pData, 0, m_dwSize);
 | ||
| 			cur_socket->read((char *) m_pData, size);
 | ||
| 			ok = true;
 | ||
| 		}
 | ||
| 	}
 | ||
|   return ok;
 | ||
| } 
 | ||
| 
 | ||
| bool TSocketClient::HttpPostFile(CONNID id, const char* remote, const char* local, const char* authorization)
 | ||
| {
 | ||
|   bool ok = false;
 | ||
| 
 | ||
| 	TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
 | ||
|   if (conn == NULL)
 | ||
|     return ok;
 | ||
|   const char* const eol = "\r\n";
 | ||
| 
 | ||
|   TString buf(4096);
 | ||
|   buf << "POST " << remote << " HTTP/1.0" << eol
 | ||
|       << "User-Agent: Campo" << eol
 | ||
|       << "Content-Type: text/plain" << eol
 | ||
|       << "Content-Length: " << fsize(local) << eol;
 | ||
|   if (authorization && *authorization)
 | ||
|     buf << "Authorization: " << authorization << eol;
 | ||
|   buf << eol;
 | ||
|   
 | ||
|   ok = conn->WriteLine(buf); 
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     ifstream input(local, ios::binary);
 | ||
| 
 | ||
|     while (!input.eof())
 | ||
|     {
 | ||
|       input.read(buf.get_buffer(), buf.size());
 | ||
|       const size_t count = input.gcount();
 | ||
|       if (count > 0)
 | ||
|       {
 | ||
| 				skstream* cur_socket = conn->GetSocket();
 | ||
| 
 | ||
|         cur_socket->sync();
 | ||
|         cur_socket->write(buf, count);
 | ||
|         cur_socket->flush();
 | ||
|       }
 | ||
|       else
 | ||
|         break;
 | ||
|     }
 | ||
|     conn->ReadLine(buf);
 | ||
|     ok = buf.find("200 OK") >= 0;
 | ||
|                     
 | ||
|     if (ok)                
 | ||
|     {
 | ||
| 			skstream* cur_socket = conn->GetSocket();
 | ||
|       unsigned long size = 0;
 | ||
|       for (int r = 0; !cur_socket->eof(); r++)
 | ||
|       {
 | ||
|         cur_socket->getline(buf.get_buffer(), buf.size(), '\n');
 | ||
|         if (buf.blank())
 | ||
|           break;
 | ||
|         if (buf.starts_with("Content-length:", true) == 0)
 | ||
|         {
 | ||
|           const int colon = buf.find(':');
 | ||
|           size = atol(buf.mid(colon+1));
 | ||
|         }
 | ||
|       }
 | ||
|       ReleaseBuffer();
 | ||
|       ok = size > 0;
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         m_dwSize = size;
 | ||
|         m_pData = new BYTE[m_dwSize+1];
 | ||
|         memset(m_pData, 0, size_t(m_dwSize+1));
 | ||
|         cur_socket->read((char *) m_pData, (size_t)m_dwSize);
 | ||
|       }
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       ReleaseBuffer();
 | ||
|       m_dwSize = buf.len()+1;
 | ||
|       m_pData = new BYTE[m_dwSize];
 | ||
|       memcpy(m_pData, buf, (size_t)m_dwSize);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 |