PPTClient.cc

Go to the documentation of this file.
00001 // PPTClient.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <string>
00034 #include <iostream>
00035 #include <sstream>
00036 
00037 using std::string ;
00038 using std::cerr ;
00039 using std::cout ;
00040 using std::endl ;
00041 using std::ostringstream ;
00042 
00043 #include "PPTClient.h"
00044 #include "TcpSocket.h"
00045 #include "UnixSocket.h"
00046 #include "PPTProtocol.h"
00047 #include "BESInternalError.h"
00048 #include "TheBESKeys.h"
00049 
00050 #include "config.h"
00051 #ifdef HAVE_OPENSSL
00052 #include "SSLClient.h"
00053 #endif
00054 
00055 PPTClient::PPTClient( const string &hostStr, int portVal, int timeout )
00056     : PPTConnection( timeout ),
00057       _connected( false ),
00058       _host( hostStr )
00059 {
00060     // connect to the specified host at the specified socket to handle the
00061     // secure connection
00062     _mySock = new TcpSocket( hostStr, portVal ) ;
00063     _mySock->connect() ;
00064     _connected = _mySock->isConnected();
00065 }
00066     
00067 PPTClient::PPTClient( const string &unix_socket, int timeout )
00068     : PPTConnection( timeout ),
00069       _connected( false )
00070 {
00071     // connect to the specified unix socket to handle the secure connection
00072     _mySock = new UnixSocket( unix_socket ) ;
00073     _mySock->connect() ;
00074     _connected = true ;
00075 }
00076 
00077 void
00078 PPTClient::get_secure_files()
00079 {
00080     bool found = false ;
00081     _cfile = TheBESKeys::TheKeys()->get_key( "BES.ClientCertFile", found ) ;
00082     if( !found || _cfile.empty() )
00083     {
00084         string err = "Unable to determine client certificate file." ;
00085         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00086     }
00087 
00088     _kfile = TheBESKeys::TheKeys()->get_key( "BES.ClientKeyFile", found ) ;
00089     if( !found || _kfile.empty() )
00090     {
00091         string err = "Unable to determine client key file." ;
00092         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00093     }
00094 }
00095 
00096 PPTClient::~PPTClient()
00097 {
00098     if( _mySock )
00099     {
00100         if( _connected )
00101         {
00102             closeConnection() ;
00103         }
00104         delete _mySock ;
00105         _mySock = 0 ;
00106     }
00107 }
00108 
00109 void
00110 PPTClient::initConnection()
00111 {
00112     try
00113     {
00114         send( PPTProtocol::PPTCLIENT_TESTING_CONNECTION ) ;
00115     }
00116     catch( BESInternalError &e )
00117     {
00118         string msg = "Failed to initialize connection to server\n" ;
00119         msg += e.get_message() ;
00120         throw BESInternalError( msg, __FILE__, __LINE__ ) ;
00121     }
00122 
00123     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00124     int bytesRead = readBufferNonBlocking( inBuff ) ;
00125     if( bytesRead < 1 )
00126     {
00127         delete [] inBuff ;
00128         string err = "Could not connect to server, server may be down or busy" ;
00129         throw BESInternalError( err, __FILE__, __LINE__) ;
00130     }
00131 
00132     if( bytesRead > PPT_PROTOCOL_BUFFER_SIZE )
00133         bytesRead = PPT_PROTOCOL_BUFFER_SIZE ;
00134     inBuff[bytesRead] = '\0' ;
00135     string status( inBuff, 0, bytesRead ) ;
00136     delete [] inBuff ;
00137 
00138     if( status == PPTProtocol::PPT_PROTOCOL_UNDEFINED )
00139     {
00140         string err = "Could not connect to server, server may be down or busy" ;
00141         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00142     }
00143 
00144     if( status == PPTProtocol::PPTSERVER_AUTHENTICATE )
00145     {
00146         authenticateWithServer() ;
00147     }
00148     else if( status != PPTProtocol::PPTSERVER_CONNECTION_OK )
00149     {
00150         string err = "Server reported an invalid connection, \""
00151                      + status + "\"" ;
00152         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00153     }
00154 }
00155 
00156 void
00157 PPTClient::authenticateWithServer()
00158 {
00159 #ifdef HAVE_OPENSSL
00160     // get the certificate and key file information
00161     get_secure_files() ;
00162 
00163     // send request for the authentication port
00164     send( PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT ) ;
00165 
00166     // receive response with port, terminated with TERMINATE token
00167     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00168     int bytesRead = readBufferNonBlocking( inBuff ) ;
00169     if( bytesRead < 1 )
00170     {
00171         delete [] inBuff ;
00172         string err = "Expecting secure port number response" ;
00173         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00174     }
00175 
00176     if( bytesRead > PPT_PROTOCOL_BUFFER_SIZE )
00177     {
00178         bytesRead = PPT_PROTOCOL_BUFFER_SIZE ;
00179     }
00180     inBuff[bytesRead] = '\0' ;
00181     ostringstream portResponse( inBuff ) ;
00182     delete [] inBuff ;
00183 
00184     int portVal = atoi( portResponse.str().c_str() ) ;
00185     if( portVal == 0 )
00186     {
00187         string err = "Expecting valid secure port number response" ;
00188         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00189     }
00190 
00191     // authenticate using SSLClient
00192     SSLClient client( _host, portVal, _cfile, _kfile ) ;
00193     client.initConnection() ;
00194     client.closeConnection() ;
00195 
00196     // If it authenticates, good, if not then an exception is thrown. We
00197     // don't need to do anything else here.
00198 #else
00199     string err = "Server has requested authentication "
00200                  + "but OpenSSL is not built into this client" ;
00201     throw BESInternalError( err, __FILE__, __LINE__ ) ;
00202 #endif
00203 }
00204 
00205 void
00206 PPTClient::closeConnection()
00207 {
00208     if( _connected )
00209     {
00210         if( !_brokenPipe )
00211         {
00212             try
00213             {
00214                 sendExit() ;
00215             }
00216             catch( BESInternalError e )
00217             {
00218                 cerr << "Failed to inform server that the client is exiting, "
00219                      << "continuing" << endl ;
00220                 cerr << e.get_message() << endl ;
00221             }
00222         }
00223 
00224         _mySock->close() ;
00225 
00226         _connected = false ;
00227         _brokenPipe = false ;
00228     }
00229 }
00230 
00237 void
00238 PPTClient::dump( ostream &strm ) const
00239 {
00240     strm << BESIndent::LMarg << "PPTClient::dump - ("
00241                              << (void *)this << ")" << endl ;
00242     BESIndent::Indent() ;
00243     strm << BESIndent::LMarg << "connected? " << _connected << endl ;
00244     strm << BESIndent::LMarg << "host: " << _host << endl ;
00245     PPTConnection::dump( strm ) ;
00246     BESIndent::UnIndent() ;
00247 }
00248 

Generated on Tue Mar 4 23:13:37 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.1