Switch to unified view

a/src/utils/netcon.cpp b/src/utils/netcon.cpp
1
/* Copyright (C) 2002 Jean-Francois Dockes */
1
/* Copyright (C) 2002 J.F. Dockes
2
 *   This program is free software; you can redistribute it and/or modify
3
 *   it under the terms of the GNU General Public License as published by
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *   (at your option) any later version.
6
 *
7
 *   This program is distributed in the hope that it will be useful,
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 *   GNU General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU General Public License
13
 *   along with this program; if not, write to the
14
 *   Free Software Foundation, Inc.,
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 */
2
17
3
// Wrapper classes for the socket interface
18
// Wrapper classes for the socket interface
4
19
5
20
6
#ifndef TEST_NETCON
21
#ifndef TEST_NETCON
...
...
14
#endif // _AIX
29
#endif // _AIX
15
30
16
#include <unistd.h>
31
#include <unistd.h>
17
#include <fcntl.h>
32
#include <fcntl.h>
18
#include <sys/time.h>
33
#include <sys/time.h>
19
20
#include <sys/socket.h>
34
#include <sys/socket.h>
35
#include <sys/un.h>
21
#include <netinet/in.h>
36
#include <netinet/in.h>
22
#include <netinet/tcp.h>
37
#include <netinet/tcp.h>
23
#include <arpa/inet.h>
38
#include <arpa/inet.h>
24
#include <netdb.h>
39
#include <netdb.h>
25
40
26
#include <map>
41
#include <map>
27
42
28
#ifndef NO_NAMESPACES
43
44
#ifdef RECOLL_DATADIR
45
#include "debuglog.h"
46
47
#else
48
49
#define LOGFATAL(X)
50
#define LOGERR(X)
51
#define LOGINFO(X)
52
#define LOGDEB(X)
53
#define LOGDEB0(X)
54
#define LOGDEB1(X)
55
#define LOGDEB2(X)
56
#define LOGDEB3(X)
57
#define LOGDEB4(X)
58
#endif
59
60
#include "netcon.h"
61
29
using namespace std;
62
using namespace std;
30
#endif
31
32
#include "debuglog.h"
33
#include "netcon.h"
34
63
35
#ifndef SOCKLEN_T
64
#ifndef SOCKLEN_T
36
#define SOCKLEN_T socklen_t
65
#define SOCKLEN_T socklen_t
66
#endif
67
68
// Size of path buffer in sockaddr_un (AF_UNIX socket
69
// addr). Mysteriously it's 108 (explicit value) under linux, no
70
// define accessible. Let's take a little margin as it appears that
71
// some systems use 92. I believe we could also malloc a variable size
72
// struct but why bother.
73
#ifndef UNIX_PATH_MAX
74
#define UNIX_PATH_MAX 90
37
#endif
75
#endif
38
76
39
// Need &one, &zero for setsockopt...
77
// Need &one, &zero for setsockopt...
40
static const int one = 1;
78
static const int one = 1;
41
static const int zero = 0;
79
static const int zero = 0;
...
...
70
    tv.tv_sec = timeo;
108
    tv.tv_sec = timeo;
71
    tv.tv_usec =  0;
109
    tv.tv_usec =  0;
72
    FD_ZERO(&rd);
110
    FD_ZERO(&rd);
73
    FD_SET(fd, &rd);
111
    FD_SET(fd, &rd);
74
    if (write) {
112
    if (write) {
75
  ret = select(fd+1, 0, &rd, 0, &tv);
113
        ret = select(fd+1, 0, &rd, 0, &tv);
76
    } else {
114
    } else {
77
  ret = select(fd+1, &rd, 0, 0, &tv);
115
        ret = select(fd+1, &rd, 0, 0, &tv);
78
    }
116
    }
79
    if (!FD_ISSET(fd, &rd)) {
117
    if (!FD_ISSET(fd, &rd)) {
80
  LOGERR(("Netcon::select1: fd not ready after select ??\n"));
118
        LOGERR(("Netcon::select1: fd not ready after select ??\n"));
81
  return -1;
119
        return -1;
82
    }
120
    }
83
    return ret;
121
    return ret;
84
}
122
}
85
123
86
void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms)
124
void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms)
87
{
125
{
88
    m_periodichandler = handler;
126
    m_periodichandler = handler;
89
    m_periodicparam = p;
127
    m_periodicparam = p;
90
    m_periodicmillis = ms;
128
    m_periodicmillis = ms;
91
    if (m_periodicmillis > 0)
129
    if (m_periodicmillis > 0) {
92
  gettimeofday(&m_lasthdlcall, 0);
130
        gettimeofday(&m_lasthdlcall, 0);
131
    }
93
}
132
}
94
133
95
// Compute the appropriate timeout so that the select call returns in
134
// Compute the appropriate timeout so that the select call returns in
96
// time to call the periodic routine.
135
// time to call the periodic routine.
97
void SelectLoop::periodictimeout(struct timeval *tv)
136
void SelectLoop::periodictimeout(struct timeval *tv)
98
{
137
{
99
    // If periodic not set, the select call times out and we loop
138
    // If periodic not set, the select call times out and we loop
100
    // after a very long time (we'd need to pass NULL to select for an
139
    // after a very long time (we'd need to pass NULL to select for an
101
    // infinite wait, and I'm too lazy to handle it)
140
    // infinite wait, and I'm too lazy to handle it)
102
    if (m_periodicmillis <= 0) {
141
    if (m_periodicmillis <= 0) {
103
  tv->tv_sec = 10000;
142
        tv->tv_sec = 10000;
104
  tv->tv_usec = 0;
143
        tv->tv_usec = 0;
105
  return;
144
        return;
106
    }
145
    }
107
146
108
    struct timeval mtv;
147
    struct timeval mtv;
109
    gettimeofday(&mtv, 0);
148
    gettimeofday(&mtv, 0);
110
    int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
149
    int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
111
150
112
    // millis <= 0 means we should have already done the thing. *dont* set the 
151
    // millis <= 0 means we should have already done the thing. *dont* set the
113
    // tv to 0, which means no timeout at all !
152
    // tv to 0, which means no timeout at all !
114
    if (millis <= 0)
153
    if (millis <= 0) {
115
  millis = 1;
154
        millis = 1;
155
    }
116
    tv->tv_sec = millis / 1000;
156
    tv->tv_sec = millis / 1000;
117
    tv->tv_usec = (millis % 1000) * 1000;
157
    tv->tv_usec = (millis % 1000) * 1000;
118
}
158
}
119
159
120
// Check if it's time to call the handler. selectloop will return to
160
// Check if it's time to call the handler. selectloop will return to
121
// caller if it or we return 0
161
// caller if it or we return 0
122
int SelectLoop::maybecallperiodic()
162
int SelectLoop::maybecallperiodic()
123
{
163
{
124
    if (m_periodicmillis <= 0)
164
    if (m_periodicmillis <= 0) {
125
  return 1;
165
        return 1;
166
    }
126
    struct timeval mtv;
167
    struct timeval mtv;
127
    gettimeofday(&mtv, 0);
168
    gettimeofday(&mtv, 0);
128
    int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
169
    int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv);
129
    if (millis <= 0) {
170
    if (millis <= 0) {
130
  gettimeofday(&m_lasthdlcall, 0);
171
        gettimeofday(&m_lasthdlcall, 0);
131
  if (m_periodichandler)
172
        if (m_periodichandler) {
132
      return m_periodichandler(m_periodicparam);
173
            return m_periodichandler(m_periodicparam);
133
  else 
174
        } else {
134
      return 0;
175
            return 0;
176
        }
135
    }
177
    }
136
    return 1;
178
    return 1;
137
}
179
}
138
180
139
int SelectLoop::doLoop()
181
int SelectLoop::doLoop()
140
{
182
{
141
    for (;;) {
183
    for (;;) {
142
  if (m_selectloopDoReturn) {
184
        if (m_selectloopDoReturn) {
143
      m_selectloopDoReturn = false;
185
            m_selectloopDoReturn = false;
144
      LOGDEB(("Netcon::selectloop: returning on request\n"));
186
            LOGDEB(("Netcon::selectloop: returning on request\n"));
145
      return m_selectloopReturnValue;
187
            return m_selectloopReturnValue;
146
  }
188
        }
147
  int nfds;
189
        int nfds;
148
  fd_set rd, wd;
190
        fd_set rd, wd;
149
  FD_ZERO(&rd);
191
        FD_ZERO(&rd);
150
  FD_ZERO(&wd);
192
        FD_ZERO(&wd);
151
  
193
152
  // Walk the netcon map and set up the read and write fd_sets
194
        // Walk the netcon map and set up the read and write fd_sets
153
  // for select()
195
        // for select()
154
  nfds = 0;
196
        nfds = 0;
155
  for (map<int,NetconP>::iterator it = m_polldata.begin();
197
        for (map<int,NetconP>::iterator it = m_polldata.begin();
156
       it != m_polldata.end(); it++) {
198
                it != m_polldata.end(); it++) {
157
      NetconP &pll = it->second;
199
            NetconP &pll = it->second;
158
      int fd  = it->first;
200
            int fd  = it->first;
159
      LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
201
            LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
160
      if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
202
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
161
      FD_SET(fd, &rd);
203
                FD_SET(fd, &rd);
162
      nfds = MAX(nfds, fd + 1);
204
                nfds = MAX(nfds, fd + 1);
163
      }
205
            }
164
      if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
206
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
165
      FD_SET(fd, &wd);
207
                FD_SET(fd, &wd);
166
      nfds = MAX(nfds, fd + 1);
208
                nfds = MAX(nfds, fd + 1);
167
      }
209
            }
168
  }
210
        }
