00001 // Filename: socketStream.cxx 00002 // Created by: drose (19Oct02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "socketStream.h" 00020 #include "datagram.h" 00021 #include "datagramIterator.h" 00022 00023 #ifdef HAVE_SSL 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: ISocketStream::receive_datagram 00027 // Access: Public 00028 // Description: Receives a datagram over the socket by expecting a 00029 // little-endian 16-bit byte count as a prefix. If the 00030 // socket stream is non-blocking, may return false if 00031 // the data is not available; otherwise, returns false 00032 // only if the socket closes. 00033 //////////////////////////////////////////////////////////////////// 00034 bool ISocketStream:: 00035 receive_datagram(Datagram &dg) { 00036 if (_data_expected == 0) { 00037 // Read the first two bytes: the datagram length. 00038 while (_data_so_far.length() < 2) { 00039 int ch = get(); 00040 if (eof()) { 00041 clear(); 00042 return false; 00043 } 00044 _data_so_far += (char)ch; 00045 } 00046 00047 Datagram header(_data_so_far); 00048 DatagramIterator di(header); 00049 _data_expected = di.get_uint16(); 00050 _data_so_far = string(); 00051 00052 if (_data_expected == 0) { 00053 // Empty datagram. 00054 dg.clear(); 00055 return true; 00056 } 00057 } 00058 00059 // Read the next n bytes until the datagram is filled. 00060 while (_data_so_far.length() < _data_expected) { 00061 int ch = get(); 00062 if (eof()) { 00063 clear(); 00064 return false; 00065 } 00066 _data_so_far += (char)ch; 00067 } 00068 00069 dg.clear(); 00070 dg.append_data(_data_so_far); 00071 00072 _data_expected = 0; 00073 _data_so_far = string(); 00074 return true; 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: OSocketStream::send_datagram 00079 // Access: Public 00080 // Description: Transmits the indicated datagram over the socket by 00081 // prepending it with a little-endian 16-bit byte count. 00082 // Does not return until the data is sent or the 00083 // connection is closed, even if the socket stream is 00084 // non-blocking. 00085 //////////////////////////////////////////////////////////////////// 00086 bool OSocketStream:: 00087 send_datagram(const Datagram &dg) { 00088 Datagram header; 00089 header.add_uint16(dg.get_length()); 00090 write((const char *)header.get_data(), header.get_length()); 00091 write((const char *)dg.get_data(), dg.get_length()); 00092 flush(); 00093 00094 return !is_closed(); 00095 } 00096 00097 //////////////////////////////////////////////////////////////////// 00098 // Function: SocketStream::receive_datagram 00099 // Access: Public 00100 // Description: Receives a datagram over the socket by expecting a 00101 // little-endian 16-bit byte count as a prefix. If the 00102 // socket stream is non-blocking, may return false if 00103 // the data is not available; otherwise, returns false 00104 // only if the socket closes. 00105 //////////////////////////////////////////////////////////////////// 00106 bool SocketStream:: 00107 receive_datagram(Datagram &dg) { 00108 if (_data_expected == 0) { 00109 // Read the first two bytes: the datagram length. 00110 while (_data_so_far.length() < 2) { 00111 int ch = get(); 00112 if (eof()) { 00113 clear(); 00114 return false; 00115 } 00116 _data_so_far += (char)ch; 00117 } 00118 00119 Datagram header(_data_so_far); 00120 DatagramIterator di(header); 00121 _data_expected = di.get_uint16(); 00122 _data_so_far = string(); 00123 00124 if (_data_expected == 0) { 00125 // Empty datagram. 00126 dg.clear(); 00127 return true; 00128 } 00129 } 00130 00131 // Read the next n bytes until the datagram is filled. 00132 while (_data_so_far.length() < _data_expected) { 00133 int ch = get(); 00134 if (eof()) { 00135 clear(); 00136 return false; 00137 } 00138 _data_so_far += (char)ch; 00139 } 00140 00141 dg.clear(); 00142 dg.append_data(_data_so_far); 00143 00144 _data_expected = 0; 00145 _data_so_far = string(); 00146 return true; 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: SocketStream::send_datagram 00151 // Access: Public 00152 // Description: Transmits the indicated datagram over the socket by 00153 // prepending it with a little-endian 16-bit byte count. 00154 // Does not return until the data is sent or the 00155 // connection is closed, even if the socket stream is 00156 // non-blocking. 00157 //////////////////////////////////////////////////////////////////// 00158 bool SocketStream:: 00159 send_datagram(const Datagram &dg) { 00160 Datagram header; 00161 header.add_uint16(dg.get_length()); 00162 00163 // These two writes don't generate two socket calls, because the 00164 // socket stream is always buffered. 00165 write((const char *)header.get_data(), header.get_length()); 00166 write((const char *)dg.get_data(), dg.get_length()); 00167 00168 // Now flush the buffer immediately, forcing the data to be sent 00169 // (unless collect-tcp mode is in effect). 00170 return consider_flush(); 00171 } 00172 00173 #endif // HAVE_SSL