00001 #ifndef __NONECLOCKING_CONNECTTION_H_
00002 #define __NONECLOCKING_CONNECTTION_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "pandabase.h"
00015 #include "socket_base.h"
00016 #include "datagram.h"
00017 #include "pvector.h"
00018 #include "buffered_datagramreader.h"
00019 #include "buffered_datagramwriter.h"
00020 #include "config_nativenet.h"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 class EXPCL_PANDA_NATIVENET Buffered_DatagramConnection : public Socket_TCP
00032 {
00033 private:
00034 struct AddressQueue : private pvector<Socket_Address>
00035 {
00036 size_t _active_index;
00037 bool GetNext(Socket_Address &out)
00038 {
00039 size_t the_size = size();
00040 if(the_size == 0)
00041 return false;
00042
00043 if(_active_index >= the_size || _active_index < 0)
00044 _active_index = 0;
00045 out = (*this)[_active_index++];
00046 return true;
00047 }
00048
00049 void clear() { pvector<Socket_Address>::clear(); };
00050 void push_back(Socket_Address &address)
00051 {
00052 iterator ii;
00053 for(ii = begin(); ii != end(); ii++)
00054 if(*ii == address)
00055 return;
00056 pvector<Socket_Address>::push_back(address);
00057 }
00058
00059 size_t size() { return pvector<Socket_Address>::size(); };
00060 };
00061 protected:
00062
00063 virtual void PostConnect(void) { };
00064 virtual void NewWriteBuffer(void) { };
00065
00066 inline void ClearAll(void);
00067
00068 inline bool SendMessageBufferOnly(Datagram &msg);
00069 PUBLISHED:
00070 inline bool GetMessage(Datagram &val);
00071 inline bool DoConnect(void);
00072 inline bool IsConnected(void);
00073 inline Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point) ;
00074 virtual ~Buffered_DatagramConnection(void) ;
00075
00076 inline bool SendMessage(const Datagram &msg);
00077 inline bool Flush(void);
00078 inline void Reset(void);
00079
00080
00081
00082 inline void WaitForNetworkReadEvent(PN_stdfloat MaxTime)
00083 {
00084 Socket_fdset fdset;
00085 fdset.setForSocket(*this);
00086 Socket_Selector selector;
00087 Time_Span waittime(MaxTime);
00088 selector.WaitFor_Read_Error(fdset,waittime);
00089 }
00090
00091
00092
00093 inline size_t AddressQueueSize() { return _Addresslist.size(); };
00094 inline void AddAddress(Socket_Address &inadr);
00095 inline void ClearAddresses(void);
00096 private:
00097 Buffered_DatagramWriter _Writer;
00098 Buffered_DatagramReader _Reader;
00099 AddressQueue _Addresslist;
00100 Socket_Address _Adddress;
00101
00102 friend class Buffered_DatagramReader;
00103 friend class Buffered_DatagramWriter;
00104
00105 public:
00106 static TypeHandle get_class_type() {
00107 return _type_handle;
00108 }
00109 static void init_type() {
00110 Socket_IP::init_type();
00111 register_type(_type_handle, "Buffered_DatagramConnection",
00112 Socket_IP::get_class_type());
00113 }
00114 virtual TypeHandle get_type() const {
00115 return get_class_type();
00116 }
00117 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00118
00119 private:
00120 static TypeHandle _type_handle;
00121 };
00122
00123
00124
00125
00126
00127
00128
00129
00130 inline void Buffered_DatagramConnection::ClearAll(void) {
00131 nativenet_cat.error() << "Buffered_DatagramConnection::ClearAll Starting Auto Reset\n";
00132 Close();
00133 _Writer.ReSet();
00134 _Reader.ReSet();
00135 }
00136
00137 inline bool Buffered_DatagramConnection::DoConnect(void) {
00138 if(!_Addresslist.GetNext(_Adddress))
00139 return false;
00140
00141 if(ActiveOpen(_Adddress,true) == true) {
00142 SetNoDelay();
00143 SetNonBlocking();
00144 NewWriteBuffer();
00145 return true;
00146 }
00147
00148 return false;
00149
00150 }
00151
00152
00153
00154 // Function name : Buffered_DatagramConnection::DoConnect
00155 // Description : This is the function thah does the conection for us
00156 //
00157 // Return type : inline bool
00158 // Argument : void
00159
00160 inline bool Buffered_DatagramConnection::DoConnect(void) {
00161 if(Active() != true) {
00162 if(_LastConnectTry.Expired() != true)
00163 return true;
00164
00165 if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
00166 return false;
00167
00168 if(ActiveOpen(_Adddress) == true) {
00169 _LastConnectTry.ReStart();
00170 _tryingToOpen = true; // set the flag indicating we are trying to open up
00171 SetNonBlocking(); // maybe should be blocking?
00172 SetSendBufferSize(1024*50); // we need to hand tune these for the os we are using
00173 SetRecvBufferSize(1024*50);
00174 NewWriteBuffer();
00175 return true;
00176 }
00177
00178 return true;
00179 }
00180
00181 if(_tryingToOpen) { // okay handle the i am connecting state....
00182 Socket_fdset fdset;
00183 fdset.setForSocket(*this);
00184 Socket_Selector selector;
00185 if(selector.WaitFor_All(fdset,0) >0) {
00186 _tryingToOpen = false;
00187 if(selector._error.IsSetFor(*this) == true) { // means we are in errorconnected. else writable
00188 ClearAll();
00189 return false; // error on connect
00190 }
00191 PostConnect();
00192 return true; // just got connected
00193 }
00194 return true; // still connecting
00195 }
00196 return true;
00197 }
00198
00199 */
00200
00201
00202
00203
00204
00205
00206
00207
00208 inline Buffered_DatagramConnection::~Buffered_DatagramConnection(void)
00209 {
00210 Close();
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 inline Buffered_DatagramConnection::Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point)
00222 : _Writer(wbufsize,write_flush_point) , _Reader(rbufsize)
00223 {
00224 nativenet_cat.error() << "Buffered_DatagramConnection Constructor rbufsize = " << rbufsize
00225 << " wbufsize = " << wbufsize << " write_flush_point = " << write_flush_point << "\n";
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 inline bool Buffered_DatagramConnection::SendMessage(const Datagram &msg)
00235 {
00236 if(IsConnected()) {
00237
00238 int val = 0;
00239 val = _Writer.AddData(msg.get_data(),msg.get_length(),*this);
00240 if(val >= 0)
00241 return true;
00242
00243 nativenet_cat.warning() << "Buffered_DatagramConnection::SendMessage->Error On Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
00244 #ifdef HAVE_PYTHON
00245 ostringstream s;
00246 PyObject *exc_type = PyExc_StandardError;
00247
00248 s << endl << "Error sending message: " << endl;
00249 msg.dump_hex(s);
00250
00251 s << "Message data: " << msg.get_data() << endl;
00252
00253 string message = s.str();
00254 PyErr_SetString(exc_type, message.c_str());
00255 #endif
00256
00257 ClearAll();
00258 }
00259 return false;
00260 }
00261
00262 inline bool Buffered_DatagramConnection::SendMessageBufferOnly(Datagram &msg)
00263 {
00264 int val = _Writer.AddData(msg.get_data(),msg.get_length());
00265 if(val >= 0)
00266 return true;
00267
00268 nativenet_cat.error() << "Buffered_DatagramConnection::SendMessageBufferOnly->Error On Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
00269 ClearAll();
00270 return false;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 inline void Buffered_DatagramConnection::AddAddress(Socket_Address &inadr)
00281 {
00282 _Addresslist.push_back(inadr);
00283 }
00284
00285 inline void Buffered_DatagramConnection::ClearAddresses(void)
00286 {
00287 _Addresslist.clear();
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 inline bool Buffered_DatagramConnection::GetMessage(Datagram &val)
00300 {
00301 if(IsConnected())
00302 {
00303 int ans1 = _Reader.PumpMessageReader(val,*this);
00304 if(ans1 == 0)
00305 return false;
00306 if(ans1 <0) {
00307 nativenet_cat.error() << "Buffered_DatagramConnection::GetMessage->Error On PumpMessageReader--Out Buffer = " << _Writer.AmountBuffered() << "\n";
00308 ClearAll();
00309 return false;
00310 }
00311 return true;
00312 }
00313 return false;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 bool Buffered_DatagramConnection::Flush(void)
00326 {
00327 if (IsConnected())
00328 {
00329 int flush_resp = _Writer.FlushNoBlock(*this);
00330 if(flush_resp < 0)
00331 {
00332 nativenet_cat.error() << "Buffered_DatagramConnection::Flush->Error On Flush [" <<GetLastError() << "]\n"
00333
00334 << "Buffered_DatagramConnection::Flush->Error ..Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
00335 ClearAll();
00336 return false;
00337 }
00338 return true;
00339 }
00340 return false;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 inline void Buffered_DatagramConnection::Reset()
00350 {
00351 nativenet_cat.error() << "Buffered_DatagramConnection::Reset()\n";
00352 ClearAll();
00353 };
00354
00355
00356 inline bool Buffered_DatagramConnection::IsConnected(void) {
00357 return ( Active() == true );
00358 }
00359
00360
00361 #endif //__NONECLOCKING_CONNECTTION_H_
00362