Switch to unified view

a/src/utils/netcon.h b/src/utils/netcon.h
...
...
34
/// The listening/connection-accepting code currently only uses
34
/// The listening/connection-accepting code currently only uses
35
/// TCP. The classes include client-side and server-side (accepting)
35
/// TCP. The classes include client-side and server-side (accepting)
36
/// endpoints. Netcon also has server-side static code to handle a set
36
/// endpoints. Netcon also has server-side static code to handle a set
37
/// of client connections in parallel. This should be moved to a
37
/// of client connections in parallel. This should be moved to a
38
/// friend class.
38
/// friend class.
39
/// 
39
///
40
/// The client data transfer class can also be used for
40
/// The client data transfer class can also be used for
41
/// timeout-protected/asynchronous io using a given fd (ie a pipe
41
/// timeout-protected/asynchronous io using a given fd (ie a pipe
42
/// descriptor)
42
/// descriptor)
43
43
44
/// Base class for all network endpoints:
44
/// Base class for all network endpoints:
...
...
46
typedef STD_SHARED_PTR<Netcon> NetconP;
46
typedef STD_SHARED_PTR<Netcon> NetconP;
47
class SelectLoop;
47
class SelectLoop;
48
48
49
class Netcon {
49
class Netcon {
50
public:
50
public:
51
    enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
51
    enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE = 0x2};
52
    Netcon() 
52
    Netcon()
53
  : m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
53
        : m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
54
    m_loop(0) {
54
          m_loop(0) {
55
    }
55
    }
56
    virtual ~Netcon();
56
    virtual ~Netcon();
57
    /// Remember whom we're talking to. We let external code do this because 
57
    /// Remember whom we're talking to. We let external code do this because
58
    /// the application may have a non-dns method to find the peer name.
58
    /// the application may have a non-dns method to find the peer name.
59
    virtual void setpeer(const char *hostname);
59
    virtual void setpeer(const char *hostname);
60
    /// Retrieve the peer's hostname. Only works if it was set before !
60
    /// Retrieve the peer's hostname. Only works if it was set before !
61
    virtual const char *getpeer() {
61
    virtual const char *getpeer() {
62
  return m_peer ? (const char *)m_peer : "none";
62
        return m_peer ? (const char *)m_peer : "none";
63
    }
63
    }
64
    /// Set or reset the TCP_NODELAY option. 
64
    /// Set or reset the TCP_NODELAY option.
65
    virtual int settcpnodelay(int on = 1); 
65
    virtual int settcpnodelay(int on = 1);
66
    /// Did the last receive() call time out ? Resets the flag.
66
    /// Did the last receive() call time out ? Resets the flag.
67
    virtual int timedout() {
67
    virtual int timedout() {
68
        int s = m_didtimo; 
68
        int s = m_didtimo;
69
        m_didtimo = 0; 
69
        m_didtimo = 0;
70
        return s;
70
        return s;
71
    }
71
    }
72
    /// Return string version of last syscall error
72
    /// Return string version of last syscall error
73
    virtual char *sterror();
73
    virtual char *sterror();
74
    /// Return the socket descriptor
74
    /// Return the socket descriptor
...
...
109
    /// Utility function for a simplified select() interface: check one fd
109
    /// Utility function for a simplified select() interface: check one fd
110
    /// for reading or writing, for a specified maximum number of seconds.
110
    /// for reading or writing, for a specified maximum number of seconds.
111
    static int select1(int fd, int secs, int writing = 0);
111
    static int select1(int fd, int secs, int writing = 0);
112
112
113
protected:
113
protected:
114
    char *m_peer; // Name of the connected host
114
    char *m_peer;   // Name of the connected host
115
    int   m_fd;
115
    int   m_fd;
116
    bool  m_ownfd;
116
    bool  m_ownfd;
117
    int   m_didtimo;
117
    int   m_didtimo;
118
    // Used when part of the selectloop map.
118
    // Used when part of the selectloop map.
119
    short m_wantedEvents;
119
    short m_wantedEvents;
...
...
125
        m_loop = loop;
125
        m_loop = loop;
126
    }
126
    }
