mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
add do_connect()
This commit is contained in:
parent
191cd9ff38
commit
3ad212f066
@ -41,6 +41,7 @@
|
|||||||
httpChannel.cxx \
|
httpChannel.cxx \
|
||||||
identityStream.cxx identityStreamBuf.cxx \
|
identityStream.cxx identityStreamBuf.cxx \
|
||||||
multiplexStream.cxx multiplexStreamBuf.cxx \
|
multiplexStream.cxx multiplexStreamBuf.cxx \
|
||||||
|
socketStream.cxx \
|
||||||
urlSpec.cxx \
|
urlSpec.cxx \
|
||||||
$[if $[HAVE_NET], downloadDb.cxx downloader.cxx] \
|
$[if $[HAVE_NET], downloadDb.cxx downloader.cxx] \
|
||||||
$[if $[HAVE_ZLIB], decompressor.cxx download_utils.cxx]
|
$[if $[HAVE_ZLIB], decompressor.cxx download_utils.cxx]
|
||||||
|
@ -54,31 +54,4 @@ BioPtr::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: BioPtr::connect
|
|
||||||
// Access: Public
|
|
||||||
// Description: Calls BIO_do_connect() to establish a connection on
|
|
||||||
// the previously-named server and port. Returns true
|
|
||||||
// if successful, false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool BioPtr::
|
|
||||||
connect() const {
|
|
||||||
nassertr(_bio != (BIO *)NULL && !_server_name.empty(), false);
|
|
||||||
if (downloader_cat.is_debug()) {
|
|
||||||
downloader_cat.debug()
|
|
||||||
<< "Connecting to " << _server_name << ":" << _port << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BIO_do_connect(_bio) <= 0) {
|
|
||||||
downloader_cat.info()
|
|
||||||
<< "Could not connect to " << _server_name << ":" << _port << "\n";
|
|
||||||
#ifdef REPORT_SSL_ERRORS
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
|
@ -51,7 +51,6 @@ public:
|
|||||||
INLINE void set_bio(BIO *bio);
|
INLINE void set_bio(BIO *bio);
|
||||||
INLINE BIO *get_bio() const;
|
INLINE BIO *get_bio() const;
|
||||||
|
|
||||||
bool connect() const;
|
|
||||||
INLINE const string &get_server_name() const;
|
INLINE const string &get_server_name() const;
|
||||||
INLINE int get_port() const;
|
INLINE int get_port() const;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ IBioStream(BioPtr *source) : ISocketStream(&_buf) {
|
|||||||
INLINE IBioStream &IBioStream::
|
INLINE IBioStream &IBioStream::
|
||||||
open(BioPtr *source) {
|
open(BioPtr *source) {
|
||||||
clear(0);
|
clear(0);
|
||||||
_buf.open_read(source);
|
_buf.open(source);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +56,92 @@ open(BioPtr *source) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE IBioStream &IBioStream::
|
INLINE IBioStream &IBioStream::
|
||||||
close() {
|
close() {
|
||||||
_buf.close_read();
|
_buf.close();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OBioStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE OBioStream::
|
||||||
|
OBioStream() : OSocketStream(&_buf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OBioStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE OBioStream::
|
||||||
|
OBioStream(BioPtr *source) : OSocketStream(&_buf) {
|
||||||
|
open(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OBioStream::open
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE OBioStream &OBioStream::
|
||||||
|
open(BioPtr *source) {
|
||||||
|
clear(0);
|
||||||
|
_buf.open(source);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OBioStream::close
|
||||||
|
// Access: Public
|
||||||
|
// Description: Resets the BioStream to empty, but does not actually
|
||||||
|
// close the source BIO unless owns_source was true.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE OBioStream &OBioStream::
|
||||||
|
close() {
|
||||||
|
_buf.close();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE BioStream::
|
||||||
|
BioStream() : SocketStream(&_buf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE BioStream::
|
||||||
|
BioStream(BioPtr *source) : SocketStream(&_buf) {
|
||||||
|
open(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStream::open
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE BioStream &BioStream::
|
||||||
|
open(BioPtr *source) {
|
||||||
|
clear(0);
|
||||||
|
_buf.open(source);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStream::close
|
||||||
|
// Access: Public
|
||||||
|
// Description: Resets the BioStream to empty, but does not actually
|
||||||
|
// close the source BIO unless owns_source was true.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE BioStream &BioStream::
|
||||||
|
close() {
|
||||||
|
_buf.close();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -33,3 +33,37 @@ is_closed() {
|
|||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OBioStream::is_closed
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns true if the last write fail condition was
|
||||||
|
// triggered because the socket has genuinely closed, or
|
||||||
|
// false if we can expect to send more data along
|
||||||
|
// shortly.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool OBioStream::
|
||||||
|
is_closed() {
|
||||||
|
if (_buf._is_closed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStream::is_closed
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns true if the last eof or failure condition was
|
||||||
|
// triggered because the socket has genuinely closed, or
|
||||||
|
// false if we can expect to read or send more data
|
||||||
|
// shortly.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool BioStream::
|
||||||
|
is_closed() {
|
||||||
|
if (_buf._is_closed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -50,6 +50,48 @@ private:
|
|||||||
BioStreamBuf _buf;
|
BioStreamBuf _buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : OBioStream
|
||||||
|
// Description : An output stream object that writes data to an
|
||||||
|
// OpenSSL BIO object. This is used by the HTTPClient
|
||||||
|
// and HTTPChannel classes to provide a C++ interface
|
||||||
|
// to OpenSSL.
|
||||||
|
//
|
||||||
|
// Seeking is not supported.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDAEXPRESS OBioStream : public OSocketStream {
|
||||||
|
public:
|
||||||
|
INLINE OBioStream();
|
||||||
|
INLINE OBioStream(BioPtr *source);
|
||||||
|
|
||||||
|
INLINE OBioStream &open(BioPtr *source);
|
||||||
|
INLINE OBioStream &close();
|
||||||
|
|
||||||
|
virtual bool is_closed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BioStreamBuf _buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : BioStream
|
||||||
|
// Description : A bi-directional stream object that reads and writes
|
||||||
|
// data to an OpenSSL BIO object.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDAEXPRESS BioStream : public SocketStream {
|
||||||
|
public:
|
||||||
|
INLINE BioStream();
|
||||||
|
INLINE BioStream(BioPtr *source);
|
||||||
|
|
||||||
|
INLINE BioStream &open(BioPtr *source);
|
||||||
|
INLINE BioStream &close();
|
||||||
|
|
||||||
|
virtual bool is_closed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BioStreamBuf _buf;
|
||||||
|
};
|
||||||
|
|
||||||
#include "bioStream.I"
|
#include "bioStream.I"
|
||||||
|
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
|
@ -38,15 +38,21 @@ BioStreamBuf() {
|
|||||||
// In spite of the claims of the MSDN Library to the contrary,
|
// In spite of the claims of the MSDN Library to the contrary,
|
||||||
// Windows doesn't seem to provide an allocate() function, so we'll
|
// Windows doesn't seem to provide an allocate() function, so we'll
|
||||||
// do it by hand.
|
// do it by hand.
|
||||||
char *buf = new char[4096];
|
char *buf = new char[8192];
|
||||||
char *ebuf = buf + 4096;
|
char *ebuf = buf + 8192;
|
||||||
setg(buf, ebuf, ebuf);
|
char *mbuf = buf + 4096;
|
||||||
setp(buf, ebuf);
|
setg(buf, mbuf, mbuf);
|
||||||
|
setp(mbuf, ebuf);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
allocate();
|
allocate();
|
||||||
setg(base(), ebuf(), ebuf());
|
// Chop the buffer in half. The bottom half goes to the get buffer;
|
||||||
setp(base(), ebuf());
|
// the top half goes to the put buffer.
|
||||||
|
char *b = base();
|
||||||
|
char *t = ebuf();
|
||||||
|
char *m = b + (t - b) / 2;
|
||||||
|
setg(b, m, m);
|
||||||
|
setp(b, m);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,29 +63,79 @@ BioStreamBuf() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
BioStreamBuf::
|
BioStreamBuf::
|
||||||
~BioStreamBuf() {
|
~BioStreamBuf() {
|
||||||
close_read();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BioStreamBuf::open_read
|
// Function: BioStreamBuf::open
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void BioStreamBuf::
|
void BioStreamBuf::
|
||||||
open_read(BioPtr *source) {
|
open(BioPtr *source) {
|
||||||
_source = source;
|
_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BioStreamBuf::close_read
|
// Function: BioStreamBuf::close
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void BioStreamBuf::
|
void BioStreamBuf::
|
||||||
close_read() {
|
close() {
|
||||||
|
sync();
|
||||||
_source.clear();
|
_source.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStreamBuf::overflow
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: Called by the system ostream implementation when its
|
||||||
|
// internal buffer is filled, plus one character.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int BioStreamBuf::
|
||||||
|
overflow(int ch) {
|
||||||
|
size_t n = pptr() - pbase();
|
||||||
|
if (n != 0) {
|
||||||
|
size_t num_wrote = write_chars(pbase(), n);
|
||||||
|
pbump(-(int)n);
|
||||||
|
if (num_wrote != n) {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch != EOF) {
|
||||||
|
// Store the next character back in the buffer.
|
||||||
|
*pptr() = ch;
|
||||||
|
pbump(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStreamBuf::sync
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: Called by the system iostream implementation to
|
||||||
|
// implement a flush operation.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int BioStreamBuf::
|
||||||
|
sync() {
|
||||||
|
/*
|
||||||
|
size_t n = egptr() - gptr();
|
||||||
|
gbump(n);
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t n = pptr() - pbase();
|
||||||
|
size_t num_wrote = write_chars(pbase(), n);
|
||||||
|
pbump(-(int)n);
|
||||||
|
if (num_wrote != n) {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: BioStreamBuf::underflow
|
// Function: BioStreamBuf::underflow
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
@ -118,5 +174,51 @@ underflow() {
|
|||||||
return (unsigned char)*gptr();
|
return (unsigned char)*gptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: BioStreamBuf::write_chars
|
||||||
|
// Access: Private
|
||||||
|
// Description: Sends some characters to the dest stream. Does not
|
||||||
|
// return until all characters are sent or the socket is
|
||||||
|
// closed, even if the underlying BIO is non-blocking.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
size_t BioStreamBuf::
|
||||||
|
write_chars(const char *start, size_t length) {
|
||||||
|
size_t wrote_so_far = 0;
|
||||||
|
|
||||||
|
int write_count = BIO_write(*_source, start, length);
|
||||||
|
while (write_count != (int)(length - wrote_so_far)) {
|
||||||
|
if (write_count <= 0) {
|
||||||
|
_is_closed = !BIO_should_retry(*_source);
|
||||||
|
if (_is_closed) {
|
||||||
|
return wrote_so_far;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block on the underlying socket before we try to write some
|
||||||
|
// more.
|
||||||
|
int fd = -1;
|
||||||
|
BIO_get_fd(*_source, &fd);
|
||||||
|
if (fd < 0) {
|
||||||
|
downloader_cat.warning()
|
||||||
|
<< "socket BIO has no file descriptor.\n";
|
||||||
|
} else {
|
||||||
|
downloader_cat.spam()
|
||||||
|
<< "waiting to write to BIO.\n";
|
||||||
|
fd_set wset;
|
||||||
|
FD_ZERO(&wset);
|
||||||
|
FD_SET(fd, &wset);
|
||||||
|
select(fd + 1, NULL, &wset, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// wrote some characters.
|
||||||
|
wrote_so_far += write_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to write some more.
|
||||||
|
write_count = BIO_write(*_source, start + wrote_so_far, length - wrote_so_far);
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
|
@ -38,17 +38,23 @@ public:
|
|||||||
BioStreamBuf();
|
BioStreamBuf();
|
||||||
virtual ~BioStreamBuf();
|
virtual ~BioStreamBuf();
|
||||||
|
|
||||||
void open_read(BioPtr *source);
|
void open(BioPtr *source);
|
||||||
void close_read();
|
void close();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual int overflow(int c);
|
||||||
|
virtual int sync(void);
|
||||||
virtual int underflow(void);
|
virtual int underflow(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
size_t write_chars(const char *start, size_t length);
|
||||||
|
|
||||||
PT(BioPtr) _source;
|
PT(BioPtr) _source;
|
||||||
bool _is_closed;
|
bool _is_closed;
|
||||||
|
|
||||||
friend class IBioStream;
|
friend class IBioStream;
|
||||||
|
friend class OBioStream;
|
||||||
|
friend class BioStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE BioStreamPtr::
|
INLINE BioStreamPtr::
|
||||||
BioStreamPtr(IBioStream *stream) : _stream(stream) {
|
BioStreamPtr(BioStream *stream) : _stream(stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -31,7 +31,7 @@ BioStreamPtr(IBioStream *stream) : _stream(stream) {
|
|||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE IBioStream &BioStreamPtr::
|
INLINE BioStream &BioStreamPtr::
|
||||||
operator *() const {
|
operator *() const {
|
||||||
return *_stream;
|
return *_stream;
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ operator *() const {
|
|||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE IBioStream *BioStreamPtr::
|
INLINE BioStream *BioStreamPtr::
|
||||||
operator ->() const {
|
operator ->() const {
|
||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ operator ->() const {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE BioStreamPtr::
|
INLINE BioStreamPtr::
|
||||||
operator IBioStream * () const {
|
operator BioStream * () const {
|
||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ operator IBioStream * () const {
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void BioStreamPtr::
|
INLINE void BioStreamPtr::
|
||||||
set_stream(IBioStream *stream) {
|
set_stream(BioStream *stream) {
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ set_stream(IBioStream *stream) {
|
|||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE IBioStream *BioStreamPtr::
|
INLINE BioStream *BioStreamPtr::
|
||||||
get_stream() const {
|
get_stream() const {
|
||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
BioStreamPtr::
|
BioStreamPtr::
|
||||||
~BioStreamPtr() {
|
~BioStreamPtr() {
|
||||||
if (_stream != (IBioStream *)NULL) {
|
if (_stream != (BioStream *)NULL) {
|
||||||
delete _stream;
|
delete _stream;
|
||||||
_stream = (IBioStream *)NULL;
|
_stream = (BioStream *)NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,25 +30,25 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : BioStreamPtr
|
// Class : BioStreamPtr
|
||||||
// Description : A wrapper around an IBioStream object to make a
|
// Description : A wrapper around an BioStream object to make a
|
||||||
// reference-counting pointer to it.
|
// reference-counting pointer to it.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDAEXPRESS BioStreamPtr : public ReferenceCount {
|
class EXPCL_PANDAEXPRESS BioStreamPtr : public ReferenceCount {
|
||||||
public:
|
public:
|
||||||
INLINE BioStreamPtr(IBioStream *stream);
|
INLINE BioStreamPtr(BioStream *stream);
|
||||||
virtual ~BioStreamPtr();
|
virtual ~BioStreamPtr();
|
||||||
|
|
||||||
INLINE IBioStream &operator *() const;
|
INLINE BioStream &operator *() const;
|
||||||
INLINE IBioStream *operator -> () const;
|
INLINE BioStream *operator -> () const;
|
||||||
INLINE operator IBioStream * () const;
|
INLINE operator BioStream * () const;
|
||||||
|
|
||||||
INLINE void set_stream(IBioStream *stream);
|
INLINE void set_stream(BioStream *stream);
|
||||||
INLINE IBioStream *get_stream() const;
|
INLINE BioStream *get_stream() const;
|
||||||
|
|
||||||
bool connect() const;
|
bool connect() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IBioStream *_stream;
|
BioStream *_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "bioStreamPtr.I"
|
#include "bioStreamPtr.I"
|
||||||
|
@ -13,5 +13,6 @@
|
|||||||
#include "identityStreamBuf.cxx"
|
#include "identityStreamBuf.cxx"
|
||||||
#include "multiplexStream.cxx"
|
#include "multiplexStream.cxx"
|
||||||
#include "multiplexStreamBuf.cxx"
|
#include "multiplexStreamBuf.cxx"
|
||||||
|
#include "socketStream.cxx"
|
||||||
#include "urlSpec.cxx"
|
#include "urlSpec.cxx"
|
||||||
|
|
||||||
|
@ -30,6 +30,18 @@ is_valid() const {
|
|||||||
(_status_code / 100) == 2);
|
(_status_code / 100) == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HTTPChannel::is_connection_ready
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if a connection has been established to
|
||||||
|
// the named server in a previous call to connect_to()
|
||||||
|
// or begin_connect_to(), false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool HTTPChannel::
|
||||||
|
is_connection_ready() const {
|
||||||
|
return (!_source.is_null() && _state == S_ready);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HTTPChannel::get_url
|
// Function: HTTPChannel::get_url
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -312,7 +324,7 @@ reset() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool HTTPChannel::
|
INLINE bool HTTPChannel::
|
||||||
post_form(const URLSpec &url, const string &body) {
|
post_form(const URLSpec &url, const string &body) {
|
||||||
begin_request("POST", url, body, false, 0, 0);
|
begin_request(M_post, url, body, false, 0, 0);
|
||||||
run();
|
run();
|
||||||
return is_valid();
|
return is_valid();
|
||||||
}
|
}
|
||||||
@ -325,7 +337,7 @@ post_form(const URLSpec &url, const string &body) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool HTTPChannel::
|
INLINE bool HTTPChannel::
|
||||||
get_document(const URLSpec &url) {
|
get_document(const URLSpec &url) {
|
||||||
begin_request("GET", url, string(), false, 0, 0);
|
begin_request(M_get, url, string(), false, 0, 0);
|
||||||
run();
|
run();
|
||||||
return is_valid();
|
return is_valid();
|
||||||
}
|
}
|
||||||
@ -342,7 +354,7 @@ get_document(const URLSpec &url) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool HTTPChannel::
|
INLINE bool HTTPChannel::
|
||||||
get_subdocument(const URLSpec &url, size_t first_byte, size_t last_byte) {
|
get_subdocument(const URLSpec &url, size_t first_byte, size_t last_byte) {
|
||||||
begin_request("GET", url, string(), false, first_byte, last_byte);
|
begin_request(M_get, url, string(), false, first_byte, last_byte);
|
||||||
run();
|
run();
|
||||||
return is_valid();
|
return is_valid();
|
||||||
}
|
}
|
||||||
@ -358,11 +370,30 @@ get_subdocument(const URLSpec &url, size_t first_byte, size_t last_byte) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool HTTPChannel::
|
INLINE bool HTTPChannel::
|
||||||
get_header(const URLSpec &url) {
|
get_header(const URLSpec &url) {
|
||||||
begin_request("HEAD", url, string(), false, 0, 0);
|
begin_request(M_head, url, string(), false, 0, 0);
|
||||||
run();
|
run();
|
||||||
return is_valid();
|
return is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HTTPChannel::connect_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Establish a direct connection to the server and port
|
||||||
|
// indicated by the URL, but do not issue any HTTP
|
||||||
|
// requests. If successful, the connection may then be
|
||||||
|
// taken to use for whatever purposes you like by
|
||||||
|
// calling get_connection().
|
||||||
|
//
|
||||||
|
// This establishes a blocking I/O socket. Also see
|
||||||
|
// begin_connect_to().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool HTTPChannel::
|
||||||
|
connect_to(const URLSpec &url) {
|
||||||
|
begin_request(M_connect, url, string(), false, 0, 0);
|
||||||
|
run();
|
||||||
|
return is_connection_ready();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HTTPChannel::begin_post_form
|
// Function: HTTPChannel::begin_post_form
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -379,7 +410,7 @@ get_header(const URLSpec &url) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void HTTPChannel::
|
INLINE void HTTPChannel::
|
||||||
begin_post_form(const URLSpec &url, const string &body) {
|
begin_post_form(const URLSpec &url, const string &body) {
|
||||||
begin_request("POST", url, body, true, 0, 0);
|
begin_request(M_post, url, body, true, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -398,7 +429,7 @@ begin_post_form(const URLSpec &url, const string &body) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void HTTPChannel::
|
INLINE void HTTPChannel::
|
||||||
begin_get_document(const URLSpec &url) {
|
begin_get_document(const URLSpec &url) {
|
||||||
begin_request("GET", url, string(), true, 0, 0);
|
begin_request(M_get, url, string(), true, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -415,7 +446,7 @@ begin_get_document(const URLSpec &url) {
|
|||||||
INLINE void HTTPChannel::
|
INLINE void HTTPChannel::
|
||||||
begin_get_subdocument(const URLSpec &url, size_t first_byte,
|
begin_get_subdocument(const URLSpec &url, size_t first_byte,
|
||||||
size_t last_byte) {
|
size_t last_byte) {
|
||||||
begin_request("GET", url, string(), true, first_byte, last_byte);
|
begin_request(M_get, url, string(), true, first_byte, last_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -426,7 +457,30 @@ begin_get_subdocument(const URLSpec &url, size_t first_byte,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void HTTPChannel::
|
INLINE void HTTPChannel::
|
||||||
begin_get_header(const URLSpec &url) {
|
begin_get_header(const URLSpec &url) {
|
||||||
begin_request("HEAD", url, string(), true, 0, 0);
|
begin_request(M_head, url, string(), true, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HTTPChannel::begin_connect_to
|
||||||
|
// Access: Published
|
||||||
|
// Description: Begins a non-blocking request to establish a direct
|
||||||
|
// connection to the server and port indicated by the
|
||||||
|
// URL. No HTTP requests will be issued beyond what is
|
||||||
|
// necessary to establish the connection. When run()
|
||||||
|
// has finished, you may call is_connection_ready() to
|
||||||
|
// determine if the connection was successfully
|
||||||
|
// established.
|
||||||
|
//
|
||||||
|
// If successful, the connection may then be taken to
|
||||||
|
// use for whatever purposes you like by calling
|
||||||
|
// get_connection().
|
||||||
|
//
|
||||||
|
// This establishes a nonblocking I/O socket. Also see
|
||||||
|
// connect_to().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void HTTPChannel::
|
||||||
|
begin_connect_to(const URLSpec &url) {
|
||||||
|
begin_request(M_connect, url, string(), true, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -56,6 +56,8 @@ HTTPChannel(HTTPClient *client) :
|
|||||||
_max_updates_per_second = 1.0f / _seconds_per_update;
|
_max_updates_per_second = 1.0f / _seconds_per_update;
|
||||||
_bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
|
_bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
|
||||||
_nonblocking = false;
|
_nonblocking = false;
|
||||||
|
_want_ssl = false;
|
||||||
|
_proxy_serves_document = false;
|
||||||
_first_byte = 0;
|
_first_byte = 0;
|
||||||
_last_byte = 0;
|
_last_byte = 0;
|
||||||
_read_index = 0;
|
_read_index = 0;
|
||||||
@ -258,7 +260,7 @@ run() {
|
|||||||
} else {
|
} else {
|
||||||
_bio = new BioPtr(_proxy);
|
_bio = new BioPtr(_proxy);
|
||||||
}
|
}
|
||||||
_source = new BioStreamPtr(new IBioStream(_bio));
|
_source = new BioStreamPtr(new BioStream(_bio));
|
||||||
if (_nonblocking) {
|
if (_nonblocking) {
|
||||||
BIO_set_nbio(*_bio, 1);
|
BIO_set_nbio(*_bio, 1);
|
||||||
}
|
}
|
||||||
@ -509,6 +511,33 @@ download_to_ram(Ramfile *ramfile) {
|
|||||||
return is_download_complete();
|
return is_download_complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HTTPChannel::get_connection
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the connection that was established via a
|
||||||
|
// previous call to connect_to() or begin_connect_to(),
|
||||||
|
// or NULL if the connection attempt failed or if those
|
||||||
|
// methods have not recently been called.
|
||||||
|
//
|
||||||
|
// This stream has been allocated from the free store.
|
||||||
|
// It is the user's responsibility to delete this
|
||||||
|
// pointer when finished with it.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
SocketStream *HTTPChannel::
|
||||||
|
get_connection() {
|
||||||
|
if (!is_connection_ready()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BioStream *stream = _source->get_stream();
|
||||||
|
_source->set_stream(NULL);
|
||||||
|
|
||||||
|
// We're now passing ownership of the connection to the user.
|
||||||
|
free_bio();
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HTTPChannel::reached_done_state
|
// Function: HTTPChannel::reached_done_state
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -552,6 +581,8 @@ reached_done_state() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool HTTPChannel::
|
bool HTTPChannel::
|
||||||
run_connecting() {
|
run_connecting() {
|
||||||
|
_status_code = 0;
|
||||||
|
_status_string = string();
|
||||||
if (BIO_do_connect(*_bio) <= 0) {
|
if (BIO_do_connect(*_bio) <= 0) {
|
||||||
if (BIO_should_retry(*_bio)) {
|
if (BIO_should_retry(*_bio)) {
|
||||||
return true;
|
return true;
|
||||||
@ -577,11 +608,7 @@ run_connecting() {
|
|||||||
_state = S_proxy_ready;
|
_state = S_proxy_ready;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (_url.get_scheme() == "https") {
|
_state = _want_ssl ? S_setup_ssl : S_ready;
|
||||||
_state = S_setup_ssl;
|
|
||||||
} else {
|
|
||||||
_state = S_ready;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -702,11 +729,7 @@ run_proxy_reading_header() {
|
|||||||
_proxy_tunnel = true;
|
_proxy_tunnel = true;
|
||||||
make_request_text(string());
|
make_request_text(string());
|
||||||
|
|
||||||
if (_url.get_scheme() == "https") {
|
_state = _want_ssl ? S_setup_ssl : S_ready;
|
||||||
_state = S_setup_ssl;
|
|
||||||
} else {
|
|
||||||
_state = S_ready;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,7 +1001,7 @@ run_reading_header() {
|
|||||||
|
|
||||||
if ((get_status_code() / 100) == 3 && get_status_code() != 305) {
|
if ((get_status_code() / 100) == 3 && get_status_code() != 305) {
|
||||||
// Redirect. Should we handle it automatically?
|
// Redirect. Should we handle it automatically?
|
||||||
if (!get_redirect().empty() && (_method == "GET" || _method == "HEAD")) {
|
if (!get_redirect().empty() && (_method == M_get || _method == M_head)) {
|
||||||
// Sure!
|
// Sure!
|
||||||
URLSpec new_url = get_redirect();
|
URLSpec new_url = get_redirect();
|
||||||
if (!_redirect_trail.insert(new_url).second) {
|
if (!_redirect_trail.insert(new_url).second) {
|
||||||
@ -1049,7 +1072,7 @@ run_begin_body() {
|
|||||||
if (get_status_code() / 100 == 1 ||
|
if (get_status_code() / 100 == 1 ||
|
||||||
get_status_code() == 204 ||
|
get_status_code() == 204 ||
|
||||||
get_status_code() == 304 ||
|
get_status_code() == 304 ||
|
||||||
_method == "HEAD") {
|
_method == M_head) {
|
||||||
// These status codes, or method HEAD, indicate we have no body.
|
// These status codes, or method HEAD, indicate we have no body.
|
||||||
// Therefore, we have already read the (nonexistent) body.
|
// Therefore, we have already read the (nonexistent) body.
|
||||||
_state = S_ready;
|
_state = S_ready;
|
||||||
@ -1283,8 +1306,9 @@ run_download_to_ram() {
|
|||||||
// necessary.
|
// necessary.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void HTTPChannel::
|
void HTTPChannel::
|
||||||
begin_request(const string &method, const URLSpec &url, const string &body,
|
begin_request(HTTPChannel::Method method, const URLSpec &url,
|
||||||
bool nonblocking, size_t first_byte, size_t last_byte) {
|
const string &body, bool nonblocking,
|
||||||
|
size_t first_byte, size_t last_byte) {
|
||||||
reset_for_new_request();
|
reset_for_new_request();
|
||||||
|
|
||||||
// Changing the proxy, or the nonblocking state, is grounds for
|
// Changing the proxy, or the nonblocking state, is grounds for
|
||||||
@ -1299,19 +1323,29 @@ begin_request(const string &method, const URLSpec &url, const string &body,
|
|||||||
free_bio();
|
free_bio();
|
||||||
}
|
}
|
||||||
|
|
||||||
_method = method;
|
|
||||||
set_url(url);
|
set_url(url);
|
||||||
|
_method = method;
|
||||||
_body = body;
|
_body = body;
|
||||||
|
|
||||||
|
// An https-style request means we'll need to establish an SSL
|
||||||
|
// connection.
|
||||||
|
_want_ssl = (_url.get_scheme() == "https");
|
||||||
|
|
||||||
|
// If we have a proxy, we'll be asking the proxy to hand us the
|
||||||
|
// document--except when we also have https, in which case we'll be
|
||||||
|
// tunnelling through the proxy to talk to the server directly.
|
||||||
|
_proxy_serves_document = (!_proxy.empty() && !_want_ssl);
|
||||||
|
|
||||||
_first_byte = first_byte;
|
_first_byte = first_byte;
|
||||||
_last_byte = last_byte;
|
_last_byte = last_byte;
|
||||||
|
|
||||||
make_header();
|
make_header();
|
||||||
make_request_text(string());
|
make_request_text(string());
|
||||||
|
|
||||||
if (!_proxy.empty() && _url.get_scheme() == "https") {
|
if (!_proxy.empty() && (_want_ssl || _method == M_connect)) {
|
||||||
// HTTPS over proxy requires tunnelling through the proxy to the
|
// Maybe we need to tunnel through the proxy to connect to the
|
||||||
// server so we can handle the SSL connection directly, rather
|
// server directly. We need this for HTTPS, or if the user
|
||||||
// than asking the proxy to hand us the particular document(s) in
|
// requested a direct connection somewhere.
|
||||||
// question.
|
|
||||||
ostringstream request;
|
ostringstream request;
|
||||||
request
|
request
|
||||||
<< "CONNECT " << _url.get_server() << ":" << _url.get_port()
|
<< "CONNECT " << _url.get_server() << ":" << _url.get_port()
|
||||||
@ -1338,7 +1372,7 @@ begin_request(const string &method, const URLSpec &url, const string &body,
|
|||||||
_state = S_begin_body;
|
_state = S_begin_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
_done_state = S_read_header;
|
_done_state = (_method == M_connect) ? S_ready : S_read_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1414,6 +1448,8 @@ bool HTTPChannel::
|
|||||||
http_send(const string &str) {
|
http_send(const string &str) {
|
||||||
nassertr(str.length() > _sent_so_far, true);
|
nassertr(str.length() > _sent_so_far, true);
|
||||||
|
|
||||||
|
// Use the underlying BIO to write to the server, instead of the
|
||||||
|
// BIOStream, which would insist on blocking.
|
||||||
size_t bytes_to_send = str.length() - _sent_so_far;
|
size_t bytes_to_send = str.length() - _sent_so_far;
|
||||||
int write_count =
|
int write_count =
|
||||||
BIO_write(*_bio, str.data() + _sent_so_far, bytes_to_send);
|
BIO_write(*_bio, str.data() + _sent_so_far, bytes_to_send);
|
||||||
@ -1923,24 +1959,51 @@ x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void HTTPChannel::
|
void HTTPChannel::
|
||||||
make_header() {
|
make_header() {
|
||||||
string path;
|
if (_method == M_connect) {
|
||||||
if (_proxy.empty() || _url.get_scheme() == "https") {
|
// This method doesn't require an HTTP header at all; we'll just
|
||||||
// In either of these cases, we contact the server directly for
|
// open a plain connection. (Except when we're using a proxy; but
|
||||||
// the document, so we just need the server-relative path.
|
// in that case, it's the proxy_header we'll need, not the regular
|
||||||
path = _url.get_path();
|
// HTTP header.)
|
||||||
|
_header = string();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
string path;
|
||||||
// In this case (http-over-proxy), we ask the proxy for the
|
if (_proxy_serves_document) {
|
||||||
// document, so we need its full URL.
|
// If we'll be asking the proxy for the document, we need its full
|
||||||
|
// URL--but we omit the username, which is information just for us.
|
||||||
URLSpec url_no_username = _url;
|
URLSpec url_no_username = _url;
|
||||||
url_no_username.set_username(string());
|
url_no_username.set_username(string());
|
||||||
path = url_no_username.get_url();
|
path = url_no_username.get_url();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If we'll be asking the server directly for the document, we
|
||||||
|
// just want its path relative to the server.
|
||||||
|
path = _url.get_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream stream;
|
ostringstream stream;
|
||||||
|
|
||||||
|
switch (_method) {
|
||||||
|
case M_get:
|
||||||
|
stream << "GET";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_head:
|
||||||
|
stream << "HEAD";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_post:
|
||||||
|
stream << "POST";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case M_connect:
|
||||||
|
stream << "CONNECT";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
stream
|
stream
|
||||||
<< _method << " " << path << " "
|
<< " " << path << " "
|
||||||
<< _client->get_http_version_string() << "\r\n";
|
<< _client->get_http_version_string() << "\r\n";
|
||||||
|
|
||||||
if (_client->get_http_version() >= HTTPClient::HV_11) {
|
if (_client->get_http_version() >= HTTPClient::HV_11) {
|
||||||
|
@ -74,6 +74,7 @@ public:
|
|||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE bool is_valid() const;
|
INLINE bool is_valid() const;
|
||||||
|
INLINE bool is_connection_ready() const;
|
||||||
INLINE const URLSpec &get_url() const;
|
INLINE const URLSpec &get_url() const;
|
||||||
INLINE HTTPClient::HTTPVersion get_http_version() const;
|
INLINE HTTPClient::HTTPVersion get_http_version() const;
|
||||||
INLINE const string &get_http_version_string() const;
|
INLINE const string &get_http_version_string() const;
|
||||||
@ -106,6 +107,7 @@ PUBLISHED:
|
|||||||
INLINE bool get_subdocument(const URLSpec &url,
|
INLINE bool get_subdocument(const URLSpec &url,
|
||||||
size_t first_byte, size_t last_byte);
|
size_t first_byte, size_t last_byte);
|
||||||
INLINE bool get_header(const URLSpec &url);
|
INLINE bool get_header(const URLSpec &url);
|
||||||
|
INLINE bool connect_to(const URLSpec &url);
|
||||||
|
|
||||||
INLINE void begin_post_form(const URLSpec &url, const string &body);
|
INLINE void begin_post_form(const URLSpec &url, const string &body);
|
||||||
INLINE void begin_get_document(const URLSpec &url);
|
INLINE void begin_get_document(const URLSpec &url);
|
||||||
@ -113,16 +115,25 @@ PUBLISHED:
|
|||||||
size_t first_byte, size_t last_byte);
|
size_t first_byte, size_t last_byte);
|
||||||
INLINE void begin_get_header(const URLSpec &url);
|
INLINE void begin_get_header(const URLSpec &url);
|
||||||
bool run();
|
bool run();
|
||||||
|
INLINE void begin_connect_to(const URLSpec &url);
|
||||||
|
|
||||||
ISocketStream *read_body();
|
ISocketStream *read_body();
|
||||||
bool download_to_file(const Filename &filename, size_t first_byte = 0);
|
bool download_to_file(const Filename &filename, size_t first_byte = 0);
|
||||||
bool download_to_ram(Ramfile *ramfile);
|
bool download_to_ram(Ramfile *ramfile);
|
||||||
|
SocketStream *get_connection();
|
||||||
|
|
||||||
INLINE size_t get_bytes_downloaded() const;
|
INLINE size_t get_bytes_downloaded() const;
|
||||||
INLINE size_t get_bytes_requested() const;
|
INLINE size_t get_bytes_requested() const;
|
||||||
INLINE bool is_download_complete() const;
|
INLINE bool is_download_complete() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Method {
|
||||||
|
M_get,
|
||||||
|
M_head,
|
||||||
|
M_post,
|
||||||
|
M_connect
|
||||||
|
};
|
||||||
|
|
||||||
bool reached_done_state();
|
bool reached_done_state();
|
||||||
bool run_connecting();
|
bool run_connecting();
|
||||||
bool run_proxy_ready();
|
bool run_proxy_ready();
|
||||||
@ -142,7 +153,7 @@ private:
|
|||||||
bool run_download_to_file();
|
bool run_download_to_file();
|
||||||
bool run_download_to_ram();
|
bool run_download_to_ram();
|
||||||
|
|
||||||
void begin_request(const string &method, const URLSpec &url,
|
void begin_request(Method method, const URLSpec &url,
|
||||||
const string &body, bool nonblocking,
|
const string &body, bool nonblocking,
|
||||||
size_t first_byte, size_t last_byte);
|
size_t first_byte, size_t last_byte);
|
||||||
void reset_for_new_request();
|
void reset_for_new_request();
|
||||||
@ -193,9 +204,11 @@ private:
|
|||||||
bool _nonblocking;
|
bool _nonblocking;
|
||||||
|
|
||||||
URLSpec _url;
|
URLSpec _url;
|
||||||
string _method;
|
Method _method;
|
||||||
string _header;
|
string _header;
|
||||||
string _body;
|
string _body;
|
||||||
|
bool _want_ssl;
|
||||||
|
bool _proxy_serves_document;
|
||||||
size_t _first_byte;
|
size_t _first_byte;
|
||||||
size_t _last_byte;
|
size_t _last_byte;
|
||||||
|
|
||||||
|
@ -24,4 +24,24 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE ISocketStream::
|
INLINE ISocketStream::
|
||||||
ISocketStream(streambuf *buf) : istream(buf) {
|
ISocketStream(streambuf *buf) : istream(buf) {
|
||||||
|
_data_expected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OSocketStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE OSocketStream::
|
||||||
|
OSocketStream(streambuf *buf) : ostream(buf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SocketStream::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE SocketStream::
|
||||||
|
SocketStream(streambuf *buf) : iostream(buf) {
|
||||||
|
_data_expected = 0;
|
||||||
}
|
}
|
||||||
|
165
panda/src/downloader/socketStream.cxx
Normal file
165
panda/src/downloader/socketStream.cxx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// Filename: socketStream.cxx
|
||||||
|
// Created by: drose (19Oct02)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://www.panda3d.org/license.txt .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d@yahoogroups.com .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "socketStream.h"
|
||||||
|
#include "datagram.h"
|
||||||
|
#include "datagramIterator.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: ISocketStream::receive_datagram
|
||||||
|
// Access: Public
|
||||||
|
// Description: Receives a datagram over the socket by expecting a
|
||||||
|
// little-endian 16-bit byte count as a prefix. If the
|
||||||
|
// socket stream is non-blocking, may return false if
|
||||||
|
// the data is not available; otherwise, returns false
|
||||||
|
// only if the socket closes.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool ISocketStream::
|
||||||
|
receive_datagram(Datagram &dg) {
|
||||||
|
if (_data_expected == 0) {
|
||||||
|
// Read the first two bytes: the datagram length.
|
||||||
|
while (_data_so_far.length() < 2) {
|
||||||
|
int ch = get();
|
||||||
|
if (eof()) {
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_data_so_far += (char)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
Datagram header(_data_so_far);
|
||||||
|
DatagramIterator di(header);
|
||||||
|
_data_expected = di.get_uint16();
|
||||||
|
_data_so_far = string();
|
||||||
|
|
||||||
|
if (_data_expected == 0) {
|
||||||
|
// Empty datagram.
|
||||||
|
dg.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next n bytes until the datagram is filled.
|
||||||
|
while (_data_so_far.length() < _data_expected) {
|
||||||
|
int ch = get();
|
||||||
|
if (eof()) {
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_data_so_far += (char)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
dg.clear();
|
||||||
|
dg.append_data(_data_so_far);
|
||||||
|
|
||||||
|
_data_expected = 0;
|
||||||
|
_data_so_far = string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: OSocketStream::send_datagram
|
||||||
|
// Access: Public
|
||||||
|
// Description: Transmits the indicated datagram over the socket by
|
||||||
|
// prepending it with a little-endian 16-bit byte count.
|
||||||
|
// Does not return until the data is sent or the
|
||||||
|
// connection is closed, even if the socket stream is
|
||||||
|
// non-blocking.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool OSocketStream::
|
||||||
|
send_datagram(const Datagram &dg) {
|
||||||
|
Datagram header;
|
||||||
|
header.add_uint16(dg.get_length());
|
||||||
|
write(header.get_data(), header.get_length());
|
||||||
|
write(dg.get_data(), dg.get_length());
|
||||||
|
flush();
|
||||||
|
|
||||||
|
return !is_closed();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SocketStream::receive_datagram
|
||||||
|
// Access: Public
|
||||||
|
// Description: Receives a datagram over the socket by expecting a
|
||||||
|
// little-endian 16-bit byte count as a prefix. If the
|
||||||
|
// socket stream is non-blocking, may return false if
|
||||||
|
// the data is not available; otherwise, returns false
|
||||||
|
// only if the socket closes.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SocketStream::
|
||||||
|
receive_datagram(Datagram &dg) {
|
||||||
|
if (_data_expected == 0) {
|
||||||
|
// Read the first two bytes: the datagram length.
|
||||||
|
while (_data_so_far.length() < 2) {
|
||||||
|
int ch = get();
|
||||||
|
if (eof()) {
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_data_so_far += (char)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
Datagram header(_data_so_far);
|
||||||
|
DatagramIterator di(header);
|
||||||
|
_data_expected = di.get_uint16();
|
||||||
|
_data_so_far = string();
|
||||||
|
|
||||||
|
if (_data_expected == 0) {
|
||||||
|
// Empty datagram.
|
||||||
|
dg.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next n bytes until the datagram is filled.
|
||||||
|
while (_data_so_far.length() < _data_expected) {
|
||||||
|
int ch = get();
|
||||||
|
if (eof()) {
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_data_so_far += (char)ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
dg.clear();
|
||||||
|
dg.append_data(_data_so_far);
|
||||||
|
|
||||||
|
_data_expected = 0;
|
||||||
|
_data_so_far = string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: SocketStream::send_datagram
|
||||||
|
// Access: Public
|
||||||
|
// Description: Transmits the indicated datagram over the socket by
|
||||||
|
// prepending it with a little-endian 16-bit byte count.
|
||||||
|
// Does not return until the data is sent or the
|
||||||
|
// connection is closed, even if the socket stream is
|
||||||
|
// non-blocking.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool SocketStream::
|
||||||
|
send_datagram(const Datagram &dg) {
|
||||||
|
Datagram header;
|
||||||
|
header.add_uint16(dg.get_length());
|
||||||
|
write(header.get_data(), header.get_length());
|
||||||
|
write(dg.get_data(), dg.get_length());
|
||||||
|
flush();
|
||||||
|
|
||||||
|
return !is_closed();
|
||||||
|
}
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
|
|
||||||
|
class Datagram;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : ISocketStream
|
// Class : ISocketStream
|
||||||
// Description : This is a base class for istreams implemented in
|
// Description : This is a base class for istreams implemented in
|
||||||
@ -41,9 +43,54 @@ public:
|
|||||||
INLINE ISocketStream(streambuf *buf);
|
INLINE ISocketStream(streambuf *buf);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
|
bool receive_datagram(Datagram &dg);
|
||||||
|
|
||||||
|
virtual bool is_closed() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _data_expected;
|
||||||
|
string _data_so_far;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : OSocketStream
|
||||||
|
// Description : A base class for ostreams that write to a (possibly
|
||||||
|
// non-blocking) socket. It adds is_closed(), which can
|
||||||
|
// be called after any write operation fails to check
|
||||||
|
// whether the socket has been closed, or whether more
|
||||||
|
// data may be sent later.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDAEXPRESS OSocketStream : public ostream {
|
||||||
|
public:
|
||||||
|
INLINE OSocketStream(streambuf *buf);
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
bool send_datagram(const Datagram &dg);
|
||||||
|
|
||||||
virtual bool is_closed() = 0;
|
virtual bool is_closed() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : SocketStream
|
||||||
|
// Description : A base class for iostreams that read and write to a
|
||||||
|
// (possibly non-blocking) socket.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDAEXPRESS SocketStream : public iostream {
|
||||||
|
public:
|
||||||
|
INLINE SocketStream(streambuf *buf);
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
bool receive_datagram(Datagram &dg);
|
||||||
|
bool send_datagram(const Datagram &dg);
|
||||||
|
|
||||||
|
virtual bool is_closed() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _data_expected;
|
||||||
|
string _data_so_far;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#include "socketStream.I"
|
#include "socketStream.I"
|
||||||
|
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user