169
211
170
  if (nfds == 0) {
212
        if (nfds == 0) {
171
      // This should never happen in a server as we should at least
213
            // This should never happen in a server as we should at least
172
      // always monitor the main listening server socket. For a
214
            // always monitor the main listening server socket. For a
173
      // client, it's up to client code to avoid or process this
215
            // client, it's up to client code to avoid or process this
174
      // condition.
216
            // condition.
175
217
176
      // Just in case there would still be open fds in there
218
            // Just in case there would still be open fds in there
177
      // (with no r/w flags set). Should not be needed, but safer
219
            // (with no r/w flags set). Should not be needed, but safer
178
      m_polldata.clear();
220
            m_polldata.clear();
179
      LOGDEB1(("Netcon::selectloop: no fds\n"));
221
            LOGDEB1(("Netcon::selectloop: no fds\n"));
180
      return 0;
222
            return 0;
181
  }
223
        }
182
224
183
  LOGDEB2(("Netcon::selectloop: selecting, nfds = %d\n", nfds));
225
        LOGDEB2(("Netcon::selectloop: selecting, nfds = %d\n", nfds));
184
226
185
  // Compute the next timeout according to what might need to be
227
        // Compute the next timeout according to what might need to be
186
  // done apart from waiting for data
228
        // done apart from waiting for data
187
  struct timeval tv;
229
        struct timeval tv;
188
  periodictimeout(&tv);
230
        periodictimeout(&tv);
189
  // Wait for something to happen
231
        // Wait for something to happen
190
  int ret = select(nfds, &rd, &wd, 0, &tv);
232
        int ret = select(nfds, &rd, &wd, 0, &tv);
191
  LOGDEB2(("Netcon::selectloop: select returns %d\n", ret));
233
        LOGDEB2(("Netcon::selectloop: select returns %d\n", ret));
192
  if (ret < 0) {
234
        if (ret < 0) {
193
      LOGSYSERR("Netcon::selectloop", "select", "");
235
            LOGSYSERR("Netcon::selectloop", "select", "");
194
      return -1;
236
            return -1;
195
  }
237
        }
196
  if (m_periodicmillis > 0)
238
        if (m_periodicmillis > 0)
197
      if (maybecallperiodic() <= 0)
239
            if (maybecallperiodic() <= 0) {
198
      return 1;
240
                return 1;
241
            }
199
242
200
  // Timeout, do it again.
243
        // Timeout, do it again.
201
  if (ret == 0) 
244
        if (ret == 0) {
202
      continue;
245
            continue;
246
        }
203
247
204
  // We don't start the fd sweep at 0, else some fds would be advantaged.
248
        // We don't start the fd sweep at 0, else some fds would be advantaged.
205
  // Note that we do an fd sweep, not a map sweep. This is
249
        // Note that we do an fd sweep, not a map sweep. This is
206
  // inefficient because the fd array may be very sparse. Otoh, the
250
        // inefficient because the fd array may be very sparse. Otoh, the
207
  // map may change between 2 sweeps, so that we'd have to be smart
251
        // map may change between 2 sweeps, so that we'd have to be smart
208
  // with the iterator. As the cost per unused fd is low (just 2 bit
252
        // with the iterator. As the cost per unused fd is low (just 2 bit
209
  // flag tests), we keep it like this for now
253
        // flag tests), we keep it like this for now
210
  if (m_placetostart >= nfds) 
254
        if (m_placetostart >= nfds) {
211
      m_placetostart = 0;
255
            m_placetostart = 0;
212
  int i, fd;
256
        }
257
        int i, fd;
213
  for (i = 0, fd = m_placetostart; i < nfds;i++, fd++) {
258
        for (i = 0, fd = m_placetostart; i < nfds; i++, fd++) {
214
      if (fd >= nfds)
259
            if (fd >= nfds) {
215
      fd = 0;
260
                fd = 0;
261
            }
216
262
217
      int canread = FD_ISSET(fd, &rd);
263
            int canread = FD_ISSET(fd, &rd);
218
      int canwrite = FD_ISSET(fd, &wd);
264
            int canwrite = FD_ISSET(fd, &wd);
219
      bool none = !canread && !canwrite;
265
            bool none = !canread && !canwrite;
220
      LOGDEB2(("Netcon::selectloop: fd %d %s %s %s\n", fd,
266
            LOGDEB2(("Netcon::selectloop: fd %d %s %s %s\n", fd,
221
          none ? "blocked" : "can" , canread ? "read" : "", 
267
                     none ? "blocked" : "can" , canread ? "read" : "",
222
          canwrite ? "write" : ""));
268
                     canwrite ? "write" : ""));
223
      if (none)
269
            if (none) {
224
      continue;
270
                continue;
271
            }
225
272
226
      map<int,NetconP>::iterator it = m_polldata.find(fd);
273
            map<int,NetconP>::iterator it = m_polldata.find(fd);
227
      if (it == m_polldata.end()) {
274
            if (it == m_polldata.end()) {
228
      /// This should not happen actually
275
                /// This should not happen actually
229
      LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
276
                LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
230
      continue;
277
                continue;
231
      }
278
            }
232
279
233
      // Next start will be one beyond last serviced (modulo nfds)
280
            // Next start will be one beyond last serviced (modulo nfds)
234
      m_placetostart = fd + 1;
281
            m_placetostart = fd + 1;
235
      NetconP &pll = it->second;
282
            NetconP &pll = it->second;
236
      if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0)
283
            if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) {
237
      pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
284
                pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
285
            }
238
      if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0)
286
            if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
239
      pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
287
                pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
288
            }
240
      if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) {
289
            if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) {
241
      LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n", 
290
                LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
242
           it->first, it->second->m_wantedEvents));
291
                         it->first, it->second->m_wantedEvents));
243
      m_polldata.erase(it);
292
                m_polldata.erase(it);
244
      }
293
            }
245
  } // fd sweep
294
        } // fd sweep
246
295
247
    } // forever loop
296
    } // forever loop
248
    LOGERR(("SelectLoop::doLoop: got out of loop !\n"));
297
    LOGERR(("SelectLoop::doLoop: got out of loop !\n"));
249
    return -1;
298
    return -1;
250
}
299
}
251
300
252
// Add a connection to the monitored set.
301
// Add a connection to the monitored set.
253
int SelectLoop::addselcon(NetconP con, int events)
302
int SelectLoop::addselcon(NetconP con, int events)
254
{
303
{
255
    if (con.isNull()) return -1;
304
    if (!con) {
305
        return -1;
306
    }
256
    LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd));
307
    LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd));
257
    con->set_nonblock(1);
308
    con->set_nonblock(1);
258
    con->setselevents(events);
309
    con->setselevents(events);
259
    m_polldata[con->m_fd] = con;
310
    m_polldata[con->m_fd] = con;
260
    con->setloop(this);
311
    con->setloop(this);
...
...
262
}
313
}
263
314
264
// Remove a connection from the monitored set.
315
// Remove a connection from the monitored set.
265
int SelectLoop::remselcon(NetconP con)
316
int SelectLoop::remselcon(NetconP con)
266
{
317
{
267
    if (con.isNull()) return -1;
318
    if (!con) {
319
        return -1;
320
    }
268
    LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
321
    LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
269
    map<int,NetconP>::iterator it = m_polldata.find(con->m_fd);
322
    map<int,NetconP>::iterator it = m_polldata.find(con->m_fd);
270
    if (it == m_polldata.end()) {
323
    if (it == m_polldata.end()) {
271
  LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
324
        LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
272
  return -1;
325
        return -1;
273
    }
326
    }
274
    con->setloop(0);
327
    con->setloop(0);
275
    m_polldata.erase(it);
328
    m_polldata.erase(it);
276
    return 0;
329
    return 0;
277
}
330
}
278
331
279
//////////////////////////////////////////////////////////
332
//////////////////////////////////////////////////////////
280
// Base class (Netcon) methods
333
// Base class (Netcon) methods
281
Netcon::~Netcon() {
334
Netcon::~Netcon() 
335
{
282
    closeconn();
336
    closeconn();
283
    if (m_peer) {
337
    if (m_peer) {
284
  free(m_peer);
338
        free(m_peer);
285
  m_peer = 0;
339
        m_peer = 0;
286
    }
340
    }
287
}
341
}
288
342
289
void Netcon::closeconn() 
343
void Netcon::closeconn()
290
{
344
{
291
    if (m_ownfd && m_fd >= 0) {
345
    if (m_ownfd && m_fd >= 0) {
292
  close(m_fd);
346
        close(m_fd);
293
    }
347
    }
294
    m_fd = -1;
348
    m_fd = -1;
295
    m_ownfd = true;
349
    m_ownfd = true;
296
}
350
}
297
351
...
...
300
    return strerror(errno);
354
    return strerror(errno);
301
}
355
}
302
356
303
void Netcon::setpeer(const char *hostname)
357
void Netcon::setpeer(const char *hostname)
304
{
358
{
305
    if (m_peer)
359
    if (m_peer) {
306
  free(m_peer);
360
        free(m_peer);
361
    }
307
    m_peer = strdup(hostname);
362
    m_peer = strdup(hostname);
308
}
363
}
309
364
310
int Netcon::settcpnodelay(int on)
365
int Netcon::settcpnodelay(int on)
311
{
366
{
312
    LOGDEB2(( "Netcon::settcpnodelay\n" ));
367
    LOGDEB2(( "Netcon::settcpnodelay\n" ));
313
    if (m_fd < 0) {
368
    if (m_fd < 0) {
314
  LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
369
        LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
315
  return -1;
370
        return -1;
316
    }
371
    }
317
    char *cp = on ? (char *)&one : (char *)&zero;
372
    char *cp = on ? (char *)&one : (char *)&zero;
318
    if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, cp, sizeof(one)) < 0) {
373
    if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, cp, sizeof(one)) < 0) {
319
  LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY");
374
        LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY");
320
  return -1;
375
        return -1;
321
    }
376
    }
322
    return 0;
377
    return 0;
