Switch to unified view

a/src/netcon.cpp b/src/netcon.cpp
...
...
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 */
16
 */
17
17
18
// Wrapper classes for the socket interface
18
// Wrapper classes for the socket interface
19
19
20
21
#ifndef TEST_NETCON
20
#ifndef TEST_NETCON
22
#ifdef BUILDING_RECOLL
21
#ifdef BUILDING_RECOLL
23
#include "autoconfig.h"
22
#include "autoconfig.h"
24
#else
23
#else
25
#include "config.h"
24
#include "config.h"
26
#endif
25
#endif
26
27
#include "netcon.h"
27
28
28
#include <stdio.h>
29
#include <stdio.h>
29
#include <stdlib.h>
30
#include <stdlib.h>
30
#include <string.h>
31
#include <string.h>
31
#include <errno.h>
32
#include <errno.h>
...
...
44
#include <arpa/inet.h>
45
#include <arpa/inet.h>
45
#include <netdb.h>
46
#include <netdb.h>
46
47
47
#include <map>
48
#include <map>
48
49
49
50
#ifdef BUILDING_RECOLL
51
#include "debuglog.h"
50
#include "log.h"
52
53
#else
54
55
#define LOGFATAL(X)
56
#define LOGERR(X)
57
#define LOGINFO(X)
58
#define LOGDEB(X)
59
#define LOGDEB0(X)
60
#define LOGDEB1(X)
61
#define LOGDEB2(X)
62
#define LOGDEB3(X)
63
#define LOGDEB4(X)
64
#endif
65
66
#include "netcon.h"
67
51
68
using namespace std;
52
using namespace std;
69
53
70
#ifndef SOCKLEN_T
54
#ifndef SOCKLEN_T
71
#define SOCKLEN_T socklen_t
55
#define SOCKLEN_T socklen_t
...
...
82
66
83
// Need &one, &zero for setsockopt...
67
// Need &one, &zero for setsockopt...
84
static const int one = 1;
68
static const int one = 1;
85
static const int zero = 0;
69
static const int zero = 0;
86
70
87
#define LOGSYSERR(who, call, spar)                  \
71
#define LOGSYSERR(who, call, spar)                                      \
88
    LOGERR(("%s: %s(%s) errno %d (%s)\n", who, call,            \
72
    LOGERR((who) << ": "  << (call) << "("  << (spar) << ") errno " <<  \
89
        spar, errno, strerror(errno)))
73
           (errno) << " ("  << (strerror(errno)) << ")\n")
90
74
91
#ifndef MIN
75
#ifndef MIN
92
#define MIN(a,b) (a<b?a:b)
76
#define MIN(a,b) ((a)<(b)?(a):(b))
93
#endif
77
#endif
94
#ifndef MAX
78
#ifndef MAX
95
#define MAX(a,b) (a>b?a:b)
79
#define MAX(a,b) ((a)>(b)?(a):(b))
96
#endif
80
#endif
97
#ifndef freeZ
81
#ifndef freeZ
98
#define freeZ(X) if (X) {free(X);X=0;}
82
#define freeZ(X) if (X) {free(X);X=0;}
99
#endif
83
#endif
100
84
...
...
119
        ret = select(fd + 1, 0, &rd, 0, &tv);
103
        ret = select(fd + 1, 0, &rd, 0, &tv);
120
    } else {
104
    } else {
121
        ret = select(fd + 1, &rd, 0, 0, &tv);
105
        ret = select(fd + 1, &rd, 0, 0, &tv);
122
    }
106
    }
123
    if (!FD_ISSET(fd, &rd)) {
107
    if (!FD_ISSET(fd, &rd)) {
124
        LOGDEB2(("Netcon::select1: fd %d timeout\n", fd));
108
        LOGDEB2("Netcon::select1: fd "  << (fd) << " timeout\n" );
125
    }
109
    }
126
    return ret;
110
    return ret;
127
}
111
}
128
112
129
void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms)
113
void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms)
...
...
186
int SelectLoop::doLoop()
170
int SelectLoop::doLoop()
187
{
171
{
188
    for (;;) {
172
    for (;;) {
189
        if (m_selectloopDoReturn) {
173
        if (m_selectloopDoReturn) {
190
            m_selectloopDoReturn = false;
174
            m_selectloopDoReturn = false;
191
            LOGDEB(("Netcon::selectloop: returning on request\n"));
175
            LOGDEB("Netcon::selectloop: returning on request\n" );
192
            return m_selectloopReturnValue;
176
            return m_selectloopReturnValue;
193
        }
177
        }
194
        int nfds;
178
        int nfds;
195
        fd_set rd, wd;
179
        fd_set rd, wd;
196
        FD_ZERO(&rd);
180
        FD_ZERO(&rd);
...
...
201
        nfds = 0;
185
        nfds = 0;
202
        for (map<int, NetconP>::iterator it = m_polldata.begin();
186
        for (map<int, NetconP>::iterator it = m_polldata.begin();
203
                it != m_polldata.end(); it++) {
187
                it != m_polldata.end(); it++) {
204
            NetconP& pll = it->second;
188
            NetconP& pll = it->second;
205
            int fd  = it->first;
189
            int fd  = it->first;
206
            LOGDEB2(("Selectloop: fd %d flags 0x%x\n", fd, pll->m_wantedEvents));
190
            LOGDEB2("Selectloop: fd "  << (fd) << " flags 0x"  << (pll->m_wantedEvents) << "\n" );
207
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
191
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
208
                FD_SET(fd, &rd);
192
                FD_SET(fd, &rd);
209
                nfds = MAX(nfds, fd + 1);
193
                nfds = MAX(nfds, fd + 1);
210
            }
194
            }
211
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
195
            if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
...
...
221
            // condition.
205
            // condition.
222
206
223
            // Just in case there would still be open fds in there
207
            // Just in case there would still be open fds in there
224
            // (with no r/w flags set). Should not be needed, but safer
208
            // (with no r/w flags set). Should not be needed, but safer
225
            m_polldata.clear();
209
            m_polldata.clear();
226
            LOGDEB1(("Netcon::selectloop: no fds\n"));
210
            LOGDEB1("Netcon::selectloop: no fds\n" );
227
            return 0;
211
            return 0;
228
        }
212
        }
229
213
230
        LOGDEB2(("Netcon::selectloop: selecting, nfds = %d\n", nfds));
214
        LOGDEB2("Netcon::selectloop: selecting, nfds = "  << (nfds) << "\n" );
231
215
232
        // Compute the next timeout according to what might need to be
216
        // Compute the next timeout according to what might need to be
233
        // done apart from waiting for data
217
        // done apart from waiting for data
234
        struct timeval tv;
218
        struct timeval tv;
235
        periodictimeout(&tv);
219
        periodictimeout(&tv);
236
        // Wait for something to happen
220
        // Wait for something to happen
237
        int ret = select(nfds, &rd, &wd, 0, &tv);
221
        int ret = select(nfds, &rd, &wd, 0, &tv);
238
        LOGDEB2(("Netcon::selectloop: select returns %d\n", ret));
222
        LOGDEB2("Netcon::selectloop: select returns "  << (ret) << "\n" );
239
        if (ret < 0) {
223
        if (ret < 0) {
240
            LOGSYSERR("Netcon::selectloop", "select", "");
224
            LOGSYSERR("Netcon::selectloop", "select", "");
241
            return -1;
225
            return -1;
242
        }
226
        }
243
        if (m_periodicmillis > 0)
227
        if (m_periodicmillis > 0)
...
...
266
            }
250
            }
