WvStreams
wvlistener.cc
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * A base implementation for "listeners", streams that spawn other streams
00006  * from (presumably) incoming connections.
00007  */ 
00008 #include "wvlistener.h"
00009 #include "wvistreamlist.h"
00010 #include "wvaddr.h"
00011 #include "wvmoniker.h"
00012 
00013 UUID_MAP_BEGIN(WvListener)
00014   UUID_MAP_ENTRY(IObject)
00015   UUID_MAP_ENTRY(IWvStream)
00016   UUID_MAP_ENTRY(IWvListener)
00017   UUID_MAP_END
00018 
00019 
00020 IWvListener *IWvListener::create(WvString moniker, IObject *obj)
00021 {
00022     IWvListener *l = wvcreate<IWvListener>(moniker, obj);
00023     if (!l)
00024     {
00025         l = new WvNullListener();
00026         l->seterr_both(EINVAL, "Unknown moniker '%s'", moniker);
00027     }
00028     return l;
00029 }
00030 
00031 
00032 WvListener::WvListener(IWvStream *_cloned)
00033 {
00034     cloned = _cloned;
00035     wrapper = 0;
00036 }
00037     
00038 
00039 WvListener::~WvListener()
00040 {
00041     if (cloned)
00042         WVRELEASE(cloned);
00043     WvIStreamList::globallist.unlink(this);
00044 }
00045 
00046 
00047 static IWvStream *wrapper_runner(IWvListenerWrapper wrapper,
00048                                  IWvStream *s)
00049 {
00050     return wrapper(s);
00051 }
00052 
00053 
00054 void WvListener::addwrap(IWvListenerWrapper _wrapper)
00055 {
00056     // What the heck is this, you ask?
00057     // The idea is that we can support multiple layers of wrappers by
00058     // creating recursive callbacks.  When we add a wrapper and one already
00059     // exists, we want to create a new one to essentially do newer(older(s))
00060     // ...but only when it finally gets called.
00061     if (wrapper)
00062         wrapper = wv::bind(&wrapper_runner, _wrapper, _1);
00063     else
00064         wrapper = _wrapper;
00065 }
00066 
00067 
00068 void WvListener::callback()
00069 {  
00070     if (acceptor)
00071     {
00072         IWvStream *s = accept();
00073         if (s) acceptor(s);
00074     }
00075 }
00076 
00077 
00078 IWvStream *WvListener::wrap(IWvStream *s)
00079 {
00080     if (wrapper && s)
00081         return wrapper(s);
00082     else
00083         return s;
00084 }
00085     
00086 
00087 IWvListenerCallback WvListener::onaccept(IWvListenerCallback _cb)
00088 {
00089     IWvListenerCallback old = acceptor;
00090     acceptor = _cb;
00091     return old;
00092 }
00093 
00094 
00095 void WvListener::runonce(time_t msec_delay)
00096 {
00097     callback();
00098 }
00099 
00100 
00101 static WvStringAddr nulladdr("ERROR", WvEncap::Unknown);
00102 const WvAddr *WvNullListener::src() const
00103 {
00104     return &nulladdr;
00105 }
00106 
00107 WvString WvListener::getattr(WvStringParm name) const
00108 {
00109     WvString ret = attrs.get(name);
00110     if (ret.isnull() && cloned)
00111         return cloned->getattr(name);
00112 
00113     return ret;
00114 }