127
};
127
};
128
128
129
129
130
/// The selectloop interface is used to implement parallel servers. 
130
/// The selectloop interface is used to implement parallel servers.
131
// The select loop mechanism allows several netcons to be used for io
131
// The select loop mechanism allows several netcons to be used for io
132
// in a program without blocking as long as there is data to be read
132
// in a program without blocking as long as there is data to be read
133
// or written. In a multithread program which is also using select, it
133
// or written. In a multithread program which is also using select, it
134
// would typically make sense to have one SelectLoop active per
134
// would typically make sense to have one SelectLoop active per
135
// thread.
135
// thread.
136
class SelectLoop {
136
class SelectLoop {
137
public:
137
public:
138
    SelectLoop()
138
    SelectLoop()
139
  : m_selectloopDoReturn(false), m_selectloopReturnValue(0),
139
        : m_selectloopDoReturn(false), m_selectloopReturnValue(0),
140
    m_placetostart(0), 
140
          m_placetostart(0),
141
    m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) {
141
          m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) {
142
    }
142
    }
143
143
144
    /// Loop waiting for events on the connections and call the
144
    /// Loop waiting for events on the connections and call the
145
    /// cando() method on the object when something happens (this will in 
145
    /// cando() method on the object when something happens (this will in
146
    /// turn typically call the app callback set on the netcon). Possibly
146
    /// turn typically call the app callback set on the netcon). Possibly
147
    /// call the periodic handler (if set) at regular intervals.
147
    /// call the periodic handler (if set) at regular intervals.
148
    /// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
148
    /// @return -1 for error. 0 if no descriptors left for i/o. 1 for periodic
149
    ///  timeout (should call back in after processing)
149
    ///  timeout (should call back in after processing)
150
    int doLoop();
150
    int doLoop();
151
151
152
    /// Call from data handler: make selectloop return the param value
152
    /// Call from data handler: make selectloop return the param value
153
    void loopReturn(int value) {
153
    void loopReturn(int value) {
154
  m_selectloopDoReturn = true;
154
        m_selectloopDoReturn = true;
155
  m_selectloopReturnValue = value;
155
        m_selectloopReturnValue = value;
156
    }
156
    }
157
    /// Add a connection to be monitored (this will usually be called
157
    /// Add a connection to be monitored (this will usually be called
158
    /// from the server's listen connection's accept callback)
158
    /// from the server's listen connection's accept callback)
159
    int addselcon(NetconP con, int events);
159
    int addselcon(NetconP con, int events);
160
    /// Remove a connection from the monitored set. This is
160
    /// Remove a connection from the monitored set. This is
161
    /// automatically called when EOF is detected on a connection.
161
    /// automatically called when EOF is detected on a connection.
162
    int remselcon(NetconP con);
162
    int remselcon(NetconP con);
163
163
164
    /// Set a function to be called periodically, or a time before return.
164
    /// Set a function to be called periodically, or a time before return.
165
    /// @param handler the function to be called. 
165
    /// @param handler the function to be called.
166
    ///  - if it is 0, selectloop() will return after ms mS (and can be called
166
    ///  - if it is 0, selectloop() will return after ms mS (and can be called
167
    ///    again
167
    ///    again
168
    ///  - if it is not 0, it will be called at ms mS intervals. If its return 
168
    ///  - if it is not 0, it will be called at ms mS intervals. If its return
169
    ///    value is <= 0, selectloop will return. 
169
    ///    value is <= 0, selectloop will return.
170
    /// @param clp client data to be passed to handler at every call.
170
    /// @param clp client data to be passed to handler at every call.
171
    /// @param ms milliseconds interval between handler calls or
171
    /// @param ms milliseconds interval between handler calls or
172
    ///   before return. Set to 0 for no periodic handler.
172
    ///   before return. Set to 0 for no periodic handler.
173
    void setperiodichandler(int (*handler)(void *), void *clp, int ms);
173
    void setperiodichandler(int (*handler)(void *), void *clp, int ms);
174
174
...
...
193
};
193
};
194
194
195
///////////////////////
195
///////////////////////
196
class NetconData;
196
class NetconData;
197
197
198
/// Class for the application callback routine (when in selectloop). 
198
/// Class for the application callback routine (when in selectloop).
199
///
199
///
200
/// This is set by the app on the NetconData by calling
200
/// This is set by the app on the NetconData by calling
201
/// setcallback(). It is then called from the NetconData's cando()
201
/// setcallback(). It is then called from the NetconData's cando()
202
/// routine, itself called by selectloop.
202
/// routine, itself called by selectloop.
203
/// 
203
///
204
/// It would be nicer to override cando() in a subclass instead of
204
/// It would be nicer to override cando() in a subclass instead of
205
/// setting a callback, but this can't be done conveniently because
205
/// setting a callback, but this can't be done conveniently because
206
/// accept() always creates a base NetconData (another approach would
206
/// accept() always creates a base NetconData (another approach would
207
/// be to pass a factory function to the listener, to create
207
/// be to pass a factory function to the listener, to create
208
/// NetconData derived classes).
208
/// NetconData derived classes).
...
...
227
    ///  error occurred.
