Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

SockListenModule.cxx

00001 /*
00002  * Copyright (C) 1991-9 Eric M. Hopper <hopper@omnifarious.mn.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 of the License, or
00007  *     (at your option) any later version.
00008  * 
00009  *     This program is distributed in the hope that it will be useful, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/StrMod/SockListenModule.cxx,v 1.28 2002/11/25 05:40:05 hopper Exp $ */
00020 
00021 // For a log, see ./ChangeLog
00022 
00023 // $Revision: 1.28 $
00024 
00025 #ifdef __GNUG__
00026 #  pragma implementation "SockListenModule.h"
00027 #endif
00028 
00029 #include "StrMod/SockListenModule.h"
00030 
00031 #ifndef _STR_SocketModule_H_
00032 #  include "StrMod/SocketModule.h"
00033 #endif
00034 
00035 #include <EHnet++/SocketAddress.h>
00036 #include <EHnet++/InetAddress.h>
00037 
00038 #include <fcntl.h>
00039 #include <sys/types.h>
00040 #include <sys/socket.h>
00041 #include <cerrno>
00042 #include <unistd.h>
00043 #include <netinet/in.h>
00044 #include <cassert>
00045 #include <new>
00046 #include "config.h"
00047 #include "sockdecl.h"
00048 #include <iostream>
00049 
00050 namespace strmod {
00051 namespace strmod {
00052 
00053 using ehnet::SocketAddress;
00054 using lcore::LCoreError;
00055 
00056 const STR_ClassIdent SockListenModule::identifier(13UL);
00057 const STR_ClassIdent SockListenModule::SLPlug::identifier(14UL);
00058 const STR_ClassIdent SocketModuleChunk::identifier(15UL);
00059 
00060 /**A parent class for the three sub event classes.
00061  *
00062  * The sub event classes don't do anything except call parent class protected
00063  * functions.  The only reason they exist is to avoid having a switch statement
00064  * in the parent.
00065 */
00066 class SockListenModule::FDPollEv : public unievent::Event
00067 {
00068  public:
00069    inline FDPollEv(SockListenModule &parent);
00070    virtual ~FDPollEv()                                 { }
00071 
00072    virtual void triggerEvent(Dispatcher *dispatcher = 0) = 0;
00073 
00074    inline void parentGone()                            { hasparent_ = false; }
00075 
00076  protected:
00077    inline void triggerRead();
00078    inline void triggerError();
00079 
00080  private:
00081    bool hasparent_;
00082    SockListenModule &parent_;
00083 };
00084 
00085 inline SockListenModule::FDPollEv::FDPollEv(SockListenModule &parent)
00086      : hasparent_(true), parent_(parent)
00087 {
00088 }
00089 
00090 inline void SockListenModule::FDPollEv::triggerRead()
00091 {
00092    // cerr << "In triggerRead\n";
00093    if (hasparent_)
00094    {
00095       parent_.eventRead();
00096    }
00097 }
00098 
00099 inline void SockListenModule::FDPollEv::triggerError()
00100 {
00101    // cerr << "In triggerError\n";
00102    if (hasparent_)
00103    {
00104       parent_.eventError();
00105    }
00106 }
00107 
00108 //: This is one of the three helper classes for SockListenModule::FDPollEv
00109 class SockListenModule::FDPollRdEv : public SockListenModule::FDPollEv
00110 {
00111  public:
00112    inline FDPollRdEv(SockListenModule &parent) : FDPollEv(parent)   { }
00113    virtual ~FDPollRdEv()                                            { }
00114 
00115    virtual void triggerEvent(Dispatcher *dispatcher = 0)     { triggerRead(); }
00116 };
00117 
00118 //: This is one of the three helper classes for SockListenModule::FDPollEv
00119 class SockListenModule::FDPollErEv : public SockListenModule::FDPollEv {
00120  public:
00121    inline FDPollErEv(SockListenModule &parent) : FDPollEv(parent)   { }
00122    virtual ~FDPollErEv()                                            { }
00123 
00124    virtual void triggerEvent(Dispatcher *dispatcher = 0)     { triggerError(); }
00125 };
00126 
00127 SockListenModule::SockListenModule(const SocketAddress &bind_addr,
00128                                    unievent::Dispatcher &disp,
00129                                    unievent::UnixEventRegistry &ureg,
00130                                    int qlen)
00131       : sockfd_(-1), has_error_(false), lplug_(*this),
00132         plug_pulled_(false), checking_read_(false), newmodule_(0),
00133         myaddr_(*(bind_addr.Copy())),
00134         disp_(disp), ureg_(ureg), readevptr_(0), errorevptr_(0)
00135 {
00136    using unievent::UNIXError;
00137    sockfd_ = socket(myaddr_.SockAddr()->sa_family, SOCK_STREAM, PF_UNSPEC);
00138    if (sockfd_ < 0)
00139    {
00140       const int myerrno = UNIXError::getErrno();
00141       setError(UNIXError("socket", myerrno,
00142                          LCoreError("Creating listening socket",
00143                                     LCORE_GET_COMPILERINFO())));
00144       return;
00145    }
00146    {
00147       int temp = fcntl(sockfd_, F_GETFL, 0);
00148 
00149       if (temp < 0)
00150       {
00151          const int myerrno = UNIXError::getErrno();
00152          setError(UNIXError("fcntl", myerrno,
00153                             LCoreError("Setting non-blocking mode",
00154                                        LCORE_GET_COMPILERINFO())));
00155          close(sockfd_);
00156          sockfd_ = -1;
00157          return;
00158       }
00159       temp &= ~O_NDELAY;
00160       if (fcntl(sockfd_, F_SETFL, temp | O_NONBLOCK) < 0)
00161       {
00162          const int myerrno = UNIXError::getErrno();
00163          setError(UNIXError("fcntl", myerrno,
00164                             LCoreError("Setting non-blocking mode",
00165                                        LCORE_GET_COMPILERINFO())));
00166          close(sockfd_);
00167          sockfd_ = -1;
00168          return;
00169       }
00170    }
00171    if (bind(sockfd_, myaddr_.SockAddr(), myaddr_.AddressSize()) < 0)
00172    {
00173       const int myerrno = UNIXError::getErrno();
00174 //      int myerrno = errno;
00175 //      std::cerr << "errno == " << myerrno << "\n";
00176       setError(UNIXError("bind", myerrno,
00177                          LCoreError("Binding listening socket",
00178                                     LCORE_GET_COMPILERINFO())));
00179       close(sockfd_);
00180       sockfd_ = -1;
00181       return;
00182    }
00183    if (listen(sockfd_, qlen) < 0)
00184    {
00185       const int myerrno = UNIXError::getErrno();
00186       setError(UNIXError("listen", myerrno,
00187                          LCoreError("Listening on listening socket",
00188                                     LCORE_GET_COMPILERINFO())));
00189       close(sockfd_);
00190       sockfd_ = -1;
00191       return;
00192    }
00193    readevptr_ = new FDPollRdEv(*this);
00194    std::cerr << "readevptr_ == " << readevptr_ << "\n";
00195    readev_ = readevptr_;
00196    errorevptr_ = new FDPollErEv(*this);
00197    std::cerr << "errorevptr_ == " << errorevptr_ << "\n";
00198    errorev_ = errorevptr_;
00199    checking_read_ = true;
00200    {
00201       static const UnixEventRegistry::FDCondSet
00202          errorconds(UnixEventRegistry::FD_Error,
00203                     UnixEventRegistry::FD_Closed,
00204                     UnixEventRegistry::FD_Invalid);
00205       static const UnixEventRegistry::FDCondSet
00206          readcond(UnixEventRegistry::FD_Readable);
00207       ureg_.registerFDCond(sockfd_, errorconds, errorev_);
00208       ureg_.registerFDCond(sockfd_, readcond, readev_);
00209    }
00210 }
00211 
00212 SockListenModule::~SockListenModule()
00213 {
00214    if (sockfd_ >= 0)
00215    {
00216       close(sockfd_);
00217       ureg_.freeFD(sockfd_);
00218    }
00219    delete &myaddr_;
00220    if (readevptr_)
00221    {
00222       readevptr_->parentGone();
00223    }
00224    if (errorevptr_)
00225    {
00226       errorevptr_->parentGone();
00227    }
00228 }
00229 
00230 void SockListenModule::eventRead()
00231 {
00232    using unievent::UNIXError;
00233    checking_read_ = false;
00234    if (newmodule_ == 0)
00235    {
00236       doAccept();
00237    }
00238 }
00239 
00240 void SockListenModule::eventError()
00241 {
00242    using unievent::UNIXError;
00243    setError(UNIXError("<none>", 0,
00244                       LCoreError("Got error condition",
00245                                  LCORE_GET_COMPILERINFO())));
00246 }
00247 
00248 void SockListenModule::doAccept()
00249 {
00250    using unievent::UNIXError;
00251    assert(newmodule_ == 0);
00252 
00253    if (newmodule_ != 0)
00254    {
00255       setReadableFlagFor(&lplug_, true);
00256       return;
00257    }
00258 
00259    unsigned char addrbuf[8192];
00260    struct sockaddr *saddr = reinterpret_cast<struct sockaddr *>(addrbuf);
00261    size_t length = sizeof(addrbuf);
00262 #ifdef ACCEPT_NEEDS_INT
00263    int stupid_compatibility_trick = length;
00264    int tempfd = accept(sockfd_, saddr, &stupid_compatibility_trick);
00265    length = stupid_compatibility_trick;
00266 #else
00267    int tempfd = accept(sockfd_, saddr, &length);
00268 #endif
00269 
00270    if (tempfd < 0)
00271    {
00272       const int myerrno = UNIXError::getErrno();
00273       if (myerrno != EAGAIN)
00274       {
00275          setError(UNIXError("accept", myerrno,
00276                             LCoreError("Error accepting connection",
00277                                        LCORE_GET_COMPILERINFO())));
00278       }
00279       else if (!checking_read_)
00280       {
00281          static const UnixEventRegistry::FDCondSet
00282             readcond(UnixEventRegistry::FD_Readable);
00283          ureg_.registerFDCond(sockfd_, readcond, readev_);
00284          checking_read_ = true;
00285       }
00286    }
00287    else
00288    {
00289       if (saddr->sa_family != AF_INET)
00290       {
00291          close(tempfd);
00292          setError(UNIXError("<none>", 0,
00293                             LCoreError("Got connection from non-AF_INET peer",
00294                                        LCORE_GET_COMPILERINFO())));
00295       }
00296       else
00297       {
00298          {
00299             int temp = fcntl(tempfd, F_GETFL, 0);
00300 
00301             if (temp < 0)
00302             {
00303                const int myerrno = UNIXError::getErrno();
00304                setError(UNIXError("fcntl", myerrno,
00305                                   LCoreError("Setting accepted connection non-blocking",
00306                                              LCORE_GET_COMPILERINFO())));
00307                close(tempfd);
00308                tempfd = -1;
00309             }
00310             else
00311             {
00312                temp &= ~O_NDELAY;
00313                if (fcntl(tempfd, F_SETFL, temp | O_NONBLOCK) < 0)
00314                {
00315                   const int myerrno = UNIXError::getErrno();
00316                   setError(UNIXError("fcntl", myerrno,
00317                                      LCoreError("Setting accepted connection non-blocking",
00318                                                 LCORE_GET_COMPILERINFO())));
00319                   close(tempfd);
00320                   tempfd = -1;
00321                   return;
00322                }
00323             }
00324          }
00325 
00326          if (tempfd >= 0)
00327          {
00328             sockaddr_in *sinad
00329                = reinterpret_cast<struct sockaddr_in *>(saddr);
00330             ehnet::InetAddress *addr = new ehnet::InetAddress(*sinad);
00331 
00332             newmodule_ = makeSocketModule(tempfd, addr, disp_, ureg_);
00333          }
00334       }
00335    }
00336    if (newmodule_ != 0)
00337    {
00338       setReadableFlagFor(&lplug_, true);
00339    }
00340    else
00341    {
00342       setReadableFlagFor(&lplug_, false);
00343    }
00344 }
00345 
00346 void SockListenModule::clearError() throw()
00347 {
00348    using unievent::UNIXError;
00349    if (has_error_)
00350    {
00351       (reinterpret_cast<UNIXError *>(errorstore_))->~UNIXError();
00352       has_error_ = false;
00353    }
00354 }
00355 
00356 const unievent::UNIXError &SockListenModule::getError() const throw()
00357 {
00358    using unievent::UNIXError;
00359    const void *raw = errorstore_;
00360    return *reinterpret_cast<const UNIXError *>(raw);
00361 }
00362 
00363 void SockListenModule::setError(const unievent::UNIXError &err) throw()
00364 {
00365    using unievent::UNIXError;
00366    void *raw = errorstore_;
00367    UNIXError *store = reinterpret_cast<UNIXError *>(raw);
00368    if (has_error_)
00369    {
00370       store->~UNIXError();
00371    }
00372    else
00373    {
00374       has_error_ = true;
00375    }
00376    new(raw) UNIXError(err);
00377 }
00378 
00379 SocketModule *SockListenModule::getNewModule()
00380 {
00381    SocketModule *retval = newmodule_;
00382 
00383    if (newmodule_ != 0)
00384    {
00385       newmodule_ = 0;
00386       doAccept();
00387    }
00388    return(retval);
00389 }
00390 
00391 const SocketModuleChunkPtr SockListenModule::SLPlug::getConnection()
00392 {
00393    return(new SocketModuleChunk(getParent().getNewModule()));
00394 }
00395 
00396 const StrChunkPtr SockListenModule::SLPlug::i_Read()
00397 {
00398    return(getConnection());
00399 }
00400 
00401 void SockListenModule::SLPlug::i_Write(const StrChunkPtr &chunk)
00402 {
00403    assert(false);
00404 }
00405 
00406 };  // End namespace strmod
00407 };  // End namespace strmod

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1