PPTConnection.cc

Go to the documentation of this file.
00001 // PPTConnection.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 <poll.h>
00034 #include <errno.h>
00035 #include <iostream>
00036 
00037 using std::cout ;
00038 using std::flush ;
00039 
00040 #include "PPTConnection.h"
00041 #include "PPTProtocol.h"
00042 #include "Socket.h"
00043 #include "PPTException.h"
00044 #include "PPTMarkFinder.h"
00045 
00046 void
00047 PPTConnection::send( const string &buffer )
00048 {
00049     if( buffer != "" )
00050     {
00051         writeBuffer( buffer ) ;
00052     }
00053     writeBuffer( PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION ) ;
00054 }
00055 
00056 void
00057 PPTConnection::sendExit()
00058 {
00059     writeBuffer( PPTProtocol::PPT_EXIT_NOW ) ;
00060 }
00061 
00062 void
00063 PPTConnection::writeBuffer( const string &buffer )
00064 {
00065     _mySock->send( buffer, 0, buffer.length() ) ;
00066 }
00067     
00068 /* OLD RECEIVE
00069 bool
00070 PPTConnection::receive( ostream *strm )
00071 {
00072     bool isDone = false ;
00073     ostream *use_strm = _out ;
00074     if( strm )
00075         use_strm = strm ;
00076 
00077     int termlen = PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION.length() ;
00078     int exitlen = PPTProtocol::PPT_EXIT_NOW.length() ;
00079     int start = termlen ;
00080     bool done = false ;
00081     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+termlen+1] ;
00082     while( done == false )
00083     {
00084         int bytesRead = readBuffer( inBuff+termlen ) ;
00085         if( bytesRead != 0 )
00086         {
00087             if( !strncmp( inBuff+start, PPTProtocol::PPT_EXIT_NOW.c_str(), exitlen ) )
00088             {
00089                 done = true ;
00090                 isDone = true ;
00091             }
00092             else
00093             {
00094                 int charsInBuff = bytesRead + ( termlen - start ) ;
00095                 int writeBytes = charsInBuff - termlen ;
00096                 if( charsInBuff >= termlen )
00097                 {
00098                     if( !strncmp( inBuff+bytesRead, PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION.c_str(), termlen ) )
00099                     {
00100                         done = true ;
00101                     }
00102 
00103                     for( int j = 0; j < writeBytes; j++ )
00104                     {
00105                         if( use_strm )
00106                         {
00107                             (*use_strm) << inBuff[start+j] ;
00108                         }
00109                     }
00110 
00111                     if( !done )
00112                     {
00113                         memcpy( inBuff, inBuff + bytesRead, termlen ) ;
00114                         start = 0 ;
00115                     }
00116                 }
00117                 else
00118                 {
00119                     int newstart = termlen - charsInBuff ;
00120                     memcpy( inBuff + newstart, inBuff + start, charsInBuff ) ;
00121                     start = newstart ;
00122                 }
00123             }
00124         }
00125         else
00126         {
00127             done = true ;
00128         }
00129     }
00130     delete [] inBuff ;
00131     return isDone ;
00132 }
00133 */
00134 
00135 bool
00136 PPTConnection::receive( ostream *strm )
00137 {
00138     bool isDone = false ;
00139     ostream *use_strm = _out ;
00140     if( strm )
00141         use_strm = strm ;
00142 
00143     int bytesRead, markBufBytes, i ;
00144 
00145     int termlen = PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION.length() ;
00146     int exitlen = PPTProtocol::PPT_EXIT_NOW.length() ;
00147 
00148     PPTMarkFinder mf( (unsigned char *)PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION.c_str(),
00149                       termlen ) ;
00150     unsigned char markBuffer[termlen] ;
00151     markBufBytes = 0 ; // zero byte count in the mark buffer
00152 
00153     char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+termlen+1] ;
00154     bool done = false;
00155     while( !done )
00156     {
00157         bytesRead = readBuffer( inBuff ) ;
00158         if( bytesRead != 0 )
00159         {
00160             // did we find an exit string?
00161             if( !strncmp( inBuff, PPTProtocol::PPT_EXIT_NOW.c_str(), exitlen ) )
00162             {
00163                 done = true ;
00164                 isDone = true ;
00165             }
00166             else
00167             {
00168                 // look at what we got to find the exit or the term string
00169                 for( i = 0; i < bytesRead && !done; i++ )
00170                 {
00171                     // check for the mark. If we've found the entire marker
00172                     // then markCheck returns true. If we haven't yet found
00173                     // the entire mark but have found part of it then
00174                     // markCheck will return false and the markIndex will be
00175                     // greater than 0. If the check failed because the
00176                     // character checked is not part of the marker then the
00177                     // markIndex is set to 0 and false is returned.
00178                     done = mf.markCheck( inBuff[i] ) ;
00179                     if( !done )
00180                     {
00181                         // didn't find the mark yet, check if we've found
00182                         // part of it
00183                         if( mf.getMarkIndex() > 0 )
00184                         {
00185                             // we found part of it, so cache what we found
00186                             // in markBuffer
00187                             markBuffer[markBufBytes++] = inBuff[i] ;
00188                         }
00189                         else
00190                         {
00191                             // we are here because inBuff[i] does not match
00192                             // the current position in the marker.
00193 
00194                             // if we found part of the mark (there's some
00195                             // characters in markBuffer meaning markBufBytes
00196                             // is greater than 0) then we need to send the
00197                             // first character in the markBuffer and begiin
00198                             // checking the rest of the characters in the
00199                             // markBuffer against the markFinder. inBuff[i]
00200                             // could still be part of the marker, so don't
00201                             // send it to the stream just yet. The case here
00202                             // is that the inBuff contains PPPT instead of
00203                             // PPT as the beginning of the marker. PP is in
00204                             // the markBuffer and we've just checked the
00205                             // third 'P', which returns false and markIndex
00206                             // is set to 0. So, send the first 'P' in
00207                             // markBuffer, shift the remaining characters
00208                             // and check them against the markFinder.
00209                             if( markBufBytes > 0 )
00210                             {
00211                                 // let's put inBuf[i] in the markBuffer so
00212                                 // that we don't have to worry about it
00213                                 // anymore
00214                                 markBuffer[markBufBytes++] = inBuff[i] ;
00215 
00216                                 bool isdone = false ;
00217                                 while( !isdone )
00218                                 {
00219                                     // always throw the first character iin
00220                                     // markBuffer to the stream
00221                                     (*use_strm) << markBuffer[0] ;
00222 
00223                                     // shift the rest of the characters in
00224                                     // markBuffer to the left one
00225                                     for( int j = 1; j < markBufBytes; j++ )
00226                                     {
00227                                         markBuffer[j-1] = markBuffer[j] ;
00228                                     }
00229 
00230                                     // we've sent the first character to the
00231                                     // stream, so reduce the number in
00232                                     // markBuffer
00233                                     markBufBytes-- ;
00234 
00235                                     // start checking the rest of the
00236                                     // characters in markBuffer
00237                                     bool partof = true ;
00238                                     for( int j = 0; j < markBufBytes && partof; j++ )
00239                                     {
00240                                         // don't need to look at the result
00241                                         // of markCheck because we already
00242                                         // know that we have not
00243                                         // found the complete marker, we're
00244                                         // just dealing with potentially
00245                                         // part of the marker
00246                                         mf.markCheck( markBuffer[j] ) ;
00247                                         if( mf.getMarkIndex() == 0 )
00248                                         {
00249                                             // if the markIndex is 0 then
00250                                             // the character we just checked
00251                                             // is not part of the marker, so
00252                                             // repeat this process starting
00253                                             // at for( !isdone )
00254                                             partof = false ;
00255                                         }
00256                                     }
00257 
00258                                     if( partof == true )
00259                                     {
00260                                         // if we've made it this far then
00261                                         // what's in the markBuffer is part
00262                                         // of the marker, so move on to the
00263                                         // next character in inBuff
00264                                         isdone = true ;
00265                                     }
00266                                 }
00267                             }
00268                             else
00269                             {
00270                                 // There's nothing in the markBuffer so just
00271                                 // send inBuff on to the stream
00272                                 (*use_strm) << inBuff[i] ;
00273                             }
00274                         }
00275                     }
00276                 }
00277             }
00278         }
00279         else
00280         {
00281             done = true;
00282         }
00283     }
00284     delete [] inBuff ;
00285     return isDone ;
00286 }
00287 
00288 int
00289 PPTConnection::readBuffer( char *inBuff )
00290 {
00291     return _mySock->receive( inBuff, PPT_PROTOCOL_BUFFER_SIZE ) ;
00292 }
00293 
00294 int
00295 PPTConnection::readBufferNonBlocking( char *inBuff )
00296 {
00297     struct pollfd p ;
00298     p.fd = getSocket()->getSocketDescriptor();
00299     p.events = POLLIN ;
00300     struct pollfd arr[1] ;
00301     arr[0] = p ;
00302 
00303     // Lets loop _timeout times with a delay block on poll of 1000 milliseconds
00304     // and see if there is any data.
00305     for( int j = 0; j < _timeout; j++ )
00306     {
00307         if( poll( arr, 1, 1000 ) < 0 )
00308         {
00309             string error( "poll error" ) ;
00310             const char* error_info = strerror( errno ) ;
00311             if( error_info )
00312                 error += " " + (string)error_info ;
00313             throw PPTException( error ) ;
00314         }
00315         else
00316         {
00317             if (arr[0].revents==POLLIN)
00318             {
00319                 return readBuffer( inBuff ) ;
00320             }
00321             else
00322             {
00323                 cout << " " << j << flush ;
00324             }
00325         }
00326     }
00327     cout << endl ;
00328     return -1 ;
00329 }
00330 
00337 void
00338 PPTConnection::dump( ostream &strm ) const
00339 {
00340     strm << BESIndent::LMarg << "PPTConnection::dump - ("
00341                              << (void *)this << ")" << endl ;
00342     BESIndent::Indent() ;
00343     Connection::dump( strm ) ;
00344     BESIndent::UnIndent() ;
00345 }
00346 

Generated on Wed Aug 29 02:59:01 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2