267
251
268
            int canread = FD_ISSET(fd, &rd);
252
            int canread = FD_ISSET(fd, &rd);
269
            int canwrite = FD_ISSET(fd, &wd);
253
            int canwrite = FD_ISSET(fd, &wd);
270
            bool none = !canread && !canwrite;
254
            bool none = !canread && !canwrite;
271
            LOGDEB2(("Netcon::selectloop: fd %d %s %s %s\n", fd,
255
            LOGDEB2("Netcon::selectloop: fd "  << (fd) << " "  << (none ? "blocked" : "can") << " "  << (canread ? "read" : "") << " "  << (canwrite ? "write" : "") << "\n" );
272
                     none ? "blocked" : "can" , canread ? "read" : "",
273
                     canwrite ? "write" : ""));
274
            if (none) {
256
            if (none) {
275
                continue;
257
                continue;
276
            }
258
            }
277
259
278
            map<int, NetconP>::iterator it = m_polldata.find(fd);
260
            map<int, NetconP>::iterator it = m_polldata.find(fd);
279
            if (it == m_polldata.end()) {
261
            if (it == m_polldata.end()) {
280
                /// This should not happen actually
262
                /// This should not happen actually
281
                LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
263
                LOGDEB2("Netcon::selectloop: fd "  << (fd) << " not found\n" );
282
                continue;
264
                continue;
283
            }
265
            }
284
266
285
            // Next start will be one beyond last serviced (modulo nfds)
267
            // Next start will be one beyond last serviced (modulo nfds)
286
            m_placetostart = fd + 1;
268
            m_placetostart = fd + 1;
...
...
290
            }
272
            }
291
            if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
273
            if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
292
                pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
274
                pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
293
            }
275
            }
294
            if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE | Netcon::NETCONPOLL_READ))) {
276
            if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE | Netcon::NETCONPOLL_READ))) {
295
                LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
277
                LOGDEB0("Netcon::selectloop: fd "  << (it->first) << " has 0x"  << (it->second->m_wantedEvents) << " mask, erasing\n" );
296
                         it->first, it->second->m_wantedEvents));
297
                m_polldata.erase(it);
278
                m_polldata.erase(it);
298
            }
279
            }
299
        } // fd sweep
280
        } // fd sweep
300
281
301
    } // forever loop
282
    } // forever loop
302
    LOGERR(("SelectLoop::doLoop: got out of loop !\n"));
283
    LOGERR("SelectLoop::doLoop: got out of loop !\n" );
303
    return -1;
284
    return -1;
304
}
285
}
305
286
306
// Add a connection to the monitored set.
287
// Add a connection to the monitored set.
307
int SelectLoop::addselcon(NetconP con, int events)
288
int SelectLoop::addselcon(NetconP con, int events)
308
{
289
{
309
    if (!con) {
290
    if (!con) {
310
        return -1;
291
        return -1;
311
    }
292
    }
312
    LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd));
293
    LOGDEB1("Netcon::addselcon: fd "  << (con->m_fd) << "\n" );
313
    con->set_nonblock(1);
294
    con->set_nonblock(1);
314
    con->setselevents(events);
295
    con->setselevents(events);
315
    m_polldata[con->m_fd] = con;
296
    m_polldata[con->m_fd] = con;
316
    con->setloop(this);
297
    con->setloop(this);
317
    return 0;
298
    return 0;
