Panda3D
|
00001 // Filename: socketStream.cxx 00002 // Created by: drose (19Oct02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "socketStream.h" 00016 #include "datagram.h" 00017 #include "datagramIterator.h" 00018 #include "httpChannel.h" 00019 #include "config_downloader.h" 00020 00021 #ifdef HAVE_OPENSSL 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: SSReader::Constructor 00025 // Access: Public 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 SSReader:: 00029 SSReader(istream *stream) : _istream(stream) { 00030 _data_expected = 0; 00031 _tcp_header_size = tcp_header_size; 00032 00033 #ifdef SIMULATE_NETWORK_DELAY 00034 _delay_active = false; 00035 _min_delay = 0.0; 00036 _delay_variance = 0.0; 00037 #endif // SIMULATE_NETWORK_DELAY 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: SSReader::Destructor 00042 // Access: Public, Virtual 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 SSReader:: 00046 ~SSReader() { 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: SSReader::do_receive_datagram 00051 // Access: Private 00052 // Description: Receives a datagram over the socket by expecting a 00053 // little-endian 16-bit byte count as a prefix. If the 00054 // socket stream is non-blocking, may return false if 00055 // the data is not available; otherwise, returns false 00056 // only if the socket closes. 00057 //////////////////////////////////////////////////////////////////// 00058 bool SSReader:: 00059 do_receive_datagram(Datagram &dg) { 00060 if (_tcp_header_size == 0) { 00061 _data_expected = _data_so_far.length(); 00062 } 00063 if (_data_expected == 0) { 00064 // Read the first two bytes: the datagram length. 00065 while ((int)_data_so_far.length() < _tcp_header_size) { 00066 int ch = _istream->get(); 00067 if (_istream->eof() || _istream->fail()) { 00068 _istream->clear(); 00069 return false; 00070 } 00071 _data_so_far += (char)ch; 00072 } 00073 00074 Datagram header(_data_so_far); 00075 DatagramIterator di(header); 00076 if (_tcp_header_size == 2) { 00077 _data_expected = di.get_uint16(); 00078 } else if (_tcp_header_size == 4) { 00079 _data_expected = di.get_uint32(); 00080 } 00081 _data_so_far = _data_so_far.substr(_tcp_header_size); 00082 00083 if (_data_expected == 0) { 00084 // Empty datagram. 00085 dg.clear(); 00086 return true; 00087 } 00088 } 00089 00090 // Read the next n bytes until the datagram is filled. 00091 00092 static const size_t buffer_size = 1024; 00093 char buffer[buffer_size]; 00094 00095 size_t read_count = min(_data_expected - _data_so_far.length(), 00096 buffer_size); 00097 _istream->read(buffer, read_count); 00098 size_t count = _istream->gcount(); 00099 while (count != 0) { 00100 _data_so_far.append(buffer, count); 00101 00102 read_count = min(_data_expected - _data_so_far.length(), 00103 buffer_size); 00104 _istream->read(buffer, read_count); 00105 count = _istream->gcount(); 00106 } 00107 00108 if (_data_so_far.length() < _data_expected) { 00109 // Not yet here. Clear the istream error flag and return false to 00110 // indicate more coming. 00111 _istream->clear(); 00112 return false; 00113 } 00114 00115 dg.clear(); 00116 dg.append_data(_data_so_far); 00117 00118 _data_expected = 0; 00119 _data_so_far = string(); 00120 00121 return true; 00122 } 00123 00124 #ifdef SIMULATE_NETWORK_DELAY 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: SSReader::start_delay 00127 // Access: Published 00128 // Description: Enables a simulated network latency. All datagrams 00129 // received from this point on will be held for a random 00130 // interval of least min_delay seconds, and no more than 00131 // max_delay seconds, before being visible. It is as if 00132 // datagrams suddenly took much longer to arrive. 00133 // 00134 // This should *only* be called if the underlying socket 00135 // is non-blocking. If you call this on a blocking 00136 // socket, it will force all datagrams to be held up 00137 // until the socket closes. 00138 //////////////////////////////////////////////////////////////////// 00139 void SSReader:: 00140 start_delay(double min_delay, double max_delay) { 00141 _min_delay = min_delay; 00142 _delay_variance = max(max_delay - min_delay, 0.0); 00143 _delay_active = true; 00144 } 00145 #endif // SIMULATE_NETWORK_DELAY 00146 00147 #ifdef SIMULATE_NETWORK_DELAY 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: SSReader::stop_delay 00150 // Access: Published 00151 // Description: Disables the simulated network latency started by a 00152 // previous call to start_delay(). Datagrams will once 00153 // again be visible as soon as they are received. 00154 //////////////////////////////////////////////////////////////////// 00155 void SSReader:: 00156 stop_delay() { 00157 _delay_active = false; 00158 } 00159 #endif // SIMULATE_NETWORK_DELAY 00160 00161 #ifdef SIMULATE_NETWORK_DELAY 00162 //////////////////////////////////////////////////////////////////// 00163 // Function: SSReader::delay_datagram 00164 // Access: Private 00165 // Description: Adds the datagram to the delay queue for a random 00166 // time interval. 00167 //////////////////////////////////////////////////////////////////// 00168 void SSReader:: 00169 delay_datagram(const Datagram &datagram) { 00170 nassertv(_delay_active); 00171 00172 double now = TrueClock::get_global_ptr()->get_short_time(); 00173 double reveal_time = now + _min_delay; 00174 00175 if (_delay_variance > 0.0) { 00176 reveal_time += _delay_variance * ((double)rand() / (double)RAND_MAX); 00177 } 00178 _delayed.push_back(DelayedDatagram()); 00179 DelayedDatagram &dd = _delayed.back(); 00180 dd._reveal_time = reveal_time; 00181 dd._datagram = datagram; 00182 } 00183 #endif // SIMULATE_NETWORK_DELAY 00184 00185 #ifdef SIMULATE_NETWORK_DELAY 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: SSReader::get_delayed 00188 // Access: Private 00189 // Description: Checks the delayed queue for any now available 00190 // datagrams. If any are available, returns true and 00191 // fills datagram with its value. 00192 //////////////////////////////////////////////////////////////////// 00193 bool SSReader:: 00194 get_delayed(Datagram &datagram) { 00195 if (_delayed.empty()) { 00196 return false; 00197 } 00198 const DelayedDatagram &dd = _delayed.front(); 00199 if (_delay_active) { 00200 double now = TrueClock::get_global_ptr()->get_short_time(); 00201 if (dd._reveal_time > now) { 00202 // Not yet. 00203 return false; 00204 } 00205 } 00206 00207 datagram = dd._datagram; 00208 _delayed.pop_front(); 00209 00210 return true; 00211 } 00212 #endif // SIMULATE_NETWORK_DELAY 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: SSWriter::Constructor 00216 // Access: Public 00217 // Description: 00218 //////////////////////////////////////////////////////////////////// 00219 SSWriter:: 00220 SSWriter(ostream *stream) : _ostream(stream) { 00221 _collect_tcp = collect_tcp; 00222 _collect_tcp_interval = collect_tcp_interval; 00223 _queued_data_start = 0.0; 00224 _tcp_header_size = tcp_header_size; 00225 } 00226 00227 //////////////////////////////////////////////////////////////////// 00228 // Function: SSWriter::Destructor 00229 // Access: Public, Virtual 00230 // Description: 00231 //////////////////////////////////////////////////////////////////// 00232 SSWriter:: 00233 ~SSWriter() { 00234 } 00235 00236 //////////////////////////////////////////////////////////////////// 00237 // Function: SSWriter::send_datagram 00238 // Access: Public 00239 // Description: Transmits the indicated datagram over the socket by 00240 // prepending it with a little-endian 16-bit byte count. 00241 // Does not return until the data is sent or the 00242 // connection is closed, even if the socket stream is 00243 // non-blocking. 00244 //////////////////////////////////////////////////////////////////// 00245 bool SSWriter:: 00246 send_datagram(const Datagram &dg) { 00247 Datagram header; 00248 if (_tcp_header_size == 2) { 00249 if (dg.get_length() >= 0x10000) { 00250 downloader_cat.error() 00251 << "Attempt to send TCP datagram of " << dg.get_length() 00252 << " bytes--too long!\n"; 00253 nassert_raise("Datagram too long"); 00254 return false; 00255 } 00256 00257 header.add_uint16(dg.get_length()); 00258 } else if (_tcp_header_size == 4) { 00259 header.add_uint32(dg.get_length()); 00260 } 00261 00262 // These two writes don't generate two socket calls, because the 00263 // socket stream is always buffered. 00264 _ostream->write((const char *)header.get_data(), header.get_length()); 00265 _ostream->write((const char *)dg.get_data(), dg.get_length()); 00266 00267 // Now flush the buffer immediately, forcing the data to be sent 00268 // (unless collect-tcp mode is in effect). 00269 flush(); 00270 00271 return !is_closed(); 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: ISocketStream::Destructor 00276 // Access: Published, Virtual 00277 // Description: 00278 //////////////////////////////////////////////////////////////////// 00279 ISocketStream:: 00280 ~ISocketStream() { 00281 // This should already have been cleared by the subclass destructor. 00282 nassertv(_channel == NULL); 00283 } 00284 00285 #endif // HAVE_OPENSSL