|
a/src/netcon.cpp |
|
b/src/netcon.cpp |
|
... |
|
... |
65 |
|
65 |
|
66 |
// Need &one, &zero for setsockopt...
|
66 |
// Need &one, &zero for setsockopt...
|
67 |
static const int one = 1;
|
67 |
static const int one = 1;
|
68 |
static const int zero = 0;
|
68 |
static const int zero = 0;
|
69 |
|
69 |
|
70 |
#define LOGSYSERR(who, call, spar) \
|
70 |
#define LOGSYSERR(who, call, spar) \
|
71 |
LOGERR((who) << ": " << (call) << "(" << (spar) << ") errno " << \
|
71 |
LOGERR(who << ": " << call << "(" << spar << ") errno " << \
|
72 |
(errno) << " (" << (strerror(errno)) << ")\n")
|
72 |
errno << " (" << strerror(errno) << ")\n")
|
73 |
|
73 |
|
74 |
#ifndef MIN
|
74 |
#ifndef MIN
|
75 |
#define MIN(a,b) ((a)<(b)?(a):(b))
|
75 |
#define MIN(a,b) ((a)<(b)?(a):(b))
|
76 |
#endif
|
76 |
#endif
|
77 |
#ifndef MAX
|
77 |
#ifndef MAX
|
|
... |
|
... |
184 |
nfds = 0;
|
184 |
nfds = 0;
|
185 |
for (map<int, NetconP>::iterator it = m_polldata.begin();
|
185 |
for (map<int, NetconP>::iterator it = m_polldata.begin();
|
186 |
it != m_polldata.end(); it++) {
|
186 |
it != m_polldata.end(); it++) {
|
187 |
NetconP& pll = it->second;
|
187 |
NetconP& pll = it->second;
|
188 |
int fd = it->first;
|
188 |
int fd = it->first;
|
189 |
LOGDEB2("Selectloop: fd " << (fd) << " flags 0x" << (pll->m_wantedEvents) << "\n" );
|
189 |
LOGDEB2("Selectloop: fd " << fd << " flags 0x" <<
|
|
|
190 |
pll->m_wantedEvents << "\n");
|
190 |
if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
|
191 |
if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
|
191 |
FD_SET(fd, &rd);
|
192 |
FD_SET(fd, &rd);
|
192 |
nfds = MAX(nfds, fd + 1);
|
193 |
nfds = MAX(nfds, fd + 1);
|
193 |
}
|
194 |
}
|
194 |
if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
|
195 |
if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) {
|
|
... |
|
... |
208 |
m_polldata.clear();
|
209 |
m_polldata.clear();
|
209 |
LOGDEB1("Netcon::selectloop: no fds\n" );
|
210 |
LOGDEB1("Netcon::selectloop: no fds\n" );
|
210 |
return 0;
|
211 |
return 0;
|
211 |
}
|
212 |
}
|
212 |
|
213 |
|
213 |
LOGDEB2("Netcon::selectloop: selecting, nfds = " << (nfds) << "\n" );
|
214 |
LOGDEB2("Netcon::selectloop: selecting, nfds = " << nfds << "\n");
|
214 |
|
215 |
|
215 |
// Compute the next timeout according to what might need to be
|
216 |
// Compute the next timeout according to what might need to be
|
216 |
// done apart from waiting for data
|
217 |
// done apart from waiting for data
|
217 |
struct timeval tv;
|
218 |
struct timeval tv;
|
218 |
periodictimeout(&tv);
|
219 |
periodictimeout(&tv);
|
|
... |
|
... |
360 |
return -1;
|
361 |
return -1;
|
361 |
}
|
362 |
}
|
362 |
return 0;
|
363 |
return 0;
|
363 |
}
|
364 |
}
|
364 |
|
365 |
|
|
|
366 |
|
365 |
// Set/reset non-blocking flag on fd
|
367 |
// Set/reset non-blocking flag on fd
|
366 |
int Netcon::set_nonblock(int onoff)
|
368 |
int Netcon::set_nonblock(int onoff)
|
367 |
{
|
369 |
{
|
368 |
int flags = fcntl(m_fd, F_GETFL, 0);
|
370 |
int flags = fcntl(m_fd, F_GETFL, 0);
|
369 |
if (flags != -1) {
|
371 |
if (flags != -1) {
|
|
... |
|
... |
377 |
}
|
379 |
}
|
378 |
|
380 |
|
379 |
/////////////////////////////////////////////////////////////////////
|
381 |
/////////////////////////////////////////////////////////////////////
|
380 |
// Data socket (NetconData) methods
|
382 |
// Data socket (NetconData) methods
|
381 |
|
383 |
|
|
|
384 |
NetconData::NetconData(bool cancellable)
|
|
|
385 |
: m_buf(0), m_bufbase(0), m_bufbytes(0), m_bufsize(0), m_wkfds{-1,-1}
|
|
|
386 |
{
|
|
|
387 |
if (cancellable) {
|
|
|
388 |
if (pipe(m_wkfds) < 0) {
|
|
|
389 |
LOGSYSERR("NetconData::NetconData", "pipe", "");
|
|
|
390 |
m_wkfds[0] = m_wkfds[1] = -1;
|
|
|
391 |
}
|
|
|
392 |
LOGDEB2("NetconData:: m_wkfds[0] " << m_wkfds[0] << " m_wkfds[1] " <<
|
|
|
393 |
m_wkfds[1] << endl);
|
|
|
394 |
for (int i = 0; i < 2; i++) {
|
|
|
395 |
int flags = fcntl(m_wkfds[i], F_GETFL, 0);
|
|
|
396 |
fcntl(m_wkfds[i], F_SETFL, flags | O_NONBLOCK);
|
|
|
397 |
}
|
|
|
398 |
}
|
|
|
399 |
}
|
|
|
400 |
|
382 |
NetconData::~NetconData()
|
401 |
NetconData::~NetconData()
|
383 |
{
|
402 |
{
|
384 |
freeZ(m_buf);
|
403 |
freeZ(m_buf);
|
385 |
m_bufbase = 0;
|
404 |
m_bufbase = 0;
|
386 |
m_bufbytes = m_bufsize = 0;
|
405 |
m_bufbytes = m_bufsize = 0;
|
|
|
406 |
for (int i = 0; i < 2; i++) {
|
|
|
407 |
if (m_wkfds[i] >= 0) {
|
|
|
408 |
close(m_wkfds[i]);
|
|
|
409 |
}
|
|
|
410 |
}
|
387 |
}
|
411 |
}
|
388 |
|
412 |
|
389 |
int NetconData::send(const char *buf, int cnt, int expedited)
|
413 |
int NetconData::send(const char *buf, int cnt, int expedited)
|
390 |
{
|
414 |
{
|
391 |
LOGDEB2("NetconData::send: fd " << (m_fd) << " cnt " << (cnt) << " expe " << (expedited) << "\n" );
|
415 |
LOGDEB2("NetconData::send: fd " << m_fd << " cnt " << cnt <<
|
|
|
416 |
" expe " << expedited << "\n");
|
392 |
int flag = 0;
|
417 |
int flag = 0;
|
393 |
if (m_fd < 0) {
|
418 |
if (m_fd < 0) {
|
394 |
LOGERR("NetconData::send: connection not opened\n" );
|
419 |
LOGERR("NetconData::send: connection not opened\n" );
|
395 |
return -1;
|
420 |
return -1;
|
396 |
}
|
421 |
}
|
397 |
if (expedited) {
|
422 |
if (expedited) {
|
398 |
LOGDEB2("NetconData::send: expedited data, count " << (cnt) << " bytes\n" );
|
423 |
LOGDEB2("NetconData::send: expedited data, count " <<cnt << " bytes\n");
|
399 |
flag = MSG_OOB;
|
424 |
flag = MSG_OOB;
|
400 |
}
|
425 |
}
|
401 |
int ret;
|
426 |
int ret;
|
402 |
// There is a bug in the uthread version of sendto() in FreeBSD at
|
427 |
// There is a bug in the uthread version of sendto() in FreeBSD at
|
403 |
// least up to 2.2.7, so avoid using it when possible
|
428 |
// least up to 2.2.7, so avoid using it when possible
|
|
... |
|
... |
414 |
LOGSYSERR("NetconData::send", "send", fdcbuf);
|
439 |
LOGSYSERR("NetconData::send", "send", fdcbuf);
|
415 |
}
|
440 |
}
|
416 |
return ret;
|
441 |
return ret;
|
417 |
}
|
442 |
}
|
418 |
|
443 |
|
419 |
// Test for data available
|
444 |
void NetconData::cancelReceive()
|
420 |
int NetconData::readready()
|
|
|
421 |
{
|
445 |
{
|
422 |
LOGDEB2("NetconData::readready\n" );
|
|
|
423 |
if (m_fd < 0) {
|
446 |
if (m_wkfds[1] >= 0) {
|
424 |
LOGERR("NetconData::readready: connection not opened\n" );
|
447 |
LOGDEB2("NetconData::cancelReceive: writing to " << m_wkfds[1] << endl);
|
425 |
return -1;
|
448 |
::write(m_wkfds[1], "!", 1);
|
426 |
}
|
449 |
}
|
427 |
return select1(m_fd, 0);
|
|
|
428 |
}
|
|
|
429 |
|
|
|
430 |
// Test for writable
|
|
|
431 |
int NetconData::writeready()
|
|
|
432 |
{
|
|
|
433 |
LOGDEB2("NetconData::writeready\n" );
|
|
|
434 |
if (m_fd < 0) {
|
|
|
435 |
LOGERR("NetconData::writeready: connection not opened\n" );
|
|
|
436 |
return -1;
|
|
|
437 |
}
|
|
|
438 |
return select1(m_fd, 0, 1);
|
|
|
439 |
}
|
450 |
}
|
440 |
|
451 |
|
441 |
// Receive at most cnt bytes (maybe less)
|
452 |
// Receive at most cnt bytes (maybe less)
|
442 |
int NetconData::receive(char *buf, int cnt, int timeo)
|
453 |
int NetconData::receive(char *buf, int cnt, int timeo)
|
443 |
{
|
454 |
{
|
444 |
LOGDEB2("NetconData::receive: cnt " << (cnt) << " timeo " << (timeo) << " m_buf 0x" << (m_buf) << " m_bufbytes " << (m_bufbytes) << "\n" );
|
455 |
LOGDEB2("NetconData::receive: cnt " << cnt << " timeo " << timeo <<
|
|
|
456 |
" m_buf 0x" << m_buf << " m_bufbytes " << m_bufbytes << "\n");
|
|
|
457 |
|
445 |
if (m_fd < 0) {
|
458 |
if (m_fd < 0) {
|
446 |
LOGERR("NetconData::receive: connection not opened\n" );
|
459 |
LOGERR("NetconData::receive: connection not opened\n" );
|
447 |
return -1;
|
460 |
return -1;
|
448 |
}
|
461 |
}
|
|
|
462 |
|
449 |
int fromibuf = 0;
|
463 |
int fromibuf = 0;
|
450 |
// Get whatever might have been left in the buffer by a previous
|
464 |
// Get whatever might have been left in the buffer by a previous
|
451 |
// getline, except if we're called to fill the buffer of course
|
465 |
// getline, except if we're called to fill the buffer of course
|
452 |
if (m_buf && m_bufbytes > 0 && (buf < m_buf || buf > m_buf + m_bufsize)) {
|
466 |
if (m_buf && m_bufbytes > 0 && (buf < m_buf || buf > m_buf + m_bufsize)) {
|
453 |
fromibuf = MIN(m_bufbytes, cnt);
|
467 |
fromibuf = MIN(m_bufbytes, cnt);
|
454 |
memcpy(buf, m_bufbase, fromibuf);
|
468 |
memcpy(buf, m_bufbase, fromibuf);
|
455 |
m_bufbytes -= fromibuf;
|
469 |
m_bufbytes -= fromibuf;
|
456 |
m_bufbase += fromibuf;
|
470 |
m_bufbase += fromibuf;
|
457 |
cnt -= fromibuf;
|
471 |
cnt -= fromibuf;
|
458 |
LOGDEB2("NetconData::receive: transferred " << (fromibuf) << " from mbuf\n" );
|
472 |
LOGDEB2("NetconData::receive: got " << fromibuf << " from mbuf\n");
|
459 |
if (cnt <= 0) {
|
473 |
if (cnt <= 0) {
|
460 |
return fromibuf;
|
474 |
return fromibuf;
|
461 |
}
|
475 |
}
|
462 |
}
|
476 |
}
|
|
|
477 |
|
463 |
if (timeo > 0) {
|
478 |
if (timeo > 0) {
|
|
|
479 |
struct timeval tv;
|
|
|
480 |
tv.tv_sec = timeo;
|
|
|
481 |
tv.tv_usec = 0;
|
|
|
482 |
fd_set rd;
|
|
|
483 |
FD_ZERO(&rd);
|
|
|
484 |
FD_SET(m_fd, &rd);
|
|
|
485 |
bool cancellable = (m_wkfds[0] >= 0);
|
|
|
486 |
if (cancellable) {
|
|
|
487 |
LOGDEB2("NetconData::receive: cancel fd " << m_wkfds[0] << endl);
|
|
|
488 |
FD_SET(m_wkfds[0], &rd);
|
|
|
489 |
}
|
|
|
490 |
int nfds = MAX(m_fd, m_wkfds[0]) + 1;
|
|
|
491 |
|
464 |
int ret = select1(m_fd, timeo);
|
492 |
int ret = select(nfds, &rd, 0, 0, &tv);
|
465 |
if (ret == 0) {
|
493 |
LOGDEB2("NetconData::receive: select returned " << ret << endl);
|
466 |
LOGDEB2("NetconData::receive timed out\n" );
|
494 |
|
|
|
495 |
if (cancellable && FD_ISSET(m_wkfds[0], &rd)) {
|
|
|
496 |
char b[100];
|
|
|
497 |
read(m_wkfds[0], b, 100);
|
|
|
498 |
return Cancelled;
|
|
|
499 |
}
|
|
|
500 |
|
|
|
501 |
if (!FD_ISSET(m_fd, &rd)) {
|
467 |
m_didtimo = 1;
|
502 |
m_didtimo = 1;
|
468 |
return -1;
|
503 |
return TimeoutOrError;
|
469 |
}
|
504 |
}
|
|
|
505 |
|
470 |
if (ret < 0) {
|
506 |
if (ret < 0) {
|
471 |
LOGSYSERR("NetconData::receive", "select", "");
|
507 |
LOGSYSERR("NetconData::receive", "select", "");
|
472 |
return -1;
|
508 |
m_didtimo = 0;
|
473 |
}
|
509 |
return TimeoutOrError;
|
474 |
}
|
510 |
}
|
|
|
511 |
}
|
|
|
512 |
|
475 |
m_didtimo = 0;
|
513 |
m_didtimo = 0;
|
476 |
if ((cnt = read(m_fd, buf + fromibuf, cnt)) < 0) {
|
514 |
if ((cnt = read(m_fd, buf + fromibuf, cnt)) < 0) {
|
477 |
char fdcbuf[20];
|
|
|
478 |
sprintf(fdcbuf, "%d", m_fd);
|
|
|
479 |
LOGSYSERR("NetconData::receive", "read", fdcbuf);
|
515 |
LOGSYSERR("NetconData::receive", "read", m_fd);
|
480 |
return -1;
|
516 |
return -1;
|
481 |
}
|
517 |
}
|
482 |
LOGDEB2("NetconData::receive: normal return, cnt " << (cnt) << "\n" );
|
518 |
LOGDEB2("NetconData::receive: normal return, fromibuf " << fromibuf <<
|
|
|
519 |
" cnt " << cnt << "\n");
|
483 |
return fromibuf + cnt;
|
520 |
return fromibuf + cnt;
|
484 |
}
|
521 |
}
|
485 |
|
522 |
|
486 |
// Receive exactly cnt bytes (except for timeout)
|
523 |
// Receive exactly cnt bytes (except for timeout)
|
487 |
int NetconData::doreceive(char *buf, int cnt, int timeo)
|
524 |
int NetconData::doreceive(char *buf, int cnt, int timeo)
|
488 |
{
|
525 |
{
|
489 |
int got, cur;
|
526 |
int got, cur;
|
490 |
LOGDEB2("Netcon::doreceive: cnt " << (cnt) << ", timeo " << (timeo) << "\n" );
|
527 |
LOGDEB2("Netcon::doreceive: cnt " << cnt << ", timeo " << timeo << "\n");
|
491 |
cur = 0;
|
528 |
cur = 0;
|
492 |
while (cnt > cur) {
|
529 |
while (cnt > cur) {
|
493 |
got = receive(buf, cnt - cur, timeo);
|
530 |
got = receive(buf, cnt - cur, timeo);
|
494 |
LOGDEB2("Netcon::doreceive: got " << (got) << "\n" );
|
531 |
LOGDEB2("Netcon::doreceive: got " << (got) << "\n" );
|
495 |
if (got < 0) {
|
532 |
if (got < 0) {
|
496 |
return -1;
|
533 |
return got;
|
497 |
}
|
534 |
}
|
498 |
if (got == 0) {
|
535 |
if (got == 0) {
|
499 |
return cur;
|
536 |
return cur;
|
500 |
}
|
537 |
}
|
501 |
cur += got;
|
538 |
cur += got;
|