15 #include "chunkedStreamBuf.h" 16 #include "config_downloader.h" 22 #ifndef HAVE_STREAMSIZE 24 typedef int streamsize;
36 _wanted_nonblocking =
false;
37 _read_state = ISocketStream::RS_initial;
40 _buffer = (
char *)PANDA_MALLOC_ARRAY(4096);
41 char *ebuf = _buffer + 4096;
42 setg(_buffer, ebuf, ebuf);
47 setg(base(), ebuf(), ebuf());
61 PANDA_FREE_ARRAY(_buffer);
72 void ChunkedStreamBuf::
73 open_read(BioStreamPtr *source, HTTPChannel *doc) {
75 nassertv(!_source.is_null());
78 _wanted_nonblocking = doc->_wanted_nonblocking;
79 _read_state = ISocketStream::RS_reading;
82 if (_doc != (HTTPChannel *)NULL) {
83 _read_index = doc->_read_index;
84 _doc->_transfer_file_size = 0;
85 _doc->_got_transfer_file_size =
true;
99 void ChunkedStreamBuf::
110 int ChunkedStreamBuf::
113 if (gptr() >= egptr()) {
114 size_t buffer_size = egptr() - eback();
115 gbump(-(
int)buffer_size);
117 size_t num_bytes = buffer_size;
118 size_t read_count = read_chars(gptr(), buffer_size);
120 if (read_count != num_bytes) {
122 if (read_count == 0) {
128 nassertr(read_count < num_bytes, EOF);
129 size_t delta = num_bytes - read_count;
130 memmove(gptr() + delta, gptr(), read_count);
135 return (
unsigned char)*gptr();
144 size_t ChunkedStreamBuf::
145 read_chars(
char *start,
size_t length) {
147 nassertr(!_source.is_null(), 0);
152 if (_chunk_remaining != 0) {
154 length = min(length, _chunk_remaining);
155 (*_source)->read(start, length);
156 size_t read_count = (*_source)->gcount();
157 if (!_wanted_nonblocking) {
158 while (read_count == 0 && !(*_source)->is_closed()) {
161 (*_source)->read(start, length);
162 read_count = (*_source)->gcount();
165 _chunk_remaining -= read_count;
167 if (read_count == 0 && (*_source)->is_closed()) {
169 _read_state = ISocketStream::RS_error;
177 bool got_line = http_getline(line);
178 while (got_line && line.empty()) {
182 got_line = http_getline(line);
186 if ((*_source)->is_closed()) {
188 _read_state = ISocketStream::RS_error;
191 if (!_wanted_nonblocking) {
199 size_t chunk_size = (size_t)strtol(line.c_str(), NULL, 16);
200 if (downloader_cat.is_spam()) {
201 downloader_cat.spam()
202 <<
"Got chunk of size " << chunk_size <<
" bytes.\n";
205 if (chunk_size == 0) {
208 if (_doc != (HTTPChannel *)NULL && _read_index == _doc->_read_index) {
209 _doc->_file_size = _doc->_transfer_file_size;
210 _doc->_got_file_size =
true;
212 _read_state = ISocketStream::RS_complete;
216 if (_doc != (HTTPChannel *)NULL && _read_index == _doc->_read_index) {
217 _doc->_transfer_file_size += chunk_size;
220 _chunk_remaining = chunk_size;
237 bool ChunkedStreamBuf::
238 http_getline(
string &str) {
239 nassertr(!_source.is_null(),
false);
240 int ch = (*_source)->get();
241 while (!(*_source)->eof() && !(*_source)->fail()) {
245 str = _working_getline;
246 _working_getline = string();
250 size_t p = str.length();
251 while (p > 0 && isspace(str[p - 1])) {
254 str = str.substr(0, p);
264 _working_getline += (char)ch;
266 ch = (*_source)->get();
272 #endif // HAVE_OPENSSL