// Filename: socketStream.I // Created by: drose (15Oct02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: SSReader::receive_datagram // Access: Published // 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. //////////////////////////////////////////////////////////////////// INLINE bool SSReader:: receive_datagram(Datagram &dg) { #ifdef SIMULATE_NETWORK_DELAY if (_delay_active) { while (do_receive_datagram(dg)) { delay_datagram(dg); } return get_delayed(dg); } // Pick up any datagrams that might have been leftover in the queue // when we disabled the delay. if (get_delayed(dg)) { return true; } #endif // SIMULATE_NETWORK_DELAY return do_receive_datagram(dg); } //////////////////////////////////////////////////////////////////// // Function: SSReader::set_tcp_header_size // Access: Published // Description: Sets the header size for datagrams. At the present, // legal values for this are 0, 2, or 4; this specifies // the number of bytes to use encode the datagram length // at the start of each TCP datagram. Sender and // receiver must independently agree on this. //////////////////////////////////////////////////////////////////// INLINE void SSReader:: set_tcp_header_size(int tcp_header_size) { nassertv(tcp_header_size == 0 || tcp_header_size == 2 || tcp_header_size == 4); _tcp_header_size = tcp_header_size; } //////////////////////////////////////////////////////////////////// // Function: SSReader::get_tcp_header_size // Access: Published // Description: Returns the header size for datagrams. See // set_tcp_header_size(). //////////////////////////////////////////////////////////////////// INLINE int SSReader:: get_tcp_header_size() const { return _tcp_header_size; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::set_collect_tcp // Access: Published // Description: Enables or disables "collect-tcp" mode. In this // mode, individual TCP packets are not sent // immediately, but rather they are collected together // and accumulated to be sent periodically as one larger // TCP packet. This cuts down on overhead from the // TCP/IP protocol, especially if many small packets // need to be sent on the same connection, but it // introduces additional latency (since packets must be // held before they can be sent). // // See set_collect_tcp_interval() to specify the // interval of time for which to hold packets before // sending them. // // If you enable this mode, you may also need to // periodically call consider_flush() to flush the queue // if no packets have been sent recently. //////////////////////////////////////////////////////////////////// INLINE void SSWriter:: set_collect_tcp(bool collect_tcp) { _collect_tcp = collect_tcp; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::get_collect_tcp // Access: Published // Description: Returns the current setting of "collect-tcp" mode. // See set_collect_tcp(). //////////////////////////////////////////////////////////////////// INLINE bool SSWriter:: get_collect_tcp() const { return _collect_tcp; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::set_collect_tcp_interval // Access: Published // Description: Specifies the interval in time, in seconds, for which // to hold TCP packets before sending all of the // recently received packets at once. This only has // meaning if "collect-tcp" mode is enabled; see // set_collect_tcp(). //////////////////////////////////////////////////////////////////// INLINE void SSWriter:: set_collect_tcp_interval(double interval) { _collect_tcp_interval = interval; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::get_collect_tcp_interval // Access: Published // Description: Returns the interval in time, in seconds, for which // to hold TCP packets before sending all of the // recently received packets at once. This only has // meaning if "collect-tcp" mode is enabled; see // set_collect_tcp(). //////////////////////////////////////////////////////////////////// INLINE double SSWriter:: get_collect_tcp_interval() const { return _collect_tcp_interval; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::set_tcp_header_size // Access: Published // Description: Sets the header size for datagrams. At the present, // legal values for this are 0, 2, or 4; this specifies // the number of bytes to use encode the datagram length // at the start of each TCP datagram. Sender and // receiver must independently agree on this. //////////////////////////////////////////////////////////////////// INLINE void SSWriter:: set_tcp_header_size(int tcp_header_size) { nassertv(tcp_header_size == 0 || tcp_header_size == 2 || tcp_header_size == 4); _tcp_header_size = tcp_header_size; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::get_tcp_header_size // Access: Published // Description: Returns the header size for datagrams. See // set_tcp_header_size(). //////////////////////////////////////////////////////////////////// INLINE int SSWriter:: get_tcp_header_size() const { return _tcp_header_size; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::consider_flush // Access: Published // Description: Sends the most recently queued data if enough time // has elapsed. This only has meaning if // set_collect_tcp() has been set to true. //////////////////////////////////////////////////////////////////// INLINE bool SSWriter:: consider_flush() { if (!_collect_tcp) { return flush(); } else { double elapsed = TrueClock::get_global_ptr()->get_short_time() - _queued_data_start; // If the elapsed time is negative, someone must have reset the // clock back, so just go ahead and flush. if (elapsed < 0.0 || elapsed >= _collect_tcp_interval) { return flush(); } } return true; } //////////////////////////////////////////////////////////////////// // Function: SSWriter::flush // Access: Published // Description: Sends the most recently queued data now. This only // has meaning if set_collect_tcp() has been set to // true. //////////////////////////////////////////////////////////////////// INLINE bool SSWriter:: flush() { _ostream->flush(); _queued_data_start = TrueClock::get_global_ptr()->get_short_time(); return !is_closed(); } //////////////////////////////////////////////////////////////////// // Function: ISocketStream::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE ISocketStream:: ISocketStream(streambuf *buf) : istream(buf), SSReader(this) { _channel = NULL; } //////////////////////////////////////////////////////////////////// // Function: OSocketStream::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE OSocketStream:: OSocketStream(streambuf *buf) : ostream(buf), SSWriter(this) { } //////////////////////////////////////////////////////////////////// // Function: OSocketStream::flush // Access: Published // Description: Sends the most recently queued data now. This only // has meaning if set_collect_tcp() has been set to // true. //////////////////////////////////////////////////////////////////// INLINE bool OSocketStream:: flush() { return SSWriter::flush(); } //////////////////////////////////////////////////////////////////// // Function: SocketStream::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE SocketStream:: SocketStream(streambuf *buf) : iostream(buf), SSReader(this), SSWriter(this) { } //////////////////////////////////////////////////////////////////// // Function: SocketStream::set_tcp_header_size // Access: Published // Description: Sets the header size for datagrams. At the present, // legal values for this are 0, 2, or 4; this specifies // the number of bytes to use encode the datagram length // at the start of each TCP datagram. Sender and // receiver must independently agree on this. //////////////////////////////////////////////////////////////////// INLINE void SocketStream:: set_tcp_header_size(int tcp_header_size) { SSReader::set_tcp_header_size(tcp_header_size); SSWriter::set_tcp_header_size(tcp_header_size); } //////////////////////////////////////////////////////////////////// // Function: SocketStream::get_tcp_header_size // Access: Published // Description: Returns the header size for datagrams. See // set_tcp_header_size(). //////////////////////////////////////////////////////////////////// INLINE int SocketStream:: get_tcp_header_size() const { return SSReader::get_tcp_header_size(); } //////////////////////////////////////////////////////////////////// // Function: SocketStream::flush // Access: Published // Description: Sends the most recently queued data now. This only // has meaning if set_collect_tcp() has been set to // true. //////////////////////////////////////////////////////////////////// INLINE bool SocketStream:: flush() { return SSWriter::flush(); }