323
}
378
}
324
379
325
// Set/reset non-blocking flag on fd
380
// Set/reset non-blocking flag on fd
326
int Netcon::set_nonblock(int onoff)
381
int Netcon::set_nonblock(int onoff)
327
{
382
{
328
    int  flags = fcntl(m_fd, F_GETFL, 0);
383
    int  flags = fcntl(m_fd, F_GETFL, 0);
329
    if (flags != -1 )   {
384
    if (flags != -1 )   {
330
  int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK;
385
        int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK;
331
  if (newflags != flags)
386
        if (newflags != flags)
332
      if (fcntl(m_fd, F_SETFL, newflags)< 0)
387
            if (fcntl(m_fd, F_SETFL, newflags) < 0) {
333
      return -1;
388
                return -1;
389
            }
334
    }
390
    }
335
    return flags;
391
    return flags;
336
}
392
}
337
393
338
/////////////////////////////////////////////////////////////////////
394
/////////////////////////////////////////////////////////////////////
339
// Data socket (NetconData) methods
395
// Data socket (NetconData) methods
340
396
341
NetconData::~NetconData() {
397
NetconData::~NetconData() 
398
{
342
    freeZ(m_buf);
399
    freeZ(m_buf);
343
    m_bufbase = 0;
400
    m_bufbase = 0;
344
    m_bufbytes = m_bufsize = 0;
401
    m_bufbytes = m_bufsize = 0;
345
}
402
}
346
403
347
int NetconData::send(const char *buf, int cnt, int expedited)
404
int NetconData::send(const char *buf, int cnt, int expedited)
348
{
405
{
349
    LOGDEB2(("NetconData::send: fd %d cnt %d expe %d\n", m_fd, cnt, expedited));
406
    LOGDEB2(("NetconData::send: fd %d cnt %d expe %d\n", m_fd, cnt, expedited));
350
    int flag = 0;
407
    int flag = 0;
351
    if (m_fd < 0) {
408
    if (m_fd < 0) {
352
  LOGERR(("NetconData::send: connection not opened\n"));
409
        LOGERR(("NetconData::send: connection not opened\n"));
353
  return -1;
410
        return -1;
354
    }
411
    }
355
    if (expedited) {
412
    if (expedited) {
356
  LOGDEB2(("NetconData::send: expedited data, count %d bytes\n", cnt));
413
        LOGDEB2(("NetconData::send: expedited data, count %d bytes\n", cnt));
357
  flag = MSG_OOB;
414
        flag = MSG_OOB;
358
    }
415
    }
359
    int ret;
416
    int ret;
360
    // There is a bug in the uthread version of sendto() in FreeBSD at
417
    // There is a bug in the uthread version of sendto() in FreeBSD at
361
    // least up to 2.2.7, so avoid using it when possible
418
    // least up to 2.2.7, so avoid using it when possible
362
    if (flag)
419
    if (flag) {
363
  ret = ::send(m_fd, buf, cnt, flag);
420
        ret = ::send(m_fd, buf, cnt, flag);
364
    else 
421
    } else {
365
  ret = ::write(m_fd, buf, cnt);
422
        ret = ::write(m_fd, buf, cnt);
423
    }
366
424
367
    // Note: byte count may be different from cnt if fd is non-blocking
425
    // Note: byte count may be different from cnt if fd is non-blocking
368
    if (ret < 0) {
426
    if (ret < 0) {
369
  char fdcbuf[20];sprintf(fdcbuf, "%d", m_fd);
427
        char fdcbuf[20];
428
        sprintf(fdcbuf, "%d", m_fd);
370
  LOGSYSERR("NetconData::send", "send", fdcbuf);
429
        LOGSYSERR("NetconData::send", "send", fdcbuf);
371
    }
430
    }
372
    return ret;
431
    return ret;
373
}
432
}
374
433
375
// Test for data available
434
// Test for data available
376
int NetconData::readready()
435
int NetconData::readready()
377
{
436
{
378
    LOGDEB2(("NetconData::readready\n"));
437
    LOGDEB2(("NetconData::readready\n"));
379
    if (m_fd < 0) {
438
    if (m_fd < 0) {
380
  LOGERR(("NetconData::readready: connection not opened\n"));
439
        LOGERR(("NetconData::readready: connection not opened\n"));
381
  return -1;
440
        return -1;
382
    }
441
    }
383
    return select1(m_fd, 0);
442
    return select1(m_fd, 0);
384
}
443
}
385
444
386
// Test for writable
445
// Test for writable
387
int NetconData::writeready()
446
int NetconData::writeready()
388
{
447
{
389
    LOGDEB2(("NetconData::writeready\n"));
448
    LOGDEB2(("NetconData::writeready\n"));
390
    if (m_fd < 0) {
449
    if (m_fd < 0) {
391
  LOGERR(("NetconData::writeready: connection not opened\n"));
450
        LOGERR(("NetconData::writeready: connection not opened\n"));
392
  return -1;
451
        return -1;
393
    }
452
    }
394
    return select1(m_fd, 0, 1);
453
    return select1(m_fd, 0, 1);
395
}
454
}
396
455
397
// Receive at most cnt bytes (maybe less)
456
// Receive at most cnt bytes (maybe less)
398
int NetconData::receive(char *buf, int cnt, int timeo)
457
int NetconData::receive(char *buf, int cnt, int timeo)
399
{
458
{
400
    LOGDEB2(("NetconData::receive: cnt %d timeo %d m_buf 0x%x m_bufbytes %d\n",
459
    LOGDEB2(("NetconData::receive: cnt %d timeo %d m_buf 0x%x m_bufbytes %d\n",
401
       cnt, timeo, m_buf, m_bufbytes));
460
             cnt, timeo, m_buf, m_bufbytes));
402
    if (m_fd < 0) {
461
    if (m_fd < 0) {
403
  LOGERR(("NetconData::receive: connection not opened\n"));
462
        LOGERR(("NetconData::receive: connection not opened\n"));
404
  return -1;
463
        return -1;
405
    }
464
    }
406
    int fromibuf = 0;
465
    int fromibuf = 0;
407
    // Get whatever might have been left in the buffer by a previous 
466
    // Get whatever might have been left in the buffer by a previous
408
    // getline, except if we're called to fill the buffer of course
467
    // getline, except if we're called to fill the buffer of course
409
    if (m_buf && m_bufbytes > 0 && (buf < m_buf || buf > m_buf + m_bufsize)) {
468
    if (m_buf && m_bufbytes > 0 && (buf < m_buf || buf > m_buf + m_bufsize)) {
410
  fromibuf = MIN(m_bufbytes, cnt);
469
        fromibuf = MIN(m_bufbytes, cnt);
411
  memcpy(buf, m_bufbase, fromibuf);
470
        memcpy(buf, m_bufbase, fromibuf);
412
  m_bufbytes -= fromibuf;
471
        m_bufbytes -= fromibuf;
413
  m_bufbase += fromibuf;
472
        m_bufbase += fromibuf;
414
  cnt -= fromibuf;
473
        cnt -= fromibuf;
415
        LOGDEB2(("NetconData::receive: transferred %d from mbuf\n", fromibuf));
474
        LOGDEB2(("NetconData::receive: transferred %d from mbuf\n", fromibuf));
416
  if (cnt <= 0)
475
        if (cnt <= 0) {
417
      return fromibuf;
476
            return fromibuf;
477
        }
418
    }
478
    }
419
    if (timeo > 0) {
479
    if (timeo > 0) {
420
  int ret = select1(m_fd, timeo);
480
        int ret = select1(m_fd, timeo);
421
  if (ret == 0) {
481
        if (ret == 0) {
422
      LOGDEB2(("NetconData::receive timed out\n"));
482
            LOGDEB2(("NetconData::receive timed out\n"));
423
      m_didtimo = 1;
483
            m_didtimo = 1;
424
      return -1;
484
            return -1;
425
  }
485
        }
426
  if (ret < 0) {
486
        if (ret < 0) {
427
      LOGSYSERR("NetconData::receive", "select", "");
487
            LOGSYSERR("NetconData::receive", "select", "");
428
      return -1;
488
            return -1;
429
  }
489
        }
430
    }
490
    }
431
    m_didtimo = 0;
491
    m_didtimo = 0;
432
    if ((cnt = read(m_fd, buf + fromibuf, cnt)) < 0) {
492
    if ((cnt = read(m_fd, buf + fromibuf, cnt)) < 0) {
433
  char fdcbuf[20];sprintf(fdcbuf, "%d", m_fd);
493
        char fdcbuf[20];
494
        sprintf(fdcbuf, "%d", m_fd);
434
  LOGSYSERR("NetconData::receive", "read", fdcbuf);
495
        LOGSYSERR("NetconData::receive", "read", fdcbuf);
435
  return -1;
496
        return -1;
436
    }
497
    }
437
    LOGDEB2(("NetconData::receive: normal return, cnt %d\n", cnt));
498
    LOGDEB2(("NetconData::receive: normal return, cnt %d\n", cnt));
438
    return fromibuf + cnt;
499
    return fromibuf + cnt;
439
}
500
}
440
501
...
...
443
{
504
{
444
    int got, cur;
505
    int got, cur;
445
    LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
506
    LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
446
    cur = 0;
507
    cur = 0;
447
    while (cnt > cur) {
508
    while (cnt > cur) {
448
  got = receive(buf, cnt-cur, timeo);
509
        got = receive(buf, cnt-cur, timeo);
449
  LOGDEB2(("Netcon::doreceive: got %d\n", got));
510
        LOGDEB2(("Netcon::doreceive: got %d\n", got));
450
  if (got < 0) {
511
        if (got < 0) {
451
      return -1;
512
            return -1;
452
  }
513
        }
453
  if (got == 0) {
514
        if (got == 0) {
454
      return cur;
515
            return cur;
455
  }
516
        }
456
  cur += got;
517
        cur += got;
457
  buf += got;
518
        buf += got;
458
    }
519
    }
459
    return cur;
520
    return cur;
460
}
521
}
461
522
462
// Read data until cnt-1 characters are read or a newline is found. Add
523
// Read data until cnt-1 characters are read or a newline is found. Add
...
...
470
static const int defbufsize = 200;
531
static const int defbufsize = 200;
471
int NetconData::getline(char *buf, int cnt, int timeo)
532
int NetconData::getline(char *buf, int cnt, int timeo)
472
{
533
{
473
    LOGDEB2(("NetconData::getline: cnt %d, timeo %d\n", cnt, timeo));
534
    LOGDEB2(("NetconData::getline: cnt %d, timeo %d\n", cnt, timeo));
474
    if (m_buf == 0) {
535
    if (m_buf == 0) {
475
  if ((m_buf = (char *)malloc(defbufsize)) == 0) {
536
        if ((m_buf = (char *)malloc(defbufsize)) == 0) {
476
      LOGSYSERR("NetconData::getline: Out of mem", "malloc", "");
537
            LOGSYSERR("NetconData::getline: Out of mem", "malloc", "");
477
      return -1;
538
            return -1;
478
  }
539
        }
479
  m_bufsize = defbufsize;
540
        m_bufsize = defbufsize;
480
  m_bufbase = m_buf;
541
        m_bufbase = m_buf;
481
  m_bufbytes = 0;
542
        m_bufbytes = 0;
482
    }
543
    }
483
544
484
    char *cp = buf;
545
    char *cp = buf;
485
    for (;;) {
546
    for (;;) {
486
  // Transfer from buffer. Have to take a lot of care to keep counts and
547
        // Transfer from buffer. Have to take a lot of care to keep counts and
487
  // pointers consistant in all end cases
548
        // pointers consistant in all end cases
488
  int maxtransf = MIN(m_bufbytes, cnt-1);
549
        int maxtransf = MIN(m_bufbytes, cnt-1);
489
  int nn = maxtransf;
550
        int nn = maxtransf;
490
  LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n", 
551
        LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n",
491
       m_bufbytes, maxtransf, nn));
552
                 m_bufbytes, maxtransf, nn));
