|
a/src/utils/netcon.h |
|
b/src/utils/netcon.h |
|
... |
|
... |
16 |
* Free Software Foundation, Inc.,
|
16 |
* Free Software Foundation, Inc.,
|
17 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
18 |
*/
|
18 |
*/
|
19 |
#include <sys/time.h>
|
19 |
#include <sys/time.h>
|
20 |
#include <map>
|
20 |
#include <map>
|
|
|
21 |
#include <string>
|
|
|
22 |
|
21 |
#include "refcntr.h"
|
23 |
#include "refcntr.h"
|
22 |
|
|
|
23 |
using std::map;
|
|
|
24 |
|
24 |
|
25 |
/// A set of classes to manage client-server communication over a
|
25 |
/// A set of classes to manage client-server communication over a
|
26 |
/// connection-oriented network, or a pipe.
|
26 |
/// connection-oriented network, or a pipe.
|
27 |
///
|
27 |
///
|
28 |
/// The listening/connection-accepting code currently only uses
|
28 |
/// The listening/connection-accepting code currently only uses
|
|
... |
|
... |
43 |
class Netcon {
|
43 |
class Netcon {
|
44 |
public:
|
44 |
public:
|
45 |
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
|
45 |
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
|
46 |
Netcon()
|
46 |
Netcon()
|
47 |
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
|
47 |
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
|
48 |
m_loop(0)
|
48 |
m_loop(0) {
|
49 |
{}
|
49 |
}
|
50 |
virtual ~Netcon();
|
50 |
virtual ~Netcon();
|
51 |
/// Remember whom we're talking to. We let external code do this because
|
51 |
/// Remember whom we're talking to. We let external code do this because
|
52 |
/// the application may have a non-dns method to find the peer name.
|
52 |
/// the application may have a non-dns method to find the peer name.
|
53 |
virtual void setpeer(const char *hostname);
|
53 |
virtual void setpeer(const char *hostname);
|
54 |
/// Retrieve the peer's hostname. Only works if it was set before !
|
54 |
/// Retrieve the peer's hostname. Only works if it was set before !
|
|
... |
|
... |
56 |
return m_peer ? (const char *)m_peer : "none";
|
56 |
return m_peer ? (const char *)m_peer : "none";
|
57 |
}
|
57 |
}
|
58 |
/// Set or reset the TCP_NODELAY option.
|
58 |
/// Set or reset the TCP_NODELAY option.
|
59 |
virtual int settcpnodelay(int on = 1);
|
59 |
virtual int settcpnodelay(int on = 1);
|
60 |
/// Did the last receive() call time out ? Resets the flag.
|
60 |
/// Did the last receive() call time out ? Resets the flag.
|
61 |
virtual int timedout() {int s = m_didtimo; m_didtimo = 0; return s;}
|
61 |
virtual int timedout() {
|
|
|
62 |
int s = m_didtimo;
|
|
|
63 |
m_didtimo = 0;
|
|
|
64 |
return s;
|
|
|
65 |
}
|
62 |
/// Return string version of last syscall error
|
66 |
/// Return string version of last syscall error
|
63 |
virtual char *sterror();
|
67 |
virtual char *sterror();
|
64 |
/// Return the socket descriptor
|
68 |
/// Return the socket descriptor
|
65 |
virtual int getfd() {return m_fd;}
|
69 |
virtual int getfd() {
|
|
|
70 |
return m_fd;
|
|
|
71 |
}
|
66 |
/// Close the current connection if it is open
|
72 |
/// Close the current connection if it is open
|
67 |
virtual void closeconn();
|
73 |
virtual void closeconn();
|
68 |
/// Set/reset the non-blocking flag on the underlying fd. Returns
|
74 |
/// Set/reset the non-blocking flag on the underlying fd. Returns
|
69 |
/// prev state The default is that sockets are blocking except
|
75 |
/// prev state The default is that sockets are blocking except
|
70 |
/// when added to the selectloop, or, transparently, to handle
|
76 |
/// when added to the selectloop, or, transparently, to handle
|
71 |
/// connection timeout issues.
|
77 |
/// connection timeout issues.
|
72 |
virtual int set_nonblock(int onoff);
|
78 |
virtual int set_nonblock(int onoff);
|
73 |
|
79 |
|
74 |
/// Decide what events the connection will be looking for
|
80 |
/// Decide what events the connection will be looking for
|
75 |
/// (NETCONPOLL_READ, NETCONPOLL_WRITE)
|
81 |
/// (NETCONPOLL_READ, NETCONPOLL_WRITE)
|
76 |
int setselevents(int evs) {return m_wantedEvents = evs;}
|
82 |
int setselevents(int evs) {
|
|
|
83 |
return m_wantedEvents = evs;
|
|
|
84 |
}
|
77 |
/// Retrieve the connection's currently monitored set of events
|
85 |
/// Retrieve the connection's currently monitored set of events
|
78 |
int getselevents() {return m_wantedEvents;}
|
86 |
int getselevents() {
|
|
|
87 |
return m_wantedEvents;
|
|
|
88 |
}
|
79 |
/// Add events to current set
|
89 |
/// Add events to current set
|
80 |
int addselevents(int evs) {return m_wantedEvents |= evs;}
|
90 |
int addselevents(int evs) {
|
|
|
91 |
return m_wantedEvents |= evs;
|
|
|
92 |
}
|
81 |
/// Clear events from current set
|
93 |
/// Clear events from current set
|
82 |
int clearselevents(int evs) {return m_wantedEvents &= ~evs;}
|
94 |
int clearselevents(int evs) {
|
|
|
95 |
return m_wantedEvents &= ~evs;
|
|
|
96 |
}
|
83 |
|
97 |
|
84 |
friend class SelectLoop;
|
98 |
friend class SelectLoop;
|
85 |
SelectLoop *getloop() {return m_loop;}
|
99 |
SelectLoop *getloop() {
|
|
|
100 |
return m_loop;
|
|
|
101 |
}
|
86 |
|
102 |
|
87 |
/// Utility function for a simplified select() interface: check one fd
|
103 |
/// Utility function for a simplified select() interface: check one fd
|
88 |
/// for reading or writing, for a specified maximum number of seconds.
|
104 |
/// for reading or writing, for a specified maximum number of seconds.
|
89 |
static int select1(int fd, int secs, int writing = 0);
|
105 |
static int select1(int fd, int secs, int writing = 0);
|
90 |
|
106 |
|
|
... |
|
... |
97 |
short m_wantedEvents;
|
113 |
short m_wantedEvents;
|
98 |
SelectLoop *m_loop;
|
114 |
SelectLoop *m_loop;
|
99 |
// Method called by the selectloop when something can be done with a netcon
|
115 |
// Method called by the selectloop when something can be done with a netcon
|
100 |
virtual int cando(Netcon::Event reason) = 0;
|
116 |
virtual int cando(Netcon::Event reason) = 0;
|
101 |
// Called when added to loop
|
117 |
// Called when added to loop
|
102 |
virtual void setloop(SelectLoop *loop) {m_loop = loop;}
|
118 |
virtual void setloop(SelectLoop *loop) {
|
|
|
119 |
m_loop = loop;
|
|
|
120 |
}
|
103 |
};
|
121 |
};
|
104 |
|
122 |
|
105 |
|
123 |
|
106 |
/// The selectloop interface is used to implement parallel servers.
|
124 |
/// The selectloop interface is used to implement parallel servers.
|
107 |
// The select loop mechanism allows several netcons to be used for io
|
125 |
// The select loop mechanism allows several netcons to be used for io
|
|
... |
|
... |
112 |
class SelectLoop {
|
130 |
class SelectLoop {
|
113 |
public:
|
131 |
public:
|
114 |
SelectLoop()
|
132 |
SelectLoop()
|
115 |
: m_selectloopDoReturn(false), m_selectloopReturnValue(0),
|
133 |
: m_selectloopDoReturn(false), m_selectloopReturnValue(0),
|
116 |
m_placetostart(0),
|
134 |
m_placetostart(0),
|
117 |
m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0)
|
135 |
m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) {
|
118 |
{}
|
136 |
}
|
119 |
|
137 |
|
120 |
/// Loop waiting for events on the connections and call the
|
138 |
/// Loop waiting for events on the connections and call the
|
121 |
/// cando() method on the object when something happens (this will in
|
139 |
/// cando() method on the object when something happens (this will in
|
122 |
/// turn typically call the app callback set on the netcon). Possibly
|
140 |
/// turn typically call the app callback set on the netcon). Possibly
|
123 |
/// call the periodic handler (if set) at regular intervals.
|
141 |
/// call the periodic handler (if set) at regular intervals.
|
124 |
/// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
|
142 |
/// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
|
125 |
/// timeout (should call back in after processing)
|
143 |
/// timeout (should call back in after processing)
|
126 |
int doLoop();
|
144 |
int doLoop();
|
127 |
|
145 |
|
128 |
/// Call from data handler: make selectloop return the param value
|
146 |
/// Call from data handler: make selectloop return the param value
|
129 |
void loopReturn(int value)
|
147 |
void loopReturn(int value) {
|
130 |
{
|
|
|
131 |
m_selectloopDoReturn = true;
|
148 |
m_selectloopDoReturn = true;
|
132 |
m_selectloopReturnValue = value;
|
149 |
m_selectloopReturnValue = value;
|
133 |
}
|
150 |
}
|
134 |
/// Add a connection to be monitored (this will usually be called
|
151 |
/// Add a connection to be monitored (this will usually be called
|
135 |
/// from the server's listen connection's accept callback)
|
152 |
/// from the server's listen connection's accept callback)
|
|
... |
|
... |
154 |
bool m_selectloopDoReturn;
|
171 |
bool m_selectloopDoReturn;
|
155 |
int m_selectloopReturnValue;
|
172 |
int m_selectloopReturnValue;
|
156 |
int m_placetostart;
|
173 |
int m_placetostart;
|
157 |
|
174 |
|
158 |
// Map of NetconP indexed by fd
|
175 |
// Map of NetconP indexed by fd
|
159 |
map<int, NetconP> m_polldata;
|
176 |
std::map<int, NetconP> m_polldata;
|
160 |
|
177 |
|
161 |
// The last time we did the periodic thing. Initialized by setperiodic()
|
178 |
// The last time we did the periodic thing. Initialized by setperiodic()
|
162 |
struct timeval m_lasthdlcall;
|
179 |
struct timeval m_lasthdlcall;
|
163 |
// The call back function and its parameter
|
180 |
// The call back function and its parameter
|
164 |
int (*m_periodichandler)(void *);
|
181 |
int (*m_periodichandler)(void *);
|
|
... |
|
... |
190 |
};
|
207 |
};
|
191 |
|
208 |
|
192 |
/// Base class for connections that actually transfer data. T
|
209 |
/// Base class for connections that actually transfer data. T
|
193 |
class NetconData : public Netcon {
|
210 |
class NetconData : public Netcon {
|
194 |
public:
|
211 |
public:
|
195 |
NetconData() : m_buf(0), m_bufbase(0), m_bufbytes(0), m_bufsize(0)
|
212 |
NetconData() : m_buf(0), m_bufbase(0), m_bufbytes(0), m_bufsize(0) {
|
196 |
{}
|
213 |
}
|
197 |
virtual ~NetconData();
|
214 |
virtual ~NetconData();
|
198 |
|
215 |
|
199 |
/// Write data to the connection.
|
216 |
/// Write data to the connection.
|
200 |
/// @param buf the data buffer
|
217 |
/// @param buf the data buffer
|
201 |
/// @param cnt the number of bytes we should try to send
|
218 |
/// @param cnt the number of bytes we should try to send
|
|
... |
|
... |
216 |
virtual int doreceive(char *buf, int cnt, int timeo = -1);
|
233 |
virtual int doreceive(char *buf, int cnt, int timeo = -1);
|
217 |
/// Check for data being available for reading
|
234 |
/// Check for data being available for reading
|
218 |
virtual int readready();
|
235 |
virtual int readready();
|
219 |
/// Check for data being available for writing
|
236 |
/// Check for data being available for writing
|
220 |
virtual int writeready();
|
237 |
virtual int writeready();
|
221 |
/// Read a line of text on an ascii connection
|
238 |
/// Read a line of text on an ascii connection. Returns -1 or byte count
|
|
|
239 |
/// including final 0. \n is kept
|
222 |
virtual int getline(char *buf, int cnt, int timeo = -1);
|
240 |
virtual int getline(char *buf, int cnt, int timeo = -1);
|
223 |
/// Set handler to be called when the connection is placed in the
|
241 |
/// Set handler to be called when the connection is placed in the
|
224 |
/// selectloop and an event occurs.
|
242 |
/// selectloop and an event occurs.
|
225 |
virtual void setcallback(RefCntr<NetconWorker> user) {m_user = user;}
|
243 |
virtual void setcallback(RefCntr<NetconWorker> user) {
|
|
|
244 |
m_user = user;
|
|
|
245 |
}
|
226 |
|
246 |
|
227 |
private:
|
247 |
private:
|
228 |
char *m_buf; // Buffer. Only used when doing getline()s
|
248 |
char *m_buf; // Buffer. Only used when doing getline()s
|
229 |
char *m_bufbase; // Pointer to current 1st byte of useful data
|
249 |
char *m_bufbase; // Pointer to current 1st byte of useful data
|
230 |
int m_bufbytes; // Bytes of data.
|
250 |
int m_bufbytes; // Bytes of data.
|
|
... |
|
... |
234 |
};
|
254 |
};
|
235 |
|
255 |
|
236 |
/// Network endpoint, client side.
|
256 |
/// Network endpoint, client side.
|
237 |
class NetconCli : public NetconData {
|
257 |
class NetconCli : public NetconData {
|
238 |
public:
|
258 |
public:
|
239 |
NetconCli(int silent = 0) {m_silentconnectfailure = silent;}
|
259 |
NetconCli(int silent = 0) {
|
|
|
260 |
m_silentconnectfailure = silent;
|
|
|
261 |
}
|
240 |
|
262 |
|
241 |
/// Open connection to specified host and named service.
|
263 |
/// Open connection to specified host and named service. Set host
|
|
|
264 |
/// to an absolute path name for an AF_UNIX service. serv is
|
|
|
265 |
/// ignored in this case.
|
242 |
int openconn(const char *host, char *serv, int timeo = -1);
|
266 |
int openconn(const char *host, const char *serv, int timeo = -1);
|
243 |
|
267 |
|
244 |
/// Open connection to specified host and numeric port. port is in
|
268 |
/// Open connection to specified host and numeric port. port is in
|
245 |
/// HOST byte order
|
269 |
/// HOST byte order. Set host to an absolute path name for an
|
|
|
270 |
/// AF_UNIX service. serv is ignored in this case.
|
246 |
int openconn(const char *host, unsigned int port, int timeo = -1);
|
271 |
int openconn(const char *host, unsigned int port, int timeo = -1);
|
247 |
|
272 |
|
248 |
/// Reuse existing fd.
|
273 |
/// Reuse existing fd.
|
249 |
/// We DONT take ownership of the fd, and do no closin' EVEN on an
|
274 |
/// We DONT take ownership of the fd, and do no closin' EVEN on an
|
250 |
/// explicit closeconn() or setconn() (use getfd(), close,
|
275 |
/// explicit closeconn() or setconn() (use getfd(), close,
|
251 |
/// setconn(-1) if you need to really close the fd and have no
|
276 |
/// setconn(-1) if you need to really close the fd and have no
|
252 |
/// other copy).
|
277 |
/// other copy).
|
253 |
int setconn(int fd);
|
278 |
int setconn(int fd);
|
254 |
|
279 |
|
255 |
/// Do not log message if openconn() fails.
|
280 |
/// Do not log message if openconn() fails.
|
256 |
void setSilentFail(int onoff) {m_silentconnectfailure = onoff;}
|
281 |
void setSilentFail(int onoff) {
|
|
|
282 |
m_silentconnectfailure = onoff;
|
|
|
283 |
}
|
257 |
|
284 |
|
258 |
private:
|
285 |
private:
|
259 |
int m_silentconnectfailure; // No logging of connection failures if set
|
286 |
int m_silentconnectfailure; // No logging of connection failures if set
|
260 |
};
|
287 |
};
|
261 |
|
288 |
|
|
... |
|
... |
287 |
okaddrs.len = okmasks.len = 0;
|
314 |
okaddrs.len = okmasks.len = 0;
|
288 |
okaddrs.intarray = okmasks.intarray = 0;
|
315 |
okaddrs.intarray = okmasks.intarray = 0;
|
289 |
#endif /* NETCON_ACCESSCONTROL */
|
316 |
#endif /* NETCON_ACCESSCONTROL */
|
290 |
}
|
317 |
}
|
291 |
~NetconServLis();
|
318 |
~NetconServLis();
|
292 |
/// Open named service.
|
319 |
/// Open named service. Used absolute pathname to create an
|
|
|
320 |
/// AF_UNIX path-based socket instead of an IP one.
|
293 |
int openservice(char *serv, int backlog = 10);
|
321 |
int openservice(const char *serv, int backlog = 10);
|
294 |
/// Open service by port number.
|
322 |
/// Open service by port number.
|
295 |
int openservice(int port, int backlog = 10);
|
323 |
int openservice(int port, int backlog = 10);
|
296 |
/// Wait for incoming connection. Returned connected Netcon
|
324 |
/// Wait for incoming connection. Returned connected Netcon
|
297 |
NetconServCon *accept(int timeo = -1);
|
325 |
NetconServCon *accept(int timeo = -1);
|
298 |
|
326 |
|
|
... |
|
... |
300 |
/// This should be overriden in a derived class to handle incoming
|
328 |
/// This should be overriden in a derived class to handle incoming
|
301 |
/// connections. It will usually call NetconServLis::accept(), and
|
329 |
/// connections. It will usually call NetconServLis::accept(), and
|
302 |
/// insert the new connection in the selectloop.
|
330 |
/// insert the new connection in the selectloop.
|
303 |
virtual int cando(Netcon::Event reason);
|
331 |
virtual int cando(Netcon::Event reason);
|
304 |
|
332 |
|
|
|
333 |
// Empty if port was numeric, else service name or socket path
|
|
|
334 |
std::string m_serv;
|
|
|
335 |
|
305 |
private:
|
336 |
private:
|
306 |
#ifdef NETCON_ACCESSCONTROL
|
337 |
#ifdef NETCON_ACCESSCONTROL
|
307 |
int permsinit;
|
338 |
int permsinit;
|
308 |
struct intarrayparam okaddrs;
|
339 |
struct intarrayparam okaddrs;
|
309 |
struct intarrayparam okmasks;
|
340 |
struct intarrayparam okmasks;
|
310 |
int initperms(char *servicename);
|
341 |
int initperms(const char *servicename);
|
311 |
int initperms(int port);
|
342 |
int initperms(int port);
|
312 |
int checkperms(void *cli, int clilen);
|
343 |
int checkperms(void *cli, int clilen);
|
313 |
#endif /* NETCON_ACCESSCONTROL */
|
344 |
#endif /* NETCON_ACCESSCONTROL */
|
314 |
};
|
345 |
};
|
315 |
|
346 |
|
316 |
/// Server-side accepted client connection. The only specific code
|
347 |
/// Server-side accepted client connection. The only specific code
|
317 |
/// allows closing the listening endpoint in the child process (in the
|
348 |
/// allows closing the listening endpoint in the child process (in the
|
318 |
/// case of a forking server)
|
349 |
/// case of a forking server)
|
319 |
class NetconServCon : public NetconData {
|
350 |
class NetconServCon : public NetconData {
|
320 |
public:
|
351 |
public:
|
321 |
NetconServCon(int newfd, Netcon* lis = 0)
|
352 |
NetconServCon(int newfd, Netcon* lis = 0) {
|
322 |
{
|
|
|
323 |
m_liscon = lis;
|
353 |
m_liscon = lis;
|
324 |
m_fd = newfd;
|
354 |
m_fd = newfd;
|
325 |
}
|
355 |
}
|
326 |
/// This is for forked servers that want to get rid of the main socket
|
356 |
/// This is for forked servers that want to get rid of the main socket
|
327 |
void closeLisCon() {
|
357 |
void closeLisCon() {
|
328 |
if (m_liscon)
|
358 |
if (m_liscon) {
|
329 |
m_liscon->closeconn();
|
359 |
m_liscon->closeconn();
|
|
|
360 |
}
|
330 |
}
|
361 |
}
|
331 |
private:
|
362 |
private:
|
332 |
Netcon* m_liscon;
|
363 |
Netcon* m_liscon;
|
333 |
};
|
364 |
};
|
334 |
|
365 |
|