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 "SocketException.h"
00048 #include "PPTException.h"
00049 #include "TheBESKeys.h"
00050 
00051 #include "config.h"
00052 #ifdef HAVE_OPENSSL
00053 #include "SSLClient.h"
00054 #endif
00055 
00056 PPTClient::PPTClient( const string &hostStr, int portVal, int timeout )
00057     : PPTConnection( timeout ),
00058       _connected( false ),
00059       _host( hostStr )
00060 {
00061     // connect to the specified host at the specified socket to handle the
00062     // secure connection
00063     _mySock = new TcpSocket( hostStr, portVal ) ;
00064     _mySock->connect() ;
00065     _connected = _mySock->isConnected();
00066 }
00067     
00068 PPTClient::PPTClient( const string &unix_socket, int timeout )
00069     : PPTConnection( timeout ),
00070       _connected( false )
00071 {
00072     // connect to the specified unix socket to handle the secure connection
00073     _mySock = new UnixSocket( unix_socket ) ;
00074     _mySock->connect() ;
00075     _connected = true ;
00076 }
00077 
00078 void
00079 PPTClient::get_secure_files()
00080 {
00081     bool found = false ;
00082     _cfile = TheBESKeys::TheKeys()->get_key( "BES.ClientCertFile", found ) ;
00083     if( !found || _cfile.empty() )
00084     {
00085         throw PPTException( "Unable to determine client certificate file.",
00086                             __FILE__, __LINE__ ) ;
00087     }
00088 
00089     _kfile = TheBESKeys::TheKeys()->get_key( "BES.ClientKeyFile", found ) ;
00090     if( !found || _kfile.empty() )
00091     {
00092         throw PPTException( "Unable to determine client key file.",
00093                             __FILE__, __LINE__ ) ;
00094     }
00095 }
00096 
00097 PPTClient::~PPTClient()
00098 {
00099     if( _mySock )
00100     {
00101         if( _connected )
00102         {
00103             closeConnection() ;
00104         }
00105         delete _mySock ;
00106         _mySock = 0 ;
00107     }
00108 }
00109 
00110 void
00111 PPTClient::initConnection()
00112 {
00113     try
00114     {
00115         writeBuffer( PPTProtocol::PPTCLIENT_TESTING_CONNECTION ) ;
00116     }
00117     catch( SocketException &e )
00118     {
00119         string msg = "Failed to initialize connection to server\n" ;
00120         msg += e.getMessage() ;
00121         throw PPTException( msg, __FILE__, __LINE__ ) ;
00122     }
00123 
00124     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00125     int bytesRead = readBufferNonBlocking( inBuff ) ;
00126     if( bytesRead < 1 )
00127     {
00128         delete [] inBuff ;
00129         throw PPTException( "Could not connect to server, server may be down or busy" , __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         throw PPTException( "Could not connect to server, server may be down or busy", __FILE__, __LINE__ ) ;
00141     }
00142 
00143     if( status == PPTProtocol::PPTSERVER_AUTHENTICATE )
00144     {
00145         authenticateWithServer() ;
00146     }
00147     else if( status != PPTProtocol::PPTSERVER_CONNECTION_OK )
00148     {
00149         throw PPTException( "Server reported an invalid connection, \"" + status + "\"", __FILE__, __LINE__ ) ;
00150     }
00151 }
00152 
00153 void
00154 PPTClient::authenticateWithServer()
00155 {
00156 #ifdef HAVE_OPENSSL
00157     // get the certificate and key file information
00158     get_secure_files() ;
00159 
00160     // send request for the authentication port
00161     writeBuffer( PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT ) ;
00162 
00163     // receive response with port, terminated with TERMINATE token
00164     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00165     int bytesRead = readBufferNonBlocking( inBuff ) ;
00166     if( bytesRead < 1 )
00167     {
00168         throw PPTException( "Expecting secure port number response", __FILE__, __LINE__ ) ;
00169     }
00170 
00171     if( bytesRead > PPT_PROTOCOL_BUFFER_SIZE )
00172         bytesRead = PPT_PROTOCOL_BUFFER_SIZE ;
00173     inBuff[bytesRead] = '\0' ;
00174     ostringstream portResponse( inBuff ) ;
00175     delete [] inBuff ;
00176 
00177     int portVal = atoi( portResponse.str().c_str() ) ;
00178     if( portVal == 0 )
00179     {
00180         throw PPTException( "Expecting valid secure port number response", __FILE__, __LINE__ ) ;
00181     }
00182 
00183     // authenticate using SSLClient
00184     SSLClient client( _host, portVal, _cfile, _kfile ) ;
00185     client.initConnection() ;
00186     client.closeConnection() ;
00187 
00188     // If it authenticates, good, if not then an exception is thrown. We
00189     // don't need to do anything else here.
00190 #else
00191     throw PPTException( "Server has requested authentication but OpenSSL is not built into this client", __FILE__, __LINE__ ) ;
00192 #endif
00193 }
00194 
00195 void
00196 PPTClient::closeConnection()
00197 {
00198     if( _connected )
00199     {
00200         if( !_brokenPipe )
00201         {
00202             try
00203             {
00204                 sendExit() ;
00205             }
00206             catch( SocketException e )
00207             {
00208                 cerr << "Failed to inform server that the client is exiting, "
00209                      << "continuing" << endl ;
00210                 cerr << e.getMessage() << endl ;
00211             }
00212         }
00213 
00214         _mySock->close() ;
00215 
00216         _connected = false ;
00217         _brokenPipe = false ;
00218     }
00219 }
00220 
00227 void
00228 PPTClient::dump( ostream &strm ) const
00229 {
00230     strm << BESIndent::LMarg << "PPTClient::dump - ("
00231                              << (void *)this << ")" << endl ;
00232     BESIndent::Indent() ;
00233     strm << BESIndent::LMarg << "connected? " << _connected << endl ;
00234     strm << BESIndent::LMarg << "host: " << _host << endl ;
00235     PPTConnection::dump( strm ) ;
00236     BESIndent::UnIndent() ;
00237 }
00238 

Generated on Wed Jan 2 06:01:19 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.4