492
  for (nn = maxtransf; nn > 0;) {
553
        for (nn = maxtransf; nn > 0;) {
493
      // This is not pretty but we want nn to be decremented for
554
            // This is not pretty but we want nn to be decremented for
494
      // each byte copied (even newline), and not become -1 if
555
            // each byte copied (even newline), and not become -1 if
495
      // we go to the end. Better ways welcome!
556
            // we go to the end. Better ways welcome!
496
      nn--;
557
            nn--;
497
      if ((*cp++ = *m_bufbase++) == '\n')
558
            if ((*cp++ = *m_bufbase++) == '\n') {
498
      break;
559
                break;
499
  }
560
            }
561
        }
500
  // Update counts
562
        // Update counts
501
  maxtransf -= nn; // Actual count transferred
563
        maxtransf -= nn; // Actual count transferred
502
  m_bufbytes -= maxtransf;
564
        m_bufbytes -= maxtransf;
503
  cnt -= maxtransf;
565
        cnt -= maxtransf;
504
  LOGDEB2(("After transfer: actual transf %d cnt %d, m_bufbytes %d\n",
566
        LOGDEB2(("After transfer: actual transf %d cnt %d, m_bufbytes %d\n",
505
       maxtransf, cnt, m_bufbytes));
567
                 maxtransf, cnt, m_bufbytes));
506
568
507
  // Finished ?
569
        // Finished ?
508
  if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) {
570
        if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) {
509
      *cp = 0;
571
            *cp = 0;
510
      return cp - buf;
572
            return cp - buf;
511
  }
573
        }
512
574
513
  // Transfer from net
575
        // Transfer from net
514
  m_bufbase = m_buf;
576
        m_bufbase = m_buf;
515
  m_bufbytes = receive(m_buf, m_bufsize, timeo);   
577
        m_bufbytes = receive(m_buf, m_bufsize, timeo);
516
  if (m_bufbytes == 0) {
578
        if (m_bufbytes == 0) {
517
      // EOF
579
            // EOF
518
      *cp = 0;
580
            *cp = 0;
519
      return cp - buf;
581
            return cp - buf;
520
  }
582
        }
521
  if (m_bufbytes < 0) {
583
        if (m_bufbytes < 0) {
522
      m_bufbytes = 0;
584
            m_bufbytes = 0;
523
      *cp = 0;
585
            *cp = 0;
524
      return -1;
586
            return -1;
525
  }
587
        }
526
    }
588
    }
527
}
589
}
528
590
529
// Called when selectloop detects that data can be read or written on
591
// Called when selectloop detects that data can be read or written on
530
// the connection. The user callback would normally have been set
592
// the connection. The user callback would normally have been set
531
// up. If it is, call it and return. Else, perform housecleaning: read
593
// up. If it is, call it and return. Else, perform housecleaning: read
532
// and discard.
594
// and discard.
533
int NetconData::cando(Netcon::Event reason)
595
int NetconData::cando(Netcon::Event reason)
534
{
596
{
535
    LOGDEB2(("NetconData::cando\n"));
597
    LOGDEB2(("NetconData::cando\n"));
536
    if (!m_user.isNull()) {
598
    if (m_user) {
537
  return m_user->data(this, reason);
599
        return m_user->data(this, reason);
538
    }
600
    }
539
601
540
    // No user callback. Clean up by ourselves
602
    // No user callback. Clean up by ourselves
541
    if (reason & NETCONPOLL_READ) {
603
    if (reason & NETCONPOLL_READ) {
542
#define BS 200
604
#define BS 200
543
  char buf[BS];
605
        char buf[BS];
544
  int n;
606
        int n;
545
  if ((n = receive(buf, BS)) < 0) {
607
        if ((n = receive(buf, BS)) < 0) {
546
      LOGSYSERR("NetconData::cando", "receive", "");
608
            LOGSYSERR("NetconData::cando", "receive", "");
547
      return -1;
609
            return -1;
548
  }
610
        }
549
  if (n == 0) {
611
        if (n == 0) {
550
      // EOF
612
            // EOF
551
      return 0;
613
            return 0;
552
  }
614
        }
553
    }
615
    }
554
    clearselevents(NETCONPOLL_WRITE);
616
    clearselevents(NETCONPOLL_WRITE);
555
    return 1;
617
    return 1;
556
}
618
}
557
619
...
...
562
    int ret = -1;
624
    int ret = -1;
563
    LOGDEB2(("Netconcli::openconn: host %s, port %d\n", host, port));
625
    LOGDEB2(("Netconcli::openconn: host %s, port %d\n", host, port));
564
626
565
    closeconn();
627
    closeconn();
566
628
629
    struct sockaddr *saddr;
630
    socklen_t addrsize;
631
567
    struct sockaddr_in saddr;
632
    struct sockaddr_in ip_addr;
633
    struct sockaddr_un unix_addr;
634
    if (host[0] != '/') {
568
    memset(&saddr, 0, sizeof(saddr));
635
        memset(&ip_addr, 0, sizeof(ip_addr));
569
    saddr.sin_family = AF_INET;
636
        ip_addr.sin_family = AF_INET;
570
    saddr.sin_port = htons(port);
637
        ip_addr.sin_port = htons(port);
571
638
572
    // Server name may be host name or IP address
639
        // Server name may be host name or IP address
573
    int addr;
640
        int addr;
574
    if ((addr = inet_addr(host)) != -1) {
641
        if ((addr = inet_addr(host)) != -1) {
575
  memcpy(&saddr.sin_addr, &addr, sizeof(addr));
642
            memcpy(&ip_addr.sin_addr, &addr, sizeof(addr));
643
        } else {
644
            struct hostent *hp;
645
            if ((hp = gethostbyname(host)) == 0) {
646
                LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n", 
647
                        host));
648
                return -1;
649
            }
650
            memcpy(&ip_addr.sin_addr, hp->h_addr, hp->h_length);
651
        }
652
653
        if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
654
            LOGSYSERR("NetconCli::openconn", "socket", "");
655
            return -1;
656
        }
657
        addrsize = sizeof(ip_addr);
658
        saddr = (sockaddr*)&ip_addr;
576
    } else {
659
    } else {
577
  struct hostent *hp;
660
        memset(&unix_addr, 0, sizeof(unix_addr));
578
  if ((hp = gethostbyname(host)) == 0) {
661
        unix_addr.sun_family = AF_UNIX;
579
      LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n", host));
662
        if (strlen(host) > UNIX_PATH_MAX - 1) {
663
            LOGERR(("NetconCli::openconn: name too long: %s\n", host));
580
      return -1;
664
            return -1;
581
  }
582
  memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
583
    }
665
        }
666
        strcpy(unix_addr.sun_path, host);
584
667
585
    if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
668
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
586
  LOGSYSERR("NetconCli::openconn", "socket", "");
669
            LOGSYSERR("NetconCli::openconn", "socket", "");
587
  return -1;
670
            return -1;
588
    }
671
        }
672
        addrsize = sizeof(unix_addr);
673
        saddr = (sockaddr*)&unix_addr;
674
    }
589
    if (timeo > 0)
675
    if (timeo > 0) {
590
  set_nonblock(1);
676
        set_nonblock(1);
677
    }
591
678
592
    if(connect(m_fd,(struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
679
    if (connect(m_fd, saddr, addrsize) < 0) {
593
  if (timeo > 0) {
680
        if (timeo > 0) {
594
      if (errno != EINPROGRESS)
681
            if (errno != EINPROGRESS) {
595
      goto out;
682
                goto out;
683
            }
596
      if (select1(m_fd, timeo, 1) == 1)
684
            if (select1(m_fd, timeo, 1) == 1) {
597
      goto connectok;
685
                goto connectok;
598
  }
686
            }
687
        }
599
  if (m_silentconnectfailure == 0) {
688
        if (m_silentconnectfailure == 0) {
600
      LOGSYSERR("NetconCli", "connect", "");
689
            LOGSYSERR("NetconCli", "connect", "");
601
  }
602
  goto out;
603
    }
690
        }
691
        goto out;
692
    }
604
 connectok:
693
connectok:
605
    if (timeo > 0)
694
    if (timeo > 0) {
606
  set_nonblock(0);
695
        set_nonblock(0);
696
    }
607
697
608
    LOGDEB2(("NetconCli::connect: setting keepalive\n"));
698
    LOGDEB2(("NetconCli::connect: setting keepalive\n"));
609
    if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, 
699
    if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE,
610
         (char *)&one, sizeof(one)) < 0) {
700
                   (char *)&one, sizeof(one)) < 0) {
611
  LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE");
701
        LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE");
612
    }
