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

SockListenModule.h

00001 #ifndef _STR_SockListenModule_H_  // -*-c++-*-
00002 
00003 /*
00004  * Copyright (C) 1991-2002 Eric M. Hopper <hopper@omnifarious.org>
00005  * 
00006  *     This program is free software; you can redistribute it and/or modify it
00007  *     under the terms of the GNU Lesser General Public License as published
00008  *     by the Free Software Foundation; either version 2 of the License, or
00009  *     (at your option) any later version.
00010  * 
00011  *     This program is distributed in the hope that it will be useful, but
00012  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *     Lesser General Public License for more details.
00015  * 
00016  *     You should have received a copy of the GNU Lesser General Public
00017  *     License along with this program; if not, write to the Free Software
00018  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #ifdef __GNUG__
00022 #  pragma interface
00023 #endif
00024 
00025 /* $Header: /home/hopper/src/cvs/C++/StrMod/StrMod/SockListenModule.h,v 1.16 2002/08/29 00:58:04 hopper Exp $ */
00026 
00027 // For a log, see ../ChangeLog
00028 
00029 // $Revision: 1.16 $
00030 
00031 #include <string>
00032 
00033 #include <UniEvent/EventPtr.h>
00034 #include <UniEvent/UnixEventRegistry.h>
00035 #include <UniEvent/UNIXError.h>
00036 #include <EHnet++/SocketAddress.h>
00037 
00038 #ifndef _STR_StreamModule_H_
00039 #   include <StrMod/StreamModule.h>
00040 #endif
00041 
00042 #ifndef _STR_StrChunk_H_
00043 #  include <StrMod/StrChunk.h>
00044 #endif
00045 
00046 #ifndef _STR_StrChunkPtrT_H_
00047 #  include <StrMod/StrChunkPtrT.h>
00048 #endif
00049 
00050 #ifndef _STR_SocketModule_H_
00051 #  include <StrMod/SocketModule.h>
00052 #endif
00053 
00054 
00055 #define _STR_SockListenModule_H_
00056 
00057 namespace strmod {
00058 namespace strmod {
00059 
00060 class ListeningPlug;
00061 class SocketModuleChunk;
00062 
00063 /** \class SocketModuleChunk SockListenModule.h StrMod/SockListenModule.h
00064  * \brief A special 'zero length' chunk that contains a SocketModule.
00065  *
00066  * This class is sort of a fake class to shove the listening socket into the
00067  * standard StreamModule framework.  The SockListenModule mints SocketModule
00068  * instances, but all the plug definitions require that instances of StrChunk be
00069  * passed between the plugs.  This class wraps a SocketModule in a StrChunk.
00070  * SocketModule's really can't be passed to anywhere outside the process, so all
00071  * the methods for this class are going to act like this SockModuleChunk is
00072  * empty.
00073  */
00074 class SocketModuleChunk : public StrChunk
00075 {
00076  public:
00077    static const STR_ClassIdent identifier;
00078 
00079    //! Creates a SocketModule chunk wrapping SocketModule 'mod'.
00080    explicit SocketModuleChunk(SocketModule *mod) : module_(mod)  { }
00081    //! If 'ReleaseModule' hasn't been called, also deletes wrapped SocketModule
00082    inline virtual ~SocketModuleChunk();
00083 
00084    inline virtual int AreYouA(const lcore::ClassIdent &cid) const;
00085 
00086    virtual unsigned int Length() const                 { return 0; }
00087 
00088    /** Returns the wrapped SocketModule, and possibly forget about its existence.
00089     * @param release If this parameter is true, the SocketModuleChunk forgets
00090     * the wrapped SocketModule and you become responsible for managing its
00091     * existence (ie you must delete it at the proper time).
00092     */
00093    SocketModule *getModule(bool release = true)
00094    {
00095       SocketModule *ret = module_;
00096       if (release)
00097       {
00098          module_ = 0;
00099       }
00100       return ret;
00101    }
00102 
00103  protected:
00104    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00105 
00106    //! Accept a ChunkVisitor, and maybe lead it through your children.
00107    virtual void acceptVisitor(ChunkVisitor &visitor)
00108       throw(ChunkVisitor::halt_visitation)             { }
00109 
00110  private:
00111    SocketModule *module_;
00112 };
00113 
00114 typedef StrChunkPtrT<SocketModuleChunk> SocketModuleChunkPtr;
00115 
00116 //--------------------------SockListenModule class-----------------------------
00117 
00118 /** \class SockListenModule SockListenModule.h StrMod/SockListenModule.h
00119  * \brief A class that accepts connections on a particular socket.
00120  *
00121  * This class creates instances of SocketModules and wraps them up in a
00122  * SocketModuleChunk.
00123  */
00124 class SockListenModule : public StreamModule {
00125    class FDPollEv;
00126    friend class FDPollEv;
00127    class FDPollRdEv;
00128    friend class FDPollRdEv;
00129    class FDPollErEv;
00130    friend class FDPollErEv;
00131 
00132  public:
00133    class SLPlug;  // Declared at end of public section for clarity.
00134    friend class SLPlug;
00135    static const STR_ClassIdent identifier;
00136 
00137    /** \brief What address am I going to listen on, and what's the length of
00138     * the pending connection queue?
00139     */
00140    SockListenModule(const ehnet::SocketAddress &bind_addr,
00141                     unievent::Dispatcher &disp,
00142                     unievent::UnixEventRegistry &ureg,
00143                     int qlen = 1);
00144    //! Closes the socket being listened to.
00145    virtual ~SockListenModule();
00146 
00147    inline virtual int AreYouA(const lcore::ClassIdent &cid) const;
00148 
00149    inline virtual bool canCreate(int side = 0) const;
00150    inline SLPlug *makePlug(int side = 0);
00151    inline virtual bool ownsPlug(const Plug *plug) const;
00152    inline virtual bool deletePlug(Plug *plug);
00153 
00154    //! Has there been an error of any kind?
00155    bool hasError() const throw()               { return has_error_; }
00156    //! What was the error, if any?
00157    const unievent::UNIXError &getError() const throw();
00158    //! Pretend no error happened.
00159    void clearError() throw();
00160 
00161    //! What's the local address for this socket?
00162    const ehnet::SocketAddress &GetBoundAddress() const { return(myaddr_); }
00163 
00164    /** \class SLPlug SockListenModule.h StrMod/SockListenModule.h
00165     * \brief A plug from a SockListenModule.
00166     */
00167    class SLPlug : public StreamModule::Plug {
00168       friend class SockListenModule;
00169 
00170     public:
00171       static const STR_ClassIdent identifier;
00172 
00173       inline virtual int AreYouA(const lcore::ClassIdent &cid) const;
00174 
00175       inline SockListenModule &getParent() const;
00176       virtual int side() const                          { return(0); }
00177 
00178       //! Read a socket module chunk, if there is one.
00179       const SocketModuleChunkPtr getConnection();
00180 
00181     protected:
00182       //! Note that this can ONLY be constructed using a SockListenModule
00183       SLPlug(SockListenModule &parent) : Plug(parent)   { }
00184       /** \brief Protected because mere mortals shouldn't just create and
00185        * destroy these things at random.  */
00186       virtual ~SLPlug()                                 { }
00187 
00188       virtual const lcore::ClassIdent *i_GetIdent() const {
00189          return &identifier;
00190       }
00191 
00192       //! Forwards to getParent()->plugRead()
00193       virtual const StrChunkPtr i_Read();
00194       /** \brief A dead operation that either assert fails, or is a no-op that
00195        * throws away its data. */
00196       virtual void i_Write(const StrChunkPtr &ptr);
00197    };
00198 
00199  protected:
00200    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00201 
00202    inline virtual Plug *i_MakePlug(int side);
00203 
00204    /** Make a socket module once I've done the accept.
00205     * Note, ownership of <code>peer</code> is being passed here.
00206     */
00207    inline SocketModule *makeSocketModule(int fd, ehnet::SocketAddress *peer,
00208                                          unievent::Dispatcher &disp,
00209                                          unievent::UnixEventRegistry &ureg);
00210 
00211    //! Set an error so that hasError and getError return something.
00212    inline void setError(const unievent::UNIXError &err) throw();
00213 
00214    //! Return the new module (if any) and try to 'accept' another connection.
00215    SocketModule *getNewModule();
00216 
00217  private:
00218    typedef unievent::Dispatcher Dispatcher;
00219    typedef unievent::UnixEventRegistry UnixEventRegistry;
00220 
00221    int sockfd_;
00222    unsigned char errorstore_[sizeof(unievent::UNIXError)];
00223    bool has_error_;
00224    SLPlug lplug_;
00225    bool plug_pulled_;
00226    bool checking_read_;
00227    SocketModule *newmodule_;
00228    ehnet::SocketAddress &myaddr_;
00229    Dispatcher &disp_;
00230    UnixEventRegistry &ureg_;
00231    FDPollEv *readevptr_;
00232    unievent::EventPtr readev_;
00233    FDPollEv *errorevptr_;
00234    unievent::EventPtr errorev_;
00235 
00236    void eventRead();
00237    void eventError();
00238    void doAccept();
00239 };
00240 
00241 //--------------------SocketModuleChunk inline functions-----------------------
00242 
00243 inline SocketModuleChunk::~SocketModuleChunk()
00244 {
00245    if (module_)
00246    {
00247       delete module_;
00248    }
00249 }
00250 
00251 inline int SocketModuleChunk::AreYouA(const lcore::ClassIdent &cid) const
00252 {
00253    return((identifier == cid) || StrChunk::AreYouA(cid));
00254 }
00255 
00256 // ---------------------SockListenModule inline functions----------------------
00257 
00258 inline int SockListenModule::AreYouA(const lcore::ClassIdent &cid) const
00259 {
00260    return((identifier == cid) || StreamModule::AreYouA(cid));
00261 }
00262 
00263 inline bool SockListenModule::canCreate(int side) const
00264 {
00265    return((side == 0) && !plug_pulled_ && !hasError());
00266 }
00267 
00268 inline SockListenModule::SLPlug *SockListenModule::makePlug(int side)
00269 {
00270    return((SLPlug *)(i_MakePlug(side)));
00271 }
00272 
00273 inline bool SockListenModule::ownsPlug(const Plug *plug) const
00274 {
00275    return(plug_pulled_ && (plug == &lplug_));
00276 }
00277 
00278 inline bool SockListenModule::deletePlug(Plug *plug)
00279 {
00280    if (ownsPlug(plug))
00281    {
00282       lplug_.unPlug();
00283       plug_pulled_ = false;
00284       return(true);
00285    }
00286    else
00287    {
00288       return(false);
00289    }
00290 }
00291 
00292 inline StreamModule::Plug *SockListenModule::i_MakePlug(int side)
00293 {
00294    if (side != 0 || plug_pulled_ || hasError())
00295    {
00296       return(0);
00297    } else {
00298       plug_pulled_ = true;
00299       return(&lplug_);
00300    }
00301 }
00302 
00303 inline SocketModule *
00304 SockListenModule::makeSocketModule(int fd, ehnet::SocketAddress *peer,
00305                                    unievent::Dispatcher &disp,
00306                                    unievent::UnixEventRegistry &ureg)
00307 {
00308    // Ownership of peer is passed here.
00309    return(new SocketModule(fd, peer, disp, ureg));
00310 }
00311 
00312 //----------------------ListeningPlug inline functions-------------------------
00313 
00314 inline int SockListenModule::SLPlug::AreYouA(const lcore::ClassIdent &cid) const
00315 {
00316    return((identifier == cid) || Plug::AreYouA(cid));
00317 }
00318 
00319 inline SockListenModule &SockListenModule::SLPlug::getParent() const
00320 {
00321    return(static_cast<SockListenModule &>(Plug::getParent()));
00322 }
00323 
00324 };  // namespace strmod
00325 };  // namespace strmod
00326 
00327 #endif

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