diff options
Diffstat (limited to 'mcop')
81 files changed, 19737 insertions, 0 deletions
diff --git a/mcop/Makefile.am b/mcop/Makefile.am new file mode 100644 index 0000000..72fc23b --- /dev/null +++ b/mcop/Makefile.am @@ -0,0 +1,33 @@ + +AM_CPPFLAGS = -DEXTENSION_DIR='"$(libdir)"' -DTRADER_DIR='"$(libdir)/mcop"' +## +lib_LTLIBRARIES = libmcop.la +# +# Programs to compile, Manpages to install and Versions +# +INCLUDES = -I$(top_srcdir)/libltdl $(all_includes) +libmcop_la_SOURCES = buffer.cc connection.cc core.cc debug.cc dispatcher.cc \ + iomanager.cc object.cc socketconnection.cc tcpconnection.cc \ + unixconnection.cc tcpserver.cc unixserver.cc objectmanager.cc \ + factory.cc idlfilereg.cc ifacerepo_impl.cc mcoputils.cc \ + startupmanager.cc md5.c md5auth.cc referenceclean.cc datapacket.cc \ + asyncstream.cc notification.cc flowsystem.cc extensionloader.cc \ + tmpglobalcomm.cc mcopconfig.cc connect.cc reference.cc type.cc \ + trader_impl.cc dynamicrequest.cc anyref.cc loopback.cc \ + delayedreturn.cc thread.cc dynamicskeleton.cc + +libmcop_la_LIBADD = $(LIBSOCKET) $(GLIB_LIBADD) $(top_builddir)/libltdl/libltdlc.la +libmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(GLIB_LDFLAGS) $(all_libraries) + +artsincludedir = $(includedir)/arts +artsinclude_HEADERS = arts_export.h buffer.h common.h connection.h core.h dispatcher.h \ + factory.h flowsystem.h idlfilereg.h ifacerepo_impl.h iomanager.h \ + mcoputils.h object.h objectmanager.h pool.h socketconnection.h \ + startupmanager.h tcpconnection.h tcpserver.h type.h unixconnection.h \ + unixserver.h referenceclean.h datapacket.h asyncstream.h notification.h \ + extensionloader.h mcopconfig.h connect.h reference.h weakreference.h \ + dynamicrequest.h anyref.h debug.h delayedreturn.h dynamicskeleton.h thread.h \ + core.idl + +core: $(srcdir)/core.idl $(MCOPIDL) + $(MCOPIDL) -e Arts::Object -I$(srcdir) $(srcdir)/core.idl diff --git a/mcop/anyref.cc b/mcop/anyref.cc new file mode 100644 index 0000000..9ea434b --- /dev/null +++ b/mcop/anyref.cc @@ -0,0 +1,310 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "anyref.h" +#include "common.h" +#include "startupmanager.h" +#include "debug.h" +#include <assert.h> + +using namespace Arts; +using namespace std; + +/* + * private utility class to deal with any types + */ +namespace Arts { + static class AnyRefHelper { + private: + Arts::InterfaceRepoV2 interfaceRepo; + + public: + AnyRefHelper() { + interfaceRepo = DynamicCast(Dispatcher::the()->interfaceRepo()); + } + void skipType(Buffer& buffer, const string& type); + } *anyRefHelper = 0; + + static class AnyRefHelperStartup : public StartupClass { + void startup() { + assert(anyRefHelper == 0); + anyRefHelper = new AnyRefHelper(); + } + void shutdown() { + delete anyRefHelper; + anyRefHelper = 0; + } + } The_AnyRefHelperStartup; +} + +string AnyRefBase::type() const +{ +/* + keep common types here, so that the string constructor doesn't need + to get called each and every time + */ + static const string tVoid("void"); + static const string tByte("byte"); + static const string tsByte("*byte"); + static const string tLong("long"); + static const string tsLong("*long"); + static const string tFloat("float"); + static const string tsFloat("*float"); + static const string tString("string"); + static const string tsString("*string"); + static const string tBool("bool"); + static const string tsBool("*bool"); + + switch(rep) + { + case repVoid: return tVoid; + + // primitive types + case repByte: return tByte; + case repInt: + case repLong: return tLong; + case repFloat: + case repDouble: return tFloat; + case repString: + case repCString: return tString; + case repBool: return tBool; + + // sequences of primitive types + case repByteSeq: return tsByte; + case repLongSeq: return tsLong; + case repFloatSeq: return tsFloat; + case repStringSeq: return tsString; + case repBoolSeq: return tsBool; + + case repAny: return ((Any *)data)->type; + } + assert(false); + return tVoid; // silence compiler +} + +void AnyRefBase::_write(Buffer *b) const +{ + switch(rep) + { + case repVoid: + break; + + // primitive types + case repByte: b->writeByte(*(mcopbyte *)data); + break; + + case repInt: b->writeLong(*(int *)data); + break; + + case repLong: b->writeLong(*(long *)data); + break; + + case repFloat: b->writeFloat(*(float *)data); + break; + + case repDouble: b->writeFloat(*(double *)data); + break; + + case repString: b->writeString(*(string *)data); + break; + + case repCString: b->writeString((const char *)data); + break; + + case repBool: b->writeBool(*(bool *)data); + break; + + // sequences of primitive types + case repByteSeq: b->writeByteSeq(*(vector<mcopbyte> *)data); + break; + + case repLongSeq: b->writeLongSeq(*(vector<long> *)data); + break; + + case repFloatSeq: b->writeFloatSeq(*(vector<float> *)data); + break; + + case repStringSeq: b->writeStringSeq(*(vector<string> *)data); + break; + + case repBoolSeq: b->writeBoolSeq(*(vector<bool> *)data); + break; + + case repAny: b->write(((Any *)data)->value); + break; + + default: assert(false); + } +} + +void AnyRefBase::_read(Buffer *b) const +{ + switch(rep) + { + case repVoid: + break; + + // primitive types + case repByte: *(mcopbyte *)data = b->readByte(); + break; + + case repInt: *(int *)data = b->readLong(); + break; + + case repLong: *(long *)data = b->readLong(); + break; + + case repFloat: *(float *)data = b->readFloat(); + break; + + case repDouble: *(double *)data = b->readFloat(); + break; + + case repString: b->readString(*(string *)data); + break; + + case repBool: *(bool *)data = b->readBool(); + break; + + // sequences of primitive types + case repByteSeq: b->readByteSeq(*(vector<mcopbyte> *)data); + break; + + case repLongSeq: b->readLongSeq(*(vector<long> *)data); + break; + + case repFloatSeq: b->readFloatSeq(*(vector<float> *)data); + break; + + case repStringSeq: b->readStringSeq(*(vector<string> *)data); + break; + + case repBoolSeq: b->readBoolSeq(*(vector<bool> *)data); + break; + + case repAny: + { + // find out the size by skipping over it for the first time + long startPos = b->size() - b->remaining(); + anyRefHelper->skipType(*b, ((Any *)data)->type); + + // if everything went well, read the raw value in one step + long size = (b->size() - b->remaining()) - startPos; + if(!b->readError()) + { + b->rewind(); + b->skip(startPos); + b->read(((Any *)data)->value, size); + } + } + break; + + default: assert(false); + } +} + +/** + * correct skipping of an arbitary type not known at compile-time (this is + * a problem, since the size of the type will vary, due to the sequence<...>s + * contained) + */ +void AnyRefHelper::skipType(Buffer& buffer, const string& type) +{ + /* sequences */ + if(type[0] == '*') + { + long seqlen = buffer.readLong(); + while(seqlen > 0 && !buffer.readError()) + { + skipType(buffer, type.c_str()+1); + seqlen--; + } + } + else + { + TypeIdentification ti = interfaceRepo.identifyType(type); + switch(ti) + { + case tiString: + { + string s; + buffer.readString(s); + } + break; + + case tiLong: + buffer.readLong(); + break; + + case tiFloat: + buffer.readFloat(); + break; + + case tiByte: + buffer.readByte(); + break; + + case tiBoolean: + buffer.readBool(); + break; + + case tiVoid: + /* nothing to do */ + break; + + case tiType: + { + Arts::TypeDef td = interfaceRepo.queryType(type); + + if(td.name == type) + { + vector<TypeComponent>::iterator tci; + for(tci = td.contents.begin(); tci != td.contents.end(); + tci++) + { + skipType(buffer,tci->type); + } + } + else + { + arts_warning("unknown type %s",type.c_str()); + } + } + break; + + case tiEnum: + buffer.readLong(); + break; + + case tiInterface: + { + ObjectReference oref; + oref.readType(buffer); + } + break; + + default: + arts_warning("AnyRefHelper: can't read %s",type.c_str()); + break; + } + } +} diff --git a/mcop/anyref.h b/mcop/anyref.h new file mode 100644 index 0000000..688f9db --- /dev/null +++ b/mcop/anyref.h @@ -0,0 +1,146 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef MCOP_ANYREF_H +#define MCOP_ANYREF_H + +#include "buffer.h" +#include <string> +#include "arts_export.h" +/* + * BC - Status (2002-03-08): AnyRefBase, AnyRef, AnyConstRef + * + * These classes will be kept binary compatibile. To change it, adding a new + * representation is necessary. No private d pointer for this reason. + */ + +namespace Arts { + +class Any; +class ARTS_EXPORT AnyRefBase { +protected: + void *data; + + /* + * This is used for specifying which is the content of a sequence or + * an enum or similar. For normal types, it remains unset, as their + * name can be generated from rep. + */ + std::string _type; + + /* + * What representation data is pointing to? + * + * repInt (int *), repDouble (double *) and repConstChar (const char *) + * are no native MCOP types, but alternative ways or representing the + * native "int", "float" and "const char *" types + */ + + // BC: adding new representations and types is possible, however, existing + // numbers may not be changed + enum Representation { + repVoid = 0, + repByte = 10, + repLong = 20, repInt = 21 /* treated as long */, + repFloat = 30, repDouble = 31 /* treated as float */, + repString = 40, repCString = 41 /* string */, + repBool = 50, + repByteSeq = 510, + repLongSeq = 520, + repFloatSeq = 530, + repStringSeq = 540, + repBoolSeq = 550, + repAny = 1000 /* may hold any type */ + } rep; + + void _write(Buffer *b) const; + void _read(Buffer *b) const; + + AnyRefBase(const void *data, Representation rep) + : data(const_cast<void *>(data)), rep(rep) { }; + AnyRefBase(const void *data, Representation rep, const char *type) + : data(const_cast<void *>(data)), _type(type), rep(rep) { }; + AnyRefBase(const AnyRefBase ©) + : data(copy.data), _type(copy._type), rep(copy.rep) { } +public: + std::string type() const; +}; + +class ARTS_EXPORT AnyConstRef : public AnyRefBase { +public: + AnyConstRef() : AnyRefBase(0,repVoid) { }; + AnyConstRef(const mcopbyte& value) : AnyRefBase(&value,repByte) { }; + AnyConstRef(const int& value) : AnyRefBase(&value,repInt) { }; + AnyConstRef(const long& value) : AnyRefBase(&value,repLong) { }; + AnyConstRef(const float& value) : AnyRefBase(&value,repFloat) { }; + AnyConstRef(const double& value) : AnyRefBase(&value,repDouble) { }; + AnyConstRef(const std::string& value) : AnyRefBase(&value,repString) { }; + AnyConstRef(const char *value) : AnyRefBase(value,repCString) { }; + AnyConstRef(const bool& value) : AnyRefBase(&value,repBool) { }; + + AnyConstRef(const std::vector<mcopbyte>& v) + : AnyRefBase(&v,repByteSeq) { }; + AnyConstRef(const std::vector<long>& v) + : AnyRefBase(&v,repLongSeq) { }; + AnyConstRef(const std::vector<float>& v) + : AnyRefBase(&v,repFloatSeq) { }; + AnyConstRef(const std::vector<std::string>& v) + : AnyRefBase(&v,repStringSeq) { }; + AnyConstRef(const std::vector<bool>& v) + : AnyRefBase(&v,repBoolSeq) { }; + + AnyConstRef(const Any& value) : AnyRefBase(&value,repAny) { }; + + AnyConstRef(const AnyConstRef& ref) : AnyRefBase(ref) { } + void write(Buffer *b) const { _write(b); } +}; + +class ARTS_EXPORT AnyRef : public AnyRefBase { +public: + AnyRef() : AnyRefBase(0,repVoid) { }; + + // primitive types + AnyRef(mcopbyte& value) : AnyRefBase(&value,repByte) { }; + AnyRef(int& value) : AnyRefBase(&value,repInt) { }; + AnyRef(long& value) : AnyRefBase(&value,repLong) { }; + AnyRef(float& value) : AnyRefBase(&value,repFloat) { }; + AnyRef(double& value) : AnyRefBase(&value,repDouble) { }; + AnyRef(std::string& value) : AnyRefBase(&value,repString) { }; + AnyRef(bool& value) : AnyRefBase(&value,repBool) { }; + + // sequence of primitive types + AnyRef(std::vector<mcopbyte>& value) : AnyRefBase(&value,repByteSeq) { }; + AnyRef(std::vector<long>& value) : AnyRefBase(&value,repLongSeq) { }; + AnyRef(std::vector<float>& value) : AnyRefBase(&value,repFloatSeq) { }; + AnyRef(std::vector<std::string>& value) : AnyRefBase(&value,repStringSeq){}; + AnyRef(std::vector<bool>& value) : AnyRefBase(&value,repBoolSeq){}; + + AnyRef(Any& value) : AnyRefBase(&value,repAny) { }; + + AnyRef(const AnyRef& ref) : AnyRefBase(ref) { } + + void read(Buffer *b) const { _read(b); } + void write(Buffer *b) const { _write(b); } +}; + +} +#endif /* MCOP_ANYREF_H */ diff --git a/mcop/arts_export.h.in b/mcop/arts_export.h.in new file mode 100644 index 0000000..4de637e --- /dev/null +++ b/mcop/arts_export.h.in @@ -0,0 +1,53 @@ +/* This file is part of the KDE libraries + Copyright (c) 2002-2003 KDE Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef ARTS_EXPORT_H +#define ARTS_EXPORT_H + +#undef __KDE_HAVE_GCC_VISIBILITY + +/** + * The ARTS_NO_EXPORT macro marks the symbol of the given variable + * to be hidden. A hidden symbol is stripped during the linking step, + * so it can't be used from outside the resulting library, which is similar + * to static. However, static limits the visibility to the current + * compilation unit. hidden symbols can still be used in multiple compilation + * units. + * + * \code + * int ARTS_NO_EXPORT foo; + * int ARTS_EXPORT bar; + * \end + */ + +#if defined(__KDE_HAVE_GCC_VISIBILITY) +/* Visibility is available for GCC newer than 3.4. + * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9283 + */ +#define ARTS_NO_EXPORT __attribute__ ((visibility("hidden"))) +#define ARTS_EXPORT __attribute__ ((visibility("default"))) +#elif defined(_WIN32) +#define ARTS_NO_EXPORT +#define ARTS_EXPORT __declspec(dllexport) +#else +#define ARTS_NO_EXPORT +#define ARTS_EXPORT +#endif + +#endif /* ARTS_EXPORTS */ diff --git a/mcop/asyncstream.cc b/mcop/asyncstream.cc new file mode 100644 index 0000000..a623353 --- /dev/null +++ b/mcop/asyncstream.cc @@ -0,0 +1,46 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "asyncstream.h" +#include "datapacket.h" + +using namespace Arts; + +DataPacket<float> *FloatAsyncStream::allocPacket(int capacity) +{ + return new FloatDataPacket(capacity,channel); +} + +GenericAsyncStream *FloatAsyncStream::createNewStream() +{ + return new FloatAsyncStream(); +} + +DataPacket<mcopbyte> *ByteAsyncStream::allocPacket(int capacity) +{ + return new ByteDataPacket(capacity,channel); +} + +GenericAsyncStream *ByteAsyncStream::createNewStream() +{ + return new ByteAsyncStream(); +} diff --git a/mcop/asyncstream.h b/mcop/asyncstream.h new file mode 100644 index 0000000..8d0a603 --- /dev/null +++ b/mcop/asyncstream.h @@ -0,0 +1,103 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ASYNCSTREAM_H +#define ASYNCSTREAM_H + +#include "arts_export.h" +#include "buffer.h" +#include "datapacket.h" + +/* + * BC - Status (2002-03-08): GenericAsyncStream, AsyncStream, + * FloatAsyncStream/ByteAsyncStream + * + * These classes are to be treated with extreme care, as they are used in + * all kinds of relations with the flow system and the generated code. Do + * NOT touch unless you REALLY know what you are doing. For further + * extensibility, GenericAsyncStream features a private d pointer. + */ + +namespace Arts { + +class GenericAsyncStreamPrivate; + +class ARTS_EXPORT GenericAsyncStream { +private: + GenericAsyncStreamPrivate *d; // unused +public: + /** + * interface to create packets and to get rid of them + */ + virtual GenericDataPacket *createPacket(int capacity) = 0; + virtual void freePacket(GenericDataPacket *packet) = 0; + + virtual GenericAsyncStream *createNewStream() = 0; + + GenericDataChannel *channel; + int _notifyID; + + inline int notifyID() { return _notifyID; } +}; + +template<class T> +class AsyncStream : public GenericAsyncStream { +protected: + GenericDataPacket *createPacket(int capacity) + { + return allocPacket(capacity); + } + void freePacket(GenericDataPacket *packet) + { + delete packet; + } +public: + // for outgoing streams + virtual DataPacket<T> *allocPacket(int capacity) = 0; + + inline void setPull(int packets, int capacity) + { + channel->setPull(packets,capacity); + } + inline void endPull() + { + channel->endPull(); + } +}; + +class ARTS_EXPORT FloatAsyncStream : public AsyncStream<float> +{ +public: + DataPacket<float> *allocPacket(int capacity); + GenericAsyncStream *createNewStream(); +}; + +class ARTS_EXPORT ByteAsyncStream : public AsyncStream<mcopbyte> +{ +public: + DataPacket<mcopbyte> *allocPacket(int capacity); + GenericAsyncStream *createNewStream(); +}; + +} + +#endif /* ASYNCSTREAM_H */ diff --git a/mcop/buffer.cc b/mcop/buffer.cc new file mode 100644 index 0000000..de21b3e --- /dev/null +++ b/mcop/buffer.cc @@ -0,0 +1,386 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "buffer.h" +#include <assert.h> +#include <string.h> + +using namespace std; +using namespace Arts; + +Buffer::Buffer() : rpos(0), _readError(false),d(0) +{ + contents.reserve(128); +} + +Buffer::~Buffer() +{ +} + +long Buffer::size() +{ + return contents.size(); +} + +long Buffer::remaining() +{ + return size()-rpos; +} + +bool Buffer::readError() { + return _readError; +} + +void Buffer::writeBool(bool b) { + contents.push_back(b?1:0); +} + +void Buffer::writeByte(mcopbyte b) { + contents.push_back(b); +} + +void Buffer::writeLong(long l) { + contents.push_back((l >> 24) & 0xff); + contents.push_back((l >> 16) & 0xff); + contents.push_back((l >> 8) & 0xff); + contents.push_back(l & 0xff); +} + +void Buffer::writeBoolSeq(const vector<bool>& seq) { + writeLong(seq.size()); + + vector<bool>::const_iterator i; + for(i = seq.begin(); i != seq.end(); i++) writeBool(*i); +} + +void Buffer::writeByteSeq(const vector<mcopbyte>& seq) { + writeLong(seq.size()); // bytes are sent raw, so we can call read here + write(seq); +} + +void Buffer::writeLongSeq(const vector<long>& seq) { + writeLong(seq.size()); + + vector<long>::const_iterator i; + for(i = seq.begin(); i != seq.end(); i++) writeLong(*i); +} + +void Buffer::writeFloat(float f) { + // FIXME: on some machines this may fail badly (there is explicit + // float marshalling and demarshalling code in mico/orb/util.cc) + union { float f; long l; } u = {f}; + writeLong(u.l); +} + +void Buffer::writeFloatSeq(const std::vector<float>& seq) { + writeLong(seq.size()); + + vector<float>::const_iterator i; + for(i = seq.begin(); i != seq.end(); i++) writeFloat(*i); +} + +void Buffer::writeString(const string& s) { + long len = s.size()+1; + + writeLong(len); + contents.insert(contents.end(),reinterpret_cast<const unsigned char*>(s.c_str()), + reinterpret_cast<const unsigned char*>(s.c_str()+len)); +} + +void Buffer::writeStringSeq(const vector<string>& seq) { + writeLong(seq.size()); + + vector<string>::const_iterator i; + for(i = seq.begin(); i != seq.end(); i++) writeString(*i); +} + +void Buffer::write(void *data, long len) { + unsigned char *c = (unsigned char *)data; + + contents.insert(contents.end(),c,c+len); +} + +void Buffer::write(const vector<mcopbyte>& raw) +{ + contents.insert(contents.end(), raw.begin(), raw.end()); +} + +void Buffer::read(vector<mcopbyte>& raw, long l) +{ + if(l >= 0 && remaining() >= l) { + raw.clear(); + raw.insert(raw.end(), contents.begin()+rpos, contents.begin()+rpos+l); + rpos += l; + } else { + _readError = true; + } +} + +void *Buffer::read(long l) { + void *result = 0; + + if(l >= 0 && remaining() >= l) { + result = &contents[rpos]; + rpos += l; + } else { + _readError = true; + } + return result; +} + +void *Buffer::peek(long l) { + assert(l >= 0 && remaining() >= l); + return &contents[rpos]; +} + +void Buffer::skip(long l) { + if(l >= 0 && remaining() >= l) { + rpos += l; + } else { + _readError = true; + } +} + +void Buffer::rewind() { + rpos = 0; +} + +bool Buffer::readBool() +{ + long result = false; + if(remaining() >= 1) { + if(contents[rpos] == 1) + result = true; + else + { + assert(contents[rpos] == 0); + } + rpos += 1; + } else { + _readError = true; + } + return result; +} + +void Buffer::readBoolSeq(vector<bool>& result) +{ + // might be optimizable a bit + long i,seqlen = readLong(); + + result.clear(); + if(seqlen >= 0 && remaining() >= seqlen) + { + for(i=0;i<seqlen;i++) result.push_back(readBool()); + } + else + { + _readError = true; + } +} + + +mcopbyte Buffer::readByte() +{ + if(remaining() >= 1) + { + return contents[rpos++]; + } + else + { + _readError = true; + return 0; + } +} + +void Buffer::readByteSeq(vector<mcopbyte>& result) +{ + long seqlen = readLong(); // bytes are sent raw, so we can call read here + read(result, seqlen); +} + +long Buffer::readLong() +{ + long result = 0; + if(remaining() >= 4) { + result = (contents[rpos] << 24) + + (contents[rpos+1] << 16) + + (contents[rpos+2] << 8) + + contents[rpos+3]; + rpos += 4; + } else { + _readError = true; + } + return result; +} + +void Buffer::readLongSeq(vector<long>& result) +{ + // might be optimizable a bit + long i,seqlen = readLong(); + + result.clear(); + if(seqlen * 4 >= 0 && remaining() >= seqlen * 4) + { + for(i=0;i<seqlen;i++) result.push_back(readLong()); + } + else + { + _readError = true; + } +} + +float Buffer::readFloat() +{ + // FIXME: see writeFloat() + union {float f; long l; } u; + u.l = readLong(); + + if(!_readError) return u.f; + return 0.0; +} + +void Buffer::readFloatSeq(vector<float>& result) +{ + // might be optimizable a bit + long i,seqlen = readLong(); + + result.clear(); + if(seqlen * 4 >= 0 && remaining() >= seqlen * 4) + { + for(i=0;i<seqlen;i++) result.push_back(readFloat()); + } + else + { + _readError = true; + } +} + +void Buffer::readString(string& result) +{ + long len = readLong(); + char *data = (char *)read(len); + + if(data && len) + result.assign(data,len-1); + else + result = ""; +} + +void Buffer::readStringSeq(vector<string>& result) +{ + // might be optimizable a bit + + long i,seqlen = readLong(); + + result.clear(); + //result.reserve(seqlen); + + for(i=0;i<seqlen;i++) { + string s; + + readString(s); + if(_readError) return; + + result.push_back(s); + } +} + + +void Buffer::patchLength() +{ + long len = size(); + assert(len >= 8); + + contents[4] = (len >> 24) & 0xff; + contents[5] = (len >> 16) & 0xff; + contents[6] = (len >> 8) & 0xff; + contents[7] = len & 0xff; +} + +void Buffer::patchLong(long position, long value) +{ + long len = size(); + assert(len >= position+4); + + contents[position] = (value >> 24) & 0xff; + contents[position+1] = (value >> 16) & 0xff; + contents[position+2] = (value >> 8) & 0xff; + contents[position+3] = value & 0xff; +} + +string Buffer::toString(const string& name) +{ + string result; + char hex[17] = "0123456789abcdef"; + + vector<unsigned char>::iterator ci; + for(ci = contents.begin(); ci != contents.end(); ci++) + { + result += hex[(*ci >> 4) & 0xf]; + result += hex[*ci & 0xf]; + } + + if(name.empty()) return result; + return name + ":" + result; +} + +unsigned char Buffer::fromHexNibble(char c) +{ + int uc = (unsigned char)c; + + if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0'; + if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a'; + if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A'; + + return 16; // error +} + +static int stringncmp(const string& s1, const string& s2, size_t n) +{ + // I don't know a way to implement that compliant to all STL string + // implementations (compare seems to work differently sometimes) + return strncmp(s1.c_str(),s2.c_str(),n); +} + +bool Buffer::fromString(const string& data, const string& name) +{ + string start = name+":"; + if(name.empty()) start = ""; + + if(stringncmp(data,start,start.size()) != 0) return false; + contents.clear(); + + string::const_iterator di = data.begin() + start.size(); + + while(di != data.end()) + { + unsigned char h = fromHexNibble(*di++); // high nibble + if(di == data.end()) return false; + + unsigned char l = fromHexNibble(*di++); // low nibble + + if(h >= 16 || l >= 16) return false; // no proper hex digit + contents.push_back((h << 4) + l); + } + return true; +} + diff --git a/mcop/buffer.h b/mcop/buffer.h new file mode 100644 index 0000000..b361092 --- /dev/null +++ b/mcop/buffer.h @@ -0,0 +1,104 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef BUFFER_H +#define BUFFER_H + +#include <string> +#include <vector> +#include "arts_export.h" +/* + * BC - Status (2002-03-08): Buffer. + * + * Has to be kept binary compatible. As buffer is speed relevant, currently + * there are no private d ptrs, and the idea is to keep this as possible. + * + * If not, put additional stuff in the d ptr, but keep as much data as + * possible in the main items. + */ + +namespace Arts { + +#ifndef MCOPBYTE_DEFINED +#define MCOPBYTE_DEFINED +typedef unsigned char mcopbyte; +#endif + +class BufferPrivate; + +class ARTS_EXPORT Buffer { +private: + long rpos; + bool _readError; + std::vector<unsigned char> contents; + + BufferPrivate *d; // unused + unsigned char fromHexNibble(char c); + +public: + Buffer(); + ~Buffer(); + + bool readError(); + void writeBool(bool b); + void writeBoolSeq(const std::vector<bool>& seq); + void writeByte(mcopbyte b); + void writeByteSeq(const std::vector<mcopbyte>& seq); + void writeLong(long l); + void writeLongSeq(const std::vector<long>& seq); + void writeFloat(float f); + void writeFloatSeq(const std::vector<float>& seq); + void writeString(const std::string& s); + void writeStringSeq(const std::vector<std::string>& seq); + + long size(); + long remaining(); + void *read(long l); + void read(std::vector<mcopbyte>& raw, long l); + void *peek(long l); + void skip(long l); + void rewind(); + + void write(void *data, long l); + void write(const std::vector<mcopbyte>& raw); + + bool readBool(); + void readBoolSeq(std::vector<bool>& result); + mcopbyte readByte(); + void readByteSeq(std::vector<mcopbyte>& result); + long readLong(); + void readLongSeq(std::vector<long>& result); + float readFloat(); + void readFloatSeq(std::vector<float>& result); + void readString(std::string& result); + void readStringSeq(std::vector<std::string>& result); + + void patchLength(); + void patchLong(long position, long value); + + std::string toString(const std::string& name); + bool fromString(const std::string& data, const std::string& name); +}; + +} + +#endif diff --git a/mcop/common.h b/mcop/common.h new file mode 100644 index 0000000..4021fb9 --- /dev/null +++ b/mcop/common.h @@ -0,0 +1,141 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef COMMON_H +#define COMMON_H + +#include "buffer.h" +#include "type.h" +#include "dispatcher.h" +#include "object.h" +#include "connection.h" +#include "objectmanager.h" +#include "idlfilereg.h" +#include "asyncstream.h" +#include "mcoputils.h" +#include "anyref.h" +#include "connect.h" + +/* + * BC - Status (2002-03-08): Read/WriteObject(Seq) + * + * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this. + * (Interaction with generated code). + */ + +/* define this to see what mcop transfers around */ +#undef DEBUG_IO + +/* define this to see what mcop messages are processed */ +#undef DEBUG_MESSAGES + +#include "core.h" + +namespace Arts { +/* some marshalling helpers */ + +template<class T> +void readTypeSeq(Buffer& stream, std::vector<T>& sequence) { + sequence.clear(); + + unsigned long l = stream.readLong(); + while(l--) sequence.push_back(T(stream)); +} + +template<class T> +void writeTypeSeq(Buffer& stream, const std::vector<T>& sequence) { + stream.writeLong(sequence.size()); + for(unsigned long l=0;l<sequence.size();l++) + sequence[l].writeType(stream); +} + +template<class T> +void writeObject(Buffer& stream, T* object) { + if(object) + { + /* + * perhaps reimplement directly (without conversion to/from string) + * for more speed + */ + + std::string s = object->_toString(); + + Buffer buffer; + buffer.fromString(s,"MCOP-Object"); + ObjectReference reference(buffer); + + object->_copyRemote(); // prevents that the object is freed for a while + reference.writeType(stream); + } + else + { + ObjectReference null_reference; + + null_reference.serverID = "null"; + null_reference.objectID = 0; + null_reference.writeType(stream); + } +} + +template<class T> +void readObject(Buffer& stream, T*& result) { + ObjectReference reference(stream); + + if(reference.serverID == "null") + result = 0; // null reference? + else + result = T::_fromReference(reference,false); +} + +template<class T> +void readObjectSeq(Buffer& stream, std::vector<T>& sequence) +{ + sequence.clear(); + + unsigned long l = stream.readLong(); + while(l--) + { + typename T::_base_class *temp; + readObject(stream, temp); + sequence.push_back(T::_from_base(temp)); + } +} + +template<class T> +void writeObjectSeq(Buffer& stream, const std::vector<T>& sequence) +{ + stream.writeLong(sequence.size()); + + for(unsigned long l=0;l<sequence.size();l++) + { + T object = sequence[l]; + writeObject(stream,object._base()); + } +} + +#ifndef MCOPBYTE_DEFINED +#define MCOPBYTE_DEFINED +typedef unsigned char mcopbyte; +#endif + +} +#endif diff --git a/mcop/connect.cc b/mcop/connect.cc new file mode 100644 index 0000000..88d5dff --- /dev/null +++ b/mcop/connect.cc @@ -0,0 +1,149 @@ +/* + Copyright (C) 2000 Nicolas Brodu + nicolas.brodu@free.fr + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "connect.h" +#include "flowsystem.h" +#include <assert.h> +#include "debug.h" + +// NDEBUG is the symbol name that can remove the assertions +#ifdef NDEBUG +#define mywarning(a,b) +#else +#include <iostream> +#define mywarning(a,b) if (!(a)) arts_warning("MCOP connection warning: %s",b) +#endif + +using namespace std; + +namespace Arts { + +// Connect function overloaded for objects with default port +void connect(const Object& src, const std::string& output, const Object& dest, const std::string& input) +{ + ScheduleNode *node = src._node(); + assert(node); + node->connect(output, dest._node(), input); +} + +void connect(const Object& src, const string& output, const Object& dest) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsIn = dest._defaultPortsIn(); + mywarning(portsIn.size() == 1, "default input not found in void connect(const Object& src, const string& output, const Object& dest);"); + node->connect(output, dest._node(), portsIn[0]); +} + +void connect(const Object& src, const Object& dest, const string& input) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsOut = src._defaultPortsOut(); + mywarning(portsOut.size() == 1, "default output not found in void connect(const Object& src, const Object& dest, const string& input);"); + node->connect(portsOut[0], dest._node(), input); +} + +void connect(const Object& src, const Object& dest) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsOut = src._defaultPortsOut(); + vector<std::string> portsIn = dest._defaultPortsIn(); + mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void connect(const Object& src, const Object& dest);"); + mywarning(!portsOut.empty(), "no defaults for src and dest in void connect(const Object& src, const Object& dest);"); + vector<std::string>::iterator ot = portsOut.begin(); + vector<std::string>::iterator it = portsIn.begin(); + for (; ot != portsOut.end(); it++, ot++) { + node->connect(*ot, dest._node(), *it); + } +} + +void disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input) +{ + ScheduleNode *node = src._node(); + assert(node); + node->disconnect(output, dest._node(), input); +} + +void disconnect(const Object& src, const string& output, const Object& dest) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsIn = dest._defaultPortsIn(); + mywarning(portsIn.size() == 1, "default input not found in void disconnect(const Object& src, const string& output, const Object& dest);"); + node->disconnect(output, dest._node(), portsIn[0]); +} + +void disconnect(const Object& src, const Object& dest, const string& input) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsOut = src._defaultPortsOut(); + mywarning(portsOut.size() == 1, "default output not found in void disconnect(const Object& src, const Object& dest, const string& input);"); + node->disconnect(portsOut[0], dest._node(), input); +} + +void disconnect(const Object& src, const Object& dest) +{ + ScheduleNode *node = src._node(); + assert(node); + vector<std::string> portsOut = src._defaultPortsOut(); + vector<std::string> portsIn = dest._defaultPortsIn(); + mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void disconnect(const Object& src, const Object& dest);"); + mywarning(!portsOut.empty(), "no defaults for src and dest in void disconnect(const Object& src, const Object& dest);"); + vector<std::string>::iterator ot = portsOut.begin(); + vector<std::string>::iterator it = portsIn.begin(); + for (; ot != portsOut.end(); it++, ot++) { + node->disconnect(*ot, dest._node(), *it); + } +} + +// setValue function overloaded for objects with default port +void setValue(const Object& c, const std::string& port, const float fvalue) +{ + ScheduleNode *node = c._node(); + assert(node); + node->setFloatValue(port, fvalue); +} + +void setValue(const Object& c, const float fvalue) +{ + ScheduleNode *node = c._node(); + assert(node); + vector<std::string> portsIn = c._defaultPortsIn(); + mywarning(!portsIn.empty(), "c has no default ports in void setValue(const Object& c, const float fvalue);"); + vector<std::string>::iterator it = portsIn.begin(); + for (; it != portsIn.end(); it++) { + node->setFloatValue(*it, fvalue); + } +} + +/* String values??? +void setValue(Object& c, const string& port, const string& svalue) +{ +} + +void setValue(Object& c, const string& svalue) +{ +} +*/ + +} diff --git a/mcop/connect.h b/mcop/connect.h new file mode 100644 index 0000000..f9db8b5 --- /dev/null +++ b/mcop/connect.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2000 Nicolas Brodu + nicolas.brodu@free.fr + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef MCOP_CONNECT_H +#define MCOP_CONNECT_H + +/* + * BC - Status (2002-03-08): connect / setValue functions + * + * Will be kept as they are (binary compatible). + */ + +#include <string> +#include "arts_export.h" + +namespace Arts { +class Object; + +// Connect function overloaded for components with default port +void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest, const std::string& input); +void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest); +void ARTS_EXPORT connect(const Object& src, const Object& dest, const std::string& input); +void ARTS_EXPORT connect(const Object& src, const Object& dest); +// Same for disconnect function +void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input); +void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest); +void ARTS_EXPORT disconnect(const Object& src, const Object& dest, const std::string& input); +void ARTS_EXPORT disconnect(const Object& src, const Object& dest); + +// setValue function overloaded for components with default port +void ARTS_EXPORT setValue(const Object& c, const std::string& port, const float fvalue); +void ARTS_EXPORT setValue(const Object& c, const float fvalue); +//void setValue(const Object& c, const std::string& port, const std::string& svalue); +//void setValue(const Object& c, const std::string& svalue); + +} + +#endif diff --git a/mcop/connection.cc b/mcop/connection.cc new file mode 100644 index 0000000..49221f9 --- /dev/null +++ b/mcop/connection.cc @@ -0,0 +1,196 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "connection.h" +#include "dispatcher.h" +#include "debug.h" +#include <stdio.h> +#include <string.h> // for Solaris +#include <queue> +#include <algorithm> + +using namespace Arts; +using namespace std; + +namespace Arts { +class ConnectionPrivate { +public: + struct Data { + Data() : data(0), len(0) { } + Data(unsigned char *data, long len) : data(data), len(len) { } + Data(const Data& d) : data(d.data), len(d.len) { } + unsigned char *data; + long len; + }; + + queue<Data> incoming; + map<string,string> hints; +}; +} + +Connection::Connection() :d(new ConnectionPrivate), _refCnt(1) +{ + _connState = unknown; +} + +Connection::~Connection() +{ + assert(d->incoming.empty()); + assert(_refCnt == 0); + + delete d; +} + +void Connection::_copy() +{ + assert(_refCnt > 0); + _refCnt++; +} + +void Connection::_release() +{ + assert(_refCnt > 0); + _refCnt--; + if(_refCnt == 0) + delete this; +} + +void Connection::initReceive() +{ + rcbuf = 0; + receiveHeader = true; + remaining = 12; +} + +void Connection::receive(unsigned char *newdata, long newlen) +{ + /* + * protect against being freed while receive is running, as there are a + * few points where reentrant event loops may happen (Dispatcher::handle) + */ + _copy(); + + d->incoming.push(ConnectionPrivate::Data(newdata,newlen)); + + do + { + ConnectionPrivate::Data &data = d->incoming.front(); + + // get a buffer for the incoming message + if(!rcbuf) rcbuf = new Buffer; + + // put a suitable amount of input data into the receive buffer + long len = min(remaining, data.len); + + remaining -= len; + rcbuf->write(data.data,len); + + data.len -= len; + data.data += len; + + if(data.len == 0) + d->incoming.pop(); + + // look if it was enough to do something useful with it + if(remaining == 0) + { + if(receiveHeader) + { + long mcopMagic; + + mcopMagic = rcbuf->readLong(); + remaining = rcbuf->readLong() - 12; + messageType = rcbuf->readLong(); + + if(_connState != Connection::established + && (remaining >= 4096 || remaining < 0)) + { + /* + * don't accept large amounts of data on unauthenticated + * connections + */ + remaining = 0; + } + + if(mcopMagic == MCOP_MAGIC) + { + // do we need to receive more data (message body?) + if(remaining) + { + receiveHeader = false; + } + else + { + Buffer *received = rcbuf; + initReceive(); + Dispatcher::the()->handle(this,received,messageType); + } + } + else + { + initReceive(); + Dispatcher::the()->handleCorrupt(this); + } + } + else + { + Buffer *received = rcbuf; + + /* + * it's important to prepare to receive new messages *before* + * calling Dispatcher::the()->handle(...), as handle may + * get into an I/O situation (e.g. when doing an invocation + * itself), and we may receive more messages while handle is + * running + */ + initReceive(); + + // rcbuf is consumed by the dispatcher + Dispatcher::the()->handle(this,received,messageType); + } + } + } while(!d->incoming.empty()); + + _release(); +} + +void Connection::setHints(const vector<string>& hints) +{ + vector<string>::const_iterator i; + + for(i = hints.begin(); i != hints.end(); i++) + { + string key; + vector<string> values; + + if(MCOPUtils::tokenize(*i, key, values)) + { + if(values.size() == 1) + d->hints[key] = values[0]; + } + } +} + +string Connection::findHint(const string& hint) +{ + return d->hints[hint]; +} diff --git a/mcop/connection.h b/mcop/connection.h new file mode 100644 index 0000000..db7edf0 --- /dev/null +++ b/mcop/connection.h @@ -0,0 +1,100 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef CONNECTION_H +#define CONNECTION_H + +#include "arts_export.h" +#include "buffer.h" + +/* + * BC - Status (2002-03-08): Connection. + * + * None of these classes is considered part of the public API. However, they + * NEED to be kept binary compatible as the DO interact with generated code. + * + * Especially virtual functions and stuff can't be added, if you need to, + * you need to add classes parallel to the Connection hierarchy. + */ + +namespace Arts { + +class ConnectionPrivate; + +class ARTS_EXPORT Connection { +private: + ConnectionPrivate *d; // unused +public: + enum ConnectionState { + unknown = 0, + expectServerHello = 1, + expectClientHello = 2, + expectAuthAccept = 3, + established = 4 + }; +protected: + Buffer *rcbuf; + bool receiveHeader; + long remaining; + long messageType; + ConnectionState _connState; + std::string serverID; + std::string _cookie; + + long _refCnt; + + /** + * If you don't want to handle message fragmentation yourself: + * + * Call initReceive in your derived Connection constructor, ald + * receive as soon as you receive some data - the connection object + * will handle the rest (put the messages into buffers and send them + * to the dispatcher) + */ + void initReceive(); + void receive(unsigned char *data, long len); + + virtual ~Connection(); +public: + Connection(); + + inline void setServerID(const std::string& _serverID) { serverID = _serverID; } + inline bool isConnected(const std::string& s) { return (serverID == s); } + inline void setConnState(ConnectionState cs) { _connState = cs; }; + + inline std::string cookie() { return _cookie; } + void setCookie(const std::string& c) { _cookie = c; } + void setHints(const std::vector<std::string>& hints); + std::string findHint(const std::string& name); + + inline ConnectionState connState() { return _connState; }; + virtual void drop() = 0; + virtual bool broken() = 0; + virtual void qSendBuffer(Buffer *buffer) = 0; + + void _release(); + void _copy(); +}; + +} + +#endif diff --git a/mcop/core.cc b/mcop/core.cc new file mode 100644 index 0000000..b0d48eb --- /dev/null +++ b/mcop/core.cc @@ -0,0 +1,3191 @@ +/* this file was generated by the MCOP idl compiler - DO NOT EDIT */ + +#include "common.h" + +// Implementation +Arts::Header::Header() +{ +} + +Arts::Header::Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType) +{ + this->magic = _a_magic; + this->messageLength = _a_messageLength; + this->messageType = _a_messageType; +} + +Arts::Header::Header(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::Header::Header(const Arts::Header& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::Header& Arts::Header::operator=(const Arts::Header& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::Header::readType(Arts::Buffer& stream) +{ + magic = (Arts::HeaderMagic)stream.readLong(); + messageLength = stream.readLong(); + messageType = (Arts::MessageType)stream.readLong(); +} + +void Arts::Header::writeType(Arts::Buffer& stream) const +{ + stream.writeLong(magic); + stream.writeLong(messageLength); + stream.writeLong(messageType); +} + +std::string Arts::Header::_typeName() const +{ + return "Arts::Header"; +} + +Arts::Invocation::Invocation() +{ +} + +Arts::Invocation::Invocation(long _a_objectID, long _a_methodID, long _a_requestID) +{ + this->objectID = _a_objectID; + this->methodID = _a_methodID; + this->requestID = _a_requestID; +} + +Arts::Invocation::Invocation(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::Invocation::Invocation(const Arts::Invocation& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::Invocation& Arts::Invocation::operator=(const Arts::Invocation& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::Invocation::readType(Arts::Buffer& stream) +{ + objectID = stream.readLong(); + methodID = stream.readLong(); + requestID = stream.readLong(); +} + +void Arts::Invocation::writeType(Arts::Buffer& stream) const +{ + stream.writeLong(objectID); + stream.writeLong(methodID); + stream.writeLong(requestID); +} + +std::string Arts::Invocation::_typeName() const +{ + return "Arts::Invocation"; +} + +Arts::OnewayInvocation::OnewayInvocation() +{ +} + +Arts::OnewayInvocation::OnewayInvocation(long _a_objectID, long _a_methodID) +{ + this->objectID = _a_objectID; + this->methodID = _a_methodID; +} + +Arts::OnewayInvocation::OnewayInvocation(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::OnewayInvocation::OnewayInvocation(const Arts::OnewayInvocation& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::OnewayInvocation& Arts::OnewayInvocation::operator=(const Arts::OnewayInvocation& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::OnewayInvocation::readType(Arts::Buffer& stream) +{ + objectID = stream.readLong(); + methodID = stream.readLong(); +} + +void Arts::OnewayInvocation::writeType(Arts::Buffer& stream) const +{ + stream.writeLong(objectID); + stream.writeLong(methodID); +} + +std::string Arts::OnewayInvocation::_typeName() const +{ + return "Arts::OnewayInvocation"; +} + +Arts::ServerHello::ServerHello() +{ +} + +Arts::ServerHello::ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed) +{ + this->mcopVersion = _a_mcopVersion; + this->serverID = _a_serverID; + this->authProtocols = _a_authProtocols; + this->authSeed = _a_authSeed; +} + +Arts::ServerHello::ServerHello(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::ServerHello::ServerHello(const Arts::ServerHello& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::ServerHello& Arts::ServerHello::operator=(const Arts::ServerHello& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::ServerHello::readType(Arts::Buffer& stream) +{ + stream.readString(mcopVersion); + stream.readString(serverID); + stream.readStringSeq(authProtocols); + stream.readString(authSeed); +} + +void Arts::ServerHello::writeType(Arts::Buffer& stream) const +{ + stream.writeString(mcopVersion); + stream.writeString(serverID); + stream.writeStringSeq(authProtocols); + stream.writeString(authSeed); +} + +std::string Arts::ServerHello::_typeName() const +{ + return "Arts::ServerHello"; +} + +Arts::ClientHello::ClientHello() +{ +} + +Arts::ClientHello::ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData) +{ + this->serverID = _a_serverID; + this->authProtocol = _a_authProtocol; + this->authData = _a_authData; +} + +Arts::ClientHello::ClientHello(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::ClientHello::ClientHello(const Arts::ClientHello& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::ClientHello& Arts::ClientHello::operator=(const Arts::ClientHello& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::ClientHello::readType(Arts::Buffer& stream) +{ + stream.readString(serverID); + stream.readString(authProtocol); + stream.readString(authData); +} + +void Arts::ClientHello::writeType(Arts::Buffer& stream) const +{ + stream.writeString(serverID); + stream.writeString(authProtocol); + stream.writeString(authData); +} + +std::string Arts::ClientHello::_typeName() const +{ + return "Arts::ClientHello"; +} + +Arts::AuthAccept::AuthAccept() +{ +} + +Arts::AuthAccept::AuthAccept(const std::vector<std::string>& _a_hints) +{ + this->hints = _a_hints; +} + +Arts::AuthAccept::AuthAccept(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::AuthAccept::AuthAccept(const Arts::AuthAccept& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::AuthAccept& Arts::AuthAccept::operator=(const Arts::AuthAccept& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::AuthAccept::readType(Arts::Buffer& stream) +{ + stream.readStringSeq(hints); +} + +void Arts::AuthAccept::writeType(Arts::Buffer& stream) const +{ + stream.writeStringSeq(hints); +} + +std::string Arts::AuthAccept::_typeName() const +{ + return "Arts::AuthAccept"; +} + +Arts::ObjectReference::ObjectReference() +{ +} + +Arts::ObjectReference::ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls) +{ + this->serverID = _a_serverID; + this->objectID = _a_objectID; + this->urls = _a_urls; +} + +Arts::ObjectReference::ObjectReference(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::ObjectReference::ObjectReference(const Arts::ObjectReference& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::ObjectReference& Arts::ObjectReference::operator=(const Arts::ObjectReference& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::ObjectReference::readType(Arts::Buffer& stream) +{ + stream.readString(serverID); + objectID = stream.readLong(); + stream.readStringSeq(urls); +} + +void Arts::ObjectReference::writeType(Arts::Buffer& stream) const +{ + stream.writeString(serverID); + stream.writeLong(objectID); + stream.writeStringSeq(urls); +} + +std::string Arts::ObjectReference::_typeName() const +{ + return "Arts::ObjectReference"; +} + +Arts::ParamDef::ParamDef() +{ +} + +Arts::ParamDef::ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints) +{ + this->type = _a_type; + this->name = _a_name; + this->hints = _a_hints; +} + +Arts::ParamDef::ParamDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::ParamDef::ParamDef(const Arts::ParamDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::ParamDef& Arts::ParamDef::operator=(const Arts::ParamDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::ParamDef::readType(Arts::Buffer& stream) +{ + stream.readString(type); + stream.readString(name); + stream.readStringSeq(hints); +} + +void Arts::ParamDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(type); + stream.writeString(name); + stream.writeStringSeq(hints); +} + +std::string Arts::ParamDef::_typeName() const +{ + return "Arts::ParamDef"; +} + +Arts::MethodDef::MethodDef() +{ +} + +Arts::MethodDef::MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->type = _a_type; + this->flags = _a_flags; + this->signature = _a_signature; + this->hints = _a_hints; +} + +Arts::MethodDef::MethodDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::MethodDef::MethodDef(const Arts::MethodDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::MethodDef& Arts::MethodDef::operator=(const Arts::MethodDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::MethodDef::readType(Arts::Buffer& stream) +{ + stream.readString(name); + stream.readString(type); + flags = (Arts::MethodType)stream.readLong(); + Arts::readTypeSeq(stream,signature); + stream.readStringSeq(hints); +} + +void Arts::MethodDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + stream.writeString(type); + stream.writeLong(flags); + Arts::writeTypeSeq(stream,signature); + stream.writeStringSeq(hints); +} + +std::string Arts::MethodDef::_typeName() const +{ + return "Arts::MethodDef"; +} + +Arts::AttributeDef::AttributeDef() +{ +} + +Arts::AttributeDef::AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->type = _a_type; + this->flags = _a_flags; + this->hints = _a_hints; +} + +Arts::AttributeDef::AttributeDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::AttributeDef::AttributeDef(const Arts::AttributeDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::AttributeDef& Arts::AttributeDef::operator=(const Arts::AttributeDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::AttributeDef::readType(Arts::Buffer& stream) +{ + stream.readString(name); + stream.readString(type); + flags = (Arts::AttributeType)stream.readLong(); + stream.readStringSeq(hints); +} + +void Arts::AttributeDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + stream.writeString(type); + stream.writeLong(flags); + stream.writeStringSeq(hints); +} + +std::string Arts::AttributeDef::_typeName() const +{ + return "Arts::AttributeDef"; +} + +Arts::InterfaceDef::InterfaceDef() +{ +} + +Arts::InterfaceDef::InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->inheritedInterfaces = _a_inheritedInterfaces; + this->methods = _a_methods; + this->attributes = _a_attributes; + this->defaultPorts = _a_defaultPorts; + this->hints = _a_hints; +} + +Arts::InterfaceDef::InterfaceDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::InterfaceDef::InterfaceDef(const Arts::InterfaceDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::InterfaceDef& Arts::InterfaceDef::operator=(const Arts::InterfaceDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::InterfaceDef::readType(Arts::Buffer& stream) +{ + stream.readString(name); + stream.readStringSeq(inheritedInterfaces); + Arts::readTypeSeq(stream,methods); + Arts::readTypeSeq(stream,attributes); + stream.readStringSeq(defaultPorts); + stream.readStringSeq(hints); +} + +void Arts::InterfaceDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + stream.writeStringSeq(inheritedInterfaces); + Arts::writeTypeSeq(stream,methods); + Arts::writeTypeSeq(stream,attributes); + stream.writeStringSeq(defaultPorts); + stream.writeStringSeq(hints); +} + +std::string Arts::InterfaceDef::_typeName() const +{ + return "Arts::InterfaceDef"; +} + +Arts::TypeComponent::TypeComponent() +{ +} + +Arts::TypeComponent::TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints) +{ + this->type = _a_type; + this->name = _a_name; + this->hints = _a_hints; +} + +Arts::TypeComponent::TypeComponent(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::TypeComponent::TypeComponent(const Arts::TypeComponent& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::TypeComponent& Arts::TypeComponent::operator=(const Arts::TypeComponent& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::TypeComponent::readType(Arts::Buffer& stream) +{ + stream.readString(type); + stream.readString(name); + stream.readStringSeq(hints); +} + +void Arts::TypeComponent::writeType(Arts::Buffer& stream) const +{ + stream.writeString(type); + stream.writeString(name); + stream.writeStringSeq(hints); +} + +std::string Arts::TypeComponent::_typeName() const +{ + return "Arts::TypeComponent"; +} + +Arts::TypeDef::TypeDef() +{ +} + +Arts::TypeDef::TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->contents = _a_contents; + this->hints = _a_hints; +} + +Arts::TypeDef::TypeDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::TypeDef::TypeDef(const Arts::TypeDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::TypeDef& Arts::TypeDef::operator=(const Arts::TypeDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::TypeDef::readType(Arts::Buffer& stream) +{ + stream.readString(name); + Arts::readTypeSeq(stream,contents); + stream.readStringSeq(hints); +} + +void Arts::TypeDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + Arts::writeTypeSeq(stream,contents); + stream.writeStringSeq(hints); +} + +std::string Arts::TypeDef::_typeName() const +{ + return "Arts::TypeDef"; +} + +Arts::EnumComponent::EnumComponent() +{ +} + +Arts::EnumComponent::EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->value = _a_value; + this->hints = _a_hints; +} + +Arts::EnumComponent::EnumComponent(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::EnumComponent::EnumComponent(const Arts::EnumComponent& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::EnumComponent& Arts::EnumComponent::operator=(const Arts::EnumComponent& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::EnumComponent::readType(Arts::Buffer& stream) +{ + stream.readString(name); + value = stream.readLong(); + stream.readStringSeq(hints); +} + +void Arts::EnumComponent::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + stream.writeLong(value); + stream.writeStringSeq(hints); +} + +std::string Arts::EnumComponent::_typeName() const +{ + return "Arts::EnumComponent"; +} + +Arts::EnumDef::EnumDef() +{ +} + +Arts::EnumDef::EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints) +{ + this->name = _a_name; + this->contents = _a_contents; + this->hints = _a_hints; +} + +Arts::EnumDef::EnumDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::EnumDef::EnumDef(const Arts::EnumDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::EnumDef& Arts::EnumDef::operator=(const Arts::EnumDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::EnumDef::readType(Arts::Buffer& stream) +{ + stream.readString(name); + Arts::readTypeSeq(stream,contents); + stream.readStringSeq(hints); +} + +void Arts::EnumDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(name); + Arts::writeTypeSeq(stream,contents); + stream.writeStringSeq(hints); +} + +std::string Arts::EnumDef::_typeName() const +{ + return "Arts::EnumDef"; +} + +Arts::ModuleDef::ModuleDef() +{ +} + +Arts::ModuleDef::ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints) +{ + this->moduleName = _a_moduleName; + this->enums = _a_enums; + this->types = _a_types; + this->interfaces = _a_interfaces; + this->hints = _a_hints; +} + +Arts::ModuleDef::ModuleDef(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::ModuleDef::ModuleDef(const Arts::ModuleDef& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::ModuleDef& Arts::ModuleDef::operator=(const Arts::ModuleDef& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::ModuleDef::readType(Arts::Buffer& stream) +{ + stream.readString(moduleName); + Arts::readTypeSeq(stream,enums); + Arts::readTypeSeq(stream,types); + Arts::readTypeSeq(stream,interfaces); + stream.readStringSeq(hints); +} + +void Arts::ModuleDef::writeType(Arts::Buffer& stream) const +{ + stream.writeString(moduleName); + Arts::writeTypeSeq(stream,enums); + Arts::writeTypeSeq(stream,types); + Arts::writeTypeSeq(stream,interfaces); + stream.writeStringSeq(hints); +} + +std::string Arts::ModuleDef::_typeName() const +{ + return "Arts::ModuleDef"; +} + +Arts::Any::Any() +{ +} + +Arts::Any::Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value) +{ + this->type = _a_type; + this->value = _a_value; +} + +Arts::Any::Any(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::Any::Any(const Arts::Any& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::Any& Arts::Any::operator=(const Arts::Any& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::Any::readType(Arts::Buffer& stream) +{ + stream.readString(type); + stream.readByteSeq(value); +} + +void Arts::Any::writeType(Arts::Buffer& stream) const +{ + stream.writeString(type); + stream.writeByteSeq(value); +} + +std::string Arts::Any::_typeName() const +{ + return "Arts::Any"; +} + +Arts::TraderEntry::TraderEntry() +{ +} + +Arts::TraderEntry::TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines) +{ + this->interfaceName = _a_interfaceName; + this->lines = _a_lines; +} + +Arts::TraderEntry::TraderEntry(Arts::Buffer& stream) +{ + readType(stream); +} + +Arts::TraderEntry::TraderEntry(const Arts::TraderEntry& copyType) : Arts::Type(copyType) +{ + Arts::Buffer buffer; + copyType.writeType(buffer); + readType(buffer); +} + +Arts::TraderEntry& Arts::TraderEntry::operator=(const Arts::TraderEntry& assignType) +{ + Arts::Buffer buffer; + assignType.writeType(buffer); + readType(buffer); + return *this; +} + +void Arts::TraderEntry::readType(Arts::Buffer& stream) +{ + stream.readString(interfaceName); + stream.readStringSeq(lines); +} + +void Arts::TraderEntry::writeType(Arts::Buffer& stream) const +{ + stream.writeString(interfaceName); + stream.writeStringSeq(lines); +} + +std::string Arts::TraderEntry::_typeName() const +{ + return "Arts::TraderEntry"; +} + +Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)skel->_cast(Arts::InterfaceRepo_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::InterfaceRepo_base::_fromReference(r,true); + return 0; +} + +Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)object._base()->_cast(Arts::InterfaceRepo_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::InterfaceRepo_base *result; + result = (Arts::InterfaceRepo_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepo"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::InterfaceRepo_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::InterfaceRepo")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::InterfaceRepo_base::_cast(unsigned long iid) +{ + if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::InterfaceRepo_stub::InterfaceRepo_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::InterfaceRepo_stub::InterfaceRepo_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +long Arts::InterfaceRepo_stub::insertModule(const Arts::ModuleDef& newModule) +{ + long methodID = _lookupMethodFast("method:0000000d696e736572744d6f64756c6500000000056c6f6e6700000000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + newModule.writeType(*request); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return 0; // error occurred + long returnCode = result->readLong(); + delete result; + return returnCode; +} + +void Arts::InterfaceRepo_stub::removeModule(long moduleID) +{ + long methodID = _lookupMethodFast("method:0000000d72656d6f76654d6f64756c650000000005766f6964000000000200000001000000056c6f6e6700000000096d6f64756c654944000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeLong(moduleID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +Arts::InterfaceDef Arts::InterfaceRepo_stub::queryInterface(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000f7175657279496e746572666163650000000013417274733a3a496e7465726661636544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return Arts::InterfaceDef(); // error occurred + Arts::InterfaceDef _returnCode(*result); + delete result; + return _returnCode; +} + +Arts::TypeDef Arts::InterfaceRepo_stub::queryType(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000a717565727954797065000000000e417274733a3a5479706544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return Arts::TypeDef(); // error occurred + Arts::TypeDef _returnCode(*result); + delete result; + return _returnCode; +} + +Arts::EnumDef Arts::InterfaceRepo_stub::queryEnum(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000a7175657279456e756d000000000e417274733a3a456e756d44656600000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return Arts::EnumDef(); // error occurred + Arts::EnumDef _returnCode(*result); + delete result; + return _returnCode; +} + +std::vector<std::string> * Arts::InterfaceRepo_stub::queryChildren(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000e71756572794368696c6472656e00000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +std::vector<std::string> * Arts::InterfaceRepo_stub::queryInterfaces() +{ + long methodID = _lookupMethodFast("method:000000107175657279496e746572666163657300000000082a737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +std::vector<std::string> * Arts::InterfaceRepo_stub::queryTypes() +{ + long methodID = _lookupMethodFast("method:0000000b7175657279547970657300000000082a737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +std::vector<std::string> * Arts::InterfaceRepo_stub::queryEnums() +{ + long methodID = _lookupMethodFast("method:0000000b7175657279456e756d7300000000082a737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +std::string Arts::InterfaceRepo_skel::_interfaceName() +{ + return "Arts::InterfaceRepo"; +} + +bool Arts::InterfaceRepo_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::InterfaceRepo") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::InterfaceRepo_skel::_interfaceNameSkel() +{ + return "Arts::InterfaceRepo"; +} + +// insertModule +static void _dispatch_Arts_InterfaceRepo_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::ModuleDef newModule(*request); + result->writeLong(((Arts::InterfaceRepo_skel *)object)->insertModule(newModule)); +} + +// removeModule +static void _dispatch_Arts_InterfaceRepo_01(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + long moduleID = request->readLong(); + ((Arts::InterfaceRepo_skel *)object)->removeModule(moduleID); +} + +// queryInterface +static void _dispatch_Arts_InterfaceRepo_02(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::InterfaceDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterface(name); + _returnCode.writeType(*result); +} + +// queryType +static void _dispatch_Arts_InterfaceRepo_03(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::TypeDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryType(name); + _returnCode.writeType(*result); +} + +// queryEnum +static void _dispatch_Arts_InterfaceRepo_04(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::EnumDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnum(name); + _returnCode.writeType(*result); +} + +// queryChildren +static void _dispatch_Arts_InterfaceRepo_05(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryChildren(name); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +// queryInterfaces +static void _dispatch_Arts_InterfaceRepo_06(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterfaces(); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +// queryTypes +static void _dispatch_Arts_InterfaceRepo_07(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryTypes(); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +// queryEnums +static void _dispatch_Arts_InterfaceRepo_08(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnums(); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +void Arts::InterfaceRepo_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000d696e736572744d6f64756c6500000000056c6f6e670000" + "0000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65" + "774d6f64756c650000000000000000000000000d72656d6f76654d6f64756c6500" + "00000005766f6964000000000200000001000000056c6f6e6700000000096d6f64" + "756c6549440000000000000000000000000f7175657279496e7465726661636500" + "00000013417274733a3a496e746572666163654465660000000002000000010000" + "0007737472696e6700000000056e616d650000000000000000000000000a717565" + "727954797065000000000e417274733a3a54797065446566000000000200000001" + "00000007737472696e6700000000056e616d650000000000000000000000000a71" + "75657279456e756d000000000e417274733a3a456e756d44656600000000020000" + "000100000007737472696e6700000000056e616d65000000000000000000000000" + "0e71756572794368696c6472656e00000000082a737472696e6700000000020000" + "000100000007737472696e6700000000056e616d65000000000000000000000000" + "107175657279496e746572666163657300000000082a737472696e670000000002" + "00000000000000000000000b7175657279547970657300000000082a737472696e" + "67000000000200000000000000000000000b7175657279456e756d730000000008" + "2a737472696e6700000000020000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_InterfaceRepo_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_01,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_02,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_03,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_04,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_05,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_06,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_07,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_InterfaceRepo_08,this,Arts::MethodDef(m)); +} + +Arts::InterfaceRepo_skel::InterfaceRepo_skel() +{ +} + +Arts::Object_base* Arts::InterfaceRepo::_Creator() { + return Arts::InterfaceRepo_base::_create(); +} + +unsigned long Arts::InterfaceRepo_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepo"); + +Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)skel->_cast(Arts::InterfaceRepoV2_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::InterfaceRepoV2_base::_fromReference(r,true); + return 0; +} + +Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)object._base()->_cast(Arts::InterfaceRepoV2_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::InterfaceRepoV2_base *result; + result = (Arts::InterfaceRepoV2_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepoV2"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::InterfaceRepoV2_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::InterfaceRepoV2")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::InterfaceRepoV2_base::_cast(unsigned long iid) +{ + if(iid == Arts::InterfaceRepoV2_base::_IID) return (Arts::InterfaceRepoV2_base *)this; + if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +Arts::TypeIdentification Arts::InterfaceRepoV2_stub::identifyType(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000d6964656e74696679547970650000000019417274733a3a547970654964656e74696669636174696f6e00000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return (Arts::TypeIdentification)0; // error occurred + Arts::TypeIdentification returnCode = (Arts::TypeIdentification)result->readLong(); + delete result; + return returnCode; +} + +std::string Arts::InterfaceRepoV2_skel::_interfaceName() +{ + return "Arts::InterfaceRepoV2"; +} + +bool Arts::InterfaceRepoV2_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::InterfaceRepoV2") return true; + if (interfacename == "Arts::InterfaceRepo") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::InterfaceRepoV2_skel::_interfaceNameSkel() +{ + return "Arts::InterfaceRepoV2"; +} + +// identifyType +static void _dispatch_Arts_InterfaceRepoV2_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + result->writeLong(((Arts::InterfaceRepoV2_skel *)object)->identifyType(name)); +} + +void Arts::InterfaceRepoV2_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000d6964656e74696679547970650000000019417274733a3a" + "547970654964656e74696669636174696f6e000000000200000001000000077374" + "72696e6700000000056e616d65000000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_InterfaceRepoV2_00,this,Arts::MethodDef(m)); + Arts::InterfaceRepo_skel::_buildMethodTable(); +} + +Arts::InterfaceRepoV2_skel::InterfaceRepoV2_skel() +{ +} + +Arts::Object_base* Arts::InterfaceRepoV2::_Creator() { + return Arts::InterfaceRepoV2_base::_create(); +} + +unsigned long Arts::InterfaceRepoV2_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepoV2"); + +Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)skel->_cast(Arts::FlowSystemSender_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::FlowSystemSender_base::_fromReference(r,true); + return 0; +} + +Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)object._base()->_cast(Arts::FlowSystemSender_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::FlowSystemSender_base *result; + result = (Arts::FlowSystemSender_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemSender"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::FlowSystemSender_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::FlowSystemSender")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::FlowSystemSender_base::_cast(unsigned long iid) +{ + if(iid == Arts::FlowSystemSender_base::_IID) return (Arts::FlowSystemSender_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::FlowSystemSender_stub::FlowSystemSender_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::FlowSystemSender_stub::FlowSystemSender_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +void Arts::FlowSystemSender_stub::processed() +{ + long methodID = _lookupMethodFast("method:0000000a70726f6365737365640000000005766f696400000000010000000000000000"); + Arts::Buffer *request = Arts::Dispatcher::the()->createOnewayRequest(_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + +} + +void Arts::FlowSystemSender_stub::disconnect() +{ + long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +std::string Arts::FlowSystemSender_skel::_interfaceName() +{ + return "Arts::FlowSystemSender"; +} + +bool Arts::FlowSystemSender_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::FlowSystemSender") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::FlowSystemSender_skel::_interfaceNameSkel() +{ + return "Arts::FlowSystemSender"; +} + +// processed +static void _dispatch_Arts_FlowSystemSender_00(void *object, Arts::Buffer *) +{ + ((Arts::FlowSystemSender_skel *)object)->processed(); +} + +// disconnect +static void _dispatch_Arts_FlowSystemSender_01(void *object, Arts::Buffer *, Arts::Buffer *) +{ + ((Arts::FlowSystemSender_skel *)object)->disconnect(); +} + +void Arts::FlowSystemSender_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000a70726f6365737365640000000005766f69640000000001" + "00000000000000000000000b646973636f6e6e6563740000000005766f69640000" + "0000020000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_FlowSystemSender_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystemSender_01,this,Arts::MethodDef(m)); +} + +Arts::FlowSystemSender_skel::FlowSystemSender_skel() +{ +} + +Arts::Object_base* Arts::FlowSystemSender::_Creator() { + return Arts::FlowSystemSender_base::_create(); +} + +unsigned long Arts::FlowSystemSender_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemSender"); + +Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)skel->_cast(Arts::FlowSystemReceiver_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::FlowSystemReceiver_base::_fromReference(r,true); + return 0; +} + +Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)object._base()->_cast(Arts::FlowSystemReceiver_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::FlowSystemReceiver_base *result; + result = (Arts::FlowSystemReceiver_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemReceiver"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::FlowSystemReceiver_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::FlowSystemReceiver")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::FlowSystemReceiver_base::_cast(unsigned long iid) +{ + if(iid == Arts::FlowSystemReceiver_base::_IID) return (Arts::FlowSystemReceiver_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +void Arts::FlowSystemReceiver_stub::disconnect() +{ + long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +long Arts::FlowSystemReceiver_stub::receiveHandlerID() +{ + long methodID = _lookupMethodFast("method:000000165f6765745f7265636569766548616e646c6572494400000000056c6f6e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return 0; // error occurred + long returnCode = result->readLong(); + delete result; + return returnCode; +} + +std::string Arts::FlowSystemReceiver_skel::_interfaceName() +{ + return "Arts::FlowSystemReceiver"; +} + +bool Arts::FlowSystemReceiver_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::FlowSystemReceiver") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::FlowSystemReceiver_skel::_interfaceNameSkel() +{ + return "Arts::FlowSystemReceiver"; +} + +// disconnect +static void _dispatch_Arts_FlowSystemReceiver_00(void *object, Arts::Buffer *, Arts::Buffer *) +{ + ((Arts::FlowSystemReceiver_skel *)object)->disconnect(); +} + +// _get_receiveHandlerID +static void _dispatch_Arts_FlowSystemReceiver_01(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + result->writeLong(((Arts::FlowSystemReceiver_skel *)object)->receiveHandlerID()); +} + +void Arts::FlowSystemReceiver_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000b646973636f6e6e6563740000000005766f696400000000" + "020000000000000000000000165f6765745f7265636569766548616e646c657249" + "4400000000056c6f6e6700000000020000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_FlowSystemReceiver_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystemReceiver_01,this,Arts::MethodDef(m)); +} + +Arts::FlowSystemReceiver_skel::FlowSystemReceiver_skel() +{ +} + +Arts::Object_base* Arts::FlowSystemReceiver::_Creator() { + return Arts::FlowSystemReceiver_base::_create(); +} + +unsigned long Arts::FlowSystemReceiver_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemReceiver"); + +Arts::FlowSystem_base *Arts::FlowSystem_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)skel->_cast(Arts::FlowSystem_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::FlowSystem_base *Arts::FlowSystem_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::FlowSystem_base::_fromReference(r,true); + return 0; +} + +Arts::FlowSystem_base *Arts::FlowSystem_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)object._base()->_cast(Arts::FlowSystem_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::FlowSystem_base *Arts::FlowSystem_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::FlowSystem_base *result; + result = (Arts::FlowSystem_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystem"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::FlowSystem_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::FlowSystem")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::FlowSystem_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::FlowSystem_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::FlowSystem_base::_cast(unsigned long iid) +{ + if(iid == Arts::FlowSystem_base::_IID) return (Arts::FlowSystem_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::FlowSystem_stub::FlowSystem_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::FlowSystem_stub::FlowSystem_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +void Arts::FlowSystem_stub::startObject(Arts::Object node) +{ + long methodID = _lookupMethodFast("method:0000000c73746172744f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,node._base()); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +void Arts::FlowSystem_stub::stopObject(Arts::Object node) +{ + long methodID = _lookupMethodFast("method:0000000b73746f704f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,node._base()); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +void Arts::FlowSystem_stub::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) +{ + long methodID = _lookupMethodFast("method:0000000e636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,sourceObject._base()); + request->writeString(sourcePort); + Arts::writeObject(*request,destObject._base()); + request->writeString(destPort); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +void Arts::FlowSystem_stub::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) +{ + long methodID = _lookupMethodFast("method:00000011646973636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,sourceObject._base()); + request->writeString(sourcePort); + Arts::writeObject(*request,destObject._base()); + request->writeString(destPort); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +Arts::AttributeType Arts::FlowSystem_stub::queryFlags(Arts::Object node, const std::string& port) +{ + long methodID = _lookupMethodFast("method:0000000b7175657279466c6167730000000014417274733a3a41747472696275746554797065000000000200000002000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,node._base()); + request->writeString(port); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return (Arts::AttributeType)0; // error occurred + Arts::AttributeType returnCode = (Arts::AttributeType)result->readLong(); + delete result; + return returnCode; +} + +void Arts::FlowSystem_stub::setFloatValue(Arts::Object node, const std::string& port, float value) +{ + long methodID = _lookupMethodFast("method:0000000e736574466c6f617456616c75650000000005766f6964000000000200000003000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000006666c6f6174000000000676616c7565000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,node._base()); + request->writeString(port); + request->writeFloat(value); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +Arts::FlowSystemReceiver Arts::FlowSystem_stub::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender) +{ + long methodID = _lookupMethodFast("method:0000000f63726561746552656365697665720000000019417274733a3a466c6f7753797374656d5265636569766572000000000200000003000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000017417274733a3a466c6f7753797374656d53656e646572000000000773656e646572000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,destObject._base()); + request->writeString(destPort); + Arts::writeObject(*request,sender._base()); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if (!result) return Arts::FlowSystemReceiver::null(); + Arts::FlowSystemReceiver_base* returnCode; + Arts::readObject(*result,returnCode); + delete result; + return Arts::FlowSystemReceiver::_from_base(returnCode); +} + +std::string Arts::FlowSystem_skel::_interfaceName() +{ + return "Arts::FlowSystem"; +} + +bool Arts::FlowSystem_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::FlowSystem") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::FlowSystem_skel::_interfaceNameSkel() +{ + return "Arts::FlowSystem"; +} + +// startObject +static void _dispatch_Arts_FlowSystem_00(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + Arts::Object_base* _temp_node; + Arts::readObject(*request,_temp_node); + Arts::Object node = Arts::Object::_from_base(_temp_node); + ((Arts::FlowSystem_skel *)object)->startObject(node); +} + +// stopObject +static void _dispatch_Arts_FlowSystem_01(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + Arts::Object_base* _temp_node; + Arts::readObject(*request,_temp_node); + Arts::Object node = Arts::Object::_from_base(_temp_node); + ((Arts::FlowSystem_skel *)object)->stopObject(node); +} + +// connectObject +static void _dispatch_Arts_FlowSystem_02(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + Arts::Object_base* _temp_sourceObject; + Arts::readObject(*request,_temp_sourceObject); + Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject); + std::string sourcePort; + request->readString(sourcePort); + Arts::Object_base* _temp_destObject; + Arts::readObject(*request,_temp_destObject); + Arts::Object destObject = Arts::Object::_from_base(_temp_destObject); + std::string destPort; + request->readString(destPort); + ((Arts::FlowSystem_skel *)object)->connectObject(sourceObject,sourcePort,destObject,destPort); +} + +// disconnectObject +static void _dispatch_Arts_FlowSystem_03(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + Arts::Object_base* _temp_sourceObject; + Arts::readObject(*request,_temp_sourceObject); + Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject); + std::string sourcePort; + request->readString(sourcePort); + Arts::Object_base* _temp_destObject; + Arts::readObject(*request,_temp_destObject); + Arts::Object destObject = Arts::Object::_from_base(_temp_destObject); + std::string destPort; + request->readString(destPort); + ((Arts::FlowSystem_skel *)object)->disconnectObject(sourceObject,sourcePort,destObject,destPort); +} + +// queryFlags +static void _dispatch_Arts_FlowSystem_04(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::Object_base* _temp_node; + Arts::readObject(*request,_temp_node); + Arts::Object node = Arts::Object::_from_base(_temp_node); + std::string port; + request->readString(port); + result->writeLong(((Arts::FlowSystem_skel *)object)->queryFlags(node,port)); +} + +// setFloatValue +static void _dispatch_Arts_FlowSystem_05(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + Arts::Object_base* _temp_node; + Arts::readObject(*request,_temp_node); + Arts::Object node = Arts::Object::_from_base(_temp_node); + std::string port; + request->readString(port); + float value = request->readFloat(); + ((Arts::FlowSystem_skel *)object)->setFloatValue(node,port,value); +} + +// createReceiver +static void _dispatch_Arts_FlowSystem_06(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::Object_base* _temp_destObject; + Arts::readObject(*request,_temp_destObject); + Arts::Object destObject = Arts::Object::_from_base(_temp_destObject); + std::string destPort; + request->readString(destPort); + Arts::FlowSystemSender_base* _temp_sender; + Arts::readObject(*request,_temp_sender); + Arts::FlowSystemSender sender = Arts::FlowSystemSender::_from_base(_temp_sender); + Arts::FlowSystemReceiver returnCode = ((Arts::FlowSystem_skel *)object)->createReceiver(destObject,destPort,sender); + Arts::writeObject(*result,returnCode._base()); +} + +void Arts::FlowSystem_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000c73746172744f626a6563740000000005766f6964000000" + "000200000001000000076f626a65637400000000056e6f64650000000000000000" + "000000000b73746f704f626a6563740000000005766f6964000000000200000001" + "000000076f626a65637400000000056e6f64650000000000000000000000000e63" + "6f6e6e6563744f626a6563740000000005766f6964000000000200000004000000" + "076f626a656374000000000d736f757263654f626a656374000000000000000007" + "737472696e67000000000b736f75726365506f72740000000000000000076f626a" + "656374000000000b646573744f626a656374000000000000000007737472696e67" + "000000000964657374506f727400000000000000000000000011646973636f6e6e" + "6563744f626a6563740000000005766f6964000000000200000004000000076f62" + "6a656374000000000d736f757263654f626a656374000000000000000007737472" + "696e67000000000b736f75726365506f72740000000000000000076f626a656374" + "000000000b646573744f626a656374000000000000000007737472696e67000000" + "000964657374506f72740000000000000000000000000b7175657279466c616773" + "0000000014417274733a3a41747472696275746554797065000000000200000002" + "000000076f626a65637400000000056e6f6465000000000000000007737472696e" + "670000000005706f72740000000000000000000000000e736574466c6f61745661" + "6c75650000000005766f6964000000000200000003000000076f626a6563740000" + "0000056e6f6465000000000000000007737472696e670000000005706f72740000" + "00000000000006666c6f6174000000000676616c75650000000000000000000000" + "000f63726561746552656365697665720000000019417274733a3a466c6f775379" + "7374656d5265636569766572000000000200000003000000076f626a6563740000" + "00000b646573744f626a656374000000000000000007737472696e670000000009" + "64657374506f7274000000000000000017417274733a3a466c6f7753797374656d" + "53656e646572000000000773656e646572000000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_FlowSystem_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_01,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_02,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_03,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_04,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_05,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_FlowSystem_06,this,Arts::MethodDef(m)); +} + +Arts::FlowSystem_skel::FlowSystem_skel() +{ +} + +Arts::Object_base* Arts::FlowSystem::_Creator() { + return Arts::FlowSystem_base::_create(); +} + +unsigned long Arts::FlowSystem_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystem"); + +Arts::GlobalComm_base *Arts::GlobalComm_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)skel->_cast(Arts::GlobalComm_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::GlobalComm_base *Arts::GlobalComm_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::GlobalComm_base::_fromReference(r,true); + return 0; +} + +Arts::GlobalComm_base *Arts::GlobalComm_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)object._base()->_cast(Arts::GlobalComm_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::GlobalComm_base *Arts::GlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::GlobalComm_base *result; + result = (Arts::GlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::GlobalComm"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::GlobalComm_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::GlobalComm")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::GlobalComm_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::GlobalComm_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::GlobalComm_base::_cast(unsigned long iid) +{ + if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::GlobalComm_stub::GlobalComm_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::GlobalComm_stub::GlobalComm_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +bool Arts::GlobalComm_stub::put(const std::string& variable, const std::string& value) +{ + long methodID = _lookupMethodFast("method:000000047075740000000008626f6f6c65616e00000000020000000200000007737472696e6700000000097661726961626c65000000000000000007737472696e67000000000676616c7565000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(variable); + request->writeString(value); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return false; // error occurred + bool returnCode = result->readBool(); + delete result; + return returnCode; +} + +std::string Arts::GlobalComm_stub::get(const std::string& variable) +{ + long methodID = _lookupMethodFast("method:000000046765740000000007737472696e6700000000020000000100000007737472696e6700000000097661726961626c65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(variable); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return""; // error occurred + std::string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +void Arts::GlobalComm_stub::erase(const std::string& variable) +{ + long methodID = _lookupMethodFast("method:0000000665726173650000000005766f696400000000020000000100000007737472696e6700000000097661726961626c65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(variable); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +std::string Arts::GlobalComm_skel::_interfaceName() +{ + return "Arts::GlobalComm"; +} + +bool Arts::GlobalComm_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::GlobalComm") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::GlobalComm_skel::_interfaceNameSkel() +{ + return "Arts::GlobalComm"; +} + +// put +static void _dispatch_Arts_GlobalComm_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string variable; + request->readString(variable); + std::string value; + request->readString(value); + result->writeBool(((Arts::GlobalComm_skel *)object)->put(variable,value)); +} + +// get +static void _dispatch_Arts_GlobalComm_01(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string variable; + request->readString(variable); + result->writeString(((Arts::GlobalComm_skel *)object)->get(variable)); +} + +// erase +static void _dispatch_Arts_GlobalComm_02(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + std::string variable; + request->readString(variable); + ((Arts::GlobalComm_skel *)object)->erase(variable); +} + +void Arts::GlobalComm_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:000000047075740000000008626f6f6c65616e0000000002000000" + "0200000007737472696e6700000000097661726961626c65000000000000000007" + "737472696e67000000000676616c75650000000000000000000000000467657400" + "00000007737472696e6700000000020000000100000007737472696e6700000000" + "097661726961626c65000000000000000000000000066572617365000000000576" + "6f696400000000020000000100000007737472696e670000000009766172696162" + "6c65000000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_GlobalComm_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_GlobalComm_01,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_GlobalComm_02,this,Arts::MethodDef(m)); +} + +Arts::GlobalComm_skel::GlobalComm_skel() +{ +} + +Arts::Object_base* Arts::GlobalComm::_Creator() { + return Arts::GlobalComm_base::_create(); +} + +unsigned long Arts::GlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::GlobalComm"); + +Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)skel->_cast(Arts::TmpGlobalComm_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::TmpGlobalComm_base::_fromReference(r,true); + return 0; +} + +Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)object._base()->_cast(Arts::TmpGlobalComm_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::TmpGlobalComm_base *result; + result = (Arts::TmpGlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TmpGlobalComm"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::TmpGlobalComm_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::TmpGlobalComm")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::TmpGlobalComm_base::_cast(unsigned long iid) +{ + if(iid == Arts::TmpGlobalComm_base::_IID) return (Arts::TmpGlobalComm_base *)this; + if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::TmpGlobalComm_stub::TmpGlobalComm_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::TmpGlobalComm_stub::TmpGlobalComm_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +std::string Arts::TmpGlobalComm_skel::_interfaceName() +{ + return "Arts::TmpGlobalComm"; +} + +bool Arts::TmpGlobalComm_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::TmpGlobalComm") return true; + if (interfacename == "Arts::GlobalComm") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::TmpGlobalComm_skel::_interfaceNameSkel() +{ + return "Arts::TmpGlobalComm"; +} + +void Arts::TmpGlobalComm_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:", + "MethodTable" + ); + Arts::GlobalComm_skel::_buildMethodTable(); +} + +Arts::TmpGlobalComm_skel::TmpGlobalComm_skel() +{ +} + +Arts::Object_base* Arts::TmpGlobalComm::_Creator() { + return Arts::TmpGlobalComm_base::_create(); +} + +unsigned long Arts::TmpGlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::TmpGlobalComm"); + +Arts::TraderOffer_base *Arts::TraderOffer_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)skel->_cast(Arts::TraderOffer_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::TraderOffer_base *Arts::TraderOffer_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::TraderOffer_base::_fromReference(r,true); + return 0; +} + +Arts::TraderOffer_base *Arts::TraderOffer_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)object._base()->_cast(Arts::TraderOffer_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::TraderOffer_base *Arts::TraderOffer_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::TraderOffer_base *result; + result = (Arts::TraderOffer_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderOffer"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::TraderOffer_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::TraderOffer")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::TraderOffer_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::TraderOffer_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::TraderOffer_base::_cast(unsigned long iid) +{ + if(iid == Arts::TraderOffer_base::_IID) return (Arts::TraderOffer_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::TraderOffer_stub::TraderOffer_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::TraderOffer_stub::TraderOffer_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +std::vector<std::string> * Arts::TraderOffer_stub::getProperty(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000c67657450726f706572747900000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +std::string Arts::TraderOffer_stub::interfaceName() +{ + long methodID = _lookupMethodFast("method:000000135f6765745f696e746572666163654e616d650000000007737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return""; // error occurred + std::string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +std::string Arts::TraderOffer_skel::_interfaceName() +{ + return "Arts::TraderOffer"; +} + +bool Arts::TraderOffer_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::TraderOffer") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::TraderOffer_skel::_interfaceNameSkel() +{ + return "Arts::TraderOffer"; +} + +// getProperty +static void _dispatch_Arts_TraderOffer_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + std::vector<std::string> *_returnCode = ((Arts::TraderOffer_skel *)object)->getProperty(name); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +// _get_interfaceName +static void _dispatch_Arts_TraderOffer_01(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + result->writeString(((Arts::TraderOffer_skel *)object)->interfaceName()); +} + +void Arts::TraderOffer_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000c67657450726f706572747900000000082a737472696e67" + "00000000020000000100000007737472696e6700000000056e616d650000000000" + "00000000000000135f6765745f696e746572666163654e616d6500000000077374" + "72696e6700000000020000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_TraderOffer_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_TraderOffer_01,this,Arts::MethodDef(m)); +} + +Arts::TraderOffer_skel::TraderOffer_skel() +{ +} + +Arts::Object_base* Arts::TraderOffer::_Creator() { + return Arts::TraderOffer_base::_create(); +} + +unsigned long Arts::TraderOffer_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderOffer"); + +Arts::TraderQuery_base *Arts::TraderQuery_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)skel->_cast(Arts::TraderQuery_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::TraderQuery_base *Arts::TraderQuery_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::TraderQuery_base::_fromReference(r,true); + return 0; +} + +Arts::TraderQuery_base *Arts::TraderQuery_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)object._base()->_cast(Arts::TraderQuery_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::TraderQuery_base *Arts::TraderQuery_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::TraderQuery_base *result; + result = (Arts::TraderQuery_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderQuery"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::TraderQuery_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::TraderQuery")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::TraderQuery_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::TraderQuery_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::TraderQuery_base::_cast(unsigned long iid) +{ + if(iid == Arts::TraderQuery_base::_IID) return (Arts::TraderQuery_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::TraderQuery_stub::TraderQuery_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::TraderQuery_stub::TraderQuery_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +void Arts::TraderQuery_stub::supports(const std::string& property, const std::string& value) +{ + long methodID = _lookupMethodFast("method:00000009737570706f7274730000000005766f696400000000020000000200000007737472696e67000000000970726f7065727479000000000000000007737472696e67000000000676616c7565000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(property); + request->writeString(value); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +std::vector<Arts::TraderOffer> * Arts::TraderQuery_stub::query() +{ + long methodID = _lookupMethodFast("method:00000006717565727900000000132a417274733a3a5472616465724f6666657200000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<Arts::TraderOffer> *_returnCode = new std::vector<Arts::TraderOffer>; + if(!result) return _returnCode; // error occurred + Arts::readObjectSeq(*result,*_returnCode); + delete result; + return _returnCode; +} + +std::string Arts::TraderQuery_skel::_interfaceName() +{ + return "Arts::TraderQuery"; +} + +bool Arts::TraderQuery_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::TraderQuery") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::TraderQuery_skel::_interfaceNameSkel() +{ + return "Arts::TraderQuery"; +} + +// supports +static void _dispatch_Arts_TraderQuery_00(void *object, Arts::Buffer *request, Arts::Buffer *) +{ + std::string property; + request->readString(property); + std::string value; + request->readString(value); + ((Arts::TraderQuery_skel *)object)->supports(property,value); +} + +// query +static void _dispatch_Arts_TraderQuery_01(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<Arts::TraderOffer> *_returnCode = ((Arts::TraderQuery_skel *)object)->query(); + Arts::writeObjectSeq(*result,*_returnCode); + delete _returnCode; +} + +void Arts::TraderQuery_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:00000009737570706f7274730000000005766f6964000000000200" + "00000200000007737472696e67000000000970726f706572747900000000000000" + "0007737472696e67000000000676616c7565000000000000000000000000067175" + "65727900000000132a417274733a3a5472616465724f6666657200000000020000" + "000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_TraderQuery_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_TraderQuery_01,this,Arts::MethodDef(m)); +} + +Arts::TraderQuery_skel::TraderQuery_skel() +{ +} + +Arts::Object_base* Arts::TraderQuery::_Creator() { + return Arts::TraderQuery_base::_create(); +} + +unsigned long Arts::TraderQuery_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderQuery"); + +Arts::Loader_base *Arts::Loader_base::_create(const std::string& subClass) +{ + Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass); + assert(skel); + Arts::Loader_base *castedObject = (Arts::Loader_base *)skel->_cast(Arts::Loader_base::_IID); + assert(castedObject); + return castedObject; +} + +Arts::Loader_base *Arts::Loader_base::_fromString(std::string objectref) +{ + Arts::ObjectReference r; + + if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref)) + return Arts::Loader_base::_fromReference(r,true); + return 0; +} + +Arts::Loader_base *Arts::Loader_base::_fromDynamicCast(const Arts::Object& object) +{ + if(object.isNull()) return 0; + + Arts::Loader_base *castedObject = (Arts::Loader_base *)object._base()->_cast(Arts::Loader_base::_IID); + if(castedObject) return castedObject->_copy(); + + return _fromString(object._toString()); +} + +Arts::Loader_base *Arts::Loader_base::_fromReference(Arts::ObjectReference r, bool needcopy) +{ + Arts::Loader_base *result; + result = (Arts::Loader_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::Loader"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Arts::Loader_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + if (!result->_isCompatibleWith("Arts::Loader")) { + result->_release(); + return 0; + } + } + } + return result; +} + +std::vector<std::string> Arts::Loader_base::_defaultPortsIn() const { + std::vector<std::string> ret; + return ret; +} +std::vector<std::string> Arts::Loader_base::_defaultPortsOut() const { + std::vector<std::string> ret; + return ret; +} + +void *Arts::Loader_base::_cast(unsigned long iid) +{ + if(iid == Arts::Loader_base::_IID) return (Arts::Loader_base *)this; + if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this; + return 0; +} + +Arts::Loader_stub::Loader_stub() +{ + // constructor for subclasses (don't use directly) +} + +Arts::Loader_stub::Loader_stub(Arts::Connection *connection, long objectID) + : Arts::Object_stub(connection, objectID) +{ + // constructor to create a stub for an object +} + +Arts::Object Arts::Loader_stub::loadObject(Arts::TraderOffer offer) +{ + long methodID = _lookupMethodFast("method:0000000b6c6f61644f626a65637400000000076f626a65637400000000020000000100000012417274733a3a5472616465724f6666657200000000066f66666572000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + Arts::writeObject(*request,offer._base()); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if (!result) return Arts::Object::null(); + Arts::Object_base* returnCode; + Arts::readObject(*result,returnCode); + delete result; + return Arts::Object::_from_base(returnCode); +} + +std::string Arts::Loader_stub::dataVersion() +{ + long methodID = _lookupMethodFast("method:000000115f6765745f6461746156657273696f6e0000000007737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return""; // error occurred + std::string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +std::vector<Arts::TraderEntry> * Arts::Loader_stub::traderEntries() +{ + long methodID = _lookupMethodFast("method:000000135f6765745f747261646572456e747269657300000000132a417274733a3a547261646572456e74727900000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<Arts::TraderEntry> *_returnCode = new std::vector<Arts::TraderEntry>; + if(!result) return _returnCode; // error occurred + Arts::readTypeSeq(*result,*_returnCode); + delete result; + return _returnCode; +} + +std::vector<Arts::ModuleDef> * Arts::Loader_stub::modules() +{ + long methodID = _lookupMethodFast("method:0000000d5f6765745f6d6f64756c657300000000112a417274733a3a4d6f64756c6544656600000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<Arts::ModuleDef> *_returnCode = new std::vector<Arts::ModuleDef>; + if(!result) return _returnCode; // error occurred + Arts::readTypeSeq(*result,*_returnCode); + delete result; + return _returnCode; +} + +std::string Arts::Loader_skel::_interfaceName() +{ + return "Arts::Loader"; +} + +bool Arts::Loader_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename == "Arts::Loader") return true; + if (interfacename == "Arts::Object") return true; + return false; +} + +std::string Arts::Loader_skel::_interfaceNameSkel() +{ + return "Arts::Loader"; +} + +// loadObject +static void _dispatch_Arts_Loader_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::TraderOffer_base* _temp_offer; + Arts::readObject(*request,_temp_offer); + Arts::TraderOffer offer = Arts::TraderOffer::_from_base(_temp_offer); + Arts::Object returnCode = ((Arts::Loader_skel *)object)->loadObject(offer); + Arts::writeObject(*result,returnCode._base()); +} + +// _get_dataVersion +static void _dispatch_Arts_Loader_01(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + result->writeString(((Arts::Loader_skel *)object)->dataVersion()); +} + +// _get_traderEntries +static void _dispatch_Arts_Loader_02(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<Arts::TraderEntry> *_returnCode = ((Arts::Loader_skel *)object)->traderEntries(); + Arts::writeTypeSeq(*result,*_returnCode); + delete _returnCode; +} + +// _get_modules +static void _dispatch_Arts_Loader_03(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<Arts::ModuleDef> *_returnCode = ((Arts::Loader_skel *)object)->modules(); + Arts::writeTypeSeq(*result,*_returnCode); + delete _returnCode; +} + +void Arts::Loader_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000b6c6f61644f626a65637400000000076f626a6563740000" + "0000020000000100000012417274733a3a5472616465724f666665720000000006" + "6f66666572000000000000000000000000115f6765745f6461746156657273696f" + "6e0000000007737472696e6700000000020000000000000000000000135f676574" + "5f747261646572456e747269657300000000132a417274733a3a54726164657245" + "6e747279000000000200000000000000000000000d5f6765745f6d6f64756c6573" + "00000000112a417274733a3a4d6f64756c65446566000000000200000000000000" + "00", + "MethodTable" + ); + _addMethod(_dispatch_Arts_Loader_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Loader_01,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Loader_02,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Loader_03,this,Arts::MethodDef(m)); +} + +Arts::Loader_skel::Loader_skel() +{ +} + +Arts::Object_base* Arts::Loader::_Creator() { + return Arts::Loader_base::_create(); +} + +unsigned long Arts::Loader_base::_IID = Arts::MCOPUtils::makeIID("Arts::Loader"); + +static Arts::IDLFileReg IDLFileReg_core("core", + "IDLFile:00000001000000000500000012417274733a3a4865616465724d6167696300" + "000000010000000b4d434f505f4d41474943004d434f50000000000000000000000012" + "417274733a3a4d657373616765547970650000000007000000136d636f704d65737361" + "6765496e76616c6964000000000000000000000000106d636f7053657276657248656c" + "6c6f000000000100000000000000106d636f70436c69656e7448656c6c6f0000000002" + "000000000000000f6d636f70417574684163636570740000000003000000000000000f" + "6d636f70496e766f636174696f6e0000000004000000000000000b6d636f7052657475" + "726e000000000500000000000000156d636f704f6e65776179496e766f636174696f6e" + "0000000006000000000000000000000011417274733a3a4d6574686f64547970650000" + "0000020000000d6d6574686f644f6e657761790000000001000000000000000d6d6574" + "686f6454776f7761790000000002000000000000000000000014417274733a3a417474" + "7269627574655479706500000000070000000973747265616d496e0000000001000000" + "000000000a73747265616d4f75740000000002000000000000000c73747265616d4d75" + "6c74690000000004000000000000001061747472696275746553747265616d00000000" + "0800000000000000136174747269627574654174747269627574650000000010000000" + "000000000c73747265616d4173796e630000000020000000000000000e73747265616d" + "44656661756c740000000040000000000000000000000019417274733a3a5479706549" + "64656e74696669636174696f6e000000000a0000000a7469556e6b6e6f776e00000000" + "0000000000000000077469566f69640000000001000000000000000774694c6f6e6700" + "0000000200000000000000077469427974650000000003000000000000000974695374" + "72696e670000000004000000000000000a7469426f6f6c65616e000000000500000000" + "000000087469466c6f6174000000000600000000000000077469456e756d0000000080" + "00000000000000077469547970650000000081000000000000000c7469496e74657266" + "61636500000000820000000000000000000000120000000d417274733a3a4865616465" + "72000000000300000012417274733a3a4865616465724d6167696300000000066d6167" + "69630000000000000000056c6f6e67000000000e6d6573736167654c656e6774680000" + "00000000000012417274733a3a4d65737361676554797065000000000c6d6573736167" + "655479706500000000000000000000000011417274733a3a496e766f636174696f6e00" + "00000003000000056c6f6e6700000000096f626a65637449440000000000000000056c" + "6f6e6700000000096d6574686f6449440000000000000000056c6f6e67000000000a72" + "657175657374494400000000000000000000000017417274733a3a4f6e65776179496e" + "766f636174696f6e0000000002000000056c6f6e6700000000096f626a656374494400" + "00000000000000056c6f6e6700000000096d6574686f64494400000000000000000000" + "000012417274733a3a53657276657248656c6c6f000000000400000007737472696e67" + "000000000c6d636f7056657273696f6e000000000000000007737472696e6700000000" + "0973657276657249440000000000000000082a737472696e67000000000e6175746850" + "726f746f636f6c73000000000000000007737472696e67000000000961757468536565" + "6400000000000000000000000012417274733a3a436c69656e7448656c6c6f00000000" + "0300000007737472696e67000000000973657276657249440000000000000000077374" + "72696e67000000000d6175746850726f746f636f6c000000000000000007737472696e" + "670000000009617574684461746100000000000000000000000011417274733a3a4175" + "74684163636570740000000001000000082a737472696e67000000000668696e747300" + "000000000000000000000016417274733a3a4f626a6563745265666572656e63650000" + "00000300000007737472696e6700000000097365727665724944000000000000000005" + "6c6f6e6700000000096f626a65637449440000000000000000082a737472696e670000" + "00000575726c730000000000000000000000000f417274733a3a506172616d44656600" + "0000000300000007737472696e67000000000574797065000000000000000007737472" + "696e6700000000056e616d650000000000000000082a737472696e6700000000066869" + "6e747300000000000000000000000010417274733a3a4d6574686f6444656600000000" + "0500000007737472696e6700000000056e616d65000000000000000007737472696e67" + "000000000574797065000000000000000011417274733a3a4d6574686f645479706500" + "00000006666c6167730000000000000000102a417274733a3a506172616d4465660000" + "00000a7369676e61747572650000000000000000082a737472696e6700000000066869" + "6e747300000000000000000000000013417274733a3a41747472696275746544656600" + "0000000400000007737472696e6700000000056e616d65000000000000000007737472" + "696e67000000000574797065000000000000000014417274733a3a4174747269627574" + "65547970650000000006666c6167730000000000000000082a737472696e6700000000" + "0668696e747300000000000000000000000013417274733a3a496e7465726661636544" + "6566000000000600000007737472696e6700000000056e616d65000000000000000008" + "2a737472696e670000000014696e68657269746564496e746572666163657300000000" + "00000000112a417274733a3a4d6574686f6444656600000000086d6574686f64730000" + "000000000000142a417274733a3a417474726962757465446566000000000b61747472" + "6962757465730000000000000000082a737472696e67000000000d64656661756c7450" + "6f7274730000000000000000082a737472696e67000000000668696e74730000000000" + "0000000000000014417274733a3a54797065436f6d706f6e656e740000000003000000" + "07737472696e67000000000574797065000000000000000007737472696e6700000000" + "056e616d650000000000000000082a737472696e67000000000668696e747300000000" + "00000000000000000e417274733a3a5479706544656600000000030000000773747269" + "6e6700000000056e616d650000000000000000152a417274733a3a54797065436f6d70" + "6f6e656e740000000009636f6e74656e74730000000000000000082a737472696e6700" + "0000000668696e747300000000000000000000000014417274733a3a456e756d436f6d" + "706f6e656e74000000000300000007737472696e6700000000056e616d650000000000" + "000000056c6f6e67000000000676616c75650000000000000000082a737472696e6700" + "0000000668696e74730000000000000000000000000e417274733a3a456e756d446566" + "000000000300000007737472696e6700000000056e616d650000000000000000152a41" + "7274733a3a456e756d436f6d706f6e656e740000000009636f6e74656e747300000000" + "00000000082a737472696e67000000000668696e747300000000000000000000000010" + "417274733a3a4d6f64756c65446566000000000500000007737472696e67000000000b" + "6d6f64756c654e616d6500000000000000000f2a417274733a3a456e756d4465660000" + "000006656e756d7300000000000000000f2a417274733a3a5479706544656600000000" + "0674797065730000000000000000142a417274733a3a496e7465726661636544656600" + "0000000b696e74657266616365730000000000000000082a737472696e670000000006" + "68696e74730000000000000000000000000a417274733a3a416e790000000002000000" + "07737472696e670000000005747970650000000000000000062a627974650000000006" + "76616c756500000000000000000000000012417274733a3a547261646572456e747279" + "000000000200000007737472696e67000000000e696e746572666163654e616d650000" + "000000000000082a737472696e6700000000066c696e65730000000000000000000000" + "000b00000014417274733a3a496e746572666163655265706f00000000000000000900" + "00000d696e736572744d6f64756c6500000000056c6f6e670000000002000000010000" + "0010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c6500000000" + "00000000000000000d72656d6f76654d6f64756c650000000005766f69640000000002" + "00000001000000056c6f6e6700000000096d6f64756c65494400000000000000000000" + "00000f7175657279496e746572666163650000000013417274733a3a496e7465726661" + "636544656600000000020000000100000007737472696e6700000000056e616d650000" + "000000000000000000000a717565727954797065000000000e417274733a3a54797065" + "44656600000000020000000100000007737472696e6700000000056e616d6500000000" + "00000000000000000a7175657279456e756d000000000e417274733a3a456e756d4465" + "6600000000020000000100000007737472696e6700000000056e616d65000000000000" + "0000000000000e71756572794368696c6472656e00000000082a737472696e67000000" + "00020000000100000007737472696e6700000000056e616d6500000000000000000000" + "0000107175657279496e746572666163657300000000082a737472696e670000000002" + "00000000000000000000000b7175657279547970657300000000082a737472696e6700" + "0000000200000000000000000000000b7175657279456e756d7300000000082a737472" + "696e670000000002000000000000000000000000000000000000000000000016417274" + "733a3a496e746572666163655265706f5632000000000100000014417274733a3a496e" + "746572666163655265706f00000000010000000d6964656e7469667954797065000000" + "0019417274733a3a547970654964656e74696669636174696f6e000000000200000001" + "00000007737472696e6700000000056e616d6500000000000000000000000000000000" + "000000000000000017417274733a3a466c6f7753797374656d53656e64657200000000" + "00000000020000000a70726f6365737365640000000005766f69640000000001000000" + "00000000000000000b646973636f6e6e6563740000000005766f696400000000020000" + "00000000000000000000000000000000000000000019417274733a3a466c6f77537973" + "74656d52656365697665720000000000000000010000000b646973636f6e6e65637400" + "00000005766f6964000000000200000000000000000000000100000011726563656976" + "6548616e646c6572494400000000056c6f6e6700000000120000000000000000000000" + "0000000011417274733a3a466c6f7753797374656d0000000000000000070000000c73" + "746172744f626a6563740000000005766f6964000000000200000001000000076f626a" + "65637400000000056e6f64650000000000000000000000000b73746f704f626a656374" + "0000000005766f6964000000000200000001000000076f626a65637400000000056e6f" + "64650000000000000000000000000e636f6e6e6563744f626a6563740000000005766f" + "6964000000000200000004000000076f626a656374000000000d736f757263654f626a" + "656374000000000000000007737472696e67000000000b736f75726365506f72740000" + "000000000000076f626a656374000000000b646573744f626a65637400000000000000" + "0007737472696e67000000000964657374506f72740000000000000000000000001164" + "6973636f6e6e6563744f626a6563740000000005766f69640000000002000000040000" + "00076f626a656374000000000d736f757263654f626a65637400000000000000000773" + "7472696e67000000000b736f75726365506f72740000000000000000076f626a656374" + "000000000b646573744f626a656374000000000000000007737472696e670000000009" + "64657374506f72740000000000000000000000000b7175657279466c61677300000000" + "14417274733a3a41747472696275746554797065000000000200000002000000076f62" + "6a65637400000000056e6f6465000000000000000007737472696e670000000005706f" + "72740000000000000000000000000e736574466c6f617456616c75650000000005766f" + "6964000000000200000003000000076f626a65637400000000056e6f64650000000000" + "00000007737472696e670000000005706f7274000000000000000006666c6f61740000" + "00000676616c75650000000000000000000000000f6372656174655265636569766572" + "0000000019417274733a3a466c6f7753797374656d5265636569766572000000000200" + "000003000000076f626a656374000000000b646573744f626a65637400000000000000" + "0007737472696e67000000000964657374506f7274000000000000000017417274733a" + "3a466c6f7753797374656d53656e646572000000000773656e64657200000000000000" + "000000000000000000000000000000000011417274733a3a476c6f62616c436f6d6d00" + "0000000000000003000000047075740000000008626f6f6c65616e0000000002000000" + "0200000007737472696e6700000000097661726961626c650000000000000000077374" + "72696e67000000000676616c7565000000000000000000000000046765740000000007" + "737472696e6700000000020000000100000007737472696e6700000000097661726961" + "626c650000000000000000000000000665726173650000000005766f69640000000002" + "0000000100000007737472696e6700000000097661726961626c650000000000000000" + "0000000000000000000000000000000014417274733a3a546d70476c6f62616c436f6d" + "6d000000000100000011417274733a3a476c6f62616c436f6d6d000000000000000000" + "000000000000000000000012417274733a3a5472616465724f66666572000000000000" + "0000010000000c67657450726f706572747900000000082a737472696e670000000002" + "0000000100000007737472696e6700000000056e616d65000000000000000000000000" + "010000000e696e746572666163654e616d650000000007737472696e67000000001200" + "000000000000000000000000000012417274733a3a5472616465725175657279000000" + "00000000000200000009737570706f7274730000000005766f69640000000002000000" + "0200000007737472696e67000000000970726f70657274790000000000000000077374" + "72696e67000000000676616c7565000000000000000000000000067175657279000000" + "00132a417274733a3a5472616465724f66666572000000000200000000000000000000" + "000000000000000000000000000d417274733a3a4f626a65637400000000000000000e" + "0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e67000000000200000001" + "00000010417274733a3a4d6574686f64446566000000000a6d6574686f644465660000" + "000000000000000000000f5f696e746572666163654e616d650000000007737472696e" + "6700000000020000000000000000000000105f7175657279496e746572666163650000" + "000013417274733a3a496e746572666163654465660000000002000000010000000773" + "7472696e6700000000056e616d650000000000000000000000000b5f71756572795479" + "7065000000000e417274733a3a54797065446566000000000200000001000000077374" + "72696e6700000000056e616d650000000000000000000000000b5f7175657279456e75" + "6d000000000e417274733a3a456e756d44656600000000020000000100000007737472" + "696e6700000000056e616d650000000000000000000000000a5f746f537472696e6700" + "00000007737472696e6700000000020000000000000000000000125f6973436f6d7061" + "7469626c65576974680000000008626f6f6c65616e0000000002000000010000000773" + "7472696e67000000000e696e746572666163656e616d65000000000000000000000000" + "0c5f636f707952656d6f74650000000005766f69640000000002000000000000000000" + "00000b5f75736552656d6f74650000000005766f696400000000020000000000000000" + "0000000f5f72656c6561736552656d6f74650000000005766f69640000000002000000" + "00000000000000000a5f6164644368696c640000000007737472696e67000000000200" + "000002000000076f626a65637400000000066368696c64000000000000000007737472" + "696e6700000000056e616d650000000000000000000000000d5f72656d6f7665436869" + "6c640000000008626f6f6c65616e00000000020000000100000007737472696e670000" + "0000056e616d650000000000000000000000000a5f6765744368696c6400000000076f" + "626a65637400000000020000000100000007737472696e6700000000056e616d650000" + "000000000000000000000f5f71756572794368696c6472656e00000000082a73747269" + "6e6700000000020000000000000000000000010000000c5f666c6f7753797374656d00" + "00000011417274733a3a466c6f7753797374656d000000001200000000000000000000" + "00000000000d417274733a3a4c6f616465720000000000000000010000000b6c6f6164" + "4f626a65637400000000076f626a65637400000000020000000100000012417274733a" + "3a5472616465724f6666657200000000066f6666657200000000000000000000000003" + "0000000c6461746156657273696f6e0000000007737472696e67000000001200000000" + "0000000e747261646572456e747269657300000000132a417274733a3a547261646572" + "456e747279000000001200000000000000086d6f64756c657300000000112a41727473" + "3a3a4d6f64756c65446566000000001200000000000000000000000000000000" +); diff --git a/mcop/core.h b/mcop/core.h new file mode 100644 index 0000000..5ab73e1 --- /dev/null +++ b/mcop/core.h @@ -0,0 +1,1561 @@ +/* this file was generated by the MCOP idl compiler - DO NOT EDIT */ + +#ifndef CORE_H +#define CORE_H + +#include "common.h" +#include "arts_export.h" + +namespace Arts { +enum HeaderMagic {MCOP_MAGIC = 1296256848}; +enum MessageType {mcopMessageInvalid = 0, mcopServerHello = 1, mcopClientHello = 2, mcopAuthAccept = 3, mcopInvocation = 4, mcopReturn = 5, mcopOnewayInvocation = 6}; +enum MethodType {methodOneway = 1, methodTwoway = 2, methodMax = 0xffffffff}; +enum AttributeType {streamIn = 1, streamOut = 2, streamMulti = 4, attributeStream = 8, attributeAttribute = 16, streamAsync = 32, streamDefault = 64}; +enum TypeIdentification {tiUnknown = 0, tiVoid = 1, tiLong = 2, tiByte = 3, tiString = 4, tiBoolean = 5, tiFloat = 6, tiEnum = 128, tiType = 129, tiInterface = 130}; +} +namespace Arts { +class ARTS_EXPORT Header : public Arts::Type { +public: + Header(); + Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType); + Header(Arts::Buffer& stream); + Header(const Header& copyType); + Header& operator=(const Header& assignType); + Arts::HeaderMagic magic; + long messageLength; + Arts::MessageType messageType; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT Invocation : public Arts::Type { +public: + Invocation(); + Invocation(long _a_objectID, long _a_methodID, long _a_requestID); + Invocation(Arts::Buffer& stream); + Invocation(const Invocation& copyType); + Invocation& operator=(const Invocation& assignType); + long objectID; + long methodID; + long requestID; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT OnewayInvocation : public Arts::Type { +public: + OnewayInvocation(); + OnewayInvocation(long _a_objectID, long _a_methodID); + OnewayInvocation(Arts::Buffer& stream); + OnewayInvocation(const OnewayInvocation& copyType); + OnewayInvocation& operator=(const OnewayInvocation& assignType); + long objectID; + long methodID; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT ServerHello : public Arts::Type { +public: + ServerHello(); + ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed); + ServerHello(Arts::Buffer& stream); + ServerHello(const ServerHello& copyType); + ServerHello& operator=(const ServerHello& assignType); + std::string mcopVersion; + std::string serverID; + std::vector<std::string> authProtocols; + std::string authSeed; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT ClientHello : public Arts::Type { +public: + ClientHello(); + ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData); + ClientHello(Arts::Buffer& stream); + ClientHello(const ClientHello& copyType); + ClientHello& operator=(const ClientHello& assignType); + std::string serverID; + std::string authProtocol; + std::string authData; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT AuthAccept : public Arts::Type { +public: + AuthAccept(); + AuthAccept(const std::vector<std::string>& _a_hints); + AuthAccept(Arts::Buffer& stream); + AuthAccept(const AuthAccept& copyType); + AuthAccept& operator=(const AuthAccept& assignType); + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT ObjectReference : public Arts::Type { +public: + ObjectReference(); + ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls); + ObjectReference(Arts::Buffer& stream); + ObjectReference(const ObjectReference& copyType); + ObjectReference& operator=(const ObjectReference& assignType); + std::string serverID; + long objectID; + std::vector<std::string> urls; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT ParamDef : public Arts::Type { +public: + ParamDef(); + ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints); + ParamDef(Arts::Buffer& stream); + ParamDef(const ParamDef& copyType); + ParamDef& operator=(const ParamDef& assignType); + std::string type; + std::string name; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT MethodDef : public Arts::Type { +public: + MethodDef(); + MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints); + MethodDef(Arts::Buffer& stream); + MethodDef(const MethodDef& copyType); + MethodDef& operator=(const MethodDef& assignType); + std::string name; + std::string type; + Arts::MethodType flags; + std::vector<Arts::ParamDef> signature; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT AttributeDef : public Arts::Type { +public: + AttributeDef(); + AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints); + AttributeDef(Arts::Buffer& stream); + AttributeDef(const AttributeDef& copyType); + AttributeDef& operator=(const AttributeDef& assignType); + std::string name; + std::string type; + Arts::AttributeType flags; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT InterfaceDef : public Arts::Type { +public: + InterfaceDef(); + InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints); + InterfaceDef(Arts::Buffer& stream); + InterfaceDef(const InterfaceDef& copyType); + InterfaceDef& operator=(const InterfaceDef& assignType); + std::string name; + std::vector<std::string> inheritedInterfaces; + std::vector<Arts::MethodDef> methods; + std::vector<Arts::AttributeDef> attributes; + std::vector<std::string> defaultPorts; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT TypeComponent : public Arts::Type { +public: + TypeComponent(); + TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints); + TypeComponent(Arts::Buffer& stream); + TypeComponent(const TypeComponent& copyType); + TypeComponent& operator=(const TypeComponent& assignType); + std::string type; + std::string name; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT TypeDef : public Arts::Type { +public: + TypeDef(); + TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints); + TypeDef(Arts::Buffer& stream); + TypeDef(const TypeDef& copyType); + TypeDef& operator=(const TypeDef& assignType); + std::string name; + std::vector<Arts::TypeComponent> contents; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT EnumComponent : public Arts::Type { +public: + EnumComponent(); + EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints); + EnumComponent(Arts::Buffer& stream); + EnumComponent(const EnumComponent& copyType); + EnumComponent& operator=(const EnumComponent& assignType); + std::string name; + long value; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT EnumDef : public Arts::Type { +public: + EnumDef(); + EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints); + EnumDef(Arts::Buffer& stream); + EnumDef(const EnumDef& copyType); + EnumDef& operator=(const EnumDef& assignType); + std::string name; + std::vector<Arts::EnumComponent> contents; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT ModuleDef : public Arts::Type { +public: + ModuleDef(); + ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints); + ModuleDef(Arts::Buffer& stream); + ModuleDef(const ModuleDef& copyType); + ModuleDef& operator=(const ModuleDef& assignType); + std::string moduleName; + std::vector<Arts::EnumDef> enums; + std::vector<Arts::TypeDef> types; + std::vector<Arts::InterfaceDef> interfaces; + std::vector<std::string> hints; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT Any : public Arts::Type { +public: + Any(); + Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value); + Any(Arts::Buffer& stream); + Any(const Any& copyType); + Any& operator=(const Any& assignType); + std::string type; + std::vector<Arts::mcopbyte> value; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +class ARTS_EXPORT TraderEntry : public Arts::Type { +public: + TraderEntry(); + TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines); + TraderEntry(Arts::Buffer& stream); + TraderEntry(const TraderEntry& copyType); + TraderEntry& operator=(const TraderEntry& assignType); + std::string interfaceName; + std::vector<std::string> lines; + +// marshalling functions + void readType(Arts::Buffer& stream); + void writeType(Arts::Buffer& stream) const; + std::string _typeName() const; +}; + +} +namespace Arts { +class InterfaceRepo; +class InterfaceRepoV2; +class FlowSystemSender; +class FlowSystemReceiver; +class FlowSystem; +class GlobalComm; +class TmpGlobalComm; +class TraderOffer; +class TraderQuery; +class Loader; + +class ARTS_EXPORT InterfaceRepo_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static InterfaceRepo_base *_create(const std::string& subClass = "Arts::InterfaceRepo"); + static InterfaceRepo_base *_fromString(std::string objectref); + static InterfaceRepo_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static InterfaceRepo_base *_fromDynamicCast(const Arts::Object& object); + inline InterfaceRepo_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual long insertModule(const Arts::ModuleDef& newModule) = 0; + virtual void removeModule(long moduleID) = 0; + virtual Arts::InterfaceDef queryInterface(const std::string& name) = 0; + virtual Arts::TypeDef queryType(const std::string& name) = 0; + virtual Arts::EnumDef queryEnum(const std::string& name) = 0; + virtual std::vector<std::string> * queryChildren(const std::string& name) = 0; + virtual std::vector<std::string> * queryInterfaces() = 0; + virtual std::vector<std::string> * queryTypes() = 0; + virtual std::vector<std::string> * queryEnums() = 0; +}; + +class ARTS_EXPORT InterfaceRepo_stub : virtual public InterfaceRepo_base, virtual public Arts::Object_stub { +protected: + InterfaceRepo_stub(); + +public: + InterfaceRepo_stub(Arts::Connection *connection, long objectID); + + long insertModule(const Arts::ModuleDef& newModule); + void removeModule(long moduleID); + Arts::InterfaceDef queryInterface(const std::string& name); + Arts::TypeDef queryType(const std::string& name); + Arts::EnumDef queryEnum(const std::string& name); + std::vector<std::string> * queryChildren(const std::string& name); + std::vector<std::string> * queryInterfaces(); + std::vector<std::string> * queryTypes(); + std::vector<std::string> * queryEnums(); +}; + +class ARTS_EXPORT InterfaceRepo_skel : virtual public InterfaceRepo_base, virtual public Arts::Object_skel { +public: + InterfaceRepo_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT InterfaceRepo : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + InterfaceRepo_base *_cache; + inline InterfaceRepo_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(InterfaceRepo_base *)_pool->base->_cast(InterfaceRepo_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline InterfaceRepo(InterfaceRepo_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef InterfaceRepo_base _base_class; + + inline InterfaceRepo() : Arts::Object(_Creator), _cache(0) {} + inline InterfaceRepo(const Arts::SubClass& s) : + Arts::Object(InterfaceRepo_base::_create(s.string())), _cache(0) {} + inline InterfaceRepo(const Arts::Reference &r) : + Arts::Object(r.isString()?(InterfaceRepo_base::_fromString(r.string())):(InterfaceRepo_base::_fromReference(r.reference(),true))), _cache(0) {} + inline InterfaceRepo(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepo_base::_fromDynamicCast(c.object())), _cache(0) {} + inline InterfaceRepo(const InterfaceRepo& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline InterfaceRepo(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static InterfaceRepo null() {return InterfaceRepo((InterfaceRepo_base*)0);} + inline static InterfaceRepo _from_base(InterfaceRepo_base* b) {return InterfaceRepo(b);} + inline InterfaceRepo& operator=(const InterfaceRepo& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline InterfaceRepo_base* _base() {return _cache?_cache:_method_call();} + + inline long insertModule(const Arts::ModuleDef& newModule); + inline void removeModule(long moduleID); + inline Arts::InterfaceDef queryInterface(const std::string& name); + inline Arts::TypeDef queryType(const std::string& name); + inline Arts::EnumDef queryEnum(const std::string& name); + inline std::vector<std::string> * queryChildren(const std::string& name); + inline std::vector<std::string> * queryInterfaces(); + inline std::vector<std::string> * queryTypes(); + inline std::vector<std::string> * queryEnums(); +}; + +class ARTS_EXPORT InterfaceRepoV2_base : virtual public Arts::InterfaceRepo_base { +public: + static unsigned long _IID; // interface ID + + static InterfaceRepoV2_base *_create(const std::string& subClass = "Arts::InterfaceRepoV2"); + static InterfaceRepoV2_base *_fromString(std::string objectref); + static InterfaceRepoV2_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static InterfaceRepoV2_base *_fromDynamicCast(const Arts::Object& object); + inline InterfaceRepoV2_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual Arts::TypeIdentification identifyType(const std::string& name) = 0; +}; + +class ARTS_EXPORT InterfaceRepoV2_stub : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_stub { +protected: + InterfaceRepoV2_stub(); + +public: + InterfaceRepoV2_stub(Arts::Connection *connection, long objectID); + + Arts::TypeIdentification identifyType(const std::string& name); +}; + +class ARTS_EXPORT InterfaceRepoV2_skel : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_skel { +public: + InterfaceRepoV2_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT InterfaceRepoV2 : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + InterfaceRepoV2_base *_cache; + inline InterfaceRepoV2_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(InterfaceRepoV2_base *)_pool->base->_cast(InterfaceRepoV2_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline InterfaceRepoV2(InterfaceRepoV2_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef InterfaceRepoV2_base _base_class; + + inline InterfaceRepoV2() : Arts::Object(_Creator), _cache(0) {} + inline InterfaceRepoV2(const Arts::SubClass& s) : + Arts::Object(InterfaceRepoV2_base::_create(s.string())), _cache(0) {} + inline InterfaceRepoV2(const Arts::Reference &r) : + Arts::Object(r.isString()?(InterfaceRepoV2_base::_fromString(r.string())):(InterfaceRepoV2_base::_fromReference(r.reference(),true))), _cache(0) {} + inline InterfaceRepoV2(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepoV2_base::_fromDynamicCast(c.object())), _cache(0) {} + inline InterfaceRepoV2(const InterfaceRepoV2& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline InterfaceRepoV2(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static InterfaceRepoV2 null() {return InterfaceRepoV2((InterfaceRepoV2_base*)0);} + inline static InterfaceRepoV2 _from_base(InterfaceRepoV2_base* b) {return InterfaceRepoV2(b);} + inline InterfaceRepoV2& operator=(const InterfaceRepoV2& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline operator Arts::InterfaceRepo() const { return Arts::InterfaceRepo(*_pool); } + inline InterfaceRepoV2_base* _base() {return _cache?_cache:_method_call();} + + inline long insertModule(const Arts::ModuleDef& newModule); + inline void removeModule(long moduleID); + inline Arts::InterfaceDef queryInterface(const std::string& name); + inline Arts::TypeDef queryType(const std::string& name); + inline Arts::EnumDef queryEnum(const std::string& name); + inline std::vector<std::string> * queryChildren(const std::string& name); + inline std::vector<std::string> * queryInterfaces(); + inline std::vector<std::string> * queryTypes(); + inline std::vector<std::string> * queryEnums(); + inline Arts::TypeIdentification identifyType(const std::string& name); +}; + +class ARTS_EXPORT FlowSystemSender_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static FlowSystemSender_base *_create(const std::string& subClass = "Arts::FlowSystemSender"); + static FlowSystemSender_base *_fromString(std::string objectref); + static FlowSystemSender_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static FlowSystemSender_base *_fromDynamicCast(const Arts::Object& object); + inline FlowSystemSender_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual void processed() = 0; + virtual void disconnect() = 0; +}; + +class ARTS_EXPORT FlowSystemSender_stub : virtual public FlowSystemSender_base, virtual public Arts::Object_stub { +protected: + FlowSystemSender_stub(); + +public: + FlowSystemSender_stub(Arts::Connection *connection, long objectID); + + void processed(); + void disconnect(); +}; + +class ARTS_EXPORT FlowSystemSender_skel : virtual public FlowSystemSender_base, virtual public Arts::Object_skel { +public: + FlowSystemSender_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT FlowSystemSender : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + FlowSystemSender_base *_cache; + inline FlowSystemSender_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(FlowSystemSender_base *)_pool->base->_cast(FlowSystemSender_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline FlowSystemSender(FlowSystemSender_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef FlowSystemSender_base _base_class; + + inline FlowSystemSender() : Arts::Object(_Creator), _cache(0) {} + inline FlowSystemSender(const Arts::SubClass& s) : + Arts::Object(FlowSystemSender_base::_create(s.string())), _cache(0) {} + inline FlowSystemSender(const Arts::Reference &r) : + Arts::Object(r.isString()?(FlowSystemSender_base::_fromString(r.string())):(FlowSystemSender_base::_fromReference(r.reference(),true))), _cache(0) {} + inline FlowSystemSender(const Arts::DynamicCast& c) : Arts::Object(FlowSystemSender_base::_fromDynamicCast(c.object())), _cache(0) {} + inline FlowSystemSender(const FlowSystemSender& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline FlowSystemSender(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static FlowSystemSender null() {return FlowSystemSender((FlowSystemSender_base*)0);} + inline static FlowSystemSender _from_base(FlowSystemSender_base* b) {return FlowSystemSender(b);} + inline FlowSystemSender& operator=(const FlowSystemSender& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline FlowSystemSender_base* _base() {return _cache?_cache:_method_call();} + + inline void processed(); + inline void disconnect(); +}; + +class ARTS_EXPORT FlowSystemReceiver_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static FlowSystemReceiver_base *_create(const std::string& subClass = "Arts::FlowSystemReceiver"); + static FlowSystemReceiver_base *_fromString(std::string objectref); + static FlowSystemReceiver_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static FlowSystemReceiver_base *_fromDynamicCast(const Arts::Object& object); + inline FlowSystemReceiver_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual long receiveHandlerID() = 0; + virtual void disconnect() = 0; +}; + +class ARTS_EXPORT FlowSystemReceiver_stub : virtual public FlowSystemReceiver_base, virtual public Arts::Object_stub { +protected: + FlowSystemReceiver_stub(); + +public: + FlowSystemReceiver_stub(Arts::Connection *connection, long objectID); + + long receiveHandlerID(); + void disconnect(); +}; + +class ARTS_EXPORT FlowSystemReceiver_skel : virtual public FlowSystemReceiver_base, virtual public Arts::Object_skel { +protected: + // emitters for change notifications + inline void receiveHandlerID_changed(long newValue) { + _emit_changed("receiveHandlerID_changed",newValue); + } + +public: + FlowSystemReceiver_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT FlowSystemReceiver : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + FlowSystemReceiver_base *_cache; + inline FlowSystemReceiver_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(FlowSystemReceiver_base *)_pool->base->_cast(FlowSystemReceiver_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline FlowSystemReceiver(FlowSystemReceiver_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef FlowSystemReceiver_base _base_class; + + inline FlowSystemReceiver() : Arts::Object(_Creator), _cache(0) {} + inline FlowSystemReceiver(const Arts::SubClass& s) : + Arts::Object(FlowSystemReceiver_base::_create(s.string())), _cache(0) {} + inline FlowSystemReceiver(const Arts::Reference &r) : + Arts::Object(r.isString()?(FlowSystemReceiver_base::_fromString(r.string())):(FlowSystemReceiver_base::_fromReference(r.reference(),true))), _cache(0) {} + inline FlowSystemReceiver(const Arts::DynamicCast& c) : Arts::Object(FlowSystemReceiver_base::_fromDynamicCast(c.object())), _cache(0) {} + inline FlowSystemReceiver(const FlowSystemReceiver& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline FlowSystemReceiver(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static FlowSystemReceiver null() {return FlowSystemReceiver((FlowSystemReceiver_base*)0);} + inline static FlowSystemReceiver _from_base(FlowSystemReceiver_base* b) {return FlowSystemReceiver(b);} + inline FlowSystemReceiver& operator=(const FlowSystemReceiver& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline FlowSystemReceiver_base* _base() {return _cache?_cache:_method_call();} + + inline long receiveHandlerID(); + inline void disconnect(); +}; + +class ARTS_EXPORT FlowSystem_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static FlowSystem_base *_create(const std::string& subClass = "Arts::FlowSystem"); + static FlowSystem_base *_fromString(std::string objectref); + static FlowSystem_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static FlowSystem_base *_fromDynamicCast(const Arts::Object& object); + inline FlowSystem_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual void startObject(Arts::Object node) = 0; + virtual void stopObject(Arts::Object node) = 0; + virtual void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0; + virtual void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0; + virtual Arts::AttributeType queryFlags(Arts::Object node, const std::string& port) = 0; + virtual void setFloatValue(Arts::Object node, const std::string& port, float value) = 0; + virtual Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender) = 0; +}; + +class ARTS_EXPORT FlowSystem_stub : virtual public FlowSystem_base, virtual public Arts::Object_stub { +protected: + FlowSystem_stub(); + +public: + FlowSystem_stub(Arts::Connection *connection, long objectID); + + void startObject(Arts::Object node); + void stopObject(Arts::Object node); + void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort); + void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort); + Arts::AttributeType queryFlags(Arts::Object node, const std::string& port); + void setFloatValue(Arts::Object node, const std::string& port, float value); + Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender); +}; + +class ARTS_EXPORT FlowSystem_skel : virtual public FlowSystem_base, virtual public Arts::Object_skel { +public: + FlowSystem_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT FlowSystem : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + FlowSystem_base *_cache; + inline FlowSystem_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(FlowSystem_base *)_pool->base->_cast(FlowSystem_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline FlowSystem(FlowSystem_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef FlowSystem_base _base_class; + + inline FlowSystem() : Arts::Object(_Creator), _cache(0) {} + inline FlowSystem(const Arts::SubClass& s) : + Arts::Object(FlowSystem_base::_create(s.string())), _cache(0) {} + inline FlowSystem(const Arts::Reference &r) : + Arts::Object(r.isString()?(FlowSystem_base::_fromString(r.string())):(FlowSystem_base::_fromReference(r.reference(),true))), _cache(0) {} + inline FlowSystem(const Arts::DynamicCast& c) : Arts::Object(FlowSystem_base::_fromDynamicCast(c.object())), _cache(0) {} + inline FlowSystem(const FlowSystem& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline FlowSystem(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static FlowSystem null() {return FlowSystem((FlowSystem_base*)0);} + inline static FlowSystem _from_base(FlowSystem_base* b) {return FlowSystem(b);} + inline FlowSystem& operator=(const FlowSystem& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline FlowSystem_base* _base() {return _cache?_cache:_method_call();} + + inline void startObject(Arts::Object node); + inline void stopObject(Arts::Object node); + inline void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort); + inline void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort); + inline Arts::AttributeType queryFlags(Arts::Object node, const std::string& port); + inline void setFloatValue(Arts::Object node, const std::string& port, float value); + inline Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender); +}; + +class ARTS_EXPORT GlobalComm_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static GlobalComm_base *_create(const std::string& subClass = "Arts::GlobalComm"); + static GlobalComm_base *_fromString(std::string objectref); + static GlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static GlobalComm_base *_fromDynamicCast(const Arts::Object& object); + inline GlobalComm_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual bool put(const std::string& variable, const std::string& value) = 0; + virtual std::string get(const std::string& variable) = 0; + virtual void erase(const std::string& variable) = 0; +}; + +class ARTS_EXPORT GlobalComm_stub : virtual public GlobalComm_base, virtual public Arts::Object_stub { +protected: + GlobalComm_stub(); + +public: + GlobalComm_stub(Arts::Connection *connection, long objectID); + + bool put(const std::string& variable, const std::string& value); + std::string get(const std::string& variable); + void erase(const std::string& variable); +}; + +class ARTS_EXPORT GlobalComm_skel : virtual public GlobalComm_base, virtual public Arts::Object_skel { +public: + GlobalComm_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT GlobalComm : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + GlobalComm_base *_cache; + inline GlobalComm_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(GlobalComm_base *)_pool->base->_cast(GlobalComm_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline GlobalComm(GlobalComm_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef GlobalComm_base _base_class; + + inline GlobalComm() : Arts::Object(_Creator), _cache(0) {} + inline GlobalComm(const Arts::SubClass& s) : + Arts::Object(GlobalComm_base::_create(s.string())), _cache(0) {} + inline GlobalComm(const Arts::Reference &r) : + Arts::Object(r.isString()?(GlobalComm_base::_fromString(r.string())):(GlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {} + inline GlobalComm(const Arts::DynamicCast& c) : Arts::Object(GlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {} + inline GlobalComm(const GlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline GlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static GlobalComm null() {return GlobalComm((GlobalComm_base*)0);} + inline static GlobalComm _from_base(GlobalComm_base* b) {return GlobalComm(b);} + inline GlobalComm& operator=(const GlobalComm& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline GlobalComm_base* _base() {return _cache?_cache:_method_call();} + + inline bool put(const std::string& variable, const std::string& value); + inline std::string get(const std::string& variable); + inline void erase(const std::string& variable); +}; + +class ARTS_EXPORT TmpGlobalComm_base : virtual public Arts::GlobalComm_base { +public: + static unsigned long _IID; // interface ID + + static TmpGlobalComm_base *_create(const std::string& subClass = "Arts::TmpGlobalComm"); + static TmpGlobalComm_base *_fromString(std::string objectref); + static TmpGlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static TmpGlobalComm_base *_fromDynamicCast(const Arts::Object& object); + inline TmpGlobalComm_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + +}; + +class ARTS_EXPORT TmpGlobalComm_stub : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_stub { +protected: + TmpGlobalComm_stub(); + +public: + TmpGlobalComm_stub(Arts::Connection *connection, long objectID); + +}; + +class ARTS_EXPORT TmpGlobalComm_skel : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_skel { +public: + TmpGlobalComm_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT TmpGlobalComm : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + TmpGlobalComm_base *_cache; + inline TmpGlobalComm_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(TmpGlobalComm_base *)_pool->base->_cast(TmpGlobalComm_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline TmpGlobalComm(TmpGlobalComm_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef TmpGlobalComm_base _base_class; + + inline TmpGlobalComm() : Arts::Object(_Creator), _cache(0) {} + inline TmpGlobalComm(const Arts::SubClass& s) : + Arts::Object(TmpGlobalComm_base::_create(s.string())), _cache(0) {} + inline TmpGlobalComm(const Arts::Reference &r) : + Arts::Object(r.isString()?(TmpGlobalComm_base::_fromString(r.string())):(TmpGlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {} + inline TmpGlobalComm(const Arts::DynamicCast& c) : Arts::Object(TmpGlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {} + inline TmpGlobalComm(const TmpGlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline TmpGlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static TmpGlobalComm null() {return TmpGlobalComm((TmpGlobalComm_base*)0);} + inline static TmpGlobalComm _from_base(TmpGlobalComm_base* b) {return TmpGlobalComm(b);} + inline TmpGlobalComm& operator=(const TmpGlobalComm& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline operator Arts::GlobalComm() const { return Arts::GlobalComm(*_pool); } + inline TmpGlobalComm_base* _base() {return _cache?_cache:_method_call();} + + inline bool put(const std::string& variable, const std::string& value); + inline std::string get(const std::string& variable); + inline void erase(const std::string& variable); +}; + +class ARTS_EXPORT TraderOffer_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static TraderOffer_base *_create(const std::string& subClass = "Arts::TraderOffer"); + static TraderOffer_base *_fromString(std::string objectref); + static TraderOffer_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static TraderOffer_base *_fromDynamicCast(const Arts::Object& object); + inline TraderOffer_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual std::string interfaceName() = 0; + virtual std::vector<std::string> * getProperty(const std::string& name) = 0; +}; + +class ARTS_EXPORT TraderOffer_stub : virtual public TraderOffer_base, virtual public Arts::Object_stub { +protected: + TraderOffer_stub(); + +public: + TraderOffer_stub(Arts::Connection *connection, long objectID); + + std::string interfaceName(); + std::vector<std::string> * getProperty(const std::string& name); +}; + +class ARTS_EXPORT TraderOffer_skel : virtual public TraderOffer_base, virtual public Arts::Object_skel { +protected: + // emitters for change notifications + inline void interfaceName_changed(const std::string& newValue) { + _emit_changed("interfaceName_changed",newValue); + } + +public: + TraderOffer_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT TraderOffer : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + TraderOffer_base *_cache; + inline TraderOffer_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(TraderOffer_base *)_pool->base->_cast(TraderOffer_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline TraderOffer(TraderOffer_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef TraderOffer_base _base_class; + + inline TraderOffer() : Arts::Object(_Creator), _cache(0) {} + inline TraderOffer(const Arts::SubClass& s) : + Arts::Object(TraderOffer_base::_create(s.string())), _cache(0) {} + inline TraderOffer(const Arts::Reference &r) : + Arts::Object(r.isString()?(TraderOffer_base::_fromString(r.string())):(TraderOffer_base::_fromReference(r.reference(),true))), _cache(0) {} + inline TraderOffer(const Arts::DynamicCast& c) : Arts::Object(TraderOffer_base::_fromDynamicCast(c.object())), _cache(0) {} + inline TraderOffer(const TraderOffer& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline TraderOffer(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static TraderOffer null() {return TraderOffer((TraderOffer_base*)0);} + inline static TraderOffer _from_base(TraderOffer_base* b) {return TraderOffer(b);} + inline TraderOffer& operator=(const TraderOffer& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline TraderOffer_base* _base() {return _cache?_cache:_method_call();} + + inline std::string interfaceName(); + inline std::vector<std::string> * getProperty(const std::string& name); +}; + +class ARTS_EXPORT TraderQuery_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static TraderQuery_base *_create(const std::string& subClass = "Arts::TraderQuery"); + static TraderQuery_base *_fromString(std::string objectref); + static TraderQuery_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static TraderQuery_base *_fromDynamicCast(const Arts::Object& object); + inline TraderQuery_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual void supports(const std::string& property, const std::string& value) = 0; + virtual std::vector<Arts::TraderOffer> * query() = 0; +}; + +class ARTS_EXPORT TraderQuery_stub : virtual public TraderQuery_base, virtual public Arts::Object_stub { +protected: + TraderQuery_stub(); + +public: + TraderQuery_stub(Arts::Connection *connection, long objectID); + + void supports(const std::string& property, const std::string& value); + std::vector<Arts::TraderOffer> * query(); +}; + +class ARTS_EXPORT TraderQuery_skel : virtual public TraderQuery_base, virtual public Arts::Object_skel { +public: + TraderQuery_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT TraderQuery : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + TraderQuery_base *_cache; + inline TraderQuery_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(TraderQuery_base *)_pool->base->_cast(TraderQuery_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline TraderQuery(TraderQuery_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef TraderQuery_base _base_class; + + inline TraderQuery() : Arts::Object(_Creator), _cache(0) {} + inline TraderQuery(const Arts::SubClass& s) : + Arts::Object(TraderQuery_base::_create(s.string())), _cache(0) {} + inline TraderQuery(const Arts::Reference &r) : + Arts::Object(r.isString()?(TraderQuery_base::_fromString(r.string())):(TraderQuery_base::_fromReference(r.reference(),true))), _cache(0) {} + inline TraderQuery(const Arts::DynamicCast& c) : Arts::Object(TraderQuery_base::_fromDynamicCast(c.object())), _cache(0) {} + inline TraderQuery(const TraderQuery& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline TraderQuery(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static TraderQuery null() {return TraderQuery((TraderQuery_base*)0);} + inline static TraderQuery _from_base(TraderQuery_base* b) {return TraderQuery(b);} + inline TraderQuery& operator=(const TraderQuery& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline TraderQuery_base* _base() {return _cache?_cache:_method_call();} + + inline void supports(const std::string& property, const std::string& value); + inline std::vector<Arts::TraderOffer> * query(); +}; + +class ARTS_EXPORT Loader_base : virtual public Arts::Object_base { +public: + static unsigned long _IID; // interface ID + + static Loader_base *_create(const std::string& subClass = "Arts::Loader"); + static Loader_base *_fromString(std::string objectref); + static Loader_base *_fromReference(Arts::ObjectReference ref, bool needcopy); + + static Loader_base *_fromDynamicCast(const Arts::Object& object); + inline Loader_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + void *_cast(unsigned long iid); + + virtual std::string dataVersion() = 0; + virtual std::vector<Arts::TraderEntry> * traderEntries() = 0; + virtual std::vector<Arts::ModuleDef> * modules() = 0; + virtual Arts::Object loadObject(Arts::TraderOffer offer) = 0; +}; + +class ARTS_EXPORT Loader_stub : virtual public Loader_base, virtual public Arts::Object_stub { +protected: + Loader_stub(); + +public: + Loader_stub(Arts::Connection *connection, long objectID); + + std::string dataVersion(); + std::vector<Arts::TraderEntry> * traderEntries(); + std::vector<Arts::ModuleDef> * modules(); + Arts::Object loadObject(Arts::TraderOffer offer); +}; + +class ARTS_EXPORT Loader_skel : virtual public Loader_base, virtual public Arts::Object_skel { +protected: + // emitters for change notifications + inline void dataVersion_changed(const std::string& newValue) { + _emit_changed("dataVersion_changed",newValue); + } + +public: + Loader_skel(); + + static std::string _interfaceNameSkel(); + std::string _interfaceName(); + bool _isCompatibleWith(const std::string& interfacename); + void _buildMethodTable(); + void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID); +}; + +} +#include "reference.h" +namespace Arts { +class ARTS_EXPORT Loader : public Arts::Object { +private: + static Arts::Object_base* _Creator(); + Loader_base *_cache; + inline Loader_base *_method_call() { + _pool->checkcreate(); + if(_pool->base) { + _cache=(Loader_base *)_pool->base->_cast(Loader_base::_IID); + assert(_cache); + } + return _cache; + } + +protected: + inline Loader(Loader_base* b) : Arts::Object(b), _cache(0) {} + + +public: + typedef Loader_base _base_class; + + inline Loader() : Arts::Object(_Creator), _cache(0) {} + inline Loader(const Arts::SubClass& s) : + Arts::Object(Loader_base::_create(s.string())), _cache(0) {} + inline Loader(const Arts::Reference &r) : + Arts::Object(r.isString()?(Loader_base::_fromString(r.string())):(Loader_base::_fromReference(r.reference(),true))), _cache(0) {} + inline Loader(const Arts::DynamicCast& c) : Arts::Object(Loader_base::_fromDynamicCast(c.object())), _cache(0) {} + inline Loader(const Loader& target) : Arts::Object(target._pool), _cache(target._cache) {} + inline Loader(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {} + inline static Loader null() {return Loader((Loader_base*)0);} + inline static Loader _from_base(Loader_base* b) {return Loader(b);} + inline Loader& operator=(const Loader& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _cache = target._cache; + _pool->Inc(); + return *this; + } + inline Loader_base* _base() {return _cache?_cache:_method_call();} + + inline std::string dataVersion(); + inline std::vector<Arts::TraderEntry> * traderEntries(); + inline std::vector<Arts::ModuleDef> * modules(); + inline Arts::Object loadObject(Arts::TraderOffer offer); +}; + +} +// Forward wrapper calls to _base classes: + +inline long Arts::InterfaceRepo::insertModule(const Arts::ModuleDef& newModule) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule); +} + +inline void Arts::InterfaceRepo::removeModule(long moduleID) +{ + _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID); +} + +inline Arts::InterfaceDef Arts::InterfaceRepo::queryInterface(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name); +} + +inline Arts::TypeDef Arts::InterfaceRepo::queryType(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name); +} + +inline Arts::EnumDef Arts::InterfaceRepo::queryEnum(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name); +} + +inline std::vector<std::string> * Arts::InterfaceRepo::queryChildren(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name); +} + +inline std::vector<std::string> * Arts::InterfaceRepo::queryInterfaces() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces(); +} + +inline std::vector<std::string> * Arts::InterfaceRepo::queryTypes() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes(); +} + +inline std::vector<std::string> * Arts::InterfaceRepo::queryEnums() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums(); +} + +inline long Arts::InterfaceRepoV2::insertModule(const Arts::ModuleDef& newModule) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule); +} + +inline void Arts::InterfaceRepoV2::removeModule(long moduleID) +{ + _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID); +} + +inline Arts::InterfaceDef Arts::InterfaceRepoV2::queryInterface(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name); +} + +inline Arts::TypeDef Arts::InterfaceRepoV2::queryType(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name); +} + +inline Arts::EnumDef Arts::InterfaceRepoV2::queryEnum(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name); +} + +inline std::vector<std::string> * Arts::InterfaceRepoV2::queryChildren(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name); +} + +inline std::vector<std::string> * Arts::InterfaceRepoV2::queryInterfaces() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces(); +} + +inline std::vector<std::string> * Arts::InterfaceRepoV2::queryTypes() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes(); +} + +inline std::vector<std::string> * Arts::InterfaceRepoV2::queryEnums() +{ + return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums(); +} + +inline Arts::TypeIdentification Arts::InterfaceRepoV2::identifyType(const std::string& name) +{ + return _cache?static_cast<Arts::InterfaceRepoV2_base*>(_cache)->identifyType(name):static_cast<Arts::InterfaceRepoV2_base*>(_method_call())->identifyType(name); +} + +inline void Arts::FlowSystemSender::processed() +{ + _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->processed():static_cast<Arts::FlowSystemSender_base*>(_method_call())->processed(); +} + +inline void Arts::FlowSystemSender::disconnect() +{ + _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemSender_base*>(_method_call())->disconnect(); +} + +inline long Arts::FlowSystemReceiver::receiveHandlerID() +{ + return _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->receiveHandlerID():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->receiveHandlerID(); +} + +inline void Arts::FlowSystemReceiver::disconnect() +{ + _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->disconnect(); +} + +inline void Arts::FlowSystem::startObject(Arts::Object node) +{ + _cache?static_cast<Arts::FlowSystem_base*>(_cache)->startObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->startObject(node); +} + +inline void Arts::FlowSystem::stopObject(Arts::Object node) +{ + _cache?static_cast<Arts::FlowSystem_base*>(_cache)->stopObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->stopObject(node); +} + +inline void Arts::FlowSystem::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) +{ + _cache?static_cast<Arts::FlowSystem_base*>(_cache)->connectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->connectObject(sourceObject, sourcePort, destObject, destPort); +} + +inline void Arts::FlowSystem::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) +{ + _cache?static_cast<Arts::FlowSystem_base*>(_cache)->disconnectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->disconnectObject(sourceObject, sourcePort, destObject, destPort); +} + +inline Arts::AttributeType Arts::FlowSystem::queryFlags(Arts::Object node, const std::string& port) +{ + return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->queryFlags(node, port):static_cast<Arts::FlowSystem_base*>(_method_call())->queryFlags(node, port); +} + +inline void Arts::FlowSystem::setFloatValue(Arts::Object node, const std::string& port, float value) +{ + _cache?static_cast<Arts::FlowSystem_base*>(_cache)->setFloatValue(node, port, value):static_cast<Arts::FlowSystem_base*>(_method_call())->setFloatValue(node, port, value); +} + +inline Arts::FlowSystemReceiver Arts::FlowSystem::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender) +{ + return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->createReceiver(destObject, destPort, sender):static_cast<Arts::FlowSystem_base*>(_method_call())->createReceiver(destObject, destPort, sender); +} + +inline bool Arts::GlobalComm::put(const std::string& variable, const std::string& value) +{ + return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value); +} + +inline std::string Arts::GlobalComm::get(const std::string& variable) +{ + return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable); +} + +inline void Arts::GlobalComm::erase(const std::string& variable) +{ + _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable); +} + +inline bool Arts::TmpGlobalComm::put(const std::string& variable, const std::string& value) +{ + return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value); +} + +inline std::string Arts::TmpGlobalComm::get(const std::string& variable) +{ + return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable); +} + +inline void Arts::TmpGlobalComm::erase(const std::string& variable) +{ + _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable); +} + +inline std::string Arts::TraderOffer::interfaceName() +{ + return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->interfaceName():static_cast<Arts::TraderOffer_base*>(_method_call())->interfaceName(); +} + +inline std::vector<std::string> * Arts::TraderOffer::getProperty(const std::string& name) +{ + return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->getProperty(name):static_cast<Arts::TraderOffer_base*>(_method_call())->getProperty(name); +} + +inline void Arts::TraderQuery::supports(const std::string& property, const std::string& value) +{ + _cache?static_cast<Arts::TraderQuery_base*>(_cache)->supports(property, value):static_cast<Arts::TraderQuery_base*>(_method_call())->supports(property, value); +} + +inline std::vector<Arts::TraderOffer> * Arts::TraderQuery::query() +{ + return _cache?static_cast<Arts::TraderQuery_base*>(_cache)->query():static_cast<Arts::TraderQuery_base*>(_method_call())->query(); +} + +inline std::string Arts::Loader::dataVersion() +{ + return _cache?static_cast<Arts::Loader_base*>(_cache)->dataVersion():static_cast<Arts::Loader_base*>(_method_call())->dataVersion(); +} + +inline std::vector<Arts::TraderEntry> * Arts::Loader::traderEntries() +{ + return _cache?static_cast<Arts::Loader_base*>(_cache)->traderEntries():static_cast<Arts::Loader_base*>(_method_call())->traderEntries(); +} + +inline std::vector<Arts::ModuleDef> * Arts::Loader::modules() +{ + return _cache?static_cast<Arts::Loader_base*>(_cache)->modules():static_cast<Arts::Loader_base*>(_method_call())->modules(); +} + +inline Arts::Object Arts::Loader::loadObject(Arts::TraderOffer offer) +{ + return _cache?static_cast<Arts::Loader_base*>(_cache)->loadObject(offer):static_cast<Arts::Loader_base*>(_method_call())->loadObject(offer); +} + +#endif /* CORE_H */ diff --git a/mcop/core.idl b/mcop/core.idl new file mode 100644 index 0000000..33081e7 --- /dev/null +++ b/mcop/core.idl @@ -0,0 +1,715 @@ +/* + + Copyright (C) 1999-2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +module Arts { +// MCOP protocol + +enum HeaderMagic { MCOP_MAGIC = 0x4d434f50 }; /* gets marshalled as "MCOP" */ + /* decimal 1296256848 */ +enum MessageType { + mcopMessageInvalid = 0, /* never send this */ + mcopServerHello = 1, + mcopClientHello = 2, + mcopAuthAccept = 3, + mcopInvocation = 4, + mcopReturn = 5, + mcopOnewayInvocation = 6 +}; + +/** + * This type is sent as header of each MCOP message. + */ +struct Header { + /** + * the value 0x504f434d, which is marshalled as MCOP + */ + HeaderMagic magic; + long messageLength; + MessageType messageType; +}; + +/** + * This is sent as start of each normal (twoway) invocation + */ +struct Invocation { + /** + * The ID of the object receiving the request + */ + long objectID; + /** + * The ID of the method that is to be invoked + */ + long methodID; + /** + * A unique number of the request (needed to send the return code back) + */ + long requestID; +}; + +/** + * This is sent as start of each oneway invocation + */ +struct OnewayInvocation { + /** + * The ID of the object receiving the request + */ + long objectID; + /** + * The ID of the method that is to be invoked + */ + long methodID; +}; + +/** + * Body of the mcopServerHello MCOP message + */ +struct ServerHello { + string mcopVersion; + string serverID; + sequence<string> authProtocols; + string authSeed; +}; + +/** + * Body of the mcopClientHello MCOP message + */ +struct ClientHello { + string serverID; + string authProtocol; + string authData; +}; + +/** + * The message you get when you connect a MCOP server. The MCOP server can + * send you some useful information here. Usually, it will send you + * + * GlobalComm=<object reference of a global comm interface> + * InterfaceRepo=<object reference of an interface repository> + * + * But as this is called "hints" it doesn't necessarily need to happen. + */ +struct AuthAccept { + sequence<string> hints; +}; + +/** + * An object reference + */ +struct ObjectReference { + /** + * A unique ID for the server the object is located on, (a server ID may + * i.e. be composed of start time, hostname, and pid) + */ + string serverID; + + /** + * The number of the object under that server + */ + long objectID; + + /** + * where the server holding object can be reached + */ + sequence<string> urls; +}; + +// Interface definitions + +/** + * The definition of a parameter of a method + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct ParamDef { + string type; + string name; + sequence<string> hints; +}; + +/** + * Twoway methods are such where the calling process does a call and is + * suspended until some result (maybe even a void result) gets back. + * + * Oneway methods are one shot and forget methods: you send the invocation, + * and continue. Maybe it will be received, maybe executed later. You will + * never hear the result. + */ +enum MethodType { + methodOneway = 1, + methodTwoway = 2 +}; + +/** + * The definition of a method. + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct MethodDef { + string name; + string type; + MethodType flags; + + sequence<ParamDef> signature; + sequence<string> hints; +}; + +/** + * an attribute + * + * flags should contain things like + * + * @li attribute is readonly/writeonly/readwrite + * @li attribute is incoming/outgoing stream + * @li if it's a stream, it also should contain the information whether it is + * asynchronous or synchronous + * @li NB20000320: see InterfaceDef for the meaning of streamDefault + */ +enum AttributeType { + streamIn = 1, + streamOut = 2, + streamMulti = 4, + attributeStream = 8, + attributeAttribute = 16, + streamAsync = 32, + streamDefault = 64 +}; + +/** + * The definition of an attribute and/or stream + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct AttributeDef { + string name; + string type; + AttributeType flags; + sequence<string> hints; +}; + +/** + * InterfaceDef - interface definition structure + * + * defines what methods/attributes a particular interface supports: these + * do not contain the methods/attributes of inherited interfaces. + * + * inheritedInterfaces only contains the names of Interfaces that this one + * inherits in exactly one step. So to see if interface XYZ is inherited + * from ABC, you need to check the "inheritedInterfaces" of XYZ, and their + * "inheritedInterfaces" and their "inheritedInterfaces" and so on. + * + * - NB20000320: defaultPorts allows to connect to those port by default if + * connection is made in the corresponding direction. + * It cannot be just an attribute flag because of the syntax + * on a separate line. + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ + +struct InterfaceDef { + string name; + + sequence<string> inheritedInterfaces; + sequence<MethodDef> methods; + sequence<AttributeDef> attributes; + + sequence<string> defaultPorts; + sequence<string> hints; +}; + +// Type definitions (struct's and such) + +/** + * One component of a struct + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct TypeComponent { + string type; + string name; + sequence<string> hints; +}; + +/** + * The definition of a struct + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct TypeDef { + string name; + + sequence<TypeComponent> contents; + sequence<string> hints; +}; + +/** + * One item of an enum value + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct EnumComponent { + string name; + + long value; + sequence<string> hints; +}; + +/** + * The definition of an enum + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct EnumDef { + /** + * name if the enum, "_anonymous_" for anonymous enum - of course, when + * using namespaces, this can also lead to things like "Arts::_anonymous_", + * which would mean an anonymous enum in the Arts namespace + */ + string name; + + sequence<EnumComponent> contents; + sequence<string> hints; +}; + +/** + * The contents of an idl file + * + * hints is reserved for future extensions, such as default, min and maxvalues + */ +struct ModuleDef { + string moduleName; + + sequence<EnumDef> enums; + sequence<TypeDef> types; + sequence<InterfaceDef> interfaces; + sequence<string> hints; +}; + +/** + * The interface repository + */ +interface InterfaceRepo { + /** + * inserts the contents of a module into the interface repository + * + * @returns an ID which can be used to remove the entry again + */ + long insertModule(ModuleDef newModule); + + /** + * removes the contents of a module from the interface repository + */ + void removeModule(long moduleID); + + /** + * queries the definition of an interface + */ + InterfaceDef queryInterface(string name); + + /** + * queries the definition of a type + */ + TypeDef queryType(string name); + + /** + * queries the definition of an enum value + */ + EnumDef queryEnum(string name); + + /** + * queries all interfaces that inherit a given interface + */ + sequence<string> queryChildren(string name); + + /** + * queries all interfaces + */ + sequence<string> queryInterfaces(); + + /** + * queries all types + */ + sequence<string> queryTypes(); + + /** + * queries all enums + */ + sequence<string> queryEnums(); +}; + +enum TypeIdentification { + tiUnknown = 0, + tiVoid = 1, + tiLong = 2, + tiByte = 3, + tiString = 4, + tiBoolean = 5, + tiFloat = 6, + tiEnum = 128, + tiType = 129, + tiInterface = 130 +}; + +interface InterfaceRepoV2 : InterfaceRepo { + /** + * identifies whether a type is a primitive, enum, type or interface, + * or not known at all + */ + TypeIdentification identifyType(string name); +}; + +/** + * Flow System interface + */ + +/** + * Internal use: implement distributed asynchronous streams. + * + * The FlowSystemSender object transmits the packets that should be sent + * over the stream via _allocCustomMessage (Object_base). + */ +interface FlowSystemSender { + /** + * This method is invoked whenever the receiver has finished processing + * a packet of the stream + */ + oneway void processed(); + + /** + * This method is for telling the local FlowSystemSender to break the + * connection to the remote Receiver (it's not intended to be called + * remotely) + */ + void disconnect(); +}; + +/** + * Internal use: implement distributed asynchronous streams. + * + * The FlowSystemReceiver object receives and extracts the packets sent by + * the sender object and injects them in the notification system again. + */ +interface FlowSystemReceiver { + /** + * The custom message ID which should be used to send the stream packets + */ + readonly attribute long receiveHandlerID; + + /** + * This method is for telling the local FlowSystemReceiver to break the + * connection to the remote Sender (it's not intended to be called + * remotely) + */ + void disconnect(); +}; + +/** + * A flow system. + * + * Flow systems handle the streaming between MCOP objects. As this streaming + * is network transparent (at least for asynchronous streams) they have this + * remote interface. + */ +interface FlowSystem { + /** + * This starts a scheduling node + * + * Don't use this manually. Use object->_node()->connect(...) instead. + */ + void startObject(object node); + + /** + * This stops a scheduling node + * + * Don't use this manually. Use object->_node()->connect(...) instead. + */ + void stopObject(object node); + + /** + * This connects two objects, maybe even remote + * + * it is important that + * - sourceObject/sourcePort points to the node the signal flow is + * coming from + * - destObject/destPort points to the node/port the signal flow is + * going to + * + * Don't use this manually. Use object->_node()->connect(...) instead. + */ + void connectObject(object sourceObject, string sourcePort, + object destObject, string destPort); + + /** + * This disconnects two objects, maybe even remote + * + * it is important that + * @li sourceObject/sourcePort points to the node the signal flow is + * coming from + * @li destObject/destPort points to the node/port the signal flow is + * going to + * + * Don't use this manually. Use object->_node()->connect(...) instead. + */ + void disconnectObject(object sourceObject, string sourcePort, + object destObject, string destPort); + + /** + * queries the stream flags - returns 0 when such a stream isn't + * present + */ + AttributeType queryFlags(object node, string port); + + /** + * directly sets an audio port to a fixed value + */ + void setFloatValue(object node, string port, float value); + + /** + * network transparent connections + */ + FlowSystemReceiver createReceiver(object destObject, string destPort, + FlowSystemSender sender); +}; + +/** + * A global communication space used to obtain initial object references + * + * MCOP needs a way to connect to initial (global) object references. This + * is done by these global communication spaces. + */ +interface GlobalComm { + /** + * puts a variable/value pair into the global communication + * space - it will not change the value of the variable if it is + * already present. Returns true if success, false if the variable + * was already there. + */ + boolean put(string variable, string value); + + /** + * gets the value of a variable out of the global communication + * space - it returns an empty string when the variable isn't there + */ + string get(string variable); + + /** + * removes a variable from the global communication space + */ + void erase(string variable); +}; + +/** + * global communication based on the /tmp/mcop-<username> directory + */ +interface TmpGlobalComm : GlobalComm { +}; + +/* + * Trading interfaces follow - trading is used to locate objects with certain + * properties. This is especially recommended, if you want to allow that after + * your code has been released, people can extend it, without changing your + * code, by adding new components. + */ + +/** + * TraderOffer - this contains an offer of an object (which is usually returned + * as result of a query. + */ +interface TraderOffer { + /** + * You can use this interface name to create one of the objects that + * fulfill your query + */ + readonly attribute string interfaceName; + + /** + * This allows you to query additional information about the offer, + * such as the author of the plugin, the name of the library that + * implements it (if it is a library) or similar. + * + * Since some properties support having multiple values, this always + * returns a sequence<string>, which may be empty if the property isn't + * present at all. + */ + sequence<string> getProperty(string name); +}; + +/** + * TraderQuery - this is a query against the trader. The idea is simple: you + * say what you need, and the trader offers you components that do what you + * want. + */ +interface TraderQuery { + /** + * This restricts the query to only objects which support a "property" + * with the value "value". For instance, you could say + * + * aquery.supports("Interface","Arts::PlayObject"); + * + * to restrict the matching objects to only those that support the + * interface Arts::PlayObject + */ + void supports(string property, string value); + + /** + * This performs the query, and returns a set of results + */ + sequence<TraderOffer> query(); +}; + +/** + * Arts::Object is the base object that every interface implicitely inherits + * + * it is also the source for generation of the Object_stub stuff + * (use mcopidl -e Arts::Object to avoid code generation for this interface) + */ +interface Object { + /** + * access to the flow system this object is running in + */ + readonly attribute FlowSystem _flowSystem; + + /** <interface description> + * returns the ID for methodinvocations to this specific method + * methodID = 0 => _lookupMethod (always) + */ + long _lookupMethod(MethodDef methodDef); + + /** <interface description> + * returns the name of the interface + * methodID = 1 => _interfaceName (always) + */ + string _interfaceName(); + + /** <interface description> + * returns the interface description to a given interface + * methodID = 2 => _queryInterface (always) + */ + InterfaceDef _queryInterface(string name); + + /** <interface description> + * returns the type description to a given type + * methodID = 3 => _queryType (always) + */ + TypeDef _queryType(string name); + + /** <interface description> + * returns the enum description to a given enum + * methodID = 4 => _queryEnum (always) + */ + EnumDef _queryEnum(string name); + + /** + * stringifies the object to one string + */ + string _toString(); + + /** <interface description> + * Run-time type compatibility check + */ + boolean _isCompatibleWith(string interfacename); + + /** <reference counting> + * prepares object for remote transmission (so that it will not be freed + * soon, since the remote receiver expects it to be there after receiving + * it) + */ + void _copyRemote(); + + /** <reference counting> + * declares that the object is used remotely now (do that only after + * _copyRemote) + */ + void _useRemote(); + + /** <reference counting> + * declares that the object is no longer used remotely + */ + void _releaseRemote(); + + /** <aggregation> + * add a child object - this makes this object hold a strong reference to + * the child object (i.e. the child object will stay alive at least as + * long as the object does) + * + * if there is already a child with the same name, a postfix will be added + * automatically (i.e. if you add an object named "view" twice, the first + * will be called view, the second view1). + */ + string _addChild(object child, string name); + + /** <aggregation> + * removes a child object + */ + boolean _removeChild(string name); + + /** <aggregation> + * gets a child object + */ + object _getChild(string name); + + /** <aggregation> + * lists all children + */ + sequence<string> _queryChildren(); +}; + +/** + * a simple struct which can hold any other type + */ +struct Any { + string type; + sequence<byte> value; +}; + +/** + * TraderEntries as produced by the loader + */ + +struct TraderEntry { + string interfaceName; + sequence<string> lines; +}; + +/** + * loader to load plugins (implemented in some language/binary format) + */ +interface Loader { + object loadObject(TraderOffer offer); + + /* + * this is used for the type system to cache your trader data and + * module data as long as it stays unchanged + */ + readonly attribute string dataVersion; + + /* + * the trader entries of the components that can be loaded + */ + readonly attribute sequence<TraderEntry> traderEntries; + + /* + * the interface information of the components that can be loaded + */ + readonly attribute sequence<ModuleDef> modules; +}; + +}; diff --git a/mcop/datapacket.cc b/mcop/datapacket.cc new file mode 100644 index 0000000..8f9848f --- /dev/null +++ b/mcop/datapacket.cc @@ -0,0 +1,65 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <string.h> +#include "datapacket.h" +#include "buffer.h" + +using namespace Arts; + +long GenericDataPacket::_staticDataPacketCount = 0; + +/**** specific DataPacket types ****/ + +void FloatDataPacket::read(Buffer& stream) +{ + size = stream.readLong(); + ensureCapacity(size); + for(int i=0;i<size;i++) contents[i] = stream.readFloat(); +} + +void FloatDataPacket::write(Buffer& stream) +{ + stream.writeLong(size); + for(int i=0;i<size;i++) stream.writeFloat(contents[i]); +} + +void ByteDataPacket::read(Buffer& stream) +{ + size = stream.readLong(); + ensureCapacity(size); + + // we know that bytes are marshalled as bytes, + // so we can read them as block + unsigned char *buffer = (unsigned char *)stream.read(size); + if(buffer) + memcpy(contents,buffer,size); +} + +void ByteDataPacket::write(Buffer& stream) +{ + // we know that bytes are marshalled as bytes, + // so we can write them as block + + stream.writeLong(size); + stream.write(contents,size); +} diff --git a/mcop/datapacket.h b/mcop/datapacket.h new file mode 100644 index 0000000..34cd211 --- /dev/null +++ b/mcop/datapacket.h @@ -0,0 +1,230 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef DATAPACKET_H +#define DATAPACKET_H + +#include "arts_export.h" +#include "buffer.h" + +/* + * BC - Status (2002-03-08): GenericDataChannel, DataPacket types + * + * These classes must be kept binary compatible, as the do interact with + * generated code. So you MUST KNOW WHAT YOU ARE DOING, once you start + * using the provided d pointers for extensions. + */ + +namespace Arts { +class GenericDataChannelPrivate; +class GenericDataPacket; +/* + * The GenericDataChannel interface is to be implemented by the flowsystem + */ +class ARTS_EXPORT GenericDataChannel { +private: + GenericDataChannelPrivate *d; // unused + +protected: + friend class GenericDataPacket; + + /* + * this is used internally by DataPacket + */ + virtual void processedPacket(GenericDataPacket *packet) = 0; + + /* + * used internally by DataPacket + */ + virtual void sendPacket(GenericDataPacket *packet) = 0; + +public: + /* + * used to set pull delivery mode + */ + virtual void setPull(int packets, int capacity) = 0; + virtual void endPull() = 0; + + GenericDataChannel() : d(0) + { + } +}; + +/* + * DataPackets are the heard of asynchronous streaming (MCOP has synchronous + * and asynchronous streams). They are used + * + * - in the interface async streams expose to C++ implementations of MCOP + * interfaces (they directly deal with datapackets) + * + * - from the FlowSystem implemenentations + */ + +/** + * The GenericDataPacket class provides the interface the flow system can + * use to deal with data packets. + */ +class GenericDataPacketPrivate; + +class ARTS_EXPORT GenericDataPacket { +private: + GenericDataPacketPrivate *d; + static long _staticDataPacketCount; + +public: + /** + * the amount of active data packets (memory leak debugging only) + */ + static long _dataPacketCount() { return _staticDataPacketCount; } + + /** + * the channel this datapacket belongs to + */ + GenericDataChannel *channel; + + /** + * ensureCapactity ensures that there is room for at least capacity + * Elements in the packet. This is implemented destructive - that + * means: you may not find your old contents in the packet after + * calling ensureCapacity + */ + virtual void ensureCapacity(int capacity) = 0; + + /** + * read/write write the contents of the packet. Read will also + * automatically ensure that capacity is adapted before reading. + */ + virtual void read(Buffer& stream) = 0; + virtual void write(Buffer& stream) = 0; + + /** + * having size here (and not in the derived concrete DataPackets) is so + * that we can see whether the sender can't supply more data (and starts + * sending zero size packets + */ + int size; + + /** + * useCount is to be set from sendPacket + */ + int useCount; + + inline void send() + { + channel->sendPacket(this); + } + inline void processed() + { + useCount--; + if(useCount == 0) + { + if(channel) + channel->processedPacket(this); + else + delete this; + } + } + + virtual ~GenericDataPacket() + { + _staticDataPacketCount--; + } + +protected: + GenericDataPacket(GenericDataChannel *channel) + :d(0),channel(channel),useCount(0) + { + _staticDataPacketCount++; + } +}; + +/** + * The DataPacket<T> interface is what C++ implementations of MCOP interfaces + * will need to use. + */ +template<class T> +class DataPacket : public GenericDataPacket { +public: + T *contents; + +protected: + DataPacket(GenericDataChannel *channel) + : GenericDataPacket(channel) {} + ~DataPacket() {} +}; + +/** + * The RawDataPacket<T> interface handles raw class T arrays of data + */ +template<class T> +class RawDataPacket : public DataPacket<T> { +protected: + int capacity; + void ensureCapacity(int newCapacity) + { + if(newCapacity > capacity) + { + delete[] this->contents; + capacity = newCapacity; + this->contents = new T[capacity]; + } + } + RawDataPacket(int capacity, GenericDataChannel *channel) + :DataPacket<T>(channel), capacity(capacity) + { + this->size = capacity; + this->contents = new T[capacity]; + } + ~RawDataPacket() + { + delete[] this->contents; + } +}; + +/** + * FloatDataPacket finally is one concrete DataPacket (which contains the + * information how to marshal a datapacket of type float) + */ +class ARTS_EXPORT FloatDataPacket : public RawDataPacket<float> { +public: + FloatDataPacket(int capacity, GenericDataChannel *channel) + : RawDataPacket<float>(capacity, channel) + { + // + } + void read(Buffer& stream); + void write(Buffer& stream); +}; + +class ARTS_EXPORT ByteDataPacket : public RawDataPacket<mcopbyte> { +public: + ByteDataPacket(int capacity, GenericDataChannel *channel) + : RawDataPacket<mcopbyte>(capacity, channel) + { + // + } + void read(Buffer& stream); + void write(Buffer& stream); +}; + +} +#endif diff --git a/mcop/debug.cc b/mcop/debug.cc new file mode 100644 index 0000000..208727b --- /dev/null +++ b/mcop/debug.cc @@ -0,0 +1,821 @@ + /* + + Copyright (C) 2000-2002 Stefan Westerfeld + stefan@space.twc.de + + (see also below for details on the copyright of arts_strdup_printf, + which is taken from GLib) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "debug.h" +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include "thread.h" + +static int arts_debug_level = Arts::Debug::lInfo; +static bool arts_debug_abort = false; +static const char *arts_debug_prefix = ""; +static char *messageAppName = 0; +static Arts::Mutex *arts_debug_mutex = 0; + +/* routines for variable length sprintf without buffer overflow (from GLib) */ +static char* arts_strdup_vprintf(const char *format, va_list args1); + +namespace Arts { + +static char * shell_quote(const char *s) +{ + char *result; + char *p; + p = result = static_cast<char*>( malloc(strlen(s)*5+1) ); + while(*s) + { + if (*s == '\'') + { + *p++ = '\''; + *p++ = '"'; + *p++ = *s++; + *p++ = '"'; + *p++ = '\''; + } + else + { + *p++ = *s++; + } + } + *p = '\0'; + return result; +} + +/* + * Call the graphical application to display a message, if + * defined. Otherwise, send to standard error. Debug messages are + * always sent to standard error because they tend to be very verbose. + * Note that the external application is run in the background to + * avoid blocking the sound server. + */ +static void output_message(Debug::Level level, const char *msg) { + char *quoted_msg; + char *buff = 0; + + /* default to text output if no message app is defined or if it is a debug message. */ + if (messageAppName == 0 || !strcmp(messageAppName, "") || (level == Debug::lDebug)) + { + fprintf(stderr, "%s\n", msg); + return; + } + + quoted_msg = shell_quote(msg); + switch (level) { + case Debug::lFatal: + buff = arts_strdup_printf("%s -e 'Sound server fatal error:\n\n%s' &", messageAppName, quoted_msg); + break; + case Debug::lWarning: + buff = arts_strdup_printf("%s -w 'Sound server warning message:\n\n%s' &", messageAppName, quoted_msg); + break; + case Debug::lInfo: + buff = arts_strdup_printf("%s -i 'Sound server informational message:\n\n%s' &", messageAppName, quoted_msg); + break; + default: + break; // avoid compile warning + } + free(quoted_msg); + + if(buff != 0) + { + system(buff); + free(buff); + } +} + +/* + * Display a message using output_message. If the message is the same + * as the previous one, just increment a count but don't display + * it. This prevents flooding the user with duplicate warnings. If the + * message is not the same as the previous one, then we report the + * previously repeated message (if any) and reset the last message and + * count. + */ +static void display_message(Debug::Level level, const char *msg) { + static char lastMsg[1024]; + static Debug::Level lastLevel; + static int msgCount = 0; + + if(arts_debug_mutex) + arts_debug_mutex->lock(); + + if (!strncmp(msg, lastMsg, 1024)) + { + msgCount++; + } else { + if (msgCount > 0) + { + char *buff; + buff = arts_strdup_printf("%s\n(The previous message was repeated %d times.)", lastMsg, msgCount); + output_message(lastLevel, buff); + free(buff); + } + strncpy(lastMsg, msg, 1024); + lastMsg[ 1023 ] = '\0'; + lastLevel = level; + msgCount = 0; + output_message(level, msg); + } + + if(arts_debug_mutex) + arts_debug_mutex->unlock(); +} + +static class DebugInitFromEnv { +public: + DebugInitFromEnv() { + const char *env = getenv("ARTS_DEBUG"); + if(env) + { + if(strcmp(env,"debug") == 0) + arts_debug_level = Debug::lDebug; + else if(strcmp(env,"info") == 0) + arts_debug_level = Debug::lInfo; + else if(strcmp(env,"warning") == 0) + arts_debug_level = Debug::lWarning; + else if(strcmp(env,"quiet") == 0) + arts_debug_level = Debug::lFatal; + else + { + fprintf(stderr, + "ARTS_DEBUG must be one of debug,info,warning,quiet\n"); + } + } + env = getenv("ARTS_DEBUG_ABORT"); + if(env) + arts_debug_abort = true; + } +} debugInitFromEnv; + +} + +void Arts::Debug::init(const char *prefix, Level level) +{ + arts_debug_level = level; + arts_debug_prefix = prefix; +} + +void Arts::Debug::fatal(const char *fmt, ...) +{ + char *buff; + va_list ap; + + va_start(ap, fmt); + buff = arts_strdup_vprintf(fmt, ap); + va_end(ap); + + display_message(Debug::lFatal, buff); + free(buff); + + if(arts_debug_abort) abort(); + exit(1); +} + +void Arts::Debug::warning(const char *fmt, ...) +{ + if(lWarning >= arts_debug_level) + { + char *buff; + va_list ap; + + va_start(ap, fmt); + buff = arts_strdup_vprintf(fmt, ap); + va_end(ap); + + display_message(Debug::lWarning, buff); + free(buff); + } +} + +void Arts::Debug::info(const char *fmt, ...) +{ + if(lInfo >= arts_debug_level) + { + char *buff; + va_list ap; + + va_start(ap, fmt); + buff = arts_strdup_vprintf(fmt, ap); + va_end(ap); + + display_message(Debug::lInfo, buff); + free(buff); + } +} + +void Arts::Debug::debug(const char *fmt, ...) +{ + if(lDebug >= arts_debug_level) + { + char *buff; + va_list ap; + + va_start(ap, fmt); + buff = arts_strdup_vprintf(fmt, ap); + va_end(ap); + + display_message(Debug::lDebug, buff); + free(buff); + } +} + +void Arts::Debug::messageApp(const char *appName) +{ + messageAppName = (char*) realloc(messageAppName, strlen(appName)+1); + strcpy(messageAppName, appName); +} + +void Arts::Debug::initMutex() +{ + arts_return_if_fail(arts_debug_mutex == 0); + + arts_debug_mutex = new Arts::Mutex(); +} + +void Arts::Debug::freeMutex() +{ + arts_return_if_fail(arts_debug_mutex != 0); + + delete arts_debug_mutex; + arts_debug_mutex = 0; +} + +/* + * For the sake of portability (snprintf is non-portable), what follows is an + * implementation of a variant g_strdup_printf, to format debug messages of + * an arbitary length appropriately. This is reduntant with flow/gsl/gslglib.c, + * however, as libmcop doesn't necessarily link against gslglib.c, this is a + * more-or-less complete copy. + */ + +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * GScanner: Flexible lexical scanner for general purpose. + * Copyright (C) 1997, 1998 Tim Janik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + + +#include <sys/types.h> +#include <stdarg.h> +#include <string.h> + +#define g_warning printf +#define g_strerror strerror + +/*--- gslglib.h ---*/ + +#include <limits.h> +#include <float.h> +#include <stddef.h> +#include <stdarg.h> + +/* --- GLib typedefs --- */ +typedef void* gpointer; +typedef const void* gconstpointer; +typedef char gchar; +typedef unsigned char guchar; +typedef signed short gshort; +typedef unsigned short gushort; +typedef signed int gint; +typedef unsigned int guint; +typedef signed long glong; +typedef unsigned long gulong; +typedef float gfloat; +typedef double gdouble; +typedef size_t gsize; +typedef gchar gint8; +typedef guchar guint8; +typedef gshort gint16; +typedef gushort guint16; +typedef gint gint32; +typedef guint guint32; +typedef gint gboolean; +typedef gint32 GTime; +#ifdef __alpha +typedef long int gint64; +typedef unsigned long int guint64; +#else +typedef long long int gint64; +typedef unsigned long long int guint64; +#endif +typedef struct _GString GString; + +/* --- standard macros --- */ +#ifndef ABS +#define ABS(a) ((a) > 0 ? (a) : -(a)) +#endif +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef CLAMP +#define CLAMP(v,l,h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v)) +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif +#ifndef NULL +#define NULL ((void*) 0) +#endif + +/* --- configure stuff!!! --- */ +#ifdef WORDS_BIGENDIAN +#define G_BYTE_ORDER G_BIG_ENDIAN +#else +#define G_BYTE_ORDER G_LITTLE_ENDIAN +#endif + +/* #define GLIB_HAVE_STPCPY 1 */ +/* Define G_VA_COPY() to do the right thing for copying va_list variables. + * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy. + */ +#if !defined (G_VA_COPY) +# if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32) || defined(WIN32)) || defined(__s390__) || defined(__x86_64__) +# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) +# elif defined (G_VA_COPY_AS_ARRAY) +# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) +# else /* va_list is a pointer */ +# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) +# endif /* va_list is a pointer */ +#endif /* !G_VA_COPY */ + +/* --- glib macros --- */ +#define G_MINFLOAT FLT_MIN +#define G_MAXFLOAT FLT_MAX +#define G_MINDOUBLE DBL_MIN +#define G_MAXDOUBLE DBL_MAX +#define G_MINSHORT SHRT_MIN +#define G_MAXSHORT SHRT_MAX +#define G_MAXUSHORT USHRT_MAX +#define G_MININT INT_MIN +#define G_MAXINT INT_MAX +#define G_MAXUINT UINT_MAX +#define G_MINLONG LONG_MIN +#define G_MAXLONG LONG_MAX +#define G_MAXULONG ULONG_MAX +#define G_USEC_PER_SEC 1000000 +#define G_LITTLE_ENDIAN 1234 +#define G_BIG_ENDIAN 4321 + +#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string) +#define G_STRINGIFY_ARG(contents) #contents +#if defined __GNUC__ && !defined __cplusplus +# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()" +#else +# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) +#endif + +/* subtract from biased_exponent to form base2 exponent (normal numbers) */ +typedef union _GDoubleIEEE754 GDoubleIEEE754; +typedef union _GFloatIEEE754 GFloatIEEE754; +#define G_IEEE754_FLOAT_BIAS (127) +#define G_IEEE754_DOUBLE_BIAS (1023) +/* multiply with base2 exponent to get base10 exponent (nomal numbers) */ +#define G_LOG_2_BASE_10 (0.30102999566398119521) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint mantissa : 23; + guint biased_exponent : 8; + guint sign : 1; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint mantissa_low : 32; + guint mantissa_high : 20; + guint biased_exponent : 11; + guint sign : 1; + } mpn; +}; +#elif G_BYTE_ORDER == G_BIG_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint sign : 1; + guint biased_exponent : 8; + guint mantissa : 23; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint sign : 1; + guint biased_exponent : 11; + guint mantissa_high : 20; + guint mantissa_low : 32; + } mpn; +}; +#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ +#error unknown ENDIAN type +#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +#define GLIB_SIZEOF_INTMAX (8 /* educated guess */) + +typedef struct +{ + guint min_width; + guint precision; + gboolean alternate_format, zero_padding, adjust_left, locale_grouping; + gboolean add_space, add_sign, possible_sign, seen_precision; + gboolean mod_half, mod_long, mod_extra_long; +} PrintfArgSpec; + + +static gsize +printf_string_upper_bound (const gchar *format, + gboolean may_warn, + va_list args) +{ + static gboolean honour_longs = sizeof(long) > 4 || sizeof(void*) > 4; + gsize len = 1; + + if (!format) + return len; + + while (*format) + { + register gchar c = *format++; + + if (c != '%') + len += 1; + else /* (c == '%') */ + { + PrintfArgSpec spec = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gboolean seen_l = FALSE, conv_done = FALSE; + gsize conv_len = 0; + const gchar *spec_start = format; + + do + { + c = *format++; + switch (c) + { + GDoubleIEEE754 u_double; + guint v_uint; + gint v_int; + const gchar *v_string; + + /* beware of positional parameters + */ + case '$': + if (may_warn) + g_warning (G_STRLOC ": unable to handle positional parameters (%%n$)"); + len += 1024; /* try adding some safety padding */ + break; + + /* parse flags + */ + case '#': + spec.alternate_format = TRUE; + break; + case '0': + spec.zero_padding = TRUE; + break; + case '-': + spec.adjust_left = TRUE; + break; + case ' ': + spec.add_space = TRUE; + break; + case '+': + spec.add_sign = TRUE; + break; + case '\'': + spec.locale_grouping = TRUE; + break; + + /* parse output size specifications + */ + case '.': + spec.seen_precision = TRUE; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + v_uint = c - '0'; + c = *format; + while (c >= '0' && c <= '9') + { + format++; + v_uint = v_uint * 10 + c - '0'; + c = *format; + } + if (spec.seen_precision) + spec.precision = MAX (spec.precision, v_uint); + else + spec.min_width = MAX (spec.min_width, v_uint); + break; + case '*': + v_int = va_arg (args, int); + if (spec.seen_precision) + { + /* forget about negative precision */ + if (v_int >= 0) + spec.precision = MAX (spec.precision, (unsigned)v_int); + } + else + { + if (v_int < 0) + { + v_int = - v_int; + spec.adjust_left = TRUE; + } + spec.min_width = MAX (spec.min_width, (unsigned)v_int); + } + break; + + /* parse type modifiers + */ + case 'h': + spec.mod_half = TRUE; + break; + case 'l': + if (!seen_l) + { + spec.mod_long = TRUE; + seen_l = TRUE; + break; + } + /* else, fall through */ + case 'L': + case 'q': + spec.mod_long = TRUE; + spec.mod_extra_long = TRUE; + break; + case 'z': + case 'Z': + if (sizeof(size_t)) + { + spec.mod_long = TRUE; + spec.mod_extra_long = TRUE; + } + break; + case 't': + if (sizeof(ptrdiff_t) > 4) + { + spec.mod_long = TRUE; + spec.mod_extra_long = TRUE; + } + break; + case 'j': + if (GLIB_SIZEOF_INTMAX > 4) + { + spec.mod_long = TRUE; + spec.mod_extra_long = TRUE; + } + break; + + /* parse output conversions + */ + case '%': + conv_len += 1; + break; + case 'O': + case 'D': + case 'I': + case 'U': + /* some C libraries feature long variants for these as well? */ + spec.mod_long = TRUE; + /* fall through */ + case 'o': + conv_len += 2; + /* fall through */ + case 'd': + case 'i': + conv_len += 1; /* sign */ + /* fall through */ + case 'u': + conv_len += 4; + /* fall through */ + case 'x': + case 'X': + spec.possible_sign = TRUE; + conv_len += 10; + if (spec.mod_long && honour_longs) + conv_len *= 2; + if (spec.mod_extra_long) + conv_len *= 2; + if (spec.mod_extra_long) + { + (void) va_arg (args, gint64); + } + else if (spec.mod_long) + (void) va_arg (args, long); + else + (void) va_arg (args, int); + break; + case 'A': + case 'a': + /* 0x */ + conv_len += 2; + /* fall through */ + case 'g': + case 'G': + case 'e': + case 'E': + case 'f': + spec.possible_sign = TRUE; + /* n . dddddddddddddddddddddddd E +- eeee */ + conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4; + if (may_warn && spec.mod_extra_long) + g_warning (G_STRLOC ": unable to handle long double, collecting double only"); +#ifdef HAVE_LONG_DOUBLE +#error need to implement special handling for long double +#endif + u_double.v_double = va_arg (args, double); + /* %f can expand up to all significant digits before '.' (308) */ + if (c == 'f' && + u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047) + { + gint exp = u_double.mpn.biased_exponent; + + exp -= G_IEEE754_DOUBLE_BIAS; + exp = (gint)(exp * G_LOG_2_BASE_10 + 1); + conv_len += ABS (exp); /* exp can be <0 */ + } + /* some printf() implementations require extra padding for rounding */ + conv_len += 2; + /* we can't really handle locale specific grouping here */ + if (spec.locale_grouping) + conv_len *= 2; + break; + case 'C': + spec.mod_long = TRUE; + /* fall through */ + case 'c': + conv_len += spec.mod_long ? MB_LEN_MAX : 1; + (void) va_arg (args, int); + break; + case 'S': + spec.mod_long = TRUE; + /* fall through */ + case 's': + v_string = va_arg (args, char*); + if (!v_string) + conv_len += 8; /* hold "(null)" */ + else if (spec.seen_precision) + conv_len += spec.precision; + else + conv_len += strlen (v_string); + conv_done = TRUE; + if (spec.mod_long) + { + if (may_warn) + g_warning (G_STRLOC": unable to handle wide char strings"); + len += 1024; /* try adding some safety padding */ + } + break; + case 'P': /* do we actually need this? */ + /* fall through */ + case 'p': + spec.alternate_format = TRUE; + conv_len += 10; + if (honour_longs) + conv_len *= 2; + /* fall through */ + case 'n': + conv_done = TRUE; + (void) va_arg (args, void*); + break; + case 'm': + /* there's not much we can do to be clever */ + v_string = g_strerror (errno); + v_uint = v_string ? strlen (v_string) : 0; + conv_len += MAX (256, v_uint); + break; + + /* handle invalid cases + */ + case '\000': + /* no conversion specification, bad bad */ + conv_len += format - spec_start; + break; + default: + if (may_warn) + g_warning (G_STRLOC": unable to handle `%c' while parsing format", + c); + break; + } + conv_done |= conv_len > 0; + } + while (!conv_done); + /* handle width specifications */ + conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width)); + /* handle flags */ + conv_len += spec.alternate_format ? 2 : 0; + conv_len += (spec.add_space || spec.add_sign || spec.possible_sign); + /* finally done */ + len += conv_len; + } /* else (c == '%') */ + } /* while (*format) */ + + return len; +} + +static char* +#ifdef __GNUC__ +__attribute__ ( (format (printf, 1, 0) ) ) +#endif +arts_strdup_vprintf (const char *format, va_list args1) +{ + gchar *buffer; +#ifdef HAVE_VASPRINTF + if (vasprintf (&buffer, format, args1) < 0) + buffer = NULL; +#else + va_list args2; + + G_VA_COPY (args2, args1); + + buffer = (gchar *)malloc (printf_string_upper_bound (format, TRUE, args1)); + + vsprintf (buffer, format, args2); + va_end (args2); +#endif + return buffer; +} + +char* +#ifdef __GNUC__ +__attribute__ ( (format (printf, 1, 0) ) ) +#endif +arts_strdup_printf (const char *format, ...) +{ + gchar *buffer; + va_list args; + + va_start (args, format); + buffer = arts_strdup_vprintf (format, args); + va_end (args); + + return buffer; +} diff --git a/mcop/debug.h b/mcop/debug.h new file mode 100644 index 0000000..94cd01f --- /dev/null +++ b/mcop/debug.h @@ -0,0 +1,138 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + + Some inspiration taken from glib. + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GLib Team and others 1997-1999. + + */ + +#ifndef _ARTSDEBUG_H_ +#define _ARTSDEBUG_H_ + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): Debug. + * + * Collection class, no instance, no members. Thus binary compatible (will + * be kept). + */ + +#define arts_fatal ::Arts::Debug::fatal +#define arts_warning ::Arts::Debug::warning +#define arts_info ::Arts::Debug::info +#define arts_debug ::Arts::Debug::debug + +/* source compatibility with older sources */ +#define artsdebug ::Arts::Debug::debug +#define setartsdebug(x) arts_warning("setartsdebug is obsolete") + +#ifdef __GNUC__ + +#define arts_return_if_fail(expr) \ + do { \ + if (!(expr)) \ + { \ + arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return; \ + } \ + } while(0) + +#define arts_return_val_if_fail(expr,val) \ + do { \ + if (!(expr)) \ + { \ + arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return (val); \ + } \ + } while(0) + +#define arts_assert(expr) \ + do { \ + if (!(expr)) \ + arts_fatal ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + } while(0) + +#else + +#define arts_return_if_fail(expr) \ + do { \ + if (!(expr)) \ + { \ + arts_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return; \ + } \ + } while(0) + +#define arts_return_val_if_fail(expr,val) \ + do { \ + if (!(expr)) \ + { \ + arts_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return (val); \ + } \ + } while(0) + +#define arts_assert(expr) \ + do { \ + if (!(expr)) \ + arts_fatal ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + } while(0) + +#endif + +ARTS_EXPORT char* arts_strdup_printf (const char *format, ...); + +namespace Arts { + class ARTS_EXPORT Debug { + public: + enum Level { lFatal = 3, lWarning = 2, lInfo = 1, lDebug = 0 }; + + /** + * Initializes at which is the minimum level to react to. If you + * call this, call this before creating the Arts::Dispatcher object. + */ + static void init(const char *prefix, Level level); + + static void fatal(const char *fmt,...); // print on stderr & abort + static void warning(const char *fmt,...); // print on stderr + static void info(const char *fmt,...); // print on stdout + static void debug(const char *fmt,...); // print on stdout + + /** + * This method sets the name of an external application to + * display messages graphically. + */ + static void messageApp(const char *appName); + + static void initMutex(); // called from the dispatcher constructor + static void freeMutex(); // called from the dispatcher destructor + }; +} + +#endif diff --git a/mcop/delayedreturn.cc b/mcop/delayedreturn.cc new file mode 100644 index 0000000..1eab0ed --- /dev/null +++ b/mcop/delayedreturn.cc @@ -0,0 +1,71 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <assert.h> +#include "anyref.h" +#include "connection.h" +#include "delayedreturn.h" + +using namespace Arts; +using namespace std; + +DelayedReturn::DelayedReturn() : buffer(0), connection(0) +{ + // +} + +void DelayedReturn::initialize(Connection *connection, Buffer *buffer) +{ + this->connection = connection; + this->buffer = buffer; + connection->_copy(); +} + +DelayedReturn::~DelayedReturn() +{ + connection->_release(); + connection = 0; + buffer = 0; +} + +void DelayedReturn::doReturn(const AnyConstRef& value) +{ + assert(connection); + assert(buffer); + + value.write(buffer); + buffer->patchLength(); + connection->qSendBuffer(buffer); + + delete this; +} + +void DelayedReturn::doReturn() +{ + assert(connection); + assert(buffer); + + buffer->patchLength(); + connection->qSendBuffer(buffer); + + delete this; +} diff --git a/mcop/delayedreturn.h b/mcop/delayedreturn.h new file mode 100644 index 0000000..fe2a140 --- /dev/null +++ b/mcop/delayedreturn.h @@ -0,0 +1,102 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_MCOP_DELAYEDRETURN_H +#define ARTS_MCOP_DELAYEDRETURN_H + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): DelayedReturn + * + * This class will be kept binary compatible. It has a private d-pointer for + * further extensions. + */ + +namespace Arts { + +class AnyConstRef; +class Buffer; +class Connection; +class DelayedReturnPrivate; + +/** + * The "DelayedReturn" class implements delayed returning from functions. + * + * For instance, suppose you would like to return from a wait() operation + * only after a certain time has passed, without blocking other clients + * from using your interface during this time. + * + * Your implementation (in the skel file) of wait should look like this + * + * <pre> + * static DelayedReturn *delayedReturn = 0; + * + * bool TimeServer::waitUntil(long time) + * { + * if(time(0) < time) + * { + * // ... initialize timer here ... + * delayedReturn = Dispatcher::the()->delayReturn(); + * } + * return false; + * } + * + * void timerEvent() + * { + * delayedReturn->doReturn(true); + * } + * </pre> + * + * NOTE: this class breaks for local use (i.e. you can only use it if the + * call was a remote call), so it is strongly recommended not to use it + * unless there is no alternative (and you should really know what you are + * doing, too). + */ +class ARTS_EXPORT DelayedReturn { +friend class Dispatcher; +private: + DelayedReturnPrivate *d; + +protected: + Buffer *buffer; + Connection *connection; + + DelayedReturn(); + void initialize(Connection *connection, Buffer *buffer); + ~DelayedReturn(); + +public: + /** + * call this only once to make the request really return + */ + void doReturn(const AnyConstRef& value); + + /** + * return without value (for void functions) + */ + void doReturn(); +}; + +} + +#endif /* ARTS_MCOP_DELAYEDRETURN_H */ diff --git a/mcop/dispatcher.cc b/mcop/dispatcher.cc new file mode 100644 index 0000000..c055f64 --- /dev/null +++ b/mcop/dispatcher.cc @@ -0,0 +1,1090 @@ + /* + + Copyright (C) 2000-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "dispatcher.h" +#include "delayedreturn.h" +#include "startupmanager.h" +#include "unixconnection.h" +#include "tcpconnection.h" +#include "referenceclean.h" +#include "core.h" +#include "md5auth.h" +#include "mcoputils.h" +#include "loopback.h" +#include "debug.h" +#include "ifacerepo_impl.h" +#include "thread.h" + +#include <sys/stat.h> +#include <stdio.h> +#include <signal.h> +#include <cstring> +#include <cstdlib> +#include <errno.h> +#include <iostream> + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#elif HAVE_SYS_TIME_H +# include <sys/time.h> +#else +# include <time.h> +#endif + +/* Dispatcher private data class (to ensure binary compatibility) */ + +using namespace std; +using namespace Arts; + +namespace Arts { + +class DispatcherWakeUpHandler; + +class DispatcherPrivate { +public: + GlobalComm globalComm; + InterfaceRepo interfaceRepo; + AuthAccept *accept; + LoopbackConnection *loopbackConnection; + DelayedReturn *delayedReturn; + bool allowNoAuthentication; + Mutex mutex; + + /* + * Thread condition that gets signalled whenever something relevant for + * waitForResult happens. Note that broken connections are also relevant + * for waitForResult. + */ + ThreadCondition requestResultCondition; + + /* + * Thread condition that gets signalled whenever something relevant for + * the server connection process happens. This is either: + * - authentication fails + * - authentication succeeds + * - a connection breaks + */ + ThreadCondition serverConnectCondition; + + DispatcherWakeUpHandler *wakeUpHandler; +}; + +/** + * Class that performs dispatcher wakeup. + * + * The sending thread (requesting wakeup) writes a byte to a pipe. The + * main thread watches the pipe, and as soon as the byte arrives, gets + * woken by the IOManager. This should work, no matter what type of IOManager + * is used (i.e. StdIOManager/GIOManager/QIOManager). + */ +class DispatcherWakeUpHandler : public IONotify { +private: + enum { wReceive = 0, wSend = 1 }; + int wakeUpPipe[2]; + +public: + DispatcherWakeUpHandler() + { + if(pipe(wakeUpPipe) != 0) + arts_fatal("can't initialize wakeUp pipe (%s)",strerror(errno)); + + Dispatcher::the()->ioManager()->watchFD(wakeUpPipe[wReceive], + IOType::read | IOType::reentrant, this); + } + virtual ~DispatcherWakeUpHandler() + { + Dispatcher::the()->ioManager()->remove(this, IOType::all); + + close(wakeUpPipe[wSend]); + close(wakeUpPipe[wReceive]); + } + void notifyIO(int fd, int type) + { + arts_return_if_fail(fd == wakeUpPipe[wReceive]); + arts_return_if_fail(type == IOType::read); + + mcopbyte one; + int result; + do + result = read(wakeUpPipe[wReceive],&one,1); + while(result < 0 && errno == EINTR); + } + void wakeUp() + { + mcopbyte one = 1; + + int result; + do + result = write(wakeUpPipe[wSend],&one,1); + while(result < 0 && errno == EINTR); + } +}; + +} + +Dispatcher *Dispatcher::_instance = 0; + +Dispatcher::Dispatcher(IOManager *ioManager, StartServer startServer) +{ + assert(!_instance); + _instance = this; + + /* private data pointer */ + d = new DispatcherPrivate(); + + lock(); + + /* makes arts_debug/arts_message/arts_return_if_fail/... threadsafe */ + Debug::initMutex(); + + generateServerID(); + + if(ioManager) + { + _ioManager = ioManager; + deleteIOManagerOnExit = false; + } + else + { + _ioManager = new StdIOManager; + deleteIOManagerOnExit = true; + } + + d->wakeUpHandler = new DispatcherWakeUpHandler; + + objectManager = new ObjectManager; + + notificationManager = new NotificationManager; + + if(startServer & startUnixServer) + { + unixServer = new UnixServer(this,serverID); + if(!unixServer->running()) + { + delete unixServer; + arts_warning("MCOP: couldn't start UnixServer"); + unixServer = 0; + } + } + else unixServer = 0; + + if(startServer & startTCPServer) + { + tcpServer = new TCPServer(this); + if(!tcpServer->running()) + { + delete tcpServer; + arts_warning("MCOP: couldn't start TCPServer"); + tcpServer = 0; + } + } + else tcpServer = 0; + + d->allowNoAuthentication = startServer & noAuthentication; + d->accept = 0; + d->loopbackConnection = new LoopbackConnection(serverID); + d->interfaceRepo = InterfaceRepo::_from_base(new InterfaceRepo_impl()); + d->delayedReturn = 0; + + _flowSystem = 0; + referenceClean = new ReferenceClean(objectPool); + + /* + * setup signal handler for SIGPIPE + */ + orig_sigpipe = signal(SIGPIPE,SIG_IGN); + if((orig_sigpipe != SIG_DFL) && (orig_sigpipe != SIG_IGN)) + { + cerr << "mcop warning: user defined signal handler found for" + " SIG_PIPE, overriding" << endl; + } + + StartupManager::startup(); + + /* + * this is required for publishing global references - might be a good + * reason for startup priorities as since this is required for cookie&co, + * no communication is possible without that + */ + + + char *env = getenv("ARTS_SERVER"); + bool envOk = false; + if(env) + { + string url = "tcp:"; url += env; + Connection *conn = connectUrl(url); + arts_debug("connection to %s for globalComm", url.c_str()); + if(conn) + { + arts_debug("hint %s", conn->findHint("GlobalComm").c_str()); + d->globalComm = Reference(conn->findHint("GlobalComm")); + envOk = true; + arts_debug("using globalcomm from env variable"); + } + } + + if(!envOk) + { + string globalCommName + = MCOPUtils::readConfigEntry("GlobalComm","Arts::TmpGlobalComm"); + d->globalComm = GlobalComm(SubClass(globalCommName)); + } + + // --- initialize MD5auth --- + /* + * Path for random seed: better to store it in home, because some + * installations wipe /tmp on reboot. + */ + string seedpath = MCOPUtils::createFilePath("random-seed"); + string mcopdir = MCOPUtils::mcopDirectory(); + if(!mcopdir.empty()) seedpath = mcopdir + "/random-seed"; + arts_md5_auth_init_seed(seedpath.c_str()); + + /* + * first generate a new random cookie and try to set secret-cookie to it + * as put will not overwrite, this has no effect if there is already a + * secret cookie + */ + char *cookie = arts_md5_auth_mkcookie(); + globalComm().put("secret-cookie",cookie); + + /* + * Then get the secret cookie from globalComm. As we've just set one, + * and as it is never removed, this always works. + */ + string secretCookie = globalComm().get("secret-cookie"); + if(!arts_md5_auth_set_cookie(secretCookie.c_str())) + { + /* + * Handle the case where the cookie obtained from GlobalComm is not + * a valid cookie (i.e. too short) - this should practically never + * happen. In this case, we will remove the cookie and overwrite it + * with our previously generated cookie. + */ + arts_warning("bad md5 secret-cookie obtained from %s - replacing it", + globalComm()._interfaceName().c_str()); + + globalComm().erase("secret-cookie"); + globalComm().put("secret-cookie",cookie); + + if(!arts_md5_auth_set_cookie(cookie)) + arts_fatal("error initializing md5 secret cookie " + "(generated cookie invalid)"); + } + memset(cookie,0,strlen(cookie)); // try to keep memory clean + free(cookie); + + string::iterator i; // try to keep memory clean from secret cookie + for(i=secretCookie.begin();i != secretCookie.end();i++) *i = 'y'; + + unlock(); +} + +Dispatcher::~Dispatcher() +{ + lock(); + + /* no interaction possible now anymore - remove our global references */ + if(objectManager) + objectManager->removeGlobalReferences(); + + /* remove everything that might have been tagged for remote copying */ + referenceClean->forceClean(); + delete referenceClean; + + d->globalComm = GlobalComm::null(); + + /* shutdown all extensions we loaded */ + if(objectManager) + objectManager->shutdownExtensions(); + + StartupManager::shutdown(); + + /* drop all open connections */ + list<Connection *>::iterator ci; + for(ci=connections.begin(); ci != connections.end();ci++) + { + Connection *conn = *ci; + conn->drop(); + } + d->requestResultCondition.wakeAll(); + d->serverConnectCondition.wakeAll(); + + /* + * remove signal handler for SIGPIPE + */ + signal(SIGPIPE,orig_sigpipe); + + + d->interfaceRepo = InterfaceRepo::null(); + + if(d->accept) + { + delete d->accept; + d->accept = 0; + } + + if(d->loopbackConnection) + { + d->loopbackConnection->_release(); + d->loopbackConnection = 0; + } + if(unixServer) + { + delete unixServer; + unixServer = 0; + } + + if(tcpServer) + { + delete tcpServer; + tcpServer = 0; + } + + if(notificationManager) + { + delete notificationManager; + notificationManager = 0; + } + + if(objectManager && Object_base::_objectCount() == 0) + { + objectManager->removeExtensions(); + delete objectManager; + objectManager = 0; + } + + if(d->wakeUpHandler) + { + delete d->wakeUpHandler; + d->wakeUpHandler = 0; + } + + if(deleteIOManagerOnExit) + { + delete _ioManager; + _ioManager = 0; + } + + if(Object_base::_objectCount()) + { + cerr << "warning: leaving MCOP Dispatcher and still " + << Object_base::_objectCount() << " object references alive." << endl; + list<Object_skel *> which = objectPool.enumerate(); + list<Object_skel *>::iterator i; + for(i = which.begin(); i != which.end();i++) + cerr << " - " << (*i)->_interfaceName() << endl; + } + + if(Type::_typeCount()) + { + cerr << "warning: leaving MCOP Dispatcher and still " + << Type::_typeCount() << " types alive." << endl; + } + + if(GenericDataPacket::_dataPacketCount()) + { + cerr << "warning: leaving MCOP Dispatcher and still " + << GenericDataPacket::_dataPacketCount() + << " data packets alive." << endl; + } + + Debug::freeMutex(); + + unlock(); + + /* private data pointer */ + assert(d); + delete d; + d = 0; + + assert(_instance); + _instance = 0; +} + +InterfaceRepo Dispatcher::interfaceRepo() +{ + return d->interfaceRepo; +} + +FlowSystem_impl *Dispatcher::flowSystem() +{ + assert(_flowSystem); + return _flowSystem; +} + +GlobalComm Dispatcher::globalComm() +{ + assert(!d->globalComm.isNull()); + return d->globalComm; +} + +void Dispatcher::setFlowSystem(FlowSystem_impl *fs) +{ + assert(!_flowSystem); + _flowSystem = fs; +} + +Dispatcher *Dispatcher::the() +{ + return _instance; +} + +Buffer *Dispatcher::waitForResult(long requestID, Connection *connection) +{ + bool isMainThread = SystemThreads::the()->isMainThread(); + Buffer *b = requestResultPool[requestID]; + + connection->_copy(); // Keep extra ref + + while(!b && !connection->broken()) { + if(isMainThread) + _ioManager->processOneEvent(true); + else + d->requestResultCondition.wait(d->mutex); + + b = requestResultPool[requestID]; + } + + requestResultPool.releaseSlot(requestID); + + if(connection->broken()) // connection went away before we got some result + b = 0; + + connection->_release(); // Give up extra ref + + return b; +} + +Buffer *Dispatcher::createRequest(long& requestID, long objectID, long methodID) +{ + Buffer *buffer = new Buffer; + + // write mcop header record + buffer->writeLong(MCOP_MAGIC); + buffer->writeLong(0); // message length - to be patched later + buffer->writeLong(mcopInvocation); + + // generate a request ID + requestID = requestResultPool.allocSlot(); + + // write invocation record + buffer->writeLong(objectID); + buffer->writeLong(methodID); + buffer->writeLong(requestID); + + return buffer; +} + +Buffer *Dispatcher::createOnewayRequest(long objectID, long methodID) +{ + Buffer *buffer = new Buffer; + + // write mcop header record + buffer->writeLong(MCOP_MAGIC); + buffer->writeLong(0); // message length - to be patched later + buffer->writeLong(mcopOnewayInvocation); + + // write oneway invocation record + buffer->writeLong(objectID); + buffer->writeLong(methodID); + + return buffer; +} + +void Dispatcher::handle(Connection *conn, Buffer *buffer, long messageType) +{ + _activeConnection = conn; + +#ifdef DEBUG_IO + printf("got a message %ld, %ld bytes in body\n", + messageType,buffer->remaining()); + if(conn->connState() == Connection::unknown) + cout << "connectionState = unknown" << endl; + if(conn->connState() == Connection::expectClientHello) + cout << "connectionState = expectClientHello" << endl; + if(conn->connState() == Connection::expectServerHello) + cout << "connectionState = expectServerHello" << endl; + if(conn->connState() == Connection::expectAuthAccept) + cout << "connectionState = expectAuthAccept" << endl; + if(conn->connState() == Connection::established) + cout << "connectionState = established" << endl; +#endif + switch(conn->connState()) + { + case Connection::established: + /* + * we're connected to a trusted server, so we can accept + * invocations + */ + if(messageType == mcopInvocation) { +#ifdef DEBUG_MESSAGES + printf("[got Invocation]\n"); +#endif + long objectID = buffer->readLong(); + long methodID = buffer->readLong(); + long requestID = buffer->readLong(); + + Buffer *result = new Buffer; + // write mcop header record + result->writeLong(MCOP_MAGIC); + result->writeLong(0); // message length - to be patched later + result->writeLong(mcopReturn); + + // write result record (returnCode is written by dispatch) + result->writeLong(requestID); + + // perform the request + Object_skel *object = objectPool[objectID]; + object->_copy(); + object->_dispatch(buffer,result,methodID); + object->_release(); + + assert(!buffer->readError() && !buffer->remaining()); + delete buffer; + + if(d->delayedReturn) + { + delete result; + + result = new Buffer; + result->writeLong(MCOP_MAGIC); + result->writeLong(0); // to be patched later + result->writeLong(mcopReturn); + result->writeLong(requestID); + + d->delayedReturn->initialize(conn,result); + d->delayedReturn = 0; + } + else /* return normally */ + { + result->patchLength(); + conn->qSendBuffer(result); + } + return; /* everything ok - leave here */ + } + + if(messageType == mcopReturn) + { +#ifdef DEBUG_MESSAGES + printf("[got Return]\n"); +#endif + long requestID = buffer->readLong(); + requestResultPool[requestID] = buffer; + d->requestResultCondition.wakeAll(); + + return; /* everything ok - leave here */ + } + + if(messageType == mcopOnewayInvocation) { +#ifdef DEBUG_MESSAGES + printf("[got OnewayInvocation]\n"); +#endif + long objectID = buffer->readLong(); + long methodID = buffer->readLong(); + + // perform the request + Object_skel *object = objectPool[objectID]; + object->_copy(); + object->_dispatch(buffer,methodID); + object->_release(); + + assert(!buffer->readError() && !buffer->remaining()); + delete buffer; + + return; /* everything ok - leave here */ + } + break; + + case Connection::expectServerHello: + if(messageType == mcopServerHello) + { +#ifdef DEBUG_MESSAGES + printf("[got ServerHello]\n"); +#endif + /* + * if we get a server hello, answer with a client hello + */ + ServerHello h; + h.readType(*buffer); + bool valid = (!buffer->readError() && !buffer->remaining()); + delete buffer; + + if(!valid) break; // invalid hello received -> forget it + + conn->setServerID(h.serverID); + + /* + * check if md5auth or noauth is offered by the server + */ + bool md5authSupported = false; + bool noauthSupported = false; + vector<string>::iterator ai; + for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++) + { + if(*ai == "md5auth") md5authSupported = true; + if(*ai == "noauth") noauthSupported = true; + } + + if(noauthSupported) // noauth is usually easier to pass ;) + { + Buffer *helloBuffer = new Buffer; + + Header header(MCOP_MAGIC,0,mcopClientHello); + header.writeType(*helloBuffer); + ClientHello clientHello(serverID,"noauth",""); + clientHello.writeType(*helloBuffer); + + helloBuffer->patchLength(); + + conn->qSendBuffer(helloBuffer); + conn->setConnState(Connection::expectAuthAccept); + return; /* everything ok - leave here */ + } + else if(md5authSupported) + { + Buffer *helloBuffer = new Buffer; + + Header header(MCOP_MAGIC,0,mcopClientHello); + header.writeType(*helloBuffer); + ClientHello clientHello(serverID,"md5auth",""); + + const char *random_cookie = h.authSeed.c_str(); + if(strlen(random_cookie) == 32) + { + char *response = arts_md5_auth_mangle(random_cookie); + clientHello.authData = response; +#ifdef DEBUG_AUTH + printf(" got random_cookie = %s\n",random_cookie); + printf("reply with authData = %s\n",response); +#endif + free(response); + } + clientHello.writeType(*helloBuffer); + + helloBuffer->patchLength(); + + conn->qSendBuffer(helloBuffer); + conn->setConnState(Connection::expectAuthAccept); + return; /* everything ok - leave here */ + } + else + { + cerr << "MCOP error: don't know authentication protocol" << endl; + cerr << " server offered: "; + for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++) + cerr << *ai << " "; + cerr << endl; + } + } + break; + + case Connection::expectClientHello: + if(messageType == mcopClientHello) + { +#ifdef DEBUG_MESSAGES + printf("[got ClientHello]\n"); +#endif + ClientHello c; + c.readType(*buffer); + bool valid = (!buffer->readError() && !buffer->remaining()); + delete buffer; + + if(valid && ( + (c.authProtocol == "md5auth" && c.authData == conn->cookie()) + || (c.authProtocol == "noauth" && d->allowNoAuthentication) )) + { + conn->setServerID(c.serverID); + + /* build hints only for the first connection */ + if(!d->accept) + { + d->accept = new AuthAccept(); + + d->accept->hints.push_back( + "GlobalComm="+d->globalComm.toString()); + d->accept->hints.push_back( + "InterfaceRepo="+d->interfaceRepo.toString()); + } + + Buffer *helloBuffer = new Buffer; + Header header(MCOP_MAGIC,0,mcopAuthAccept); + header.writeType(*helloBuffer); + d->accept->writeType(*helloBuffer); + + helloBuffer->patchLength(); + conn->qSendBuffer(helloBuffer); + conn->setConnState(Connection::established); + + return; /* everything ok - leave here */ + } + } + break; + + case Connection::expectAuthAccept: + if(messageType == mcopAuthAccept) + { +#ifdef DEBUG_MESSAGES + printf("[got AuthAccept]\n"); +#endif + AuthAccept a; + a.readType(*buffer); + delete buffer; +#ifdef DEBUG_MESSAGES + + vector<string>::iterator hi; + for(hi = a.hints.begin(); hi != a.hints.end(); hi++) + cout << "[got ConnectionHint] " << *hi << endl; + +#endif + + conn->setConnState(Connection::established); + conn->setHints(a.hints); + d->serverConnectCondition.wakeAll(); + return; /* everything ok - leave here */ + } + break; + + case Connection::unknown: + assert(false); + break; + } + + /* + * We shouldn't reach this point if everything went all right + */ + cerr << "Fatal communication error with a client" << endl; + if(conn->connState() != Connection::established) + { + cerr << " Authentication of this client was not successful" << endl; + cerr << " Connection dropped" << endl; + conn->drop(); + } +} + +long Dispatcher::addObject(Object_skel *object) +{ + long objectID = objectPool.allocSlot(); + + objectPool[objectID] = object; + return objectID; +} + +void Dispatcher::removeObject(long objectID) +{ + assert(objectPool[objectID]); + objectPool.releaseSlot(objectID); +} + +void Dispatcher::generateServerID() +{ + char *buffer; + buffer = arts_strdup_printf("%s-%04x-%08lx", + MCOPUtils::getFullHostname().c_str(), + getpid(),time(0)); + serverID = buffer; + free(buffer); +} + +string Dispatcher::objectToString(long objectID) +{ + Buffer b; + ObjectReference oref; + + oref.serverID = serverID; + oref.objectID = objectID; + + // prefer a unix domainsocket connection over a plain tcp connection + if(unixServer) oref.urls.push_back(unixServer->url()); + if(tcpServer) oref.urls.push_back(tcpServer->url()); + + oref.writeType(b); + + return b.toString("MCOP-Object"); +} + +bool Dispatcher::stringToObjectReference(ObjectReference& r, const string& s) +{ + if(strncmp(s.c_str(),"global:",7) == 0) + { + // if the object reference starts with "global:", it refers to + // a global object which can be found with the objectManager + + string lookup = objectManager->getGlobalReference(&s.c_str()[7]); + return stringToObjectReference(r,lookup); + } + + + Buffer b; + if(!b.fromString(s,"MCOP-Object")) return false; + + r.readType(b); + if(b.readError() || b.remaining()) return false; + + return true; +} + +void *Dispatcher::connectObjectLocal(ObjectReference& reference, + const string& interface) +{ + if(reference.serverID == serverID) + { + void *result = objectPool[reference.objectID]->_cast(interface); + + if(result) + { + objectPool[reference.objectID]->_copy(); + return result; + } + } + + return 0; +} + +Connection *Dispatcher::connectObjectRemote(ObjectReference& reference) +{ + if(reference.serverID == "null") // null reference? + return 0; + + if(reference.serverID == serverID) + return loopbackConnection(); + + list<Connection *>::iterator i; + + for(i=connections.begin(); i != connections.end();i++) + { + Connection *conn = *i; + + if(conn->isConnected(reference.serverID)) + { + // fixme: we should check for the existence of the object + // and increment a reference count or something like that + return conn; + } + } + + /* try to connect the server */ + vector<string>::iterator ui; + for(ui = reference.urls.begin(); ui != reference.urls.end(); ui++) + { + Connection *conn = connectUrl(*ui); + if(conn) + { + if(conn->isConnected(reference.serverID)) + { + return conn; + } + else + { + /* we connected somewhere, but not the right server ;) */ + connections.remove(conn); + conn->_release(); + } + } + } + return 0; +} + +Connection *Dispatcher::connectUrl(const string& url) +{ + Connection *conn = 0; + bool isMainThread = SystemThreads::the()->isMainThread(); + + if(strncmp(url.c_str(),"tcp:",4) == 0) + { + conn = new TCPConnection(url); + } + else if(strncmp(url.c_str(),"unix:",5) == 0) + { + conn = new UnixConnection(url); + } + + if(conn) + { + conn->_copy(); // Keep extra ref for when the connection breaks + conn->setConnState(Connection::expectServerHello); + + while((conn->connState() != Connection::established) + && !conn->broken()) + { + if(isMainThread) + _ioManager->processOneEvent(true); + else + d->serverConnectCondition.wait(d->mutex); + } + + if(conn->connState() == Connection::established) + { + connections.push_back(conn); + conn->_release(); // Give up extra ref + return conn; + } + + // well - bad luck (building a connection failed) + + // Give up extra ref + conn->_release(); + } + return 0; +} + +void Dispatcher::run() +{ + assert(SystemThreads::the()->isMainThread()); + + _ioManager->run(); +} + +void Dispatcher::terminate() +{ + _ioManager->terminate(); +} + +void Dispatcher::initiateConnection(Connection *connection) +{ + vector<string> authProtocols; + authProtocols.push_back("md5auth"); + + if(d->allowNoAuthentication) + authProtocols.push_back("noauth"); + + char *authSeed = arts_md5_auth_mkcookie(); + char *authResult = arts_md5_auth_mangle(authSeed); + + Buffer *helloBuffer = new Buffer; + + Header header(MCOP_MAGIC,0,mcopServerHello); + header.writeType(*helloBuffer); + ServerHello serverHello("aRts/MCOP-1.0.0",serverID,authProtocols,authSeed); + serverHello.writeType(*helloBuffer); + + helloBuffer->patchLength(); + + connection->qSendBuffer(helloBuffer); + connection->setConnState(Connection::expectClientHello); + + connection->setCookie(authResult); + free(authSeed); + free(authResult); + + connections.push_back(connection); +} + +void Dispatcher::handleCorrupt(Connection *connection) +{ + if(connection->connState() != Connection::established) + { + cerr << "received corrupt message on unauthenticated connection" <<endl; + cerr << "closing connection." << endl; + connection->drop(); + d->serverConnectCondition.wakeAll(); + } + else + { + cerr << "WARNING: got corrupt MCOP message !??" << endl; + } +} + +void Dispatcher::handleConnectionClose(Connection *connection) +{ + /* + * we can't use enumerate here, because the "existing objects list" might + * be changing due to the other _disconnectRemote calls we make, so we + * enumerate() the objects manually + */ + unsigned long l; + for(l=0; l<objectPool.max(); l++) + { + Object_skel *skel = objectPool[l]; + if(skel) skel->_disconnectRemote(connection); + } + + d->requestResultCondition.wakeAll(); + d->serverConnectCondition.wakeAll(); + + /* + * FIXME: + * + * there may be error handling to do (e.g., check that the _stub's that + * still refer to that connection don't crash now). + */ + connection->_release(); + + list<Connection *>::iterator i; + for(i=connections.begin(); i != connections.end();i++) + { + if(*i == connection) + { + connections.erase(i); + return; + } + } +} + +Connection *Dispatcher::activeConnection() +{ + return _activeConnection; +} + +Connection *Dispatcher::loopbackConnection() +{ + return d->loopbackConnection; +} + +DelayedReturn *Dispatcher::delayReturn() +{ + assert(!d->delayedReturn); + + return d->delayedReturn = new DelayedReturn(); +} + +Object_skel *Dispatcher::getLocalObject(long objectID) +{ + Object_skel *result = objectPool[objectID]; + + if(result) result->_copy(); + return result; +} + +void Dispatcher::lock() +{ + _instance->d->mutex.lock(); +} + +void Dispatcher::unlock() +{ + _instance->d->mutex.unlock(); +} + +void Dispatcher::wakeUp() +{ + if(SystemThreads::the()->isMainThread()) return; + + _instance->d->wakeUpHandler->wakeUp(); +} + +/* +void Dispatcher::reloadTraderData() is declared in trader_impl.cc +*/ diff --git a/mcop/dispatcher.h b/mcop/dispatcher.h new file mode 100644 index 0000000..b143a1e --- /dev/null +++ b/mcop/dispatcher.h @@ -0,0 +1,265 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef DISPATCHER_H +#define DISPATCHER_H + +#include "common.h" +#include "pool.h" +#include "iomanager.h" +#include "tcpserver.h" +#include "unixserver.h" +#include "connection.h" +#include "notification.h" + +#include <deque> +#include <stack> +#include <vector> +#include <list> +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): Dispatcher + * + * This is part of the public API (and interacts with generated code) and + * has to be kept binary compatible. + */ + +namespace Arts { + +class ObjectReference; +class FlowSystem_impl; +class GlobalComm; +class InterfaceRepo; +class ObjectManager; +class Object_skel; +class ReferenceClean; +class DelayedReturn; + +extern "C" { + typedef void (*mcop_sighandler)(int); +} + +class ARTS_EXPORT Dispatcher { +private: + class DispatcherPrivate *d; + +protected: + static Dispatcher *_instance; + + Pool<Buffer> requestResultPool; + Pool<Object_skel> objectPool; + std::list<Connection *> connections; + + std::string serverID; + void generateServerID(); // helper function + + bool deleteIOManagerOnExit; + + TCPServer *tcpServer; + UnixServer *unixServer; + IOManager *_ioManager; + FlowSystem_impl *_flowSystem; + ObjectManager *objectManager; + ReferenceClean *referenceClean; + NotificationManager *notificationManager; + + mcop_sighandler orig_sigpipe; // original signal handler for SIG_PIPE + Connection *_activeConnection; // internal use only (for refcounting) + + /** + * connects to a given URL + * + * @returns a valid connection, or a 0 pointer on error + */ + Connection *connectUrl(const std::string& url); + +public: + enum StartServer { + noServer = 0, // don't be a server + startUnixServer = 1, // listen on a unix domain socket + startTCPServer = 2, // listen on a tcp port + noAuthentication = 4 // don't require authentication + }; + + Dispatcher(IOManager *ioManager = 0, StartServer startServer = noServer); + ~Dispatcher(); + + static Dispatcher *the(); + inline IOManager *ioManager() { return _ioManager; }; + InterfaceRepo interfaceRepo(); + FlowSystem_impl *flowSystem(); + GlobalComm globalComm(); + void setFlowSystem(FlowSystem_impl *fs); + + void refillRequestIDs(); + + // blocking wait for result + Buffer *waitForResult(long requestID,Connection *connection); + + // request creation for oneway and twoway requests + Buffer *createRequest(long& requestID, long objectID, long methodID); + Buffer *createOnewayRequest(long objectID, long methodID); + + // processes messages + void handle(Connection *conn, Buffer *buffer, long messageType); + + /* + * special hook to handle corrupt messages + */ + void handleCorrupt(Connection *conn); + + /** + * object registration + * + * do not call manually, this is used by the Object_skel constructor + * to register itself + */ + long addObject(Object_skel *object); + + /** + * object deregistration + * + * do not call manually, this is called by the Object_skel destructor + * as soon as the object is deleted + */ + void removeObject(long objectID); + + /** + * connects to a local object, returning a readily casted "interface" * + * if success, or NULL if this object is not local + */ + void *connectObjectLocal(ObjectReference& reference, const std::string& interface); + + /** + * connects to a remote object, establishing a connection if necessary + * + * returns NULL if connecting fails or object isn't present or whatever + * else could go wrong + */ + Connection *connectObjectRemote(ObjectReference& reference); + + /** + * stringification of objects (only used by the object implementations, + * which in turn provide a _toString method) + */ + std::string objectToString(long objectID); + + /** + * destringification of objects (mainly used by the object implementations, + * which in turn provide a _fromString method) + */ + bool stringToObjectReference(ObjectReference& r, const std::string& s); + + /** + * main loop + */ + void run(); + + /** + * this function quits the main loop (it must be running, of course) + * and causes the run() function to return. + */ + void terminate(); + + /** + * Is called by the transport services as soon as a new connection is + * created - this will send authentication request, etc. + */ + void initiateConnection(Connection *connection); + + /** + * Is called by the Connection as soon as the connection goes down, + * which may happen due to a normal cause (client exits), and may + * happen if an error occurs as well (network down) + */ + void handleConnectionClose(Connection *connection); + + /** + * Locks the dispatcher. Whenever you want to do anything with any kind + * of aRts object, you will hold a lock on Arts::Dispatcher. There is + * only one exception to the rule, and that is: you don't have to lock + * the dispatcher when the lock is already held. + * + * Generally, that is very often the case. Typical situations where you + * don't need to lock() the Dispatcher are: + * + * @li you receive a callback from the IOManager (timer or fd) + * @li you get call due to some MCOP request + * @li you are called from the NotificationManager + * @li you are called from the FlowSystem (calculateBlock) + */ + static void lock(); + + /** + * Unlocks the dispatcher. Do this to release a lock you hold on + * the Arts::Dispatcher. + */ + static void unlock(); + + /** + * Wakes the dispatcher - normally, the dispatcher will go to sleep in + * it's event loop, when nothing is to be done. If you change things from + * another thread, like: add a new Timer, write something to a connection, + * and so on, the dispatcher will not notice it. To wake the dispatcher + * up, this call is provided. + */ + static void wakeUp(); + + /** + * - internal usage only - + * + * this will return the Connection the last request came from + */ + Connection *activeConnection(); + + /** + * - internal usage only - + * + * this will return a loopback Connection for sending requests to myself + */ + Connection *loopbackConnection(); + + /** + * - internal usage only - + * + * this will cause a function to return from a request later + * @see DelayedReturn + */ + DelayedReturn *delayReturn(); + + /** + * - internal usage only - + * + * gets object with a given ID + * @returns the object if successful, 0 otherwise + */ + Object_skel *getLocalObject(long ID); + + /** + * reloads the trader data (do this if things have been added/changed + * there) + */ + void reloadTraderData(); +}; +} +#endif diff --git a/mcop/dynamicrequest.cc b/mcop/dynamicrequest.cc new file mode 100644 index 0000000..6ba64f7 --- /dev/null +++ b/mcop/dynamicrequest.cc @@ -0,0 +1,152 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "dynamicrequest.h" +#include "common.h" +#include "debug.h" +#include <iostream> + +using namespace Arts; +using namespace std; + +class Arts::DynamicRequestPrivate { +public: + Connection *connection; + Buffer *buffer; + MethodDef method; + Object object; + + /** + * methodID is kept between the requests, so that we don't need to lookup + * a method again when it gets called twice - the value for "we need to + * lookup again" is -1, which gets set whenever the current request differs + * from the last + */ + long requestID, methodID, objectID; + unsigned long paramCount; + + /** + * constructor + */ + DynamicRequestPrivate(const Object &obj) + : buffer(0), object(obj), methodID(-1) + { + } +}; + +DynamicRequest::DynamicRequest(const Object& obj) +{ + d = new DynamicRequestPrivate(obj); + d->connection = obj._base()->_connection; + d->objectID = obj._base()->_objectID; +} + +DynamicRequest::~DynamicRequest() +{ + delete d; +} + +DynamicRequest& DynamicRequest::method(const string& method) +{ + assert(!d->buffer); + + // methodID will be set later + d->buffer = Dispatcher::the()->createRequest(d->requestID, d->objectID, 0); + + if(d->method.name != method) + { + d->method.name = method; + d->methodID = -1; + } + d->paramCount = 0; + return *this; +} + +DynamicRequest& DynamicRequest::param(const AnyConstRef& ref) +{ + if(d->paramCount == d->method.signature.size()) + { + ParamDef pd; + pd.type = ref.type(); + d->method.signature.push_back(pd); + } + else + { + if(d->method.signature[d->paramCount].type != ref.type()) + { + d->method.signature[d->paramCount].type = ref.type(); + d->methodID = -1; + } + } + d->paramCount++; + ref.write(d->buffer); + return *this; +} + +bool DynamicRequest::invoke() +{ + AnyRef voidReference; + return invoke(voidReference); +} + +bool DynamicRequest::invoke(const AnyRef& returnCode) +{ + if(d->method.type != returnCode.type()) + { + d->method.type = returnCode.type(); + d->methodID = -1; + } + if(d->method.signature.size() != d->paramCount) + d->methodID = -1; + + /* + * need to lookup method? (if the requested method is exactly the + * same as the last, we need not, which signigicantly improves performance + */ + if(d->methodID == -1) + { + d->method.signature.resize(d->paramCount); + d->methodID = d->object._lookupMethod(d->method); + + if(d->methodID == -1) + { + arts_warning("DynamicRequest: invalid method called"); + return false; + } + } + + + d->buffer->patchLength(); + d->buffer->patchLong(16,d->methodID); + d->connection->qSendBuffer(d->buffer); + d->buffer = 0; + + Buffer *result = + Dispatcher::the()->waitForResult(d->requestID,d->connection); + + if(result) + { + returnCode.read(result); + delete result; + } + return result != 0; +} diff --git a/mcop/dynamicrequest.h b/mcop/dynamicrequest.h new file mode 100644 index 0000000..f749637 --- /dev/null +++ b/mcop/dynamicrequest.h @@ -0,0 +1,133 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef MCOP_DYNAMICREQUEST_H +#define MCOP_DYNAMICREQUEST_H + +#include "buffer.h" +#include "anyref.h" +#include <vector> +#include <string> + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): DynamicRequest + * + * Has to be kept binary compatible (use d ptr). + */ + +namespace Arts { + +class Object; +class Type; +class DynamicRequestPrivate; + +/** + * The DynamicRequest class can be used to invoke requests on objects, without + * using IDL generated code to do so (i.e. you can talk to objects without + * having to know their interfaces at compile time) + * + * Suppose you have the interface + * + * interface SimpleSoundServer { + * [...] + * long play(string file); // plays a file and returns an id + * [...] + * }; + * + * And server is of type SimpleSoundServer, you can write in your C++ code: + * + * long id; + * if(DynamicRequest(server).method("play").param("/tmp/bong.wav").invoke(id)) + * { + * cout << "playing file now, id is " << id << endl; + * } + * else + * { + * cout << "something went wrong with the dynamic request" << endl; + * } + * + * You can of course also add parameters and other information one-by-one: + * + * DynamicRequest request(server); + * request.method("play"); + * request.param("/tmp/bong.wav"); + * + * long id; + * if(request.invoke(id)) cout << "success" << endl; + */ + +class ARTS_EXPORT DynamicRequest { +public: + /** + * creates a dynamic request which will be sent to a specific object + */ + DynamicRequest(const Object& object); + + /** + * deletes the dynamic request + */ + ~DynamicRequest(); + + /** + * says that the following method will be a oneway method, for example + * + * DynamicRequest(someobject).oneway().method("stop").invoke(); + */ + DynamicRequest& oneway(); + + /** + * sets the method to invoke + */ + DynamicRequest& method(const std::string& method); + + /** + * adds a parameter to the call + */ + DynamicRequest& param(const AnyConstRef& value); + + /** + * executes the request, call this if you don't expect a return type + * + * @returns true if the request could be performed + */ + bool invoke(); + + /** + * executes the request: this version accepts an AnyRef& as result type + * + * @returns true if the request could be performed + */ + bool invoke(const AnyRef& result); + + /* + * TODO: Some types can't yet be used in dynamic requests, these are + * enum, sequence<enum>, type, sequence<type>, object, sequence<object> + */ +private: + DynamicRequestPrivate *d; +}; + +} + +#endif /* MCOP_DYNAMICREQUEST_H */ diff --git a/mcop/dynamicskeleton.cc b/mcop/dynamicskeleton.cc new file mode 100644 index 0000000..99d6dd1 --- /dev/null +++ b/mcop/dynamicskeleton.cc @@ -0,0 +1,204 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "dynamicskeleton.h" +#include "dispatcher.h" +#include "debug.h" +#include "stdio.h" + +using namespace Arts; +using namespace std; + +/* we could share the "class part" of those implicitely, as + types never change */ + +namespace Arts { +class DynamicSkeletonData { +public: + DynamicSkeletonData(DynamicSkeletonBase *base, + Object_skel *skel, + const string& interfaceName, + const string& interfaceNameParent) + : base(base), skel(skel), interfaceName(interfaceName), + interfaceNameParent(interfaceNameParent) + { + } + + enum InterfaceType { itNone, itParent, itDynamic }; + + void buildInterfaces(); + void buildInterfaces(const string& s, InterfaceType t); + void buildMethodTable(); + + DynamicSkeletonBase *base; + Object_skel *skel; + string interfaceName, interfaceNameParent; + map<string, InterfaceType> interfaceMap; + map<string, void**> attrs; +}; +} + +DynamicSkeletonBase::DynamicSkeletonBase(Object_skel *skel, + const std::string& interfaceName, const std::string& interfaceNameParent) +{ + arts_assert(skel != 0); + _dsInit(skel,interfaceName,interfaceNameParent); +} + +DynamicSkeletonBase::DynamicSkeletonBase() +{ +} + +void DynamicSkeletonBase::_dsInit(Object_skel *skel, + const std::string& interfaceName, const std::string& interfaceNameParent) +{ + d = new DynamicSkeletonData(this,skel,interfaceName,interfaceNameParent); + d->buildInterfaces(); + + /* TODO: optimize me! */ + map<string, DynamicSkeletonData::InterfaceType>::iterator ii; + for(ii = d->interfaceMap.begin(); ii != d->interfaceMap.end(); ii++) + { + if(ii->second == DynamicSkeletonData::itDynamic) + { + InterfaceDef id; + id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first); + + vector<AttributeDef>::iterator ai; + for(ai = id.attributes.begin(); ai != id.attributes.end(); ai++) + { + AttributeDef& ad = *ai; + if((ad.flags & attributeStream) == attributeStream) + { + void**& data = d->attrs[ad.name.c_str()]; + arts_assert(data == 0); + data = new (void*); + d->skel->_initStream(ad.name.c_str(),data,ad.flags); + } + } + } + } +} + +DynamicSkeletonBase::~DynamicSkeletonBase() +{ + delete d; +} + +std::string DynamicSkeletonBase::_dsInterfaceName() +{ + return d->interfaceName; +} + +bool DynamicSkeletonBase::_dsIsCompatibleWith(const std::string& interfacename) +{ + d->buildInterfaces(); + return d->interfaceMap[interfacename] != 0; +} + +void DynamicSkeletonBase::_dsBuildMethodTable() +{ + d->buildMethodTable(); +} + +static void _dispatch_dynamic(void *object, long methodID, Buffer *request, Buffer *result) +{ + ((DynamicSkeletonBase *)object)->process(methodID, request, result); +} + +void DynamicSkeletonData::buildMethodTable() +{ + buildInterfaces(); + + map<string, DynamicSkeletonData::InterfaceType>::iterator ii; + for(ii = interfaceMap.begin(); ii != interfaceMap.end(); ii++) + { + if(ii->second == itDynamic) + { + InterfaceDef id; + id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first); + + /* methods */ + vector<MethodDef>::iterator mi; + for(mi = id.methods.begin(); mi != id.methods.end(); mi++) + skel->_addMethod(_dispatch_dynamic, base, *mi); + + /* _get_ and _set_ methods for attributes */ + vector<AttributeDef>::iterator ai; + for(ai = id.attributes.begin();ai != id.attributes.end();ai++) + { + AttributeDef& ad = *ai; + + if(ad.flags & attributeAttribute) + { + MethodDef md; + if(ad.flags & streamOut) /* readable from outside */ + { + md.name = "_get_"+ad.name; + md.type = ad.type; + md.flags = methodTwoway; + /* no parameters (don't set md.signature) */ + + skel->_addMethod(_dispatch_dynamic, base, md); + } + if(ad.flags & streamIn) /* writeable from outside */ + { + md.name = "_set_"+ad.name; + md.type = "void"; + md.flags = methodTwoway; + + ParamDef pd; + pd.type = ad.type; + pd.name = "newValue"; + md.signature.push_back(pd); + + skel->_addMethod(_dispatch_dynamic, base, md); + } + } + } + } + } +} + +void DynamicSkeletonData::buildInterfaces() +{ + if(interfaceMap.size() != 0) return; + + buildInterfaces(interfaceName, itDynamic); + buildInterfaces(interfaceNameParent, itParent); +} + +void DynamicSkeletonData::buildInterfaces(const string& name, DynamicSkeletonData::InterfaceType t) +{ + InterfaceDef id = Dispatcher::the()->interfaceRepo().queryInterface(name); + + if(interfaceMap[name] == t) return; + interfaceMap[name] = t; + + vector<string>::iterator ii; + for(ii = id.inheritedInterfaces.begin(); + ii != id.inheritedInterfaces.end(); ii++) + { + buildInterfaces(*ii,t); + } + buildInterfaces("Arts::Object",t); +} diff --git a/mcop/dynamicskeleton.h b/mcop/dynamicskeleton.h new file mode 100644 index 0000000..0c5cba7 --- /dev/null +++ b/mcop/dynamicskeleton.h @@ -0,0 +1,163 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_MCOP_DYNAMICSKELETON_H +#define ARTS_MCOP_DYNAMICSKELETON_H + +#include "arts_export.h" + +#include "object.h" + +/* + * BC - Status (2002-03-08): DynamicSkeletonBase, DynamicSkeleton + * + * Will be kept binary compatible (using d ptr). + */ +namespace Arts { + +class DynamicSkeletonData; + +class ARTS_EXPORT DynamicSkeletonBase { +private: + DynamicSkeletonData *d; + +protected: + DynamicSkeletonBase(); + /* <obsolete compatibility code> */ + DynamicSkeletonBase(Object_skel *skel, + const std::string& interfacename, + const std::string& interfacenameparent); + /* </obsolete compatibility code> */ + virtual ~DynamicSkeletonBase(); + + void _dsInit(Object_skel *skel, const std::string& interfacename, + const std::string& interfacenameparent); + std::string _dsInterfaceName(); + bool _dsIsCompatibleWith(const std::string& interfacename); + void _dsBuildMethodTable(); + +public: + /** + * process is called whenever you get a request that you need to implement + * dynamically + * + * @param methodID contains the ID of the method that you need to + * implement - you can get the full signature by calling + * getMethodDef + * + * @param request contains the marshalled parameters + * + * @param result is for the return code - if your method returns a + * value, you need to write the it in the result Buffer + */ + virtual void process(long methodID, Buffer *request, Buffer *result) = 0; +}; + +/** + * DynamicSkeleton is used to dynamically implement an interface (i.e. without + * static type bindings as generated by the MCOP idl compiler. + * + * You will always implement a mixed version: mcopidl generated skeletons up + * to a certain point, and above this, dynamically implemented interfaces. + * So you'll inherit DynamicSkeleton<Static_skel> and give the interface you + * want to implement dynamically as argument. Suppose your idl file looks + * like + * + * <pre> + * interface A { void a(); }; + * interface B : A { void b(); }; + * </pre> + * + * And you want to implement interface A "classic" (i.e. with mcopidl generated + * virtual void a()) and interface B "dynamic", you would do + * + * <pre> + * typedef Arts::DynamicSkeleton<A_skel> A_dskel; // convenient with typedef + * + * class B_impl : public A_dskel { + * public: + * B_impl() : A_dskel("B") { // we dynamically implement the B interface + * } + * void a() { // through A_skel + * arts_info("a called"); + * } + * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result) + * { + * const Arts::MethodDef& methodDef = getMethodDef(methodID); + * + * if(methodDef.name == "b") + * arts_info("b called!"); + * else + * arts_fatal("Unknown method '%s' called"); + * } + * }; + * </pre> + */ +template<class Parent_skel> +class DynamicSkeleton : virtual public Parent_skel, public DynamicSkeletonBase +{ +public: + /** + * constructor + */ + DynamicSkeleton(const std::string& interface) + { + _dsInit(this, interface, Parent_skel::_interfaceNameSkel()); + } + + /** + * getMethodDef returns a MethodDef structure for a given methodID - it + * is quite useful if you implement process + * + * <pre> + * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result) + * { + * const Arts::MethodDef& methodDef = getMethodDef(methodID); + * + * if(methodDef.name == "hello") // the method named hello was called + * printf("Hello!\n"); + * else // method with other name was called + * arts_fatal("Method '%s' not implemented",methodDef.name.c_str()); + * } + * </pre> + */ + const MethodDef& getMethodDef(long methodID) { + return this->_dsGetMethodDef(methodID); + } + +/*-- reimplemented from Arts::Object_skel: --*/ + std::string _interfaceName() { + return _dsInterfaceName(); + } + + bool _isCompatibleWith(const std::string& interfacename) { + if(_dsIsCompatibleWith(interfacename)) return true; + return Parent_skel::_isCompatibleWith(interfacename); + } + void _buildMethodTable() { + Parent_skel::_buildMethodTable(); + _dsBuildMethodTable(); + } +}; + +} +#endif /* ARTS_MCOP_DYNAMICSKELETON_H */ diff --git a/mcop/extensionloader.cc b/mcop/extensionloader.cc new file mode 100644 index 0000000..82c56c5 --- /dev/null +++ b/mcop/extensionloader.cc @@ -0,0 +1,116 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "extensionloader.h" +#include "startupmanager.h" +#include "mcoputils.h" +#include "debug.h" +#include <unistd.h> +#include <assert.h> + +using namespace std; +using namespace Arts; + +ExtensionLoader::ExtensionLoader(const string& filename) :handle(0) +{ + string dlfilename; + + assert(filename.size()); + if(filename[0] == '/') + dlfilename = filename; + else + { + const vector<string> *path = MCOPUtils::extensionPath(); + + vector<string>::const_iterator pi; + for(pi = path->begin(); pi != path->end(); pi++) + { + dlfilename = *pi + "/" + filename; + + if(access(dlfilename.c_str(),F_OK) == 0) + break; + } + } + + + /* this will catch all startup classes here */ + StartupManager::setExtensionLoader(this); + + lt_dlinit(); + handle = lt_dlopen(dlfilename.c_str()); + + StartupManager::setExtensionLoader(0); + + if(handle) + { + /* now process all startup classes of the loaded extension */ + list<StartupClass *>::iterator i; + + for(i = startupClasses.begin(); i != startupClasses.end(); i++) + (*i)->startup(); + needShutdown = true; + } + else + { + arts_warning("loading extension from '%s' failed: %s", + dlfilename.c_str(), lt_dlerror()); + } +} + +bool ExtensionLoader::success() +{ + return (handle != 0); +} + +void ExtensionLoader::shutdown() +{ + if(handle && needShutdown) + { + /* shutdown the loaded extension properly */ + list<StartupClass *>::iterator i; + + for(i = startupClasses.begin(); i != startupClasses.end(); i++) + (*i)->shutdown(); + needShutdown = false; + } +} + +ExtensionLoader::~ExtensionLoader() +{ + if(handle) + { + shutdown(); + lt_dlclose(handle); + + /* + * lt_dlexit & lt_dlinit have a counter, so there is no harm in + * calling one lt_dlinit in the constructor and one lt_dlexit here + */ + lt_dlexit(); + } +} + +void ExtensionLoader::addStartupClass(class StartupClass *sc) +{ + startupClasses.push_back(sc); +} diff --git a/mcop/extensionloader.h b/mcop/extensionloader.h new file mode 100644 index 0000000..ce67f12 --- /dev/null +++ b/mcop/extensionloader.h @@ -0,0 +1,59 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef EXTENSIONLOADER_H +#define EXTENSIONLOADER_H + +#include <string> +#include <list> +#include <ltdl.h> + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): ExtensionLoader + * + * None of these classes is considered part of the public API. Do NOT use it + * in your apps. No binary compatibility guaranteed. (Interactions: + * ObjectManager, Startup stuff) + */ + +namespace Arts { + +class ARTS_EXPORT ExtensionLoader { +protected: + std::list<class StartupClass *> startupClasses; + lt_dlhandle handle; + bool needShutdown; + +public: + ExtensionLoader(const std::string& path); + ~ExtensionLoader(); + + bool success(); + void shutdown(); + + void addStartupClass(class StartupClass *sc); +}; + +} +#endif /* EXTENSIONLOADER_H */ diff --git a/mcop/factory.cc b/mcop/factory.cc new file mode 100644 index 0000000..f0cb2ab --- /dev/null +++ b/mcop/factory.cc @@ -0,0 +1,36 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "factory.h" +#include "objectmanager.h" + +using namespace Arts; + +void Factory::startup() +{ + ObjectManager::the()->registerFactory(this); +} + +void Factory::shutdown() +{ + ObjectManager::the()->removeFactory(this); +} diff --git a/mcop/factory.h b/mcop/factory.h new file mode 100644 index 0000000..91970ad --- /dev/null +++ b/mcop/factory.h @@ -0,0 +1,69 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef FACTORY_H +#define FACTORY_H + +#include <string> + +#include "arts_export.h" + +#include "object.h" +#include "startupmanager.h" + +/* + * BC - Status (2002-03-08): Factory + * + * Will need to remain binary compatible (REGISTER_IMPLEMENTATION), d ptr + * provided for convenience, watch out for interactions with generated + * code. + */ + +namespace Arts { + +class FactoryPrivate; + +class ARTS_EXPORT Factory : public StartupClass { +private: + FactoryPrivate *d; +public: + void startup(); + void shutdown(); + virtual Object_skel *createInstance() = 0; + virtual std::string interfaceName() = 0; +}; + +/* + * Dont's forget to place a semicolon after the use of this macro, + * like: + * REGISTER_IMPLEMENTATION(MyClass); + */ +#define REGISTER_IMPLEMENTATION(impl) \ + class impl ## _Factory : virtual public Arts::Factory { \ + public: \ + std::string interfaceName() { return impl::_interfaceNameSkel(); } \ + Arts::Object_skel *createInstance() { return new impl ; } \ +} The_ ## impl ## _Factory + +} + +#endif diff --git a/mcop/flowsystem.cc b/mcop/flowsystem.cc new file mode 100644 index 0000000..50ca26b --- /dev/null +++ b/mcop/flowsystem.cc @@ -0,0 +1,180 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "flowsystem.h" +#include "debug.h" + +using namespace Arts; + +//-------------- ScheduleNode ----------------- + +ScheduleNode::ScheduleNode(Object_base *object) : _nodeObject(object) +{ + // +} + +ScheduleNode::~ScheduleNode() +{ + // +} + +Object ScheduleNode::nodeObject() +{ + assert(_nodeObject); + return Object::_from_base(_nodeObject->_copy()); +} + +RemoteScheduleNode *ScheduleNode::remoteScheduleNode() +{ + return 0; +} + +void *ScheduleNode::cast(const std::string&) +{ + return 0; +} + + +//----------- RemoteScheduleNode ------------- + +RemoteScheduleNode::RemoteScheduleNode(Object_stub *stub) : ScheduleNode(stub) +{ + // +} + +RemoteScheduleNode *RemoteScheduleNode::remoteScheduleNode() +{ + return this; +} + +void RemoteScheduleNode::initStream(const std::string&, void *, long) +{ + // not for stub objects + assert(false); +} + +void RemoteScheduleNode::requireFlow() +{ + // stub objects can't require flow on this server (they don't live here) + assert(false); +} + +void RemoteScheduleNode::virtualize(const std::string&, ScheduleNode *, + const std::string&) +{ + // (de)virtualization of ports is only implemented locally + assert(false); +} + +void RemoteScheduleNode::devirtualize(const std::string&, ScheduleNode *, + const std::string&) +{ + // (de)virtualization of ports is only implemented locally + assert(false); +} + +// interface to modify the node from outside + +void RemoteScheduleNode::start() +{ + FlowSystem remoteFs = nodeObject()._flowSystem(); + arts_return_if_fail(!remoteFs.isNull()); + + remoteFs.startObject(nodeObject()); +} + +void RemoteScheduleNode::stop() +{ + FlowSystem remoteFs = nodeObject()._flowSystem(); + arts_return_if_fail(!remoteFs.isNull()); + + remoteFs.stopObject(nodeObject()); +} + +void RemoteScheduleNode::connect(const std::string& port, + ScheduleNode *remoteNode, + const std::string& remotePort) +{ + arts_return_if_fail(remoteNode != 0); + + FlowSystem fs = nodeObject()._flowSystem(); + arts_return_if_fail(!fs.isNull()); + + AttributeType flags = fs.queryFlags(nodeObject(),port); + arts_return_if_fail(flags != 0); + + // connectObject must be called as connectObject([sourcePort], [destPort]); + + if(flags & streamOut) // if our port is an output port, this order + { + fs.connectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort); + } + else if(flags & streamIn) + { + FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem(); + arts_return_if_fail(!remoteFs.isNull()); + + remoteFs.connectObject(remoteNode->nodeObject(), + remotePort,nodeObject(),port); + } else { + assert(false); + } +} + +void RemoteScheduleNode::disconnect(const std::string& port, + ScheduleNode *remoteNode, + const std::string& remotePort) +{ + arts_return_if_fail(remoteNode != 0); + + FlowSystem fs = nodeObject()._flowSystem(); + arts_return_if_fail(!fs.isNull()); + + AttributeType flags = fs.queryFlags(nodeObject(),port); + arts_return_if_fail(flags != 0); + + // connectObject must be called as connectObject([sourcePort], [destPort]); + + if(flags & streamOut) // if our port is an output port, this order + { + fs.disconnectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort); + } + else if(flags & streamIn) + { + FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem(); + arts_return_if_fail(!remoteFs.isNull()); + + remoteFs.disconnectObject(remoteNode->nodeObject(), + remotePort,nodeObject(),port); + } else { + assert(false); + } +} + +// constant values +void RemoteScheduleNode::setFloatValue(const std::string& port, float value) +{ + FlowSystem fs = nodeObject()._flowSystem(); + arts_return_if_fail(!fs.isNull()); + + fs.setFloatValue(nodeObject(), port, value); +} diff --git a/mcop/flowsystem.h b/mcop/flowsystem.h new file mode 100644 index 0000000..c64c57b --- /dev/null +++ b/mcop/flowsystem.h @@ -0,0 +1,147 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef FLOWSYSTEM_H +#define FLOWSYSTEM_H + +#include "arts_export.h" +#include "object.h" +#include "common.h" + +/* + * BC - Status (2002-03-08): ScheduleNode, FlowSystem, FlowSystem_impl, + * RemoteScheduleNode + * + * Heavy interactions with generated and hand-written code, flowsystem binding + * and whatever. DO KEEP COMPATIBLE. Do not change the underlying IDL MODEL. + * d ptrs available. + */ + +namespace Arts { + +class Object_skel; +class Object_stub; +class RemoteScheduleNode; +class ScheduleNodePrivate; + +class ARTS_EXPORT ScheduleNode +{ +private: + Object_base *_nodeObject; + ScheduleNodePrivate *d; // unused + +public: + ScheduleNode(Object_base *object); + virtual ~ScheduleNode(); + + Object nodeObject(); + + // check if this is a remote schedule node + + virtual RemoteScheduleNode *remoteScheduleNode(); + + // other casts + + virtual void *cast(const std::string& target); + + // internal interface against Object_skel + + typedef bool (*QueryInitStreamFunc)(Object_skel *object, + const std::string& name); + + virtual void initStream(const std::string& name, void *ptr, long flags) = 0; + + // interface against node implementation + + virtual void requireFlow() = 0; + virtual void virtualize(const std::string& port, ScheduleNode *implNode, + const std::string& implPort) = 0; + virtual void devirtualize(const std::string& port, ScheduleNode *implNode, + const std::string& implPort) = 0; + + // interface to modify the node from outside + + virtual void start() = 0; + virtual void stop() = 0; + virtual void connect(const std::string& port, ScheduleNode *remoteNode, + const std::string& remotePort) = 0; + virtual void disconnect(const std::string& port, ScheduleNode *remoteNode, + const std::string& remotePort) = 0; + + // constant values + virtual void setFloatValue(const std::string& port, float value) = 0; +}; + +class RemoteScheduleNodePrivate; + +class ARTS_EXPORT RemoteScheduleNode : public ScheduleNode +{ +private: + RemoteScheduleNodePrivate *d; // unused +public: + RemoteScheduleNode(Object_stub *stub); + + RemoteScheduleNode *remoteScheduleNode(); + + // internal interface against Object_skel + + void initStream(const std::string& name, void *ptr, long flags); + + // interface against node implementation + + void requireFlow(); + virtual void virtualize(const std::string& port, ScheduleNode *implNode, + const std::string& implPort); + virtual void devirtualize(const std::string& port, ScheduleNode *implNode, + const std::string& implPort); + + // interface to modify the node from outside + + void start(); + void stop(); + void connect(const std::string& port, ScheduleNode *remoteNode, + const std::string& remotePort); + void disconnect(const std::string& port, ScheduleNode *remoteNode, + const std::string& remotePort); + + // constant values + void setFloatValue(const std::string& port, float value); +}; + +class FlowSystem_impl_private; + +class FlowSystem_impl :virtual public FlowSystem_skel +{ +private: + FlowSystem_impl_private *d; +public: + virtual ScheduleNode *addObject(Object_skel *object) = 0; + virtual void removeObject(ScheduleNode *node) = 0; + virtual bool suspendable() = 0; + virtual bool suspended() = 0; + virtual void suspend() = 0; + virtual void restart() = 0; +}; + +} + +#endif diff --git a/mcop/idlfilereg.cc b/mcop/idlfilereg.cc new file mode 100644 index 0000000..4c15e24 --- /dev/null +++ b/mcop/idlfilereg.cc @@ -0,0 +1,44 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "common.h" + +using namespace Arts; + +IDLFileReg::IDLFileReg(const char *name, const char *contents) +{ + _name = name; + _contents = contents; +} + +void IDLFileReg::startup() +{ + Buffer b; + b.fromString(_contents,"IDLFile"); + + nr = Dispatcher::the()->interfaceRepo().insertModule(ModuleDef(b)); +} + +void IDLFileReg::shutdown() +{ + Dispatcher::the()->interfaceRepo().removeModule(nr); +} diff --git a/mcop/idlfilereg.h b/mcop/idlfilereg.h new file mode 100644 index 0000000..e9146ba --- /dev/null +++ b/mcop/idlfilereg.h @@ -0,0 +1,51 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef IDLFILEREG_H +#define IDLFILEREG_H + +#include <string> +#include "startupmanager.h" + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): IDLFileReg + * + * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this. + * (Interaction with generated code). Add a new class if you need something + * else than this does. + */ + +namespace Arts { + +class ARTS_EXPORT IDLFileReg : public StartupClass { + long nr; + const char *_name, *_contents; +public: + IDLFileReg(const char *name, const char *contents); + void startup(); + void shutdown(); +}; + +} +#endif /* IDLFILEREG_H */ diff --git a/mcop/ifacerepo_impl.cc b/mcop/ifacerepo_impl.cc new file mode 100644 index 0000000..5a7572c --- /dev/null +++ b/mcop/ifacerepo_impl.cc @@ -0,0 +1,305 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "ifacerepo_impl.h" +#include "debug.h" +#include <iostream> +#include <stdio.h> + +using namespace std; +using namespace Arts; + +InterfaceRepo_impl::InterfaceRepo_impl() +{ + nextModuleID = 1; + tiMap["void"] = tiVoid; + tiMap["byte"] = tiByte; + tiMap["string"] = tiString; + tiMap["boolean"] = tiBoolean; + tiMap["float"] = tiFloat; + tiMap["long"] = tiLong; + tiMap["object"] = tiInterface; +} + +InterfaceRepo_impl::~InterfaceRepo_impl() +{ + while(!unloadModuleList.empty()) + { + removeModule(unloadModuleList.front()); + unloadModuleList.pop_front(); + } +} + +long InterfaceRepo_impl::insertModule(const ModuleDef& newModule) +{ + long moduleID = nextModuleID++; + + /* insert interfaces */ + vector<InterfaceDef>::const_iterator ii; + for(ii=newModule.interfaces.begin(); + ii != newModule.interfaces.end();ii++) + { + Buffer b; + ii->writeType(b); + InterfaceEntry *ie = new InterfaceEntry(b,moduleID); + interfaces.push_back(ie); + + tiMap[ie->name] = tiInterface; + } + + /* insert types */ + vector<TypeDef>::const_iterator ti; + for(ti=newModule.types.begin(); + ti != newModule.types.end();ti++) + { + Buffer b; + ti->writeType(b); + TypeEntry *entry = new TypeEntry(b,moduleID); + types.push_back(entry); + + tiMap[entry->name] = tiType; + } + + /* insert enums */ + vector<EnumDef>::const_iterator ei; + for(ei=newModule.enums.begin(); + ei != newModule.enums.end();ei++) + { + Buffer b; + ei->writeType(b); + EnumEntry *entry = new EnumEntry(b,moduleID); + enums.push_back(entry); + + tiMap[entry->name] = tiEnum; + } + + return moduleID; +} + +void InterfaceRepo_impl::removeModule(long moduleID) +{ + /* erase interfaces */ + list<InterfaceEntry *>::iterator ii; + ii = interfaces.begin(); + while(ii != interfaces.end()) + { + if((*ii)->moduleID == moduleID) + { + delete (*ii); + interfaces.erase(ii); + ii = interfaces.begin(); + } + else ii++; + } + + /* erase types */ + list<TypeEntry *>::iterator ti; + ti = types.begin(); + while(ti != types.end()) + { + if((*ti)->moduleID == moduleID) + { + delete (*ti); + types.erase(ti); + ti = types.begin(); + } + else ti++; + } + + /* erase enums */ + list<EnumEntry *>::iterator ei; + ei = enums.begin(); + while(ei != enums.end()) + { + if((*ei)->moduleID == moduleID) + { + delete (*ei); + enums.erase(ei); + ei = enums.begin(); + } + else ei++; + } +} + +InterfaceDef InterfaceRepo_impl::queryInterfaceLocal(const string& name) +{ + list<InterfaceEntry *>::iterator ii; + + for(ii = interfaces.begin();ii != interfaces.end();ii++) + { + if((*ii)->name == name) + return **ii; + } + return InterfaceDef(); +} + +InterfaceDef InterfaceRepo_impl::queryInterface(const string& name) +{ + InterfaceDef def = queryInterfaceLocal(name); + + if(def.name.empty()) + { + TraderQuery q; + q.supports("Type",name); + vector<TraderOffer> *offers = q.query(); + vector<TraderOffer>::iterator i; + for(i = offers->begin(); i != offers->end();i++) + { + TraderOffer& offer = *i; + + if(def.name.empty()) + { + vector<string> *types = offer.getProperty("TypeFile"); + if(types->size() == 1) + { + const vector<string> *path = MCOPUtils::traderPath(); + + vector<string>::const_iterator pi = path->begin(); + while(pi != path->end() && def.name.empty()) + { + string filename = *pi++ + "/" + types->front(); + + FILE *extfile = fopen(filename.c_str(),"r"); + if(extfile) + { + arts_debug("InterfaceRepo: loading %s", + filename.c_str()); + + Buffer b; + int c; + while((c = fgetc(extfile)) >= 0) b.writeByte(c); + fclose(extfile); + + long id = insertModule(ModuleDef(b)); + def = queryInterfaceLocal(name); + unloadModuleList.push_back(id); + } + } + } + delete types; + } + } + delete offers; + } + + if(def.name.empty()) + { + arts_warning("InterfaceRepo: no information about the interface %s " + "is known", name.c_str()); + } + + return def; +} + +TypeDef InterfaceRepo_impl::queryType(const string& name) +{ + list<TypeEntry *>::iterator ti; + + for(ti = types.begin();ti != types.end();ti++) + { + if((*ti)->name == name) + return **ti; + } + + arts_warning("InterfaceRepo: no information about the type %s is known.", + name.c_str()); + return TypeDef(); +} + +EnumDef InterfaceRepo_impl::queryEnum(const string& name) +{ + list<EnumEntry *>::iterator ei; + + for(ei = enums.begin();ei != enums.end();ei++) + { + if((*ei)->name == name) + return **ei; + } + + arts_warning("InterfaceRepo: no information about the enum %s is known.", + name.c_str()); + return EnumDef(); +} + +vector<string> *InterfaceRepo_impl::queryChildren(const std::string& name) +{ + vector<string> *result = new vector<string>; + list<InterfaceEntry *>::iterator ii; + + for(ii = interfaces.begin();ii != interfaces.end();ii++) + { + bool found = false; + vector<string>::iterator j; + + for(j = (*ii)->inheritedInterfaces.begin(); + j != (*ii)->inheritedInterfaces.end() && !found; j++) + { + if(*j == name) + { + result->push_back((*ii)->name); + found = true; + } + } + if((*ii)->inheritedInterfaces.empty() && ((name == "Arts::Object") || (name == "object")) && ((*ii)->name != "Arts::Object")) + result->push_back((*ii)->name); + } + + return result; +} + +vector<string> *InterfaceRepo_impl::queryInterfaces() +{ + vector<string> *result = new vector<string>; + list<InterfaceEntry *>::iterator ii; + + for(ii = interfaces.begin();ii != interfaces.end();ii++) + result->push_back((*ii)->name); + + return result; +} + +vector<string> *InterfaceRepo_impl::queryTypes() +{ + vector<string> *result = new vector<string>; + list<TypeEntry *>::iterator ti; + + for(ti = types.begin();ti != types.end();ti++) + result->push_back((*ti)->name); + + return result; +} + +vector<string> *InterfaceRepo_impl::queryEnums() +{ + vector<string> *result = new vector<string>; + list<EnumEntry *>::iterator ei; + + for(ei = enums.begin();ei != enums.end();ei++) + result->push_back((*ei)->name); + + return result; +} + +TypeIdentification InterfaceRepo_impl::identifyType(const string& name) +{ + return tiMap[name]; +} diff --git a/mcop/ifacerepo_impl.h b/mcop/ifacerepo_impl.h new file mode 100644 index 0000000..ffa98de --- /dev/null +++ b/mcop/ifacerepo_impl.h @@ -0,0 +1,98 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): InterfaceRepo_impl + * + * This is an implementation class, and not kept binary compatible. It's + * only here since the REGISTER_IMPLEMENTATION bootstrapping may not yet + * be done before the first piece of startup code (IDLFileReg) needs the + * Interface repository. + */ + +#ifndef IFACEREPO_H +#define IFACEREPO_H + +#include "common.h" +#include <map> + +namespace Arts { + +class InterfaceRepo_impl : virtual public InterfaceRepoV2_skel { + class Entry { + public: + long moduleID; + Entry(long moduleID) : moduleID(moduleID) + { + } + }; + class EnumEntry : public EnumDef, public Entry { + public: + EnumEntry(Buffer& stream, long moduleID) + :EnumDef(stream), Entry(moduleID) + { + } + }; + class TypeEntry : public TypeDef, public Entry { + public: + TypeEntry(Buffer& stream, long moduleID) + :TypeDef(stream), Entry(moduleID) + { + } + }; + class InterfaceEntry : public InterfaceDef, public Entry { + public: + InterfaceEntry(Buffer& stream, long moduleID) + :InterfaceDef(stream), Entry(moduleID) + { + }; + }; + + std::list<EnumEntry *> enums; + std::list<TypeEntry *> types; + std::list<InterfaceEntry *> interfaces; + std::map<std::string, TypeIdentification> tiMap; + std::list<long> unloadModuleList; + + long nextModuleID; + + InterfaceDef queryInterfaceLocal(const std::string& name); +public: + + InterfaceRepo_impl(); + ~InterfaceRepo_impl(); + + long insertModule(const ModuleDef& newModule); + void removeModule(long moduleID); + InterfaceDef queryInterface(const std::string& name); + TypeDef queryType(const std::string& name); + EnumDef queryEnum(const std::string& name); + + TypeIdentification identifyType(const std::string& name); + + std::vector<std::string> *queryChildren(const std::string& name); + std::vector<std::string> *queryInterfaces(); + std::vector<std::string> *queryTypes(); + std::vector<std::string> *queryEnums(); +}; +} +#endif /* IFACEREPO_H */ diff --git a/mcop/iomanager.cc b/mcop/iomanager.cc new file mode 100644 index 0000000..442318a --- /dev/null +++ b/mcop/iomanager.cc @@ -0,0 +1,494 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "iomanager.h" +#include "dispatcher.h" +#include "notification.h" +#include "thread.h" +#include <stdio.h> +#include <fcntl.h> + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> // Needed on some systems. +#endif +// WABA: NOTE! +// sys/select.h is needed on e.g. AIX to define "fd_set". +// However, we can not include config.h in a header file. +// The right solution would be not to use "fd_set" in the +// header file but to use it only in a private datastructure +// defined in the .cc file. + +using namespace std; +using namespace Arts; + +namespace Arts { +/* internal data structures */ +class IOWatchFD { + int _fd, _types; + IONotify *_notify; + +public: + int activeTypes; + + IOWatchFD(int fd, int types, IONotify *notify); + + inline int fd() { return _fd; }; + inline int types() { return _types; }; + inline IONotify *notify() { return _notify; }; + inline void remove(int types) { _types &= ~types; } +}; + +class TimeWatcher { + int milliseconds; + TimeNotify *_notify; + timeval nextNotify; + bool active, destroyed; + + bool earlier(const timeval& reference); +public: + TimeWatcher(int _milliseconds, TimeNotify *notify); + + inline TimeNotify *notify() { return _notify; }; + timeval advance(const timeval& currentTime); + void destroy(); +}; +} + +/* + * Enable this if you want to debug how long certain plugins / operations + * take to perform. You'll get the times between two select() calls that are + * done by the IOManager, which is equivalent to the time the input/output + * remains unserved. For apps like artsd, it gives the minimum audio latency + * users will need to specify to avoid dropouts. + */ +#undef IOMANAGER_DEBUG_LATENCY + +#ifdef IOMANAGER_DEBUG_LATENCY +static timeval iomanager_debug_latency_time = { 0, 0 }; + +static void iomanager_debug_latency_end() +{ + if(iomanager_debug_latency_time.tv_sec) + { + timeval end; + gettimeofday(&end,0); + + float diff = (end.tv_usec-iomanager_debug_latency_time.tv_usec)/1000.0 + + (end.tv_sec-iomanager_debug_latency_time.tv_sec)*1000.0; + + /* change this value if you get your screen filled up with messages */ + if(diff >= 1.5) + fprintf(stderr,"IOManager: latency for operation: %2.3f ms\n",diff); + } +} + +static void iomanager_debug_latency_start() +{ + gettimeofday(&iomanager_debug_latency_time,0); +} +#else +static inline void iomanager_debug_latency_end() +{ +} + +static inline void iomanager_debug_latency_start() +{ +} +#endif + +IOWatchFD::IOWatchFD(int fd, int types, IONotify *notify) +{ + _fd = fd; + _types = types; + _notify = notify; + activeTypes = 0; +} + +StdIOManager::StdIOManager() +{ + // force initialization of the fd_set's + fdListChanged = true; + timeListChanged = false; + level = 0; +} + +void StdIOManager::processOneEvent(bool blocking) +{ + assert(SystemThreads::the()->isMainThread()); + + level++; + + // we release and acquire the lock only on level 1 + if(level == 1) + Dispatcher::lock(); + + // notifications not carried out reentrant + if(level == 1) + NotificationManager::the()->run(); + + // FIXME: timers *could* change the file descriptors to select... + //--- + if(fdListChanged) + { + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_ZERO(&reentrant_readfds); + FD_ZERO(&reentrant_writefds); + FD_ZERO(&reentrant_exceptfds); + + maxfd = 0; + + list<IOWatchFD *>::iterator i; + for(i = fdList.begin(); i != fdList.end(); i++) + { + IOWatchFD *w = *i; + + if(w->types() & IOType::read) FD_SET(w->fd(),&readfds); + if(w->types() & IOType::write) FD_SET(w->fd(),&writefds); + if(w->types() & IOType::except) FD_SET(w->fd(),&exceptfds); + + if(w->types() & IOType::reentrant) + { + if(w->types() & IOType::read) + FD_SET(w->fd(),&reentrant_readfds); + if(w->types() & IOType::write) + FD_SET(w->fd(),&reentrant_writefds); + if(w->types() & IOType::except) + FD_SET(w->fd(),&reentrant_exceptfds); + } + + if(w->types() && w->fd() > maxfd) maxfd = w->fd(); + } + + fdListChanged = false; + } + fd_set rfd,wfd,efd; + if(level == 1) + { + rfd = readfds; + wfd = writefds; + efd = exceptfds; + } + else + { + // watch out, this is reentrant I/O + rfd = reentrant_readfds; + wfd = reentrant_writefds; + efd = reentrant_exceptfds; + } + + /* default timeout 5 seconds */ + long selectabs; + + if(blocking) + selectabs = 5000000; + else + selectabs = 0; + + /* prepare timers - only at level 1 */ + if(level == 1 && timeList.size()) + { + struct timeval currenttime; + gettimeofday(¤ttime,0); + + list<TimeWatcher *>::iterator ti; + + timeListChanged = false; + ti = timeList.begin(); + while(ti != timeList.end()) + { + TimeWatcher *w = *ti++; + timeval timertime = w->advance(currenttime); + + // if that may happen in the next ten seconds + if(timertime.tv_sec < currenttime.tv_sec+10) + { + long timerabs = (timertime.tv_sec - currenttime.tv_sec)*1000000; + timerabs += (timertime.tv_usec - currenttime.tv_usec); + + if(timerabs < selectabs) selectabs = timerabs; + } + + if(timeListChanged) + { + ti = timeList.begin(); + timeListChanged = false; + } + } + } + + timeval select_timeout; + select_timeout.tv_sec = selectabs / 1000000; + select_timeout.tv_usec = selectabs % 1000000; + + if(level == 1) iomanager_debug_latency_end(); + + // we release and acquire the lock only on level 1 + if(level == 1) + Dispatcher::unlock(); + + int retval = select(maxfd+1,&rfd,&wfd,&efd,&select_timeout); + + // we release and acquire the lock only on level 1 + if(level == 1) + Dispatcher::lock(); + + if(level == 1) iomanager_debug_latency_start(); + + if(retval > 0) + { + /* + * the problem is, that objects that are being notified may change + * the watch list, add fds, remove fds, remove objects and whatever + * else + * + * so we can' notify them from the loop - but we can make a stack + * of "notifications to do" and send them as soon as we looked up + * in the list what to send + */ + long tonotify = 0; + + list<IOWatchFD *>::iterator i; + for(i = fdList.begin(); i != fdList.end(); i++) { + IOWatchFD *w = *i; + int match = 0; + + if(FD_ISSET(w->fd(),&rfd) && (w->types() & IOType::read)) + match |= IOType::read; + + if(FD_ISSET(w->fd(),&wfd) && (w->types() & IOType::write)) + match |= IOType::write; + + if(FD_ISSET(w->fd(),&efd) && (w->types() & IOType::except)) + match |= IOType::except; + + if((w->types() & IOType::reentrant) == 0 && level != 1) + match = 0; + + if(match) { + tonotify++; + w->activeTypes = match; + notifyStack.push(w); + } + } + + while(tonotify != 0) + { + if(!fdListChanged) + { + IOWatchFD *w = notifyStack.top(); + int activeTypes = w->activeTypes; + int fd = w->fd(); + IONotify *notify = w->notify(); + + w->activeTypes = 0; + notify->notifyIO(fd, activeTypes); + // warning: w and notify might no longer exist here + } + + notifyStack.pop(); + tonotify--; + } + } + /* handle timers - only at level 1 */ + if(level == 1 && timeList.size()) + { + struct timeval currenttime; + gettimeofday(¤ttime,0); + + list<TimeWatcher *>::iterator ti; + + timeListChanged = false; + ti = timeList.begin(); + while(ti != timeList.end()) + { + TimeWatcher *w = *ti++; + w->advance(currenttime); + if (timeListChanged) + { + ti = timeList.begin(); + timeListChanged = false; + } + } + } + + // notifications not carried out reentrant + if(level == 1) + NotificationManager::the()->run(); + + // we release and acquire the lock only on level 1 + if(level == 1) + Dispatcher::unlock(); + + level--; +} + +void StdIOManager::run() +{ + assert(SystemThreads::the()->isMainThread()); + assert(level == 0); + + // FIXME: this might not be threadsafe, as there is no lock here! + terminated = false; + while(!terminated) + processOneEvent(true); +} + +void StdIOManager::terminate() +{ + terminated = true; + Dispatcher::wakeUp(); +} + +void StdIOManager::watchFD(int fd, int types, IONotify *notify) +{ + /* + IOWatchFD *watchfd = findWatch(fd,notify); + if(watchfd) + { + watchfd->add(types); + } + else + { + fdList.push_back(new IOWatchFD(fd,types,notify)); + } + */ + + // FIXME: might want to reuse old watches + fdList.push_back(new IOWatchFD(fd,types,notify)); + fdListChanged = true; + Dispatcher::wakeUp(); +} + +void StdIOManager::remove(IONotify *notify, int types) +{ + list<IOWatchFD *>::iterator i; + + i = fdList.begin(); + + while(i != fdList.end()) + { + IOWatchFD *w = *i; + + if(w->notify() == notify) w->remove(types); + + // nothing left to watch? + if(w->types() == 0 || w->types() == IOType::reentrant) + { + i = fdList.erase(i); + delete w; // FIXME: shouldn't we have a destroy() similar + // to the one for timers + } + else i++; + } + fdListChanged = true; +} + +void StdIOManager::addTimer(int milliseconds, TimeNotify *notify) +{ + if (milliseconds == -1 && notify == 0) { + // HACK: in order to not add a virtual function to IOManager we're calling addTimer with + // magic values. This call tells the ioManager that notifications are pending and + // NotificationManager::run() should get called soon. + } else { + timeList.push_back(new TimeWatcher(milliseconds,notify)); + timeListChanged = true; + Dispatcher::wakeUp(); + } +} + +void StdIOManager::removeTimer(TimeNotify *notify) +{ + list<TimeWatcher *>::iterator i; + + i = timeList.begin(); + + while(i != timeList.end()) + { + TimeWatcher *w = *i; + + if(w->notify() == notify) + { + i = timeList.erase(i); + timeListChanged = true; + w->destroy(); + } + else i++; + } +} + +TimeWatcher::TimeWatcher(int _milliseconds, TimeNotify *notify) + : milliseconds(_milliseconds),_notify(notify),active(false),destroyed(false) +{ + gettimeofday(&nextNotify,0); + + nextNotify.tv_usec += (milliseconds%1000)*1000; + nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000); + nextNotify.tv_usec %= 1000000; +} + +timeval TimeWatcher::advance(const timeval& currentTime) +{ + active = true; + while(earlier(currentTime)) + { + nextNotify.tv_usec += (milliseconds%1000)*1000; + nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000); + nextNotify.tv_usec %= 1000000; + + _notify->notifyTime(); + + if(destroyed) + { + delete this; + + struct timeval never = { 0xffffffff, 0 }; + return never; + } + } + active = false; + return nextNotify; +} + +bool TimeWatcher::earlier(const timeval& reference) +{ + if(nextNotify.tv_sec > reference.tv_sec) return false; + if(nextNotify.tv_sec < reference.tv_sec) return true; + + return (nextNotify.tv_usec < reference.tv_usec); +} + +void TimeWatcher::destroy() +{ + if(active) + { + destroyed = true; + } + else + { + delete this; + } +} diff --git a/mcop/iomanager.h b/mcop/iomanager.h new file mode 100644 index 0000000..a226e0c --- /dev/null +++ b/mcop/iomanager.h @@ -0,0 +1,214 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): + * BINARY COMPATIBLE: IONotify, TimeNotify, IOManager + * NO BC FOR: StdIOManager + * + * Whereas the first three are part of the Interface (i.e. DEFINITELY to be + * kept binary compatible), the next three are part of the implementation + * in libmcop and subject to any kind of change. + */ + +#ifndef IOMANAGER_H +#define IOMANAGER_H + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <list> +#include <stack> + +#include "arts_export.h" + +namespace Arts { +// constants: + +/** + * What does the reentrant flag do? + * + * The IOManager offers a processOneEvent call. This means, that you can ask + * that I/O is handled, even while in a routine that handles I/O. As a + * practical example: you may have got a remote invocation for the function + * foo. Now you are in function foo() and call function bar() on a remote + * server. When you wait for the result, you obviously will again require + * the IOManager to wait for it. Thus this is a case where you need reentrant + * I/O handling. + * + * That way, you get a multiple level stack: + * + * <pre> + * [...] + * | + * [ Hander for I/O ] + * | + * [ IOManager ] level 2 + * | + * [ Some other function ] + * | + * [ Hander for I/O ] + * | + * [ IOManager ] level 1 + * | + * [ main() ] + * </pre> + * + * What reentrant does, is to allow that IO Watch to be activated at levels + * higher than one. + * + * Timers and notifications, on the other hand will only be carried out at + * level 1. + */ +struct IOType { + enum { read = 1, write = 2, except = 4, reentrant = 8, all = 15 }; +}; + +/** + * IONotify is the base class you can derive from to receive callbacks about + * IO activity. You will need to call the watchFD function of the IOManager + * to start watching a filedescriptor. + * + * @see Arts::IOManager + */ +class ARTS_EXPORT IONotify { +public: + /** + * This is the function that gets called if something relevant happened + * on the filedescriptor you watched with IOManager::watchFD. + * + * @param fd is the filedescriptor that has seen some IO activity + * @param type is the type of activity (as combination of IOType) + */ + virtual void notifyIO(int fd, int type) = 0; +}; + +/** + * TimeNotify is the base class you can derive from to receive timer callbacks. + * You will need to call the addTimer function of the IOManager to start + * watching a filedescriptor. + * + * @see Arts::IOManager + */ +class ARTS_EXPORT TimeNotify { +public: + /** + * This function gets whenever the timer is activated. Note that the + * IOManager will try to "catch up" lost time, that is, if you have a + * 300ms timer that didn't get called for a second (because there was + * something else to do), you'll receive three calls in a row. + */ + virtual void notifyTime() = 0; +}; + +/** + * Provides services like timers and notifications when filedescriptors get + * ready to read/write. + */ +class ARTS_EXPORT IOManager { +public: + virtual ~IOManager() {}; + + /** + * processes exactly one io event + */ + virtual void processOneEvent(bool blocking) = 0; + + /** + * enters a loop which processes io events, until terminate is called + * + * may only be called once (use processOneEvent for other purposes) + */ + virtual void run() = 0; + + /** + * terminates the io event loop (which was started with run) + */ + virtual void terminate() = 0; + + /** + * starts watching one filedescriptor for certain types of operations + * + * notifies the notify object when e.g. the fd requires (allows) reading + * and types contained IOType::read. + * + * @see Arts::IOType + * @see Arts::IONotify + */ + virtual void watchFD(int fd, int types, IONotify *notify) = 0; + + /** + * stops watching a filedescriptor + */ + virtual void remove(IONotify *notify, int types) = 0; + /* + * BCI when breaking BC, probably int fd should be added as argument + * to remove, this would be more consistent with the way watches are added + */ + + /** + * starts a periodic timer + * + * @see Arts::TimeNotify + */ + virtual void addTimer(int milliseconds, TimeNotify *notify) = 0; + + /** + * stops the timer + */ + virtual void removeTimer(TimeNotify *notify) = 0; +}; + +class IOWatchFD; +class TimeWatcher; + +class ARTS_EXPORT StdIOManager : public IOManager { +protected: + std::list<IOWatchFD *> fdList; + std::list<TimeWatcher *> timeList; + std::stack<IOWatchFD *> notifyStack; + + bool terminated; + + bool fdListChanged; // causes the fd_sets to be rebuilt before using them + bool timeListChanged; + fd_set readfds, writefds, exceptfds; + fd_set reentrant_readfds, reentrant_writefds, reentrant_exceptfds; + int maxfd; + + int level; + +public: + StdIOManager(); + + void processOneEvent(bool blocking); + void run(); + void terminate(); + void watchFD(int fd, int types, IONotify *notify); + void remove(IONotify *notify, int types); + void addTimer(int milliseconds, TimeNotify *notify); + void removeTimer(TimeNotify *notify); +}; + +} + +#endif diff --git a/mcop/loopback.cc b/mcop/loopback.cc new file mode 100644 index 0000000..0cc58a8 --- /dev/null +++ b/mcop/loopback.cc @@ -0,0 +1,57 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "loopback.h" +#include "common.h" + +using namespace Arts; +using namespace std; + +LoopbackConnection::LoopbackConnection(const std::string& serverID) +{ + setServerID(serverID); + _connState = established; +} + +void LoopbackConnection::qSendBuffer(Buffer *buffer) +{ + assert(buffer->size() >= 12); + + long magic = buffer->readLong(); + assert(magic == MCOP_MAGIC); + + /* messageSize, irrelevant here, since we've got the buffer already */ + buffer->readLong(); + long messageType = buffer->readLong(); + + Dispatcher::the()->handle(this,buffer,messageType); +} + +void LoopbackConnection::drop() +{ + assert(false); +} + +bool LoopbackConnection::broken() +{ + return false; +} diff --git a/mcop/loopback.h b/mcop/loopback.h new file mode 100644 index 0000000..0e0c092 --- /dev/null +++ b/mcop/loopback.h @@ -0,0 +1,51 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef MCOP_LOOPBACKCONNECTION_H +#define MCOP_LOOPBACKCONNECTION_H + +#include "connection.h" + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): LoopbackConnection + * + * Not part of the public API. Do NOT use it in your apps. No binary + * compatibility guaranteed. + */ + +namespace Arts { + +class ARTS_EXPORT LoopbackConnection : public Connection +{ +public: + LoopbackConnection(const std::string& serverID); + + void qSendBuffer(Buffer *buffer); + void drop(); + bool broken(); +}; + +} + +#endif /* MCOP_LOOPBACKCONNECTION_H */ diff --git a/mcop/mcopconfig.cc b/mcop/mcopconfig.cc new file mode 100644 index 0000000..ad56c55 --- /dev/null +++ b/mcop/mcopconfig.cc @@ -0,0 +1,67 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "mcopconfig.h" +#include "mcoputils.h" +#include <fstream> + +using namespace std; +using namespace Arts; + +MCOPConfig::MCOPConfig(const string& filename) :filename(filename) +{ +} + +string MCOPConfig::readEntry(const string& key, const string& defaultValue) +{ + ifstream in(filename.c_str()); + string keyvalue; + + while(in >> keyvalue) + { + int i = keyvalue.find("=",0); + if(i != 0 && keyvalue.substr( 0, i ) == key) + return keyvalue.substr( i+1, keyvalue.size()-(i+1) ); + } + return defaultValue; +} + +vector<string> *MCOPConfig::readListEntry(const string& key) +{ + vector<string> *result = new vector<string>; + + ifstream in(filename.c_str()); + string keyvalue; + + while(in >> keyvalue) + { + string k; + + MCOPUtils::tokenize(keyvalue,k,*result); + if(k == key) + return result; + + result->clear(); + } + + return result; +} diff --git a/mcop/mcopconfig.h b/mcop/mcopconfig.h new file mode 100644 index 0000000..04531f0 --- /dev/null +++ b/mcop/mcopconfig.h @@ -0,0 +1,55 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): MCOPConfig + * + * Is guaranteed to stay binary compatible. d ptr provided. + */ + +#ifndef MCOPCONFIG_H +#define MCOPCONFIG_H + +#include <string> +#include <vector> + +#include "arts_export.h" + +namespace Arts { + +class MCOPConfigPrivate; +class ARTS_EXPORT MCOPConfig { +private: + MCOPConfigPrivate *d; // unused +protected: + std::string filename; + +public: + MCOPConfig(const std::string& filename); + + std::string readEntry(const std::string& key, + const std::string& defaultValue = ""); + std::vector<std::string> *readListEntry(const std::string& key); +}; + +} +#endif /* MCOPCONFIG_H */ diff --git a/mcop/mcoputils.cc b/mcop/mcoputils.cc new file mode 100644 index 0000000..14275fb --- /dev/null +++ b/mcop/mcoputils.cc @@ -0,0 +1,574 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "mcoputils.h" +#include "mcopconfig.h" +#include "debug.h" +#include <pwd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <netdb.h> +#include <errno.h> +#include <config.h> +#include <ctype.h> +#include <cstdlib> +#include <cstring> +#include <stdio.h> +#include <map> + +using namespace std; +using namespace Arts; + +// 0: Dir ok +// 1: Dir not ok +static int check_tmp_dir(const char *tmp_dir) +{ + int result; + struct stat stat_buf; + result = lstat(tmp_dir, &stat_buf); + if ((result == -1) && (errno == ENOENT)) + { + return 1; + } + if ((result == -1) || (!S_ISDIR(stat_buf.st_mode))) + { + arts_warning("Error: \"%s\" is not a directory.\n", tmp_dir); + return 1; + } + + if (stat_buf.st_uid != getuid()) + { + arts_warning("Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir, stat_buf.st_uid, getuid()); + return 1; + } + return 0; +} + + +// 0: Link not ok +// != 0: location of mcop directory +static char *locate_mcop_dir() +{ + struct passwd *pw_ent; + char kde_tmp_dir[PATH_MAX+1]; + char user_tmp_dir[PATH_MAX+1]; + int uid = getuid(); + const char *home_dir = getenv("HOME"); + const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME"); + const char *kde_prefix = "/socket-"; + const char *tmp; + char *tmp_buf; + int result; + struct stat stat_buf; + + tmp = getenv("KDETMP"); + if (!tmp || !tmp[0]) + tmp = getenv("TMPDIR"); + if (!tmp || !tmp[0]) + tmp = "/tmp"; + + kde_tmp_dir[0] = 0; + + pw_ent = getpwuid(uid); + if (!pw_ent) + { + arts_warning("Error: Can not find password entry for uid %d.\n", getuid()); + return 0; + } + + strncpy(user_tmp_dir, tmp, PATH_MAX ); + user_tmp_dir[ PATH_MAX ] = '\0'; + strncat(user_tmp_dir, "/ksocket-", PATH_MAX - strlen(user_tmp_dir) ); + user_tmp_dir[ PATH_MAX ] = '\0'; + strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(user_tmp_dir)); + user_tmp_dir[ PATH_MAX ] = '\0'; + + if (!kde_home || !kde_home[0]) + { + kde_home = "~/.kde/"; + } + + if (kde_home[0] == '~') + { + if (uid == 0) + { + home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root"; + } + if (!home_dir || !home_dir[0]) + { + arts_fatal("Aborting. $HOME not set!"); + } + if (strlen(home_dir) > (PATH_MAX-100)) + { + arts_fatal("Aborting. Home directory path too long!"); + } + kde_home++; + strncpy(kde_tmp_dir, home_dir, PATH_MAX); + kde_tmp_dir[ PATH_MAX ] = '\0'; + } + strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir)); + + /** Strip trailing '/' **/ + if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/') + kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0; + + result = stat(kde_tmp_dir, &stat_buf); + if (result == -1) + { + return 0; + } + + strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir)); + if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0) + { + arts_fatal("Aborting. Could not determine hostname or hostname too long."); + } + kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0'; + + result = lstat(kde_tmp_dir, &stat_buf); + if ((result == 0) && (S_ISDIR(stat_buf.st_mode))) + { + /* $KDEHOME/socket-$HOSTNAME is a normal directory. Do nothing. */ + tmp_buf = (char *) malloc(PATH_MAX+1); + if (!tmp_buf) + return 0; + + strncpy(tmp_buf, kde_tmp_dir, PATH_MAX); + tmp_buf[ PATH_MAX ] = '\0'; + + return tmp_buf; + } + + if ((result == -1) && (errno == ENOENT)) + { + // Link mising... + return 0; + } + if ((result == -1) || (!S_ISLNK(stat_buf.st_mode))) + { + arts_warning("Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir); + return 0; + } + tmp_buf = (char *) malloc(PATH_MAX+1); + if (!tmp_buf) + return 0; + + /* kde_tmp_dir is a link. Check whether it points to a valid directory. */ + result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX); + if (result == -1) + { + arts_warning("Error: \"%s\" could not be read.\n", kde_tmp_dir); + free(tmp_buf); + return 0; + } + tmp_buf[result] = '\0'; +// printf("Link points to \"%s\"\n", tmp_buf); + if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0) + { + arts_warning("Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir); + free(tmp_buf); + return 0; + } + result = check_tmp_dir(tmp_buf); + if (result == 0) return tmp_buf; /* Success */ + + free(tmp_buf); + return 0; +} + +/* blatant and literal copy from lnusertemp to avoid kdelibs dependency */ +/* Copyright (c) 2000 Waldo Bastian <bastian@kde.org>, released under LGPL */ + +static +int create_link(const char *file, const char *tmp_dir) +{ + int result; + result = check_tmp_dir(tmp_dir); + if (result) + { + return result; + } + result = symlink(tmp_dir, file); + if (result == -1) + { + fprintf(stderr, "Error: Can not create link from \"%s\" to \"%s\"\n", file, tmp_dir); + return 1; + } + printf("Created link from \"%s\" to \"%s\"\n", file, tmp_dir); + return 0; +} + + +static +int build_link(const char *tmp_prefix, const char *kde_prefix) +{ + struct passwd *pw_ent; + char kde_tmp_dir[PATH_MAX+1]; + char user_tmp_dir[PATH_MAX+1]; + char tmp_buf[PATH_MAX+1]; + int uid = getuid(); + const char *home_dir = getenv("HOME"); + const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME"); + int result; + struct stat stat_buf; + + kde_tmp_dir[0] = 0; + + pw_ent = getpwuid(uid); + if (!pw_ent) + { + fprintf(stderr, "Error: Can not find password entry for uid %d.\n", getuid()); + return 1; + } + + strncpy(user_tmp_dir, tmp_prefix, PATH_MAX); + user_tmp_dir[ PATH_MAX ] = '\0'; + strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(tmp_prefix)); + + if (!kde_home || !kde_home[0]) + { + kde_home = "~/.kde/"; + } + + if (kde_home[0] == '~') + { + if (uid == 0) + { + home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root"; + } + if (!home_dir || !home_dir[0]) + { + fprintf(stderr, "Aborting. $HOME not set!"); + exit(255); + } + if (strlen(home_dir) > (PATH_MAX-100)) + { + fprintf(stderr, "Aborting. Home directory path too long!"); + exit(255); + } + kde_home++; + strncpy(kde_tmp_dir, home_dir, PATH_MAX); + kde_tmp_dir[ PATH_MAX ] = '\0'; + } + strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir)); + + /** Strip trailing '/' **/ + if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/') + kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0; + + result = stat(kde_tmp_dir, &stat_buf); + if ((result == -1) && (errno == ENOENT)) + { + result = mkdir(kde_tmp_dir, 0700); + } + if (result == -1) + { + return 1; + } + + strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir)); + if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0) + { + perror("Aborting. Could not determine hostname: "); + exit(255); + } + kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0'; + + result = lstat(kde_tmp_dir, &stat_buf); + if ((result == 0) && (S_ISDIR(stat_buf.st_mode))) + { + /* $KDEHOME/tmp is a normal directory. Do nothing. */ + printf("Directory \"%s\" already exists.\n", kde_tmp_dir); + return 0; + } + if ((result == -1) && (errno == ENOENT)) + { + printf("Creating link %s.\n", kde_tmp_dir); + result = create_link(kde_tmp_dir, user_tmp_dir); + if (result == 0) return 0; /* Success */ + unlink(kde_tmp_dir); + strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir)); + mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */ + return create_link(kde_tmp_dir, user_tmp_dir); + } + if ((result == -1) || (!S_ISLNK(stat_buf.st_mode))) + { + fprintf(stderr, "Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir); + return 1; + } + /* kde_tmp_dir is a link. Check whether it points to a valid directory. */ + result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX); + if (result == -1) + { + fprintf(stderr, "Error: \"%s\" could not be read.\n", kde_tmp_dir); + return 1; + } + tmp_buf[result] = '\0'; + printf("Link points to \"%s\"\n", tmp_buf); + if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0) + { + fprintf(stderr, "Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir); + unlink(kde_tmp_dir); + printf("Creating link %s.\n", kde_tmp_dir); + result = create_link(kde_tmp_dir, user_tmp_dir); + if (result == 0) return 0; /* Success */ + unlink(kde_tmp_dir); + strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir)); + mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */ + return create_link(kde_tmp_dir, user_tmp_dir); + return 1; + } + result = check_tmp_dir(tmp_buf); + if (result == 0) return 0; /* Success */ + unlink(kde_tmp_dir); + strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir)); + mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */ + return create_link(kde_tmp_dir, user_tmp_dir); +} + +string MCOPUtils::createFilePath(string name) +{ + static char *mcop_dir = 0; + if (!mcop_dir) + { + mcop_dir = locate_mcop_dir(); + } + if (!mcop_dir) + { + + const char *tmp = 0; + tmp = getenv("KDETMP"); + if (!tmp || !tmp[0]) + tmp = getenv("TMPDIR"); + if (!tmp || !tmp[0]) + tmp = "/tmp"; + + char tmp_prefix[PATH_MAX+1]; + strcpy(tmp_prefix, tmp); + strcat(tmp_prefix, "/ksocket-"); + + build_link(tmp_prefix, "/socket-"); + mcop_dir = locate_mcop_dir(); + } + if (!mcop_dir) + { + arts_fatal("can't create mcop directory"); + } + string tmpdir = mcop_dir; + return tmpdir+"/"+name; +} + +/* + * try to figure out full hostname - this is important as every client which + * tries to connect objects located here will need to be able to resolve that + * correctly + */ +string MCOPUtils::getFullHostname() +{ + char buffer[1024]; + string result; + struct hostent *hp; + + if(gethostname(buffer,1024) == 0) { + buffer[1023] = '\0'; + result = buffer; + } else + return "localhost"; + + /* + * if gethostname() isn't a FQDN (guess that by checking whether it + * contains a dot), try to look it up to ensure it is + */ + if(result.find('.') == string::npos && (hp = gethostbyname(buffer)) != 0) + result = hp->h_name; + + return result; +} + +string MCOPUtils::readConfigEntry(const string& key, const string& defaultValue) +{ + const char *home = getenv("HOME"); + if(home) + { + string rcname = home + string("/.mcoprc"); + + MCOPConfig config(rcname); + return config.readEntry(key,defaultValue); + } + return defaultValue; +} + +/** IID generation **/ + +unsigned long MCOPUtils::makeIID(const string& interfaceName) +{ + static map<string, unsigned long> *iidmapobj = 0; + static unsigned long nextiid = 1; + + if(!iidmapobj) iidmapobj = new map<string,unsigned long>; + + map<string,unsigned long>& iidmap = *iidmapobj; + + if(iidmap.find(interfaceName) == iidmap.end()) { + iidmap[interfaceName] = nextiid++; + return nextiid-1; // no need to lookup in the map thrice + } + + return iidmap[interfaceName]; +} + +static vector<string> *readPath(const string& name, const string& defaultValue) +{ + vector<string> *result = 0; + const char *home = getenv("HOME"); + + if(home) + { + string rcname = home + string("/.mcoprc"); + + MCOPConfig config(rcname); + result = config.readListEntry(name); + } + if(!result) + result = new vector<string>; + if(result->empty()) + result->push_back(defaultValue); + + return result; +} + +const vector<string> *MCOPUtils::extensionPath() +{ + static vector<string> *result = 0; + + if(!result) result = readPath("ExtensionPath", EXTENSION_DIR); + return result; +} + +const vector<string> *MCOPUtils::traderPath() +{ + static vector<string> *result = 0; + + if(!result) + { + result = readPath("TraderPath", TRADER_DIR); + + const char *home = getenv("HOME"); + if(home) result->push_back(home + string("/.mcop/trader-cache")); + } + return result; +} + +string MCOPUtils::mcopDirectory() +{ + static bool initialized = false; + static string mcopDirectory; + + if(initialized) + return mcopDirectory; + initialized = true; + + const char *home = getenv("HOME"); + arts_return_val_if_fail(home != 0, ""); + + mcopDirectory = home + string("/.mcop"); + + mkdir(home,0755); + if(mkdir(mcopDirectory.c_str(),0755) != 0) + { + string why = strerror(errno); + + struct stat st; + stat(mcopDirectory.c_str(),&st); + if(!S_ISDIR(st.st_mode)) + { + arts_warning("can't create directory %s (%s)", + mcopDirectory.c_str(), why.c_str()); + + mcopDirectory = ""; + } + } + return mcopDirectory; +} + +bool MCOPUtils::tokenize(const string& line, string& key,vector<string>& values) +{ + string value; + enum { sKey, sValue, sValueQuoted, sValueQuotedEscaped, sBad } state; + + state = sKey; + for(string::const_iterator i = line.begin(); i != line.end(); i++) + { + char c = *i; + unsigned char uc = static_cast<unsigned char>(c); + + arts_assert(c != '\n'); + + if(state == sKey) + { + if(c == ' ' || c == '\t') + ; // ignore + else if(isalnum(c)) + key += c; + else if(c == '=') + state = sValue; + else + state = sBad; + } + else if(state == sValue) + { + if(c == ' ' || c == '\t') + ; // ignore + else if(c == '"') + state = sValueQuoted; + else if(c == ',') + { + values.push_back(value); + value = ""; + } + else if(uc > 32 && uc < 128) + value += c; + else + state = sBad; + } + else if(state == sValueQuoted) + { + if(c == '"') + state = sValue; + else if(c == '\\') + state = sValueQuotedEscaped; + else + value += c; + } + else if(state == sValueQuotedEscaped) + { + value += c; + state = sValueQuoted; + } + } + if(state == sValue) + values.push_back(value); + + return(state != sBad); +} diff --git a/mcop/mcoputils.h b/mcop/mcoputils.h new file mode 100644 index 0000000..ecfe9b0 --- /dev/null +++ b/mcop/mcoputils.h @@ -0,0 +1,97 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): MCOPUtils + * + * Collection class for all kinds of utility functions. BC, since never + * instanciated. + */ + +#ifndef MCOPUTILS_H +#define MCOPUTILS_H + +#include <string> +#include <vector> + +#include "arts_export.h" + +namespace Arts { + +class ARTS_EXPORT MCOPUtils { +public: + /** + * Returns the full pathname to a file in the mcop directory which + * is called "name". It will also care that no other characters than + * A-Z,a-z,0-9,-,_ occur. + * + * The result is something like /tmp/mcop-<username>/name, the directory + * will be created when necessary. + */ + static std::string createFilePath(std::string name); + + /** + * Returns the fully qualified hostname, such as "www.kde.org" (of course + * this may fail due to misconfiguration). + * + * The result is "localhost" if nothing at all can be found out. + */ + static std::string getFullHostname(); + + /** + * Returns configuration values from .mcoprc + */ + static std::string readConfigEntry(const std::string& key, + const std::string& defaultValue = ""); + + /** + * Makes an interface ID from string - if the given string is already + * known, the returned IID will be the one returned last time. If not, + * a new IID is generated + */ + static unsigned long makeIID(const std::string& interfaceName); + + /** + * Returns the directories for the trader to look into + */ + static const std::vector<std::string> *traderPath(); + + /** + * Returns the directories from where extensions can be loaded + */ + static const std::vector<std::string> *extensionPath(); + + /** + * Returns the full path of the ~/.mcop directory + */ + static std::string mcopDirectory(); + + /** + * Tokenization of a key = value1, "value 2", "value III" line into the key + * and the values. + */ + static bool tokenize(const std::string& line, std::string& key, + std::vector<std::string>& values); +}; + +} +#endif /* MCOPUTILS_H */ diff --git a/mcop/md5.c b/mcop/md5.c new file mode 100644 index 0000000..782ce30 --- /dev/null +++ b/mcop/md5.c @@ -0,0 +1,197 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "md5.h" + +/* + * this is okay for all architectures with int = 32bit, so IMHO all + * current architectures supported by KDE. + */ +typedef unsigned int uint32; + +static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN]); + +void arts_md5sum(unsigned char *message, long len, char *md5sum) +{ + long finalsize = len+1; /* in bytes */ + int i = 0, j = 0; + unsigned char w = '\0'; + uint32 buffer[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476}; + uint32 in[MD5_BINARY_LEN]; + + while((finalsize & 63) != 56) finalsize++; + finalsize += 8; + + for( i=0, j=0;i<finalsize;i++) + { + if(i < len) { + w = message[i]; + } else if(i == len) { + w = 0x80; + } else if((finalsize-i > 8) || (finalsize-i <= 4)) { + w = 0; + } else { + /* well, the length thing encoded in here will only + work until 2^32 bits (though md5 would support 2^64 + bits) */ + w = ((len*8) >> ((i+8-finalsize)*8)) & 0xff; + } + switch(i & 3) { + case 0: in[j] = w; + break; + case 1: in[j] |= w << 8; + break; + case 2: in[j] |= w << 16; + break; + case 3: in[j] |= w << 24; + j++; + if(j == MD5_BINARY_LEN) { + MD5Transform(buffer,in); + j = 0; + } + break; + } + } + + for( i=0, j=0;j<4;j++) + { + md5sum[i++] = buffer[j] & 0xff; + md5sum[i++] = (buffer[j] >> 8) & 0xff; + md5sum[i++] = (buffer[j] >> 16) & 0xff; + md5sum[i++] = (buffer[j] >> 24) & 0xff; + } +} + +/* + * I used the central part of Colin Plumb's public domain MD5 implementation + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + */ + + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN]) +{ + uint32 a = buf[0]; + uint32 b = buf[1]; + uint32 c = buf[2]; + uint32 d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/mcop/md5.h b/mcop/md5.h new file mode 100644 index 0000000..5670d7e --- /dev/null +++ b/mcop/md5.h @@ -0,0 +1,45 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): arts_md5sum + * + * No binary compatibility guaranteed (part of Dispatcher's security model). + */ + +#ifndef MD5_H +#define MD5_H + +#define MD5_BINARY_LEN 16 + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +void arts_md5sum(unsigned char *message, long len, char *md5sum); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/mcop/md5auth.cc b/mcop/md5auth.cc new file mode 100644 index 0000000..1e6fe1a --- /dev/null +++ b/mcop/md5auth.cc @@ -0,0 +1,213 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> + +#include <sys/utsname.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <assert.h> +#include <stdlib.h> + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#elif HAVE_SYS_TIME_H +# include <sys/time.h> +#else +# include <time.h> +#endif + +#include "md5.h" +#include "md5auth.h" +#include "debug.h" + +// MD5_BINARY_LEN is defined in md5.h +#define MD5_COOKIE_LEN (MD5_BINARY_LEN*2) +#define MD5_MANGLE_LEN (MD5_COOKIE_LEN*2) + + + +struct random_info { + struct timeval tv; + int pid; + struct utsname un; + char dev_urandom[MD5_BINARY_LEN]; + char seed[MD5_COOKIE_LEN+1]; + int number; +}; + +static char md5_seed[MD5_COOKIE_LEN+1]; +static char md5_cookie[MD5_COOKIE_LEN+1]; +static int md5_init = 0; +static int md5_random_cookie_number = 0; + +static char *md5_to_ascii_overwrite(char *md5) +{ + char outascii[MD5_COOKIE_LEN+1]; + char *result; + int i; + + // convert to readable text + for(i = 0; i < MD5_BINARY_LEN; i++) { + sprintf(&outascii[i*2],"%02x",md5[i] & 0xff); + } + outascii[MD5_COOKIE_LEN] = 0; + result = strdup(outascii); + + // try to zero out traces + memset(md5,0,MD5_BINARY_LEN); + memset(outascii,0,MD5_COOKIE_LEN); + + // well, here it is + return result; +} + +char *arts_md5_auth_mangle(const char *cookie) +{ + char mangle[MD5_MANGLE_LEN+1]; + char out[MD5_BINARY_LEN]; + assert(md5_init); + + // concat the two cookies and mangle them to a new one + strncpy(mangle,md5_cookie, MD5_COOKIE_LEN); + mangle[MD5_COOKIE_LEN] = 0; + strncat(mangle,cookie, MD5_COOKIE_LEN); + mangle[MD5_MANGLE_LEN] = 0; + arts_md5sum((unsigned char *)mangle,MD5_MANGLE_LEN,out); + + // try to zero out traces + memset(mangle,0,MD5_MANGLE_LEN); + + return md5_to_ascii_overwrite(out); +} + +char *arts_md5_auth_mkcookie() +{ + struct random_info r; + char out[MD5_BINARY_LEN]; + int rndfd; + + memset(&r,0,sizeof(struct random_info)); + + // collect some "random" system information + gettimeofday(&r.tv,0); + r.pid = getpid(); + uname(&r.un); + + // linux random device ; if that works, we have good random anyway, the + // above are just helpers for the case that it doesn't + rndfd = open("/dev/urandom",O_RDONLY); + if(rndfd != -1) + { + read(rndfd,r.dev_urandom,MD5_BINARY_LEN); + close(rndfd); + } + + // ensure that two cookies that are requested very shortly after each + // other (so that it looks like "at the same time") won't be the same + r.number = ++md5_random_cookie_number; + + // this is some seed from a file which is updated sometimes with a + // new "arts_md5_auth_mkcookie()" after initialization + strncpy(r.seed,md5_seed,MD5_COOKIE_LEN); + + // build hash value of all information + arts_md5sum((unsigned char *)&r,sizeof(struct random_info),out); + + // zero out traces and return + memset(&r,0,sizeof(struct random_info)); + return md5_to_ascii_overwrite(out); +} + +const char *arts_md5_auth_cookie() +{ + assert(md5_init); + return md5_cookie; +} + +static int md5_load_cookie(const char *filename, char *cookie) +{ + int fd = open(filename,O_RDONLY); + int i; + + if(fd != -1) { + struct stat st; + for(i=0;i<5;i++) { + fstat(fd,&st); + if(st.st_size == MD5_COOKIE_LEN) { + lseek(fd, 0, SEEK_SET); + if(read(fd,cookie,MD5_COOKIE_LEN) == MD5_COOKIE_LEN) + { + cookie[MD5_COOKIE_LEN] = 0; + close(fd); + return 1; + } + } + arts_warning("MCOP: " + "authority file has wrong size (just being written?)"); + sleep(1); + } + } + return 0; +} + +void arts_md5_auth_init_seed(const char *seedname) +{ + // don't care if it works - no harm is being done if it doesn't + md5_load_cookie(seedname,md5_seed); + + /* + * maxage ensures that not everybody will try to update the seed + * at the same time, while it will take at most 5 hours between + * updates (if there are any initialization calls) + */ + struct stat st; + int maxage = 300 + (getpid() & 0xfff)*4; + int lstat_result = lstat(seedname,&st); + if(lstat_result != 0 || (time(0) - st.st_mtime) > maxage) + { + int fd = open(seedname,O_TRUNC|O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR); + if(fd != -1) { + char *cookie = arts_md5_auth_mkcookie(); + write(fd,cookie,strlen(cookie)); + memset(cookie,0,strlen(cookie)); + free(cookie); + close(fd); + } + } +} + +bool arts_md5_auth_set_cookie(const char *cookie) +{ + if(strlen(cookie) != MD5_COOKIE_LEN) + return false; + + strncpy(md5_cookie,cookie,MD5_COOKIE_LEN); + md5_cookie[MD5_COOKIE_LEN] = 0; + md5_init = 1; + return true; +} diff --git a/mcop/md5auth.h b/mcop/md5auth.h new file mode 100644 index 0000000..c0197ff --- /dev/null +++ b/mcop/md5auth.h @@ -0,0 +1,105 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): arts_md5_* + * + * No guarantees - do not use. + */ + +#ifndef MD5_AUTH_H +#define MD5_AUTH_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * How that MD5 auth stuff is supposed to work: + * + * Initialization: + * + * Your service calls arts_md5_auth_set_cookie and passes a "secret cookie". + * Lets call the "secret cookie" S. As soon as a client wants to connect, + * he needs the same secret cookie S. + * + * Of course the user can copy the "secret cookie" using a secure connection + * to any computer from which he wants to access the service. + * + * 0. SERVER: if no common secret cookie is available, generate a random + * cookie and keep it secret - ensure (through secure connections) + * that the client gets the secret cookie + * + * 1. SERVER: generate a new (random) cookie R + * 2. SERVER: send it to the client + * 3. CLIENT: (should get/have the "secret cookie" S from somewhere secure) + * 4. CLIENT: mangle the cookies R and S to a mangled cookie M + * 5. CLIENT: send M to the server + * 6. SERVER: verify that mangling R and S gives just the same thing as the + * cookie M received from the client. If yes, authentication is successful. + * + * The advantage of that protocol is, that even somebody who can read all + * network traffic can't find out the secret cookie S, as that is never + * transferred as plaintext. + */ + +/* + * generates a new random cookie R (also be used to generate secret cookies) + * => free it when you don't need it any more + */ +char *arts_md5_auth_mkcookie(); + +/* + * mangles a "secret cookie" with another "random cookie" + * => free result when done + */ +char *arts_md5_auth_mangle(const char *random); + +/* + * using arts_md5_auth_init_seed, the security will be improved by loading a + * randomseed from that file, and (if it has no recent date) saving a new + * seed to it - this will ensure that the arts_md5_auth_mkcookie() routine will + * return a really unpredictable result (as it depends on all processes that + * ever have touched the seed) + */ +void arts_md5_auth_init_seed(const char *seedname); + +/* + * use this routine to set the "secret cookie" - you can pass a newly + * generated random cookie here, or the secret cookie you got from + * elsewhere (to communicate with others) + * + * returns true if success (good cookie), false if setting the cookie failed + */ +bool arts_md5_auth_set_cookie(const char *cookie); + +/* + * returns "secret cookie" + */ +const char *arts_md5_auth_cookie(); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/mcop/namedstore.h b/mcop/namedstore.h new file mode 100644 index 0000000..e5fad59 --- /dev/null +++ b/mcop/namedstore.h @@ -0,0 +1,125 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_NAMEDSTORE_H +#define ARTS_NAMEDSTORE_H + +#include <string> +#include <list> +#include <vector> +#include "stdio.h" + +/* + * BC - Status (2002-03-08): NamedStore + * + * None of these classes is considered part of the public API. Do NOT use it + * in your apps. These are part of the implementation of object.cc and not + * to be used elsewhere. + */ + +namespace Arts { + +/** + * -- internal class -- + * + * this stores key-value pairs, where key is a string which is kept unique + */ +template<class T> +class NamedStore +{ +private: + class Element { + public: + T t; + std::string name; + + Element(const T& t, const std::string& name) :t(t), name(name) { } + }; + typedef std::list<Element> Element_list; + Element_list elements; + +public: + bool get(const std::string& name, T& result) + { + typename Element_list::iterator i; + for(i = elements.begin(); i != elements.end(); i++) + { + if(i->name == name) + { + result = i->t; + return true; + } + } + + return false; + } + bool remove(const std::string& name) + { + typename Element_list::iterator i; + for(i = elements.begin(); i != elements.end(); i++) + { + if(i->name == name) + { + elements.erase(i); + return true; + } + } + return false; + } + std::vector<std::string> *contents() + { + std::vector<std::string> *result = new std::vector<std::string>; + + typename Element_list::iterator i; + for(i = elements.begin(); i != elements.end(); i++) + result->push_back(i->name); + + return result; + } + std::string put(const std::string& name, const T& t) + { + std::string xname = name; + int append = 1; + + for(;;) + { + typename Element_list::iterator i; + + i = elements.begin(); + while(i != elements.end() && i->name != xname) + i++; + + if(i == elements.end()) + { + elements.push_back(Element(t,xname)); + return xname; + } + + char buffer[1024]; + sprintf(buffer,"%d",append++); + xname = name + std::string(buffer); + } + } +}; + +} +#endif /* ARTS_NAMEDSTORE_H */ diff --git a/mcop/notification.cc b/mcop/notification.cc new file mode 100644 index 0000000..3fd70d1 --- /dev/null +++ b/mcop/notification.cc @@ -0,0 +1,101 @@ + /* + + Copyright (C) 2000-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "notification.h" +#include "debug.h" +#include "dispatcher.h" + +using namespace Arts; + +void NotificationClient::notify(const Notification&) +{ +} + +NotificationManager::NotificationManager() +{ + arts_assert(!instance); + instance = this; +} + +NotificationManager::~NotificationManager() +{ + arts_assert(instance); + instance = 0; +} + +void NotificationManager::send(Notification wm) +{ + if (todo.empty()) { + // HACK: in order to not add a virtual function to IOManager we're calling addTimer with + // magic values. This call tells the ioManager that notifications are pending and + // NotificationManager::run() should get called soon. + Arts::Dispatcher::the()->ioManager()->addTimer(-1, 0); + } + todo.push(wm); +} + +bool NotificationManager::run() +{ + if(todo.empty()) return false; + + while(!todo.empty()) + { + Notification wm = todo.front(); + todo.pop(); + + /* + * we'll copy and remove the notification first, to be sure that + * nothing bad happens to it if we rebuild "todo" (for instance in + * removeClient) + */ + wm.receiver->notify(wm); + } + return true; +} + +void NotificationManager::removeClient(NotificationClient *client) +{ + std::queue<Notification> newTodo; + + while(!todo.empty()) + { + const Notification& n = todo.front(); + if(n.receiver != client) + newTodo.push(n); + else + { + arts_debug("NotificationManager: removing one notification"); + NotificationDestroyFunction destroy = + (NotificationDestroyFunction)n.internal; + if(destroy) destroy(n); + } + todo.pop(); + } + todo = newTodo; +} + +void Notification::setDestroy(NotificationDestroyFunction destroy) +{ + internal = (void*)destroy; +} + +NotificationManager *NotificationManager::instance = 0; diff --git a/mcop/notification.h b/mcop/notification.h new file mode 100644 index 0000000..6a8582f --- /dev/null +++ b/mcop/notification.h @@ -0,0 +1,87 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef NOTIFICATION_H +#define NOTIFICATION_H + +#include <queue> +#include "arts_export.h" + +namespace Arts { + +/* + * BC - Status (2002-03-08): Notification, NotificationClient, + * NotificationManager + * + * All need to be kept BC, NotificationManager with usual d ptr. + * + * Notifications have to be FAST. Currently, they use ID, data & receiver. + * However, there may be future extensions. For this, one more internal + * field is provided. Set it to ZERO currently when sending notifications. + */ + +struct Notification; +typedef void (*NotificationDestroyFunction)(const Notification& n); + +struct Notification { + class NotificationClient *receiver; + int ID; + void *data; + void *internal; /* handle with care, equivalent to private d ptr */ + + void setDestroy(NotificationDestroyFunction destroy); +}; + +class ARTS_EXPORT NotificationClient { +public: + virtual void notify(const Notification& wm); +}; + +class NotificationManagerPrivate; +class ARTS_EXPORT NotificationManager { +private: + NotificationManagerPrivate *d; // unused +protected: + std::queue<Notification> todo; + static NotificationManager *instance; + +public: + NotificationManager(); + ~NotificationManager(); + + static inline NotificationManager *the() + { + return instance; + } + void send(Notification wm); + inline bool pending() + { + return !todo.empty(); + } + bool run(); + void removeClient(NotificationClient *client); + +}; + +} + +#endif /* NOTIFICATION_H */ diff --git a/mcop/object.cc b/mcop/object.cc new file mode 100644 index 0000000..9f01912 --- /dev/null +++ b/mcop/object.cc @@ -0,0 +1,1528 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "object.h" +#include "dispatcher.h" +#include "flowsystem.h" +#include "weakreference.h" +#include "namedstore.h" +#include "debug.h" +#include "anyref.h" +#include <stdio.h> +#include <iostream> +#include <cstdlib> + +using namespace std; +using namespace Arts; + +namespace Arts { + class AttributeSlotBind; +} + +class Arts::ObjectInternalData { +public: + struct MethodTableEntry { + union { + DispatchFunction dispatcher; + OnewayDispatchFunction onewayDispatcher; + DynamicDispatchFunction dynamicDispatcher; + } dispFunc; + enum { dfNormal, dfOneway, dfDynamic } dispatchStyle; + void *object; + MethodDef methodDef; + }; + + list<WeakReferenceBase *> weakReferences; + NamedStore<Arts::Object> children; + bool stubForLocalObject; + + // for _skel classes only: + bool methodTableInit; + std::vector<MethodTableEntry> methodTable; + list<AttributeSlotBind *> attributeSlots; +}; + +struct Object_base::ObjectStreamInfo { + string name; + long flags; + void *ptr; +}; + +/*****************************************************************************/ +/* the following methods/classes are necessary for attribute notifications */ +/*****************************************************************************/ + +namespace Arts { + class AttributeDataPacket : public GenericDataPacket { + public: + Buffer b; + AttributeDataPacket(GenericDataChannel *channel) + : GenericDataPacket(channel) + { + size = 0; + b.writeLong(0); + } + void add(const AnyConstRef& r) + { + r.write(&b); + b.patchLong(0,++size); + } + + void ensureCapacity(int) + { + } + void read(Buffer& stream) + { + vector<mcopbyte> all; + size = stream.readLong(); + b.patchLong(0,size); + stream.read(all,stream.remaining()); + b.write(all); + } + void write(Buffer& stream) + { + vector<mcopbyte> all; + b.rewind(); + b.read(all,b.remaining()); + stream.write(all); + } + }; + class AttributeSlotBind : public GenericAsyncStream { + public: + GenericDataPacket *createPacket(int) + { + return allocPacket(); + } + AttributeDataPacket *allocPacket() + { + return new AttributeDataPacket(channel); + } + + void freePacket(GenericDataPacket *packet) + { + delete packet; + } + + GenericAsyncStream *createNewStream() + { + return new AttributeSlotBind(); + } + + virtual ~AttributeSlotBind() + { + } + + string method; + bool output; + }; +} + +bool Object_skel::_initAttribute(const AttributeDef& attribute) +{ + long flags = attribute.flags; + + if(flags & attributeAttribute) + { + flags |= attributeStream | streamAsync; + flags &= ~attributeAttribute; + } + else + { + arts_warning("attribute init on stream %s", attribute.name.c_str()); + return false; + } + + list<AttributeSlotBind *>::iterator i; + for(i = _internalData->attributeSlots.begin(); + i != _internalData->attributeSlots.end(); i++) + { + AttributeSlotBind *b = *i; + if(b->method == "_set_"+attribute.name + || b->method == attribute.name + "_changed") + { + arts_warning("double attribute init %s",b->method.c_str()); + return false; + } + } + if(flags & streamIn) + { + AttributeSlotBind *b = new AttributeSlotBind(); + b->output = false; + b->method = "_set_"+attribute.name; + _internalData->attributeSlots.push_back(b); + + _scheduleNode->initStream(attribute.name, b, flags & (~streamOut)); + } + if(flags & streamOut) + { + string changed = attribute.name + "_changed"; + AttributeSlotBind *b = new AttributeSlotBind(); + b->output = true; + b->method = changed; + _internalData->attributeSlots.push_back(b); + + _scheduleNode->initStream(changed, b, flags & (~streamIn)); + } + return true; +} + +void Object_skel::_defaultNotify(const Notification& notification) +{ + list<AttributeSlotBind *>::iterator i; + list<AttributeSlotBind *>& slots = _internalData->attributeSlots; + + for(i = slots.begin(); i != slots.end(); i++) + { + if((*i)->notifyID() == notification.ID) + { + GenericDataPacket *dp = (GenericDataPacket *)notification.data; + Buffer params; + + dp->write(params); + + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + + typedef ObjectInternalData::MethodTableEntry MTE; + vector<MTE>::iterator mti; + + for(mti = _internalData->methodTable.begin(); + mti != _internalData->methodTable.end(); mti++) + { + if(mti->methodDef.name == (*i)->method) + { + Buffer result; + + long count = params.readLong(); + while(params.remaining()) + { + if(mti->dispatchStyle == MTE::dfNormal) + { + mti->dispFunc.dispatcher(mti->object, ¶ms, &result); + } + else if(mti->dispatchStyle == MTE::dfDynamic) + { + long methodID; + methodID = mti - _internalData->methodTable.begin(); + mti->dispFunc.dynamicDispatcher(mti->object, methodID, + ¶ms, &result); + } + else + { + arts_assert(0); + } + count--; + } + arts_assert(count == 0); + } + } + dp->processed(); + } + } +} + +void Object_skel::notify(const Notification& notification) +{ + _copy(); + _defaultNotify(notification); + _release(); +} + +/* for simplicity and efficiency, enums are emitted as normal "long" values, + * so that finding out/using the enum type via value.type() is not be possible + */ +void Object_skel::_emit_changed(const char *attrib, const AnyConstRef& value) +{ + list<AttributeSlotBind *>::iterator i; + list<AttributeSlotBind *>& slots = _internalData->attributeSlots; + + for(i = slots.begin(); i != slots.end(); i++) + { + if((*i)->method == attrib) + { + AttributeDataPacket *adp = + (AttributeDataPacket *)(*i)->createPacket(1); + adp->add(value); + adp->send(); + return; + } + } +} + + +bool Object_skel::_generateSlots(const std::string& name, + const std::string& interface) +{ + InterfaceDef d = _queryInterface(interface); + vector<string>::iterator ii; + for(ii = d.inheritedInterfaces.begin(); + ii != d.inheritedInterfaces.end(); ii++) + { + if(_generateSlots(name, *ii)) return true; + } + + vector<AttributeDef>::iterator ai; + for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++) + { + if(ai->flags & attributeAttribute) + { + if((ai->flags & streamIn && ai->name == name) + || (ai->flags & streamOut && ai->name+"_changed" == name)) + { + _initAttribute(*ai); + return true; + } + } + } + return false; +} + +bool Object_skel::_QueryInitStreamFunc(Object_skel *skel, const + std::string& name) +{ + /* + * this function + * + * checks if there is a stream which should be added called <name>, + * and returns true if it in fact added a stream, so that requesting + * function needs to retry + */ + bool result = skel->_generateSlots(name, skel->_interfaceName()); + if(!result) + { + arts_warning("used stream %s on object %s, which doesn't seem to exist", + name.c_str(), skel->_interfaceName().c_str()); + } + return result; +} + +/*****************************************************************************/ + + +/* + * Object: common for every object + */ + +long Object_base::_staticObjectCount = 0; + +Object_base::Object_base() : _deleteOk(false), _scheduleNode(0), _nextNotifyID(1), + _refCnt(1) +{ + _internalData = new Arts::ObjectInternalData(); + _internalData->stubForLocalObject = false; + _staticObjectCount++; +} + +void Object_base::_destroy() +{ + _deleteOk = true; + + if(_scheduleNode && !_internalData->stubForLocalObject) + { + if(_scheduleNode->remoteScheduleNode()) + { + delete _scheduleNode; + } + else + { + FlowSystem_impl *fs = Dispatcher::the()->flowSystem(); + assert(fs); + + fs->removeObject(_scheduleNode); + } + } + delete this; +} + +Object_base::~Object_base() +{ + if(!_deleteOk) + { + arts_fatal("reference counting violation - you may not call delete " + "manually - use _release() instead"); + } + assert(_deleteOk); + + /* remove attribute slots */ + list<AttributeSlotBind *>::iterator ai; + for(ai = _internalData->attributeSlots.begin(); + ai != _internalData->attributeSlots.end(); ai++) + { + delete (*ai); + } + + /* clear stream list */ + list<ObjectStreamInfo *>::iterator osii; + for(osii = _streamList.begin(); osii != _streamList.end(); osii++) + delete (*osii); + + /* inform weak references that we don't exist any longer */ + while(!_internalData->weakReferences.empty()) + _internalData->weakReferences.front()->release(); + + /* inform notification manager that we don't exist any longer */ + NotificationManager::the()->removeClient(this); + + delete _internalData; + _staticObjectCount--; +} + +ScheduleNode *Object_base::_node() +{ + if(!_scheduleNode) + { + switch(_location()) + { + case objectIsLocal: + { + FlowSystem_impl *fs = Dispatcher::the()->flowSystem(); + assert(fs); + _scheduleNode = fs->addObject(_skel()); + + /* init streams */ + + list<ObjectStreamInfo *>::iterator osii; + for(osii = _streamList.begin(); osii != _streamList.end(); osii++) + { + _scheduleNode->initStream((*osii)->name,(*osii)->ptr,(*osii)->flags); + } + _scheduleNode->initStream("QueryInitStreamFunc", + (void *)Object_skel::_QueryInitStreamFunc, -1); + } + break; + + case objectIsRemote: + { + /* + * if we're just a stub to an object that is local inside + * this process, then we don't create a new schedule node, + * but find the one associated with the implementation + * + * (this happens for instance for objects implemented as + * artsbuilder structures) + */ + if(_internalData->stubForLocalObject) + { + Dispatcher *disp = Dispatcher::the(); + Object_skel *localObject; + + localObject = disp->getLocalObject(_stub()->_objectID); + arts_assert(localObject); + + _scheduleNode = localObject->_node(); + localObject->_release(); + } + else + { + _scheduleNode = new RemoteScheduleNode(_stub()); + } + } + break; + } + + assert(_scheduleNode); + } + return _scheduleNode; +} + +bool Object_base::_isEqual(Object_base *object) const +{ + return (_internalObjectID == object->_internalObjectID); +} + +void *Object_base::_cast(unsigned long iid) +{ + if(iid == Object_base::_IID) return (Object *)this; + return 0; +} + +void *Object_base::_cast(const std::string& interface) +{ + return _cast(MCOPUtils::makeIID(interface)); +} + +bool Object_base::_error() +{ + // no error as default ;) + return false; +} + +Object_skel *Object_base::_skel() +{ + assert(false); + return 0; +} + +Object_stub *Object_base::_stub() +{ + assert(false); + return 0; +} + +Object_stub *Object_stub::_stub() +{ + return this; +} + +Object_base::ObjectLocation Object_stub::_location() const +{ + return objectIsRemote; +} + +Object_skel *Object_skel::_skel() +{ + return this; +} + +Object_base::ObjectLocation Object_skel::_location() const +{ + return objectIsLocal; +} + +void Object_skel::_initStream(const string& name, void *ptr, long flags) +{ + ObjectStreamInfo *osi = new ObjectStreamInfo; + osi->name = name; + osi->ptr = ptr; + osi->flags = flags; + _streamList.push_back(osi); +} + +void Object_base::calculateBlock(unsigned long) +{ +} + +string Object_base::_interfaceName() +{ + assert(0); // derived classes *must* override this + return ""; +} + +Buffer *Object_base::_allocCustomMessage(long /*handlerID*/) +{ + assert(0); + return 0; +} + +void Object_base::_sendCustomMessage(Buffer *buffer) +{ + assert(0); + delete buffer; +} + +// Default I/O: nothing at this level, use child virtuals +vector<std::string> Object_base::_defaultPortsIn() const +{ + vector<std::string> ret; + return ret; +} +vector<std::string> Object_base::_defaultPortsOut() const +{ + vector<std::string> ret; + return ret; +} + +// Weak References + +void Object_base::_addWeakReference(WeakReferenceBase *b) +{ + _internalData->weakReferences.push_back(b); +} + +void Object_base::_removeWeakReference(WeakReferenceBase *b) +{ + _internalData->weakReferences.remove(b); +} + +/* + * Stuff for object skeletons + */ + +Object_skel::Object_skel() :_remoteSendCount(0), _remoteSendUpdated(false) +{ + _objectID = Dispatcher::the()->addObject(this); + _connection = Dispatcher::the()->loopbackConnection(); + _internalData->methodTableInit = false; + +/* big enough for our header + 0x + needed number of hex characters + ending NULL */ + char ioid[7 + 2*sizeof(void *)+1]; + sprintf(ioid,"SKEL:%p",(void *)this); + _internalObjectID = ioid; +} + +Object_skel::~Object_skel() +{ + Dispatcher::the()->removeObject(_objectID); +} + +// flow system + +FlowSystem Object_skel::_flowSystem() +{ + FlowSystem_base *fs = Dispatcher::the()->flowSystem(); + if(fs) + return FlowSystem::_from_base(fs->_copy()); + else + return FlowSystem::null(); +} + +// reference counting + +void Object_skel::_release() +{ + arts_return_if_fail(_refCnt > 0); + + _refCnt--; + if(_refCnt == 0) _destroy(); +} + +void Object_skel::_copyRemote() +{ + // cout << "_copyRemote();" << endl; + + _copy(); + _remoteSendCount++; + _remoteSendUpdated = true; +} + +void Object_skel::_releaseRemote() +{ + //cout << "_releaseRemote();" << endl; + + Connection *conn = Dispatcher::the()->activeConnection(); + list<Connection *>::iterator i; + bool found = false; + + for(i=_remoteUsers.begin(); !found && i != _remoteUsers.end(); i++) + { + found = (*i) == conn; + if(found) + { + _remoteUsers.erase(i); + break; + } + } + assert(found); + _release(); +} + +void Object_skel::_useRemote() +{ + //cout << "_useRemote();" << endl; + + Connection *conn = Dispatcher::the()->activeConnection(); + if(_remoteSendCount == 0) + { + arts_warning("_useRemote without prior _copyRemote() - this might fail sometimes"); + _copyRemote(); + } + + _remoteSendCount--; + _remoteUsers.push_back(conn); +} + +/* + * This is needed when we've received an object from wire which we now + * hold locally. Of course it has been _copyRemote()d (rightly so), but + * we will not use it remotely, so we need to cancel the _copyRemote(). + * + * Added to _base due to BC. + */ +void Object_base::_cancelCopyRemote() +{ + assert(_location() == objectIsLocal); + + if(_skel()->_remoteSendCount == 0) + { + arts_warning("_cancelCopyRemote without prior _copyRemote() - this might fail sometimes"); + } + else + { + _skel()->_remoteSendCount--; + _release(); + } +} + +void Object_skel::_disconnectRemote(Connection *conn) +{ + //cout << "_disconnectRemote();" << endl; + + int rcount = 0; + list<Connection *>::iterator i; + + i=_remoteUsers.begin(); + while(i != _remoteUsers.end()) + { + if((*i) == conn) + { + _remoteUsers.erase(i); + i = _remoteUsers.begin(); + rcount++; + } + else i++; + } + + while(rcount) { + arts_debug("client disconnected: dropped one object reference"); + rcount--; + _release(); + } + /* warning: object may not exist any longer here */ +} + +void Object_skel::_referenceClean() +{ + if(_remoteSendCount > 0) + { + if(_remoteSendUpdated) + { + // this ensures that every client gets at least five + // seconds to connect + _remoteSendUpdated = false; + } + else + { + int rcount = _remoteSendCount; + + arts_debug("_referenceClean: found unused object marked by " + "_copyRemote => releasing"); + + while(rcount--) + { + _remoteSendCount--; + _release(); + } + } + /* warning: object may be gone here */ + } +} + +string Object_skel::_toString() +{ + return Dispatcher::the()->objectToString(_objectID); +} + +string Object_skel::_interfaceName() +{ + assert(0); // derived classes *must* override this + return ""; +} + +string Object_skel::_interfaceNameSkel() +{ + // derived classes *must* override this, but we return a sane value here + // anyway, because DynamicSkeleton depends on this + return "Arts::Object"; +} + +bool Object_skel::_isCompatibleWith(const std::string& interfacename) +{ + if (interfacename=="Arts::Object") return true; + return false; +} + +InterfaceDef Object_skel::_queryInterface(const string& name) +{ + return Dispatcher::the()->interfaceRepo().queryInterface(name); +} + +TypeDef Object_skel::_queryType(const string& name) +{ + return Dispatcher::the()->interfaceRepo().queryType(name); +} + +EnumDef Object_skel::_queryEnum(const string& name) +{ + return Dispatcher::the()->interfaceRepo().queryEnum(name); +} + +// Aggregation +std::string Object_skel::_addChild(Arts::Object child, const std::string& name) +{ + return _internalData->children.put(name,child); +} + +bool Object_skel::_removeChild(const std::string& name) +{ + return _internalData->children.remove(name); +} + +Arts::Object Object_skel::_getChild(const std::string& name) +{ + Arts::Object result; + if(_internalData->children.get(name,result)) + return result; + else + return Arts::Object::null(); +} + +std::vector<std::string> *Object_skel::_queryChildren() +{ + return _internalData->children.contents(); +} + +void Object_skel::_addMethod(DispatchFunction disp, void *obj, + const MethodDef& md) +{ + Arts::ObjectInternalData::MethodTableEntry me; + me.dispFunc.dispatcher = disp; + me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfNormal; + me.object = obj; + me.methodDef = md; + _internalData->methodTable.push_back(me); +} + +void Object_skel::_addMethod(OnewayDispatchFunction disp, void *obj, + const MethodDef& md) +{ + Arts::ObjectInternalData::MethodTableEntry me; + me.dispFunc.onewayDispatcher = disp; + me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway; + me.object = obj; + me.methodDef = md; + _internalData->methodTable.push_back(me); +} + +void Object_skel::_addMethod(DynamicDispatchFunction disp, void *obj, + const MethodDef& md) +{ + Arts::ObjectInternalData::MethodTableEntry me; + me.dispFunc.dynamicDispatcher = disp; + me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfDynamic; + me.object = obj; + me.methodDef = md; + _internalData->methodTable.push_back(me); +} + + +long Object_skel::_addCustomMessageHandler(OnewayDispatchFunction handler, + void *obj) +{ + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + Arts::ObjectInternalData::MethodTableEntry me; + me.dispFunc.onewayDispatcher = handler; + me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway; + me.object = obj; + me.methodDef.name = "_userdefined_customdatahandler"; + _internalData->methodTable.push_back(me); + return _internalData->methodTable.size()-1; +} + +void Object_skel::_dispatch(Buffer *request, Buffer *result,long methodID) +{ + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + + const ObjectInternalData::MethodTableEntry& me + = _internalData->methodTable[methodID]; + + if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfNormal) + me.dispFunc.dispatcher(me.object, request, result); + else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic) + me.dispFunc.dynamicDispatcher(me.object, methodID, request, result); + else + { + arts_assert(0); + } +} + +void Object_skel::_dispatch(Buffer *request,long methodID) +{ + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + const ObjectInternalData::MethodTableEntry& me + = _internalData->methodTable[methodID]; + + if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfOneway) + me.dispFunc.onewayDispatcher(me.object, request); + else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic) + me.dispFunc.dynamicDispatcher(me.object, methodID, request, 0); + else + { + arts_assert(0); + } +} + +long Object_skel::_lookupMethod(const MethodDef& md) +{ + long mcount = 0; + + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + + vector<Arts::ObjectInternalData::MethodTableEntry>::iterator i; + for(i=_internalData->methodTable.begin(); i != _internalData->methodTable.end(); i++) + { + MethodDef& mdm = i->methodDef; + if(mdm.name == md.name && mdm.type == md.type) + { + /* TODO: compare signature + vector<ParamDef *>::const_iterator j,k; + j = md.signature.begin(); + k = mdm.signature.begin(); + while(j != md.signature.end() && (*j) == (*k)) + { + j++; + k++; + } + + if(j == md.signature.end() && k == mdm.signature.end()) + */ + return mcount; + } + mcount++; + } + arts_warning("_lookupMethod %s %s failed this might be caused by " + "incompatible IDL files and is likely to result in crashes", + md.type.c_str(),md.name.c_str()); + return -1; +} + +const MethodDef& Object_skel::_dsGetMethodDef(long methodID) +{ + if(!_internalData->methodTableInit) + { + // take care that the object base methods are at the beginning + Object_skel::_buildMethodTable(); + _buildMethodTable(); + _internalData->methodTableInit = true; + } + return _internalData->methodTable[methodID].methodDef; +} + +// _lookupMethod +static void _dispatch_Arts_Object_00(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::MethodDef methodDef(*request); + result->writeLong(((Arts::Object_skel *)object)->_lookupMethod(methodDef)); +} + +// _interfaceName +static void _dispatch_Arts_Object_01(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + result->writeString(((Arts::Object_skel *)object)->_interfaceName()); +} + +// _queryInterface +static void _dispatch_Arts_Object_02(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::InterfaceDef _returnCode = ((Arts::Object_skel *)object)->_queryInterface(name); + _returnCode.writeType(*result); +} + +// _queryType +static void _dispatch_Arts_Object_03(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::TypeDef _returnCode = ((Arts::Object_skel *)object)->_queryType(name); + _returnCode.writeType(*result); +} + +// _queryEnum +static void _dispatch_Arts_Object_04(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::EnumDef _returnCode = ((Arts::Object_skel *)object)->_queryEnum(name); + _returnCode.writeType(*result); +} + +// _toString +static void _dispatch_Arts_Object_05(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + result->writeString(((Arts::Object_skel *)object)->_toString()); +} + +// _isCompatibleWith +static void _dispatch_Arts_Object_06(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string interfacename; + request->readString(interfacename); + result->writeBool(((Arts::Object_skel *)object)->_isCompatibleWith(interfacename)); +} + +// _copyRemote +static void _dispatch_Arts_Object_07(void *object, Arts::Buffer *, Arts::Buffer *) +{ + ((Arts::Object_skel *)object)->_copyRemote(); +} + +// _useRemote +static void _dispatch_Arts_Object_08(void *object, Arts::Buffer *, Arts::Buffer *) +{ + ((Arts::Object_skel *)object)->_useRemote(); +} + +// _releaseRemote +static void _dispatch_Arts_Object_09(void *object, Arts::Buffer *, Arts::Buffer *) +{ + ((Arts::Object_skel *)object)->_releaseRemote(); +} + +// _addChild +static void _dispatch_Arts_Object_10(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + Arts::Object_base* _temp_child; + readObject(*request,_temp_child); + Arts::Object child = Arts::Object::_from_base(_temp_child); + std::string name; + request->readString(name); + result->writeString(((Arts::Object_skel *)object)->_addChild(child,name)); +} + +// _removeChild +static void _dispatch_Arts_Object_11(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + result->writeBool(((Arts::Object_skel *)object)->_removeChild(name)); +} + +// _getChild +static void _dispatch_Arts_Object_12(void *object, Arts::Buffer *request, Arts::Buffer *result) +{ + std::string name; + request->readString(name); + Arts::Object returnCode = ((Arts::Object_skel *)object)->_getChild(name); + writeObject(*result,returnCode._base()); +} + +// _queryChildren +static void _dispatch_Arts_Object_13(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + std::vector<std::string> *_returnCode = ((Arts::Object_skel *)object)->_queryChildren(); + result->writeStringSeq(*_returnCode); + delete _returnCode; +} + +// _get__flowSystem +static void _dispatch_Arts_Object_14(void *object, Arts::Buffer *, Arts::Buffer *result) +{ + Arts::FlowSystem returnCode = ((Arts::Object_skel *)object)->_flowSystem(); + writeObject(*result,returnCode._base()); +} + +void Arts::Object_skel::_buildMethodTable() +{ + Arts::Buffer m; + m.fromString( + "MethodTable:0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e6700" + "000000020000000100000010417274733a3a4d6574686f64446566000000000a6d" + "6574686f644465660000000000000000000000000f5f696e746572666163654e61" + "6d650000000007737472696e6700000000020000000000000000000000105f7175" + "657279496e746572666163650000000013417274733a3a496e7465726661636544" + "656600000000020000000100000007737472696e6700000000056e616d65000000" + "0000000000000000000b5f717565727954797065000000000e417274733a3a5479" + "706544656600000000020000000100000007737472696e6700000000056e616d65" + "0000000000000000000000000b5f7175657279456e756d000000000e417274733a" + "3a456e756d44656600000000020000000100000007737472696e6700000000056e" + "616d650000000000000000000000000a5f746f537472696e670000000007737472" + "696e6700000000020000000000000000000000125f6973436f6d70617469626c65" + "576974680000000008626f6f6c65616e0000000002000000010000000773747269" + "6e67000000000e696e746572666163656e616d650000000000000000000000000c" + "5f636f707952656d6f74650000000005766f696400000000020000000000000000" + "0000000b5f75736552656d6f74650000000005766f696400000000020000000000" + "0000000000000f5f72656c6561736552656d6f74650000000005766f6964000000" + "000200000000000000000000000a5f6164644368696c640000000007737472696e" + "67000000000200000002000000076f626a65637400000000066368696c64000000" + "000000000007737472696e6700000000056e616d65000000000000000000000000" + "0d5f72656d6f76654368696c640000000008626f6f6c65616e0000000002000000" + "0100000007737472696e6700000000056e616d650000000000000000000000000a" + "5f6765744368696c6400000000076f626a65637400000000020000000100000007" + "737472696e6700000000056e616d650000000000000000000000000f5f71756572" + "794368696c6472656e00000000082a737472696e67000000000200000000000000" + "00000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a46" + "6c6f7753797374656d00000000020000000000000000", + "MethodTable" + ); + _addMethod(_dispatch_Arts_Object_00,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_01,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_02,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_03,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_04,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_05,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_06,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_07,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_08,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_09,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_10,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_11,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_12,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_13,this,Arts::MethodDef(m)); + _addMethod(_dispatch_Arts_Object_14,this,Arts::MethodDef(m)); +} + +/* + * Stuff for object stubs + */ + +Object_stub::Object_stub() +{ + assert(0); // never use this constructor, as it doesn't assign an object ID +} + +Object_stub::Object_stub(Connection *connection, long objectID) +{ + _connection = connection; + _connection->_copy(); + _objectID = objectID; + _lookupCacheRandom = rand(); + + if(_connection == Dispatcher::the()->loopbackConnection()) + _internalData->stubForLocalObject = true; + + char ioid[128]; + sprintf(ioid,"STUB:%ld:%p",_objectID,(void *)connection); + _internalObjectID = ioid; +} + +Object_stub::~Object_stub() +{ + /* + * invalidate method lookup cache entries of this object, as it might + * happen, that another Object_stub is created just at the same position + */ + if(_lookupMethodCache) + { + for(long p=0;p<_lookupMethodCacheSize;p++) + { + if(_lookupMethodCache[p].obj == this) + _lookupMethodCache[p].obj = NULL; + } + } + _connection->_release(); +} + +bool Object_stub::_error() +{ + /* + * servers are trustworthy - they don't do things wrong (e.g. send + * wrong buffers or things like that) - however, if the connection is + * lost, this indicates that something went terrible wrong (probably + * the remote server crashed, or maybe the network is dead), and you + * can't rely on results of invocations any longer + */ + return _connection->broken(); +} + +void Object_stub::_release() +{ + arts_return_if_fail(_refCnt > 0); + + _refCnt--; + if(_refCnt == 0) + { + _releaseRemote(); + _destroy(); + } +} + +Object_base *Object_base::_create(const std::string& subClass) +{ + Object_skel *skel = ObjectManager::the()->create(subClass); + assert(skel); + return skel; +} + +Object_base *Object_base::_fromString(const string& objectref) +{ + Object_base *result = 0; + ObjectReference r; + + if(Dispatcher::the()->stringToObjectReference(r,objectref)) + { + result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object"); + if(!result) + { + Connection *conn = Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Object_stub(conn,r.objectID); + result->_useRemote(); + } + } + } + return result; +} + +Object_base *Object_base::_fromReference(ObjectReference r, bool needcopy) +{ + Object_base *result; + result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object"); + if(result) + { + if(!needcopy) + result->_cancelCopyRemote(); + } + else + { + Connection *conn = Dispatcher::the()->connectObjectRemote(r); + if(conn) + { + result = new Object_stub(conn,r.objectID); + if(needcopy) result->_copyRemote(); + result->_useRemote(); + } + } + return result; +} + +string Object_stub::_interfaceName() +{ + long requestID; + Buffer *request, *result; + request = Dispatcher::the()->createRequest(requestID,_objectID,1); + // methodID = 1 => _interfaceName (always) + request->patchLength(); + _connection->qSendBuffer(request); + + result = Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return ""; // error + string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +InterfaceDef Object_stub::_queryInterface(const string& name) +{ + long requestID; + Buffer *request, *result; + request = Dispatcher::the()->createRequest(requestID,_objectID,2); + // methodID = 2 => _queryInterface (always) + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return InterfaceDef(); // error + InterfaceDef _returnCode(*result); + delete result; + return _returnCode; +} + +TypeDef Object_stub::_queryType(const string& name) +{ + long requestID; + Buffer *request, *result; + request = Dispatcher::the()->createRequest(requestID,_objectID,3); + // methodID = 3 => _queryType (always) + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return TypeDef(); // error + TypeDef _returnCode(*result); + delete result; + return _returnCode; +} + +EnumDef Object_stub::_queryEnum(const string& name) +{ + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,4); + // methodID = 4 => _queryEnum (always) + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return EnumDef(); // error occurred + EnumDef _returnCode(*result); + delete result; + return _returnCode; +} + +long Object_stub::_lookupMethod(const MethodDef& methodDef) +{ + long requestID; + Buffer *request, *result; + request = Dispatcher::the()->createRequest(requestID,_objectID,0); + // methodID = 0 => _lookupMethod (always) + methodDef.writeType(*request); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return 0; // error + long returnCode = result->readLong(); + delete result; + return returnCode; +} + +Object_stub::methodCacheEntry *Object_stub::_lookupMethodCache = 0; + +long Object_stub::_lookupMethodFast(const char *method) +{ + unsigned long c1 = (unsigned long)this; + unsigned long c2 = (unsigned long)method; + unsigned long pos = (c1^c2^_lookupCacheRandom)%_lookupMethodCacheSize; + /* FIXME this hashing method sucks. at a bare minimum, we're using only every 4th bin */ + + if(!_lookupMethodCache) + _lookupMethodCache = new methodCacheEntry[_lookupMethodCacheSize]; + + if(_lookupMethodCache[pos].obj == this && _lookupMethodCache[pos].method == method) + return _lookupMethodCache[pos].ID; + + Buffer _methodBuffer; + _methodBuffer.fromString(method,"method"); + long methodID = _lookupMethod(MethodDef(_methodBuffer)); + //cout << "methodID = " << methodID << endl; + + _lookupMethodCache[pos].obj = this; + _lookupMethodCache[pos].method = method; + _lookupMethodCache[pos].ID = methodID; + return methodID; +} + +// other (normal) methods without fixed location + +std::string Arts::Object_stub::_toString() +{ + long methodID = _lookupMethodFast("method:0000000a5f746f537472696e670000000007737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return""; // error occurred + std::string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +bool Arts::Object_stub::_isCompatibleWith(const std::string& interfacename) +{ + long methodID = _lookupMethodFast("method:000000125f6973436f6d70617469626c65576974680000000008626f6f6c65616e00000000020000000100000007737472696e67000000000e696e746572666163656e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(interfacename); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return false; // error occurred + bool returnCode = result->readBool(); + delete result; + return returnCode; +} + +void Arts::Object_stub::_copyRemote() +{ + long methodID = _lookupMethodFast("method:0000000c5f636f707952656d6f74650000000005766f696400000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +void Arts::Object_stub::_useRemote() +{ + long methodID = _lookupMethodFast("method:0000000b5f75736552656d6f74650000000005766f696400000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +void Arts::Object_stub::_releaseRemote() +{ + long methodID = _lookupMethodFast("method:0000000f5f72656c6561736552656d6f74650000000005766f696400000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(result) delete result; +} + +std::string Arts::Object_stub::_addChild(Arts::Object child, const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000a5f6164644368696c640000000007737472696e67000000000200000002000000076f626a65637400000000066368696c64000000000000000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + writeObject(*request,child._base()); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return""; // error occurred + std::string returnCode; + result->readString(returnCode); + delete result; + return returnCode; +} + +bool Arts::Object_stub::_removeChild(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000d5f72656d6f76654368696c640000000008626f6f6c65616e00000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if(!result) return false; // error occurred + bool returnCode = result->readBool(); + delete result; + return returnCode; +} + +Arts::Object Arts::Object_stub::_getChild(const std::string& name) +{ + long methodID = _lookupMethodFast("method:0000000a5f6765744368696c6400000000076f626a65637400000000020000000100000007737472696e6700000000056e616d65000000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->writeString(name); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if (!result) return Arts::Object::null(); + Arts::Object_base* returnCode; + readObject(*result,returnCode); + delete result; + return Arts::Object::_from_base(returnCode); +} + +std::vector<std::string> * Arts::Object_stub::_queryChildren() +{ + long methodID = _lookupMethodFast("method:0000000f5f71756572794368696c6472656e00000000082a737472696e6700000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + std::vector<std::string> *_returnCode = new std::vector<std::string>; + if(!result) return _returnCode; // error occurred + result->readStringSeq(*_returnCode); + delete result; + return _returnCode; +} + +Arts::FlowSystem Arts::Object_stub::_flowSystem() +{ + long methodID = _lookupMethodFast("method:000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a466c6f7753797374656d00000000020000000000000000"); + long requestID; + Arts::Buffer *request, *result; + request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID); + request->patchLength(); + _connection->qSendBuffer(request); + + result = Arts::Dispatcher::the()->waitForResult(requestID,_connection); + if (!result) return Arts::FlowSystem::null(); + Arts::FlowSystem_base* returnCode; + readObject(*result,returnCode); + delete result; + return Arts::FlowSystem::_from_base(returnCode); +} + +/* + * custom messaging + */ + +Buffer *Object_stub::_allocCustomMessage(long handlerID) +{ + return Dispatcher::the()->createOnewayRequest(_objectID,handlerID); +} + +void Object_stub::_sendCustomMessage(Buffer *buffer) +{ + buffer->patchLength(); + _connection->qSendBuffer(buffer); +} + +unsigned long Object_base::_IID = MCOPUtils::makeIID("Object"); + +/* + * global cleanup + */ + +void Object_stub::_cleanupMethodCache() +{ + if(_lookupMethodCache) + { + delete[] _lookupMethodCache; + _lookupMethodCache = 0; + } +} + +namespace Arts { + static class Object_stub_Shutdown : public StartupClass { + public: + void startup() { } + void shutdown() { Object_stub::_cleanupMethodCache(); } + } The_Object_stub_Shutdown; +} diff --git a/mcop/object.h b/mcop/object.h new file mode 100644 index 0000000..efe8c59 --- /dev/null +++ b/mcop/object.h @@ -0,0 +1,390 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef OBJECT_H +#define OBJECT_H + +#include "buffer.h" +#include "connection.h" +#include "notification.h" + +#include <assert.h> +#include <map> +#include <list> + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): Object_base, Object_skel, Object_stub + * + * All of them have to be kept binary compatible carefully, due to interaction + * with generated code. There are d ptrs in _skel and _stub, NOT TO BE USED + * NORMALLY. Normally, do use _internalData instead, as this is much faster + * than creating two d objects per MCOP implementation/stub. Handle with care. + */ + + +namespace Arts { +/* custom dispatching functions */ + +typedef void (*DispatchFunction)(void *object, Buffer *request, Buffer *result); +typedef void (*OnewayDispatchFunction)(void *object, Buffer *request); +typedef void (*DynamicDispatchFunction)(void *object, long methodID, Buffer *request, Buffer *result); + +class ScheduleNode; +class Object_skel; +class Object_stub; +class FlowSystem; +class MethodDef; +class ObjectReference; +class WeakReferenceBase; +class Object; +class ObjectManager; +class DynamicSkeletonData; +class DynamicSkeletonBase; + +class ARTS_EXPORT Object_base : public NotificationClient { +private: + friend class DynamicRequest; + friend class ObjectManager; + bool _deleteOk; // ensure that "delete" is not called manually + +protected: + /** + * ObjectInternalData contains private data structures for + * - Object_base + * - Object_stub + * - Object_skel + * + * This is an optimization over adding each of them private data pointers, + * which would lead to some more bloat. + */ + class ObjectInternalData *_internalData; + + struct ObjectStreamInfo; + + Object_base(); + virtual ~Object_base(); + + /* + * internal management for streams + */ + ScheduleNode *_scheduleNode; + std::list<ObjectStreamInfo *> _streamList; + + virtual Object_skel *_skel(); + virtual Object_stub *_stub(); + + enum ObjectLocation { objectIsLocal, objectIsRemote }; + virtual ObjectLocation _location() const = 0; + + long _objectID; + Connection *_connection; + std::string _internalObjectID; // two objects are "_isEqual" when these match + long _nextNotifyID; + long _refCnt; // reference count + static long _staticObjectCount; + + void _destroy(); // use this instead of delete (takes care of + // properly removing flow system node) +public: + static unsigned long _IID; // interface ID + /** + * custom messaging: these can be used to send a custom data to other + * objects. Warning: these are *not* usable for local objects. You may + * only use these functions if you know that you are talking to a remote + * object. Use _allocCustomMessage to allocate a message. Put the data + * you want to send in the Buffer. After that, call _sendCustomMessage. + * Don't free the buffer - this will happen automatically. + */ + + virtual Buffer *_allocCustomMessage(long handlerID); + virtual void _sendCustomMessage(Buffer *data); + + /* + * generic capabilities, which allow find out what you can do with an + * object even if you don't know it's interface + */ + virtual long _lookupMethod(const Arts::MethodDef &) = 0; + virtual std::string _interfaceName() = 0; + virtual class InterfaceDef _queryInterface(const std::string& name) = 0; + virtual class TypeDef _queryType(const std::string& name) = 0; + virtual class EnumDef _queryEnum(const std::string& name) = 0; + virtual std::string _toString() = 0; + + /* + * stuff for streaming (put in a seperate interface?) + */ + virtual void calculateBlock(unsigned long cycles); + ScheduleNode *_node(); + virtual FlowSystem _flowSystem() = 0; + + /* + * reference counting + */ + virtual void _release() = 0; + virtual void _copyRemote() = 0; + virtual void _useRemote() = 0; + virtual void _releaseRemote() = 0; + + // BC issue: added _cancelCopyRemote here to avoid virtual function + void _cancelCopyRemote(); + + void _addWeakReference(WeakReferenceBase *reference); + void _removeWeakReference(WeakReferenceBase *reference); + + inline Object_base *_copy() { + assert(_refCnt > 0); + _refCnt++; + return this; + } + + // Default I/O info + virtual std::vector<std::string> _defaultPortsIn() const; + virtual std::vector<std::string> _defaultPortsOut() const; + + // cast operation + virtual void *_cast(unsigned long iid); + void *_cast(const std::string& interface); + + // Run-time type compatibility check + virtual bool _isCompatibleWith(const std::string& interfacename) = 0; + + // Aggregation + virtual std::string _addChild(Arts::Object child, const std::string& name) = 0; + virtual bool _removeChild(const std::string& name) = 0; + virtual Arts::Object _getChild(const std::string& name) = 0; + virtual std::vector<std::string> * _queryChildren() = 0; + + /* + * when this is true, a fatal communication error has occurred (of course + * only possible for remote objects) - maybe your returncode is invalid, + * maybe your last invocation didn't succeed... + */ + virtual bool _error(); + + inline static long _objectCount() { return _staticObjectCount; } + inline long _mkNotifyID() { return _nextNotifyID++; } + + // object creation + static Object_base *_create(const std::string& subClass = "Object"); + + // comparison + bool _isEqual(Object_base *object) const; + + // static converter (from reference) + static Object_base *_fromString(const std::string& objectref); + static Object_base *_fromReference(class ObjectReference ref, bool needcopy); +}; + +/* + * Dispatching + */ + +class Buffer; +class MethodDef; + + +class Object_skel_private; +class AnyConstRef; +class AttributeDef; + +class ARTS_EXPORT Object_skel : virtual public Object_base { +private: + friend class Object_base; + friend class DynamicSkeletonData; + friend class DynamicSkeletonBase; + + Object_skel_private *_d_skel;// do not use until there is a very big problem + + // reference counting - remote object watching + + long _remoteSendCount; // don't kill objects just sent to other server + bool _remoteSendUpdated; // timeout if they don't want the object + std::list<class Connection *> _remoteUsers; // who is using it? + +protected: + void _addMethod(DispatchFunction disp, void *object, const MethodDef& md); + void _addMethod(OnewayDispatchFunction disp, void *object, + const MethodDef& md); + void _addMethod(DynamicDispatchFunction disp, void *object, + const MethodDef& md); + void _initStream(const std::string& name, void *ptr, long flags); + + /** stuff relative to attribute notifications **/ + bool _initAttribute(const Arts::AttributeDef& attribute); + static bool _QueryInitStreamFunc(Object_skel *skel,const std::string& name); + bool _generateSlots(const std::string& name, const std::string& interface); + + /** for DynamicSkeleton: **/ + const MethodDef& _dsGetMethodDef(long methodID); + +protected: + void _defaultNotify(const Notification& notification); + void notify(const Notification& notification); + void _emit_changed(const char *stream, const AnyConstRef& value); + + /** + * custom messaging: this is used to install a custom data handler that + * can be used to receive non-standard messages + */ + long _addCustomMessageHandler(OnewayDispatchFunction handler, void *object); + + Object_skel *_skel(); + ObjectLocation _location() const; + +public: + Object_skel(); + virtual ~Object_skel(); + + // reference counting connection drop + void _disconnectRemote(class Connection *connection); + void _referenceClean(); + + // synchronous & asynchronous dispatching + void _dispatch(Buffer *request, Buffer *result,long methodID); + void _dispatch(Buffer *request, long methodID); + long _lookupMethod(const MethodDef &); + + /* + * standard interface for every object skeleton + */ + static std::string _interfaceNameSkel(); + virtual void _buildMethodTable(); + + /* + * reference counting + */ + virtual void _release(); + virtual void _copyRemote(); + virtual void _useRemote(); + virtual void _releaseRemote(); + + /* + * streaming + */ + FlowSystem _flowSystem(); + + /* + * to inspect the (remote) object interface + */ + virtual std::string _interfaceName(); + InterfaceDef _queryInterface(const std::string& name); + TypeDef _queryType(const std::string& name); + EnumDef _queryEnum(const std::string& name); + virtual std::string _toString(); + + // Run-time type compatibility check + bool _isCompatibleWith(const std::string& interfacename); + + // Aggregation + std::string _addChild(Arts::Object child, const std::string& name); + bool _removeChild(const std::string& name); + Arts::Object _getChild(const std::string& name); + std::vector<std::string> * _queryChildren(); +}; + +class Object_stub_private; + +class ARTS_EXPORT Object_stub : virtual public Object_base { +private: + friend class Object_base; + + Object_stub_private *_d_stub;// do not use until there is a very big problem + +protected: + long _lookupCacheRandom; + + Object_stub(); + Object_stub(Connection *connection, long objectID); + virtual ~Object_stub(); + + virtual Object_stub *_stub(); + ObjectLocation _location() const; + + enum { _lookupMethodCacheSize = 337 }; + static struct methodCacheEntry { + methodCacheEntry() : obj(NULL),method(NULL),ID(0) {} ; + Object_stub *obj; + const char *method; + long ID; + } *_lookupMethodCache; + + long _lookupMethodFast(const char *method); + long _lookupMethod(const MethodDef &); + +public: + /* + * custom messaging + */ + + Buffer *_allocCustomMessage(long handlerID); + void _sendCustomMessage(Buffer *data); + + /* + * to inspect the (remote) object interface + */ + std::string _interfaceName(); + InterfaceDef _queryInterface(const std::string& name); + TypeDef _queryType(const std::string& name); + EnumDef _queryEnum(const std::string& name); + std::string _toString(); + + /* + * streaming + */ + FlowSystem _flowSystem(); + + /* + * reference counting + */ + virtual void _release(); + virtual void _copyRemote(); + virtual void _useRemote(); + virtual void _releaseRemote(); + + // Run-time type compatibility check + bool _isCompatibleWith(const std::string& interfacename); + + // Aggregation + std::string _addChild(Arts::Object child, const std::string& name); + bool _removeChild(const std::string& name); + Arts::Object _getChild(const std::string& name); + std::vector<std::string> * _queryChildren(); + + /* + * communication error? this is true when your connection to the remote + * object is lost (e.g. when the remote server crashed) - your return + * values are then undefined, so check this before relying too much + * on some invocation + */ + + bool _error(); + + /* + * global cleanup + */ + static void _cleanupMethodCache(); +}; + +} +#endif diff --git a/mcop/objectmanager.cc b/mcop/objectmanager.cc new file mode 100644 index 0000000..0617ea4 --- /dev/null +++ b/mcop/objectmanager.cc @@ -0,0 +1,289 @@ + /* + + Copyright (C) 2000,2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "mcoputils.h" +#include "mcopconfig.h" +#include "objectmanager.h" +#include "dispatcher.h" +#include "extensionloader.h" +#include "debug.h" +#include <stdio.h> +#include <unistd.h> +#include <iostream> + +using namespace std; +using namespace Arts; + +class Arts::ObjectManagerPrivate { +public: + struct LoaderData { + LoaderData() : init(false) { } + bool init; + Loader loader; + }; + + list<ExtensionLoader *> extensions; + map<string, long> capabilities; + map<string, LoaderData> loaders; +}; + +Object_skel *ObjectManager::create(const string& name) +{ + list<Factory *>::iterator i; + + /* first try: look through all factories we have */ + + for(i = factories.begin();i != factories.end(); i++) + { + Factory *f = *i; + if(f->interfaceName() == name ) return f->createInstance(); + } + + /* second try: look if there is a suitable extension we could load */ + + TraderQuery query; + query.supports("InterfaceName", name); + vector<TraderOffer> *offers = query.query(); + + vector<TraderOffer>::iterator oi; + for(oi = offers->begin(); oi != offers->end(); oi++) + { + /* + * check whether we provide everything that this + * implementation requires to run + */ + bool requirementsOk = true; + vector<string> *requires = oi->getProperty("Requires"); + + vector<string>::iterator ri; + for(ri = requires->begin(); ri != requires->end(); ri++) + { + if(d->capabilities[*ri] <= 0) + requirementsOk = false; + } + delete requires; + + vector<string> *language = oi->getProperty("Language"); + vector<string> *libs = oi->getProperty("Library"); + + if(language->size() == 0 && libs->size() == 1) + { + arts_warning("ObjectManager: %s - assuming 'Language=C++' because library given",name.c_str()); + language->push_back("C++"); + } + if(language->size() != 1) + { + arts_warning("ObjectManager: %s - Language missing", name.c_str()); + requirementsOk = false; + } + if(requirementsOk && language->front() == "C++" && libs->empty()) + { + arts_warning("ObjectManager: %s - Library missing", name.c_str()); + requirementsOk = false; + } + + /* loading C++ components */ + if(requirementsOk && language->front() == "C++") + { + string library = libs->front(); + + ExtensionLoader *e = new ExtensionLoader(library); + if(e->success()) + { + d->extensions.push_back(e); + for(i = factories.begin();i != factories.end(); i++) + { + Factory *f = *i; + if(f->interfaceName() == name) + { + delete language; + delete libs; + delete offers; + return f->createInstance(); + } + } + } + else + { + arts_warning("MCOP ObjectManager:" + " Could not load extension %s.", library.c_str()); + delete e; + } + } + delete libs; + + /* other languages/binary formats */ + if(requirementsOk) + { + string lang = language->front(); + ObjectManagerPrivate::LoaderData &ld = d->loaders[lang]; + + if(!ld.init) + { + TraderQuery query; + query.supports("Interface", "Arts::Loader"); + query.supports("LoadLanguage", lang); + + vector<TraderOffer> *loffers = query.query(); + + // TODO: error checking for SubClass + if(loffers->size() > 0) + { + ld.loader = SubClass(loffers->front().interfaceName()); + } + else + { + ld.loader = Arts::Loader::null(); + } + + delete loffers; + } + ld.init = true; + + if(!ld.loader.isNull()) + { + /* + * ### change when breaking BC: + * it's bad that ObjectManager has to return _skel()s, but + * well, can't change it now + */ + + Object obj = ld.loader.loadObject(*oi); + delete language; + delete offers; + return obj._base()->_copy()->_skel(); + } + } + + delete language; + } + + arts_warning("MCOP ObjectManager: can't find implementation for %s.", + name.c_str()); + + delete offers; + return 0; +} + +void ObjectManager::registerFactory(Factory *factory) +{ + factories.push_back(factory); +} + +void ObjectManager::removeFactory(Factory *factory) +{ + list<Factory *>::iterator i; + + i = factories.begin(); + while(i != factories.end()) + { + if(*i == factory) { + factories.erase(i); + i = factories.begin(); + } + else i++; + } +} + +ObjectManager *ObjectManager::_instance = 0; + +ObjectManager::ObjectManager() +{ + assert(!_instance); + _instance = this; + d = new ObjectManagerPrivate; +} + +ObjectManager::~ObjectManager() +{ + // they should be unloaded before this object can be deleted + assert(d->extensions.empty()); + delete d; + assert(_instance); + _instance = 0; +} + +ObjectManager *ObjectManager::the() +{ + assert(_instance); + return _instance; +} + +void ObjectManager::shutdownExtensions() +{ + // give up references to the loaders + d->loaders.clear(); + + // shuts down all dynamically loaded extensions + list<ExtensionLoader *>::iterator i; + for(i=d->extensions.begin(); i != d->extensions.end(); i++) + (*i)->shutdown(); +} + +void ObjectManager::removeExtensions() +{ + // unloads all dynamically loaded extensions + list<ExtensionLoader *>::iterator i; + for(i=d->extensions.begin(); i != d->extensions.end(); i++) + delete *i; + + d->extensions.clear(); +} + +/* + * global references + */ + +bool ObjectManager::addGlobalReference(Object object, const string& name) +{ + bool result; + + result = Dispatcher::the()->globalComm().put(name,object.toString()); + if(result) + referenceNames.push_back(name); + + return result; +} + +string ObjectManager::getGlobalReference(const string& name) +{ + return Dispatcher::the()->globalComm().get(name); +} + +void ObjectManager::removeGlobalReferences() +{ + list<string>::iterator i; + + for(i=referenceNames.begin(); i != referenceNames.end();i++) + Dispatcher::the()->globalComm().erase(*i); +} + +void ObjectManager::provideCapability(const string& name) +{ + d->capabilities[name]++; +} + +void ObjectManager::removeCapability(const string& name) +{ + d->capabilities[name]--; +} diff --git a/mcop/objectmanager.h b/mcop/objectmanager.h new file mode 100644 index 0000000..47a5c11 --- /dev/null +++ b/mcop/objectmanager.h @@ -0,0 +1,75 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef OBJECTMANAGER_H +#define OBJECTMANAGER_H + +#include "object.h" +#include "factory.h" +#include <list> + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): ObjectManager + * + * Keep binary compatible (since accessible via ::the()), use d ptr when + * changing it. + */ + +namespace Arts { + +class Object; +class ObjectManagerPrivate; + +class ARTS_EXPORT ObjectManager { +private: + ObjectManagerPrivate *d; + +protected: + static ObjectManager *_instance; + std::list<Factory *> factories; + std::list<std::string> referenceNames; + +public: + ObjectManager(); + ~ObjectManager(); + + static ObjectManager *the(); + Object_skel *create(const std::string& name); + + bool addGlobalReference(Object object, const std::string& name); + std::string getGlobalReference(const std::string& name); + void removeGlobalReferences(); + void removeExtensions(); + void shutdownExtensions(); + + void registerFactory(Factory *factory); + void removeFactory(Factory *factory); + + void provideCapability(const std::string& capability); + void removeCapability(const std::string& capability); +}; + +} + +#endif /* OBJECTMANAGER_H */ diff --git a/mcop/pool.h b/mcop/pool.h new file mode 100644 index 0000000..199f422 --- /dev/null +++ b/mcop/pool.h @@ -0,0 +1,89 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_POOL_H +#define ARTS_POOL_H + + +/* + * BC - Status (2002-03-08): Pool<type> + * + * Needs to be kept binary compatible by NOT TOUCHING. When you want something + * else, write a fresh one (used as part of Arts::Dispatcher, thus changing + * this breaks Arts::Dispatcher binary compatibility). + */ + + +/** + * A pool object of the type T keeps a pool of T* pointers, that are numbered. + * + * You allocate and release slots, and store T*'s in there. It should take + * about no time to find a new free slot to store the T object into and to + * release a slot to be reused. + * + * The pool object internally keeps track which slots are used. + */ +#include <stack> +#include <vector> +#include <list> + +namespace Arts { + +template <class T> +class Pool { + std::stack<unsigned long> freeIDs; + std::vector<T *> storage; +public: + inline T*& operator[](unsigned long n) { return storage[n]; } + inline void releaseSlot(unsigned long n) { + freeIDs.push(n); + storage[n] = 0; + } + unsigned long allocSlot() { + unsigned long slot; + if(freeIDs.empty()) + { + unsigned long n; + for(n=0;n<32;n++) { + freeIDs.push(storage.size()); + storage.push_back(0); + } + } + slot = freeIDs.top(); + freeIDs.pop(); + return slot; + } + std::list<T *> enumerate() { + std::list<T *> items; + //std::vector<T *>::iterator i; + int n,max = storage.size(); + + for(n=0; n < max; n++) + if(storage[n]) items.push_back(storage[n]); + + return items; + } + unsigned long max() { return storage.size(); } +}; + +} +#endif /* POOL_H */ diff --git a/mcop/reference.cc b/mcop/reference.cc new file mode 100644 index 0000000..3f214bf --- /dev/null +++ b/mcop/reference.cc @@ -0,0 +1,32 @@ +/* + Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr + Stefan Westerfeld, stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#include "common.h" + +using namespace Arts; + +// For technical reasons, this is here too: FlowSystem isn't declared when +// the wrapper is already needed, so we can't make this function inline, +// unfortunately... +FlowSystem Object::_flowSystem() const +{ + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_flowSystem(); +} diff --git a/mcop/reference.h b/mcop/reference.h new file mode 100644 index 0000000..ae59df6 --- /dev/null +++ b/mcop/reference.h @@ -0,0 +1,349 @@ +/* + Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr + Stefan Westerfeld, stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * BC - Status (2002-03-08): Reference, SubClass, Object, DynamicCast. + * + * Part of the public API. Must be kept binary compatible by NOT TOUCHING + * AT ALL. Interaction with generated and written code. + */ + + +#ifndef MCOP_REFERENCE_H +#define MCOP_REFERENCE_H + +#include "common.h" +#include <string> +#include <vector> + +#include "arts_export.h" + +namespace Arts { + +// Acts as a string or ObjectReference, but enables a different constructor +class ARTS_EXPORT Reference { +private: + ObjectReference myref; + std::string mys; + bool strMode; +public: + + inline explicit Reference(const ObjectReference& ref) { + myref=ref; + strMode=false; + } + + inline explicit Reference(const std::string& s) { + mys=s; + strMode=true; + } + + inline explicit Reference(const char* c) { + mys=c; + strMode=true; + } + inline Reference& operator=(const std::string& s) { + mys=s; + strMode=true; + return *this; + } + inline Reference& operator=(const char*c) { + mys=c; + strMode=true; + return *this; + } + inline bool isString() const {return strMode;} +// inline operator const std::string() const {return mys;} + inline const std::string& string() const {return mys;} +// inline operator const ObjectReference() const {return myref;} + inline const ObjectReference& reference() const {return myref;} +}; + +// Acts as a string, but enables a different constructor +class ARTS_EXPORT SubClass { +private: + std::string mys; +public: + + inline explicit SubClass(const std::string& s) : mys(s) {} + inline explicit SubClass(const char* c) : mys(c) {} + inline SubClass& operator=(const std::string& s) {mys=s; return *this;} + inline SubClass& operator=(const char*c) {mys=c; return *this;} +// inline operator const std::string() const {return mys;} + inline const std::string& string() const {return mys;} +}; + + +class ScheduleNode; +class FlowSystem; + +// Object has _no_ virtual, and must not have. That way, all the +// wrappers can be passed as argument or return type, and there is also +// no virtual table bloat. +// Moreover, the virtual mechanism still works correctly thanks to the +// _pool->base redirection. +class ARTS_EXPORT Object { +protected: + // Pool of common variables for a bunch a wrappers + class Pool { + friend class Object; + Object_base* (*creator)(); + bool created; + int count; + public: + Object_base* base; + inline Pool(Object_base* b) + : creator(0), created(true), count(1), base(b) {} + inline Pool(Object_base* (*cor)()) + : creator(cor), created(false), count(1), base(0) {} + inline void Inc() {count++;} + inline void Dec() { + if (--count==0) { + if(base) base->_release(); + delete this; + } + } + inline void checkcreate() { + if (!created) {base = creator(); created=true;} + } + } *_pool; + + inline Object(Object_base* (*cor)()) { + _pool = new Pool(cor); + } + inline Object(Pool* p) : _pool(p) { + _pool->Inc(); + } + inline Object(Pool& p) : _pool(&p) { + _pool->Inc(); + } + inline Object(Object_base* b) { + _pool = new Pool(b); + } +public: + typedef Object_base _base_class; + + // Dynamic cast constructor of inherited classes needs to access the _pool + // of a generic object if casting successful. But it could not without this + inline Pool* _get_pool() const {return _pool;} + + inline ~Object() { + _pool->Dec(); + } + + // Those constructors are public, since we don't need an actual creator. + // They enable generic object creation (like from a subclass defined at + // run-time!) + inline Object(const SubClass& s) { + _pool = new Pool(Object_base::_create(s.string())); + } + inline Object(const Reference &r) { + _pool = new Pool(r.isString()?(Object_base::_fromString(r.string())):(Object_base::_fromReference(r.reference(),true))); + } + inline Object(const Object& target) : _pool(target._pool) { + _pool->Inc(); + } + inline Object() { // creates a null object + _pool = new Pool((Object_base*)0); + } + inline Object& operator=(const Object& target) { + if (_pool == target._pool) return *this; + _pool->Dec(); + _pool = target._pool; + _pool->Inc(); + return *this; + } + // No problem for the creator, this class has protected constructors. + // So creator should give back an actual implementation + inline Object_base* _base() const { + _pool->checkcreate(); + return _pool->base; + } + + // null, error? + inline bool isNull() const { + _pool->checkcreate(); + return !(_pool->base); + } + inline bool error() const { + _pool->checkcreate(); + return _pool->base && _pool->base->_error(); + } + + // Comparision + inline bool _isEqual(const Object& other) const { + if(isNull() != other.isNull()) return false; + + // we can assume that things are created here, as we've + // called isNull of both wrappers once + if(!isNull()) + return _pool->base->_isEqual(other._pool->base); + + // both null references + return true; + } + + +// Object_base wrappers + + // Custom messaging - see Object_base for comments + inline Buffer *_allocCustomMessage(long handlerID) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_allocCustomMessage(handlerID); + } + + inline void _sendCustomMessage(Buffer *data) const { + _pool->checkcreate(); + assert(_pool->base); + _pool->base->_sendCustomMessage(data); + } + + // generic capabilities, which allow find out what you can do with an + // object even if you don't know it's interface + inline long _lookupMethod(const MethodDef& methodDef) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_lookupMethod(methodDef); + } + inline std::string _interfaceName() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_interfaceName(); + } + inline InterfaceDef _queryInterface(const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_queryInterface(name); + } + inline TypeDef _queryType(const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_queryType(name); + } + inline EnumDef _queryEnum(const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_queryEnum(name); + } + // Stringification + inline std::string _toString() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_toString(); + } + inline std::string toString() const {return _toString();} + + // stuff for streaming (put in a seperate interface?) + inline void calculateBlock(unsigned long cycles) const { + _pool->checkcreate(); + assert(_pool->base); + _pool->base->calculateBlock(cycles); + } + // Node info + inline ScheduleNode *_node() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_node(); + } + + // Ah! Flowsystem is not defined yet, so cannot be returned inline. + FlowSystem _flowSystem() const; + + inline void _copyRemote() const { + _pool->checkcreate(); + assert(_pool->base); + _pool->base->_copyRemote(); + } + inline void _useRemote() const { + _pool->checkcreate(); + assert(_pool->base); + _pool->base->_useRemote(); + } + inline void _releaseRemote() const { + _pool->checkcreate(); + assert(_pool->base); + _pool->base->_releaseRemote(); + } + + // Default I/O info + inline std::vector<std::string> _defaultPortsIn() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_defaultPortsIn(); + } + inline std::vector<std::string> _defaultPortsOut() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_defaultPortsOut(); + } + + // aggregation + inline std::string _addChild(Arts::Object child, const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_addChild(child, name); + } + inline bool _removeChild(const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_removeChild(name); + } + inline Arts::Object _getChild(const std::string& name) const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_getChild(name); + } + inline std::vector<std::string> * _queryChildren() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_queryChildren(); + } + // Do we really need those in the Wrapper? + // And would it really be sensible to make _cast wrappers? +/* inline void _release() const { + _pool->checkcreate(); + assert(_pool->base); + return _pool->base->_release(); + } + inline Object_base *_copy() const { + _poo->checkcreate(); + assert(_pool->base); + return _pool->base->_copy(); + } +*/ + + // Object::null() returns a null object (and not just a reference to one) + inline static Object null() {return Object((Object_base*)0);} + inline static Object _from_base(Object_base* b) {return Object(b);} +}; + +// Enables a different constructor, that should do the cast +class ARTS_EXPORT DynamicCast { +private: + Object obj; +public: + inline explicit DynamicCast(const Object& o) : obj(o) {} + inline const Object& object() const {return obj;} +}; + +} + +#endif diff --git a/mcop/referenceclean.cc b/mcop/referenceclean.cc new file mode 100644 index 0000000..58e7001 --- /dev/null +++ b/mcop/referenceclean.cc @@ -0,0 +1,87 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "referenceclean.h" +#include "time.h" + +using namespace std; +using namespace Arts; + +ReferenceClean::ReferenceClean(Pool<Object_skel>& objectPool) + :objectPool(objectPool) +{ + Dispatcher::the()->ioManager()->addTimer(5000, this); +} + +void ReferenceClean::notifyTime() +{ + /* + * This last_notify and now check is because IOManager accumulates + * notifyTime() calls, so it may happen that we don't get one for ten + * seconds, and then two. However, this breaks the "second-chance" + * algorithm referenceClean is using, which depends on the fact that + * there is some significant time delay between two calls. So we'll + * verify it by hand. + */ + + static time_t last_notify = 0; + time_t now; + + time(&now); + if(now-last_notify > 4) + { + clean(); + last_notify = now; + } +} + +void ReferenceClean::forceClean() +{ + /* + * as we're giving a second chance on reference clean, we need to + * clean twice to really really clean up + */ + clean(); + clean(); +} + +void ReferenceClean::clean() +{ + /* + * we manually iterate through the pool here, to get around the problem + * that if an object disappears, ten other objects might cease to exist + * as well (as they are dependant), which would break a list which we + * could obtain via enumerate() and would probably lead to a crash + */ + unsigned long l; + + for(l=0; l<objectPool.max(); l++) + { + Object_skel *skel = objectPool[l]; + if(skel) skel->_referenceClean(); + } +} + +ReferenceClean::~ReferenceClean() +{ + Dispatcher::the()->ioManager()->removeTimer(this); +} diff --git a/mcop/referenceclean.h b/mcop/referenceclean.h new file mode 100644 index 0000000..13b6ec7 --- /dev/null +++ b/mcop/referenceclean.h @@ -0,0 +1,60 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): ReferenceClean + * + * None of these classes is considered part of the public API. Do NOT use it + * in your apps. Can be changed arbitrarily even non BC. + */ + +#ifndef REFERENCECLEAN_H +#define REFERENCECLEAN_H + +#include "iomanager.h" +#include "dispatcher.h" + +namespace Arts { + +class ReferenceClean : public TimeNotify { + Pool<Object_skel>& objectPool; +protected: + void clean(); + +public: + ReferenceClean(Pool<Object_skel>& objectPool); + + /** + * this routine forces cleaning of all tagged remote objects + * + * it will be called on dispatcher shutdown, since after this there + * is no remote interaction anyway, it is be used to prevent memory + * leaks + */ + void forceClean(); + + void notifyTime(); + virtual ~ReferenceClean(); +}; + +} +#endif diff --git a/mcop/socketconnection.cc b/mcop/socketconnection.cc new file mode 100644 index 0000000..f3bc3e8 --- /dev/null +++ b/mcop/socketconnection.cc @@ -0,0 +1,205 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "tcpconnection.h" +#include "dispatcher.h" +#include "debug.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#define queue cqueue +#include <netdb.h> +#undef queue +#include <netinet/in.h> +#include <sys/un.h> +#include <errno.h> + +#undef DEBUG_CONNECTION_DATA + +using namespace Arts; + +/* + * These parameters impact the performance significantly. There are two sides: + * + * when you use too large buffers for reading/writing + * - it may be, that each operation takes too long, so that for instance + * an important real time audio job drops during that time + * - it may be, that dealing with large buffers (allocation, cache, etc) + * itself causes a penalty + * + * on the other hand, small buffers lead to repeated operating system calls, + * which is bad especially if you even go through all the chain: check what + * can be written with select, invoke the corresponding object, actually + * read (or write), do messages, do timers, go sleep again on select. + */ +static const int MCOP_MAX_READ_SIZE=8192; +static const int MCOP_MAX_WRITE_SIZE=8192; + +SocketConnection::SocketConnection() +{ +} + +SocketConnection::SocketConnection(int _fd) + : fd(_fd), _broken(false) +{ + arts_debug("socketconnection created, fd = %d",fd); + Dispatcher::the()->ioManager()->watchFD(fd, + IOType::read|IOType::except|IOType::reentrant,this); + initReceive(); +} + +void SocketConnection::qSendBuffer(Buffer *buffer) +{ + if(_broken) + { + // forget it ;) - no connection there any longer + delete buffer; + return; + } + if(pending.size() == 0) + { + // if there is nothing pending already, it may be that we are lucky + // and can write the buffer right now without blocking + + writeBuffer(buffer); + if(!buffer->remaining()) + { + delete buffer; + return; + } + + // but if it blocks, we'll need to watch for write chances to send + // that buffer later + Dispatcher::the()->ioManager()->watchFD(fd,IOType::write|IOType::reentrant,this); + } + pending.push_back(buffer); +} + +#ifdef DEBUG_CONNECTION_DATA +static void connection_hex_dump(unsigned char *buffer, long len) +{ + int i = 0; + printf("Connection: received %ld bytes:\n\n",len); + while (i < len) + { + unsigned int j, n, d[16]; + + for (n = 0; n < 16; n++) + if (i < len) + d[n] = buffer[i++]; + else + break; + printf (" "); + + for (j = 0; j < n; j++) printf ("%s %02x", j == 8 ? " " : "", d[j]); + for (; j < 16; j++) printf ("%s ", j == 8 ? " " : ""); + printf (" "); + + for (j = 0; j < n; j++) + printf ("%c", d[j] >= 32 ? d[j] : '.'); + printf ("\n"); + } +} +#endif + +void SocketConnection::notifyIO(int _fd, int types) +{ + assert(_fd == fd); + + if(types & IOType::read) + { + unsigned char buffer[MCOP_MAX_READ_SIZE]; + long n = read(fd,buffer,MCOP_MAX_READ_SIZE); + +#ifdef DEBUG_CONNECTION_DATA + connection_hex_dump(buffer,n); +#endif + + if(n > 0) + { + receive(buffer,n); + // warning: the object may not exist any more here! + return; + } + else if(n == 0 /* remote end closed connection */ + || (n == -1 && errno != EAGAIN && errno != EINTR)) /* some error */ + { + close(fd); + _broken = true; + Dispatcher::the()->ioManager()->remove(this,IOType::all); + + Dispatcher::the()->handleConnectionClose(this); + // warning: the object may not exist any more here! + return; + } + } + + if(types & IOType::write) + { + assert(pending.size() != 0); + + Buffer *pbuffer = *pending.begin(); + if(pbuffer->remaining()) writeBuffer(pbuffer); + + // no else => it could have been sent in the if(..remaining..) above + if(!pbuffer->remaining()) + { + delete pbuffer; + pending.pop_front(); + + if(pending.size() == 0) + Dispatcher::the()->ioManager()->remove(this,IOType::write); + } + } + + if(types & IOType::except) + { + assert(false); + } +} + +void SocketConnection::writeBuffer(Buffer *buffer) +{ + long len = MCOP_MAX_WRITE_SIZE; + if(buffer->remaining() < len) len = buffer->remaining(); + + void *data = buffer->peek(len); + long written = write(fd,data,len); + + if(written > 0) + buffer->skip(len); +} + +bool SocketConnection::broken() +{ + return _broken; +} + +void SocketConnection::drop() +{ + if(!_broken) + { + close(fd); + _broken = true; + Dispatcher::the()->ioManager()->remove(this,IOType::all); + } +} diff --git a/mcop/socketconnection.h b/mcop/socketconnection.h new file mode 100644 index 0000000..aaeaeb2 --- /dev/null +++ b/mcop/socketconnection.h @@ -0,0 +1,64 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): SocketConnection + * + * None of these classes is considered part of the public API. Do NOT use it + * in your apps. No BC guaranteed. + */ + +#ifndef SOCKETCONNECTION_H +#define SOCKETCONNECTION_H + +#include "buffer.h" +#include "iomanager.h" +#include "connection.h" +#include <list> +#include <string> + +namespace Arts { + +class SocketConnection :public Connection, public IONotify { +protected: + std::string serverID; + int fd; + bool _broken; + + std::list<Buffer *> pending; + void writeBuffer(Buffer *buffer); + + SocketConnection(); + +public: + SocketConnection(int _fd); + + void qSendBuffer(Buffer *buffer); + void notifyIO(int _fd, int types); + + void drop(); + bool broken(); +}; + +} + +#endif /* SOCKETCONNECTION_H */ diff --git a/mcop/startupmanager.cc b/mcop/startupmanager.cc new file mode 100644 index 0000000..89daf16 --- /dev/null +++ b/mcop/startupmanager.cc @@ -0,0 +1,150 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "startupmanager.h" +#include "extensionloader.h" +#include "debug.h" +#include <iostream> + +using namespace std; +using namespace Arts; + +/* + * StartupClass implementation + */ + +StartupClass::StartupClass() +{ + StartupManager::add(this); +} + +void StartupClass::shutdown() +{ + // shutdown is optional, startup is mandatory +} + +/* + * StartupManager implementation + */ + +list<StartupClass *> *StartupManager::startupClasses = 0; +ExtensionLoader *StartupManager::activeExtensionLoader = 0; +bool StartupManager::running = false; + +void StartupManager::add(StartupClass *sc) +{ + if(activeExtensionLoader) + { + activeExtensionLoader->addStartupClass(sc); + } + else + { + if(running) + { + /* + * the problem with adding a StartupClass when we're already running + * is that we can't execute the startup() function immediately (for + * this might break the dependancy of the StartupClass on other + * globally constructed objects) + * + * so will never execute it, which is likely to break something + * else (i.e. implementations defined in the library the startup + * class is contained in can't be found) + * + * usually, this warning is triggered when an application + * dynamically loads a library containing StartupClasses, without + * libmcop knowing about it + */ + arts_warning("MCOP StartupManager: adding a StartupClass after Dispatcher init will not work."); + } + + if(!startupClasses) startupClasses = new list<StartupClass *>; + + startupClasses->push_back(sc); + } +} + +void StartupManager::setExtensionLoader(ExtensionLoader *extension) +{ + /* + * this is not reentrant: you can't load two extensions at the same time, + * and it is impossible that an extension loads an extension while being + * loaded (nothing forbids you to load another extension from an extension + * in a StartupClass or any time later - just don't do it while being + * lt_dlopen()d + */ + if(activeExtensionLoader) + arts_assert(extension == 0); + else + arts_assert(extension != 0); + + activeExtensionLoader = extension; +} + +void StartupManager::startup() +{ + arts_return_if_fail(running == false); + running = true; + + if(startupClasses) + { + list<StartupClass *>::iterator i; + + for(i = startupClasses->begin(); i != startupClasses->end(); i++) + (*i)->startup(); + } +} + +void StartupManager::shutdown() +{ + arts_return_if_fail(running == true); + running = false; + + if(startupClasses) + { + list<StartupClass *>::iterator i; + + for(i = startupClasses->begin(); i != startupClasses->end(); i++) + (*i)->shutdown(); + } +} + +void StartupManager::internalFreeAll() +{ + if(startupClasses) + { + startupClasses->erase(startupClasses->begin(),startupClasses->end()); + + delete startupClasses; + startupClasses = 0; + } +} + +namespace Arts { + +static class StartupManagerFree { +public: + ~StartupManagerFree() { StartupManager::internalFreeAll(); } +} The_StartupManagerFree; + +} diff --git a/mcop/startupmanager.h b/mcop/startupmanager.h new file mode 100644 index 0000000..028b421 --- /dev/null +++ b/mcop/startupmanager.h @@ -0,0 +1,75 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef STARTUPMANAGER_H +#define STARTUPMANAGER_H + +#include "arts_export.h" + +#include <list> + +/* + * BC - Status (2002-03-08): StartupClass, StartupManager. + * + * The class needs to be kept BC, as the startup system bases on inheritance + * and virtual functions. Do not change. + * + * The manager is a collection class without nonstatic data, so no BC issues + * here. + */ + +namespace Arts { + +class ARTS_EXPORT StartupClass { +public: + StartupClass(); + virtual void startup() = 0; + virtual void shutdown(); +}; + +class StartupManager { + static std::list<StartupClass *> *startupClasses; + static class ExtensionLoader *activeExtensionLoader; + static bool running; +public: + static void add(StartupClass *sc); + static void startup(); + static void shutdown(); + + /** + * since extensions will register startup classes in the same global way + * all other classes do (with StartupManager::add(<some startup class>)), + * the StartupManager supports forwarding all add requests to the + * active extension, which will allow synchronizing the lt_dlopen + * lt_dlclose with the calls of startup()/shutdown() of all StartupClasses + * present in the extension + */ + static void setExtensionLoader(class ExtensionLoader *extension); + + /** + * to free all resources when the application terminates (internal use only) + */ + static void internalFreeAll(); +}; + +} +#endif /* STARTUPMANAGER_H */ diff --git a/mcop/tcpconnection.cc b/mcop/tcpconnection.cc new file mode 100644 index 0000000..e0c086e --- /dev/null +++ b/mcop/tcpconnection.cc @@ -0,0 +1,152 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "tcpconnection.h" +#include "dispatcher.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#define queue cqueue +#include <netdb.h> +#undef queue +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <sys/un.h> +#include <errno.h> +#include "debug.h" +#include <stdlib.h> + +using namespace std; +using namespace Arts; + +static struct sockaddr_in *parse_tcp_url(const char *url) +{ + static struct sockaddr_in addr; + + char *work = strdup(url); + + char *type = strtok(work,":"); + if(type == 0 || strcmp(type,"tcp") != 0) { + free(work); + return 0; + } + + char *host = strtok(NULL,":"); + if(host == 0) { + free(work); + return 0; + } + + char *port = strtok(NULL,":\n"); + if(port == 0) { + free(work); + return 0; + } + + long portno = atol(port); + if(portno < 1 || portno > 65535) { + free(work); + return 0; + } + + struct hostent *server = gethostbyname(host); + if(server == 0) + { + arts_warning("parse_tcp_url: unknown host '%s'",host); + free(work); + return 0; + } + + memset((void *) &addr, '\0', sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = *(u_long *)server->h_addr; + addr.sin_port = htons(portno); + + free(work); + return &addr; +} + +static int tcp_connect(const char *url) +{ + struct sockaddr_in *remote_addr = parse_tcp_url(url); + if(remote_addr == 0) + { + arts_warning("tcp_connect: couldn't parse url %s",url); + return -1; + } + + int my_socket = socket(AF_INET,SOCK_STREAM,0); + if(my_socket < 0) + { + arts_warning("tcp_connect: unable to open socket for read"); + return -1; + } + + struct linger lin; + lin.l_onoff=1; /* block a closing socket for 1 second */ + lin.l_linger=100; /* if data is waiting to be sent */ + if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER, + (char*)&lin, sizeof(struct linger) ) < 0 ) + { + arts_warning("tcp_connect: unable to set socket linger value to %d", + lin.l_linger); + close(my_socket); + return -1; + } + +#ifdef TCP_NODELAY + // enable TCP sending without nagle algorithm - this sends out requests + // faster, because they are not queued in the hope that more data will + // need to be sent soon + int on = 1; + if(setsockopt(my_socket, IPPROTO_TCP, TCP_NODELAY, + (char *)&on, sizeof(on)) < 0) + { + arts_debug("couldn't set TCP_NODELAY on socket %d\n", my_socket); + } +#endif + + int rc; + rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr)); + if(rc != 0) + { + arts_warning("tcp_connect: can't connect to server (%s)", url); + close(my_socket); + return -1; + } + + return my_socket; +} + +TCPConnection::TCPConnection(const string& url) +{ + fd = tcp_connect(url.c_str()); + _broken = (fd == -1); + + if(!_broken) + { + Dispatcher::the()->ioManager()->watchFD(fd, + IOType::read|IOType::except|IOType::reentrant,this); + initReceive(); + } +} diff --git a/mcop/tcpconnection.h b/mcop/tcpconnection.h new file mode 100644 index 0000000..654bfe2 --- /dev/null +++ b/mcop/tcpconnection.h @@ -0,0 +1,43 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): TCPConnection + * + * Not part of the public API. Do NOT use it in your apps. Binary incompatible + * changes allowed. + */ + +#ifndef TCPCONNECTION_H +#define TCPCONNECTION_H + +#include "socketconnection.h" + +namespace Arts { + +class TCPConnection :public SocketConnection { +public: + TCPConnection(const std::string& url); +}; + +} +#endif /* TCPCONNECTION_H */ diff --git a/mcop/tcpserver.cc b/mcop/tcpserver.cc new file mode 100644 index 0000000..d62e28c --- /dev/null +++ b/mcop/tcpserver.cc @@ -0,0 +1,193 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "tcpserver.h" +#include "socketconnection.h" +#include "dispatcher.h" +#define queue cqueue +#include <arpa/inet.h> +#undef queue +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include "mcoputils.h" +#include "debug.h" + +using namespace std; +using namespace Arts; + +bool TCPServer::running() +{ + return socketOk; +} + +TCPServer::TCPServer(Dispatcher *dispatcher) +{ + this->dispatcher = dispatcher; + + socketOk = initSocket(); + if(socketOk) { + IOManager *iom = dispatcher->ioManager(); + iom->watchFD(theSocket,IOType::read|IOType::except,this); + } +} + +TCPServer::~TCPServer() +{ + if(socketOk) + { + IOManager *iom = dispatcher->ioManager(); + iom->remove(this,IOType::read|IOType::except); + close(theSocket); + } +} + +static int TCPServerPort = 0; + +void TCPServer::setPort(int port) +{ + TCPServerPort = port; +} + +bool TCPServer::initSocket() +{ + struct sockaddr_in socket_addr; + + theSocket = socket(PF_INET,SOCK_STREAM,0); + if(theSocket < 0) + { + arts_warning("MCOP TCPServer: can't create a socket"); + return false; + } + + if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0) + { + arts_warning("MCOP TCPServer: can't initialize non blocking I/O"); + close(theSocket); + return false; + } + + if (TCPServerPort) + { + int optval = 1; + if(setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR, + (const char *)&optval, sizeof (optval)) < 0) + { + arts_warning("MCOP TCPServer: can't set address reuse"); + close(theSocket); + return false; + } + } + +#ifdef TCP_NODELAY + // enable TCP sending without nagle algorithm - this sends out requests + // faster, because they are not queued in the hope that more data will + // need to be sent soon + int on = 1; + if(setsockopt(theSocket, IPPROTO_TCP, TCP_NODELAY, + (char *)&on, sizeof(on)) < 0) + { + arts_debug("couldn't set TCP_NODELAY on socket %d\n", theSocket); + } +#endif + + socket_addr.sin_family = AF_INET; + socket_addr.sin_port = htons( TCPServerPort ); // 0 = choose port freely + socket_addr.sin_addr.s_addr = htonl( inet_addr("0.0.0.0") ); + if ( bind( theSocket, (struct sockaddr *) &socket_addr, + sizeof(struct sockaddr_in) ) < 0 ) + { + arts_warning("MCOP TCPServer: can't bind to port/address"); + close(theSocket); + return false; + } + + socklen_t sz = sizeof(struct sockaddr_in); + int r = getsockname (theSocket,(struct sockaddr *)&socket_addr, &sz); + if(r == 0) { + thePort = ntohs(socket_addr.sin_port); + } + else + { + arts_warning("MCOP TCPServer: getsockname failed"); + close(theSocket); + return false; + } + + if(listen(theSocket,16) < 0) + { + arts_warning("MCOP TCPServer: can't listen on the socket"); + close(theSocket); + return false; + } + + arts_debug("TCPServer: listening on '%s'", url().c_str()); + return true; +} + +string TCPServer::url() +{ + char xport[200]; + sprintf(xport,"%d",thePort); + + return "tcp:"+MCOPUtils::getFullHostname()+":"+xport; +} + +void TCPServer::notifyIO(int fd, int types) +{ + assert(fd == theSocket); + assert(socketOk); + + arts_debug("TCPManager: got notifyIO"); + if(types & IOType::read) + { + int clientfd; + struct sockaddr_in incoming; + socklen_t size_in = sizeof(struct sockaddr_in); + + clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in ); + if(clientfd > 0) + { + // non blocking I/O + int flags = fcntl (fd, F_GETFL, 0); + assert (flags != -1); + + int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + assert(nbl_result >= 0); + + Dispatcher::the()->initiateConnection( + new SocketConnection(clientfd)); + } + } + arts_assert((types & IOType::write) == 0); + arts_assert((types & IOType::except) == 0); +} + +// vim: sw=4 ts=4 diff --git a/mcop/tcpserver.h b/mcop/tcpserver.h new file mode 100644 index 0000000..93cecca --- /dev/null +++ b/mcop/tcpserver.h @@ -0,0 +1,61 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef TCPSERVER_H +#define TCPSERVER_H + +#include <string> +#include "arts_export.h" +#include "iomanager.h" +/* + * BC - Status (2002-03-08): TCPServer + * + * Not part of the public API. Do NOT use it in your apps. Binary incompatible + * changes allowed. + */ + +namespace Arts { + +class Dispatcher; + +class ARTS_EXPORT TCPServer :public IONotify { +protected: + Dispatcher *dispatcher; + + int theSocket; + int thePort; + bool socketOk; + bool initSocket(); + +public: + TCPServer(Dispatcher *dispatcher); + virtual ~TCPServer(); + bool running(); + std::string url(); + static void setPort(int port); + + void notifyIO(int fd, int types); +}; + +} + +#endif /* TCPSERVER_H */ diff --git a/mcop/thread.cc b/mcop/thread.cc new file mode 100644 index 0000000..2d81118 --- /dev/null +++ b/mcop/thread.cc @@ -0,0 +1,169 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "thread.h" +#include <string.h> + +using namespace Arts; + +// Thread: +Thread::~Thread() +{ + delete impl; +} + +Thread_impl::~Thread_impl() +{ +} + +// Mutex: +Mutex::~Mutex() +{ + delete impl; +} + +Mutex_impl::~Mutex_impl() +{ +} + +// ThreadCondition: + +ThreadCondition::~ThreadCondition() +{ + delete impl; +} + +ThreadCondition_impl::~ThreadCondition_impl() +{ +} + +// Semaphore +Semaphore::~Semaphore() +{ + delete impl; +} + +Semaphore_impl::~Semaphore_impl() +{ +} + +// No threading: + +namespace Arts { + +class SystemThreadsNoMutex_impl : public Mutex_impl { +public: + void lock() {}; + bool tryLock() { return true; }; + void unlock() {}; +}; + +static Thread *systemThreadsNoneCurrent = 0; + +class SystemThreadsNoThread_impl : public Thread_impl { +private: + Thread *thread; +public: + SystemThreadsNoThread_impl(Thread *thread) : thread(thread) {} + void setPriority(int) {} + void start() { + Thread *oldCurrent = systemThreadsNoneCurrent; + + systemThreadsNoneCurrent = thread; + thread->run(); + systemThreadsNoneCurrent = oldCurrent; + } + void waitDone() {} +}; + +class SystemThreadsNoThreadCondition_impl : public ThreadCondition_impl { +public: + void wakeOne() {}; + void wakeAll() {}; + void wait(Mutex_impl *) {}; +}; + +class SystemThreadsNoSemaphore_impl : public Semaphore_impl { +public: + void wait() {} + int tryWait() { return 0; } + void post() {} + int getValue() { return 0; } +}; + +class SystemThreadsNone : public SystemThreads { +public: + bool isMainThread() { + return (systemThreadsNoneCurrent == 0); + } + Mutex_impl *createMutex_impl() { + return new SystemThreadsNoMutex_impl(); + } + Mutex_impl *createRecMutex_impl() { + return new SystemThreadsNoMutex_impl(); + } + Thread_impl *createThread_impl(Thread *thread) { + return new SystemThreadsNoThread_impl(thread); + } + ThreadCondition_impl *createThreadCondition_impl() { + return new SystemThreadsNoThreadCondition_impl(); + } + Thread *getCurrentThread() { + return systemThreadsNoneCurrent; + } + Semaphore_impl *createSemaphore_impl(int, int) { + return new SystemThreadsNoSemaphore_impl(); + } +}; + +} + +static SystemThreadsNone systemThreadsNone; +static SystemThreads *SystemThreads_the = 0; + +SystemThreads *SystemThreads::the() +{ + if(!SystemThreads_the) return &systemThreadsNone; + return SystemThreads_the; +} + +bool SystemThreads::init(SystemThreads *the) +{ + if(SystemThreads_the) + return false; + else + { + SystemThreads_the = the; + return true; + } +} + +bool SystemThreads::supported() +{ + return (SystemThreads_the != 0); +} + +SystemThreads::~SystemThreads() +{ +} + +namespace Arts { void ARTS_EXPORT *gslGlobalMutexTable = 0; } diff --git a/mcop/thread.h b/mcop/thread.h new file mode 100644 index 0000000..882e596 --- /dev/null +++ b/mcop/thread.h @@ -0,0 +1,375 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_MCOP_THREAD_H +#define ARTS_MCOP_THREAD_H + +#include "arts_export.h" + +/* + * BC - Status (2002-03-08): SystemThreads, Thread, Mutex, ThreadCondition, + * Semaphore + * + * These classes are kept binary compatible. As the threading implementation + * can be changed, also + * + * Thread_impl, Mutex_impl, ThreadCondition_impl and Semaphore_impl need + * to remain as they are. The implementation of these depends on what thread + * system is used, and can attach the required data as necessary to the + * base classes. So i.e. a posix mutex can contain the pthread_mutex_t in + * the PosixMutex_impl. + */ + +namespace Arts { + +class Mutex_impl; +class Thread_impl; +class ThreadCondition_impl; +class Thread; +class Semaphore_impl; + +/** + * Encapsulates the operating system threading facilities + */ +class ARTS_EXPORT SystemThreads { +public: + static SystemThreads *the(); + static bool init(SystemThreads *the); + + /** + * Check whether there is threading support available + * + * If there is no real threading support, the Threading classes try to + * gracefully degrade the performance. For instance, locking a mutex will + * do * nothing, and calling the start() function of a Thread will execute + * it's run function. + * + * @returns true if there are real threads + */ + static bool supported(); + + /** + * Check wether the current thread is the main thread + * + * The main thread is the thread that the application's main() was + * executed in. The IOManager event loop will only run in the main + * thread. + */ + virtual bool isMainThread() = 0; + + virtual Mutex_impl *createMutex_impl() = 0; + virtual Mutex_impl *createRecMutex_impl() = 0; + virtual Thread_impl *createThread_impl(Thread *thread) = 0; + virtual ThreadCondition_impl *createThreadCondition_impl() = 0; + virtual Semaphore_impl *createSemaphore_impl(int, int) = 0; + virtual ~SystemThreads(); + + /** + * Returns a pointer to the current thread, or a null pointer if + * we're the main thread (isMainThread() is true). + */ + virtual Thread *getCurrentThread() = 0; +}; + +/** + * Base class for platform specific thread code + */ +class ARTS_EXPORT Thread_impl +{ +public: + virtual void setPriority(int) =0; + virtual void start() = 0; + virtual void waitDone() = 0; + virtual ~Thread_impl(); +}; + +/** + * Base class for platform specific mutex code + */ +class ARTS_EXPORT Mutex_impl { +public: + virtual void lock() = 0; + virtual bool tryLock() = 0; + virtual void unlock() = 0; + virtual ~Mutex_impl(); +}; + +/** + * Base class for platform specific thread condition code + */ +class ARTS_EXPORT ThreadCondition_impl { +public: + virtual void wakeOne() = 0; + virtual void wakeAll() = 0; + virtual void wait(Mutex_impl *impl) = 0; + virtual ~ThreadCondition_impl(); +}; + +class ARTS_EXPORT Semaphore_impl { +public: + virtual void wait() = 0; + virtual int tryWait() = 0; + virtual void post() = 0; + virtual int getValue() = 0; + virtual ~Semaphore_impl(); +}; + +/** + * A thread of execution + * + * Example for implementing a thread: + * + * <pre> + * class Counter : public Arts::Thread + * { + * public: + * void run() { + * for(int i = 0;i < 10;i++) + * { + * printf("%d\n",i+1); + * sleep(1); + * } + * } + * }; // start the thread with Counter c; c.start(); + * </pre> + */ +class ARTS_EXPORT Thread { +private: + Thread_impl *impl; + +public: + Thread() : impl(SystemThreads::the()->createThread_impl(this)) + { + } + + virtual ~Thread(); + + /** + * set the priority parameters for the thread + * + * FIXME: what should be minimum, maximum, recommended? + */ + inline void setPriority(int priority) { + impl->setPriority(priority); + } + + /** + * starts the run() method in a thread + */ + inline void start() + { + impl->start(); + } + + /** + * waits until the thread is executed completely + */ + inline void waitDone() + { + impl->waitDone(); + } + + /** + * implement this method, if you want to create an own thread - then + * you can simply call thread.start() to start execution of run() in + * a seperate thread + */ + virtual void run() = 0; +}; + +/** + * A mutex + * + * To protect a critical section, you can use a mutex, which will ensure that + * only one thread at a time can lock it. Here is an example for a thread-safe + * random number generator: + * + * <pre> + * class RandomGenerator { + * Arts::Mutex mutex; + * long seed; + * public: + * long get() { + * mutex.lock(); + * // do complicated calculation with seed here + * mutex.unlock(); + * return seed; + * } + * }; + * </pre> + */ +class ARTS_EXPORT Mutex { +private: + Mutex_impl *impl; + friend class ThreadCondition; + +public: + /** + * constructor + * + * @param recursive whether to create a recursive mutex (may be locked by + * the same thread more than once), or a normal mutex + */ + inline Mutex(bool recursive = false) + : impl(recursive?SystemThreads::the()->createRecMutex_impl() + :SystemThreads::the()->createMutex_impl()) + { + } + + /** + * destructor + */ + virtual ~Mutex(); + + /** + * locks the mutex + */ + inline void lock() { + impl->lock(); + } + + /** + * tries to lock the mutex, returning immediately in any case (even if + * mutex is locked by another thread) + * + * @returns true if successful (mutex locked), false otherwise + */ + inline bool tryLock() { + return impl->tryLock(); + } + + /** + * unlocks the mutex + */ + inline void unlock() { + impl->unlock(); + } +}; + +/** + * A thread condition + * + * Thread conditions are used to let a different thread know that a certain + * condition might have changed. For instance, if you have a thread that + * waits until a counter exceeds a limit, the thread would look like this: + * + * <pre> + * class WaitCounter : public Arts::Thread + * { + * int counter; + * Arts::Mutex mutex; + * Arts::ThreadCondition cond; + * + * public: + * WaitCounter() : counter(0) {} + * + * void run() { // run will terminate once the counter reaches 20 + * mutex.lock(); + * while(counter < 20) + * cond.wait(mutex); + * mutex.unlock(); + * } + * + * void inc() { // inc will increment the counter and indicate the change + * mutex.lock(); + * counter++; + * cond.wakeOne(); + * mutex.unlock(); + * } + * }; + * </pre> + */ +class ARTS_EXPORT ThreadCondition { +private: + ThreadCondition_impl *impl; + +public: + ThreadCondition() + : impl(SystemThreads::the()->createThreadCondition_impl()) + { + } + + virtual ~ThreadCondition(); + + /** + * wakes one waiting thread + */ + inline void wakeOne() + { + impl->wakeOne(); + } + + /** + * wakes all waiting threads + */ + inline void wakeAll() + { + impl->wakeAll(); + } + + /** + * Waits until the condition changes. You will need to lock the mutex + * before calling this. Internally it will unlock the mutex (to let + * others change the condition), and relock it once the wait succeeds. + */ + inline void wait(Mutex& mutex) + { + impl->wait(mutex.impl); + } +}; + +class ARTS_EXPORT Semaphore { +private: + Semaphore_impl *impl; + +public: + Semaphore(int shared=0, int count=0) + { + impl = SystemThreads::the()->createSemaphore_impl(shared, count); + } + + virtual ~Semaphore(); + + inline void wait() + { + impl->wait(); + } + + inline int tryWait() + { + return impl->tryWait(); + } + + inline void post() + { + impl->post(); + } + + inline int getValue() + { + return impl->getValue(); + } +}; + +} + +#endif /* ARTS_MCOP_THREAD_H */ diff --git a/mcop/tmpglobalcomm.cc b/mcop/tmpglobalcomm.cc new file mode 100644 index 0000000..9332bce --- /dev/null +++ b/mcop/tmpglobalcomm.cc @@ -0,0 +1,82 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "common.h" +#include "mcoputils.h" + +using namespace std; +using namespace Arts; + +namespace Arts { + +class TmpGlobalComm_impl : virtual public TmpGlobalComm_skel { +public: + bool put(const string& variable, const string& value) + { + string filename = MCOPUtils::createFilePath(variable); + + int fd = open(filename.c_str(),O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR); + if(fd != -1) + { + int result = write(fd,value.c_str(),value.size()); + + assert(result == (int)value.size()); + close(fd); + return true; + } + + return false; + } + + string get(const string& variable) + { + string result = ""; + string filename = MCOPUtils::createFilePath(variable); + + int fd = open(filename.c_str(),O_RDONLY); + if(fd != -1) + { + char buffer[8192]; + int size = read(fd,buffer,8192); + if(size > 0 && size < 8192) { + buffer[size] = 0; + result = buffer; + } + + close(fd); + } + return result; + } + + void erase(const string& variable) + { + string filename = MCOPUtils::createFilePath(variable); + unlink(filename.c_str()); + } +}; + +REGISTER_IMPLEMENTATION(TmpGlobalComm_impl); + +} diff --git a/mcop/trader_impl.cc b/mcop/trader_impl.cc new file mode 100644 index 0000000..6dd84bd --- /dev/null +++ b/mcop/trader_impl.cc @@ -0,0 +1,345 @@ + /* + + Copyright (C) 2000-2002 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "common.h" +#include "debug.h" +#include <iostream> +#include <fstream> +#include <algorithm> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <cstring> + +using namespace Arts; +using namespace std; + +namespace Arts { + +// TraderRestriction +struct TraderRestriction { + TraderRestriction(const string& key, const string& value) + :key(key), value(value) { } + + string key; + string value; +}; + +// TraderHelper (internal, no public interface) +class TraderHelper { +private: + vector<class TraderOffer_impl *> allOffers; + static TraderHelper *_instance; + +protected: + TraderHelper(); + ~TraderHelper(); + void addDirectory(const string& directory, const string& iface = "", + map< pair<dev_t,ino_t>, bool > *dirsDone = 0); + +public: + vector<TraderOffer> *doQuery(const vector<TraderRestriction>& query); + void load(); + void unload(); + static TraderHelper *the(); + static void shutdown(); +}; + +// TraderQuery +class TraderQuery_impl : virtual public TraderQuery_skel { +private: + vector<TraderRestriction> restrictions; +public: + void supports(const string& property, const string& value); + vector<TraderOffer> *query(); +}; + +REGISTER_IMPLEMENTATION(TraderQuery_impl); + +// TraderOffer +class TraderOffer_impl : virtual public TraderOffer_skel { +private: + string _interfaceName; + map<string, vector<string> > property; + +public: + TraderOffer_impl(const string& interfaceName, const string& filename); + + bool match(const vector<TraderRestriction>& restrictions); + + // IDL + string interfaceName(); + vector<string>* getProperty(const string& name); +}; + +} + +// TraderQuery +//---------------------------------------------------------------------------- +void TraderQuery_impl::supports(const string& property, const string& value) +{ + restrictions.push_back(TraderRestriction(property,value)); +} + +vector<TraderOffer> *TraderQuery_impl::query() +{ + return TraderHelper::the()->doQuery(restrictions); +} + +// TraderOffer +//---------------------------------------------------------------------------- +TraderOffer_impl::TraderOffer_impl(const string& interfaceName, + const string& filename) + :_interfaceName(interfaceName) +{ + ifstream file(filename.c_str()); + string line; + + while(getline(file,line)) + { + string key; + vector<string> values; + + if(MCOPUtils::tokenize(line,key,values)) + property[key] = values; + } + + vector<string>& iname = property["InterfaceName"]; + if(iname.empty()) + iname.push_back(interfaceName); +} + +bool TraderOffer_impl::match(const vector<TraderRestriction>& restrictions) +{ + vector<TraderRestriction>::const_iterator i; + + for(i = restrictions.begin(); i != restrictions.end();i++) + { + const TraderRestriction& res = *i; + const vector<string>& myvalues = property[res.key]; + bool okay = false; + + vector<string>::const_iterator offerIt = myvalues.begin(); + while(!okay && offerIt != myvalues.end()) + { + if(res.value == *offerIt) + okay = true; + else + offerIt++; + } + + if(!okay) return false; + } + return true; +} + +string TraderOffer_impl::interfaceName() +{ + return _interfaceName; +} + +vector<string>* TraderOffer_impl::getProperty(const string& name) +{ + return new vector<string>(property[name]); +} + +// TraderHelper +//---------------------------------------------------------------------------- + +TraderHelper::TraderHelper() +{ + load(); +} + +TraderHelper::~TraderHelper() +{ + unload(); +} + +void TraderHelper::load() +{ + const vector<string> *path = MCOPUtils::traderPath(); + + vector<string>::const_iterator pi; + for(pi = path->begin(); pi != path->end(); pi++) addDirectory(*pi); +} + +void TraderHelper::unload() +{ + vector<TraderOffer_impl *>::iterator i; + + for(i = allOffers.begin(); i != allOffers.end(); i++) + { + TraderOffer_impl *offer = *i; + offer->_release(); + } + allOffers.clear(); +} + +void TraderHelper::addDirectory(const string& directory, const string& iface, + map< pair<dev_t,ino_t>, bool > *dirsDone) +{ + bool created_dirs_done = false; + arts_debug("addDirectory(%s,%s)", directory.c_str(), iface.c_str()); + + if(!dirsDone) + { + /* map to prevent doing directories again due to symlinks */ + dirsDone = new map< pair<dev_t,ino_t>, bool >; + + struct stat st; + stat(directory.c_str(), &st); + (*dirsDone)[make_pair(st.st_dev, st.st_ino)] = true; + created_dirs_done = true; + } + + DIR *dir = opendir(directory.c_str()); + if(!dir) return; + + struct dirent *de; + while((de = readdir(dir)) != 0) + { + string currentEntry = directory + "/" + de->d_name; + + string currentIface = iface; + if(!iface.empty()) currentIface += "::"; + currentIface += de->d_name; + + struct stat st; + stat(currentEntry.c_str(),&st); + + // recurse into subdirectories + if(S_ISDIR(st.st_mode)) + { + bool& done = (*dirsDone)[make_pair(st.st_dev, st.st_ino)]; + if(strcmp(de->d_name,".") && strcmp(de->d_name,"..") && !done) + { + done = true; + addDirectory(currentEntry,currentIface,dirsDone); + } + } + else if(S_ISREG(st.st_mode)) + { + if(strlen(de->d_name) > 10 && + strncmp(&de->d_name[strlen(de->d_name)-10],".mcopclass",10) == 0) + { + // cut .mcopclass for currentIface; + currentIface = currentIface.substr(0, currentIface.size()-10); + allOffers.push_back( + new TraderOffer_impl(currentIface,currentEntry) ); + } + } + } + + if (created_dirs_done) + delete dirsDone; + + closedir(dir); +} + +static inline int getOfferPreference(TraderOffer offer) +{ + int result = 0; + + vector<string> *p = offer.getProperty("Preference"); + if(!p->empty()) + result = atoi(p->front().c_str()); + delete p; + + return result; +} + +static bool traderOfferCmp(TraderOffer offer1, TraderOffer offer2) +{ + int p1 = getOfferPreference(offer1); + int p2 = getOfferPreference(offer2); + + if(p1 > p2) + return true; + if(p1 < p2) + return false; + + /* if the Preference= entry doesn't indicate which offer is better, + * sort the offers by name to make the trader results at least + * independant from the order they are read from the file system */ + return offer1.interfaceName() < offer2.interfaceName(); +} + +vector<TraderOffer> *TraderHelper::doQuery(const + vector<TraderRestriction>& query) +{ + vector<TraderOffer> *result = new vector<TraderOffer>; + + vector<TraderOffer_impl *>::iterator i; + for(i = allOffers.begin(); i != allOffers.end(); i++) + { + TraderOffer_impl *offer = *i; + + if(offer->match(query)) + { + result->push_back(TraderOffer::_from_base(offer->_copy())); + } + } + + /* sort trader query result by Preference= line for more than one result */ + if(result->size() > 1) + sort(result->begin(), result->end(), traderOfferCmp); + return result; +} + +TraderHelper *TraderHelper::_instance = 0; +TraderHelper *TraderHelper::the() +{ + if(!_instance) _instance = new TraderHelper(); + return _instance; +} + +void TraderHelper::shutdown() +{ + if(_instance) + { + delete _instance; + _instance = 0; + } +} + +namespace Arts { + +// trader shutdown +class TraderShutdown :public StartupClass +{ +public: + void startup() { }; + void shutdown() { TraderHelper::shutdown(); }; +}; + +static TraderShutdown traderShutdown; + +} + +// Dispatcher function for reloading the trader data: +void Dispatcher::reloadTraderData() +{ + TraderHelper::the()->unload(); + TraderHelper::the()->load(); +} diff --git a/mcop/type.cc b/mcop/type.cc new file mode 100644 index 0000000..541876b --- /dev/null +++ b/mcop/type.cc @@ -0,0 +1,31 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "type.h" +#include <assert.h> + +long Arts::Type::_staticTypeCount = 0; + +Arts::Type::~Type() +{ + _staticTypeCount--; +} diff --git a/mcop/type.h b/mcop/type.h new file mode 100644 index 0000000..2f95d20 --- /dev/null +++ b/mcop/type.h @@ -0,0 +1,85 @@ + /* + + Copyright (C) 2000-2002 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef TYPE_H +#define TYPE_H + +#include "arts_export.h" +#include "buffer.h" + +/* + * BC - Status (2002-03-08): Type + * + * Keep binary compatible. DO NOT TOUCH, DO NOT CHANGE. + */ + +namespace Arts { + +/** + * Base class for the IDL mapping of struct-like types + */ +class ARTS_EXPORT Type { +private: + static long _staticTypeCount; + +public: + inline static long _typeCount() { return _staticTypeCount; } + /** + * constructor + */ + inline Type() + { + _staticTypeCount++; + } + + /** + * copy constructor + */ + inline Type(const Type&) + { + _staticTypeCount++; + } + + /** + * virtual destructor (since we have virtual functions and this stuff + */ + virtual ~Type(); + + /** + * read the type from a stream + */ + virtual void readType(Buffer& stream) = 0; + + /** + * write the type to a stream + */ + virtual void writeType(Buffer& stream) const = 0; + + /** + * type name + */ + virtual std::string _typeName() const = 0; +}; + +} + +#endif diff --git a/mcop/unixconnection.cc b/mcop/unixconnection.cc new file mode 100644 index 0000000..adda10d --- /dev/null +++ b/mcop/unixconnection.cc @@ -0,0 +1,114 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "unixconnection.h" +#include "dispatcher.h" +#include "debug.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> +#include <sys/un.h> +#include <errno.h> +#include <stdlib.h> + +using namespace std; +using namespace Arts; + +static struct sockaddr_un *parse_unix_url(const char *url) +{ + static struct sockaddr_un addr; + + char *work = strdup(url); + + char *type = strtok(work,":"); + if(type == 0 || strcmp(type,"unix") != 0) { + free(work); + return 0; + } + + char *path = strtok(NULL,":\n"); + if(path == 0) { + free(work); + return 0; + } + + int maxlen = sizeof(addr.sun_path); + memset((void *) &addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path,path,maxlen); + addr.sun_path[maxlen-1] = 0; + free(work); + return &addr; +} + +static int unix_connect(const char *url) +{ + struct sockaddr_un *remote_addr = parse_unix_url(url); + if(remote_addr == 0) + { + arts_warning("unix_connect: couldn't parse url %s",url); + return -1; + } + + int my_socket = socket(AF_UNIX,SOCK_STREAM,0); + if(my_socket < 0) + { + arts_warning("unix_connect: unable to open socket for read"); + return -1; + } + + struct linger lin; + lin.l_onoff=1; /* block a closing socket for 1 second */ + lin.l_linger=100; /* if data is waiting to be sent */ + if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER, + (char*)&lin, sizeof(struct linger) ) < 0 ) + { + arts_warning("unix_connect: unable to set socket linger value to %d", + lin.l_linger); + close(my_socket); + return -1; + } + + int rc; + rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr)); + if(rc != 0) + { + arts_warning("unix_connect: can't connect to server (%s)",url); + close(my_socket); + return -1; + } + + return my_socket; +} + +UnixConnection::UnixConnection(const string& url) +{ + fd = unix_connect(url.c_str()); + _broken = (fd == -1); + + if(!_broken) + { + Dispatcher::the()->ioManager()->watchFD(fd, + IOType::read|IOType::except|IOType::reentrant,this); + initReceive(); + } +} diff --git a/mcop/unixconnection.h b/mcop/unixconnection.h new file mode 100644 index 0000000..54a5643 --- /dev/null +++ b/mcop/unixconnection.h @@ -0,0 +1,43 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): UnixConnection + * + * Not part of the public API. Do NOT use it in your apps. Can change, even + * binary incompatible. + */ + +#ifndef UNIXCONNECTION_H +#define UNIXCONNECTION_H + +#include "socketconnection.h" + +namespace Arts { + +class UnixConnection :public SocketConnection { +public: + UnixConnection(const std::string& url); +}; + +} +#endif /* UNIXCONNECTION_H */ diff --git a/mcop/unixserver.cc b/mcop/unixserver.cc new file mode 100644 index 0000000..65cfa76 --- /dev/null +++ b/mcop/unixserver.cc @@ -0,0 +1,151 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <config.h> +#include "mcoputils.h" +#include "unixserver.h" +#include "socketconnection.h" +#include "dispatcher.h" +#include "debug.h" +#define queue cqueue +#include <arpa/inet.h> +#undef queue +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> + +using namespace std; +using namespace Arts; + +bool UnixServer::running() +{ + return socketOk; +} + +UnixServer::UnixServer(Dispatcher *dispatcher, const string& serverID) +{ + this->dispatcher = dispatcher; + + socketOk = initSocket(serverID); + if(socketOk) { + IOManager *iom = dispatcher->ioManager(); + iom->watchFD(theSocket,IOType::read|IOType::except,this); + } +} + +UnixServer::~UnixServer() +{ + if(socketOk) { + IOManager *iom = dispatcher->ioManager(); + iom->remove(this,IOType::read|IOType::except); + close(theSocket); + unlink(xserverpath.c_str()); + } +} + +bool UnixServer::initSocket(const string& serverID) +{ + struct sockaddr_un socket_addr; + + theSocket = socket(PF_UNIX,SOCK_STREAM,0); + if(theSocket < 0) + { + arts_warning("MCOP UnixServer: can't create a socket"); + return false; + } + + if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0) + { + arts_warning("MCOP UnixServer: can't initialize non blocking I/O"); + close(theSocket); + return false; + } + + int maxlen = sizeof(socket_addr.sun_path); + string pathname = MCOPUtils::createFilePath(serverID); + + socket_addr.sun_family = AF_UNIX; + strncpy(socket_addr.sun_path,pathname.c_str(),maxlen); + socket_addr.sun_path[maxlen-1] = 0; + + xserverpath = socket_addr.sun_path; + + if ( bind( theSocket, (struct sockaddr *) &socket_addr, + sizeof(struct sockaddr_un) ) < 0 ) + { + arts_warning("MCOP UnixServer: can't bind to file \"%s\"", + pathname.c_str()); + close(theSocket); + return false; + } + + if(listen(theSocket,16) < 0) + { + arts_warning("MCOP UnixServer: can't listen on the socket"); + close(theSocket); + return false; + } + return true; +} + +string UnixServer::url() +{ + return string("unix:") + xserverpath; +} + +void UnixServer::notifyIO(int fd, int types) +{ + assert(fd == theSocket); + assert(socketOk); + + arts_debug("UnixManager: got notifyIO"); + if(types & IOType::read) + { + int clientfd; + struct sockaddr_un incoming; + socklen_t size_in = sizeof(struct sockaddr_un); + + clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in ); + if(clientfd > 0) + { + // non blocking I/O + int flags = fcntl (fd, F_GETFL, 0); + assert (flags != -1); + + int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + assert(nbl_result >= 0); + + Dispatcher::the()->initiateConnection( + new SocketConnection(clientfd)); + } + } + arts_assert((types & IOType::write) == 0); + arts_assert((types & IOType::except) == 0); +} diff --git a/mcop/unixserver.h b/mcop/unixserver.h new file mode 100644 index 0000000..b492e39 --- /dev/null +++ b/mcop/unixserver.h @@ -0,0 +1,59 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): UnixServer + * + * Not part of the public API. Do NOT use it in your apps. Can change, even + * binary incompatible. + */ + +#ifndef UNIXSERVER_H +#define UNIXSERVER_H + +#include <string> +#include "iomanager.h" + +namespace Arts { + +class Dispatcher; + +class UnixServer :public IONotify { +protected: + Dispatcher *dispatcher; + + std::string xserverpath; + int theSocket; + bool socketOk; + bool initSocket(const std::string& serverID); + +public: + UnixServer(Dispatcher *dispatcher, const std::string& serverID); + virtual ~UnixServer(); + bool running(); + std::string url(); + + void notifyIO(int fd, int types); +}; + +} +#endif /* UNIXSERVER_H */ diff --git a/mcop/weakreference.h b/mcop/weakreference.h new file mode 100644 index 0000000..76bb381 --- /dev/null +++ b/mcop/weakreference.h @@ -0,0 +1,131 @@ + /* + + Copyright (C) 2000-2002 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): WeakReference(Base) + * + * Has to be kept binary compatible by not touching it. Add a new class if + * you need something else. + */ + +#ifndef MCOP_WEAKREFERENCE_H +#define MCOP_WEAKREFERENCE_H + +#include "arts_export.h" + +namespace Arts { + +class ARTS_EXPORT WeakReferenceBase { +public: + virtual void release() = 0; +}; + +/** + * The WeakReference class can be used to safely store an object, without + * disallowing that it gets destroyed. A typical situation where you may want + * to use this is when you implement a datastructure, where A refers B, and + * B refers A. Using "normal" references, this structure would never get + * freed. + * + * Usage example: + * + * Synth_WAVE_SIN sin; + * WeakReference<Synth_PLAY_WAV> weak_sin; + * + * { + * Synth_WAVE_SIN test = weak_sin; + * if(test.isNull()) + * printf("#1 missing object\n"); + * else + * test.start(); + * } + * + * // now, the strong reference leaves + * sin = Synth_WAVE_SIN::null(); + * + * { + * Synth_WAVE_SIN test = weak_sin; + * if(test.isNull()) + * printf("#2 missing object\n"); + * else + * test.stop(); + * + * This would output "#2 missing object". + * + */ + +template<class SmartWrapper> +class WeakReference : public WeakReferenceBase +{ +private: + typename SmartWrapper::_base_class *content; + +public: + WeakReference() + { + content = 0; + } + WeakReference(const WeakReference<SmartWrapper>& source) + :WeakReferenceBase(source), content(source.content) + { + if(content) + content->_addWeakReference(this); + } + WeakReference(SmartWrapper& source) + { + content = source._base(); + if(content) + content->_addWeakReference(this); + } + inline WeakReference<SmartWrapper>& operator=(const + WeakReference<SmartWrapper>& source) + { + release(); + content = source.content; + if(content) + content->_addWeakReference(this); + return *this; + } + virtual ~WeakReference() + { + release(); + } + void release() + { + if(content) + { + content->_removeWeakReference(this); + content = 0; + } + } + inline operator SmartWrapper() const + { + if(content) + return SmartWrapper::_from_base(content->_copy()); + else + return SmartWrapper::null(); + } +}; + +} + +#endif /* MCOP_WEAKREFERENCE_H */ |