Panda3D
buffered_datagramconnection.h
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 buffered_datagramconnection.h
10  * @author drose
11  * @date 2007-03-05
12  */
13 
14 
15 #ifndef __BUFFERED_DATAGRAM_CONNECTION_H__
16 #define __BUFFERED_DATAGRAM_CONNECTION_H__
17 /*
18  * Ok here is the base behavior.. A message IO engin that is Smart enough to
19  * Do 1. Non Blocking Connect .. and Buffer the writes if needed 2. Handle 1
20  * to N targets for the connection.. 3. Handle Framing and Unframing properly
21  * ..
22  */
23 
24 #include "pandabase.h"
25 #include "socket_base.h"
26 #include "datagram.h"
27 #include "pvector.h"
28 #include "buffered_datagramreader.h"
29 #include "buffered_datagramwriter.h"
30 #include "config_nativenet.h"
31 
32 // there are 3 states 1. Socket not even assigned,,,, 2. Socket Assigned and
33 // trying to get a active connect open 3. Socket is open and writable.. (
34 // Fully powered up )...
35 class EXPCL_PANDA_NATIVENET Buffered_DatagramConnection : public Socket_TCP
36 {
37 private:
38  struct AddressQueue : private pvector<Socket_Address> // this is used to do a round robin for addres to connect to ..
39  {
40  size_t _active_index;
41 
42  INLINE AddressQueue() : _active_index(0) {}
43 
44  bool GetNext(Socket_Address &out) {
45  size_t the_size = size();
46  if (the_size == 0) {
47  return false;
48  }
49 
50  if (_active_index >= the_size) {
51  _active_index = 0;
52  }
53 
54  out = (*this)[_active_index++];
55  return true;
56  }
57 
58  INLINE void clear() {
60  }
61 
62  void push_back(Socket_Address &address) {
63  iterator ii;
64  for(ii = begin(); ii != end(); ii++)
65  if(*ii == address)
66  return;
68  }
69 
70  size_t size() { return pvector<Socket_Address>::size(); };
71  };
72 
73 protected:
74  // c++ upcalls for
75  virtual void PostConnect(void) { };
76  virtual void NewWriteBuffer(void) { };
77 
78  inline void ClearAll(void);
79 
80  inline bool SendMessageBufferOnly(Datagram &msg); // do not use this .. this is a way for the the COnnecting UPcall to drop messages in queue first..
81 PUBLISHED:
82  inline bool GetMessage(Datagram &val);
83  inline bool DoConnect(void); // all the real state magic is in here
84  inline bool IsConnected(void);
85  inline explicit Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point) ;
86  virtual ~Buffered_DatagramConnection(void) ;
87  // the reason thsi all exists
88  bool SendMessage(const Datagram &msg);
89  inline bool Flush(void);
90  inline void Reset(void);
91 
92  // int WaitFor_Read_Error(const Socket_fdset & fd, const Time_Span &
93  // timeout);
94 
95  inline void WaitForNetworkReadEvent(PN_stdfloat MaxTime)
96  {
97  Socket_fdset fdset;
98  fdset.setForSocket(*this);
99  Socket_Selector selector;
100  Time_Span waittime(MaxTime);
101  selector.WaitFor_Read_Error(fdset,waittime);
102  }
103 
104  // address queue stuff
105  inline size_t AddressQueueSize() { return _Addresslist.size(); };
106  inline void AddAddress(Socket_Address &inadr);
107  inline void ClearAddresses(void);
108 private:
109  Buffered_DatagramWriter _Writer; // buffered writing
110  Buffered_DatagramReader _Reader; // buffered reader
111  AddressQueue _Addresslist; // the location of the round robin address list
112  Socket_Address _Adddress; // the conection address ( active one from list being used)
113 
114  friend class Buffered_DatagramReader;
115  friend class Buffered_DatagramWriter;
116 
117 public:
118  static TypeHandle get_class_type() {
119  return _type_handle;
120  }
121  static void init_type() {
122  Socket_IP::init_type();
123  register_type(_type_handle, "Buffered_DatagramConnection",
124  Socket_IP::get_class_type());
125  }
126  virtual TypeHandle get_type() const {
127  return get_class_type();
128  }
129  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
130 
131 private:
132  static TypeHandle _type_handle;
133 };
134 
135 /**
136  * used to do a full reset of buffers
137  */
138 inline void Buffered_DatagramConnection::ClearAll(void) {
139  nativenet_cat.error() << "Buffered_DatagramConnection::ClearAll Starting Auto Reset\n";
140  Close();
141  _Writer.ReSet();
142  _Reader.ReSet();
143 }
144 
145 inline bool Buffered_DatagramConnection::DoConnect(void) {
146  if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
147  return false;
148 
149  if(ActiveOpen(_Adddress,true) == true) {
150  SetNoDelay();
151  SetNonBlocking(); // maybe should be blocking?
152  NewWriteBuffer();
153  return true;
154  }
155 
156  return false;
157 
158 }
159 
160 /**
161  * This is the function that does the connection for us
162  */
163 /*
164 inline bool Buffered_DatagramConnection::DoConnect(void) {
165  if(Active() != true) {
166  if(_LastConnectTry.Expired() != true)
167  return true;
168 
169  if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
170  return false;
171 
172  if(ActiveOpen(_Adddress) == true) {
173  _LastConnectTry.ReStart();
174  _tryingToOpen = true; // set the flag indicating we are trying to open up
175  SetNonBlocking(); // maybe should be blocking?
176  SetSendBufferSize(1024*50); // we need to hand tune these for the os we are using
177  SetRecvBufferSize(1024*50);
178  NewWriteBuffer();
179  return true;
180  }
181 
182  return true;
183  }
184 
185  if(_tryingToOpen) { // okay handle the i am connecting state....
186  Socket_fdset fdset;
187  fdset.setForSocket(*this);
188  Socket_Selector selector;
189  if(selector.WaitFor_All(fdset,0) >0) {
190  _tryingToOpen = false;
191  if(selector._error.IsSetFor(*this) == true) { // means we are in errorconnected. else writable
192  ClearAll();
193  return false; // error on connect
194  }
195  PostConnect();
196  return true; // just got connected
197  }
198  return true; // still connecting
199  }
200  return true;
201 }
202 
203 */
204 
205 /**
206  *
207  */
209 {
210  Close();
211 }
212 /**
213  *
214  */
215 inline Buffered_DatagramConnection::Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point)
216  : _Writer(wbufsize,write_flush_point) , _Reader(rbufsize)
217 {
218  nativenet_cat.error() << "Buffered_DatagramConnection Constructor rbufsize = " << rbufsize
219  << " wbufsize = " << wbufsize << " write_flush_point = " << write_flush_point << "\n";
220 }
221 
222 inline bool Buffered_DatagramConnection::SendMessageBufferOnly(Datagram &msg)
223 {
224  int val = _Writer.AddData(msg.get_data(),msg.get_length());
225  if(val >= 0)
226  return true;
227 
228  nativenet_cat.error() << "Buffered_DatagramConnection::SendMessageBufferOnly->Error On Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
229  ClearAll();
230  return false;
231 }
232 
233 /**
234  * must be called to set value to the server
235  */
237 {
238  _Addresslist.push_back(inadr);
239 }
240 
241 inline void Buffered_DatagramConnection::ClearAddresses(void)
242 {
243  _Addresslist.clear();
244 }
245 /**
246  * Reads a message. Returns false on failure.
247  */
249 {
250  if(IsConnected())
251  {
252  int ans1 = _Reader.PumpMessageReader(val,*this);
253  if(ans1 == 0)
254  return false;
255  if(ans1 <0) {
256  nativenet_cat.error() << "Buffered_DatagramConnection::GetMessage->Error On PumpMessageReader--Out Buffer = " << _Writer.AmountBuffered() << "\n";
257  ClearAll();
258  return false;
259  }
260  return true;
261  }
262  return false;
263 }
264 
265 
266 
267 /**
268  * Flush all writes.
269  */
271 {
272  if (IsConnected())
273  {
274  int flush_resp = _Writer.FlushNoBlock(*this);
275  if(flush_resp < 0)
276  {
277  nativenet_cat.error() << "Buffered_DatagramConnection::Flush->Error On Flush [" <<GetLastError() << "]\n"
278 
279  << "Buffered_DatagramConnection::Flush->Error ..Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
280  ClearAll();
281  return false;
282  }
283  return true;
284  }
285  return false;
286 }
287 
288 /**
289  * Reset
290  */
292  nativenet_cat.error() << "Buffered_DatagramConnection::Reset()\n";
293  ClearAll();
294 }
295 
296 inline bool Buffered_DatagramConnection::IsConnected(void) {
297  return (Active() == true);
298 }
299 
300 #endif //__BUFFERED_DATAGRAM_CONNECTION_H__
void AddAddress(Socket_Address &inadr)
must be called to set value to the server
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition: socket_tcp.h:12
int SetNonBlocking()
this function will throw a socket into non-blocking mode
Definition: socket_ip.h:169
void ReSet(void)
Reset all read content, ie.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool Active()
Ask if the socket is open (allocated)
Definition: socket_ip.h:96
bool Flush(void)
Flush all writes.
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
bool GetMessage(Datagram &val)
Reads a message.
size_t AmountBuffered(void)
Will report the number of unread chars in buffer.
Definition: ringbuffer.I:32
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A simple place to store and manipulate tcp and port address for communication layer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
This is the buffered writer.
virtual ~Buffered_DatagramConnection(void)
This is the function that does the connection for us.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
int WaitFor_Read_Error(const Socket_fdset &fd, const Time_Span &timeout)
Helper function for WaitFor Only looks for readability and errors.
bool ActiveOpen(const Socket_Address &theaddress, bool setdelay)
This function will try and set the socket up for active open to a specified address and port provided...
Definition: socket_tcp.h:119
void ReSet(void)
used to clear the buffrers ...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
int SetNoDelay(bool flag=true)
Disable Nagle algorithm.
Definition: socket_tcp.h:62
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327