...
...
321
int SelectLoop::remselcon(NetconP con)
302
int SelectLoop::remselcon(NetconP con)
322
{
303
{
323
    if (!con) {
304
    if (!con) {
324
        return -1;
305
        return -1;
325
    }
306
    }
326
    LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
307
    LOGDEB1("Netcon::remselcon: fd "  << (con->m_fd) << "\n" );
327
    map<int, NetconP>::iterator it = m_polldata.find(con->m_fd);
308
    map<int, NetconP>::iterator it = m_polldata.find(con->m_fd);
328
    if (it == m_polldata.end()) {
309
    if (it == m_polldata.end()) {
329
        LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
310
        LOGDEB1("Netcon::remselcon: con not found for fd "  << (con->m_fd) << "\n" );
330
        return -1;
311
        return -1;
331
    }
312
    }
332
    con->setloop(0);
313
    con->setloop(0);
333
    m_polldata.erase(it);
314
    m_polldata.erase(it);
334
    return 0;
315
    return 0;
...
...
367
    m_peer = strdup(hostname);
348
    m_peer = strdup(hostname);
368
}
349
}
369
350
370
int Netcon::settcpnodelay(int on)
351
int Netcon::settcpnodelay(int on)
371
{
352
{
372
    LOGDEB2(("Netcon::settcpnodelay\n"));
353
    LOGDEB2("Netcon::settcpnodelay\n" );
373
    if (m_fd < 0) {
354
    if (m_fd < 0) {
374
        LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
355
        LOGERR("Netcon::settcpnodelay: connection not opened\n" );
375
        return -1;
356
        return -1;
376
    }
357
    }
377
    char *cp = on ? (char *)&one : (char *)&zero;
358
    char *cp = on ? (char *)&one : (char *)&zero;
378
    if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, cp, sizeof(one)) < 0) {
359
    if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, cp, sizeof(one)) < 0) {
379
        LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY");
360
        LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY");
...
...
406
    m_bufbytes = m_bufsize = 0;
387
    m_bufbytes = m_bufsize = 0;
407
}
388
}
408
389
409
int NetconData::send(const char *buf, int cnt, int expedited)
390
int NetconData::send(const char *buf, int cnt, int expedited)
410
{
391
{
411
    LOGDEB2(("NetconData::send: fd %d cnt %d expe %d\n", m_fd, cnt, expedited));
392
    LOGDEB2("NetconData::send: fd "  << (m_fd) << " cnt "  << (cnt) << " expe "  << (expedited) << "\n" );
412
    int flag = 0;
393
    int flag = 0;
413
    if (m_fd < 0) {
394
    if (m_fd < 0) {
414
        LOGERR(("NetconData::send: connection not opened\n"));
395
        LOGERR("NetconData::send: connection not opened\n" );
415
        return -1;
396
        return -1;
416
    }
397
    }
417
    if (expedited) {
398
    if (expedited) {
418
        LOGDEB2(("NetconData::send: expedited data, count %d bytes\n", cnt));
399
        LOGDEB2("NetconData::send: expedited data, count "  << (cnt) << " bytes\n" );
419
        flag = MSG_OOB;
400
        flag = MSG_OOB;
420
    }
401
    }
421
    int ret;
402
    int ret;
422
    // There is a bug in the uthread version of sendto() in FreeBSD at
403
    // There is a bug in the uthread version of sendto() in FreeBSD at
423
    // least up to 2.2.7, so avoid using it when possible
404
    // least up to 2.2.7, so avoid using it when possible
...
...
437
}
418
}
438
419
439
// Test for data available
420
// Test for data available
440
int NetconData::readready()
421
int NetconData::readready()
441
{
422
{
442
    LOGDEB2(("NetconData::readready\n"));
423
    LOGDEB2("NetconData::readready\n" );
443
    if (m_fd < 0) {
424
    if (m_fd < 0) {
444
        LOGERR(("NetconData::readready: connection not opened\n"));
425
        LOGERR("NetconData::readready: connection not opened\n" );
445
        return -1;
426
        return -1;
446
    }
427
    }
447
    return select1(m_fd, 0);
428
    return select1(m_fd, 0);
448
}
429
}
449
430
450
// Test for writable
431
// Test for writable
451
int NetconData::writeready()
432
int NetconData::writeready()
452
{
433
{
453
    LOGDEB2(("NetconData::writeready\n"));
434
    LOGDEB2("NetconData::writeready\n" );
454
    if (m_fd < 0) {
435
    if (m_fd < 0) {
455
        LOGERR(("NetconData::writeready: connection not opened\n"));
436
        LOGERR("NetconData::writeready: connection not opened\n" );
456
        return -1;
437
        return -1;
457
    }
438
    }
458
    return select1(m_fd, 0, 1);
439
    return select1(m_fd, 0, 1);
459
}
440
}
460
441
461
// Receive at most cnt bytes (maybe less)
442
// Receive at most cnt bytes (maybe less)
462
int NetconData::receive(char *buf, int cnt, int timeo)
443
int NetconData::receive(char *buf, int cnt, int timeo)
463
{
444
{
464
    LOGDEB2(("NetconData::receive: cnt %d timeo %d m_buf 0x%x m_bufbytes %d\n",
445
    LOGDEB2("NetconData::receive: cnt "  << (cnt) << " timeo "  << (timeo) << " m_buf 0x"  << (m_buf) << " m_bufbytes "  << (m_bufbytes) << "\n" );
465
             cnt, timeo, m_buf, m_bufbytes));
466
    if (m_fd < 0) {
446
    if (m_fd < 0) {
467
        LOGERR(("NetconData::receive: connection not opened\n"));
447
        LOGERR("NetconData::receive: connection not opened\n" );
468
        return -1;
448
        return -1;
469
    }
449
    }
470
    int fromibuf = 0;
450
    int fromibuf = 0;
471
    // Get whatever might have been left in the buffer by a previous
451
    // Get whatever might have been left in the buffer by a previous
472
    // getline, except if we're called to fill the buffer of course
452
    // getline, except if we're called to fill the buffer of course
...
...
474
        fromibuf = MIN(m_bufbytes, cnt);
454
        fromibuf = MIN(m_bufbytes, cnt);
475
        memcpy(buf, m_bufbase, fromibuf);
455
        memcpy(buf, m_bufbase, fromibuf);
476
        m_bufbytes -= fromibuf;
456
        m_bufbytes -= fromibuf;
477
        m_bufbase += fromibuf;
457
        m_bufbase += fromibuf;
478
        cnt -= fromibuf;
458
        cnt -= fromibuf;
479
        LOGDEB2(("NetconData::receive: transferred %d from mbuf\n", fromibuf));
459
        LOGDEB2("NetconData::receive: transferred "  << (fromibuf) << " from mbuf\n" );
480
        if (cnt <= 0) {
460
        if (cnt <= 0) {
481
            return fromibuf;
461
            return fromibuf;
482
        }
462
        }
483
    }
463
    }
