diff --git a/.gitattributes b/.gitattributes index 08e4a357b42b220e246a02b9a8f3089552dd93d8..15d87b117de51006e3b3c7b31031d2931610c2aa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -462,6 +462,8 @@ MAC/GCF/lofarconf.in -text svneol=native#application/octet-stream MAC/MACIO/bootstrap -text MAC/MACIO/src/KVT_Protocol.prot -text MAC/MACIO/src/LOG_Protocol.prot -text +MAC/MACIO/src/SB_Protocol.prot -text svneol=native#application/octet-stream +MAC/MACIO/test/Echo_Protocol.prot -text MAC/Navigator/CS1-Navigator-Panels.doc -text MAC/Navigator/colorDB/Lofar[!!-~]colors -text svneol=native#application/octet-stream MAC/Navigator/colorDB/colorDB_fw -text svneol=native#application/octet-stream diff --git a/MAC/MACIO/Makefile.am b/MAC/MACIO/Makefile.am index 90d82dbb21ef35ce74d0ff4e2369f9442755b76d..1068f5729e1a0d057ac416dc652127617af6ec70 100644 --- a/MAC/MACIO/Makefile.am +++ b/MAC/MACIO/Makefile.am @@ -1,11 +1,11 @@ -SUBDIRS=src include +SUBDIRS=autogen src include pkgextdir = $(prefix)/config/$(PACKAGE) pkgext_DATA = pkgext pkgextcppflags pkgextcxxflags pkgextldflags EXTRA_DIST = \ Makefile.common \ - APLProtocol.spec \ + MACIO.spec \ autoconf_share/compiletool include $(top_srcdir)/Makefile.common diff --git a/MAC/MACIO/autogen/Makefile.am b/MAC/MACIO/autogen/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..1b769ff602fc0580b9c156ea2bee50c8ca42355a --- /dev/null +++ b/MAC/MACIO/autogen/Makefile.am @@ -0,0 +1,7 @@ +pkgdatadir = $(datadir)/MACIO +pkgdata_DATA = protocol.tpl + +EXTRA_DIST = $(pkgdata_DATA) + +include $(top_srcdir)/Makefile.common + diff --git a/MAC/MACIO/autogen/protocol.tpl b/MAC/MACIO/autogen/protocol.tpl new file mode 100644 index 0000000000000000000000000000000000000000..d555f86df4c93109a0c0b376f9d87e548ffc3b7e --- /dev/null +++ b/MAC/MACIO/autogen/protocol.tpl @@ -0,0 +1,218 @@ +[+ AutoGen5 template ph cc +] +// +[+ (dne "// ") +][+ (out-push-add "/dev/null") +] +[+ DEFINE prefix_cap +][+ IF (exist? "prefix") +][+ (get "prefix") +][+ ENDIF +][+ ENDDEF +] +[+ DEFINE prefix_ucase +][+ IF (exist? "prefix") +][+ (string-upcase (get "prefix")) +][+ ENDIF +][+ ENDDEF +] +[+ DEFINE protocol_id +][+ IF (exist? "id") +][+ (get "id") +][+ ENDIF +][+ ENDDEF +] +[+ DEFINE signal_name +][+ prefix_ucase +]_[+ (get "signal") +][+ ENDDEF +] +[+ DEFINE signal_id +][+ signal_name +]_ID[+ ENDDEF +] +[+ DEFINE cap_signal +][+ (string-substitute (string-capitalize! (get "signal")) '( "_" )' ( "" )) +][+ ENDDEF +] +[+ DEFINE event_class_name +][+ prefix_cap +][+ cap_signal +]Event[+ ENDDEF +] +[+ DEFINE event_class_decl +][+ event_class_name +] : public MACIO::GCFEvent[+ ENDDEF +] +[+ DEFINE protocol_name +][+ (string-upcase (base-name)) +][+ ENDDEF +] +[+ DEFINE event_class_member_type +][+ IF (*== (get "type") "]") +][+ (substring (get "type") 0 (string-index (get "type") #\[)) +][+ ELSE +][+ (get "type") +][+ ENDIF +][+ ENDDEF +] +[+ DEFINE event_class_member +][+ event_class_member_type +][+ IF (*== (get "type") "[]") +]*[+ ENDIF +] [+ (get "name") +][+ IF (and (*== (get "type") "]") (not (*== (get "type") "[]"))) +][+ (substring (get "type") (string-index (get "type") #\[) (string-length (get "type"))) +][+ ENDIF +][+ ENDDEF +] + +[+ (out-pop) +] +// +// [+ (base-name) +].[+ (suffix) +]: [+ description +] +// +// Copyright (C) 2003-2008 +// ASTRON (Netherlands Foundation for Research in Astronomy) +// P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +// +[+ (lgpl "This program" "ASTRON" "// ") +] +// +// $Id$ +// +[+ IF (== (suffix) "cc") +] +#include "[+ (base-name) +].ph" + +using namespace LOFAR::MACIO; + +const char* LOFAR::[+ (base-name) +]::[+ protocol_name +]_signalnames[] = +{ + "[+ protocol_name +]: invalid signal",[+ FOR event "," +] + "[+ signal_name +]"[+ ENDFOR +] +}; + +const char* [+ protocol_name +]_errornames[] = +{ [+ FOR error "," +] + "[+ (get "msg") +]"[+ ENDFOR error +] +}; + +const struct protocolStrings LOFAR::[+ (base-name) +]::[+ protocol-name +]_STRINGS = { + [+ (count "event") +]+1, [+ (count "error") +], + LOFAR::[+ (base-name) +]::[+ protocol_name +]_signalnames, + [+ protocol_name +]_errornames +}; +[+ ELSE +] +#ifndef [+ protocol_name +]_H +#define [+ protocol_name +]_H + +[+ FOR include "" +] +#include [+ (get "include") +][+ ENDFOR +] +#include <MACIO/ProtocolDefs.h> +#include <Common/LofarTypes.h> +#include <string> + +namespace LOFAR +{ + namespace [+ (base-name) +] + { + +[+ (get "prelude") +] + +// +// Define protocol ID +// +enum +{ + [+ protocol_name +] = [+ protocol_id +] +}; + +// +// Define error numbers and names +// +enum +{ [+ FOR error "," +] + [+ prefix_ucase +]_[+ (get "id") +]_ERR[+ IF (= 0 (for-index)) +] = F_ERROR([+ protocol_name +], [+ (for-index) +])[+ ENDIF +][+ ENDFOR error +] +}; + +// +// Define protocol message types +// +enum +{ [+ FOR event "," +] + [+ signal_id +][+ IF (= 0 (for-index)) +] = 1[+ ENDIF +][+ ENDFOR event +] +}; + +[+ FOR event "" +] +#define [+ prefix_ucase +]_[+ (get "signal") +] F_SIGNAL([+ protocol_name +], [+ prefix_ucase +]_[+ (get "signal") +]_ID, F_[+ (get "dir")+])[+ ENDFOR event +] + +extern const char* [+ protocol_name +]_signalnames[]; // for backwards compatibility +extern const struct LOFAR::MACIO::protocolStrings [+ protocol-name +]_STRINGS; + +[+ ENDIF +] +[+ FOR event "" +][+ IF (= (suffix) "ph") +][+ FOR param "" +] +[+ IF (*== (get "type") "&") +][+ (error "reference types not supported") +][+ ENDIF +] +[+ IF (and (==* (get "type") "string") (> (string-length (get "type")) 6)) +][+ (error "only scalar 'string' is supported") +][+ ENDIF +][+ ENDFOR +] + class [+ event_class_decl +] + { + public: + [+ event_class_name +](MACIO::GCFEvent& e); + [+ event_class_name +](); + virtual ~[+ event_class_name +](); + + [+ FOR param ";" +] + [+ IF (== (get "type") "string") +]std::[+ ENDIF +][+ event_class_member +][+ IF (*== (get "type") "[]") +]; uint32 [+ (get "name") +]NOE[+ ENDIF +][+ ENDFOR +]; + + void* pack(uint32& __packsize); + + private: + [+ event_class_name +]([+ event_class_name +]&); + [+ event_class_name +]& operator= (const [+ event_class_name +]&); + + void unpack(); + }; [+ ELSE +] +[+ event_class_name +]::[+ event_class_name +](MACIO::GCFEvent& e) + : MACIO::GCFEvent(e)[+ FOR param "" +][+ IF (or (*== (get "type") "[]") (*== (get "type") "*")) +], + [+ (get "name") +](0)[+ ENDIF +][+ IF (*== (get "type") "[]") +], + [+ (get "name") +]NOE(0)[+ ENDIF +][+ ENDFOR +] +{ + unpack(); +} + +[+ event_class_name +]::[+ event_class_name +]() + : MACIO::GCFEvent([+ signal_name +])[+ FOR param "" +][+ IF (or (*== (get "type") "[]") (*== (get "type") "*")) +], + [+ (get "name") +](0)[+ ENDIF +][+ IF (*== (get "type") "[]") +], + [+ (get "name") +]NOE(0)[+ ENDIF +][+ ENDFOR +] +{ +} + +[+ event_class_name +]::~[+ event_class_name +]() +{ + if (_unpackDone) + {[+ FOR param "" +][+ IF (and (exist? "userdefined") (*== (get "type") "*")) +] + if ([+ (get "name") +]) delete [+ (get "name") +];[+ ENDIF +][+ ENDFOR +] + } +} + +void* [+ event_class_name +]::pack(uint32& __packsize) +{ + [+ FOR param "" +][+ IF (or (*== (get "type") "[]") (*== (get "type") "*")) +][+ IF (*== (get "type") "[]") +]if ([+ (get "name") +]NOE > 0) [+ ENDIF +]assert([+ (get "name") +]);[+ ENDIF +] + [+ ENDFOR +] + uint32 __requiredSize = [+ IF (not (exist? "noheader")) +]sizeof(signal) + sizeof(length)[+ ELSE +]0[+ ENDIF +][+ FOR param "" +] + [+ IF (exist? "userdefined") +]+ [+ (get "name") +][+ IF (*== (get "type") "*") +]->[+ ELSE +].[+ ENDIF +]getSize() + [+ ELIF (not (*== (get "type") "]")) +]+ [+ IF (== (get "type") "string") +][+ (get "name") +].length() + sizeof(uint16)[+ ELSE +]sizeof([+ (get "name") +])[+ ENDIF+] + [+ ELIF (*== (get "type") "[]") +]+ sizeof([+ (get "name") +]NOE) + ([+ (get "name") +]NOE * sizeof([+ event_class_member_type +])) + [+ ELSE +]+ sizeof([+ (get "name") +])[+ ENDIF +][+ ENDFOR +]; + + resizeBuf(__requiredSize); + uint32 __offset = __packsize = 0; + [+ IF (not (exist? "noheader")) +] + MACIO::GCFEvent::pack(__offset);[+ ENDIF +] + [+ FOR param "" +] + [+ IF (exist? "userdefined") +] + __offset += [+ (get "name") +][+ IF (*== (get "type") "*") +]->[+ ELSE +].[+ ENDIF +]pack(_buffer + __offset); + [+ ELIF (not (*== (get "type") "]")) +] + [+ IF (== (get "type") "string") +] + __offset += packString(_buffer + __offset, [+ (get "name") +]); + [+ ELSE +] + memcpy(_buffer + __offset, &[+ (get "name") +], sizeof([+ (get "type") +])); + __offset += sizeof([+ (get "type") +]); + [+ ENDIF +] + [+ ELIF (*== (get "type") "[]") +] + __offset += packMember(__offset, [+ (get "name") +], [+ (get "name") +]NOE, sizeof([+ event_class_member_type +])); + [+ ELSE +] + memcpy(_buffer + __offset, [+ (get "name") +], sizeof([+ (get "name") +])); + __offset += sizeof([+ (get "name") +]); + [+ ENDIF +][+ ENDFOR +] + [+ IF (= (count "param") 0) +] + // no params in this event to pack + [+ ENDIF +] + + __packsize = __offset; + return _buffer; +} + +void [+ event_class_name +]::unpack() +{ + if (length > 0) + { + [+ IF (> (count "param") 0) +] + uint32 __offset = sizeof(MACIO::GCFEvent); + char* __data = (char*) _base; + [+ ELSE +] + // no params in this event to unpack + [+ ENDIF +] + [+ FOR param "" +] + [+ IF (exist? "userdefined") +] + [+ IF (*== (get "type") "*") +] + [+ (get "name") +] = new [+ (substring (get "type") 0 (string-index (get "type") #\*)) +](); + [+ ENDIF +] + __offset += [+ (get "name") +][+ IF (*== (get "type") "*") +]->[+ ELSE +].[+ ENDIF +]unpack(__data + __offset); + [+ ELIF (not (*== (get "type") "]")) +] + [+ IF (== (get "type") "string") +] + __offset += MACIO::GCFEvent::unpackString([+ (get "name") +], __data + __offset); + [+ ELSE +] + memcpy(&[+ (get "name") +], __data + __offset, sizeof([+ (get "type") +])); + __offset += sizeof([+ (get "type") +]); + [+ ENDIF +] + [+ ELIF (*== (get "type") "[]") +] + [+ (get "name") +] = ([+ event_class_member_type +]*) unpackMember(__data, __offset, [+ (get "name") +]NOE, sizeof([+ event_class_member_type +])); + [+ ELSE +] + memcpy([+ (get "name") +], (__data + __offset), sizeof([+ (get "name") +])); + __offset += sizeof([+ (get "name") +]); + [+ ENDIF +][+ ENDFOR +] + } +}[+ ENDIF +][+ ENDFOR +] +[+ IF (= (suffix) "ph") +] + } // namespace [+ (base-name) +] +} // namespace LOFAR + + +using namespace LOFAR::[+ (base-name) +]; + +#endif +[+ ENDIF +] diff --git a/MAC/MACIO/configure.in b/MAC/MACIO/configure.in index dff8a1935d39bc8b1282ec5d6a49bee4cd2cac1b..a015beb14818e1462f30a67e6edb7c7f62659c16 100644 --- a/MAC/MACIO/configure.in +++ b/MAC/MACIO/configure.in @@ -54,13 +54,16 @@ dnl Check for LOFAR specific things dnl lofar_GENERAL lofar_COMPILETOOLS -lofar_INTERNAL(MAC/APL/RTCCommon, rtccommon, , 1, APL/RTCCommon/Marshalling.h,,) +lofar_INTERNAL(LCS/Common, Common, , 1, Common/LofarTypes.h,,) +dnl lofar_INTERNAL(MAC/APL/RTCCommon, rtccommon, , 1, APL/RTCCommon/Marshalling.h,,) dnl dnl Output Makefiles dnl AC_OUTPUT( +autogen/Makefile src/Makefile +test/Makefile include/Makefile include/MACIO/Makefile Makefile diff --git a/MAC/MACIO/include/MACIO/EventPort.h b/MAC/MACIO/include/MACIO/EventPort.h new file mode 100644 index 0000000000000000000000000000000000000000..635605d4b4e0a1706d1378162969b568615defde --- /dev/null +++ b/MAC/MACIO/include/MACIO/EventPort.h @@ -0,0 +1,122 @@ +//# EventPort.h: LCS-Common-Socket based impl of a GCF TCPPort +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef LOFAR_MACIO_EVENTPORT_H +#define LOFAR_MACIO_EVENTPORT_H + +// \file EventPort.h +// LCS-Common-Socket based impl of a GCF TCPPort + +//# Never #include <config.h> or #include <lofar_config.h> in a header file! +//# Includes +#include <Common/Net/Socket.h> +#include <MACIO/GCF_Event.h> + +// Avoid 'using namespace' in headerfiles + +namespace LOFAR { + namespace MACIO { + +// \addtogroup MACIO +// @{ + + +// Define states for the connection fases. +enum { + EP_CREATED = 0, + EP_SEES_SB, + EP_WAIT_FOR_SB_ANSWER, + EP_KNOWS_DEST, + EP_CONNECTING, + EP_CONNECTED, + EP_DISCONNECTED +}; + +// The EventPort class is a LCS/Common Socket based TCP port to make it +// possible for CEP applications to use the MAC protocols. +class EventPort +{ +public: + + // EventPort (servicename, type, protocol, hostname) + EventPort::EventPort(const string& aServiceMask, + bool aServerSocket, + int aProtocol, + const string& aHostname = "", + bool syncCommunication = false); + + // ~EventPort + EventPort::~EventPort(); + + // connect() + bool connect(); + + // send(Event*) + bool send(GCFEvent* anEvent); + + // receive() : Event + GCFEvent* receive(); + + // getStatus() + int getStatus() { return (itsStatus); } + +private: + // static receiveEvent(aSocket) + GCFEvent* receiveEvent(Socket* aSocket); + + // static sendEvent(Socket*, Event*) + void sendEvent(Socket* aSocket, + GCFEvent* anEvent); + + // _internal routines: see source code for description + string _makeServiceName(const string& aServiceMask, int32 aNumber); + bool _setupConnection(); + int32 _askBrokerThePortNumber(); + int32 _waitForSBAnswer(); + int32 _startConnectionToPeer(); + int32 _waitForPeerResponse(); + void _peerClosedConnection(); + + EventPort(); + + // Copying is not allowed + EventPort(const EventPort& that); + EventPort& operator=(const EventPort& that); + + //# --- Datamembers --- + int32 itsPort; + string itsHost; + string itsServiceName; + Socket* itsSocket; + Socket* itsListenSocket; + Socket* itsBrokerSocket; + int32 itsStatus; + bool itsSyncComm; + bool itsIsServer; +}; + + +// @} + } // namespace MACIO +} // namespace LOFAR + +#endif diff --git a/MAC/MACIO/include/MACIO/GCF_Event.h b/MAC/MACIO/include/MACIO/GCF_Event.h new file mode 100644 index 0000000000000000000000000000000000000000..017f260d8574d14547b570180b487dcfd40489c5 --- /dev/null +++ b/MAC/MACIO/include/MACIO/GCF_Event.h @@ -0,0 +1,163 @@ +//# GCF_Event.h: finite state machine events +//# +//# Copyright (C) 2002-2003 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef MACIO_GCF_EVENT_H +#define MACIO_GCF_EVENT_H + +#include <Common/LofarTypes.h> +#include <Common/lofar_string.h> + +namespace LOFAR { + namespace MACIO { + +/** + * This class is the base event data container to exchange messages between two + * tasks. + * Application tasks will have to define their own protocol by specifying the + * contents of events that are exchanged between tasks. Creating sub class from + * GCFEvent creates application (tasks) specific events. All GCFEvent sub + * classes are generally the same except for the parameters that make the event + * unique. A protocol is a collection of events where each event has a specific + * direction (IN/OUT). To create a new protocol a protocol specification file + * must be created (with extension '.prot'). The autogen utility is then used to + * convert this specification file into a header file containing GCFEvent sub + * class definitions. + * The protocol specification consists of a list of the possible events in the + * protocol each with its own parameters (or no parameters) and with the + * direction in which the event can be sent. The autogen utility is used to + * generate a header file from this definition using a template for the header + * file and the nested key-value pairs from the specification file. This header + * file contains definitions of GCFEvent sub classes, one for each event. + */ + +#define SIZEOF_EVENT(e) ((ssize_t) (sizeof((e).signal) + sizeof((e).length) + (e).length)) + +class GCFEvent +{ + public: // constructors, destructors, operators + GCFEvent() : + signal(0), length(0), _unpackDone(false), _buffer(0), + _base(0), _upperbound(0) + {} + + GCFEvent(unsigned short sig) : + signal(sig), length(0), _unpackDone(false), _buffer(0), + _base(0), _upperbound(0) + {} + + /// destructor + virtual ~GCFEvent(); + + protected: + /// special constructor it will be call by the specialised "unpack"- + /// constructor generated by autogen + GCFEvent(GCFEvent& e) : + signal(e.signal), length(e.length), _unpackDone(true), _buffer(0), + _base(&e), _upperbound(0) + {} + + private: + GCFEvent& operator= (GCFEvent& e); + + public: // member methods + + /// result of a dispatch action + enum TResult { ERROR = -1, HANDLED = 0, NOT_HANDLED = 1}; + + /** + * packs all fields of the event into the event buffer and returns its + * pointer and the number of packed bytes (output argument + */ + virtual void* pack(uint32& packsize); + + protected: // helper methods + + uint32 unpackString(string& value, char* buffer); + uint32 packString(char* buffer, const string& value); + + void resizeBuf(uint32 requiredSize); + void* unpackMember(char* data, uint32& offset, uint32& memberNOE, uint32 sizeofMemberType); + uint32 packMember(uint32 offset, const void* member, uint32 memberNOE, uint32 sizeofMemberType); + + public: // data members + /** + * @code + * Signal format + * + * 2 most significant bits indicate direction of signal: + * F_IN = 0b01 + * F_OUT = 0b10 + * F_INOUT = 0b11 (F_IN_SIGNAL | F_OUT_SIGNAL) + * + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | O | I | P | P | P | P | P | P | S | S | S | S | S | S | S | S | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * <- I/O-><--- protocol ---------><--------- signal --------------> + * @endcode + */ + uint16 signal; // lsb contains signal id (0-255) + // msb contains protocol id (0-255) + uint32 length; // payload length of the event (thus excl. signal and length) should be <= SSIZE_MAX) + + protected: + /// indicates wether the event is unpacked or not + bool _unpackDone; + /// the packbuffer + char* _buffer; + /** before the event can be unpacked the "base" must be set, which + * points to the received raw and not unpacked data. In memory first a + * GCFEvent object (with only signal and length) is placed followed by the + * packed buffer with size "length". This is the data of the specialized event. + */ + GCFEvent* _base; + + private: + /// upperbound of the buffer, will be used by resizeBuf method + unsigned int _upperbound; + +}; + +class GCFTransportable +{ + public: + virtual ~GCFTransportable() {} + virtual unsigned int pack(char* buffer) = 0; + virtual unsigned int unpack(char* buffer) = 0; + virtual unsigned int getSize() = 0; +}; + +/** + * Macros to aid in decoding the signal field. + */ +#define F_EVT_INOUT_MASK (0xc000) +#define F_EVT_PROTOCOL_MASK (0x3f00) +#define F_EVT_SIGNAL_MASK (0x00ff) + +#define F_EVT_INOUT(e) (((e).signal & F_EVT_INOUT_MASK) >> 14) +#define F_EVT_PROTOCOL(e) (((e).signal & F_EVT_PROTOCOL_MASK) >> 8) +#define F_EVT_SIGNAL(e) ((e).signal & F_EVT_SIGNAL_MASK) + + } // namespace MACIO +} // namespace LOFAR + +#endif diff --git a/MAC/MACIO/include/MACIO/MACServiceInfo.h b/MAC/MACIO/include/MACIO/MACServiceInfo.h index d3a325451562e8bc56b539af1af37dd0a8aefdff..14f227cc1347bcc967f0f822fcb9065fefb7c9b7 100644 --- a/MAC/MACIO/include/MACIO/MACServiceInfo.h +++ b/MAC/MACIO/include/MACIO/MACServiceInfo.h @@ -20,8 +20,8 @@ //# //# $Id$ -#ifndef GCFCOMMON_SERVICEINFO_H -#define GCFCOMMON_SERVICEINFO_H +#ifndef MACIO_SERVICEINFO_H +#define MACIO_SERVICEINFO_H // \file MACServiceInfo.h // Contains all information about the MAC services. diff --git a/MAC/MACIO/include/MACIO/Makefile.am b/MAC/MACIO/include/MACIO/Makefile.am index 02501127ff52300d4262271df414556583367eb5..2eea3950b27c626cf14d0ccd4238d711f5c329e5 100644 --- a/MAC/MACIO/include/MACIO/Makefile.am +++ b/MAC/MACIO/include/MACIO/Makefile.am @@ -1,5 +1,10 @@ pkgincludedir = $(includedir)/MACIO -pkginclude_HEADERS = MACServiceInfo.h +pkginclude_HEADERS = EventPort.h \ + GCF_Event.h \ + MACServiceInfo.h \ + Marshalling.h \ + ProtocolDefs.h \ + StringVector.h include $(top_srcdir)/Makefile.common diff --git a/MAC/MACIO/include/MACIO/MarshallBlitz.h b/MAC/MACIO/include/MACIO/MarshallBlitz.h deleted file mode 100644 index 8bb5ffe268a1549b60d7d1ccf2ab8295d930a107..0000000000000000000000000000000000000000 --- a/MAC/MACIO/include/MACIO/MarshallBlitz.h +++ /dev/null @@ -1,76 +0,0 @@ -//# -*- mode: c++ -*- -//# -//# MarshallBlitz.h: Macros for packing/unpacking blitz arrays -//# -//# Copyright (C) 2002-2004 -//# ASTRON (Netherlands Foundation for Research in Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl -//# -//# This program is free software; you can redistribute it and/or modify -//# it under the terms of the GNU General Public License as published by -//# the Free Software Foundation; either version 2 of the License, or -//# (at your option) any later version. -//# -//# This program 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License -//# along with this program; if not, write to the Free Software -//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//# -//# $Id$ - -#ifndef MARSHALLBLITZ_H_ -#define MARSHALLBLITZ_H_ - -#include <Common/LofarTypes.h> -#include <blitz/array.h> - -// SIZE blitz::array<...> -#define MSH_ARRAY_SIZE(array, datatype) \ - (((array).dimensions()*sizeof(int32)) + ((array).size() * sizeof(datatype))) - -// PACK blitz::array<...> -// first copy the dimensions of the array, then the array itself. -#define MSH_PACK_ARRAY(bufptr, offset, array, datatype) \ -do { \ - for (int dim = blitz::firstDim; dim < blitz::firstDim + (array).dimensions(); dim++) { \ - int32 extent = (array).extent(dim); \ - memcpy(((char*)(bufptr)) + (offset), &extent, sizeof(int32)); \ - offset += sizeof(int32); \ - } \ - \ - if ((array).numElements() > 0) { \ - if ((array).isStorageContiguous()) { \ - memcpy(((char*)(bufptr)) + (offset), (array).data(), (array).size() * sizeof(datatype)); \ - offset += (array).size() * sizeof(datatype); \ - } \ - else { \ - LOG_FATAL("array must be contiguous"); \ - exit(EXIT_FAILURE); \ - } \ - } \ -} while (0) - -// UNPACK blitz::array<...> -#define MSH_UNPACK_ARRAY(bufptr, offset, array, datatype, dims) \ -do { \ - blitz::TinyVector<int, (dims)> extent; \ - \ - for (int dim = blitz::firstDim; dim < blitz::firstDim + (dims); dim++) { \ - int32 extenttmp = array.extent(dim); \ - memcpy(&extenttmp, ((char*)(bufptr)) + (offset), sizeof(int32)); \ - offset += sizeof(int32); \ - extent(dim - blitz::firstDim) = extenttmp; \ - } \ - \ - /* resize the array to the correct size */ \ - array.resize(extent); \ - \ - memcpy(array.data(), ((char*)(bufptr)) + (offset), array.size() * sizeof(datatype)); \ - offset += array.size() * sizeof(datatype); \ -} while (0) - -#endif /* MARSHALLING_H_ */ diff --git a/MAC/MACIO/include/MACIO/Marshalling.h b/MAC/MACIO/include/MACIO/Marshalling.h new file mode 100644 index 0000000000000000000000000000000000000000..6aa8bf0a7eed582b7027e5fc51f912b00b0b87be --- /dev/null +++ b/MAC/MACIO/include/MACIO/Marshalling.h @@ -0,0 +1,209 @@ +//# -*- mode: c++ -*- +//# +//# Marshalling.h: Macros for packing/unpacking some classes +//# +//# Copyright (C) 2002-2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef MACIO_MARSHALLING_H_ +#define MACIO_MARSHALLING_H_ + +#include <Common/LofarTypes.h> +#include <Common/lofar_string.h> +#include <Common/lofar_bitset.h> +#include <Common/lofar_map.h> + +// SIZE string +#define MSH_STRING_SIZE(stdstring) \ + (sizeof(uint32) + (stdstring).size() * sizeof(char)) + +// PACK string +#define MSH_PACK_STRING(bufptr, offset, stdstring) \ +do { \ + /* pack stdstring with length */ \ + uint32 size = (stdstring).size() * sizeof(char); \ + memcpy(((char*)(bufptr)) + (offset), &size, sizeof(size)); \ + offset += sizeof(size); \ + memcpy(((char*)(bufptr)) + (offset), (stdstring).c_str(), size * sizeof(char)); \ + offset += size * sizeof(char); \ +} while (0) + +// UNPACK string +#define MSH_UNPACK_STRING(bufptr, offset, stdstring) \ +do { \ + uint32 size = 0; \ + memcpy(&size, ((char*)(bufptr)) + (offset), sizeof(size)); \ + offset += sizeof(size); \ + char stringbuf[size + 1]; \ + memcpy(stringbuf, ((char*)(bufptr)) + (offset), size * sizeof(char)); \ + stringbuf[size] = '\0'; \ + (stdstring) = string(stringbuf); /* cast to std::string */ \ + offset += size * sizeof(char); \ +} while (0) + +// SIZE bitset<...> +#define MSH_BITSET_SIZE(bset) sizeof(bset) + +// PACK bitset<...> +#define MSH_PACK_BITSET(buffer, offset, bset) \ +do { \ + memcpy(((char*)(buffer))+(offset), &(bset), sizeof(bset)); \ + offset += sizeof(bset); \ +} while(0) + +// UNPACK bitset<...> +#define MSH_UNPACK_BITSET(buffer,offset,bset) \ +do { \ + memcpy(&bset, ((char*)(buffer))+(offset), sizeof(bset)); \ + offset += sizeof(bset); \ +} while(0) + +// SIZE map<string, class_with_getSize> +#define MSH_SIZE_MAP_STRING_CLASS(sizevar, themap, datatype) \ +do { \ + sizevar = sizeof(int32); \ + map<string, datatype>::iterator iter = themap.begin(); \ + map<string, datatype>::iterator end = themap.end(); \ + while (iter != end) { \ + sizevar += MSH_STRING_SIZE(iter->first); \ + sizevar += iter->second.getSize(); \ + iter++; \ + } \ +} while (0) + + +// PACK map<string, class_with_pack> +#define MSH_PACK_MAP_STRING_CLASS(bufptr, offset, themap, datatype) \ +do { \ + int32 nrElem = themap.size(); \ + memcpy(((char*)(bufptr)) + (offset), &nrElem, sizeof(int32)); \ + offset += sizeof(int32); \ + \ + map<string, datatype>::iterator iter = themap.begin(); \ + map<string, datatype>::iterator end = themap.end(); \ + while (iter != end) { \ + MSH_PACK_STRING(bufptr, offset, iter->first); \ + offset += iter->second.pack(bufptr + offset); \ + iter++; \ + } \ +} while (0) + +// UNPACK map<string, class_with_unpack> +#define MSH_UNPACK_MAP_STRING_CLASS(bufptr, offset, themap, datatype) \ +do { \ + int32 nrElem = 0; \ + memcpy(&nrElem, ((char*)(bufptr)) + (offset), sizeof(nrElem)); \ + offset += sizeof(nrElem); \ + \ + for (int elem = 0; elem < nrElem; elem++) { \ + string elem1; \ + MSH_UNPACK_STRING(bufptr, offset, elem1); \ + offset += themap[elem1].unpack(bufptr + offset); \ + } \ +} while (0) + +// SIZE map<string, ptr2class_with_getSize> +#define MSH_SIZE_MAP_STRING_CLASSPTR(sizevar, themap, datatype) \ +do { \ + sizevar = sizeof(int32); \ + map<string, datatype*>::iterator iter = themap.begin(); \ + map<string, datatype*>::iterator end = themap.end(); \ + while (iter != end) { \ + sizevar += MSH_STRING_SIZE(iter->first); \ + sizevar += iter->second->getSize(); \ + iter++; \ + } \ +} while (0) + + +// PACK map<string, ptr2class_with_pack> +#define MSH_PACK_MAP_STRING_CLASSPTR(bufptr, offset, themap, datatype) \ +do { \ + int32 nrElem = themap.size(); \ + memcpy(((char*)(bufptr)) + (offset), &nrElem, sizeof(int32)); \ + offset += sizeof(int32); \ + \ + map<string, datatype*>::iterator iter = themap.begin(); \ + map<string, datatype*>::iterator end = themap.end(); \ + while (iter != end) { \ + MSH_PACK_STRING(bufptr, offset, iter->first); \ + offset += iter->second->pack((char*)bufptr + offset); \ + iter++; \ + } \ +} while (0) + +// UNPACK map<string, ptr2class_with_unpack> +#define MSH_UNPACK_MAP_STRING_CLASSPTR(bufptr, offset, themap, datatype) \ +do { \ + int32 nrElem = 0; \ + memcpy(&nrElem, ((char*)(bufptr)) + (offset), sizeof(nrElem)); \ + offset += sizeof(nrElem); \ + \ + for (int elem = 0; elem < nrElem; elem++) { \ + string elem1; \ + MSH_UNPACK_STRING(bufptr, offset, elem1); \ + themap[elem1] = new datatype; \ + offset += themap[elem1]->unpack((char*)bufptr + offset); \ + } \ +} while (0) + +// SIZE vector<string>> +#define MSH_SIZE_VECTOR_STRING(sizevar, thevector) \ +do { \ + sizevar = sizeof(int32); \ + vector<string>::iterator iter = thevector.begin(); \ + vector<string>::iterator end = thevector.end(); \ + while (iter != end) { \ + sizevar += MSH_STRING_SIZE(*iter); \ + iter++; \ + } \ +} while (0) + + +// PACK vector<string> +#define MSH_PACK_VECTOR_STRING(bufptr, offset, thevector) \ +do { \ + int32 nrElem = thevector.size(); \ + memcpy(((char*)(bufptr)) + (offset), &nrElem, sizeof(int32)); \ + offset += sizeof(int32); \ + \ + vector<string>::iterator iter = thevector.begin(); \ + vector<string>::iterator end = thevector.end(); \ + while (iter != end) { \ + MSH_PACK_STRING(bufptr, offset, *iter); \ + iter++; \ + } \ +} while (0) + +// UNPACK vector<string> +#define MSH_UNPACK_VECTOR_STRING(bufptr, offset, thevector) \ +do { \ + int32 nrElem = 0; \ + memcpy(&nrElem, ((char*)(bufptr)) + (offset), sizeof(nrElem)); \ + offset += sizeof(nrElem); \ + \ + for (int elem = 0; elem < nrElem; elem++) { \ + string elem1; \ + MSH_UNPACK_STRING(bufptr, offset, elem1); \ + thevector.push_back(elem1); \ + } \ +} while (0) + +#endif /* MARSHALLING_H_ */ diff --git a/MAC/MACIO/include/MACIO/ProtocolDefs.h b/MAC/MACIO/include/MACIO/ProtocolDefs.h new file mode 100644 index 0000000000000000000000000000000000000000..64c354bc79c1df41b61ce9df7bacae992124459b --- /dev/null +++ b/MAC/MACIO/include/MACIO/ProtocolDefs.h @@ -0,0 +1,97 @@ +//# ProtocolDefs.h: protocols used by the framework +//# +//# Copyright (C) 2002-2003 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef PROTOCOLDEFS_H +#define PROTOCOLDEFS_H + +#include <MACIO/GCF_Event.h> + +namespace LOFAR { + namespace MACIO { + +/** + * Macro to encode an event's signal from the signal id, protocal an in/out direction + */ +#define F_SIGNAL(prot, sig, inout) ( (((unsigned short)(inout) & 0x3) << 14) \ + | (((unsigned short)(prot) & 0x3f) << 8) \ + | ((unsigned short)(sig) & 0xff) \ + ) + +// Macros for encoding and decoding errornumbers +#define F_ERROR(prot, num) ( (((unsigned short)(prot) & 0x3f) * 100) + (num) ) +#define F_ERR_PROTOCOL(errID) ( ((unsigned short)(errID) / 100) & 0x3f ) +#define F_ERR_NR(errID) ( (unsigned short)(errID) % 100 ) + +/** + * Define different types of signals + */ +#define F_IN 0x01 +#define F_OUT 0x02 +#define F_INOUT (F_IN | F_OUT) + +// Macros for getting the direction from a signal +#define F_INDIR(signal) ( ((unsigned short)signal >> 14) & F_IN) +#define F_OUTDIR(signal) ( ((unsigned short)signal >> 14) & F_OUT) + +// convenience macros +#define F_ENTRY F_SIGNAL(F_FSM_PROTOCOL, F_ENTRY_ID, F_IN) +#define F_EXIT F_SIGNAL(F_FSM_PROTOCOL, F_EXIT_ID, F_IN) +#define F_INIT F_SIGNAL(F_FSM_PROTOCOL, F_INIT_ID, F_IN) +#define F_QUIT F_SIGNAL(F_FSM_PROTOCOL, F_QUIT_ID, F_IN) + +/** + * This enum lists all framework protocols. The application protocols should + * start numbering enums at F_APPLICATION_PROTOCOL, e.g.: + * + * enum { + * MY_CONTROL_PROTOCOL = F_APPLICATION_PROTOCOL, + * MY_MONITORING_PROTOCOL, + * }; + * + * NOTE: All application protocols should be enumerated in the same + * enum to guarantee application global uniqueness. + * + */ +enum { + F_FSM_PROTOCOL = 1, // state machine protocol (encoded in msb) + F_PORT_PROTOCOL, // port connection protocol + F_GCF_PROTOCOL, // GCF specific protocol numbers start here + F_APL_PROTOCOL = 10, // APPlication specific protocol numbers start here +}; + +// structure for administration of signalnames and errornames. +struct protocolStrings { + unsigned short nrSignals; + unsigned short nrErrors; + const char** signalNames; + const char** errorNames; +}; + +void registerProtocol (unsigned short protID, + const struct protocolStrings& protDef); +string eventName (const GCFEvent& e); +string errorName (unsigned short errorID); + + } // namespace MACIO +} // namespace LOFAR + +#endif diff --git a/MAC/MACIO/include/MACIO/StringVector.h b/MAC/MACIO/include/MACIO/StringVector.h new file mode 100644 index 0000000000000000000000000000000000000000..0abb24d70789beef1f5dc5dc95905d8330ddda17 --- /dev/null +++ b/MAC/MACIO/include/MACIO/StringVector.h @@ -0,0 +1,89 @@ +//# StringVector.h: Wrapper class for protocol files. +//# +//# Copyright (C) 2002-2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef MACIO_STRING_VECTOR_H +#define MACIO_STRING_VECTOR_H + +// \file StringVector.h +// Wrapper class for protocol files. + +//# Never #include <config.h> or #include <lofar_config.h> in a header file! +//# Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> +#include <MACIO/Marshalling.h> + +// Avoid 'using namespace' in headerfiles + +namespace LOFAR { + namespace MACIO { + +// \addtogroup MACIO +// @{ + + +// class_description +class StringVector +{ +public: + StringVector() {}; + ~StringVector() {}; + + unsigned int StringVector::getSize(); + unsigned int StringVector::pack (void *buffer); + unsigned int StringVector::unpack(void *buffer); + + //# --- PUBLIC Datamember --- + vector<string> theVector; +}; + +// @} + +// getSize() +inline unsigned int StringVector::getSize() +{ + unsigned int offset = 0; + MSH_SIZE_VECTOR_STRING(offset, theVector); + return (offset); +} + +// pack() +inline unsigned int StringVector::pack(void *buffer) +{ + unsigned int offset = 0; + MSH_PACK_VECTOR_STRING(buffer, offset, theVector); + return (offset); +} + +// unpack() +inline unsigned int StringVector::unpack(void *buffer) +{ + unsigned int offset = 0; + MSH_UNPACK_VECTOR_STRING(buffer, offset, theVector); + return (offset); +} + + + } // namespace MACIO +} // namespace LOFAR + +#endif diff --git a/MAC/MACIO/src/EventPort.cc b/MAC/MACIO/src/EventPort.cc new file mode 100644 index 0000000000000000000000000000000000000000..db12c0d496e8fa21e187584d9916eb838a01b74e --- /dev/null +++ b/MAC/MACIO/src/EventPort.cc @@ -0,0 +1,434 @@ +//# EventPort.cc: (raw) socket based implementation to exchange Events +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +//# Always #include <lofar_config.h> first! +#include <lofar_config.h> + +//# Includes +#include <Common/LofarLogger.h> +#include <Common/StringUtil.h> +#include <Common/SystemUtil.h> +#include <Common/hexdump.h> +#include <MACIO/MACServiceInfo.h> +#include <MACIO/GCF_Event.h> +#include <MACIO/EventPort.h> +#include <SB_Protocol.ph> +//#include "GSB_Defines.h" + +namespace LOFAR { + namespace MACIO { + +// Note: the difference with GCF-ports is that this port is only based on the +// LCS/Common sockets and does therefor not depend on GCF_Tasks. + +static char receiveBuffer[24*4096]; + +// +// EventPort (name, type, protocol) +// +EventPort::EventPort(const string& aServiceMask, + bool aServerSocket, + int aProtocol, + const string& aHostname, + bool syncCommunication) : + itsPort (0), + itsHost (aHostname), + itsServiceName (_makeServiceName(aServiceMask, 0)), + itsSocket (0), + itsListenSocket (0), + itsBrokerSocket (0), + itsStatus (EP_CREATED), + itsSyncComm (syncCommunication), + itsIsServer (aServerSocket) +{ + if (itsHost.empty() || itsHost == "localhost") { + itsHost = myHostname(false); + } + + // We always need a socket to the serviceBroker for getting a portnumber we may use. + itsBrokerSocket = new Socket("ServiceBroker", itsHost, toString(MAC_SERVICEBROKER_PORT)); + ASSERTSTR(itsBrokerSocket, "can't allocate socket to serviceBroker"); + + _setupConnection(); +} + +// +// ~EventPort +// +EventPort::~EventPort() +{ + if (itsSocket) { + itsSocket->shutdown(); + delete itsSocket; + }; + + if (itsListenSocket) { + itsListenSocket->shutdown(); + delete itsListenSocket; + }; + + if (itsBrokerSocket) { + itsBrokerSocket->shutdown(); + delete itsBrokerSocket; + }; +} + +// +// connect() +// +bool EventPort::connect() +{ + return (_setupConnection()); +} + +// +// _setupConnection() +// +// Depending of the stage that is already reached in the connection process, this +// function tries to continue from there till a connection is made. +// +// Note: all error handling is in this 'overall' routine to keep the subroutines +// that are called as easy as possible. +// +bool EventPort::_setupConnection() +{ + // test most likely state first for performance + if (itsStatus == EP_CONNECTED) { + return (true); + } + + // not connected, so we left somewhere in the connection sequence, pick the sequence + // at the right place. + + // No connection to the SB yet? + if (itsStatus == EP_CREATED) { + LOG_DEBUG ("Trying to make connection with the ServiceBroker"); + itsBrokerSocket->connect(itsSyncComm ? -1 : 500); // try to connect, wait forever or 0.5 sec + if (!itsBrokerSocket->isConnected()) { // failed? + if (itsSyncComm) { + ASSERTSTR(false, "Cannot connect to the ServiceBroker"); + } + return (false); // async socket allows failures. + } + itsStatus = EP_SEES_SB; + itsBrokerSocket->setBlocking(itsSyncComm); // no other tasks, do rest blocking + } + + // second step: ask service broker the portnumber + if (itsStatus == EP_SEES_SB) { + itsStatus += _askBrokerThePortNumber(); + if (itsStatus <= EP_SEES_SB) { + if (itsSyncComm) { + ASSERTSTR(false, "Cannot contact the ServiceBroker"); + } + return (false); // async socket allows failures. + } + } + + // third step: wait for the answer of the SB + if (itsStatus == EP_WAIT_FOR_SB_ANSWER) { + itsStatus += _waitForSBAnswer(); + if (itsStatus <= EP_WAIT_FOR_SB_ANSWER) { + if (itsSyncComm) { + ASSERTSTR(false, "Cannot contact the other party"); + } + return (false); // async socket allows failures. + } + } + + // fourth step: try to connect to the real socket. + if (itsStatus == EP_KNOWS_DEST) { + itsStatus += _startConnectionToPeer(); + if (itsStatus <= EP_KNOWS_DEST) { + if (itsSyncComm) { + ASSERTSTR(false, "Cannot contact the other party"); + } + return (false); // async socket allows failures. + } + } + + // fifth step: wait for response of connection request + if (itsStatus == EP_CONNECTING) { + itsStatus += _waitForPeerResponse(); + if (itsStatus <= EP_CONNECTING) { + if (itsSyncComm) { + ASSERTSTR(false, "Cannot contact the other party"); + } + return (false); // async socket allows failures. + } + } + + return (itsStatus == EP_CONNECTED); +} + +// +// send a message to the message broker requesting a portnumber +// +int32 EventPort::_askBrokerThePortNumber() +{ + // construct the question. + if (itsIsServer) { + // tell SB the name of our service + SBRegisterServiceEvent request; + request.seqnr = 5; // or any other number + request.servicename = itsServiceName; + + // send question + sendEvent(itsBrokerSocket, &request); + } + else { // client socket + // ask SB the portnumber of the (operational) service. + SBGetServiceinfoEvent request; + request.seqnr = 5; // or any other number + request.servicename = itsServiceName; + request.hostname = itsHost; + + // send question + sendEvent(itsBrokerSocket, &request); + } + + return (1); // goto next state +} + +// +// waitForSBAnswer() +// +// Wait until we received a response from the service broker. +// +int32 EventPort::_waitForSBAnswer() +{ + // wait for response + GCFEvent* answerEventPtr(receiveEvent(itsBrokerSocket)); + if (!answerEventPtr) { + return (0); // stay in this mode + } + + // a complete event was received, handle it. + if (itsIsServer) { + SBServiceRegisteredEvent response(*answerEventPtr); + if (response.result != 0) { + LOG_ERROR_STR("Service " << itsServiceName << " is already on the air."); + return (-1); // next time ask again + } + itsPort = response.portnumber; + LOG_DEBUG_STR("Service " << itsServiceName << " will be at port " << itsPort); + // note: keep connection with Broker so he knows we are on the air. + } + else { // client socket + SBServiceInfoEvent response(*answerEventPtr); + if (response.result != 0) { + LOG_ERROR_STR("Service " << itsServiceName << " is unknown"); + return (-1); // next time ask again + } + itsPort = response.portnumber; + LOG_DEBUG_STR("Service " << itsServiceName << " is at port " << itsPort); + + // close connection with Broker. + itsBrokerSocket->shutdown(); + itsBrokerSocket = 0; + } + + return (1); // continue with next stage +} + +// +// _startConnectionToPeer() +// +int32 EventPort::_startConnectionToPeer() +{ + // Finally we can make the real connection + if (itsIsServer) { + LOG_DEBUG_STR ("Opening listener on port " << itsPort); + itsListenSocket = new Socket(itsServiceName, toString(itsPort), Socket::TCP); + itsSocket = itsListenSocket->accept(itsSyncComm ? -1 : 500); + } + else { + LOG_DEBUG_STR ("Trying to make connection with " << itsServiceName); + itsSocket = new Socket(itsServiceName, itsHost, toString(itsPort), Socket::TCP); + itsSocket->connect(itsSyncComm ? -1 : 500); // try to connect, wait forever or 0.5 sec + } + return (1); +} + +// +// _waitForPeerResponse() +// +int32 EventPort::_waitForPeerResponse() +{ + // connection (already) successful? + if (itsSocket->isConnected()) { + itsSocket->setBlocking(itsSyncComm); + return (1); + } + + // do a retry + if (itsIsServer) { + itsSocket = itsListenSocket->accept(itsSyncComm ? -1 : 500); + } + else { + itsSocket->connect(itsSyncComm ? -1 : 500); // try to connect, wait forever or 0.5 sec + } + + return (0); +} + +// +// _peerClosedConnection() +// +void EventPort::_peerClosedConnection() +{ + // yeah.... what is wise to do here???? + ASSERTSTR(false, "Other side closed the connection, bailing out"); + +} + +// +// send(Event*) +// +bool EventPort::send(GCFEvent* anEvent) +{ + if (!_setupConnection()) { + return (false); + } + + sendEvent(itsSocket, anEvent); + return (true); +} + +// +// receive() : Event +// +GCFEvent* EventPort::receive() +{ + return (_setupConnection() ? receiveEvent(itsSocket) : 0L); +} + +// +// _makeServiceName(mask, number) +// +string EventPort::_makeServiceName(const string& aServiceMask, int32 aNumber) +{ + // NOTE: this code is copied from GCF/TM/Port/GCF_PortInterface.cc + string instanceNrStr; + if (aNumber) { + instanceNrStr = toString(aNumber); + } + + return(formatString(aServiceMask.c_str(), instanceNrStr.c_str())); +} + +// -------------------- STATIC FUNCTIONS -------------------- +// +// static sendEvent(Socket*, Event*) +// +void EventPort::sendEvent(Socket* aSocket, + GCFEvent* anEvent) +{ + // Serialize the message and write buffer to port + uint32 packSize; + void* buf = anEvent->pack(packSize); + int32 btsWritten = aSocket->write(buf, packSize); + ASSERTSTR(btsWritten == (int32)packSize, + "Only " << btsWritten << " of " << packSize << " bytes written"); +} + +// +// static receiveEvent(aSocket) +// +GCFEvent* EventPort::receiveEvent(Socket* aSocket) +{ + static int32 gBtsToRead(0); + static int32 gTotalBtsRead(0); + static int32 gReadState(0); + + GCFEvent* header ((GCFEvent*) &receiveBuffer[0]); + int32 btsRead(0); + + // first read signal (= eventtype) field + if (gReadState == 0) { + btsRead = aSocket->read((void*) &(header->signal), sizeof(header->signal)); + if (btsRead < 0) { + _peerClosedConnection(); + return (0); + } + if (btsRead != sizeof(header->signal)) { + if (aSocket->isBlocking()) { + ASSERTSTR(false, "Event-type was not received"); + } + return (0); // async socket allows failures. + } + gReadState++; + } + + // next read the length of the rest of the message + if (gReadState == 1) { + btsRead = aSocket->read((void*) &(header->length), sizeof(header->length)); + if (btsRead < 0) { + _peerClosedConnection(); + return (0); + } + if (btsRead != sizeof(header->length)) { + if (aSocket->isBlocking()) { + ASSERTSTR(false, "Event-length was not received"); + } + return (0); // async socket allows failures. + } + gReadState++; + gBtsToRead = header->length; // get size of data part + } + + // finally read the datapart of the event + if (gReadState == 2) { + LOG_DEBUG_STR("Still " << gBtsToRead << " bytes of data to get"); + + btsRead = 0; + if (gBtsToRead) { + btsRead = aSocket->read(&receiveBuffer[sizeof(GCFEvent) + gTotalBtsRead], gBtsToRead); + if (btsRead < 0) { + _peerClosedConnection(); + return (0); + } + if (btsRead != gBtsToRead) { + if (aSocket->isBlocking()) { + ASSERTSTR(false, "Only " << btsRead << " bytes of msg read: " << gBtsToRead); + } + return (0); // async socket allow failures + } + } + + if (btsRead == gBtsToRead) { // everything received? + // reset own admin + gReadState = 0; + gTotalBtsRead = 0; + gBtsToRead = 0; +// hexdump(receiveBuffer, sizeof(GCFEvent) + header->length); + return (header); + } + } + + // not all information received yet + return (0L); +} + + + } // namespace MACIO +} // namespace LOFAR diff --git a/MAC/MACIO/src/GCF_Event.cc b/MAC/MACIO/src/GCF_Event.cc new file mode 100644 index 0000000000000000000000000000000000000000..d783173d08a24bbf486bb12511085d3b789bdd88 --- /dev/null +++ b/MAC/MACIO/src/GCF_Event.cc @@ -0,0 +1,101 @@ +//# GCF_Event.cc: finite state machine events +//# +//# Copyright (C) 2002-2003 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> + +#include <Common/LofarLogger.h> +#include <MACIO/GCF_Event.h> + +using namespace std; + +namespace LOFAR { + namespace MACIO { + +GCFEvent::~GCFEvent() +{ + if (_buffer) { + delete [] _buffer; + } +} + +void* GCFEvent::pack(uint32& packsize) +{ + // packs the base event fields + memcpy(_buffer, &signal, sizeof(signal)); + memcpy(_buffer + sizeof(signal), &length, sizeof(length)); + packsize = sizeof(signal) + sizeof(length); + return _buffer; +} + +void GCFEvent::resizeBuf(uint32 requiredSize) +{ + // resizes the buffer if needed + if (requiredSize > _upperbound && _buffer) { + delete [] _buffer; + _buffer = 0; + } + if (!_buffer) { + _buffer = new char[requiredSize]; + _upperbound = requiredSize; + } + length = requiredSize - sizeof(length) - sizeof(signal); +} + +void* GCFEvent::unpackMember(char* data, uint32& offset, uint32& memberNOE, uint32 sizeofMemberType) +{ + void* seqPtr(0); + memcpy(&memberNOE, data + offset, sizeof(memberNOE)); + seqPtr = data + offset + sizeof(memberNOE); + offset += sizeof(memberNOE) + (memberNOE * sizeofMemberType); + return seqPtr; +} + +uint32 GCFEvent::packMember(uint32 offset, const void* member, uint32 memberNOE, uint32 sizeofMemberType) +{ + ASSERT(_buffer); + memcpy(_buffer + offset, &memberNOE, sizeof(memberNOE)); + offset += sizeof(memberNOE); + if (memberNOE > 0) { + memcpy(_buffer + offset, member, memberNOE * sizeofMemberType); + } + return (memberNOE * sizeofMemberType) + sizeof(memberNOE); +} + +uint32 GCFEvent::unpackString(string& value, char* buffer) +{ + uint16 stringLength(0); + memcpy((void *) &stringLength, buffer, sizeof(stringLength)); + value.clear(); + value.append(buffer + sizeof(stringLength), stringLength); + return stringLength + sizeof(stringLength); +} + +uint32 GCFEvent::packString(char* buffer, const string& value) +{ + uint16 stringLength(value.size()); + uint32 neededBufLength = value.size() + sizeof(stringLength); + memcpy(buffer, (void *) &stringLength, sizeof(stringLength)); + memcpy(buffer + sizeof(stringLength), (void *) value.c_str(), value.size()); + return neededBufLength; +} + } // namespace MACIO +} // namespace LOFAR diff --git a/MAC/MACIO/src/KVT_Protocol.prot b/MAC/MACIO/src/KVT_Protocol.prot index 3d26095ee13a202dd7ac25790b5e21c81b0b701c..a5e9e3a84d49e96be1883d71e57aa5ba5d21a49f 100644 --- a/MAC/MACIO/src/KVT_Protocol.prot +++ b/MAC/MACIO/src/KVT_Protocol.prot @@ -24,10 +24,10 @@ autogen definitions protocol; description = "Protocol for sending Key-Value-Time triples to the KeyValueLogger"; prefix = "KVT"; // for the signal names -id = "(LOFAR::GCF::TM::F_GCF_PROTOCOL + 1)"; +id = "(LOFAR::MACIO::F_GCF_PROTOCOL + 1)"; // specify extra include files -include = '<APL/RTCCommon/StringVector.h>'; +include = '<MACIO/StringVector.h>'; prelude = << PRELUDE_END @@ -115,12 +115,12 @@ event = { }; param = { name = "keys"; - type = "RTC::StringVector"; + type = "MACIO::StringVector"; userdefined; }; param = { name = "values"; - type = "RTC::StringVector"; + type = "MACIO::StringVector"; userdefined; }; }; diff --git a/MAC/MACIO/src/LOG_Protocol.prot b/MAC/MACIO/src/LOG_Protocol.prot index 07b0eb82a4a72bbd2c5b87ada2db156f282c58bd..db42271361a8adf789a1d7209585f6c94e139e13 100644 --- a/MAC/MACIO/src/LOG_Protocol.prot +++ b/MAC/MACIO/src/LOG_Protocol.prot @@ -24,11 +24,11 @@ autogen definitions protocol; description = "Protocol definition for sending LogMessages to a LoggingProcessor"; prefix = "LOG"; // for the signal names -id = "(LOFAR::GCF::TM::F_GCF_PROTOCOL + 0)"; +id = "(LOFAR::MACIO::F_GCF_PROTOCOL + 0)"; // specify extra include files // e.g. //include = '<sys/time.h>'; -include = '<APL/RTCCommon/StringVector.h>'; +include = '<MACIO/StringVector.h>'; prelude = << PRELUDE_END @@ -83,12 +83,12 @@ event = { }; param = { name = "DPnames"; - type = "RTC::StringVector"; + type = "MACIO::StringVector"; userdefined; }; param = { name = "messages"; - type = "RTC::StringVector"; + type = "MACIO::StringVector"; userdefined; }; }; diff --git a/MAC/MACIO/src/Makefile.am b/MAC/MACIO/src/Makefile.am index 52f2cb642afd59d77286b4f03ac148369aa72a04..4fe18fc6b75e8c037134e2a72d3ac302bfee0243 100644 --- a/MAC/MACIO/src/Makefile.am +++ b/MAC/MACIO/src/Makefile.am @@ -1,23 +1,25 @@ AUTOGEN = autogen SUFFIXES = .ph %.ph: %.prot - $(AUTOGEN) --writable -L $(datadir)/GCF/TM $< + $(AUTOGEN) --writable -L $(datadir)/MACIO $< cp $*.ph $(top_builddir)/include/MACIO/ %.cc: %.prot - $(AUTOGEN) --writable -L $(datadir)/GCF/TM $< + $(AUTOGEN) --writable -L $(datadir)/MACIO $< clean-local: rm -f *.ph bin_PROGRAMS = bin_SCRIPTS = -INSTHDRS = LOG_Protocol.ph KVT_Protocol.ph +INSTHDRS = LOG_Protocol.ph KVT_Protocol.ph SB_Protocol.ph NOINSTHDRS = BUILT_SOURCES = LOG_Protocol.cc \ LOG_Protocol.ph \ KVT_Protocol.cc \ - KVT_Protocol.ph + KVT_Protocol.ph \ + SB_Protocol.cc \ + SB_Protocol.ph pkgincludedir = $(includedir)/MACIO pkginclude_HEADERS = $(NOINSTHDRS) $(INSTHDRS) @@ -25,9 +27,12 @@ DOCHDRS = $(pkginclude_HEADERS) $(BUILT_SOURCES) EXTRA_DIST = $(configfiles_DATA) $(sysconf_DATA) # Libraries -lib_LTLIBRARIES = liblog_protocol.la libkvt_protocol.la +lib_LTLIBRARIES = liblog_protocol.la \ + libkvt_protocol.la \ + libmacio.la liblog_protocol_la_SOURCES = LOG_Protocol.cc libkvt_protocol_la_SOURCES = KVT_Protocol.cc +libmacio_la_SOURCES = GCF_Event.cc EventPort.cc ProtocolDefs.cc SB_Protocol.cc #in case of make install these files will be copied to the bindir beside the test apps configfilesdir = $(bindir) diff --git a/MAC/MACIO/src/ProtocolDefs.cc b/MAC/MACIO/src/ProtocolDefs.cc new file mode 100644 index 0000000000000000000000000000000000000000..66334d64e59af9d7918b342756dc72d6d0a0cb22 --- /dev/null +++ b/MAC/MACIO/src/ProtocolDefs.cc @@ -0,0 +1,75 @@ +//# ProtocolDefs.cc: Generic protocol related routines +//# +//# Copyright (C) 2007-2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +//# Always #include <lofar_config.h> first! +#include <lofar_config.h> +#include <Common/LofarLogger.h> +#include <Common/lofar_map.h> +#include <Common/StringUtil.h> +#include <MACIO/ProtocolDefs.h> + +namespace LOFAR { + namespace MACIO { + +typedef map<unsigned short, const struct protocolStrings*> protStringsMap; +static protStringsMap _protNameTable; + +// +// registerProtocol(protID, protocolStrings) +// +void registerProtocol (unsigned short protID, + const struct protocolStrings& protDef) +{ + _protNameTable[protID] = &protDef; + LOG_DEBUG_STR ("registered protocol: " << protID); +} + +// +// eventName(event&) +// +string eventName(const GCFEvent& e) +{ + protStringsMap::const_iterator iter = _protNameTable.find(F_EVT_PROTOCOL(e)); + if ((iter != _protNameTable.end()) && (F_EVT_SIGNAL(e) <= iter->second->nrSignals)) { + return ((iter->second->signalNames)[F_EVT_SIGNAL(e)]); + } + + return (formatString("unknown signal(protocol=%d, signal=%d)", + F_EVT_PROTOCOL(e), F_EVT_SIGNAL(e))); +} + +// +// errorName(errorNr) +// +string errorName(unsigned short errorID) +{ + protStringsMap::const_iterator iter = _protNameTable.find(F_ERR_PROTOCOL(errorID)); + if ((iter != _protNameTable.end()) && (F_ERR_NR(errorID) <= iter->second->nrErrors)) { + return ((iter->second->errorNames)[F_ERR_NR(errorID)]); + } + + return (formatString("unknown error(protocol=%d, error=%d)", + F_ERR_PROTOCOL(errorID), F_ERR_NR(errorID))); +} + + } // namespace MACIO +} // namespace LOFAR diff --git a/MAC/MACIO/src/SB_Protocol.prot b/MAC/MACIO/src/SB_Protocol.prot new file mode 100644 index 0000000000000000000000000000000000000000..ecb81edda5d86d4b254522e290d240ea806cc149 --- /dev/null +++ b/MAC/MACIO/src/SB_Protocol.prot @@ -0,0 +1,190 @@ +//# SB_Protocol.prot: Protocol definition for the Service Broker Daemon +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +autogen definitions protocol; + +description = "Protocol for the Service Broker deamon"; +prefix = "SB"; // for the signal names +id = "(LOFAR::MACIO::F_GCF_PROTOCOL + 3)"; + +// specify extra include files +// include = '<someFile.h>'; + +prelude = << PRELUDE_END + +// The following messages are defined in the servicebroker protocol +// +// REGISTER_SERVICE (uint16 seqnr, string servicename); +// SERVICE_REGISTERED (uint16 seqnr, int32 portNumber, uint16 result); +// GET_SERVICEINFO (uint16 seqnr, string servicename, string hostname); +// SERVICE_INFO (uint16 seqnr, int32 portNumber, string hostname, uint16 result); +// UNREGISTER_SERVICE (uint16 seqnr, string servicename); +// SERVICE_UNREGISTERED(uint16 seqnr, uint16 result); +// REREGISTER_SERVICE (uint16 seqnr, string servicename, int32 portNumber); +// SERVICE_REREGISTERED(uint16 seqnr, uint16 result); +// + +enum { + SB_NO_ERROR, + SB_UNKNOWN_ERROR, + SB_SERVICE_ALREADY_EXIST, + SB_NO_FREE_PORTNR, + SB_UNKNOWN_SERVICE, + SB_NO_CONNECTION, + SB_CANT_RECOVER +}; + +PRELUDE_END; + +// +// An "event" has a "signal" and a "dir" (direction) +// and zero or more "param"s. +// "dir" can be one of "IN" or "OUT". +// A "param" has a "name" and a "type". +// +event = { + signal = REGISTER_SERVICE; + dir = IN; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "servicename"; + type = "string"; + }; +}; + +event = { + signal = UNREGISTER_SERVICE; + dir = IN; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "servicename"; + type = "string"; + }; +}; + +event = { + signal = GET_SERVICEINFO; + dir = IN; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "servicename"; + type = "string"; + }; + param = { + name = "hostname"; + type = "string"; + }; +}; + +event = { + signal = SERVICE_REGISTERED; + dir = OUT; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "portnumber"; + type = "uint32"; + }; + param = { + name = "result"; + type = "uint16"; + }; +}; + +event = { + signal = SERVICE_INFO; + dir = OUT; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "portnumber"; + type = "uint32"; + }; + param = { + name = "hostname"; + type = "string"; + }; + param = { + name = "result"; + type = "uint16"; + }; +}; + +event = { + signal = SERVICE_UNREGISTERED; + dir = OUT; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "result"; + type = "uint16"; + }; +}; + +event = { + signal = REREGISTER_SERVICE; + dir = IN; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "servicename"; + type = "string"; + }; + param = { + name = "portnumber"; + type = "uint32"; + }; +}; + +event = { + signal = SERVICE_REREGISTERED; + dir = OUT; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "servicename"; + type = "string"; + }; + param = { + name = "result"; + type = "uint16"; + }; +}; diff --git a/MAC/MACIO/test/Echo_Protocol.prot b/MAC/MACIO/test/Echo_Protocol.prot new file mode 100644 index 0000000000000000000000000000000000000000..5bf428ce075d32041b6115f7e1635c860472ebc6 --- /dev/null +++ b/MAC/MACIO/test/Echo_Protocol.prot @@ -0,0 +1,57 @@ +// +// Protocol definition for the Echo server +// +autogen definitions protocol; + +description = "Protocol for the Echo server"; +prefix = "Echo"; // for the signal names +id = "LOFAR::MACIO::F_APL_PROTOCOL"; +// specify extra include files +// e.g. +include = '<sys/time.h>'; + +// +// An "event" has a "signal" and a "dir" (direction) +// and zero or more "param"s. +// "dir" can be one of "IN" or "OUT". +// A "param" has a "name" and a "type". +// +event = { + signal = PING; + dir = IN; + param = { + name = "seqnr"; + type = "unsigned int"; + }; + param = { + name = "ping_time"; + type = "timeval"; + }; +}; + +event = { + signal = ECHO; + dir = OUT; + param = { + name = "seqnr"; + type = "unsigned int"; + }; + param = { + name = "ping_time"; + type = "timeval"; + }; + param = { + name = "echo_time"; + type = "timeval"; + }; +}; + +event = { + signal = CLOCK; + dir = OUT; + noheader; + param = { + name = clockpulse; + type = char; + }; +}; diff --git a/MAC/MACIO/test/Makefile.am b/MAC/MACIO/test/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..d135bd052ee74d54ee7d0521d1cb56810fd2d4d9 --- /dev/null +++ b/MAC/MACIO/test/Makefile.am @@ -0,0 +1,32 @@ +AUTOGEN = autogen +SUFFIXES = .ph +%.ph: %.prot + $(AUTOGEN) --writable -L $(top_srcdir)/autogen $< + +%.cc: %.prot + $(AUTOGEN) --writable -L $(top_srcdir)/autogen $< + +check_PROGRAMS = tEventPort tProtocol + +tProtocol_SOURCES = testprotocol.ph testprotocol.cc \ + Echo_Protocol.ph Echo_Protocol.cc \ + tProtocol.cc +tProtocol_LDADD = ../src/libmacio.la +tProtocol_DEPENDENCIES = ../src/libmacio.la $(LOFAR_DEPEND) + +tEventPort_SOURCES = Echo_Protocol.ph Echo_Protocol.cc \ + tEventPort.cc +tEventPort_LDADD = ../src/libmacio.la +tEventPort_DEPENDENCIES = ../src/libmacio.la $(LOFAR_DEPEND) + +BUILT_SOURCES = Echo_Protocol.ph testprotocol.ph + +EXTRA_DIST = tProtocol.log_prop + +clean-local: + rm -f *.ph + +include $(top_srcdir)/Makefile.common + + + diff --git a/MAC/MACIO/test/tEventPort.cc b/MAC/MACIO/test/tEventPort.cc new file mode 100644 index 0000000000000000000000000000000000000000..f8a994a9f2df5948c3d3c5c8d47442c2e09b73a8 --- /dev/null +++ b/MAC/MACIO/test/tEventPort.cc @@ -0,0 +1,101 @@ +//# tEventPort.cc: Program to test the EventPort class +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> +#include <Common/LofarLogger.h> +#include <MACIO/EventPort.h> +#include <MACIO/MACServiceInfo.h> +#include "Echo_Protocol.ph" + +using namespace LOFAR; +using namespace LOFAR::MACIO; + +static EchoPingEvent pingEvent; +static EventPort* echoPort; + +int main (int32 argc, char*argv[]) +{ + bool syncMode; + switch (argc) { + case 2: + syncMode = (argv[1][0] == 's' || argv[1][0] == 'S'); + break; + default: + cout << "Syntax: " << argv[0] << " a | s" << endl; + cout << " the argument ('a' or 's') chooses the asynchrone or synchrone behaviour" << endl + << "of the EventPort. The synchrone mode expects the ServiceBroker and the" << endl + << "Echo server running. If not it will assert. In this mode the EventPort" << endl + << "wait forever for the answer." << endl + << "In asynchrone mode the EventPort will never complain and try forever to" << endl + << "reach each of the connection stages and receive the messages. You can" << endl + << "check the EventPort.status() to see in what state the port is." << endl; + return (1); + } + + INIT_LOGGER("tEventPort"); + + // open port + LOG_DEBUG_STR ("Operating in " << ((syncMode) ? "" : "a") << "synchrone mode."); + echoPort = new EventPort("ECHO:EchoServer", false, ECHO_PROTOCOL, "", syncMode); + + // construct event + pingEvent.seqnr = 25; + timeval pingTime; + gettimeofday(&pingTime, 0); + pingEvent.ping_time = pingTime; + + LOG_DEBUG("sending the ping event"); + if (syncMode) { + // NOTE: we could also use the while-loop of the asyncmode here. + echoPort->send(&pingEvent); + } + else { + while (!echoPort->send(&pingEvent)) { + cout << "state = " << echoPort->getStatus() << endl; + sleep (1); + ; + } + } + + LOG_DEBUG("going to wait for the answer event"); + GCFEvent* ackPtr; + if (syncMode) { + // NOTE: we could also use the while-loop of the asyncmode here. + ackPtr = echoPort->receive(); + } + else { + while (!(ackPtr = echoPort->receive())) { + cout << "state = " << echoPort->getStatus() << endl; + sleep (1); + ; + } + } + EchoEchoEvent ack(*ackPtr); + + LOG_DEBUG_STR("seqnr: " << ack.seqnr); + double delta = (1.0 * ack.echo_time.tv_sec + (ack.echo_time.tv_usec / 1000000.0)); + delta -= (1.0 * ack.ping_time.tv_sec + (ack.ping_time.tv_usec / 1000000.0)); + LOG_DEBUG_STR("dTime: " << delta << " sec"); + + return (0); +} + diff --git a/MAC/MACIO/test/tMarshalling.cc b/MAC/MACIO/test/tMarshalling.cc new file mode 100644 index 0000000000000000000000000000000000000000..663a159e14912e09be6e8145845eaa7329b58045 --- /dev/null +++ b/MAC/MACIO/test/tMarshalling.cc @@ -0,0 +1,311 @@ +//# tMarshalling.cc: test pack and unpack macros +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +//# Always #include <lofar_config.h> first! +#include <lofar_config.h> + +//# Includes +#include <Common/LofarLogger.h> +#include <Common/lofar_bitset.h> +#include <Common/lofar_map.h> +#include <Common/hexdump.h> +#include <APL/RTCCommon/Marshalling.h> +#include "tMarshalling.h" + +using namespace LOFAR; + +namespace LOFAR { + +SubArray::SubArray(int i, double d, string s) : + someInt(i), someDouble(d), someString(s) +{ +} + +unsigned int SubArray::getSize() { + return (sizeof(int) + sizeof(double) + MSH_STRING_SIZE(someString)); +} + +unsigned int SubArray::pack(void* buffer) { + unsigned int offset = 0; + memcpy(((char*)(buffer)+offset), &someInt, sizeof(int)); + offset += sizeof (int); + memcpy(((char*)(buffer)+offset), &someDouble, sizeof(double)); + offset += sizeof (double); + MSH_PACK_STRING(buffer, offset, someString); + + return (offset); +} + +unsigned int SubArray::unpack(void* buffer) { + unsigned int offset = 0; + memcpy(&someInt, ((char*)(buffer))+offset, sizeof(int)); + offset += sizeof(int); + memcpy(&someDouble, ((char*)(buffer))+offset, sizeof(double)); + offset += sizeof(double); + MSH_UNPACK_STRING(buffer, offset, someString); + return (offset); +} + +SubArrayNC::SubArrayNC(int i, double d, string s) : + someInt(i), someDouble(d), someString(s) +{ +} + +unsigned int SubArrayNC::getSize() { + return (sizeof(int) + sizeof(double) + MSH_STRING_SIZE(someString)); +} + +unsigned int SubArrayNC::pack(void* buffer) { + unsigned int offset = 0; + memcpy(((char*)(buffer)+offset), &someInt, sizeof(int)); + offset += sizeof (int); + memcpy(((char*)(buffer)+offset), &someDouble, sizeof(double)); + offset += sizeof (double); + MSH_PACK_STRING(buffer, offset, someString); + + return (offset); +} + +unsigned int SubArrayNC::unpack(void* buffer) { + unsigned int offset = 0; + memcpy(&someInt, ((char*)(buffer))+offset, sizeof(int)); + offset += sizeof(int); + memcpy(&someDouble, ((char*)(buffer))+offset, sizeof(double)); + offset += sizeof(double); + MSH_UNPACK_STRING(buffer, offset, someString); + return (offset); +} + + +} // namespace LOFAR + +int main (int argc, char* argv[]) +{ + // string test + string tstString("Dit is een teststring"); + cout << "Testing string: " << tstString << endl; + + cout << "size = " << MSH_STRING_SIZE(tstString) << endl; + + char buf[4096]; + int32 offset(0); + MSH_PACK_STRING(buf, offset, tstString); + cout << "packed: " << endl; + hexdump(buf, offset); + + string newString; + offset = 0; + MSH_UNPACK_STRING(buf, offset, newString); + cout << "unpacked: " << newString << endl; + + // bitmap test1 + bitset<32> bs1; + bs1.reset(); + bs1.set(0); + bs1.set(5); + bs1.set(20); + cout << "Testing bitset<32>" << bs1 << endl; + + cout << "size = " << MSH_BITSET_SIZE(bs1) << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_BITSET(buf, offset, bs1); + cout << "packed:" << endl; + hexdump(buf, offset); + + bitset<32> bs2; + offset = 0; + MSH_UNPACK_BITSET(buf, offset, bs2); + cout << "unpacked: " << bs2 << endl; + + // blitz array <double> + blitz::Array<double, 2> ba1(2,4); + ba1 = 10, 11, + 20, 21, + 30, 31, + 40, 41; + cout << "Testing blitz::Array<double, 2>" << ba1 << endl; + + cout << "size = " << MSH_ARRAY_SIZE(ba1, double) << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_ARRAY(buf, offset, ba1, double); + cout << "packed:" << endl; + hexdump(buf, offset); + + blitz::Array<double, 2> ba2(2,4); + offset = 0; + MSH_UNPACK_ARRAY(buf, offset, ba2, double, 2); + cout << "unpacked: " << ba2 << endl; + + // blitz array <int> + blitz::Array<int, 2> emptyArr; + cout << "Testing EMPTY blitz::Array<int, 2>" << emptyArr << endl; + + cout << "size = " << MSH_ARRAY_SIZE(emptyArr, int) << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_ARRAY(buf, offset, emptyArr, int); + cout << "packed:" << endl; + hexdump(buf, offset); + + blitz::Array<int, 2> empty2; + offset = 0; + MSH_UNPACK_ARRAY(buf, offset, empty2, int, 2); + cout << "unpacked: " << empty2 << endl; + + // SubArray + SubArray SA1(25, 3.14, "stringetje"); + cout << "Testing SubArray class:" << SA1.someInt << "," << SA1.someDouble + << "," << SA1.someString << endl; + + unsigned int size(SA1.getSize()); + cout << "size = " << size << endl; + + bzero(buf, 4096); + offset = 0; + SA1.pack(buf); + cout << "packed:" << endl; + hexdump(buf, size); + + SubArray SA2; + offset = 0; + SA2.unpack(buf); + cout << "unpacked: " << SA2.someInt << "," << SA2.someDouble + << "," << SA2.someString << endl; + + + // map<string, subArray> + map<string, SubArray> ms1; + ms1["eerste_item"] = SubArray(25, 3.14, "stringetje"); + ms1["tweede_item"] = SubArray(0, 32, "ejtegnirts"); + cout << "Testing map<string, SubArray>: " << endl; + map<string, SubArray>::iterator iter = ms1.begin(); + map<string, SubArray>::iterator end = ms1.end(); + while (iter != end) { + cout << "map[" << iter->first << "]:" << iter->second.someInt << "," << + iter->second.someDouble << "," << iter->second.someString << endl; + iter++; + } + + unsigned int mapsize; + MSH_SIZE_MAP_STRING_CLASS(mapsize, ms1, SubArray); + cout << "size = " << mapsize << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_MAP_STRING_CLASS(buf, offset, ms1, SubArray); + cout << "packed:" << endl; + hexdump(buf, mapsize); + + map<string, SubArray> ms2; + offset = 0; + MSH_UNPACK_MAP_STRING_CLASS(buf, offset, ms2, SubArray); + cout << "Unpacked map<string, SubArray>: " << endl; + map<string, SubArray>::iterator iter2 = ms2.begin(); + map<string, SubArray>::iterator end2 = ms2.end(); + while (iter2 != end2) { + cout << "map[" << iter2->first << "]:" << iter2->second.someInt << "," << + iter2->second.someDouble << "," << iter2->second.someString << endl; + iter2++; + } + + + // map<string, subArrayNC*> + map<string, SubArrayNC*> msanc1; + msanc1["eerste_item"] = new SubArrayNC(25, 3.14, "stringetje"); + msanc1["tweede_item"] = new SubArrayNC(0, 32, "ejtegnirts"); + cout << "Testing map<string, SubArrayNC*>: " << endl; + map<string, SubArrayNC*>::iterator iternc = msanc1.begin(); + map<string, SubArrayNC*>::iterator endnc = msanc1.end(); + while (iternc != endnc) { + cout << "map[" << iternc->first << "]:" << iternc->second->someInt << "," << + iternc->second->someDouble << "," << iternc->second->someString << endl; + iternc++; + } + + unsigned int mapncsize; + MSH_SIZE_MAP_STRING_CLASSPTR(mapncsize, msanc1, SubArrayNC); + cout << "size = " << mapncsize << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_MAP_STRING_CLASSPTR(buf, offset, msanc1, SubArrayNC); + cout << "packed:" << endl; + hexdump(buf, mapncsize); + + map<string, SubArrayNC*> msanc2; + offset = 0; + MSH_UNPACK_MAP_STRING_CLASSPTR(buf, offset, msanc2, SubArrayNC); + cout << "Unpacked map<string, SubArrayNC*>: " << endl; + iternc = msanc2.begin(); + endnc = msanc2.end(); + while (iternc != endnc) { + cout << "map[" << iternc->first << "]:" << iternc->second->someInt << "," << + iternc->second->someDouble << "," << iternc->second->someString << endl; + iternc++; + } + + + // vector<string> + vector<string> sv1; + sv1.push_back("piet hein"); + sv1.push_back("nelson"); + sv1.push_back("van Swieten"); + cout << "Testing vector<string>" << endl; + vector<string>::iterator itersv = sv1.begin(); + vector<string>::iterator endsv = sv1.end(); + int i = 0; + while (itersv != endsv) { + cout << "vector[" << i << "]:" << *itersv << endl; + i++; + itersv++; + } + + unsigned int svsize; + MSH_SIZE_VECTOR_STRING(svsize, sv1); + cout << "size = " << svsize << endl; + + bzero(buf, 4096); + offset = 0; + MSH_PACK_VECTOR_STRING(buf, offset, sv1); + cout << "packed:" << endl; + hexdump(buf, svsize); + + vector<string> sv2; + offset = 0; + MSH_UNPACK_VECTOR_STRING(buf, offset, sv2); + cout << "Unpacked vector<string>" << endl; + itersv = sv2.begin(); + endsv = sv2.end(); + i = 0; + while (itersv != endsv) { + cout << "vector[" << i << "]:" << *itersv << endl; + i++; + itersv++; + } + + return (0); +} diff --git a/MAC/MACIO/test/tMarshalling.h b/MAC/MACIO/test/tMarshalling.h new file mode 100644 index 0000000000000000000000000000000000000000..c8acab445f96fda48fe5fbf85c2c91356da0bbdb --- /dev/null +++ b/MAC/MACIO/test/tMarshalling.h @@ -0,0 +1,78 @@ +//# tMarshalling.h: test pack and unpack routines. +//# +//# Copyright (C) 2007 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef RTC_TMARSHALLING_H +#define RTC_TMARSHALLING_H + +// \file tMarshalling.h +// test pack and unpack macros + +//# Never #include <config.h> or #include <lofar_config.h> in a header file! +//# Includes +//#include <otherPackage/file.h> + +// Avoid 'using namespace' in headerfiles + +namespace LOFAR { + +//# --- Forward Declarations --- +//# classes mentioned as parameter or returntype without virtual functions. +//class ...; + + +// class_description +// ... + +class SubArray +{ +public: + int someInt; + double someDouble; + string someString; + + SubArray(int i, double d, string s); + SubArray() {}; + unsigned int getSize(); + unsigned int pack(void* buffer); + unsigned int unpack(void* buffer); +}; + +class SubArrayNC +{ +public: + int someInt; + double someDouble; + string someString; + + SubArrayNC(int i, double d, string s); + SubArrayNC() {}; + unsigned int getSize(); + unsigned int pack(void* buffer); + unsigned int unpack(void* buffer); +private: + // prevent copy + SubArrayNC(const SubArrayNC&); +}; + +} // namespace LOFAR + +#endif diff --git a/MAC/MACIO/test/tProtocol.cc b/MAC/MACIO/test/tProtocol.cc new file mode 100644 index 0000000000000000000000000000000000000000..7a7a02d713af36123ec2c1bb6c5eb881081bea1f --- /dev/null +++ b/MAC/MACIO/test/tProtocol.cc @@ -0,0 +1,61 @@ +//# tProtocol.cc +//# +//# Copyright (C) 2002-2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +//# Always #include <lofar_config.h> first! +#include <lofar_config.h> + +//# Includes +#include <Common/LofarLogger.h> +#include "testprotocol.ph" +#include "Echo_Protocol.ph" + +using namespace LOFAR; +using namespace LOFAR::MACIO; + +int main (int argc, char* argv[]) +{ + INIT_LOGGER(argv[0]); + + LOG_INFO_STR ("TESTPROTOCOL has id: " << TESTPROTOCOL); + + TEST_PTCTestInEvent inEvent; + + LOG_INFO("Trying to print an errormsg before registering the protocol"); + LOG_INFO_STR("errornr: " << TEST_PTC_WINDOWS_ERR << " = " + << errorName (TEST_PTC_WINDOWS_ERR)); + LOG_INFO_STR("eventname of in-event: " << eventName(inEvent)); + + LOG_INFO("--- Registering the testprotocol ---"); + registerProtocol (TESTPROTOCOL, TESTPROTOCOL_STRINGS); + LOG_INFO(formatString("errornr: %d = %s", TEST_PTC_WINDOWS_ERR, + errorName (TEST_PTC_WINDOWS_ERR).c_str())); + LOG_INFO_STR("signalname of in-event: " << eventName(inEvent)); + + LOG_INFO ("Registering a second protocol"); + registerProtocol (ECHO_PROTOCOL, ECHO_PROTOCOL_STRINGS); + + EchoPingEvent pingEvent; + LOG_INFO_STR("signalname of ping-event: " << eventName(pingEvent)); + + return (0); +} + diff --git a/MAC/MACIO/test/tProtocol.log_prop b/MAC/MACIO/test/tProtocol.log_prop new file mode 100644 index 0000000000000000000000000000000000000000..642b26cfd88e17b84221cb7b5a26e663fe77ddac --- /dev/null +++ b/MAC/MACIO/test/tProtocol.log_prop @@ -0,0 +1,11 @@ + +# Configure the rootLogger +log4cplus.rootLogger=DEBUG, STDOUT +# Define the STDOUT appender +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%-5p - %m%n + +# Define foo at level TRACE4 +#log4cplus.logger.TRC=TRACE4 + diff --git a/MAC/MACIO/test/testprotocol.prot b/MAC/MACIO/test/testprotocol.prot new file mode 100644 index 0000000000000000000000000000000000000000..fab32b28692fee7f0c1a05bd7765d215592d9d24 --- /dev/null +++ b/MAC/MACIO/test/testprotocol.prot @@ -0,0 +1,85 @@ +//# testprotocol.prot: Protocol definition to test the base functions +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +autogen definitions protocol; + +description = "Protocol for testing the prtocol-programs"; +prefix = "TEST_PTC"; // for the signal names +id = "63"; + +// specify extra include files + +prelude = << PRELUDE_END + +// The following messages are defined in the servicebroker protocol +// +// TEST_IN (uint16 seqnr, string question); +// TEST_OUT (uint16 seqnr, string answer); +// + +PRELUDE_END; + +// +// An "event" has a "signal" and a "dir" (direction) +// and zero or more "param"s. +// "dir" can be one of "IN" or "OUT". +// A "param" has a "name" and a "type". +// +event = { + signal = TEST_IN; + dir = IN; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "question"; + type = "string"; + }; +}; + +event = { + signal = TEST_OUT; + dir = OUT; + param = { + name = "seqnr"; + type = "uint16"; + }; + param = { + name = "answer"; + type = "string"; + }; +}; + +error = { + id = NO; + msg = "No errors"; +}; +error = { + id = RANGE; + msg = "Illegal range specified"; +}; +error = { + id = WINDOWS; + msg = "You are using Windows"; +}; +