Panda3D
Loading...
Searching...
No Matches
identityStreamBuf.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file identityStreamBuf.cxx
10 * @author drose
11 * @date 2002-10-09
12 */
13
14#include "identityStreamBuf.h"
15
16// This module is not compiled if OpenSSL is not available.
17#ifdef HAVE_OPENSSL
18#include "httpChannel.h"
19
20/**
21 *
22 */
23IdentityStreamBuf::
24IdentityStreamBuf() {
25 _has_content_length = true;
26 _bytes_remaining = 0;
27 _wanted_nonblocking = false;
28 _read_state = ISocketStream::RS_initial;
29
30#ifdef PHAVE_IOSTREAM
31 _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
32 char *ebuf = _buffer + 4096;
33 setg(_buffer, ebuf, ebuf);
34 setp(_buffer, ebuf);
35
36#else
37 allocate();
38 setg(base(), ebuf(), ebuf());
39 setp(base(), ebuf());
40#endif
41}
42
43/**
44 *
45 */
46IdentityStreamBuf::
47~IdentityStreamBuf() {
48 close_read();
49#ifdef PHAVE_IOSTREAM
50 PANDA_FREE_ARRAY(_buffer);
51#endif
52}
53
54/**
55 * If the document pointer is non-NULL, it will be updated with the length of
56 * the file as it is derived from the identity encoding.
57 */
58void IdentityStreamBuf::
59open_read(BioStreamPtr *source, HTTPChannel *doc,
60 bool has_content_length, size_t content_length) {
61 _source = source;
62 _has_content_length = has_content_length;
63 _wanted_nonblocking = doc->_wanted_nonblocking;
64 _bytes_remaining = content_length;
65 _read_state = ISocketStream::RS_reading;
66}
67
68/**
69 *
70 */
71void IdentityStreamBuf::
72close_read() {
73 _source.clear();
74}
75
76/**
77 * Called by the system istream implementation when its internal buffer needs
78 * more characters.
79 */
80int IdentityStreamBuf::
81underflow() {
82 // Sometimes underflow() is called even if the buffer is not empty.
83 if (gptr() >= egptr()) {
84 size_t buffer_size = egptr() - eback();
85 gbump(-(int)buffer_size);
86
87 size_t num_bytes = buffer_size;
88 size_t read_count = read_chars(gptr(), buffer_size);
89
90 if (read_count != num_bytes) {
91 // Oops, we didn't read what we thought we would.
92 if (read_count == 0) {
93 gbump(num_bytes);
94 return EOF;
95 }
96
97 // Slide what we did read to the top of the buffer.
98 nassertr(read_count < num_bytes, EOF);
99 size_t delta = num_bytes - read_count;
100 memmove(gptr() + delta, gptr(), read_count);
101 gbump(delta);
102 }
103 }
104
105 return (unsigned char)*gptr();
106}
107
108
109/**
110 * Gets some characters from the source stream.
111 */
112size_t IdentityStreamBuf::
113read_chars(char *start, size_t length) {
114 size_t read_count = 0;
115
116 if (!_has_content_length) {
117 // If we have no restrictions on content length, read till end of file.
118 (*_source)->read(start, length);
119 read_count = (*_source)->gcount();
120
121 if (!_wanted_nonblocking) {
122 while (read_count == 0 && !(*_source)->is_closed()) {
123 // Simulate blocking.
124 thread_yield();
125 (*_source)->read(start, length);
126 read_count = (*_source)->gcount();
127 }
128 }
129
130 if (read_count == 0) {
131 if ((*_source)->is_closed()) {
132 // socket closed; we're done.
133 _read_state = ISocketStream::RS_complete;
134 }
135 return 0;
136 }
137
138 } else {
139 // Extract some of the remaining bytes, but do not read past the
140 // content_length restriction.
141
142 if (_bytes_remaining != 0) {
143 length = std::min(length, _bytes_remaining);
144 (*_source)->read(start, length);
145 read_count = (*_source)->gcount();
146 if (!_wanted_nonblocking) {
147 while (read_count == 0 && !(*_source)->is_closed()) {
148 // Simulate blocking.
149 thread_yield();
150 (*_source)->read(start, length);
151 read_count = (*_source)->gcount();
152 }
153 }
154 nassertr(read_count <= _bytes_remaining, 0);
155 _bytes_remaining -= read_count;
156
157 if (read_count == 0) {
158 if ((*_source)->is_closed()) {
159 // socket closed unexpectedly; problem.
160 _read_state = ISocketStream::RS_error;
161 }
162 return 0;
163 }
164 }
165
166 if (_bytes_remaining == 0) {
167 // We're done.
168 _read_state = ISocketStream::RS_complete;
169 }
170 }
171
172 return read_count;
173}
174
175#endif // HAVE_OPENSSL
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.