/* -*- Mode: C++ -*- * Worldvisions Weaver Software: * Copyright (C) 1997-2002 Net Integration Technologies, Inc. * * A base implementation for "listeners", streams that spawn other streams * from (presumably) incoming connections. */ #include "wvlistener.h" #include "wvistreamlist.h" #include "wvaddr.h" #include "wvmoniker.h" UUID_MAP_BEGIN(WvListener) UUID_MAP_ENTRY(IObject) UUID_MAP_ENTRY(IWvStream) UUID_MAP_ENTRY(IWvListener) UUID_MAP_END IWvListener *IWvListener::create(WvString moniker, IObject *obj) { IWvListener *l = wvcreate(moniker, obj); if (!l) { l = new WvNullListener(); l->seterr_both(EINVAL, "Unknown moniker '%s'", moniker); } return l; } WvListener::WvListener(IWvStream *_cloned) { cloned = _cloned; wrapper = 0; } WvListener::~WvListener() { if (cloned) WVRELEASE(cloned); WvIStreamList::globallist.unlink(this); } static IWvStream *wrapper_runner(IWvListenerWrapper wrapper, IWvStream *s) { return wrapper(s); } void WvListener::addwrap(IWvListenerWrapper _wrapper) { // What the heck is this, you ask? // The idea is that we can support multiple layers of wrappers by // creating recursive callbacks. When we add a wrapper and one already // exists, we want to create a new one to essentially do newer(older(s)) // ...but only when it finally gets called. if (wrapper) wrapper = wv::bind(&wrapper_runner, _wrapper, _1); else wrapper = _wrapper; } void WvListener::callback() { if (acceptor) { IWvStream *s = accept(); if (s) acceptor(s); } } IWvStream *WvListener::wrap(IWvStream *s) { if (wrapper && s) return wrapper(s); else return s; } IWvListenerCallback WvListener::onaccept(IWvListenerCallback _cb) { IWvListenerCallback old = acceptor; acceptor = _cb; return old; } void WvListener::runonce(time_t msec_delay) { callback(); } static WvStringAddr nulladdr("ERROR", WvEncap::Unknown); const WvAddr *WvNullListener::src() const { return &nulladdr; } WvString WvListener::getattr(WvStringParm name) const { WvString ret = attrs.get(name); if (ret.isnull() && cloned) return cloned->getattr(name); return ret; }