702
    }
613
    setpeer(host);
703
    setpeer(host);
614
    LOGDEB2(("NetconCli::openconn: connection opened ok\n"));
704
    LOGDEB2(("NetconCli::openconn: connection opened ok\n"));
615
    ret = 0;
705
    ret = 0;
616
 out:
706
out:
617
    if (ret < 0)
707
    if (ret < 0) {
618
  closeconn();
708
        closeconn();
709
    }
619
    return ret;
710
    return ret;
620
}
711
}
621
712
622
// Same as previous, but get the port number from services
713
// Same as previous, but get the port number from services
623
int NetconCli::openconn(const char *host, char *serv, int timeo)
714
int NetconCli::openconn(const char *host, const char *serv, int timeo)
624
{
715
{
625
    LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv));
716
    LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv));
626
717
718
    if (host[0]  != '/') {
627
    struct servent *sp;
719
        struct servent *sp;
628
    if ((sp = getservbyname(serv, "tcp")) == 0) {
720
        if ((sp = getservbyname(serv, "tcp")) == 0) {
629
  LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv));
721
            LOGERR(("NetconCli::openconn: getservbyname failed for %s\n",serv));
630
  return -1;
722
            return -1;
631
    }
723
        }
632
    // Callee expects the port number in host byte order
724
        // Callee expects the port number in host byte order
633
    return openconn(host, ntohs(sp->s_port), timeo);
725
        return openconn(host, ntohs(sp->s_port), timeo);
726
    } else {
727
        return openconn(host, (unsigned int)0, timeo);
728
    }
634
}
729
}
635
730
636
731
637
int NetconCli::setconn(int fd)
732
int NetconCli::setconn(int fd)
638
{
733
{
...
...
645
740
646
    return 0;
741
    return 0;
647
}
742
}
648
743
649
///////////////////////////////////////////////////////////////////////
744
///////////////////////////////////////////////////////////////////////
650
// Methods for the main (listening) server connection 
745
// Methods for the main (listening) server connection
651
746
652
NetconServLis::~NetconServLis() {
747
NetconServLis::~NetconServLis() 
748
{
653
#ifdef NETCON_ACCESSCONTROL
749
#ifdef NETCON_ACCESSCONTROL
654
    freeZ(okaddrs.intarray);
750
    freeZ(okaddrs.intarray);
655
    freeZ(okmasks.intarray);
751
    freeZ(okmasks.intarray);
656
#endif 
752
#endif
657
}
753
}
658
754
659
#if 0
755
#if 0
660
// code for dumping a struct servent
756
// code for dumping a struct servent
661
static void dump_servent(struct servent *servp) {
757
static void dump_servent(struct servent *servp) 
758
{
662
    fprintf(stderr, "Official name %s\n", servp->s_name);
759
    fprintf(stderr, "Official name %s\n", servp->s_name);
663
    for (char **cpp = servp->s_aliases;*cpp;cpp++)
760
    for (char **cpp = servp->s_aliases; *cpp; cpp++) {
664
  fprintf(stderr, "Nickname %s\n", *cpp);
761
        fprintf(stderr, "Nickname %s\n", *cpp);
762
    }
665
    fprintf(stderr, "Port %d\n", (int)ntohs((short)servp->s_port));
763
    fprintf(stderr, "Port %d\n", (int)ntohs((short)servp->s_port));
666
    fprintf(stderr, "Proto %s\n", servp->s_proto);
764
    fprintf(stderr, "Proto %s\n", servp->s_proto);
667
}
765
}
668
#endif
766
#endif
669
767
670
// Set up service.
768
// Set up service.
671
int NetconServLis::openservice(char *serv, int backlog)
769
int NetconServLis::openservice(const char *serv, int backlog)
672
{
770
{
673
    int   port;
771
    int port;
674
    struct servent    *servp;
772
    struct servent  *servp;
773
    if (!serv) {
774
        LOGERR(("NetconServLis::openservice: null serv??\n"));
775
        return -1;
776
    }
675
    LOGDEB1(("NetconServLis::openservice: serv %s\n", serv));
777
    LOGDEB1(("NetconServLis::openservice: serv %s\n", serv));
676
#ifdef NETCON_ACCESSCONTROL
778
#ifdef NETCON_ACCESSCONTROL
677
    if (initperms(serv) < 0) 
779
    if (initperms(serv) < 0) {
678
  return -1;
780
        return -1;
781
    }
679
#endif
782
#endif
783
784
    m_serv = serv;
785
    if (serv[0] != '/') {
680
    if ((servp = getservbyname(serv, "tcp")) == 0) {
786
        if ((servp = getservbyname(serv, "tcp")) == 0) {
681
  LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n",serv));
787
            LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n",
682
  return -1;
788
                    serv));
789
            return -1;
683
    }
790
        }
684
    port = (int)ntohs((short)servp->s_port);
791
        port = (int)ntohs((short)servp->s_port);
685
    return openservice(port, backlog);
792
        return openservice(port, backlog);
793
    } else {
794
        if (strlen(serv) > UNIX_PATH_MAX - 1) {
795
            LOGERR(("NetconServLis::openservice: too long for AF_UNIX: %s\n",
796
                    serv));
797
            return -1;
798
        }
799
        int ret = -1;
800
        struct sockaddr_un  addr;
801
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
802
            LOGSYSERR("NetconServLis", "socket", "");
803
            return -1;
804
        }
805
        memset(&addr, 0, sizeof(addr));
806
        addr.sun_family = AF_UNIX;
807
        strcpy(addr.sun_path, serv);
808
809
        if (::bind(m_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
810
            LOGSYSERR("NetconServLis", "bind", "");
811
            goto out;
812
        }
813
        if (listen(m_fd, backlog) < 0) {
814
            LOGSYSERR("NetconServLis", "listen", "");
815
            goto out;
816
        }
817
818
        LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
819
        ret = 0;
820
    out:
821
        if (ret < 0 && m_fd >= 0) {
822
            close(m_fd);
823
            m_fd = -1;
824
        }
825
        return ret;
826
    }
686
}
827
}
687
828
688
// Port is a natural host integer value
829
// Port is a natural host integer value
689
int NetconServLis::openservice(int port, int backlog)
830
int NetconServLis::openservice(int port, int backlog)
690
{
831
{
691
    LOGDEB1(("NetconServLis::openservice: port %d\n", port));
832
    LOGDEB1(("NetconServLis::openservice: port %d\n", port));
692
#ifdef NETCON_ACCESSCONTROL
833
#ifdef NETCON_ACCESSCONTROL
693
    if (initperms(port) < 0) 
834
    if (initperms(port) < 0) {
694
  return -1;
835
        return -1;
836
    }
695
#endif
837
#endif
696
    int ret = -1;
838
    int ret = -1;
697
    struct sockaddr_in  ipaddr;
839
    struct sockaddr_in  ipaddr;
698
    if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
840
    if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
699
  LOGSYSERR("NetconServLis", "socket", "");
841
        LOGSYSERR("NetconServLis", "socket", "");
700
  return -1;
842
        return -1;
701
    }
843
    }
702
    (void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one));
844
    (void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one));
703
#ifdef SO_REUSEPORT
845
#ifdef SO_REUSEPORT
704
    (void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT,(char *)&one, sizeof(one));
846
    (void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT,(char *)&one, sizeof(one));
705
#endif /*SO_REUSEPORT*/
847
#endif /*SO_REUSEPORT*/
706
    memset(&ipaddr, 0, sizeof(ipaddr));
848
    memset(&ipaddr, 0, sizeof(ipaddr));
707
    ipaddr.sin_family = AF_INET;
849
    ipaddr.sin_family = AF_INET;
708
    ipaddr.sin_addr.s_addr = htonl(INADDR_ANY);
850
    ipaddr.sin_addr.s_addr = htonl(INADDR_ANY);
709
    ipaddr.sin_port = htons((short)port);
851
    ipaddr.sin_port = htons((short)port);
710
    if (bind(m_fd, (struct sockaddr *)&ipaddr, sizeof(ipaddr)) < 0){
852
    if (::bind(m_fd, (struct sockaddr *)&ipaddr, sizeof(ipaddr)) < 0) {
711
  LOGSYSERR("NetconServLis", "bind", "");
853
        LOGSYSERR("NetconServLis", "bind", "");
712
  goto out;
854
        goto out;
713
    }
855
    }
714
    if (listen(m_fd, backlog) < 0) {
856
    if (listen(m_fd, backlog) < 0) {
715
  LOGSYSERR("NetconServLis", "listen", "");
857
        LOGSYSERR("NetconServLis", "listen", "");
716
  goto out;
858
        goto out;
717
    }
859
    }
718
860
719
    LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
861
    LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
720
    ret = 0;
862
    ret = 0;
721
 out:
863
out:
722
    if (ret < 0 && m_fd >= 0) {
864
    if (ret < 0 && m_fd >= 0) {
723
  close(m_fd);
865
        close(m_fd);
724
  m_fd = -1;
866
        m_fd = -1;
725
    }
867
    }
726
    return ret;
868
    return ret;