484
    if (timeo > 0) {
464
    if (timeo > 0) {
485
        int ret = select1(m_fd, timeo);
465
        int ret = select1(m_fd, timeo);
486
        if (ret == 0) {
466
        if (ret == 0) {
487
            LOGDEB2(("NetconData::receive timed out\n"));
467
            LOGDEB2("NetconData::receive timed out\n" );
488
            m_didtimo = 1;
468
            m_didtimo = 1;
489
            return -1;
469
            return -1;
490
        }
470
        }
491
        if (ret < 0) {
471
        if (ret < 0) {
492
            LOGSYSERR("NetconData::receive", "select", "");
472
            LOGSYSERR("NetconData::receive", "select", "");
...
...
498
        char fdcbuf[20];
478
        char fdcbuf[20];
499
        sprintf(fdcbuf, "%d", m_fd);
479
        sprintf(fdcbuf, "%d", m_fd);
500
        LOGSYSERR("NetconData::receive", "read", fdcbuf);
480
        LOGSYSERR("NetconData::receive", "read", fdcbuf);
501
        return -1;
481
        return -1;
502
    }
482
    }
503
    LOGDEB2(("NetconData::receive: normal return, cnt %d\n", cnt));
483
    LOGDEB2("NetconData::receive: normal return, cnt "  << (cnt) << "\n" );
504
    return fromibuf + cnt;
484
    return fromibuf + cnt;
505
}
485
}
506
486
507
// Receive exactly cnt bytes (except for timeout)
487
// Receive exactly cnt bytes (except for timeout)
508
int NetconData::doreceive(char *buf, int cnt, int timeo)
488
int NetconData::doreceive(char *buf, int cnt, int timeo)
509
{
489
{
510
    int got, cur;
490
    int got, cur;
511
    LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
491
    LOGDEB2("Netcon::doreceive: cnt "  << (cnt) << ", timeo "  << (timeo) << "\n" );
512
    cur = 0;
492
    cur = 0;
513
    while (cnt > cur) {
493
    while (cnt > cur) {
514
        got = receive(buf, cnt - cur, timeo);
494
        got = receive(buf, cnt - cur, timeo);
515
        LOGDEB2(("Netcon::doreceive: got %d\n", got));
495
        LOGDEB2("Netcon::doreceive: got "  << (got) << "\n" );
516
        if (got < 0) {
496
        if (got < 0) {
517
            return -1;
497
            return -1;
518
        }
498
        }
519
        if (got == 0) {
499
        if (got == 0) {
520
            return cur;
500
            return cur;
...
...
534
//  0: EOF reached, no chars transferred
514
//  0: EOF reached, no chars transferred
535
// -1: error
515
// -1: error
536
static const int defbufsize = 200;
516
static const int defbufsize = 200;
537
int NetconData::getline(char *buf, int cnt, int timeo)
517
int NetconData::getline(char *buf, int cnt, int timeo)
538
{
518
{
539
    LOGDEB2(("NetconData::getline: cnt %d, timeo %d\n", cnt, timeo));
519
    LOGDEB2("NetconData::getline: cnt "  << (cnt) << ", timeo "  << (timeo) << "\n" );
540
    if (m_buf == 0) {
520
    if (m_buf == 0) {
541
        if ((m_buf = (char *)malloc(defbufsize)) == 0) {
521
        if ((m_buf = (char *)malloc(defbufsize)) == 0) {
542
            LOGSYSERR("NetconData::getline: Out of mem", "malloc", "");
522
            LOGSYSERR("NetconData::getline: Out of mem", "malloc", "");
543
            return -1;
523
            return -1;
544
        }
524
        }
...
...
551
    for (;;) {
531
    for (;;) {
552
        // Transfer from buffer. Have to take a lot of care to keep counts and
532
        // Transfer from buffer. Have to take a lot of care to keep counts and
553
        // pointers consistant in all end cases
533
        // pointers consistant in all end cases
554
        int maxtransf = MIN(m_bufbytes, cnt - 1);
534
        int maxtransf = MIN(m_bufbytes, cnt - 1);
555
        int nn = maxtransf;
535
        int nn = maxtransf;
556
        LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n",
536
        LOGDEB2("Before loop, bufbytes "  << (m_bufbytes) << ", maxtransf "  << (maxtransf) << ", nn: "  << (nn) << "\n" );
557
                 m_bufbytes, maxtransf, nn));
558
        for (nn = maxtransf; nn > 0;) {
537
        for (nn = maxtransf; nn > 0;) {
559
            // This is not pretty but we want nn to be decremented for
538
            // This is not pretty but we want nn to be decremented for
560
            // each byte copied (even newline), and not become -1 if
539
            // each byte copied (even newline), and not become -1 if
561
            // we go to the end. Better ways welcome!
540
            // we go to the end. Better ways welcome!
562
            nn--;
541
            nn--;
...
...
566
        }
545
        }
567
        // Update counts
546
        // Update counts
568
        maxtransf -= nn; // Actual count transferred
547
        maxtransf -= nn; // Actual count transferred
569
        m_bufbytes -= maxtransf;
548
        m_bufbytes -= maxtransf;
570
        cnt -= maxtransf;
549
        cnt -= maxtransf;
571
        LOGDEB2(("After transfer: actual transf %d cnt %d, m_bufbytes %d\n",
550
        LOGDEB2("After transfer: actual transf "  << (maxtransf) << " cnt "  << (cnt) << ", m_bufbytes "  << (m_bufbytes) << "\n" );
572
                 maxtransf, cnt, m_bufbytes));
573
551
574
        // Finished ?
552
        // Finished ?
575
        if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) {
553
        if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) {
576
            *cp = 0;
554
            *cp = 0;
577
            return cp - buf;
555
            return cp - buf;
...
...
597
// the connection. The user callback would normally have been set
575
// the connection. The user callback would normally have been set
598
// up. If it is, call it and return. Else, perform housecleaning: read
576
// up. If it is, call it and return. Else, perform housecleaning: read
599
// and discard.
577
// and discard.
600
int NetconData::cando(Netcon::Event reason)
578
int NetconData::cando(Netcon::Event reason)
601
{
579
{
602
    LOGDEB2(("NetconData::cando\n"));
580
    LOGDEB2("NetconData::cando\n" );
603
    if (m_user) {
581
    if (m_user) {
604
        return m_user->data(this, reason);
582
        return m_user->data(this, reason);
605
    }
583
    }
606
584
607
    // No user callback. Clean up by ourselves
585
    // No user callback. Clean up by ourselves
...
...
625
///////////////////////////////////////////////////////////////////////
603
///////////////////////////////////////////////////////////////////////
626
// Methods for a client connection (NetconCli)
604
// Methods for a client connection (NetconCli)
627
int NetconCli::openconn(const char *host, unsigned int port, int timeo)
605
int NetconCli::openconn(const char *host, unsigned int port, int timeo)
628
{
606
{
629
    int ret = -1;
607
    int ret = -1;
630
    LOGDEB2(("Netconcli::openconn: host %s, port %d\n", host, port));
608
    LOGDEB2("Netconcli::openconn: host "  << (host) << ", port "  << (port) << "\n" );
631
609
632
    closeconn();
610
    closeconn();
633
611
634
    struct sockaddr *saddr;
612
    struct sockaddr *saddr;
635
    socklen_t addrsize;
613
    socklen_t addrsize;
...
...
646
        if ((addr = inet_addr(host)) != -1) {
624
        if ((addr = inet_addr(host)) != -1) {
647
            memcpy(&ip_addr.sin_addr, &addr, sizeof(addr));
625
            memcpy(&ip_addr.sin_addr, &addr, sizeof(addr));
648
        } else {
626
        } else {
649
            struct hostent *hp;
627
            struct hostent *hp;
650
            if ((hp = gethostbyname(host)) == 0) {
628
            if ((hp = gethostbyname(host)) == 0) {
651
                LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n",
629
                LOGERR("NetconCli::openconn: gethostbyname("  << (host) << ") failed\n" );
652
                        host));
653
                return -1;
630
                return -1;
654
            }
631
            }
655
            memcpy(&ip_addr.sin_addr, hp->h_addr, hp->h_length);
632
            memcpy(&ip_addr.sin_addr, hp->h_addr, hp->h_length);
656
        }
633
        }
657
634
...
...
663
        saddr = (sockaddr*)&ip_addr;
640
        saddr = (sockaddr*)&ip_addr;
664
    } else {
641
    } else {
665
        memset(&unix_addr, 0, sizeof(unix_addr));
642
        memset(&unix_addr, 0, sizeof(unix_addr));
666
        unix_addr.sun_family = AF_UNIX;
643
        unix_addr.sun_family = AF_UNIX;
667
        if (strlen(host) > UNIX_PATH_MAX - 1) {
644
        if (strlen(host) > UNIX_PATH_MAX - 1) {
668
            LOGERR(("NetconCli::openconn: name too long: %s\n", host));
645
            LOGERR("NetconCli::openconn: name too long: "  << (host) << "\n" );
669
            return -1;
646
            return -1;
670
        }
647
        }
671
        strcpy(unix_addr.sun_path, host);
648
        strcpy(unix_addr.sun_path, host);
672
649
673
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
650
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
...
...
698
connectok:
675
connectok:
699
    if (timeo > 0) {
676
    if (timeo > 0) {
700
        set_nonblock(0);
677
        set_nonblock(0);
701
    }
678
    }
702
679
703
    LOGDEB2(("NetconCli::connect: setting keepalive\n"));
680
    LOGDEB2("NetconCli::connect: setting keepalive\n" );
704
    if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE,
681
    if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE,
705
                   (char *)&one, sizeof(one)) < 0) {
682
                   (char *)&one, sizeof(one)) < 0) {
706
        LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE");
683
        LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE");
707
    }
684
    }
708
    setpeer(host);
685
    setpeer(host);
709
    LOGDEB2(("NetconCli::openconn: connection opened ok\n"));
686
    LOGDEB2("NetconCli::openconn: connection opened ok\n" );
710
    ret = 0;
687
    ret = 0;
711
out:
688
out:
712
    if (ret < 0) {
689
    if (ret < 0) {
713
        closeconn();
690
        closeconn();
714
    }
691
    }
...
...
716
}
693
}
717
694
718
// Same as previous, but get the port number from services
695
// Same as previous, but get the port number from services
719
int NetconCli::openconn(const char *host, const char *serv, int timeo)
696
int NetconCli::openconn(const char *host, const char *serv, int timeo)
720
{
697
{
721
    LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv));
698
    LOGDEB2("Netconcli::openconn: host "  << (host) << ", serv "  << (serv) << "\n" );
722
699
723
    if (host[0]  != '/') {
700
    if (host[0]  != '/') {
724
        struct servent *sp;
701
        struct servent *sp;
725
        if ((sp = getservbyname(serv, "tcp")) == 0) {
702
        if ((sp = getservbyname(serv, "tcp")) == 0) {
726
            LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv));
703
            LOGERR("NetconCli::openconn: getservbyname failed for "  << (serv) << "\n" );
727
            return -1;
704
            return -1;
728
        }
705
        }
729
        // Callee expects the port number in host byte order
706
        // Callee expects the port number in host byte order
730
        return openconn(host, ntohs(sp->s_port), timeo);
707
        return openconn(host, ntohs(sp->s_port), timeo);
731
    } else {
708
    } else {
...
...
734
}
711
}
735
712
736
713
737
int NetconCli::setconn(int fd)
714
int NetconCli::setconn(int fd)
738
{
715
{
739
    LOGDEB2(("Netconcli::setconn: fd %d\n", fd));
716
    LOGDEB2("Netconcli::setconn: fd "  << (fd) << "\n" );
740
    closeconn();
717
    closeconn();
741
718
742
    m_fd = fd;
719
    m_fd = fd;
743
    m_ownfd = false;
720
    m_ownfd = false;
744
    setpeer("");
721
    setpeer("");
...
...
774
int NetconServLis::openservice(const char *serv, int backlog)
751
int NetconServLis::openservice(const char *serv, int backlog)
775
{
752
{
776
    int port;
753
    int port;
777
    struct servent  *servp;
754
    struct servent  *servp;
778
    if (!serv) {
755
    if (!serv) {
779
        LOGERR(("NetconServLis::openservice: null serv??\n"));
756
        LOGERR("NetconServLis::openservice: null serv??\n" );
780
        return -1;
757
        return -1;
781
    }
758
    }
782
    LOGDEB1(("NetconServLis::openservice: serv %s\n", serv));
759
    LOGDEB1("NetconServLis::openservice: serv "  << (serv) << "\n" );
783
#ifdef NETCON_ACCESSCONTROL
760
#ifdef NETCON_ACCESSCONTROL
784
    if (initperms(serv) < 0) {
761
    if (initperms(serv) < 0) {
785
        return -1;
762
        return -1;
786
    }
763
    }
787
#endif
764
#endif
788
765
789
    m_serv = serv;
766
    m_serv = serv;
790
    if (serv[0] != '/') {
767
    if (serv[0] != '/') {
791
        if ((servp = getservbyname(serv, "tcp")) == 0) {
768
        if ((servp = getservbyname(serv, "tcp")) == 0) {
792
            LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n",
769
            LOGERR("NetconServLis::openservice: getservbyname failed for "  << (serv) << "\n" );
793
                    serv));
794
            return -1;
770
            return -1;
795
        }
771
        }
796
        port = (int)ntohs((short)servp->s_port);
772
        port = (int)ntohs((short)servp->s_port);
797
        return openservice(port, backlog);
773
        return openservice(port, backlog);
798
    } else {
774
    } else {
799
        if (strlen(serv) > UNIX_PATH_MAX - 1) {
775
        if (strlen(serv) > UNIX_PATH_MAX - 1) {
800
            LOGERR(("NetconServLis::openservice: too long for AF_UNIX: %s\n",
776
            LOGERR("NetconServLis::openservice: too long for AF_UNIX: "  << (serv) << "\n" );
801
                    serv));
802
            return -1;
777
            return -1;
803
        }
778
        }
804
        int ret = -1;
779
        int ret = -1;
805
        struct sockaddr_un  addr;
780
        struct sockaddr_un  addr;
806
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
781
        if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
...
...
818
        if (listen(m_fd, backlog) < 0) {
793
        if (listen(m_fd, backlog) < 0) {
819
            LOGSYSERR("NetconServLis", "listen", "");
794
            LOGSYSERR("NetconServLis", "listen", "");
820
            goto out;
795
            goto out;
821
        }
796
        }
822
797
823
        LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
798
        LOGDEB1("NetconServLis::openservice: service opened ok\n" );
824
        ret = 0;
799
        ret = 0;
825
out:
800
out:
826
        if (ret < 0 && m_fd >= 0) {
801
        if (ret < 0 && m_fd >= 0) {
827
            close(m_fd);
802
            close(m_fd);
828
            m_fd = -1;
803
            m_fd = -1;
...
...
832
}
807
}
833
808
834
// Port is a natural host integer value
809
// Port is a natural host integer value
835
int NetconServLis::openservice(int port, int backlog)
810
int NetconServLis::openservice(int port, int backlog)
836
{
811
{
837
    LOGDEB1(("NetconServLis::openservice: port %d\n", port));
812
    LOGDEB1("NetconServLis::openservice: port "  << (port) << "\n" );
838
#ifdef NETCON_ACCESSCONTROL
813
#ifdef NETCON_ACCESSCONTROL
839
    if (initperms(port) < 0) {
814
    if (initperms(port) < 0) {
840
        return -1;
815
        return -1;
841
    }
816
    }
842
#endif
817
#endif
...
...
861
    if (listen(m_fd, backlog) < 0) {
836
    if (listen(m_fd, backlog) < 0) {
862
        LOGSYSERR("NetconServLis", "listen", "");
837
        LOGSYSERR("NetconServLis", "listen", "");
863
        goto out;
838
        goto out;
864
    }
839
    }
865
840
866
    LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
841
    LOGDEB1("NetconServLis::openservice: service opened ok\n" );
867
    ret = 0;
842
    ret = 0;
868
out:
843
out:
869
    if (ret < 0 && m_fd >= 0) {
844
    if (ret < 0 && m_fd >= 0) {
870
        close(m_fd);
845
        close(m_fd);
871
        m_fd = -1;
846
        m_fd = -1;
...
...
891
    if (permsinit) {
866
    if (permsinit) {
892
        return 0;
867
        return 0;
893
    }
868
    }
894
869
895
    if (serv == 0 || *serv == 0 || strlen(serv) > 80) {
870
    if (serv == 0 || *serv == 0 || strlen(serv) > 80) {
896
        LOGERR(("NetconServLis::initperms: bad service name %s\n", serv));
871
        LOGERR("NetconServLis::initperms: bad service name "  << (serv) << "\n" );
897
        return -1;
872
        return -1;
898
    }
873
    }
899
874
900
    char keyname[100];
875
    char keyname[100];
901
    sprintf(keyname, "%s_okaddrs", serv);
876
    sprintf(keyname, "%s_okaddrs", serv);
902
    if (genparams->getparam(keyname, &okaddrs, 1) < 0) {
877
    if (genparams->getparam(keyname, &okaddrs, 1) < 0) {
903
        serv = "default";
878
        serv = "default";
904
        sprintf(keyname, "%s_okaddrs", serv);
879
        sprintf(keyname, "%s_okaddrs", serv);
905
        if (genparams->getparam(keyname, &okaddrs) < 0) {
880
        if (genparams->getparam(keyname, &okaddrs) < 0) {
906
            LOGERR(("NetconServLis::initperms: no okaddrs found in config file\n"));
881
            LOGERR("NetconServLis::initperms: no okaddrs found in config file\n" );
907
            return -1;
882
            return -1;
908
        }
883
        }
909
    }
884
    }
910
    sprintf(keyname, "%s_okmasks", serv);
885
    sprintf(keyname, "%s_okmasks", serv);
911
    if (genparams->getparam(keyname, &okmasks)) {
886
    if (genparams->getparam(keyname, &okmasks)) {
912
        LOGERR(("NetconServLis::initperms: okmasks not found\n"));
887
        LOGERR("NetconServLis::initperms: okmasks not found\n" );
913
        return -1;
888
        return -1;
914
    }
889
    }
915
    if (okaddrs.len == 0 || okmasks.len == 0) {
890
    if (okaddrs.len == 0 || okmasks.len == 0) {
916
        LOGERR(("NetconServLis::initperms: len 0 for okmasks or okaddrs\n"));
891
        LOGERR("NetconServLis::initperms: len 0 for okmasks or okaddrs\n" );
917
        return -1;
892
        return -1;
918
    }
893
    }
919
894
920
    permsinit = 1;
895
    permsinit = 1;
921
    return 0;
896
    return 0;
...
...
933
}
908
}
934
909
935
NetconServCon *
910
NetconServCon *
936
NetconServLis::accept(int timeo)
911
NetconServLis::accept(int timeo)
937
{
912
{
938
    LOGDEB(("NetconServLis::accept\n"));
913
    LOGDEB("NetconServLis::accept\n" );
939
914
940
    if (timeo > 0) {
915
    if (timeo > 0) {
941
        int ret = select1(m_fd, timeo);
916
        int ret = select1(m_fd, timeo);
942
        if (ret == 0) {
917
        if (ret == 0) {
943
            LOGDEB2(("NetconServLis::accept timed out\n"));
918
            LOGDEB2("NetconServLis::accept timed out\n" );
944
            m_didtimo = 1;
919
            m_didtimo = 1;
945
            return 0;
920
            return 0;
946
        }
921
        }
947
        if (ret < 0) {
922
        if (ret < 0) {
948
            LOGSYSERR("NetconServLis::accept", "select", "");
923
            LOGSYSERR("NetconServLis::accept", "select", "");
...
...
974
        }
949
        }
975
    }
950
    }
976
951
977
    con = new NetconServCon(newfd);
952
    con = new NetconServCon(newfd);
978
    if (con == 0) {
953
    if (con == 0) {
979
        LOGERR(("NetconServLis::accept: new NetconServCon failed\n"));
954
        LOGERR("NetconServLis::accept: new NetconServCon failed\n" );
980
        goto out;
955
        goto out;
981
    }
956
    }
982
957
983
    // Retrieve peer's host name. Errors are non fatal
958
    // Retrieve peer's host name. Errors are non fatal
984
    if (m_serv.empty() || m_serv[0] != '/') {
959
    if (m_serv.empty() || m_serv[0] != '/') {
985
        struct hostent *hp;
960
        struct hostent *hp;
986
        if ((hp = gethostbyaddr((char *) & (who.sin_addr),
961
        if ((hp = gethostbyaddr((char *) & (who.sin_addr),
987
                                sizeof(struct in_addr), AF_INET)) == 0) {
962
                                sizeof(struct in_addr), AF_INET)) == 0) {
988
            LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
963
            LOGERR("NetconServLis::accept: gethostbyaddr failed for addr 0x"  << (who.sin_addr.s_addr) << "\n" );
989
                    who.sin_addr.s_addr));
990
            con->setpeer(inet_ntoa(who.sin_addr));
964
            con->setpeer(inet_ntoa(who.sin_addr));
991
        } else {
965
        } else {
992
            con->setpeer(hp->h_name);
966
            con->setpeer(hp->h_name);
993
        }
967
        }
994
    } else {
968
    } else {
995
        con->setpeer(m_serv.c_str());
969
        con->setpeer(m_serv.c_str());
996
    }
970
    }
997
971
998
    LOGDEB2(("NetconServLis::accept: setting keepalive\n"));
972
    LOGDEB2("NetconServLis::accept: setting keepalive\n" );
999
    if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE,
973
    if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE,
1000
                   (char *)&one, sizeof(one)) < 0) {
974
                   (char *)&one, sizeof(one)) < 0) {
1001
        LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
975
        LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE");
1002
    }
976
    }
1003
    LOGDEB2(("NetconServLis::accept: got connect from %s\n", con->getpeer()));
977
    LOGDEB2("NetconServLis::accept: got connect from "  << (con->getpeer()) << "\n" );
1004
978
1005
out:
979
out:
1006
    if (con == 0 && newfd >= 0) {
980
    if (con == 0 && newfd >= 0) {
1007
        close(newfd);
981
        close(newfd);
1008
    }
982
    }
...
...
1020
994
1021
    struct sockaddr *addr = (struct sockaddr *)cl;
995
    struct sockaddr *addr = (struct sockaddr *)cl;
1022
    unsigned long ip_addr;
996
    unsigned long ip_addr;
1023
997
1024
    if (addr->sa_family != AF_INET) {
998
    if (addr->sa_family != AF_INET) {
1025
        LOGERR(("NetconServLis::checkperms: connection from non-INET addr !\n"));
999
        LOGERR("NetconServLis::checkperms: connection from non-INET addr !\n" );
1026
        return -1;
1000
        return -1;
1027
    }
1001
    }
1028
1002
1029
    ip_addr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
1003
    ip_addr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
1030
    LOGDEB2(("checkperms: ip_addr: 0x%x\n", ip_addr));
1004
    LOGDEB2("checkperms: ip_addr: 0x"  << (ip_addr) << "\n" );
1031
    for (int i = 0; i < okaddrs.len; i++) {
1005
    for (int i = 0; i < okaddrs.len; i++) {
1032
        unsigned int mask;
1006
        unsigned int mask;
1033
        if (i < okmasks.len) {
1007
        if (i < okmasks.len) {
1034
            mask = okmasks.intarray[i];
1008
            mask = okmasks.intarray[i];
1035
        } else {
1009
        } else {
1036
            mask = okmasks.intarray[okmasks.len - 1];
1010
            mask = okmasks.intarray[okmasks.len - 1];
1037
        }
1011
        }
1038
        LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n",
1012
        LOGDEB2("checkperms: trying okaddr 0x"  << (okaddrs.intarray[i]) << ", mask 0x"  << (mask) << "\n" );
1039
                 okaddrs.intarray[i], mask));
1040
        if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) {
1013
        if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) {
1041
            return (0);
1014
            return (0);
1042
        }
1015
        }
1043
    }
1016
    }
1044
    LOGERR(("NetconServLis::checkperm: connection from bad address 0x%x\n",
1017
    LOGERR("NetconServLis::checkperm: connection from bad address 0x"  << (ip_addr) << "\n" );
1045
            ip_addr));
1046
    return -1;
1018
    return -1;
1047
}
1019
}
1048
#endif /* NETCON_ACCESSCONTROL */
1020
#endif /* NETCON_ACCESSCONTROL */
1049
1021
1050
1022
...
...
1057
#include <stdlib.h>
1029
#include <stdlib.h>
1058
#include <unistd.h>
1030
#include <unistd.h>
1059
#include <signal.h>
1031
#include <signal.h>
1060
#include <string.h>
1032
#include <string.h>
1061
1033
1062
#include "debuglog.h"
1034
#include "log.h"
1035
1063
#include "netcon.h"
1036
#include "netcon.h"
1064
1037
1065
using namespace std;
1038
using namespace std;
1066
1039
1067
static char *thisprog;
1040
static char *thisprog;
...
...
1120
                break;
