diff --git a/src/common/config.h b/src/common/config.h new file mode 120000 index 00000000..6eb68934 --- /dev/null +++ b/src/common/config.h @@ -0,0 +1 @@ +autoconfig.h \ No newline at end of file diff --git a/src/utils/netcon.cpp b/src/utils/netcon.cpp index 995b9ce2..d0f01d47 100644 --- a/src/utils/netcon.cpp +++ b/src/utils/netcon.cpp @@ -1,4 +1,19 @@ -/* Copyright (C) 2002 Jean-Francois Dockes */ +/* Copyright (C) 2002 J.F. Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ // Wrapper classes for the socket interface @@ -16,8 +31,8 @@ #include #include #include - #include +#include #include #include #include @@ -25,17 +40,40 @@ #include -#ifndef NO_NAMESPACES -using namespace std; + +#ifdef RECOLL_DATADIR +#include "debuglog.h" + +#else + +#define LOGFATAL(X) +#define LOGERR(X) +#define LOGINFO(X) +#define LOGDEB(X) +#define LOGDEB0(X) +#define LOGDEB1(X) +#define LOGDEB2(X) +#define LOGDEB3(X) +#define LOGDEB4(X) #endif -#include "debuglog.h" #include "netcon.h" +using namespace std; + #ifndef SOCKLEN_T #define SOCKLEN_T socklen_t #endif +// Size of path buffer in sockaddr_un (AF_UNIX socket +// addr). Mysteriously it's 108 (explicit value) under linux, no +// define accessible. Let's take a little margin as it appears that +// some systems use 92. I believe we could also malloc a variable size +// struct but why bother. +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 90 +#endif + // Need &one, &zero for setsockopt... static const int one = 1; static const int zero = 0; @@ -72,13 +110,13 @@ int Netcon::select1(int fd, int timeo, int write) FD_ZERO(&rd); FD_SET(fd, &rd); if (write) { - ret = select(fd+1, 0, &rd, 0, &tv); + ret = select(fd+1, 0, &rd, 0, &tv); } else { - ret = select(fd+1, &rd, 0, 0, &tv); + ret = select(fd+1, &rd, 0, 0, &tv); } if (!FD_ISSET(fd, &rd)) { - LOGERR(("Netcon::select1: fd not ready after select ??\n")); - return -1; + LOGERR(("Netcon::select1: fd not ready after select ??\n")); + return -1; } return ret; } @@ -88,8 +126,9 @@ void SelectLoop::setperiodichandler(int (*handler)(void *), void *p, int ms) m_periodichandler = handler; m_periodicparam = p; m_periodicmillis = ms; - if (m_periodicmillis > 0) - gettimeofday(&m_lasthdlcall, 0); + if (m_periodicmillis > 0) { + gettimeofday(&m_lasthdlcall, 0); + } } // Compute the appropriate timeout so that the select call returns in @@ -100,19 +139,20 @@ void SelectLoop::periodictimeout(struct timeval *tv) // after a very long time (we'd need to pass NULL to select for an // infinite wait, and I'm too lazy to handle it) if (m_periodicmillis <= 0) { - tv->tv_sec = 10000; - tv->tv_usec = 0; - return; + tv->tv_sec = 10000; + tv->tv_usec = 0; + return; } struct timeval mtv; gettimeofday(&mtv, 0); int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv); - // millis <= 0 means we should have already done the thing. *dont* set the + // millis <= 0 means we should have already done the thing. *dont* set the // tv to 0, which means no timeout at all ! - if (millis <= 0) - millis = 1; + if (millis <= 0) { + millis = 1; + } tv->tv_sec = millis / 1000; tv->tv_usec = (millis % 1000) * 1000; } @@ -121,17 +161,19 @@ void SelectLoop::periodictimeout(struct timeval *tv) // caller if it or we return 0 int SelectLoop::maybecallperiodic() { - if (m_periodicmillis <= 0) - return 1; + if (m_periodicmillis <= 0) { + return 1; + } struct timeval mtv; gettimeofday(&mtv, 0); int millis = m_periodicmillis - MILLIS(m_lasthdlcall, mtv); if (millis <= 0) { - gettimeofday(&m_lasthdlcall, 0); - if (m_periodichandler) - return m_periodichandler(m_periodicparam); - else - return 0; + gettimeofday(&m_lasthdlcall, 0); + if (m_periodichandler) { + return m_periodichandler(m_periodicparam); + } else { + return 0; + } } return 1; } @@ -139,110 +181,117 @@ int SelectLoop::maybecallperiodic() int SelectLoop::doLoop() { for (;;) { - if (m_selectloopDoReturn) { - m_selectloopDoReturn = false; - LOGDEB(("Netcon::selectloop: returning on request\n")); - return m_selectloopReturnValue; - } - int nfds; - fd_set rd, wd; - FD_ZERO(&rd); - FD_ZERO(&wd); - - // Walk the netcon map and set up the read and write fd_sets - // for select() - nfds = 0; - for (map::iterator it = m_polldata.begin(); - it != m_polldata.end(); it++) { - NetconP &pll = it->second; - int fd = it->first; - LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents)); - if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) { - FD_SET(fd, &rd); - nfds = MAX(nfds, fd + 1); - } - if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) { - FD_SET(fd, &wd); - nfds = MAX(nfds, fd + 1); - } - } + if (m_selectloopDoReturn) { + m_selectloopDoReturn = false; + LOGDEB(("Netcon::selectloop: returning on request\n")); + return m_selectloopReturnValue; + } + int nfds; + fd_set rd, wd; + FD_ZERO(&rd); + FD_ZERO(&wd); - if (nfds == 0) { - // This should never happen in a server as we should at least - // always monitor the main listening server socket. For a - // client, it's up to client code to avoid or process this - // condition. + // Walk the netcon map and set up the read and write fd_sets + // for select() + nfds = 0; + for (map::iterator it = m_polldata.begin(); + it != m_polldata.end(); it++) { + NetconP &pll = it->second; + int fd = it->first; + LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents)); + if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) { + FD_SET(fd, &rd); + nfds = MAX(nfds, fd + 1); + } + if (pll->m_wantedEvents & Netcon::NETCONPOLL_WRITE) { + FD_SET(fd, &wd); + nfds = MAX(nfds, fd + 1); + } + } - // Just in case there would still be open fds in there - // (with no r/w flags set). Should not be needed, but safer - m_polldata.clear(); - LOGDEB1(("Netcon::selectloop: no fds\n")); - return 0; - } + if (nfds == 0) { + // This should never happen in a server as we should at least + // always monitor the main listening server socket. For a + // client, it's up to client code to avoid or process this + // condition. - LOGDEB2(("Netcon::selectloop: selecting, nfds = %d\n", nfds)); + // Just in case there would still be open fds in there + // (with no r/w flags set). Should not be needed, but safer + m_polldata.clear(); + LOGDEB1(("Netcon::selectloop: no fds\n")); + return 0; + } - // Compute the next timeout according to what might need to be - // done apart from waiting for data - struct timeval tv; - periodictimeout(&tv); - // Wait for something to happen - int ret = select(nfds, &rd, &wd, 0, &tv); - LOGDEB2(("Netcon::selectloop: select returns %d\n", ret)); - if (ret < 0) { - LOGSYSERR("Netcon::selectloop", "select", ""); - return -1; - } - if (m_periodicmillis > 0) - if (maybecallperiodic() <= 0) - return 1; + LOGDEB2(("Netcon::selectloop: selecting, nfds = %d\n", nfds)); - // Timeout, do it again. - if (ret == 0) - continue; + // Compute the next timeout according to what might need to be + // done apart from waiting for data + struct timeval tv; + periodictimeout(&tv); + // Wait for something to happen + int ret = select(nfds, &rd, &wd, 0, &tv); + LOGDEB2(("Netcon::selectloop: select returns %d\n", ret)); + if (ret < 0) { + LOGSYSERR("Netcon::selectloop", "select", ""); + return -1; + } + if (m_periodicmillis > 0) + if (maybecallperiodic() <= 0) { + return 1; + } - // We don't start the fd sweep at 0, else some fds would be advantaged. - // Note that we do an fd sweep, not a map sweep. This is - // inefficient because the fd array may be very sparse. Otoh, the - // map may change between 2 sweeps, so that we'd have to be smart - // with the iterator. As the cost per unused fd is low (just 2 bit - // flag tests), we keep it like this for now - if (m_placetostart >= nfds) - m_placetostart = 0; - int i, fd; - for (i = 0, fd = m_placetostart; i < nfds;i++, fd++) { - if (fd >= nfds) - fd = 0; + // Timeout, do it again. + if (ret == 0) { + continue; + } - int canread = FD_ISSET(fd, &rd); - int canwrite = FD_ISSET(fd, &wd); - bool none = !canread && !canwrite; - LOGDEB2(("Netcon::selectloop: fd %d %s %s %s\n", fd, - none ? "blocked" : "can" , canread ? "read" : "", - canwrite ? "write" : "")); - if (none) - continue; + // We don't start the fd sweep at 0, else some fds would be advantaged. + // Note that we do an fd sweep, not a map sweep. This is + // inefficient because the fd array may be very sparse. Otoh, the + // map may change between 2 sweeps, so that we'd have to be smart + // with the iterator. As the cost per unused fd is low (just 2 bit + // flag tests), we keep it like this for now + if (m_placetostart >= nfds) { + m_placetostart = 0; + } + int i, fd; + for (i = 0, fd = m_placetostart; i < nfds; i++, fd++) { + if (fd >= nfds) { + fd = 0; + } - map::iterator it = m_polldata.find(fd); - if (it == m_polldata.end()) { - /// This should not happen actually - LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd)); - continue; - } + int canread = FD_ISSET(fd, &rd); + int canwrite = FD_ISSET(fd, &wd); + bool none = !canread && !canwrite; + LOGDEB2(("Netcon::selectloop: fd %d %s %s %s\n", fd, + none ? "blocked" : "can" , canread ? "read" : "", + canwrite ? "write" : "")); + if (none) { + continue; + } - // Next start will be one beyond last serviced (modulo nfds) - m_placetostart = fd + 1; - NetconP &pll = it->second; - if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) - pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ; - if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) - pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE; - if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) { - LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n", - it->first, it->second->m_wantedEvents)); - m_polldata.erase(it); - } - } // fd sweep + map::iterator it = m_polldata.find(fd); + if (it == m_polldata.end()) { + /// This should not happen actually + LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd)); + continue; + } + + // Next start will be one beyond last serviced (modulo nfds) + m_placetostart = fd + 1; + NetconP &pll = it->second; + if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) { + pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ; + } + if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) { + pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE; + } + if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) { + LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n", + it->first, it->second->m_wantedEvents)); + m_polldata.erase(it); + } + } // fd sweep } // forever loop LOGERR(("SelectLoop::doLoop: got out of loop !\n")); @@ -252,7 +301,9 @@ int SelectLoop::doLoop() // Add a connection to the monitored set. int SelectLoop::addselcon(NetconP con, int events) { - if (con.isNull()) return -1; + if (!con) { + return -1; + } LOGDEB1(("Netcon::addselcon: fd %d\n", con->m_fd)); con->set_nonblock(1); con->setselevents(events); @@ -264,12 +315,14 @@ int SelectLoop::addselcon(NetconP con, int events) // Remove a connection from the monitored set. int SelectLoop::remselcon(NetconP con) { - if (con.isNull()) return -1; + if (!con) { + return -1; + } LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd)); map::iterator it = m_polldata.find(con->m_fd); if (it == m_polldata.end()) { - LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd)); - return -1; + LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd)); + return -1; } con->setloop(0); m_polldata.erase(it); @@ -278,18 +331,19 @@ int SelectLoop::remselcon(NetconP con) ////////////////////////////////////////////////////////// // Base class (Netcon) methods -Netcon::~Netcon() { +Netcon::~Netcon() +{ closeconn(); if (m_peer) { - free(m_peer); - m_peer = 0; + free(m_peer); + m_peer = 0; } } -void Netcon::closeconn() +void Netcon::closeconn() { if (m_ownfd && m_fd >= 0) { - close(m_fd); + close(m_fd); } m_fd = -1; m_ownfd = true; @@ -302,8 +356,9 @@ char *Netcon::sterror() void Netcon::setpeer(const char *hostname) { - if (m_peer) - free(m_peer); + if (m_peer) { + free(m_peer); + } m_peer = strdup(hostname); } @@ -311,13 +366,13 @@ int Netcon::settcpnodelay(int on) { LOGDEB2(( "Netcon::settcpnodelay\n" )); if (m_fd < 0) { - LOGERR(("Netcon::settcpnodelay: connection not opened\n")); - return -1; + LOGERR(("Netcon::settcpnodelay: connection not opened\n")); + return -1; } char *cp = on ? (char *)&one : (char *)&zero; if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, cp, sizeof(one)) < 0) { - LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY"); - return -1; + LOGSYSERR("NetconCli::settcpnodelay", "setsockopt", "TCP_NODELAY"); + return -1; } return 0; } @@ -327,10 +382,11 @@ int Netcon::set_nonblock(int onoff) { int flags = fcntl(m_fd, F_GETFL, 0); if (flags != -1 ) { - int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK; - if (newflags != flags) - if (fcntl(m_fd, F_SETFL, newflags)< 0) - return -1; + int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK; + if (newflags != flags) + if (fcntl(m_fd, F_SETFL, newflags) < 0) { + return -1; + } } return flags; } @@ -338,7 +394,8 @@ int Netcon::set_nonblock(int onoff) ///////////////////////////////////////////////////////////////////// // Data socket (NetconData) methods -NetconData::~NetconData() { +NetconData::~NetconData() +{ freeZ(m_buf); m_bufbase = 0; m_bufbytes = m_bufsize = 0; @@ -349,25 +406,27 @@ int NetconData::send(const char *buf, int cnt, int expedited) LOGDEB2(("NetconData::send: fd %d cnt %d expe %d\n", m_fd, cnt, expedited)); int flag = 0; if (m_fd < 0) { - LOGERR(("NetconData::send: connection not opened\n")); - return -1; + LOGERR(("NetconData::send: connection not opened\n")); + return -1; } if (expedited) { - LOGDEB2(("NetconData::send: expedited data, count %d bytes\n", cnt)); - flag = MSG_OOB; + LOGDEB2(("NetconData::send: expedited data, count %d bytes\n", cnt)); + flag = MSG_OOB; } int ret; // There is a bug in the uthread version of sendto() in FreeBSD at // least up to 2.2.7, so avoid using it when possible - if (flag) - ret = ::send(m_fd, buf, cnt, flag); - else - ret = ::write(m_fd, buf, cnt); + if (flag) { + ret = ::send(m_fd, buf, cnt, flag); + } else { + ret = ::write(m_fd, buf, cnt); + } // Note: byte count may be different from cnt if fd is non-blocking if (ret < 0) { - char fdcbuf[20];sprintf(fdcbuf, "%d", m_fd); - LOGSYSERR("NetconData::send", "send", fdcbuf); + char fdcbuf[20]; + sprintf(fdcbuf, "%d", m_fd); + LOGSYSERR("NetconData::send", "send", fdcbuf); } return ret; } @@ -377,8 +436,8 @@ int NetconData::readready() { LOGDEB2(("NetconData::readready\n")); if (m_fd < 0) { - LOGERR(("NetconData::readready: connection not opened\n")); - return -1; + LOGERR(("NetconData::readready: connection not opened\n")); + return -1; } return select1(m_fd, 0); } @@ -388,8 +447,8 @@ int NetconData::writeready() { LOGDEB2(("NetconData::writeready\n")); if (m_fd < 0) { - LOGERR(("NetconData::writeready: connection not opened\n")); - return -1; + LOGERR(("NetconData::writeready: connection not opened\n")); + return -1; } return select1(m_fd, 0, 1); } @@ -398,41 +457,43 @@ int NetconData::writeready() int NetconData::receive(char *buf, int cnt, int timeo) { LOGDEB2(("NetconData::receive: cnt %d timeo %d m_buf 0x%x m_bufbytes %d\n", - cnt, timeo, m_buf, m_bufbytes)); + cnt, timeo, m_buf, m_bufbytes)); if (m_fd < 0) { - LOGERR(("NetconData::receive: connection not opened\n")); - return -1; + LOGERR(("NetconData::receive: connection not opened\n")); + return -1; } int fromibuf = 0; - // Get whatever might have been left in the buffer by a previous + // Get whatever might have been left in the buffer by a previous // getline, except if we're called to fill the buffer of course if (m_buf && m_bufbytes > 0 && (buf < m_buf || buf > m_buf + m_bufsize)) { - fromibuf = MIN(m_bufbytes, cnt); - memcpy(buf, m_bufbase, fromibuf); - m_bufbytes -= fromibuf; - m_bufbase += fromibuf; - cnt -= fromibuf; + fromibuf = MIN(m_bufbytes, cnt); + memcpy(buf, m_bufbase, fromibuf); + m_bufbytes -= fromibuf; + m_bufbase += fromibuf; + cnt -= fromibuf; LOGDEB2(("NetconData::receive: transferred %d from mbuf\n", fromibuf)); - if (cnt <= 0) - return fromibuf; + if (cnt <= 0) { + return fromibuf; + } } if (timeo > 0) { - int ret = select1(m_fd, timeo); - if (ret == 0) { - LOGDEB2(("NetconData::receive timed out\n")); - m_didtimo = 1; - return -1; - } - if (ret < 0) { - LOGSYSERR("NetconData::receive", "select", ""); - return -1; - } + int ret = select1(m_fd, timeo); + if (ret == 0) { + LOGDEB2(("NetconData::receive timed out\n")); + m_didtimo = 1; + return -1; + } + if (ret < 0) { + LOGSYSERR("NetconData::receive", "select", ""); + return -1; + } } m_didtimo = 0; if ((cnt = read(m_fd, buf + fromibuf, cnt)) < 0) { - char fdcbuf[20];sprintf(fdcbuf, "%d", m_fd); - LOGSYSERR("NetconData::receive", "read", fdcbuf); - return -1; + char fdcbuf[20]; + sprintf(fdcbuf, "%d", m_fd); + LOGSYSERR("NetconData::receive", "read", fdcbuf); + return -1; } LOGDEB2(("NetconData::receive: normal return, cnt %d\n", cnt)); return fromibuf + cnt; @@ -445,16 +506,16 @@ int NetconData::doreceive(char *buf, int cnt, int timeo) LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo)); cur = 0; while (cnt > cur) { - got = receive(buf, cnt-cur, timeo); - LOGDEB2(("Netcon::doreceive: got %d\n", got)); - if (got < 0) { - return -1; - } - if (got == 0) { - return cur; - } - cur += got; - buf += got; + got = receive(buf, cnt-cur, timeo); + LOGDEB2(("Netcon::doreceive: got %d\n", got)); + if (got < 0) { + return -1; + } + if (got == 0) { + return cur; + } + cur += got; + buf += got; } return cur; } @@ -472,57 +533,58 @@ int NetconData::getline(char *buf, int cnt, int timeo) { LOGDEB2(("NetconData::getline: cnt %d, timeo %d\n", cnt, timeo)); if (m_buf == 0) { - if ((m_buf = (char *)malloc(defbufsize)) == 0) { - LOGSYSERR("NetconData::getline: Out of mem", "malloc", ""); - return -1; - } - m_bufsize = defbufsize; - m_bufbase = m_buf; - m_bufbytes = 0; + if ((m_buf = (char *)malloc(defbufsize)) == 0) { + LOGSYSERR("NetconData::getline: Out of mem", "malloc", ""); + return -1; + } + m_bufsize = defbufsize; + m_bufbase = m_buf; + m_bufbytes = 0; } char *cp = buf; for (;;) { - // Transfer from buffer. Have to take a lot of care to keep counts and - // pointers consistant in all end cases - int maxtransf = MIN(m_bufbytes, cnt-1); - int nn = maxtransf; - LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n", - m_bufbytes, maxtransf, nn)); - for (nn = maxtransf; nn > 0;) { - // This is not pretty but we want nn to be decremented for - // each byte copied (even newline), and not become -1 if - // we go to the end. Better ways welcome! - nn--; - if ((*cp++ = *m_bufbase++) == '\n') - break; - } - // Update counts - maxtransf -= nn; // Actual count transferred - m_bufbytes -= maxtransf; - cnt -= maxtransf; - LOGDEB2(("After transfer: actual transf %d cnt %d, m_bufbytes %d\n", - maxtransf, cnt, m_bufbytes)); + // Transfer from buffer. Have to take a lot of care to keep counts and + // pointers consistant in all end cases + int maxtransf = MIN(m_bufbytes, cnt-1); + int nn = maxtransf; + LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n", + m_bufbytes, maxtransf, nn)); + for (nn = maxtransf; nn > 0;) { + // This is not pretty but we want nn to be decremented for + // each byte copied (even newline), and not become -1 if + // we go to the end. Better ways welcome! + nn--; + if ((*cp++ = *m_bufbase++) == '\n') { + break; + } + } + // Update counts + maxtransf -= nn; // Actual count transferred + m_bufbytes -= maxtransf; + cnt -= maxtransf; + LOGDEB2(("After transfer: actual transf %d cnt %d, m_bufbytes %d\n", + maxtransf, cnt, m_bufbytes)); - // Finished ? - if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) { - *cp = 0; - return cp - buf; - } + // Finished ? + if (cnt <= 1 || (cp > buf && cp[-1] == '\n')) { + *cp = 0; + return cp - buf; + } - // Transfer from net - m_bufbase = m_buf; - m_bufbytes = receive(m_buf, m_bufsize, timeo); - if (m_bufbytes == 0) { - // EOF - *cp = 0; - return cp - buf; - } - if (m_bufbytes < 0) { - m_bufbytes = 0; - *cp = 0; - return -1; - } + // Transfer from net + m_bufbase = m_buf; + m_bufbytes = receive(m_buf, m_bufsize, timeo); + if (m_bufbytes == 0) { + // EOF + *cp = 0; + return cp - buf; + } + if (m_bufbytes < 0) { + m_bufbytes = 0; + *cp = 0; + return -1; + } } } @@ -533,23 +595,23 @@ int NetconData::getline(char *buf, int cnt, int timeo) int NetconData::cando(Netcon::Event reason) { LOGDEB2(("NetconData::cando\n")); - if (!m_user.isNull()) { - return m_user->data(this, reason); + if (m_user) { + return m_user->data(this, reason); } // No user callback. Clean up by ourselves if (reason & NETCONPOLL_READ) { #define BS 200 - char buf[BS]; - int n; - if ((n = receive(buf, BS)) < 0) { - LOGSYSERR("NetconData::cando", "receive", ""); - return -1; - } - if (n == 0) { - // EOF - return 0; - } + char buf[BS]; + int n; + if ((n = receive(buf, BS)) < 0) { + LOGSYSERR("NetconData::cando", "receive", ""); + return -1; + } + if (n == 0) { + // EOF + return 0; + } } clearselevents(NETCONPOLL_WRITE); return 1; @@ -564,73 +626,106 @@ int NetconCli::openconn(const char *host, unsigned int port, int timeo) closeconn(); - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = htons(port); + struct sockaddr *saddr; + socklen_t addrsize; - // Server name may be host name or IP address - int addr; - if ((addr = inet_addr(host)) != -1) { - memcpy(&saddr.sin_addr, &addr, sizeof(addr)); + struct sockaddr_in ip_addr; + struct sockaddr_un unix_addr; + if (host[0] != '/') { + memset(&ip_addr, 0, sizeof(ip_addr)); + ip_addr.sin_family = AF_INET; + ip_addr.sin_port = htons(port); + + // Server name may be host name or IP address + int addr; + if ((addr = inet_addr(host)) != -1) { + memcpy(&ip_addr.sin_addr, &addr, sizeof(addr)); + } else { + struct hostent *hp; + if ((hp = gethostbyname(host)) == 0) { + LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n", + host)); + return -1; + } + memcpy(&ip_addr.sin_addr, hp->h_addr, hp->h_length); + } + + if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + LOGSYSERR("NetconCli::openconn", "socket", ""); + return -1; + } + addrsize = sizeof(ip_addr); + saddr = (sockaddr*)&ip_addr; } else { - struct hostent *hp; - if ((hp = gethostbyname(host)) == 0) { - LOGERR(("NetconCli::openconn: gethostbyname(%s) failed\n", host)); - return -1; - } - memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + if (strlen(host) > UNIX_PATH_MAX - 1) { + LOGERR(("NetconCli::openconn: name too long: %s\n", host)); + return -1; + } + strcpy(unix_addr.sun_path, host); + + if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LOGSYSERR("NetconCli::openconn", "socket", ""); + return -1; + } + addrsize = sizeof(unix_addr); + saddr = (sockaddr*)&unix_addr; + } + if (timeo > 0) { + set_nonblock(1); } - if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOGSYSERR("NetconCli::openconn", "socket", ""); - return -1; + if (connect(m_fd, saddr, addrsize) < 0) { + if (timeo > 0) { + if (errno != EINPROGRESS) { + goto out; + } + if (select1(m_fd, timeo, 1) == 1) { + goto connectok; + } + } + if (m_silentconnectfailure == 0) { + LOGSYSERR("NetconCli", "connect", ""); + } + goto out; } - if (timeo > 0) - set_nonblock(1); - - if(connect(m_fd,(struct sockaddr *) &saddr, sizeof(saddr)) < 0) { - if (timeo > 0) { - if (errno != EINPROGRESS) - goto out; - if (select1(m_fd, timeo, 1) == 1) - goto connectok; - } - if (m_silentconnectfailure == 0) { - LOGSYSERR("NetconCli", "connect", ""); - } - goto out; +connectok: + if (timeo > 0) { + set_nonblock(0); } - connectok: - if (timeo > 0) - set_nonblock(0); LOGDEB2(("NetconCli::connect: setting keepalive\n")); - if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, - (char *)&one, sizeof(one)) < 0) { - LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE"); + if (setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, + (char *)&one, sizeof(one)) < 0) { + LOGSYSERR("NetconCli::connect", "setsockopt", "KEEPALIVE"); } setpeer(host); LOGDEB2(("NetconCli::openconn: connection opened ok\n")); ret = 0; - out: - if (ret < 0) - closeconn(); +out: + if (ret < 0) { + closeconn(); + } return ret; } // Same as previous, but get the port number from services -int NetconCli::openconn(const char *host, char *serv, int timeo) +int NetconCli::openconn(const char *host, const char *serv, int timeo) { LOGDEB2(("Netconcli::openconn: host %s, serv %s\n", host, serv)); - struct servent *sp; - if ((sp = getservbyname(serv, "tcp")) == 0) { - LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv)); - return -1; + if (host[0] != '/') { + struct servent *sp; + if ((sp = getservbyname(serv, "tcp")) == 0) { + LOGERR(("NetconCli::openconn: getservbyname failed for %s\n",serv)); + return -1; + } + // Callee expects the port number in host byte order + return openconn(host, ntohs(sp->s_port), timeo); + } else { + return openconn(host, (unsigned int)0, timeo); } - // Callee expects the port number in host byte order - return openconn(host, ntohs(sp->s_port), timeo); } @@ -647,42 +742,88 @@ int NetconCli::setconn(int fd) } /////////////////////////////////////////////////////////////////////// -// Methods for the main (listening) server connection +// Methods for the main (listening) server connection -NetconServLis::~NetconServLis() { +NetconServLis::~NetconServLis() +{ #ifdef NETCON_ACCESSCONTROL freeZ(okaddrs.intarray); freeZ(okmasks.intarray); -#endif +#endif } #if 0 // code for dumping a struct servent -static void dump_servent(struct servent *servp) { +static void dump_servent(struct servent *servp) +{ fprintf(stderr, "Official name %s\n", servp->s_name); - for (char **cpp = servp->s_aliases;*cpp;cpp++) - fprintf(stderr, "Nickname %s\n", *cpp); + for (char **cpp = servp->s_aliases; *cpp; cpp++) { + fprintf(stderr, "Nickname %s\n", *cpp); + } fprintf(stderr, "Port %d\n", (int)ntohs((short)servp->s_port)); fprintf(stderr, "Proto %s\n", servp->s_proto); } #endif // Set up service. -int NetconServLis::openservice(char *serv, int backlog) +int NetconServLis::openservice(const char *serv, int backlog) { - int port; - struct servent *servp; + int port; + struct servent *servp; + if (!serv) { + LOGERR(("NetconServLis::openservice: null serv??\n")); + return -1; + } LOGDEB1(("NetconServLis::openservice: serv %s\n", serv)); #ifdef NETCON_ACCESSCONTROL - if (initperms(serv) < 0) - return -1; -#endif - if ((servp = getservbyname(serv, "tcp")) == 0) { - LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n",serv)); - return -1; + if (initperms(serv) < 0) { + return -1; + } +#endif + + m_serv = serv; + if (serv[0] != '/') { + if ((servp = getservbyname(serv, "tcp")) == 0) { + LOGERR(("NetconServLis::openservice: getservbyname failed for %s\n", + serv)); + return -1; + } + port = (int)ntohs((short)servp->s_port); + return openservice(port, backlog); + } else { + if (strlen(serv) > UNIX_PATH_MAX - 1) { + LOGERR(("NetconServLis::openservice: too long for AF_UNIX: %s\n", + serv)); + return -1; + } + int ret = -1; + struct sockaddr_un addr; + if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LOGSYSERR("NetconServLis", "socket", ""); + return -1; + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, serv); + + if (::bind(m_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + LOGSYSERR("NetconServLis", "bind", ""); + goto out; + } + if (listen(m_fd, backlog) < 0) { + LOGSYSERR("NetconServLis", "listen", ""); + goto out; + } + + LOGDEB1(("NetconServLis::openservice: service opened ok\n")); + ret = 0; + out: + if (ret < 0 && m_fd >= 0) { + close(m_fd); + m_fd = -1; + } + return ret; } - port = (int)ntohs((short)servp->s_port); - return openservice(port, backlog); } // Port is a natural host integer value @@ -690,14 +831,15 @@ int NetconServLis::openservice(int port, int backlog) { LOGDEB1(("NetconServLis::openservice: port %d\n", port)); #ifdef NETCON_ACCESSCONTROL - if (initperms(port) < 0) - return -1; + if (initperms(port) < 0) { + return -1; + } #endif int ret = -1; struct sockaddr_in ipaddr; if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOGSYSERR("NetconServLis", "socket", ""); - return -1; + LOGSYSERR("NetconServLis", "socket", ""); + return -1; } (void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one)); #ifdef SO_REUSEPORT @@ -707,21 +849,21 @@ int NetconServLis::openservice(int port, int backlog) ipaddr.sin_family = AF_INET; ipaddr.sin_addr.s_addr = htonl(INADDR_ANY); ipaddr.sin_port = htons((short)port); - if (bind(m_fd, (struct sockaddr *)&ipaddr, sizeof(ipaddr)) < 0){ - LOGSYSERR("NetconServLis", "bind", ""); - goto out; + if (::bind(m_fd, (struct sockaddr *)&ipaddr, sizeof(ipaddr)) < 0) { + LOGSYSERR("NetconServLis", "bind", ""); + goto out; } if (listen(m_fd, backlog) < 0) { - LOGSYSERR("NetconServLis", "listen", ""); - goto out; + LOGSYSERR("NetconServLis", "listen", ""); + goto out; } LOGDEB1(("NetconServLis::openservice: service opened ok\n")); ret = 0; - out: +out: if (ret < 0 && m_fd >= 0) { - close(m_fd); - m_fd = -1; + close(m_fd); + m_fd = -1; } return ret; } @@ -729,8 +871,9 @@ int NetconServLis::openservice(int port, int backlog) #ifdef NETCON_ACCESSCONTROL int NetconServLis::initperms(int port) { - if (permsinit) - return 0; + if (permsinit) { + return 0; + } char sport[30]; sprintf(sport, "%d", port); @@ -738,34 +881,35 @@ int NetconServLis::initperms(int port) } // Get authorized address lists from parameter file. This is disabled for now -int NetconServLis::initperms(char *serv) +int NetconServLis::initperms(const char *serv) { - if (permsinit) - return 0; + if (permsinit) { + return 0; + } if (serv == 0 || *serv == 0 || strlen(serv) > 80) { - LOGERR(("NetconServLis::initperms: bad service name %s\n", serv)); - return -1; + LOGERR(("NetconServLis::initperms: bad service name %s\n", serv)); + return -1; } char keyname[100]; sprintf(keyname, "%s_okaddrs", serv); if (genparams->getparam(keyname, &okaddrs, 1) < 0) { - serv = "default"; - sprintf(keyname, "%s_okaddrs", serv); - if (genparams->getparam(keyname, &okaddrs) < 0) { - LOGERR(("NetconServLis::initperms: no okaddrs found in config file\n")); - return -1; - } + serv = "default"; + sprintf(keyname, "%s_okaddrs", serv); + if (genparams->getparam(keyname, &okaddrs) < 0) { + LOGERR(("NetconServLis::initperms: no okaddrs found in config file\n")); + return -1; + } } sprintf(keyname, "%s_okmasks", serv); if (genparams->getparam(keyname, &okmasks)) { - LOGERR(("NetconServLis::initperms: okmasks not found\n")); - return -1; + LOGERR(("NetconServLis::initperms: okmasks not found\n")); + return -1; } if (okaddrs.len == 0 || okmasks.len == 0) { - LOGERR(("NetconServLis::initperms: len 0 for okmasks or okaddrs\n")); - return -1; + LOGERR(("NetconServLis::initperms: len 0 for okmasks or okaddrs\n")); + return -1; } permsinit = 1; @@ -789,91 +933,111 @@ NetconServLis::accept(int timeo) LOGDEB(("NetconServLis::accept\n")); if (timeo > 0) { - int ret = select1(m_fd, timeo); - if (ret == 0) { - LOGDEB2(("NetconServLis::accept timed out\n")); - m_didtimo = 1; - return 0; - } - if (ret < 0) { - LOGSYSERR("NetconServLis::accept", "select", ""); - return 0; - } + int ret = select1(m_fd, timeo); + if (ret == 0) { + LOGDEB2(("NetconServLis::accept timed out\n")); + m_didtimo = 1; + return 0; + } + if (ret < 0) { + LOGSYSERR("NetconServLis::accept", "select", ""); + return 0; + } } m_didtimo = 0; NetconServCon *con = 0; int newfd = -1; struct sockaddr_in who; - SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who); - if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) { - LOGSYSERR("NetconServCon::accept", "accept", ""); - goto out; - } + struct sockaddr_un uwho; + if (m_serv.empty() || m_serv[0] != '/') { + SOCKLEN_T clilen = (SOCKLEN_T)sizeof(who); + if ((newfd = ::accept(m_fd, (struct sockaddr *)&who, &clilen)) < 0) { + LOGSYSERR("NetconServCon::accept", "accept", ""); + goto out; + } #ifdef NETCON_ACCESSCONTROL - if (checkperms(&who, clilen) < 0) { - goto out; - } + if (checkperms(&who, clilen) < 0) { + goto out; + } #endif + } else { + SOCKLEN_T clilen = (SOCKLEN_T)sizeof(uwho); + if ((newfd = ::accept(m_fd, (struct sockaddr *)&uwho, &clilen)) < 0) { + LOGSYSERR("NetconServCon::accept", "accept", ""); + goto out; + } + } + con = new NetconServCon(newfd); if (con == 0) { - LOGERR(("NetconServLis::accept: new NetconServCon failed\n")); - goto out; - } - // Retrieve peer's host name. Errors are non fatal - struct hostent *hp; - if ((hp = gethostbyaddr((char *)&(who.sin_addr), sizeof(struct in_addr), - AF_INET)) == 0) { - LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n", - who.sin_addr.s_addr)); - con->setpeer(inet_ntoa(who.sin_addr)); - } else { - con->setpeer(hp->h_name); + LOGERR(("NetconServLis::accept: new NetconServCon failed\n")); + goto out; } + + // Retrieve peer's host name. Errors are non fatal + if (m_serv.empty() || m_serv[0] != '/') { + struct hostent *hp; + if ((hp = gethostbyaddr((char *) & (who.sin_addr), + sizeof(struct in_addr), AF_INET)) == 0) { + LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n", + who.sin_addr.s_addr)); + con->setpeer(inet_ntoa(who.sin_addr)); + } else { + con->setpeer(hp->h_name); + } + } else { + con->setpeer(m_serv.c_str()); + } + LOGDEB2(("NetconServLis::accept: setting keepalive\n")); - if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE, - (char *)&one, sizeof(one)) < 0) { - LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE"); + if (setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE, + (char *)&one, sizeof(one)) < 0) { + LOGSYSERR("NetconServLis::accept", "setsockopt", "KEEPALIVE"); } LOGDEB2(("NetconServLis::accept: got connect from %s\n", con->getpeer())); - out: - if (con == 0 && newfd >= 0) - close(newfd); +out: + if (con == 0 && newfd >= 0) { + close(newfd); + } return con; } #ifdef NETCON_ACCESSCONTROL -int +int NetconServLis::checkperms(void *cl, int) { // If okmasks and addrs were not initialized, the default is allow to all - if (okmasks.len <= 0 || okaddrs.len <= 0) - return 0; + if (okmasks.len <= 0 || okaddrs.len <= 0) { + return 0; + } struct sockaddr *addr = (struct sockaddr *)cl; unsigned long ip_addr; if (addr->sa_family != AF_INET) { - LOGERR(("NetconServLis::checkperms: connection from non-INET addr !\n")); - return -1; + LOGERR(("NetconServLis::checkperms: connection from non-INET addr !\n")); + return -1; } ip_addr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); LOGDEB2(("checkperms: ip_addr: 0x%x\n", ip_addr)); for (int i = 0; i < okaddrs.len; i++) { - unsigned int mask; - if (i < okmasks.len) - mask = okmasks.intarray[i]; - else - mask = okmasks.intarray[okmasks.len-1]; - LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n", - okaddrs.intarray[i], mask)); - if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) - return (0); + unsigned int mask; + if (i < okmasks.len) { + mask = okmasks.intarray[i]; + } else { + mask = okmasks.intarray[okmasks.len-1]; + } + LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n", + okaddrs.intarray[i], mask)); + if ((ip_addr & mask) == (okaddrs.intarray[i] & mask)) { + return (0); + } } - LOGERR(("NetconServLis::checkperm: connection from bad address 0x%x\n", - ip_addr)); + LOGERR(("NetconServLis::checkperm: connection from bad address 0x%x\n", + ip_addr)); return -1; } #endif /* NETCON_ACCESSCONTROL */ @@ -893,6 +1057,8 @@ NetconServLis::checkperms(void *cl, int) #include "debuglog.h" #include "netcon.h" +using namespace std; + static char *thisprog; static char usage[] = "-c : Connects to trnetcon server, exchange message, then\n" @@ -900,7 +1066,7 @@ static char usage[] = "\n" "-s : open service \n" ; -static void +static void Usage() { fprintf(stderr, "Usage : %s:\n %s", thisprog, usage); @@ -923,49 +1089,55 @@ int main(int argc, char **argv) char *host, *serv; thisprog = argv[0]; - argc--; argv++; + argc--; + argv++; while (argc > 0 && **argv == '-') { - (*argv)++; - if (!(**argv)) - /* Cas du "adb - core" */ - Usage(); - while (**argv) - switch (*(*argv)++) { - case 's': - op_flags |= OPT_s; - break; - case 'c': - op_flags |= OPT_c; - break; - case 'n': - op_flags |= OPT_n; - break; - default: - Usage(); - break; - } - argc--; - argv++; + (*argv)++; + if (!(**argv)) + /* Cas du "adb - core" */ + { + Usage(); + } + while (**argv) + switch (*(*argv)++) { + case 's': + op_flags |= OPT_s; + break; + case 'c': + op_flags |= OPT_c; + break; + case 'n': + op_flags |= OPT_n; + break; + default: + Usage(); + break; + } + argc--; + argv++; } DebugLog::setfilename("stderr"); DebugLog::getdbl()->setloglevel(DEBDEB2); if (op_flags & OPT_c) { - if (argc != 2) { - Usage(); - } - host = *argv++;argc--; - serv = *argv++;argc--; - exit(trycli(host, serv)); + if (argc != 2) { + Usage(); + } + host = *argv++; + argc--; + serv = *argv++; + argc--; + exit(trycli(host, serv)); } else if (op_flags & OPT_s) { - if (argc != 1) { - Usage(); - } - serv = *argv++;argc--; - exit(tryserv(serv)); + if (argc != 1) { + Usage(); + } + serv = *argv++; + argc--; + exit(tryserv(serv)); } else { - Usage(); + Usage(); } } @@ -977,47 +1149,47 @@ static char fromcli[200]; class CliNetconWorker : public NetconWorker { public: CliNetconWorker() : m_count(0) {} - int data(NetconData *con, Netcon::Event reason) - { - LOGDEB(("clientdata\n")); - if (reason & Netcon::NETCONPOLL_WRITE) { - sprintf(fromcli, "Bonjour Bonjour client %d, count %d", - getpid(), m_count); - con->setselevents(Netcon::NETCONPOLL_READ); - if (con->send(fromcli, strlen(fromcli) + 1) < 0) { - fprintf(stderr, "send failed\n"); - return -1; - } - m_count++; - } + int data(NetconData *con, Netcon::Event reason) { + LOGDEB(("clientdata\n")); + if (reason & Netcon::NETCONPOLL_WRITE) { + sprintf(fromcli, "Bonjour Bonjour client %d, count %d", + getpid(), m_count); + con->setselevents(Netcon::NETCONPOLL_READ); + if (con->send(fromcli, strlen(fromcli) + 1) < 0) { + fprintf(stderr, "send failed\n"); + return -1; + } + m_count++; + } - if (reason & Netcon::NETCONPOLL_READ) { - con->setselevents(Netcon::NETCONPOLL_WRITE); - int n; - if ((n = con->receive(buf, buflen)) < 0) { - fprintf(stderr, "receive failed\n"); - return -1; - } - if (n == 0) { - // EOF, close connection - return -1; - } - buf[n] = 0; - fprintf(stderr, "%d received \"%s\"\n", getpid(), buf); - if (op_flags & OPT_n) { - pause(); - } else { - sleep(1); - } - } - if (m_count >= 10) { - fprintf(stderr, "Did 10, enough\n"); - if (con->getloop()) - con->getloop()->loopReturn(0); - } - return 0; + if (reason & Netcon::NETCONPOLL_READ) { + con->setselevents(Netcon::NETCONPOLL_WRITE); + int n; + if ((n = con->receive(buf, buflen)) < 0) { + fprintf(stderr, "receive failed\n"); + return -1; + } + if (n == 0) { + // EOF, close connection + return -1; + } + buf[n] = 0; + fprintf(stderr, "%d received \"%s\"\n", getpid(), buf); + if (op_flags & OPT_n) { + pause(); + } else { + sleep(1); + } + } + if (m_count >= 10) { + fprintf(stderr, "Did 10, enough\n"); + if (con->getloop()) { + con->getloop()->loopReturn(0); + } + } + return 0; } -private: +private: int m_count; }; @@ -1027,44 +1199,47 @@ int trycli(char *host, char *serv) NetconCli *clicon = new NetconCli(); NetconP con(clicon); - if (con.isNull()) { - fprintf(stderr, "new NetconCli failed\n"); - return 1; + if (!con) { + fprintf(stderr, "new NetconCli failed\n"); + return 1; } - if (clicon->openconn(host, serv) < 0) { - fprintf(stderr, "openconn(%s, %s) failed\n", host, serv); - return 1; + int port = atoi(serv); + int ret = port > 0 ? + clicon->openconn(host, port) : clicon->openconn(host, serv); + if (ret < 0) { + fprintf(stderr, "openconn(%s, %s) failed\n", host, serv); + return 1; } fprintf(stderr, "openconn(%s, %s) ok\n", host, serv); #ifdef NOSELLOOP - for (int i = 0;i < nloop;i++) { - if (con->send(fromcli, strlen(fromcli) + 1) < 0) { - fprintf(stderr, "%d: Send failed\n", getpid()); - return 1; - } - if (con->receive(buf, buflen) < 0) { - perror("receive:"); - fprintf(stderr, "%d: Receive failed\n", getpid()); - return 1; - } - fprintf(stderr, "%d Received \"%s\"\n", getpid(), buf); - if (op_flags & OPT_n) { - pause(); - } else { - sleep(1); - } + for (int i = 0; i < nloop; i++) { + if (con->send(fromcli, strlen(fromcli) + 1) < 0) { + fprintf(stderr, "%d: Send failed\n", getpid()); + return 1; + } + if (con->receive(buf, buflen) < 0) { + perror("receive:"); + fprintf(stderr, "%d: Receive failed\n", getpid()); + return 1; + } + fprintf(stderr, "%d Received \"%s\"\n", getpid(), buf); + if (op_flags & OPT_n) { + pause(); + } else { + sleep(1); + } } #else - RefCntr worker = - RefCntr(new CliNetconWorker()); + RefCntr worker = + RefCntr(new CliNetconWorker()); clicon->setcallback(worker); SelectLoop myloop; myloop.addselcon(con, Netcon::NETCONPOLL_WRITE); fprintf(stderr, "client ready\n"); - int ret = myloop.doLoop(); + ret = myloop.doLoop(); if (ret < 0) { - fprintf(stderr, "selectloop failed\n"); - exit(1); + fprintf(stderr, "selectloop failed\n"); + exit(1); } fprintf(stderr, "selectloop returned %d\n", ret); #endif @@ -1076,36 +1251,35 @@ int trycli(char *host, char *serv) class ServNetconWorker : public NetconWorker { public: ServNetconWorker() : m_count(0) {} - int data(NetconData *con, Netcon::Event reason) - { - LOGDEB(("serverdata\n")); - if (reason & Netcon::NETCONPOLL_WRITE) { - con->setselevents(Netcon::NETCONPOLL_READ); - char fromserv[200]; - sprintf(fromserv, - "Du serveur: mon fd pour ce client est %d, mon compte %d", - con->getfd(), ++m_count); - if (con->send(fromserv, strlen(fromserv) + 1) < 0) { - fprintf(stderr, "send failed\n"); - return -1; - } - } - if (reason & Netcon::NETCONPOLL_READ) { + int data(NetconData *con, Netcon::Event reason) { + LOGDEB(("serverdata\n")); + if (reason & Netcon::NETCONPOLL_WRITE) { + con->setselevents(Netcon::NETCONPOLL_READ); + char fromserv[200]; + sprintf(fromserv, + "Du serveur: mon fd pour ce client est %d, mon compte %d", + con->getfd(), ++m_count); + if (con->send(fromserv, strlen(fromserv) + 1) < 0) { + fprintf(stderr, "send failed\n"); + return -1; + } + } + if (reason & Netcon::NETCONPOLL_READ) { #define LL 200 - char buf[LL+1]; - int n; - if ((n = con->receive(buf, LL)) < 0) { - fprintf(stderr, "receive failed\n"); - return -1; - } - if (n == 0) { - return -1; - } - buf[n] = 0; - fprintf(stderr, "%d received \"%s\"\n", getpid(), buf); - con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE); - } - return 0; + char buf[LL+1]; + int n; + if ((n = con->receive(buf, LL)) < 0) { + fprintf(stderr, "receive failed\n"); + return -1; + } + if (n == 0) { + return -1; + } + buf[n] = 0; + fprintf(stderr, "%d received \"%s\"\n", getpid(), buf); + con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE); + } + return 0; } private: int m_count; @@ -1114,19 +1288,19 @@ private: class MyNetconServLis : public NetconServLis { public: MyNetconServLis(SelectLoop &loop) - : NetconServLis(), m_loop(loop) - { + : NetconServLis(), m_loop(loop) { } protected: int cando(Netcon::Event reason) { - NetconServCon *con = accept(); - if (con == 0) - return -1; - RefCntr worker = - RefCntr(new ServNetconWorker()); - con->setcallback(worker); - m_loop.addselcon(NetconP(con), NETCONPOLL_READ); - return 1; + NetconServCon *con = accept(); + if (con == 0) { + return -1; + } + RefCntr worker = + RefCntr(new ServNetconWorker()); + con->setcallback(worker); + m_loop.addselcon(NetconP(con), NETCONPOLL_READ); + return 1; } SelectLoop& m_loop; }; @@ -1137,8 +1311,9 @@ void onexit(int sig) { fprintf(stderr, "Onexit: "); - if (sig == SIGQUIT) - kill(getpid(), SIGKILL); + if (sig == SIGQUIT) { + kill(getpid(), SIGKILL); + } fprintf(stderr, "Exiting\n"); exit(0); } @@ -1149,9 +1324,9 @@ int tryserv(char *serv) SelectLoop myloop; MyNetconServLis *servlis = new MyNetconServLis(myloop); lis = NetconP(servlis); - if (lis.isNull()) { - fprintf(stderr, "new NetconServLis failed\n"); - return 1; + if (!lis) { + fprintf(stderr, "new NetconServLis failed\n"); + return 1; } // Prepare for cleanup @@ -1163,15 +1338,18 @@ int tryserv(char *serv) sigaction(SIGQUIT, &sa, 0); sigaction(SIGTERM, &sa, 0); - if (servlis->openservice(serv) < 0) { - fprintf(stderr, "openservice(%s) failed\n", serv); - return 1; + int port = atoi(serv); + int ret = port > 0 ? + servlis->openservice(port) : servlis->openservice(serv); + if (ret < 0) { + fprintf(stderr, "openservice(%s) failed\n", serv); + return 1; } myloop.addselcon(lis, Netcon::NETCONPOLL_READ); fprintf(stderr, "openservice(%s) Ok\n", serv); if (myloop.doLoop() < 0) { - fprintf(stderr, "selectloop failed\n"); - exit(1); + fprintf(stderr, "selectloop failed\n"); + exit(1); } return 0; } diff --git a/src/utils/netcon.h b/src/utils/netcon.h index cf951d78..073676b8 100644 --- a/src/utils/netcon.h +++ b/src/utils/netcon.h @@ -18,9 +18,9 @@ */ #include #include -#include "refcntr.h" +#include -using std::map; +#include "refcntr.h" /// A set of classes to manage client-server communication over a /// connection-oriented network, or a pipe. @@ -45,8 +45,8 @@ public: enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2}; Netcon() : m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0), - m_loop(0) - {} + m_loop(0) { + } virtual ~Netcon(); /// Remember whom we're talking to. We let external code do this because /// the application may have a non-dns method to find the peer name. @@ -58,11 +58,17 @@ public: /// Set or reset the TCP_NODELAY option. virtual int settcpnodelay(int on = 1); /// Did the last receive() call time out ? Resets the flag. - virtual int timedout() {int s = m_didtimo; m_didtimo = 0; return s;} + virtual int timedout() { + int s = m_didtimo; + m_didtimo = 0; + return s; + } /// Return string version of last syscall error virtual char *sterror(); /// Return the socket descriptor - virtual int getfd() {return m_fd;} + virtual int getfd() { + return m_fd; + } /// Close the current connection if it is open virtual void closeconn(); /// Set/reset the non-blocking flag on the underlying fd. Returns @@ -73,16 +79,26 @@ public: /// Decide what events the connection will be looking for /// (NETCONPOLL_READ, NETCONPOLL_WRITE) - int setselevents(int evs) {return m_wantedEvents = evs;} + int setselevents(int evs) { + return m_wantedEvents = evs; + } /// Retrieve the connection's currently monitored set of events - int getselevents() {return m_wantedEvents;} + int getselevents() { + return m_wantedEvents; + } /// Add events to current set - int addselevents(int evs) {return m_wantedEvents |= evs;} + int addselevents(int evs) { + return m_wantedEvents |= evs; + } /// Clear events from current set - int clearselevents(int evs) {return m_wantedEvents &= ~evs;} + int clearselevents(int evs) { + return m_wantedEvents &= ~evs; + } friend class SelectLoop; - SelectLoop *getloop() {return m_loop;} + SelectLoop *getloop() { + return m_loop; + } /// Utility function for a simplified select() interface: check one fd /// for reading or writing, for a specified maximum number of seconds. @@ -99,7 +115,9 @@ protected: // Method called by the selectloop when something can be done with a netcon virtual int cando(Netcon::Event reason) = 0; // Called when added to loop - virtual void setloop(SelectLoop *loop) {m_loop = loop;} + virtual void setloop(SelectLoop *loop) { + m_loop = loop; + } }; @@ -114,8 +132,8 @@ public: SelectLoop() : m_selectloopDoReturn(false), m_selectloopReturnValue(0), m_placetostart(0), - m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) - {} + m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) { + } /// Loop waiting for events on the connections and call the /// cando() method on the object when something happens (this will in @@ -126,8 +144,7 @@ public: int doLoop(); /// Call from data handler: make selectloop return the param value - void loopReturn(int value) - { + void loopReturn(int value) { m_selectloopDoReturn = true; m_selectloopReturnValue = value; } @@ -156,7 +173,7 @@ private: int m_placetostart; // Map of NetconP indexed by fd - map m_polldata; + std::map m_polldata; // The last time we did the periodic thing. Initialized by setperiodic() struct timeval m_lasthdlcall; @@ -192,8 +209,8 @@ public: /// Base class for connections that actually transfer data. T class NetconData : public Netcon { public: - NetconData() : m_buf(0), m_bufbase(0), m_bufbytes(0), m_bufsize(0) - {} + NetconData() : m_buf(0), m_bufbase(0), m_bufbytes(0), m_bufsize(0) { + } virtual ~NetconData(); /// Write data to the connection. @@ -218,11 +235,14 @@ public: virtual int readready(); /// Check for data being available for writing virtual int writeready(); - /// Read a line of text on an ascii connection + /// Read a line of text on an ascii connection. Returns -1 or byte count + /// including final 0. \n is kept virtual int getline(char *buf, int cnt, int timeo = -1); /// Set handler to be called when the connection is placed in the /// selectloop and an event occurs. - virtual void setcallback(RefCntr user) {m_user = user;} + virtual void setcallback(RefCntr user) { + m_user = user; + } private: char *m_buf; // Buffer. Only used when doing getline()s @@ -236,13 +256,18 @@ private: /// Network endpoint, client side. class NetconCli : public NetconData { public: - NetconCli(int silent = 0) {m_silentconnectfailure = silent;} + NetconCli(int silent = 0) { + m_silentconnectfailure = silent; + } - /// Open connection to specified host and named service. - int openconn(const char *host, char *serv, int timeo = -1); + /// Open connection to specified host and named service. Set host + /// to an absolute path name for an AF_UNIX service. serv is + /// ignored in this case. + int openconn(const char *host, const char *serv, int timeo = -1); /// Open connection to specified host and numeric port. port is in - /// HOST byte order + /// HOST byte order. Set host to an absolute path name for an + /// AF_UNIX service. serv is ignored in this case. int openconn(const char *host, unsigned int port, int timeo = -1); /// Reuse existing fd. @@ -253,7 +278,9 @@ public: int setconn(int fd); /// Do not log message if openconn() fails. - void setSilentFail(int onoff) {m_silentconnectfailure = onoff;} + void setSilentFail(int onoff) { + m_silentconnectfailure = onoff; + } private: int m_silentconnectfailure; // No logging of connection failures if set @@ -289,8 +316,9 @@ public: #endif /* NETCON_ACCESSCONTROL */ } ~NetconServLis(); - /// Open named service. - int openservice(char *serv, int backlog = 10); + /// Open named service. Used absolute pathname to create an + /// AF_UNIX path-based socket instead of an IP one. + int openservice(const char *serv, int backlog = 10); /// Open service by port number. int openservice(int port, int backlog = 10); /// Wait for incoming connection. Returned connected Netcon @@ -302,12 +330,15 @@ protected: /// insert the new connection in the selectloop. virtual int cando(Netcon::Event reason); + // Empty if port was numeric, else service name or socket path + std::string m_serv; + private: #ifdef NETCON_ACCESSCONTROL int permsinit; struct intarrayparam okaddrs; struct intarrayparam okmasks; - int initperms(char *servicename); + int initperms(const char *servicename); int initperms(int port); int checkperms(void *cli, int clilen); #endif /* NETCON_ACCESSCONTROL */ @@ -318,15 +349,15 @@ private: /// case of a forking server) class NetconServCon : public NetconData { public: - NetconServCon(int newfd, Netcon* lis = 0) - { + NetconServCon(int newfd, Netcon* lis = 0) { m_liscon = lis; m_fd = newfd; } /// This is for forked servers that want to get rid of the main socket void closeLisCon() { - if (m_liscon) + if (m_liscon) { m_liscon->closeconn(); + } } private: Netcon* m_liscon;