727
}
869
}
728
870
729
#ifdef NETCON_ACCESSCONTROL
871
#ifdef NETCON_ACCESSCONTROL
730
int NetconServLis::initperms(int port)
872
int NetconServLis::initperms(int port)
731
{
873
{
732
    if (permsinit)
874
    if (permsinit) {
733
  return 0;
875
        return 0;
876
    }
734
877
735
    char sport[30];
878
    char sport[30];
736
    sprintf(sport, "%d", port);
879
    sprintf(sport, "%d", port);
737
    return initperms(sport);
880
    return initperms(sport);
738
}
881
}
739
882
740
// Get authorized address lists from parameter file. This is disabled for now
883
// Get authorized address lists from parameter file. This is disabled for now
741
int NetconServLis::initperms(char *serv)
884
int NetconServLis::initperms(const char *serv)
742
{
885
{
743
    if (permsinit)
886
    if (permsinit) {
744
  return 0;
887
        return 0;
888
    }
745
889
746
    if (serv == 0 || *serv == 0 || strlen(serv) > 80) {
890
    if (serv == 0 || *serv == 0 || strlen(serv) > 80) {
747
  LOGERR(("NetconServLis::initperms: bad service name %s\n", serv));
891
        LOGERR(("NetconServLis::initperms: bad service name %s\n", serv));
748
  return -1;
892
        return -1;
749
    }
893
    }
750
894
751
    char keyname[100];
895
    char keyname[100];
752
    sprintf(keyname, "%s_okaddrs", serv);
896
    sprintf(keyname, "%s_okaddrs", serv);
753
    if (genparams->getparam(keyname, &okaddrs, 1) < 0) {
897
    if (genparams->getparam(keyname, &okaddrs, 1) < 0) {
754
  serv = "default";
898
        serv = "default";
755
  sprintf(keyname, "%s_okaddrs", serv);
899
        sprintf(keyname, "%s_okaddrs", serv);
756
  if (genparams->getparam(keyname, &okaddrs) < 0) {
900
        if (genparams->getparam(keyname, &okaddrs) < 0) {
757
      LOGERR(("NetconServLis::initperms: no okaddrs found in config file\n"));
901
            LOGERR(("NetconServLis::initperms: no okaddrs found in config file\n"));
758
      return -1;
902
            return -1;
759
  }
903
        }
760
    }
904
    }
761
    sprintf(keyname, "%s_okmasks", serv);
905
    sprintf(keyname, "%s_okmasks", serv);
762
    if (genparams->getparam(keyname, &okmasks)) {
906
    if (genparams->getparam(keyname, &okmasks)) {
763
  LOGERR(("NetconServLis::initperms: okmasks not found\n"));
907
        LOGERR(("NetconServLis::initperms: okmasks not found\n"));
764
  return -1;
908
        return -1;
765
    }
909
    }
766
    if (okaddrs.len == 0 || okmasks.len == 0) {
910
    if (okaddrs.len == 0 || okmasks.len == 0) {
767
  LOGERR(("NetconServLis::initperms: len 0 for okmasks or okaddrs\n"));
911
        LOGERR(("NetconServLis::initperms: len 0 for okmasks or okaddrs\n"));
768
  return -1;
912
        return -1;
769
    }
913
    }
770
914
771
    permsinit = 1;
915
    permsinit = 1;
772
    return 0;
916
    return 0;
773
}
917
}
...
...
787
NetconServLis::accept(int timeo)
931
NetconServLis::accept(int timeo)
788
{
932
{
789
    LOGDEB(("NetconServLis::accept\n"));
933
    LOGDEB(("NetconServLis::accept\n"));
790
934
791
    if (timeo > 0) {
935
    if (timeo > 0) {
792
  int ret = select1(m_fd, timeo);
936
        int ret = select1(m_fd, timeo);
793
  if (ret == 0) {
937
        if (ret == 0) {
794
      LOGDEB2(("NetconServLis::accept timed out\n"));
938
            LOGDEB2(("NetconServLis::accept timed out\n"));
795
      m_didtimo = 1;
939
            m_didtimo = 1;
796
      return 0;
940
            return 0;
797
  }
941
        }
798
  if (ret < 0) {
942
        if (ret < 0) {
799
      LOGSYSERR("NetconServLis::accept", "select", "");
943
            LOGSYSERR("NetconServLis::accept", "select", "");
800
      return 0;
944
            return 0;
801
  }
945
        }
802
    }
946
    }
803
    m_didtimo = 0;
947
    m_didtimo = 0;
804
948
805
    NetconServCon *con = 0;
949
    NetconServCon *con = 0;
806
    int newfd = -1;
950
    int newfd = -1;
807
    struct sockaddr_in who;
951
    struct sockaddr_in who;
952
    struct sockaddr_un uwho;
953
    if (m_serv.empty() || m_serv[0] != '/') {
808
    SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who);
954
        SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who);
809
    if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) { 
955
        if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) {
810
  LOGSYSERR("NetconServCon::accept", "accept", "");
956
            LOGSYSERR("NetconServCon::accept", "accept", "");
811
  goto out;
957
            goto out;
812
    }
958
        }
813
#ifdef NETCON_ACCESSCONTROL
959
#ifdef NETCON_ACCESSCONTROL
814
    if (checkperms(&who, clilen) < 0) {
960
        if (checkperms(&who, clilen) < 0) {
815
  goto out;
961
            goto out;
816
    }
962
        }
817
#endif
963
#endif
964
    } else {
965
        SOCKLEN_T clilen = (SOCKLEN_T)sizeof(uwho);
966
        if ((newfd = ::accept(m_fd, (struct sockaddr *)&uwho, &clilen)) < 0) {
967
            LOGSYSERR("NetconServCon::accept", "accept", "");
968
            goto out;
969
        }
970
    }
971
818
    con = new NetconServCon(newfd);
972
    con = new NetconServCon(newfd);
819
    if (con == 0) {
973
    if (con == 0) {
820
  LOGERR(("NetconServLis::accept: new NetconServCon failed\n"));
974
        LOGERR(("NetconServLis::accept: new NetconServCon failed\n"));
821
  goto out;
975
        goto out;
822
    } 
976
    }
977
823
    // Retrieve peer's host name. Errors are non fatal
978
    // Retrieve peer's host name. Errors are non fatal
979
    if (m_serv.empty() || m_serv[0] != '/') {
824
    struct hostent *hp;
980
        struct hostent *hp;
825
    if ((hp = gethostbyaddr((char *)&(who.sin_addr), sizeof(struct in_addr),
981
        if ((hp = gethostbyaddr((char *) & (who.sin_addr), 
826
              AF_INET)) == 0) {
982
                                sizeof(struct in_addr), AF_INET)) == 0) {
827
  LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
983
            LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
828
      who.sin_addr.s_addr));
984
                who.sin_addr.s_addr));
829
  con->setpeer(inet_ntoa(who.sin_addr));
985
            con->setpeer(inet_ntoa(who.sin_addr));
986
        } else {
987
            con->setpeer(hp->h_name);
988
        }
830
    } else {
989
    } else {
831
  con->setpeer(hp->h_name);
990
        con->setpeer(m_serv.c_str());
832
    }
991
    }
992
833
    LOGDEB2(("NetconServLis::accept: setting keepalive\n"));
993
    LOGDEB2(("NetconServLis::accept: setting keepalive\n"));
834
    if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE, 
994
    if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE,
835
         (char *)&one, sizeof(one)) < 0) {
995
                   (char *)&one, sizeof(one)) < 0) {
836
  LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
996
        LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
837
    }
997
    }
838
    LOGDEB2(("NetconServLis::accept: got connect from %s\n", con->getpeer()));
998
    LOGDEB2(("NetconServLis::accept: got connect from %s\n", con->getpeer()));
839
999
840
 out:
1000
out:
841
    if (con == 0 && newfd >= 0)
1001
    if (con == 0 && newfd >= 0) {
842
  close(newfd);
1002
        close(newfd);
1003
    }
843
    return con;
1004
    return con;
844
}
1005
}
845
1006
846
#ifdef NETCON_ACCESSCONTROL
1007
#ifdef NETCON_ACCESSCONTROL
847
int 
1008
int
848
NetconServLis::checkperms(void *cl, int)
1009
NetconServLis::checkperms(void *cl, int)
849
{
1010
{
850
    // If okmasks and addrs were not initialized, the default is allow to all
1011
    // If okmasks and addrs were not initialized, the default is allow to all
851
    if (okmasks.len <= 0 || okaddrs.len <= 0)
1012
    if (okmasks.len <= 0 || okaddrs.len <= 0) {
852
  return 0;
1013
        return 0;
1014
    }
853
1015
854
    struct sockaddr *addr = (struct sockaddr *)cl;
1016
    struct sockaddr *addr = (struct sockaddr *)cl;
855
    unsigned long ip_addr;
1017
    unsigned long ip_addr;
856
1018
857
    if (addr->sa_family != AF_INET) {
1019
    if (addr->sa_family != AF_INET) {
858
  LOGERR(("NetconServLis::checkperms: connection from non-INET addr !\n"));
1020
        LOGERR(("NetconServLis::checkperms: connection from non-INET addr !\n"));
859
  return -1;
1021
        return -1;
860
    }
1022
    }
861
1023
862
    ip_addr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
1024
    ip_addr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
863
    LOGDEB2(("checkperms: ip_addr: 0x%x\n", ip_addr));
1025
    LOGDEB2(("checkperms: ip_addr: 0x%x\n", ip_addr));
864
    for (int i = 0; i < okaddrs.len; i++) {
1026
    for (int i = 0; i < okaddrs.len; i++) {
865
  unsigned int mask;
1027
        unsigned int mask;
866
  if (i < okmasks.len)
1028
        if (i < okmasks.len) {
867
      mask = okmasks.intarray[i];
1029
            mask = okmasks.intarray[i];
868
  else 
1030
        } else {
869
      mask = okmasks.intarray[okmasks.len-1];
1031
            mask = okmasks.intarray[okmasks.len-1];
1032
        }
870
  LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n", 
1033
        LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n",
871
       okaddrs.intarray[i], mask));
1034
                 okaddrs.intarray[i], mask));
872
  if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) 