1093
                break;
1121
            }
1094
            }
1122
        argc--;
1095
        argc--;
1123
        argv++;
1096
        argv++;
1124
    }
1097
    }
1125
    DebugLog::setfilename("stderr");
1098
1126
    DebugLog::getdbl()->setloglevel(DEBDEB2);
1099
    Logger::getTheLog("")->setLogLevel(Logger::LLDEB2);
1127
1100
1128
    if (op_flags & OPT_c) {
1101
    if (op_flags & OPT_c) {
1129
        if (argc != 2) {
1102
        if (argc != 2) {
1130
            Usage();
1103
            Usage();
1131
        }
1104
        }
...
...
1153
1126
1154
class CliNetconWorker : public NetconWorker {
1127
class CliNetconWorker : public NetconWorker {
1155
public:
1128
public:
1156
    CliNetconWorker()  : m_count(0) {}
1129
    CliNetconWorker()  : m_count(0) {}
1157
    int data(NetconData *con, Netcon::Event reason) {
1130
    int data(NetconData *con, Netcon::Event reason) {
1158
        LOGDEB(("clientdata\n"));
1131
        LOGDEB("clientdata\n" );
1159
        if (reason & Netcon::NETCONPOLL_WRITE) {
1132
        if (reason & Netcon::NETCONPOLL_WRITE) {
1160
            sprintf(fromcli, "Bonjour Bonjour client %d, count %d",
1133
            sprintf(fromcli, "Bonjour Bonjour client %d, count %d",
1161
                    getpid(), m_count);
1134
                    getpid(), m_count);
1162
            con->setselevents(Netcon::NETCONPOLL_READ);
1135
            con->setselevents(Netcon::NETCONPOLL_READ);
1163
            if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
1136
            if (con->send(fromcli, strlen(fromcli) + 1) < 0) {
...
...
1255
// Server-side sample code
1228
// Server-side sample code
1256
class ServNetconWorker : public NetconWorker {
1229
class ServNetconWorker : public NetconWorker {
1257
public:
1230
public:
1258
    ServNetconWorker() : m_count(0) {}
1231
    ServNetconWorker() : m_count(0) {}
1259
    int data(NetconData *con, Netcon::Event reason) {
1232
    int data(NetconData *con, Netcon::Event reason) {
1260
        LOGDEB(("serverdata\n"));
1233
        LOGDEB("serverdata\n" );
1261
        if (reason & Netcon::NETCONPOLL_WRITE) {
1234
        if (reason & Netcon::NETCONPOLL_WRITE) {
1262
            con->setselevents(Netcon::NETCONPOLL_READ);
1235
            con->setselevents(Netcon::NETCONPOLL_READ);
1263
            char fromserv[200];
1236
            char fromserv[200];
1264
            sprintf(fromserv,
1237
            sprintf(fromserv,
1265
                    "Du serveur: mon fd pour ce client est  %d, mon compte %d",
1238
                    "Du serveur: mon fd pour ce client est  %d, mon compte %d",
...
...
1358
    }
1331
    }
1359
    return 0;
1332
    return 0;
1360
}
1333
}
1361
1334
1362
#endif /* TEST_NETCON */
1335
#endif /* TEST_NETCON */
1336