⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udsocket.cpp

📁 一个UNIX/LINUX下的基于内容的过滤服务器源代码
💻 CPP
字号:
//Please refer to http://dansguardian.org/?page=copyright2//for the license for this code.//Written by Daniel Barron (daniel@jadeb// .com).//For support go to http://groups.yahoo.com/group/dansguardian//  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#include "autoconf/platform.h"#include <syslog.h>#include "UDSocket.hpp"#include <csignal>#ifdef __BSD	#include <sys/wait.h>#else	#include <wait.h>#endif#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pwd.h>#include <cerrno>#include <unistd.h>#include <iostream>#include <stdexcept>// This class contains client and server Internet socket init and handling// code as well as functions for testing and working with the socket FDs.UDSocket::UDSocket() :timeout(5), isclosed(false), isused(false) {    sck_un = socket(PF_UNIX, SOCK_STREAM, 0);    memset(&my_adr_un, 0, sizeof my_adr_un);    memset(&peer_adr_un, 0, sizeof peer_adr_un);    my_adr_un.sun_family = AF_UNIX;    peer_adr_un.sun_family = AF_UNIX;}UDSocket::~UDSocket() {  // closing of fd is only automatic if socket not used    if (!isused && !isclosed) {        ::close(sck_un);    }}// For creating a socket from the 3 things that make a socketUDSocket::UDSocket(int newfd, struct sockaddr_un myadr) :timeout(5), isclosed(false), isused(true) {    sck_un = newfd;    my_adr_un = myadr;    my_adr_un_length = sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path);}void UDSocket::reset() {    ::close(sck_un);    timeout = 5;    isclosed = false;    isused = false;    sck_un = socket(PF_UNIX, SOCK_STREAM, 0);    memset(&my_adr_un, 0, sizeof my_adr_un);    memset(&peer_adr_un, 0, sizeof peer_adr_un);    my_adr_un.sun_family = AF_UNIX;    peer_adr_un.sun_family = AF_UNIX;}int UDSocket::connect(const char* path) {  // to make a connection to a serv    #ifdef DGDEBUG        std::cout << "uds connect:" << path << std::endl;    #endif    isused = true;    strcpy(my_adr_un.sun_path, path);    #ifdef __BSD        #ifdef SCM_RIGHTS     /* 4.3BSD Reno and later */            my_adr_un_length = sizeof(my_adr_un.sun_len) + sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path) + 1;            my_adr_un.sun_len = my_adr_un_length ;        #endif    #else        my_adr_un_length = sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path);    #endif    return ::connect(sck_un, (struct sockaddr *) &my_adr_un, my_adr_un_length);}int UDSocket::bind(const char* path) {  // to bind a unix domain socket to a path    isused = true;    unlink(path);    strcpy(my_adr_un.sun_path, path);    #ifdef __BSD        #ifdef SCM_RIGHTS     /* 4.3BSD Reno and later */            my_adr_un_length = sizeof(my_adr_un.sun_len) + sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path) + 1;            my_adr_un.sun_len = my_adr_un_length ;        #endif    #else        my_adr_un_length = sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path);    #endif    return ::bind(sck_un, (struct sockaddr *) &my_adr_un, my_adr_un_length);}int UDSocket::listen(int queue) {  // mark a socket as a listening server sockt    return ::listen(sck_un, queue);}UDSocket UDSocket::accept() {  // receive the incomming connection    my_adr_un_length = sizeof(my_adr_un.sun_family) + strlen(my_adr_un.sun_path);    // OS X defines accept as:    // int accept(int s, struct sockaddr *addr, int *addrlen);    // but everyone else as:    // int accept(int s, struct sockaddr *addr, socklen_t *addrlen);#ifdef __DARWIN    int newfd = ::accept(sck_un, (struct sockaddr *) &my_adr_un, (int *)&my_adr_un_length);#else    int newfd = ::accept(sck_un, (struct sockaddr *) &my_adr_un, &my_adr_un_length);#endif    UDSocket s(newfd, my_adr_un);    return s;}int UDSocket::getFD() {    return sck_un;}void UDSocket::setFD(int newfd) {    sck_un = newfd;}void UDSocket::close() {  // close the socket (fd)    ::close(sck_un);    isclosed = true;}void UDSocket::setTimeout(int t) {  // set the socket-wide timeout    timeout = t;}int UDSocket::getTimeout() {    return timeout;}bool UDSocket::checkForInput() {  // non-blocking check    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_un, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = 0;    t.tv_usec = 0;    if (UDSocket::selectEINTR(sck_un + 1, &fdSet, NULL, NULL, &t) < 1) {        return false;    }    return true;}void UDSocket::checkForInput(int timeout) throw (exception)  {                                            // blocks if socket blocking                                            // until timeout    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_un, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = timeout;    t.tv_usec = 0;    if (UDSocket::selectEINTR(sck_un + 1, &fdSet, NULL, NULL, &t) < 1) {        string err("select() on input (unix socket): ");        throw runtime_error(err + (errno? strerror(errno) : "timeout"));    }}bool UDSocket::readyForOutput() {  // non-blocking check    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_un, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = 0;    t.tv_usec = 0;    if (UDSocket::selectEINTR(sck_un + 1, NULL, &fdSet, NULL, &t) < 1) {        return false;    }    return true;}void UDSocket::readyForOutput(int timeout) throw(exception) {                                            // blocks if socket blocking                                            // until timeout    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_un, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = timeout;    t.tv_usec = 0;    if (UDSocket::selectEINTR(sck_un + 1, NULL, &fdSet, NULL, &t) < 1) {        string err("select() on output (unix socket): ");        throw runtime_error(err + (errno? strerror(errno) : "timeout"));    }}int UDSocket::getline(char* buff, int size, int timeout) throw(exception) {    char b[1];    int rc;    int i = 0;    b[0] = 0;    while(i < (size - 1)) {        rc = readFromSocket(b, 1, 0, timeout);        if (rc < 0) {            throw runtime_error(string("Can't read from unix socket: ") + strerror(errno));  // on error        }        if (rc == 0) {  // eof, other end closed so            b[0] = '\n'; // force it to return what read        }        buff[i] = b[0];        i++;        if (b[0] == '\n') {            buff[i - 1] = '\0';            break;        }    }    buff[i] = '\0';    return i;}void UDSocket::writeString(const char* line) throw(exception) {    int l = strlen(line);    if (!writeToSocket((char*)line, l, 0, 10)) {        throw runtime_error(string("Can't write to unix socket: ") + strerror(errno));    }}void UDSocket::writeToSockete(char* buff, int len, unsigned int flags, int timeout) throw(exception) {  if (!UDSocket::writeToSocket(buff, len, flags, timeout)) {      throw runtime_error(string("Can't write to unix socket: ") + strerror(errno));  }}bool UDSocket::writeToSocket(char* buff, int len, unsigned int flags, int timeout) {    int actuallysent = 0;    int sent;    while (actuallysent < len) {        try {            readyForOutput(timeout);  // throws exception on error or timeout        } catch (exception& e) {            return false;        }        sent = send(sck_un, buff + actuallysent, len - actuallysent, 0);        if (sent < 0) {            if (errno == EINTR) {                continue;  // was interupted by signal so restart            }            return false;        }        if (sent == 0) {            return false; // other end is closed        }        actuallysent += sent;    }    return true;}// read a specified expected amount and return what actually readint UDSocket::readFromSocketn(char* buff, int len, unsigned int flags, int timeout) {    int cnt, rc;    cnt = len;    while (cnt > 0) {        try {            checkForInput(timeout);  // throws exception on error or timeout        } catch (exception& e) {            return -1;        }        rc = recv(sck_un, buff, len, flags);        if (rc < 0) {            if (errno == EINTR) {                continue;            }            return -1;        }        if (rc == 0) { // eof            return len - cnt;        }        buff += rc;        cnt -= rc;    }    return len;}// read what's available and return how much readint UDSocket::readFromSocket(char* buff, int len, unsigned int flags, int timeout) {    int rc;    try {        checkForInput(timeout);    } catch (exception& e) {        return -1;    }    while (true) {        rc = recv(sck_un, buff, len, flags);        if (rc < 0) {            if (errno == EINTR) {                continue;            }        }        break;    }    return rc;}// a wrapper for select so that it auto-restarts after an ENINTRint UDSocket::selectEINTR(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) {    int rc;    while (true) {  // using the while as a restart point with continue        rc = select(numfds, readfds, writefds, exceptfds, timeout);        if (rc < 0) {            if (errno == EINTR) {                continue;  // was interupted by a signal so restart            }        }        break;  // end the while    }    return rc;  // return status}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -