"Fossies" - the Fresh Open Source Software Archive

Member "plptools-1.0.15/lib/ppsocket.cc" (31 Oct 2019, 14088 Bytes) of package /linux/privat/plptools-1.0.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ppsocket.cc" see the Fossies "Dox" file reference documentation.

    1 /*-*-c++-*-
    2  * $Id$
    3  *
    4  * This file is part of plptools.
    5  *
    6  *  Copyright (C) 1999  Philip Proudman <philip.proudman@btinternet.com>
    7  *  Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
    8  *
    9  *  This program is free software; you can redistribute it and/or modify
   10  *  it under the terms of the GNU General Public License as published by
   11  *  the Free Software Foundation; either version 2 of the License, or
   12  *  (at your option) any later version.
   13  *
   14  *  This program is distributed in the hope that it will be useful,
   15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *  GNU General Public License for more details.
   18  *
   19  *  You should have received a copy of the GNU General Public License
   20  *  along with this program; if not, write to the Free Software
   21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22  *
   23  */
   24 #ifdef HAVE_CONFIG_H
   25 #include "config.h"
   26 #endif
   27 
   28 #include "bufferstore.h"
   29 #include "ppsocket.h"
   30 #include "iowatch.h"
   31 
   32 #include <cstring>
   33 #include <iostream>
   34 
   35 #include <stdio.h>
   36 #include <stdlib.h>
   37 #include <stdarg.h>
   38 #include <fcntl.h>
   39 #include <unistd.h>
   40 #include <errno.h>
   41 #include <ctype.h>
   42 #include <sys/time.h>
   43 #include <sys/types.h>
   44 #include <netinet/in.h>
   45 #include <arpa/inet.h>
   46 
   47 #define  INVALID_SOCKET -1
   48 #define  SOCKET_ERROR   -1
   49 
   50 #ifndef MSG_NOSIGNAL
   51 #define MSG_NOSIGNAL 0
   52 #endif
   53 
   54 using namespace std;
   55 
   56 ppsocket::ppsocket(const ppsocket & another)
   57 {
   58     m_Socket = another.m_Socket;
   59     m_HostAddr = another.m_HostAddr;
   60     m_PeerAddr = another.m_PeerAddr;
   61     m_Bound = another.m_Bound;
   62     m_LastError = another.m_LastError;
   63     myWatch = another.myWatch;
   64 }
   65 
   66 
   67 ppsocket::ppsocket()
   68 {
   69     m_Socket = INVALID_SOCKET;
   70 
   71     memset(&m_HostAddr, 0, sizeof(m_HostAddr));
   72     memset(&m_PeerAddr, 0, sizeof(m_PeerAddr));
   73 
   74     ((struct sockaddr_in *) &m_HostAddr)->sin_family = AF_INET;
   75     ((struct sockaddr_in *) &m_PeerAddr)->sin_family = AF_INET;
   76 
   77     m_Bound = false;
   78     m_LastError = 0;
   79     myWatch = 0L;
   80 }
   81 
   82 ppsocket::~ppsocket()
   83 {
   84     if (m_Socket != INVALID_SOCKET) {
   85     if (myWatch)
   86         myWatch->remIO(m_Socket);
   87     shutdown(m_Socket, SHUT_RDWR);
   88     ::close(m_Socket);
   89     }
   90 }
   91 
   92 void ppsocket::
   93 setWatch(IOWatch *watch) {
   94     if (watch) {
   95     if (myWatch && (m_Socket != INVALID_SOCKET))
   96        myWatch->remIO(m_Socket);
   97     myWatch = watch;
   98     }
   99 }
  100 
  101 bool ppsocket::
  102 reconnect()
  103 {
  104     if (m_Socket != INVALID_SOCKET) {
  105     if (myWatch)
  106         myWatch->remIO(m_Socket);
  107     shutdown(m_Socket, SHUT_RDWR);
  108     ::close(m_Socket);
  109     }
  110     m_Socket = INVALID_SOCKET;
  111     if (!createSocket())
  112     return (false);
  113     m_LastError = 0;
  114     m_Bound = false;
  115     if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) != 0) {
  116     m_LastError = errno;
  117     return (false);
  118     }
  119     if (::connect(m_Socket, &m_PeerAddr, sizeof(m_PeerAddr)) != 0) {
  120     m_LastError = errno;
  121     return (false);
  122     }
  123     if (myWatch)
  124     myWatch->addIO(m_Socket);
  125     return (true);
  126 }
  127 
  128 string ppsocket::
  129 toString()
  130 {
  131     string ret = "";
  132     char nbuf[10];
  133     char *tmp = 0L;
  134     int port;
  135 
  136     tmp = inet_ntoa(((struct sockaddr_in *) &m_HostAddr)->sin_addr);
  137     ret += tmp ? tmp : "none:none";
  138     if (tmp) {
  139     ret += ':';
  140     sprintf(nbuf, "%d", ntohs(((struct sockaddr_in *) &m_HostAddr)->sin_port));
  141     ret += nbuf;
  142     }
  143     ret += " -> ";
  144     tmp = inet_ntoa(((struct sockaddr_in *) &m_PeerAddr)->sin_addr);
  145     ret += tmp ? tmp : "none:none";
  146     if (tmp) {
  147     ret += ':';
  148     sprintf(nbuf, "%d", ntohs(((struct sockaddr_in *) &m_PeerAddr)->sin_port));
  149     ret += nbuf;
  150     }
  151     return ret;
  152 }
  153 
  154 bool ppsocket::
  155 connect(const char * const Peer, int PeerPort, const char * const Host, int HostPort)
  156 {
  157     //****************************************************
  158     //* If we aren't already bound set the host and bind *
  159     //****************************************************
  160 
  161     if (!bindSocket(Host, HostPort)) {
  162     if (m_LastError != 0) {
  163         return (false);
  164     }
  165     }
  166     //****************
  167     //* Set the peer *
  168     //****************
  169     if (!setPeer(Peer, PeerPort)) {
  170     return (false);
  171     }
  172     //***********
  173     //* Connect *
  174     //***********
  175     if (::connect(m_Socket, &m_PeerAddr, sizeof(m_PeerAddr)) != 0) {
  176     m_LastError = errno;
  177     return (false);
  178     }
  179     if (myWatch)
  180     myWatch->addIO(m_Socket);
  181     return (true);
  182 }
  183 
  184 bool ppsocket::
  185 listen(const char * const Host, int Port)
  186 {
  187     //****************************************************
  188     //* If we aren't already bound set the host and bind *
  189     //****************************************************
  190 
  191     if (!bindSocket(Host, Port)) {
  192     if (m_LastError != 0) {
  193         return (false);
  194     }
  195     }
  196     //**********************
  197     //* Listen on the port *
  198     //**********************
  199 
  200     if (myWatch)
  201     myWatch->addIO(m_Socket);
  202     if (::listen(m_Socket, 5) != 0) {
  203     m_LastError = errno;
  204     return (false);
  205     }
  206     return (true);
  207 }
  208 
  209 ppsocket *ppsocket::
  210 accept(string *Peer, IOWatch *iow)
  211 {
  212 #ifdef sun
  213     int len;
  214 #else
  215 # ifdef __FreeBSD__
  216 #  if __FreeBSD_version >= 400000
  217     socklen_t len;
  218 #  else
  219     unsigned len;
  220 #  endif
  221 # endif
  222     socklen_t len;
  223 #endif
  224     ppsocket *accepted;
  225     char *peer;
  226 
  227     //*****************************************************
  228     //* Allocate a new object to hold the accepted socket *
  229     //*****************************************************
  230     accepted = new ppsocket;
  231 
  232     if (!iow)
  233     iow = myWatch;
  234     if (!accepted) {
  235     m_LastError = errno;
  236     return NULL;
  237     }
  238     //***********************
  239     //* Accept a connection *
  240     //***********************
  241 
  242     len = sizeof(struct sockaddr);
  243     accepted->m_Socket = ::accept(m_Socket, &accepted->m_PeerAddr, &len);
  244 
  245     if (accepted->m_Socket == INVALID_SOCKET) {
  246     m_LastError = errno;
  247     delete accepted;
  248     return NULL;
  249     }
  250     //****************************************************
  251     //* Got a connection so fill in the other attributes *
  252     //****************************************************
  253 
  254     // Make sure the new socket hasn't inherited O_NONBLOCK
  255     // from the accept socket
  256     int flags = fcntl(accepted->m_Socket, F_GETFL, 0);
  257     flags &= ~O_NONBLOCK;
  258     fcntl(accepted->m_Socket, F_SETFL, flags);
  259 
  260     accepted->m_HostAddr = m_HostAddr;
  261     accepted->m_Bound = true;
  262 
  263     //****************************************************
  264     //* If required get the name of the connected client *
  265     //****************************************************
  266     if (Peer) {
  267     peer = inet_ntoa(((struct sockaddr_in *) &accepted->m_PeerAddr)->sin_addr);
  268     if (peer)
  269         *Peer = peer;
  270     }
  271     if (accepted && iow) {
  272     accepted->setWatch(iow);
  273     iow->addIO(accepted->m_Socket);
  274     }
  275     return accepted;
  276 }
  277 
  278 bool ppsocket::
  279 dataToGet(int sec, int usec) const
  280 {
  281     fd_set io;
  282     FD_ZERO(&io);
  283     FD_SET(m_Socket, &io);
  284     struct timeval t;
  285     t.tv_usec = usec;
  286     t.tv_sec = sec;
  287     return (select(m_Socket + 1, &io, NULL, NULL, &t) != 0) ? true : false;
  288 }
  289 
  290 int ppsocket::
  291 getBufferStore(bufferStore & a, bool wait)
  292 {
  293     /* Returns a 0 for for no message,
  294     * 1 for message OK, and -1 for socket problem
  295     */
  296 
  297     u_int32_t l;
  298     long count = 0;
  299     unsigned char *buff;
  300     unsigned char *bp;
  301     if (!wait && !dataToGet(0, 0))
  302     return 0;
  303     a.init();
  304     if (recv(&l, sizeof(l), MSG_NOSIGNAL) != sizeof(l)) {
  305     return -1;
  306     }
  307     l = ntohl(l);
  308     if (l > 16384)
  309         return -1;
  310     bp = buff = new unsigned char[l];
  311     while (l > 0) {
  312     int j = recv(bp, l, MSG_NOSIGNAL);
  313     if (j == SOCKET_ERROR || j == 0) {
  314         delete[]buff;
  315         return -1;
  316     }
  317     count += j;
  318     l -= j;
  319     bp += j;
  320     };
  321     a.init(buff, count);
  322     delete[]buff;
  323     return (a.getLen() == 0) ? 0 : 1;
  324 }
  325 
  326 bool ppsocket::
  327 sendBufferStore(const bufferStore & a)
  328 {
  329     long l = a.getLen();
  330     u_int32_t hl = htonl(l);
  331     long sent = 0;
  332     int retries = 0;
  333     int i;
  334 
  335     bufferStore b;
  336     b.addBytes(reinterpret_cast<const unsigned char *>(&hl), sizeof(hl));
  337     b.addBuff(a);
  338     l += 4;
  339     while (l > 0) {
  340     i = send((const char *)b.getString(sent), l, MSG_NOSIGNAL);
  341     if (i == SOCKET_ERROR || i == 0)
  342         return (false);
  343     sent += i;
  344     l -= i;
  345     if (++retries > 5) {
  346         m_LastError = 0;
  347         return (false);
  348     }
  349     }
  350     return true;
  351 }
  352 
  353 int ppsocket::
  354 recv(void *buf, int len, int flags)
  355 {
  356     int i = ::recv(m_Socket, buf, len, flags);
  357 
  358     if (i < 0)
  359     m_LastError = errno;
  360 
  361     return (i);
  362 }
  363 
  364 int ppsocket::
  365 send(const void * const buf, int len, int flags)
  366 {
  367     int i = ::send(m_Socket, buf, len, flags);
  368 
  369     if (i < 0)
  370     m_LastError = errno;
  371 
  372     return (i);
  373 }
  374 
  375 bool ppsocket::
  376 closeSocket(void)
  377 {
  378     if (myWatch)
  379     myWatch->remIO(m_Socket);
  380     shutdown(m_Socket, SHUT_RDWR);
  381     if (::close(m_Socket) != 0) {
  382     m_LastError = errno;
  383     return false;
  384     }
  385     m_Socket = INVALID_SOCKET;
  386     return true;
  387 }
  388 
  389 bool ppsocket::
  390 bindSocket(const char * const Host, int Port)
  391 {
  392 
  393     // If we are already bound return false but with no last error
  394     if (m_Bound) {
  395     m_LastError = 0;
  396     return false;
  397     }
  398 
  399     // If the socket hasn't been created create it now
  400 
  401     if (m_Socket == INVALID_SOCKET) {
  402     if (!createSocket())
  403         return false;
  404     }
  405 
  406     // Set SO_REUSEADDR
  407     int one = 1;
  408     if (setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR,
  409            (const char *)&one, sizeof(int)) < 0)
  410     cerr << "Warning: Unable to set SO_REUSEADDR option\n";
  411 
  412     // If a host name was supplied then use it
  413     if (!setHost(Host, Port))
  414     return false;
  415 
  416     // Now bind the socket
  417     if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) != 0) {
  418     m_LastError = errno;
  419     return false;
  420     }
  421 
  422     m_Bound = true;
  423     return true;
  424 }
  425 
  426 bool ppsocket::
  427 bindInRange(const char * const Host, int Low, int High, int Retries)
  428 {
  429     int port;
  430     int i;
  431 
  432     // If we are already bound return false but with no last error
  433     if (m_Bound) {
  434     m_LastError = 0;
  435     return (false);
  436     }
  437 
  438     // If the socket hasn't been created create it now
  439     if (m_Socket == INVALID_SOCKET) {
  440     if (!createSocket())
  441         return false;
  442     }
  443 
  444     // If the number of retries is greater than the range then work
  445     // through the range sequentially.
  446     if (Retries > High - Low) {
  447     for (port = Low; port <= High; port++) {
  448         if (!setHost(Host, port))
  449         return false;
  450         if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) == 0)
  451         break;
  452     }
  453     if (port > High) {
  454         m_LastError = errno;
  455         return false;
  456     }
  457     } else {
  458     for (i = 0; i < Retries; i++) {
  459         port = Low + (rand() % (High - Low));
  460         if (!setHost(Host, port))
  461         return false;
  462         if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) == 0)
  463         break;
  464     }
  465     if (i >= Retries) {
  466         m_LastError = errno;
  467         return false;
  468     }
  469     }
  470     m_Bound = true;
  471     return true;
  472 }
  473 
  474 bool ppsocket::
  475 linger(bool LingerOn, int LingerTime)
  476 {
  477     int i;
  478     struct linger l;
  479 
  480     // If the socket hasn't been created create it now
  481     if (m_Socket == INVALID_SOCKET) {
  482     if (!createSocket())
  483         return false;
  484     }
  485 
  486     // Set the lingering
  487     if (LingerOn) {
  488     l.l_onoff = 1;
  489     l.l_linger = LingerTime;
  490     } else {
  491     l.l_onoff = 0;
  492     l.l_linger = 0;
  493     }
  494     i = setsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (const char *) &l, sizeof(l));
  495     // Check for errors
  496     if (i != 0) {
  497     m_LastError = errno;
  498     return false;
  499     }
  500     return true;
  501 }
  502 
  503 bool ppsocket::
  504 createSocket(void)
  505 {
  506     // If the socket has already been created just return true
  507     if (m_Socket != INVALID_SOCKET)
  508     return true;
  509 
  510     // Create the socket
  511     m_Socket = ::socket(PF_INET, SOCK_STREAM, 0);
  512     if (m_Socket == INVALID_SOCKET) {
  513     m_LastError = errno;
  514     return false;
  515     }
  516 
  517     // By default set no lingering
  518     linger(false);
  519 
  520     // Return indicating success
  521     return true;
  522 }
  523 
  524 bool ppsocket::
  525 setPeer(const char * const Peer, int Port)
  526 {
  527     struct hostent *he = NULL;
  528 
  529     // If a peer name was supplied then use it
  530     if (Peer) {
  531     if (!isdigit(Peer[0]))
  532         // RFC1035 specifies that hostnames must not start
  533         // with a digit. So we can speed up things here.
  534         he = gethostbyname(Peer);
  535     if (!he) {
  536         struct in_addr ipaddr;
  537 
  538         if (!inet_aton(Peer, &ipaddr)) {
  539         m_LastError = errno;
  540         return false;
  541         }
  542         he = gethostbyaddr((const char *)&ipaddr.s_addr, sizeof(ipaddr.s_addr), PF_INET);
  543         if (!he) {
  544         m_LastError = errno;
  545         return (false);
  546         }
  547     }
  548     memcpy(&((struct sockaddr_in *)&m_PeerAddr)->sin_addr, he->h_addr_list[0],
  549            sizeof(((struct sockaddr_in *)&m_PeerAddr)->sin_addr));
  550     }
  551     // If a port name was supplied use it
  552     if (Port > 0)
  553     ((struct sockaddr_in *)&m_PeerAddr)->sin_port = htons(Port);
  554     return true;
  555 }
  556 
  557 bool ppsocket::
  558 getPeer(string *Peer, int *Port)
  559 {
  560     char *peer;
  561 
  562     if (Peer) {
  563     peer = inet_ntoa(((struct sockaddr_in *) &m_PeerAddr)->sin_addr);
  564     if (!peer) {
  565         m_LastError = errno;
  566         return (false);
  567     }
  568     *Peer = peer;
  569     }
  570     if (Port)
  571     *Port = ntohs(((struct sockaddr_in *) &m_PeerAddr)->sin_port);
  572     return false;
  573 }
  574 
  575 bool ppsocket::
  576 setHost(const char * const Host, int Port)
  577 {
  578     struct hostent *he;
  579 
  580     // If a host name was supplied then use it
  581     if (Host) {
  582     if (!isdigit(Host[0]))
  583         // RFC1035 specifies that hostnames must not start
  584         // with a digit. So we can speed up things here.
  585         he = gethostbyname(Host);
  586     he = gethostbyname(Host);
  587     if (!he) {
  588         struct in_addr ipaddr;
  589 
  590         if (!inet_aton(Host, &ipaddr)) {
  591         m_LastError = errno;
  592         return false;
  593         }
  594         he = gethostbyaddr((const char *)&ipaddr.s_addr, sizeof(ipaddr.s_addr), PF_INET);
  595         if (!he) {
  596         m_LastError = errno;
  597         return false;
  598         }
  599     }
  600     memcpy(&((struct sockaddr_in *)&m_HostAddr)->sin_addr, he->h_addr_list[0],
  601            sizeof(((struct sockaddr_in *)&m_HostAddr)->sin_addr));
  602     }
  603 
  604     // If a port name was supplied use it
  605     if (Port > 0)
  606     ((struct sockaddr_in *)&m_HostAddr)->sin_port = htons(Port);
  607     return true;
  608 }
  609 
  610 bool ppsocket::
  611 getHost(string *Host, int *Port)
  612 {
  613     char *host;
  614 
  615     if (Host) {
  616     host = inet_ntoa(((struct sockaddr_in *)&m_HostAddr)->sin_addr);
  617     if (!host) {
  618         m_LastError = errno;
  619         return false;
  620     }
  621     *Host = host;
  622     }
  623     if (Port)
  624     *Port = ntohs(((struct sockaddr_in *)&m_HostAddr)->sin_port);
  625     return true;
  626 }
  627 
  628 /*
  629  * Local variables:
  630  * c-basic-offset: 4
  631  * End:
  632  */