227
    ///  error occurred.
228
    virtual int send(const char *buf, int cnt, int expedited = 0);
228
    virtual int send(const char *buf, int cnt, int expedited = 0);
229
229
230
    /// Read from the connection
230
    /// Read from the connection
231
    /// @param buf the data buffer
231
    /// @param buf the data buffer
232
    /// @param cnt the number of bytes we should try to read (but we return 
232
    /// @param cnt the number of bytes we should try to read (but we return
233
    ///   as soon as we get data)
233
    ///   as soon as we get data)
234
    /// @param timeo maximum number of seconds we should be waiting for data.
234
    /// @param timeo maximum number of seconds we should be waiting for data.
235
    /// @return the count of bytes actually read. 0 for timeout (call
235
    /// @return the count of bytes actually read. 0 for timeout (call
236
    ///        didtimo() to discriminate from EOF). -1 if an error occurred.
236
    ///        didtimo() to discriminate from EOF). -1 if an error occurred.
237
    virtual int receive(char *buf, int cnt, int timeo = -1);
237
    virtual int receive(char *buf, int cnt, int timeo = -1);
...
...
249
    virtual void setcallback(STD_SHARED_PTR<NetconWorker> user) {
249
    virtual void setcallback(STD_SHARED_PTR<NetconWorker> user) {
250
        m_user = user;
250
        m_user = user;
251
    }
251
    }
252
252
253
private:
253
private:
254
    char *m_buf;  // Buffer. Only used when doing getline()s
254
    char *m_buf;    // Buffer. Only used when doing getline()s
255
    char *m_bufbase;    // Pointer to current 1st byte of useful data
255
    char *m_bufbase;    // Pointer to current 1st byte of useful data
256
    int m_bufbytes;   // Bytes of data.
256
    int m_bufbytes; // Bytes of data.
257
    int m_bufsize;    // Total buffer size
257
    int m_bufsize;  // Total buffer size
258
    STD_SHARED_PTR<NetconWorker> m_user;
258
    STD_SHARED_PTR<NetconWorker> m_user;
259
    virtual int cando(Netcon::Event reason); // Selectloop slot
259
    virtual int cando(Netcon::Event reason); // Selectloop slot
260
};
260
};
261
261
262
/// Network endpoint, client side.
262
/// Network endpoint, client side.
263
class NetconCli : public NetconData { 
263
class NetconCli : public NetconData {
264
public:
264
public:
265
    NetconCli(int silent = 0) {
265
    NetconCli(int silent = 0) {
266
        m_silentconnectfailure = silent;
266
        m_silentconnectfailure = silent;
267
    }
267
    }
268
268
...
...
274
    /// Open connection to specified host and numeric port. port is in
274
    /// Open connection to specified host and numeric port. port is in
275
    /// HOST byte order. Set host to an absolute path name for an
275
    /// HOST byte order. Set host to an absolute path name for an
276
    /// AF_UNIX service. serv is ignored in this case.
276
    /// AF_UNIX service. serv is ignored in this case.
277
    int openconn(const char *host, unsigned int port, int timeo = -1);
277
    int openconn(const char *host, unsigned int port, int timeo = -1);
278
278
279
    /// Reuse existing fd. 
279
    /// Reuse existing fd.
280
    /// We DONT take ownership of the fd, and do no closin' EVEN on an
280
    /// We DONT take ownership of the fd, and do no closin' EVEN on an
281
    /// explicit closeconn() or setconn() (use getfd(), close,
281
    /// explicit closeconn() or setconn() (use getfd(), close,
282
    /// setconn(-1) if you need to really close the fd and have no
282
    /// setconn(-1) if you need to really close the fd and have no
283
    /// other copy).
283
    /// other copy).
284
    int setconn(int fd);
284
    int setconn(int fd);
...
...
287
    void setSilentFail(int onoff) {
287
    void setSilentFail(int onoff) {
288
        m_silentconnectfailure = onoff;
288
        m_silentconnectfailure = onoff;
289
    }
289
    }
290
290
291
private:
291
private:
292
    int m_silentconnectfailure;   // No logging of connection failures if set
292
    int m_silentconnectfailure; // No logging of connection failures if set
293
};
293
};
294
294
295
class NetconServCon;
295
class NetconServCon;
296
#ifdef NETCON_ACCESSCONTROL
296
#ifdef NETCON_ACCESSCONTROL
297
struct intarrayparam {
297
struct intarrayparam {
...
...
314
/// (ex: default_okaddrs, default_okmasks)
314
/// (ex: default_okaddrs, default_okmasks)
315
class NetconServLis : public Netcon {
315
class NetconServLis : public Netcon {
316
public:
316
public:
317
    NetconServLis() {
317
    NetconServLis() {
318
#ifdef NETCON_ACCESSCONTROL
318
#ifdef NETCON_ACCESSCONTROL
319
  permsinit = 0;
319
        permsinit = 0;
320
  okaddrs.len = okmasks.len = 0;
320
        okaddrs.len = okmasks.len = 0;
321
  okaddrs.intarray = okmasks.intarray = 0;
321
        okaddrs.intarray = okmasks.intarray = 0;
322
#endif /* NETCON_ACCESSCONTROL */
322
#endif /* NETCON_ACCESSCONTROL */
323
    }
323
    }
324
    ~NetconServLis();
324
    ~NetconServLis();
325
    /// Open named service. Used absolute pathname to create an
325
    /// Open named service. Used absolute pathname to create an
326
    /// AF_UNIX path-based socket instead of an IP one.
326
    /// AF_UNIX path-based socket instead of an IP one.
327
    int openservice(const char *serv, int backlog = 10);
327
    int openservice(const char *serv, int backlog = 10);
328
    /// Open service by port number.
328
    /// Open service by port number.
329
    int openservice(int port, int backlog = 10);
329
    int openservice(int port, int backlog = 10);
330
    /// Wait for incoming connection. Returned connected Netcon 
330
    /// Wait for incoming connection. Returned connected Netcon
331
    NetconServCon *accept(int timeo = -1);
331
    NetconServCon *accept(int timeo = -1);
332
332
333
protected:
333
protected:
334
    /// This should be overriden in a derived class to handle incoming
334
    /// This should be overriden in a derived class to handle incoming
335
    /// connections. It will usually call NetconServLis::accept(), and
335
    /// connections. It will usually call NetconServLis::accept(), and
336
    /// insert the new connection in the selectloop.
336
    /// insert the new connection in the selectloop.
337
    virtual int cando(Netcon::Event reason);
337
    virtual int cando(Netcon::Event reason);
338
338
339
    // Empty if port was numeric, else service name or socket path
339
    // Empty if port was numeric, else service name or socket path
340
    std::string m_serv; 
340
    std::string m_serv;
341
341
342
private:
342
private:
343
#ifdef NETCON_ACCESSCONTROL
343
#ifdef NETCON_ACCESSCONTROL
344
    int permsinit;
344
    int permsinit;
345
    struct intarrayparam okaddrs;
345
    struct intarrayparam okaddrs;
...
...
351
};
351
};
352
352
353
/// Server-side accepted client connection. The only specific code
353
/// Server-side accepted client connection. The only specific code
354
/// allows closing the listening endpoint in the child process (in the
354
/// allows closing the listening endpoint in the child process (in the
355
/// case of a forking server)
355
/// case of a forking server)
356
class NetconServCon : public NetconData { 
356
class NetconServCon : public NetconData {
357
public:
357
public:
358
    NetconServCon(int newfd, Netcon* lis = 0) { 
358
    NetconServCon(int newfd, Netcon* lis = 0) {
359
  m_liscon = lis;
359
        m_liscon = lis;
360
  m_fd = newfd;
360
        m_fd = newfd;
361
    }
361
    }
362
    /// This is for forked servers that want to get rid of the main socket
362
    /// This is for forked servers that want to get rid of the main socket
363
    void closeLisCon() {
363
    void closeLisCon() {
364
  if (m_liscon) {
364
        if (m_liscon) {
365
      m_liscon->closeconn();
365
            m_liscon->closeconn();
366
        }
366
        }
367
    }
367
    }
368
private:
368
private:
369
    Netcon* m_liscon;
369
    Netcon* m_liscon;
370
};
370
};