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  if (nativenet_cat.is_debug()) {
140  nativenet_cat.debug()
141  << "Buffered_DatagramConnection::ClearAll Starting Auto Reset\n";
142  }
143  Close();
144  _Writer.ReSet();
145  _Reader.ReSet();
146 }
147 
148 inline bool Buffered_DatagramConnection::DoConnect(void) {
149  if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
150  return false;
151 
152  if(ActiveOpen(_Adddress,true) == true) {
153  SetNoDelay();
154  SetNonBlocking(); // maybe should be blocking?
155  NewWriteBuffer();
156  return true;
157  }
158 
159  return false;
160 
161 }
162 
163 /**
164  * This is the function that does the connection for us
165  */
166 /*
167 inline bool Buffered_DatagramConnection::DoConnect(void) {
168  if(Active() != true) {
169  if(_LastConnectTry.Expired() != true)
170  return true;
171 
172  if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
173  return false;
174 
175  if(ActiveOpen(_Adddress) == true) {
176  _LastConnectTry.ReStart();
177  _tryingToOpen = true; // set the flag indicating we are trying to open up
178  SetNonBlocking(); // maybe should be blocking?
179  SetSendBufferSize(1024*50); // we need to hand tune these for the os we are using
180  SetRecvBufferSize(1024*50);
181  NewWriteBuffer();
182  return true;
183  }
184 
185  return true;
186  }
187 
188  if(_tryingToOpen) { // okay handle the i am connecting state....
189  Socket_fdset fdset;
190  fdset.setForSocket(*this);
191  Socket_Selector selector;
192  if(selector.WaitFor_All(fdset,0) >0) {
193  _tryingToOpen = false;
194  if(selector._error.IsSetFor(*this) == true) { // means we are in errorconnected. else writable
195  ClearAll();
196  return false; // error on connect
197  }
198  PostConnect();
199  return true; // just got connected
200  }
201  return true; // still connecting
202  }
203  return true;
204 }
205 
206 */
207 
208 /**
209  *
210  */
212 {
213  Close();
214 }
215 /**
216  *
217  */
218 inline Buffered_DatagramConnection::Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point)
219  : _Writer(wbufsize,write_flush_point) , _Reader(rbufsize)
220 {
221  if (nativenet_cat.is_debug()) {
222  nativenet_cat.debug()
223  << "Buffered_DatagramConnection Constructor rbufsize = " << rbufsize
224  << " wbufsize = " << wbufsize << " write_flush_point = " << write_flush_point << "\n";
225  }
226 }
227 
228 inline bool Buffered_DatagramConnection::SendMessageBufferOnly(Datagram &msg)
229 {
230  int val = _Writer.AddData(msg.get_data(),msg.get_length());
231  if(val >= 0)
232  return true;
233 
234  nativenet_cat.error() << "Buffered_DatagramConnection::SendMessageBufferOnly->Error On Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
235  ClearAll();
236  return false;
237 }
238 
239 /**
240  * must be called to set value to the server
241  */
243 {
244  _Addresslist.push_back(inadr);
245 }
246 
247 inline void Buffered_DatagramConnection::ClearAddresses(void)
248 {
249  _Addresslist.clear();
250 }
251 /**
252  * Reads a message. Returns false on failure.
253  */
255 {
256  if(IsConnected())
257  {
258  int ans1 = _Reader.PumpMessageReader(val,*this);
259  if(ans1 == 0)
260  return false;
261  if(ans1 <0) {
262  nativenet_cat.error() << "Buffered_DatagramConnection::GetMessage->Error On PumpMessageReader--Out Buffer = " << _Writer.AmountBuffered() << "\n";
263  ClearAll();
264  return false;
265  }
266  return true;
267  }
268  return false;
269 }
270 
271 
272 
273 /**
274  * Flush all writes.
275  */
277 {
278  if (IsConnected())
279  {
280  int flush_resp = _Writer.FlushNoBlock(*this);
281  if(flush_resp < 0)
282  {
283  nativenet_cat.error() << "Buffered_DatagramConnection::Flush->Error On Flush [" <<GetLastError() << "]\n"
284 
285  << "Buffered_DatagramConnection::Flush->Error ..Write--Out Buffer = " << _Writer.AmountBuffered() << "\n";
286  ClearAll();
287  return false;
288  }
289  return true;
290  }
291  return false;
292 }
293 
294 /**
295  * Reset
296  */
298  if (nativenet_cat.is_debug()) {
299  nativenet_cat.debug() << "Buffered_DatagramConnection::Reset()\n";
300  }
301  ClearAll();
302 }
303 
304 inline bool Buffered_DatagramConnection::IsConnected(void) {
305  return (Active() == true);
306 }
307 
308 #endif //__BUFFERED_DATAGRAM_CONNECTION_H__
RingBuffer::AmountBuffered
size_t AmountBuffered(void)
Will report the number of unread chars in buffer.
Definition: ringbuffer.I:32
config_nativenet.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
Socket_TCP
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition: socket_tcp.h:12
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_TCP::SetNoDelay
int SetNoDelay(bool flag=true)
Disable Nagle algorithm.
Definition: socket_tcp.h:62
register_type
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
Socket_IP::SetNonBlocking
int SetNonBlocking()
this function will throw a socket into non-blocking mode
Definition: socket_ip.h:169
Buffered_DatagramConnection::~Buffered_DatagramConnection
virtual ~Buffered_DatagramConnection(void)
This is the function that does the connection for us.
Definition: buffered_datagramconnection.h:211
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Buffered_DatagramReader
Definition: buffered_datagramreader.h:17
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Socket_IP::Active
bool Active()
Ask if the socket is open (allocated)
Definition: socket_ip.h:96
Buffered_DatagramConnection::Reset
void Reset(void)
Reset.
Definition: buffered_datagramconnection.h:297
Time_Span
Definition: time_span.h:7
Socket_fdset
Definition: socket_fdset.h:16
Buffered_DatagramConnection::AddAddress
void AddAddress(Socket_Address &inadr)
must be called to set value to the server
Definition: buffered_datagramconnection.h:242
Socket_Selector
Definition: socket_selector.h:7
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_IP::Close
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
Datagram::get_length
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
Socket_TCP::ActiveOpen
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
Buffered_DatagramReader::ReSet
void ReSet(void)
Reset all read content, ie.
Definition: buffered_datagramreader.I:34
Socket_Selector::WaitFor_Read_Error
int WaitFor_Read_Error(const Socket_fdset &fd, const Time_Span &timeout)
Helper function for WaitFor Only looks for readability and errors.
Definition: socket_selector.h:60
Buffered_DatagramWriter::ReSet
void ReSet(void)
used to clear the buffrers ...
Definition: buffered_datagramwriter.h:82
Buffered_DatagramConnection
Definition: buffered_datagramconnection.h:36
Buffered_DatagramWriter
This is the buffered writer.
Definition: buffered_datagramwriter.h:19
Socket_Address
A simple place to store and manipulate tcp and port address for communication layer.
Definition: socket_address.h:25
Buffered_DatagramConnection::Flush
bool Flush(void)
Flush all writes.
Definition: buffered_datagramconnection.h:276
Socket_IP::GetLastError
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
Buffered_DatagramConnection::GetMessage
bool GetMessage(Datagram &val)
Reads a message.
Definition: buffered_datagramconnection.h:254
Datagram::get_data
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327