Panda3D
Loading...
Searching...
No Matches
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 )...
35class EXPCL_PANDA_NATIVENET Buffered_DatagramConnection : public Socket_TCP
36{
37private:
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
73protected:
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..
81PUBLISHED:
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);
108private:
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
117public:
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
131private:
132 static TypeHandle _type_handle;
133};
134
135/**
136 * used to do a full reset of buffers
137 */
138inline 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
148inline 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/*
167inline 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 */
215/**
216 *
217 */
218inline 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
228inline 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
247inline 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
304inline bool Buffered_DatagramConnection::IsConnected(void) {
305 return (Active() == true);
306}
307
308#endif //__BUFFERED_DATAGRAM_CONNECTION_H__
void AddAddress(Socket_Address &inadr)
must be called to set value to the server
virtual ~Buffered_DatagramConnection(void)
This is the function that does the connection for us.
bool GetMessage(Datagram &val)
Reads a message.
void ReSet(void)
Reset all read content, ie.
This is the buffered writer.
void ReSet(void)
used to clear the buffrers ... use of this in mid stream is a very bad thing as you can not guarany n...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
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
size_t AmountBuffered(void)
Will report the number of unread chars in buffer.
Definition ringbuffer.I:32
A simple place to store and manipulate tcp and port address for communication layer.
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
bool Active()
Ask if the socket is open (allocated)
Definition socket_ip.h:96
int SetNonBlocking()
this function will throw a socket into non-blocking mode
Definition socket_ip.h:169
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition socket_tcp.h:12
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
int SetNoDelay(bool flag=true)
Disable Nagle algorithm.
Definition socket_tcp.h:62
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
int WaitFor_Read_Error(const Socket_fdset &fd, const Time_Span &timeout)
Helper function for WaitFor Only looks for readability and errors.