1035
        if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) {
873
      return (0);
1036
            return (0);
874
    }
1037
        }
1038
    }
875
    LOGERR(("NetconServLis::checkperm: connection from bad address 0x%x\n", 
1039
    LOGERR(("NetconServLis::checkperm: connection from bad address 0x%x\n",
876
      ip_addr));
1040
            ip_addr));
877
    return -1;
1041
    return -1;
878
}
1042
}
879
#endif /* NETCON_ACCESSCONTROL */
1043
#endif /* NETCON_ACCESSCONTROL */
880
1044
881
1045
...
...
890
#include <signal.h>
1054
#include <signal.h>
891
#include <string.h>
1055
#include <string.h>
892
1056
893
#include "debuglog.h"
1057
#include "debuglog.h"
894
#include "netcon.h"
1058
#include "netcon.h"
1059
1060
using namespace std;
895
1061
896
static char *thisprog;
1062
static char *thisprog;
897
static char usage[] =
1063
static char usage[] =
898
    "-c <host> <service>: Connects to trnetcon server, exchange message, then\n"
1064
    "-c <host> <service>: Connects to trnetcon server, exchange message, then\n"
899
    "  sleeps 10 S, except if option -n is given (sleep forever)\n"
1065
    "  sleeps 10 S, except if option -n is given (sleep forever)\n"
900
    "\n"
1066
    "\n"
901
    "-s <service>: open service <service>\n"
1067
    "-s <service>: open service <service>\n"
902
    ;
1068
    ;
903
static void 
1069
static void
904
Usage()
1070
Usage()
905
{
1071
{
906
    fprintf(stderr, "Usage : %s:\n %s", thisprog, usage);
1072
    fprintf(stderr, "Usage : %s:\n %s", thisprog, usage);
907
    exit(1);
1073
    exit(1);
908
}
1074
}
...
...
921
int main(int argc, char **argv)
1087
int main(int argc, char **argv)
922
{
1088
{
923
    char *host, *serv;
1089
    char *host, *serv;
924
1090
925
    thisprog = argv[0];
1091
    thisprog = argv[0];
926
    argc--; argv++;
1092
    argc--;
1093
    argv++;
927
1094
928
    while (argc > 0 && **argv == '-') {
1095
    while (argc > 0 && **argv == '-') {
929
  (*argv)++;
1096
        (*argv)++;
930
  if (!(**argv))
1097
        if (!(**argv))
931
      /* Cas du "adb - core" */
1098
            /* Cas du "adb - core" */
932
      Usage();
1099
        {
1100
            Usage();
1101
        }
933
  while (**argv)
1102
        while (**argv)
934
      switch (*(*argv)++) {
1103
            switch (*(*argv)++) {
935
      case 's':
1104
            case 's':
936
      op_flags |= OPT_s;
1105
                op_flags |= OPT_s;
937
      break;
1106
                break;
938
      case 'c':
1107
            case 'c':
939
      op_flags |= OPT_c;
1108
                op_flags |= OPT_c;
940
      break;
1109
                break;
941
      case 'n':
1110
            case 'n':
942
      op_flags |= OPT_n;
1111
                op_flags |= OPT_n;
943
      break;
1112
                break;
944
      default:
1113
            default:
945
      Usage();
1114
                Usage();
946
      break;
1115
                break;
947
      }
1116
        }
948
  argc--;
1117
        argc--;
949
  argv++;
1118
        argv++;
950
    }
1119
    }
951
    DebugLog::setfilename("stderr");
1120
    DebugLog::setfilename("stderr");
952
    DebugLog::getdbl()->setloglevel(DEBDEB2);
1121
    DebugLog::getdbl()->setloglevel(DEBDEB2);
953
1122
954
    if (op_flags & OPT_c) {
1123
    if (op_flags & OPT_c) {
955
  if (argc != 2) {
1124
        if (argc != 2) {
956
      Usage();
1125
            Usage();
957
  }
1126
        }
958
  host = *argv++;argc--;
1127
        host = *argv++;
959
  serv = *argv++;argc--;
1128
        argc--;
1129
        serv = *argv++;
1130
        argc--;
960
  exit(trycli(host, serv));
1131
        exit(trycli(host, serv));
961
    } else if (op_flags & OPT_s) {
1132
    } else if (op_flags & OPT_s) {
962
  if (argc != 1) {
1133
        if (argc != 1) {
963
      Usage();
1134
            Usage();
964
  }
1135
        }
965
  serv = *argv++;argc--;
1136
        serv = *argv++;
1137
        argc--;
966
  exit(tryserv(serv));
1138
        exit(tryserv(serv));
967
    } else {
1139
    } else {
968
  Usage();
1140
        Usage();
969
    }
1141
    }
970
}
1142
}
971
1143
972
1144
973
static char buf[1024];
1145
static char buf[1024];
...
...
975
static char fromcli[200];
1147
static char fromcli[200];
976
1148
977
class CliNetconWorker : public NetconWorker {
1149
class CliNetconWorker : public NetconWorker {
978
public:
1150
public:
979
    CliNetconWorker()  : m_count(0) {}
1151
    CliNetconWorker()  : m_count(0) {}
980
    int data(NetconData *con, Netcon::Event reason) 
1152
    int data(NetconData *con, Netcon::Event reason) {
981
    {
982
  LOGDEB(("clientdata\n"));
1153
        LOGDEB(("clientdata\n"));
983
  if (reason & Netcon::NETCONPOLL_WRITE) {
1154
        if (reason & Netcon::NETCONPOLL_WRITE) {
984
      sprintf(fromcli, "Bonjour Bonjour client %d, count %d", 
1155
            sprintf(fromcli, "Bonjour Bonjour client %d, count %d",
985
          getpid(), m_count);
1156
                    getpid(), m_count);
986
      con->setselevents(Netcon::NETCONPOLL_READ);
1157
            con->setselevents(Netcon::NETCONPOLL_READ);
987
      if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
1158
            if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
988
      fprintf(stderr, "send failed\n");
1159
                fprintf(stderr, "send failed\n");
989
      return -1;
1160
                return -1;
990
      }
1161
            }
991
      m_count++;
1162
            m_count++;
992
  }
1163
        }
993
1164
994
  if (reason & Netcon::NETCONPOLL_READ) {
1165
        if (reason & Netcon::NETCONPOLL_READ) {
995
      con->setselevents(Netcon::NETCONPOLL_WRITE);
1166
            con->setselevents(Netcon::NETCONPOLL_WRITE);
996
      int n;
1167
            int n;
997
      if ((n = con->receive(buf, buflen)) < 0) {
1168
            if ((n = con->receive(buf, buflen)) < 0) {
998
      fprintf(stderr, "receive failed\n");
1169
                fprintf(stderr, "receive failed\n");
999
      return -1;
1170
                return -1;
1000
      }
1171
            }
1001
      if (n == 0) {
1172
            if (n == 0) {
1002
      // EOF, close connection
1173
                // EOF, close connection
1003
      return -1;
1174
                return -1;
1004
      }
1175
            }
1005
      buf[n] = 0;
1176
            buf[n] = 0;
1006
      fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
1177
            fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
1007
      if (op_flags & OPT_n) {
1178
            if (op_flags & OPT_n) {
1008
      pause();
1179
                pause();
1009
      } else {
1180
            } else {
1010
      sleep(1);
1181
                sleep(1);
1182
            }
1183
        }
1184
        if (m_count >= 10) {
1185
            fprintf(stderr, "Did 10, enough\n");
1186
            if (con->getloop()) {
1187
                con->getloop()->loopReturn(0);
1188
            }
1189
        }
1190
        return 0;
1011
      }
1191
    }
1012
  }
1013
  if (m_count >= 10) {
1014
      fprintf(stderr, "Did 10, enough\n");
1015
      if (con->getloop())
1016
      con->getloop()->loopReturn(0);
1017
  }
1018
  return 0;
1019
    }
1020
private: 
1192
private:
1021
    int m_count;
1193
    int m_count;
1022
};
1194
};
1023
1195
1024
int trycli(char *host, char *serv)
1196
int trycli(char *host, char *serv)
1025
{
1197
{
1026
    sprintf(fromcli, "Bonjour Bonjour je suis le client %d", getpid());
1198
    sprintf(fromcli, "Bonjour Bonjour je suis le client %d", getpid());
1027
1199
1028
    NetconCli *clicon = new NetconCli();
1200
    NetconCli *clicon = new NetconCli();
1029
    NetconP con(clicon);
1201
    NetconP con(clicon);
1030
    if (con.isNull()) {
1202
    if (!con) {
1031
  fprintf(stderr, "new NetconCli failed\n");
1203
        fprintf(stderr, "new NetconCli failed\n");
1032
  return 1;
1204
        return 1;
1033
    }
1205
    }
1034
    if (clicon->openconn(host, serv) < 0) {
1206
    int port = atoi(serv);
1207
    int ret = port > 0 ? 
1208
        clicon->openconn(host, port) : clicon->openconn(host, serv);
1209
    if (ret < 0) {
1035
  fprintf(stderr, "openconn(%s, %s) failed\n", host, serv);
1210
        fprintf(stderr, "openconn(%s, %s) failed\n", host, serv);
1036
  return 1;
1211
        return 1;
1037
    }
1212
    }
1038
    fprintf(stderr, "openconn(%s, %s) ok\n", host, serv);
1213
    fprintf(stderr, "openconn(%s, %s) ok\n", host, serv);
1039
#ifdef NOSELLOOP
1214
#ifdef NOSELLOOP
1040
    for (int i = 0;i < nloop;i++) {
1215
    for (int i = 0; i < nloop; i++) {
1041
  if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
1216
        if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
1042
      fprintf(stderr, "%d: Send failed\n", getpid());
1217
            fprintf(stderr, "%d: Send failed\n", getpid());
1043
      return 1;
1218
            return 1;
1044
  }
1219
        }
1045
  if (con->receive(buf, buflen) < 0) {
1220
        if (con->receive(buf, buflen) < 0) {
1046
      perror("receive:");
1221
            perror("receive:");
1047
      fprintf(stderr, "%d: Receive failed\n", getpid());
1222
            fprintf(stderr, "%d: Receive failed\n", getpid());
1048
      return 1;
1223
            return 1;
1049
  }
1224
        }
1050
  fprintf(stderr, "%d Received \"%s\"\n", getpid(), buf);
1225
        fprintf(stderr, "%d Received \"%s\"\n", getpid(), buf);
1051
  if (op_flags & OPT_n) {
1226
        if (op_flags & OPT_n) {
1052
      pause();
1227
            pause();
1053
  } else {
1228
        } else {
1054
      sleep(1);
1229
            sleep(1);
1055
  }
1230
        }
1056
    }
1231
    }
