Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/downloader/bioStreamBuf.cxx

Go to the documentation of this file.
00001 // Filename: bioStreamBuf.cxx
00002 // Created by:  drose (25Sep02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "bioStreamBuf.h"
00020 #include "config_downloader.h"
00021 
00022 #ifdef HAVE_SSL
00023 
00024 #ifdef REPORT_OPENSSL_ERRORS
00025 #include <openssl/err.h>
00026 #endif
00027 
00028 #ifndef HAVE_STREAMSIZE
00029 // Some compilers (notably SGI) don't define this for us
00030 typedef int streamsize;
00031 #endif /* HAVE_STREAMSIZE */
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: BioStreamBuf::Constructor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 BioStreamBuf::
00039 BioStreamBuf() {
00040   _is_closed = false;
00041 
00042 #ifdef HAVE_IOSTREAM
00043   char *buf = new char[8192];
00044   char *ebuf = buf + 8192;
00045   char *mbuf = buf + 4096;
00046   setg(buf, mbuf, mbuf);
00047   setp(mbuf, ebuf);
00048 
00049 #else
00050   allocate();
00051   // Chop the buffer in half.  The bottom half goes to the get buffer;
00052   // the top half goes to the put buffer.
00053   char *b = base();
00054   char *t = ebuf();
00055   char *m = b + (t - b) / 2;
00056   setg(b, m, m);
00057   setp(b, m);
00058 #endif
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: BioStreamBuf::Destructor
00063 //       Access: Public, Virtual
00064 //  Description:
00065 ////////////////////////////////////////////////////////////////////
00066 BioStreamBuf::
00067 ~BioStreamBuf() {
00068   close();
00069 }
00070 
00071 ////////////////////////////////////////////////////////////////////
00072 //     Function: BioStreamBuf::open
00073 //       Access: Public
00074 //  Description:
00075 ////////////////////////////////////////////////////////////////////
00076 void BioStreamBuf::
00077 open(BioPtr *source) {
00078   _source = source;
00079 }
00080 
00081 ////////////////////////////////////////////////////////////////////
00082 //     Function: BioStreamBuf::close
00083 //       Access: Public
00084 //  Description:
00085 ////////////////////////////////////////////////////////////////////
00086 void BioStreamBuf::
00087 close() {
00088   sync();
00089   _source.clear();
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: BioStreamBuf::overflow
00094 //       Access: Protected, Virtual
00095 //  Description: Called by the system ostream implementation when its
00096 //               internal buffer is filled, plus one character.
00097 ////////////////////////////////////////////////////////////////////
00098 int BioStreamBuf::
00099 overflow(int ch) {
00100   size_t n = pptr() - pbase();
00101   if (n != 0) {
00102     size_t num_wrote = write_chars(pbase(), n);
00103     pbump(-(int)n);
00104     if (num_wrote != n) {
00105       return EOF;
00106     }
00107   }
00108 
00109   if (ch != EOF) {
00110     // Store the next character back in the buffer.
00111     *pptr() = ch;
00112     pbump(1);
00113   }
00114 
00115   return 0;
00116 }
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: BioStreamBuf::sync
00120 //       Access: Protected, Virtual
00121 //  Description: Called by the system iostream implementation to
00122 //               implement a flush operation.
00123 ////////////////////////////////////////////////////////////////////
00124 int BioStreamBuf::
00125 sync() {
00126   /*
00127   size_t n = egptr() - gptr();
00128   gbump(n);
00129   */
00130 
00131   size_t n = pptr() - pbase();
00132   size_t num_wrote = write_chars(pbase(), n);
00133   pbump(-(int)n);
00134   if (num_wrote != n) {
00135     return EOF;
00136   }
00137 
00138   return 0;
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: BioStreamBuf::underflow
00143 //       Access: Protected, Virtual
00144 //  Description: Called by the system istream implementation when its
00145 //               internal buffer needs more characters.
00146 ////////////////////////////////////////////////////////////////////
00147 int BioStreamBuf::
00148 underflow() {
00149   // Sometimes underflow() is called even if the buffer is not empty.
00150   if (gptr() >= egptr()) {
00151     size_t buffer_size = egptr() - eback();
00152     gbump(-(int)buffer_size);
00153 
00154     size_t num_bytes = buffer_size;
00155 
00156     // BIO_read might return -1 or -2 on eof or error, so we have to
00157     // allow for negative numbers.
00158     int read_count = BIO_read(*_source, gptr(), buffer_size);
00159 
00160     if (read_count != (int)num_bytes) {
00161       // Oops, we didn't read what we thought we would.
00162       if (read_count <= 0) {
00163         _is_closed = !BIO_should_retry(*_source);
00164         if (_is_closed) {
00165           downloader_cat.info()
00166             << "Lost connection to "
00167             << _source->get_server_name() << ":" 
00168             << _source->get_port() << " (" << read_count << ").\n";
00169 #ifdef REPORT_OPENSSL_ERRORS
00170           ERR_print_errors_fp(stderr);
00171 #endif
00172         }
00173         gbump(num_bytes);
00174         return EOF;
00175       }
00176 
00177       // Slide what we did read to the top of the buffer.
00178       nassertr(read_count < (int)num_bytes, EOF);
00179       size_t delta = (int)num_bytes - read_count;
00180       memmove(gptr() + delta, gptr(), read_count);
00181       gbump(delta);
00182     }
00183   }
00184 
00185   return (unsigned char)*gptr();
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: BioStreamBuf::write_chars
00190 //       Access: Private
00191 //  Description: Sends some characters to the dest stream.  Does not
00192 //               return until all characters are sent or the socket is
00193 //               closed, even if the underlying BIO is non-blocking.
00194 ////////////////////////////////////////////////////////////////////
00195 size_t BioStreamBuf::
00196 write_chars(const char *start, size_t length) {
00197   size_t wrote_so_far = 0;
00198 
00199   int write_count = BIO_write(*_source, start, length);
00200   while (write_count != (int)(length - wrote_so_far)) {
00201     if (write_count <= 0) {
00202       _is_closed = !BIO_should_retry(*_source);
00203       if (_is_closed) {
00204         return wrote_so_far;
00205       }
00206 
00207       // Block on the underlying socket before we try to write some
00208       // more.
00209       int fd = -1;
00210       BIO_get_fd(*_source, &fd);
00211       if (fd < 0) {
00212         downloader_cat.warning()
00213           << "socket BIO has no file descriptor.\n";
00214       } else {
00215         downloader_cat.spam()
00216           << "waiting to write to BIO.\n";
00217         fd_set wset;
00218         FD_ZERO(&wset);
00219         FD_SET(fd, &wset);
00220         select(fd + 1, NULL, &wset, NULL, NULL);
00221       }        
00222 
00223     } else {
00224       // wrote some characters.
00225       wrote_so_far += write_count;
00226     }
00227 
00228     // Try to write some more.
00229     write_count = BIO_write(*_source, start + wrote_so_far, length - wrote_so_far);
00230   }
00231 
00232   return length;
00233 }
00234 
00235 #endif  // HAVE_SSL

Generated on Fri May 2 00:36:43 2003 for Panda by doxygen1.3