1057
#else
1232
#else
1058
    RefCntr<NetconWorker> worker = 
1233
    RefCntr<NetconWorker> worker =
1059
  RefCntr<NetconWorker>(new CliNetconWorker());
1234
        RefCntr<NetconWorker>(new CliNetconWorker());
1060
    clicon->setcallback(worker);
1235
    clicon->setcallback(worker);
1061
    SelectLoop myloop;
1236
    SelectLoop myloop;
1062
    myloop.addselcon(con, Netcon::NETCONPOLL_WRITE);
1237
    myloop.addselcon(con, Netcon::NETCONPOLL_WRITE);
1063
    fprintf(stderr, "client ready\n");
1238
    fprintf(stderr, "client ready\n");
1064
    int ret = myloop.doLoop();
1239
    ret = myloop.doLoop();
1065
    if (ret < 0) {
1240
    if (ret < 0) {
1066
  fprintf(stderr, "selectloop failed\n");
1241
        fprintf(stderr, "selectloop failed\n");
1067
  exit(1);
1242
        exit(1);
1068
    }
1243
    }
1069
    fprintf(stderr, "selectloop returned %d\n", ret);
1244
    fprintf(stderr, "selectloop returned %d\n", ret);
1070
#endif
1245
#endif
1071
    return 0;
1246
    return 0;
1072
}
1247
}
...
...
1074
//////////////////////////////////////////////////////////////////
1249
//////////////////////////////////////////////////////////////////
1075
// Server-side sample code
1250
// Server-side sample code
1076
class ServNetconWorker : public NetconWorker {
1251
class ServNetconWorker : public NetconWorker {
1077
public:
1252
public:
1078
    ServNetconWorker() : m_count(0) {}
1253
    ServNetconWorker() : m_count(0) {}
1079
    int data(NetconData *con, Netcon::Event reason) 
1254
    int data(NetconData *con, Netcon::Event reason) {
1080
    {
1081
  LOGDEB(("serverdata\n"));
1255
        LOGDEB(("serverdata\n"));
1082
  if (reason & Netcon::NETCONPOLL_WRITE) {
1256
        if (reason & Netcon::NETCONPOLL_WRITE) {
1083
      con->setselevents(Netcon::NETCONPOLL_READ);
1257
            con->setselevents(Netcon::NETCONPOLL_READ);
1084
      char fromserv[200];
1258
            char fromserv[200];
1085
      sprintf(fromserv, 
1259
            sprintf(fromserv,
1086
          "Du serveur: mon fd pour ce client est  %d, mon compte %d",
1260
                    "Du serveur: mon fd pour ce client est  %d, mon compte %d",
1087
          con->getfd(), ++m_count);
1261
                    con->getfd(), ++m_count);
1088
      if (con->send(fromserv, strlen(fromserv) + 1) < 0) {
1262
            if (con->send(fromserv, strlen(fromserv) + 1) < 0) {
1089
      fprintf(stderr, "send failed\n");
1263
                fprintf(stderr, "send failed\n");
1090
      return -1;
1264
                return -1;
1091
      }
1265
            }
1092
  }
1266
        }
1093
  if (reason & Netcon::NETCONPOLL_READ) {
1267
        if (reason & Netcon::NETCONPOLL_READ) {
1094
#define LL 200
1268
#define LL 200
1095
      char buf[LL+1];
1269
            char buf[LL+1];
1096
      int n;
1270
            int n;
1097
      if ((n = con->receive(buf, LL)) < 0) {
1271
            if ((n = con->receive(buf, LL)) < 0) {
1098
      fprintf(stderr, "receive failed\n");
1272
                fprintf(stderr, "receive failed\n");
1099
      return -1;
1273
                return -1;
1100
      }
1274
            }
1101
      if (n == 0) {
1275
            if (n == 0) {
1102
      return -1;
1276
                return -1;
1103
      }
1277
            }
1104
      buf[n] = 0;
1278
            buf[n] = 0;
1105
      fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
1279
            fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
1106
      con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE);
1280
            con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE);
1107
  }
1281
        }
1108
  return 0;
1282
        return 0;
1109
    }
1283
    }
1110
private:
1284
private:
1111
    int m_count;
1285
    int m_count;
1112
};
1286
};
1113
1287
1114
class MyNetconServLis : public NetconServLis {
1288
class MyNetconServLis : public NetconServLis {
1115
public:
1289
public:
1116
    MyNetconServLis(SelectLoop &loop)
1290
    MyNetconServLis(SelectLoop &loop)
1117
  : NetconServLis(), m_loop(loop)
1291
        : NetconServLis(), m_loop(loop) {
1118
    {
1119
    }
1292
    }
1120
protected:
1293
protected:
1121
    int cando(Netcon::Event reason) {
1294
    int cando(Netcon::Event reason) {
1122
  NetconServCon *con = accept();
1295
        NetconServCon *con = accept();
1123
  if (con == 0)
1296
        if (con == 0) {
1124
      return -1;
1297
            return -1;
1298
        }
1125
  RefCntr<NetconWorker> worker = 
1299
        RefCntr<NetconWorker> worker =
1126
      RefCntr<NetconWorker>(new ServNetconWorker());
1300
            RefCntr<NetconWorker>(new ServNetconWorker());
1127
  con->setcallback(worker);
1301
        con->setcallback(worker);
1128
  m_loop.addselcon(NetconP(con), NETCONPOLL_READ);
1302
        m_loop.addselcon(NetconP(con), NETCONPOLL_READ);
1129
  return 1;
1303
        return 1;
1130
    }
1304
    }
1131
    SelectLoop& m_loop;
1305
    SelectLoop& m_loop;
1132
};
1306
};
1133
1307
1134
NetconP lis;
1308
NetconP lis;
1135
1309
1136
void
1310
void
1137
onexit(int sig)
1311
onexit(int sig)
1138
{
1312
{
1139
    fprintf(stderr, "Onexit: ");
1313
    fprintf(stderr, "Onexit: ");
1140
    if (sig == SIGQUIT)
1314
    if (sig == SIGQUIT) {
1141
  kill(getpid(), SIGKILL);
1315
        kill(getpid(), SIGKILL);
1316
    }
1142
    fprintf(stderr, "Exiting\n");
1317
    fprintf(stderr, "Exiting\n");
1143
    exit(0);
1318
    exit(0);
1144
}
1319
}
1145
1320
1146
int tryserv(char *serv)
1321
int tryserv(char *serv)
1147
{
1322
{
1148
    signal(SIGCHLD, SIG_IGN);
1323
    signal(SIGCHLD, SIG_IGN);
1149
    SelectLoop myloop;
1324
    SelectLoop myloop;
1150
    MyNetconServLis *servlis = new MyNetconServLis(myloop);
1325
    MyNetconServLis *servlis = new MyNetconServLis(myloop);
1151
    lis = NetconP(servlis);
1326
    lis = NetconP(servlis);
1152
    if (lis.isNull()) {
1327
    if (!lis) {
1153
  fprintf(stderr, "new NetconServLis failed\n");
1328
        fprintf(stderr, "new NetconServLis failed\n");
1154
  return 1;
1329
        return 1;
1155
    }
1330
    }
1156
1331
1157
    // Prepare for cleanup
1332
    // Prepare for cleanup
1158
    struct sigaction sa;
1333
    struct sigaction sa;
1159
    sa.sa_flags = 0;
1334
    sa.sa_flags = 0;
...
...
1161
    sigemptyset(&sa.sa_mask);
1336
    sigemptyset(&sa.sa_mask);
1162
    sigaction(SIGINT, &sa, 0);
1337
    sigaction(SIGINT, &sa, 0);
1163
    sigaction(SIGQUIT, &sa, 0);
1338
    sigaction(SIGQUIT, &sa, 0);
1164
    sigaction(SIGTERM, &sa, 0);
1339
    sigaction(SIGTERM, &sa, 0);
1165
1340
1166
    if (servlis->openservice(serv) < 0) {
1341
    int port = atoi(serv);
1342
    int ret = port > 0 ? 
1343
        servlis->openservice(port) : servlis->openservice(serv);
1344
    if (ret < 0) {
1167
  fprintf(stderr, "openservice(%s) failed\n", serv);
1345
        fprintf(stderr, "openservice(%s) failed\n", serv);
1168
  return 1;
1346
        return 1;
1169
    }
1347
    }
1170
    myloop.addselcon(lis, Netcon::NETCONPOLL_READ);
1348
    myloop.addselcon(lis, Netcon::NETCONPOLL_READ);
1171
    fprintf(stderr, "openservice(%s) Ok\n", serv);
1349
    fprintf(stderr, "openservice(%s) Ok\n", serv);
1172
    if (myloop.doLoop() < 0) {
1350
    if (myloop.doLoop() < 0) {
1173
  fprintf(stderr, "selectloop failed\n");
1351
        fprintf(stderr, "selectloop failed\n");
1174
  exit(1);
1352
        exit(1);
1175
    }
1353
    }
1176
    return 0;
1354
    return 0;
1177
}
1355
}
1178
1356
1179
#endif /* TEST_NETCON */
1357
#endif /* TEST_NETCON */