[esnacc-dev,v0] cxxlib: Add ROSE definitions

Message ID 20170605154644.16255-1-aconole@bytheb.org
State Superseded
Delegated to: Sagara Wickramasekara
Headers show

Commit Message

Aaron Conole June 5, 2017, 3:46 p.m.
This commit adds an initial implementation of the Remote Operations Service
Element (ROSE) to the esnacc compiler.  This is based on work contributed by
estos GmbH.  This initial implementation does not have compiler support.
It is merely the library portion for the C++ library.

Note that there is currently an auto-assigned operation ID based on hash.  I
haven't looked at whether ROSE would support this, or if manually assigned
operation IDs is required by the standard.  If so, I'll need to rework the
API slightly, but the idea was to keep the user away from needing that
information.

This commit does not:
 - implement the invoke, response, reject, error state machines.
 - add tests

Signed-off-by: Aaron Conole <aconole@bytheb.org>
CC: Stephen Eckbauer <ste@estos.de>
---
 NEWS                          |   1 +
 asn1specs/snaccrose.asn       | 121 +++++++++++++++++++++++
 cxx-lib/.gitignore            |   5 +-
 cxx-lib/automake.mk           |  56 ++++++++++-
 cxx-lib/inc/asn-rose.h        | 163 +++++++++++++++++++++++++++++++
 cxx-lib/libesnaccxxrose.pc.in |  14 +++
 cxx-lib/src/asn-rose.cpp      | 219 ++++++++++++++++++++++++++++++++++++++++++
 debian/libesnacc-dev.install  |   3 +
 debian/libesnacc180.install   |   3 +
 redhat/esnacc.spec.in         |   4 +
 snacc.h.in                    |   7 ++
 11 files changed, 590 insertions(+), 6 deletions(-)
 create mode 100644 asn1specs/snaccrose.asn
 create mode 100644 cxx-lib/inc/asn-rose.h
 create mode 100644 cxx-lib/libesnaccxxrose.pc.in
 create mode 100644 cxx-lib/src/asn-rose.cpp

Comments

Aaron Conole June 5, 2017, 3:48 p.m. | #1
Aaron Conole <aconole@bytheb.org> writes:

> This commit adds an initial implementation of the Remote Operations Service
> Element (ROSE) to the esnacc compiler.  This is based on work contributed by
> estos GmbH.  This initial implementation does not have compiler support.
> It is merely the library portion for the C++ library.
>
> Note that there is currently an auto-assigned operation ID based on hash.  I
> haven't looked at whether ROSE would support this, or if manually assigned
> operation IDs is required by the standard.  If so, I'll need to rework the
> API slightly, but the idea was to keep the user away from needing that
> information.
>
> This commit does not:
>  - implement the invoke, response, reject, error state machines.
>  - add tests
>
> Signed-off-by: Aaron Conole <aconole@bytheb.org>
> CC: Stephen Eckbauer <ste@estos.de>
> ---

This has been compile-tested on Fedora 25, and via travis-ci.

I haven't done any of the debian packaging work to include the new
library.

Thanks,
-Aaron
Aaron Conole June 13, 2017, 2:54 p.m. | #2
Aaron Conole <aconole@bytheb.org> writes:

> This commit adds an initial implementation of the Remote Operations Service
> Element (ROSE) to the esnacc compiler.  This is based on work contributed by
> estos GmbH.  This initial implementation does not have compiler support.
> It is merely the library portion for the C++ library.
>
> Note that there is currently an auto-assigned operation ID based on hash.  I
> haven't looked at whether ROSE would support this, or if manually assigned
> operation IDs is required by the standard.  If so, I'll need to rework the
> API slightly, but the idea was to keep the user away from needing that
> information.
>
> This commit does not:
>  - implement the invoke, response, reject, error state machines.
>  - add tests
>
> Signed-off-by: Aaron Conole <aconole@bytheb.org>
> CC: Stephen Eckbauer <ste@estos.de>
> ---

Actually - I will mark this patch superceded.  Thanks.

Patch

diff --git a/NEWS b/NEWS
index a18b389..1b5a62c 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@  Future
 * c++-lib: File Descriptor streambuffer
 * c++-lib: streambuf monitor
 * c++-lib: IOManipulator based encoding/decoding
+* c++-lib: ROSE support infrastructure
 * documentation: Developer's guides
 * esnacc-logo: A mascot (and CC-BY license) was added for esnacc
 * py-lib: Introduce a first cut at a python back-end
diff --git a/asn1specs/snaccrose.asn b/asn1specs/snaccrose.asn
new file mode 100644
index 0000000..6bc278f
--- /dev/null
+++ b/asn1specs/snaccrose.asn
@@ -0,0 +1,121 @@ 
+-- snaccrose: The eSNACC ROSE implementation
+-- Dual Licensed under both the esnacc public license and the Lesser GNU
+-- Public License v3 or greater.
+-- Copyright (C) 2017, Aaron Conole
+-- Portions Copright (C), estos GmbH and estos/stm
+
+SNACC-ROSE { joint-iso-itu-t remote-operations(4)
+             informationObjects(5)
+             version1(0) } DEFINITIONS ::= BEGIN
+
+-- Default ROSE message sent
+ROSEMessage ::= CHOICE {
+	invoke [1] IMPLICIT ROSEInvoke,
+	result [2] IMPLICIT ROSEResult,
+	error  [3] IMPLICIT ROSEError,
+	reject [4] IMPLICIT ROSEReject
+}
+
+-- Authentication
+
+ROSEAuth ::= SEQUENCE {
+    method   UTF8String,     -- Authentication Type ("Basic" is only supported)
+    authdata OCTET STRING    -- Authentication Data
+}
+
+ROSEAuthList ::= SEQUENCE OF ROSEAuth 
+
+ROSEAuthRequest ::= SEQUENCE {
+    auth    ROSEAuth,
+    context UTF8String OPTIONAL
+}
+
+ROSEAuthResult ::= SEQUENCE {
+  authList ROSEAuthList,
+  context  UTF8String OPTIONAL
+}
+
+
+-- ROSE messages
+
+ROSEInvoke		::=	SEQUENCE {
+    sessionID      [1]          UTF8String      OPTIONAL,
+    invokeID                    INTEGER,
+    linked-ID      [0] IMPLICIT INTEGER         OPTIONAL,
+    operationName  [2]          UTF8String      OPTIONAL,
+    authentication [3]          ROSEAuthRequest OPTIONAL,
+    operationID                 INTEGER,
+    argument                    ANY             OPTIONAL
+}
+					 
+ROSEResult ::= SEQUENCE {
+    sessionID [1] UTF8String OPTIONAL,
+    invokeID      INTEGER,
+    result        SEQUENCE {
+        resultValue INTEGER,
+        result      ANY
+    } OPTIONAL
+}
+
+ROSEError ::= SEQUENCE {
+    sessionID   [1] UTF8String OPTIONAL,
+    invokedID       INTEGER,
+    error-value     INTEGER,
+    error           ANY        OPTIONAL
+}
+
+ROSEReject ::= SEQUENCE {
+    sessionID      [1] UTF8String     OPTIONAL,
+    invokedID          CHOICE {
+        invokedID   INTEGER,
+        invokednull NULL
+    },
+    reject             RejectProblem  OPTIONAL,
+
+    -- the following are an etsos extension to reject for transmitting cause
+    details            UTF8String     OPTIONAL,
+    authentication [4] ROSEAuthResult OPTIONAL
+}
+
+RejectProblem ::= CHOICE {
+    generalProblem      [0] IMPLICIT GeneralProblem,
+    invokeProblem       [1] IMPLICIT InvokeProblem,
+    returnResultProblem [2] IMPLICIT ReturnResultProblem,
+    returnErrorProblem  [3] IMPLICIT ReturnErrorProblem
+}
+
+GeneralProblem ::= INTEGER { -- ROSE-provider detected
+	unrecognisedAPDU(0),
+	mistypedAPDU(1),
+	badlyStructuredAPDU(2)
+}
+
+InvokeProblem ::= INTEGER { -- ROSE-user detected
+    duplicateInvocation(0),
+    unrecognisedOperation(1),
+    mistypedArgument(2),
+    resourceLimitation(3),
+    initiatorReleasing(4),
+    unrecognisedLinkedID(5),
+    linkedResponseUnexpected(6),
+    unexpectedChildOperation(7),
+    invalidSessionID(8),          -- sessionID in Invoke is not valid
+    authenticationIncomplete(9),  -- Invoke Authentication failed
+    authenticationFailed(10)      -- Invoke Authentication failed  
+}
+
+ReturnResultProblem ::= INTEGER { -- ROSE-user detected
+    unrecognisedInvocation(0),
+    resultResponseUnexpected(1),
+    mistypedResult(2)
+}
+
+ReturnErrorProblem ::= INTEGER { -- ROSE-user detected
+    unrecognisedInvocation(0),
+    errorResponseUnexpected(1),
+    unrecognisedError(2),
+    unexpectedError(3),
+    mistypedParameter(4)
+}
+
+END
diff --git a/cxx-lib/.gitignore b/cxx-lib/.gitignore
index 82f7b10..64b873a 100644
--- a/cxx-lib/.gitignore
+++ b/cxx-lib/.gitignore
@@ -1,6 +1,9 @@ 
 .dirstamp
 .libs
 .deps
-libesnaccxx.pc
+*.pc
 inc/snacc.h
+inc/snaccrose.h
 inc/snacc.h.in
+src/snaccrose.cpp
+src/snaccrose.h
diff --git a/cxx-lib/automake.mk b/cxx-lib/automake.mk
index 4e78937..2c5b7ea 100644
--- a/cxx-lib/automake.mk
+++ b/cxx-lib/automake.mk
@@ -1,4 +1,5 @@ 
-lib_LTLIBRARIES += cxx-lib/libcxxasn1.la
+lib_LTLIBRARIES += cxx-lib/libcxxasn1.la \
+	cxx-lib/libcxxasn1rose.la
 
 BUILT_SOURCES += cxx-lib/inc/snacc.h
 
@@ -9,12 +10,14 @@  nobase_include_HEADERS += cxx-lib/inc/asn-buf.h \
 	cxx-lib/inc/asn-iomanip.h \
 	cxx-lib/inc/asn-list.h \
 	cxx-lib/inc/asn-listset.h \
+	cxx-lib/inc/asn-rose.h \
 	cxx-lib/inc/asn-usefultypes.h \
 	cxx-lib/inc/init.h \
 	cxx-lib/inc/meta.h \
 	cxx-lib/inc/snacc.h \
 	cxx-lib/inc/snaccdll.h \
 	cxx-lib/inc/snaccexcept.h \
+	cxx-lib/inc/snaccrose.h \
 	cxx-lib/inc/tcl-if.h
 
 cxx_lib_libcxxasn1_la_SOURCES = \
@@ -47,13 +50,24 @@  cxx_lib_libcxxasn1_la_SOURCES = \
 	cxx-lib/src/asn-bits.cpp \
 	cxx-lib/src/asn-len.cpp \
 	cxx-lib/src/asn-fileseg.cpp \
-	cxx-lib/src/asn-rvsbuf.cpp 
+	cxx-lib/src/asn-rvsbuf.cpp
+
+cxx_lib_libcxxasn1rose_la_SOURCES = \
+	asn1specs/snaccrose.asn \
+	cxx-lib/src/snaccrose.cpp \
+	cxx-lib/src/asn-rose.cpp
 
 cxx_lib_libcxxasn1_la_WIN32_FLAGS=
 cxx_lib_libcxxasn1_la_WIN32_LIBADD=
 cxx_lib_libcxxasn1_la_WIN32_LDFLAGS=
+
+cxx_lib_libcxxasn1rose_la_WIN32_FLAGS=
+cxx_lib_libcxxasn1rose_la_WIN32_LIBADD=
+cxx_lib_libcxxasn1rose_la_WIN32_LDFLAGS=
+
 if WIN32
 cxx_lib_libcxxasn1_la_WIN32_FLAGS += -DSNACCDLL_EXPORTS=1
+cxx_lib_libcxxasn1rose_la_WIN32_FLAGS += -DSNACCDLL_EXPORTS=1
 endif
 
 cxx_lib_libcxxasn1_la_CXXFLAGS = \
@@ -78,12 +92,44 @@  cxx_lib_libcxxasn1_la_LDFLAGS = \
 	$(all_lib_LDFLAGS) \
 	$(cxx_lib_libcxxasn1_la_WIN32_LDFLAGS)
 
+cxx_lib_libcxxasn1rose_la_CXXFLAGS = \
+	$(cxx_lib_libcxxasn1rose_la_WIN32_FLAGS) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/cxx-lib \
+	-I$(top_srcdir)/cxx-lib/src \
+	-I$(top_srcdir)/cxx-lib/inc
+
+cxx_lib_libcxxasn1rose_la_CFLAGS = \
+	$(cxx_lib_libcxxasn1rose_la_WIN32_FLAGS) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/cxx-lib \
+	-I$(top_srcdir)/cxx-lib/src \
+	-I$(top_srcdir)/cxx-lib/inc
+
+cxx_lib_libcxxasn1rose_la_LIBADD = \
+	$(cxx_lib_libcxxasn1rose_la_WIN32_LIBADD)
+
+cxx_lib_libcxxasn1rose_la_LDFLAGS = \
+	$(LDFLAGS) \
+	$(all_lib_LDFLAGS) \
+	$(cxx_lib_libcxxasn1rose_la_WIN32_LDFLAGS)
+
 EXTRA_DIST += \
 	cxx-lib/libesnaccxx.pc.in \
+	cxx-lib/libesnaccxxrose.pc.in \
 	cxx-lib/inc/snacc.h.in
 
-pkgconfig_DATA += cxx-lib/libesnaccxx.pc
-DISTCLEANFILES += cxx-lib/libesnaccxx.pc cxx-lib/inc/snacc.h
+pkgconfig_DATA += cxx-lib/libesnaccxx.pc cxx-lib/libesnaccxxrose.pc
+DISTCLEANFILES += cxx-lib/libesnaccxx.pc \
+	cxx-lib/libesnaccxxrose.pc \
+	cxx-lib/inc/snacc.h \
+	cxx-lib/src/snaccrose.cpp \
+	cxx-lib/src/snaccrose.h
 
 cxx-lib/inc/snacc.h.in: snacc.h.in
-	cp $< $@
+	$(AM_V_GEN)cp $< $@
+
+cxx-lib/inc/snaccrose.h:
+cxx-lib/src/snaccrose.cpp: asn1specs/snaccrose.asn compiler/esnacc$(EXEEXT)
+	$(AM_V_GEN)compiler/esnacc$(EXEEXT) -C -mo `dirname $@` $<
+	-$(AM_V_GEN)cp $(srcdir)/cxx-lib/src/snaccrose.h cxx-lib/inc/
diff --git a/cxx-lib/inc/asn-rose.h b/cxx-lib/inc/asn-rose.h
new file mode 100644
index 0000000..0389d22
--- /dev/null
+++ b/cxx-lib/inc/asn-rose.h
@@ -0,0 +1,163 @@ 
+/* asn-rose.h: Remote Operations Service Element support
+ *
+ * Copyright (C) 2017, Aaron Conole
+ *
+ * Dual licensed under both the esnacc public license, and the
+ * Lesser GNU Public License version 3 (lgpl v3).
+ *
+ * Portions of this file were contributed by estos GmbH, www.estos.com
+ */
+
+#include <stdint.h>
+#include <string>
+#include <map>
+#include <memory>
+#include <streambuf>
+#include <stdexcept>
+
+#include "asn-incl.h"
+#include "asn-buf.h"
+#include "asn-iomanip.h"
+
+#ifndef ESNACC_ASN_ROSE_H__
+#define ESNACC_ASN_ROSE_H__
+
+#define ROSE_TRANSPORT_ERROR(code) (code & 0x000F)
+#define ROSE_RE(code)              (code & 0x00F0)
+#define ROSE_REJECT(code)          (code & 0x0F00)
+#define ROSE_ERROR(code)           (code & 0xF000)
+
+/* fwd decl. for this - implementation detail.  */
+class InitialMonitoredStreamCB;
+
+namespace SNACC {
+
+class AsnType;
+class ROSEMessage;
+class ROSEInvoke;
+class ROSEResult;
+class ROSEError;
+class ROSEReject;
+class InvokeProblem;
+class ROSEAuthRequest;
+class ROSEAuthResult;
+
+static const uint32_t ROSE_TRANSPORT_FAILED   = 0x1;
+static const uint32_t ROSE_TRANSPORT_SHUTDOWN = 0x2;
+static const uint32_t ROSE_TRANSPORT_TIMEOUT  = 0x3;
+
+static const uint32_t ROSE_RE_INVALID_ANSWER = 0x10;
+static const uint32_t ROSE_RE_DECODE_ERROR   = 0x20;
+
+static const uint32_t ROSE_REJECT_UNKNOWN_OPERATION = 0x100;
+static const uint32_t ROSE_REJECT_MISTYPED_ARGUMENT = 0x200;
+static const uint32_t ROSE_REJECT_FUNCTIONS_MISSING = 0x300;
+static const uint32_t ROSE_REJECT_INVALID_CODE      = 0x400;
+static const uint32_t ROSE_REJECT_INVALID_SESSION   = 0x500;
+static const uint32_t ROSE_REJECT_START_SSL_REQUIRED        = 0x600;
+static const uint32_t ROSE_REJECT_AUTHENTICATION_INCOMPLETE = 0x700;
+static const uint32_t ROSE_REJECT_AUTHENTICATION_FAILED     = 0x800;
+
+static const uint32_t ROSE_GENERIC_ERROR = 0x1000;
+
+static const uint64_t ROSE_TIMEOUT_INF = ~0ULL;
+
+enum SnaccInvokeResult {
+    returnResult,
+    returnError,
+    returnReject
+};
+
+struct AsnInvokeCtx
+{
+    AsnInvokeCtx() : rejectResult(0), invokeAuthReq(0),
+                     invokeAuthRes(0)
+    {
+    }
+
+    ~AsnInvokeCtx();
+
+    long rejectResult;
+    ROSEAuthRequest *invokeAuthReq;
+    ROSEAuthResult  *invokeAuthRes;
+};
+
+typedef long (*InvokeCB)(ROSEInvoke *, AsnInvokeCtx *);
+
+class OperationCoordinator
+{
+public:
+    typedef std::map<std::string, InvokeCB> ByNameMap;
+    typedef std::map<InvokeCB, std::string> ByOperationMap;
+    typedef std::map<uint64_t, InvokeCB>    ByOpIdMap;
+
+    OperationCoordinator();
+    ~OperationCoordinator() { }
+
+    void SetInvokeCallback(const std::string &s, InvokeCB i);
+
+    InvokeCB FindInvoke(const std::string &s, bool &b) const
+    {
+        ByNameMap::const_iterator cit = nameMap.find(s);
+        b = false;
+        if (cit != nameMap.end()) {
+            b = true;
+            return cit->second;
+        }
+        return (InvokeCB)0;
+    }
+
+    InvokeCB FindInvoke(const uint64_t i, bool &b) const
+    {
+        ByOpIdMap::const_iterator cit = operationIdMap.find(i);
+        b = false;
+        if (cit != operationIdMap.end()) {
+            b = true;
+            return cit->second;
+        }
+        return (InvokeCB)0;
+    }
+
+    InvokeCB operator[](const std::string &s) const
+    {
+        InvokeCB i;
+        bool b;
+
+        i = FindInvoke(s, b);
+        if (!b || !i) {
+            throw std::range_error(std::string() +
+                                   "Invalid operation requested from directory");
+        }
+        return i;
+    }
+
+    void MonitorStreambuf(std::streambuf *b, SNACCEncodeDecodeRules r);
+    void RemoveStreambuf(std::streambuf *b);
+    SNACCEncodeDecodeRules StreambufEncodingType(std::streambuf *b);
+
+    void monitor()
+    {
+        monbufs();
+    }
+
+    bool ReceiveMsg(const ROSEMessage &m);
+    bool SendMsg(std::streambuf *b, ROSEMessage &r);
+
+protected:
+
+    bool ReceiveInvoke(const ROSEInvoke *i);
+    bool ReceiveResult(const ROSEResult *r);
+    bool ReceiveReject(const ROSEReject *r);
+    bool ReceiveError(const ROSEError *e);
+
+    ByNameMap      nameMap;
+    ByOperationMap operationMap;
+    ByOpIdMap      operationIdMap;
+    InitialMonitoredStreamCB *cb;
+    StreambufMonitor monbufs;
+    std::map<std::streambuf *, SNACCEncodeDecodeRules> bufEncodeMap;
+    
+};
+
+}
+#endif
diff --git a/cxx-lib/libesnaccxxrose.pc.in b/cxx-lib/libesnaccxxrose.pc.in
new file mode 100644
index 0000000..635954d
--- /dev/null
+++ b/cxx-lib/libesnaccxxrose.pc.in
@@ -0,0 +1,14 @@ 
+# Enhanced SNACC pkg-config source file
+
+PREFIX=@prefix@
+EXEC_PREFIX=@exec_prefix@
+LIBDIR=@libdir@
+INCLUDEDIR=@includedir@
+
+Name: libesnaccxxrose
+Description: Enhanced SNACC ROSE support and libs for C++
+Version: @VERSION@
+Requires:
+Conflicts:
+Libs: -L${LIBDIR} -lcxxasn1 -lcxxasn1rose
+Cflags: -I${INCLUDEDIR}/cxx-lib/inc
diff --git a/cxx-lib/src/asn-rose.cpp b/cxx-lib/src/asn-rose.cpp
new file mode 100644
index 0000000..f777f73
--- /dev/null
+++ b/cxx-lib/src/asn-rose.cpp
@@ -0,0 +1,219 @@ 
+/* asn-rose.cxx: Remote Operations Service Element support
+ *
+ * Copyright (C) 2017, Aaron Conole
+ *
+ * Dual licensed under both the esnacc public license, and the
+ * Lesser GNU Public License version 3 (lgpl v3).
+ *
+ * Portions of this file were contributed by estos GmbH, www.estos.com
+ */
+
+#include "asn-rose.h"
+#include "snaccrose.h"
+
+using namespace SNACC;
+
+static uint64_t mhash64(const void *k, size_t l, uint64_t s)
+{
+    const uint64_t m = ESNACC_CONST_ULL(0xc6a4a7935bd1e995);
+    const int r = 47;
+    uint64_t h = s ^ (l * m);
+    uint64_t dval = *(const uint64_t *)k;
+    uint64_t *data;
+    for (data = (uint64_t *)k;
+         data != ((uint64_t *)k + (l / 8)); dval = *data++) {
+        dval *= m;
+        dval ^= dval >> r;
+        dval *= m;
+
+        h ^= dval;
+        h *= m;
+    }
+
+    const unsigned char * data2 = (const unsigned char*)data;
+
+    switch(l & 7) {
+    case 7: h ^= uint64_t(data2[6]) << 48;
+    case 6: h ^= uint64_t(data2[5]) << 40;
+    case 5: h ^= uint64_t(data2[4]) << 32;
+    case 4: h ^= uint64_t(data2[3]) << 24;
+    case 3: h ^= uint64_t(data2[2]) << 16;
+    case 2: h ^= uint64_t(data2[1]) << 8;
+    case 1: h ^= uint64_t(data2[0]);
+        h *= m;
+    }
+
+    h ^= h >> r;
+    h *= m;
+    h ^= h >> r;
+
+    return h;
+}
+
+class InitialMonitoredStreamCB : public StreambufCallback
+{
+    OperationCoordinator &m_parent;
+
+    static inline AsnLen DecodeMsg(std::streambuf *stream,
+                                   SNACCEncodeDecodeRules r, ROSEMessage &rm)
+    {
+        AsnBuf buf(stream); AsnLen l;
+        switch (r) {
+        case BER: {
+            rm.BDec(buf, l);
+        }
+        break;
+
+        case PER:
+        default:
+            throw SnaccException(__FILE__, __LINE__, "DecodeMsg",
+                                 "Unsupported encoding type");
+            break;
+        }
+        return l;
+    }
+
+    StreambufCallback::Streambuf_CB_RESULT callback(Streambuf_CB_STATUS status,
+                                                    std::streambuf *stream)
+    {
+        switch (status) {
+        case StreambufCallback::CB_READ_OK: {
+                try {
+                    ROSEMessage rm;
+                    DecodeMsg(stream, m_parent.StreambufEncodingType(stream),
+                              rm);
+                    m_parent.ReceiveMsg(rm);
+                } catch (SnaccException &e) {
+                    ROSEReject rejectMsg;
+                    rejectMsg.invokedID.choiceId =
+                        ROSERejectChoice::invokednullCid;
+                    rejectMsg.invokedID.invokednull = new AsnNull;
+                    ROSEMessage m;
+                    m.reject = new ROSEReject(rejectMsg);
+                    m_parent.SendMsg(stream, m);
+                }
+        }
+        break;
+        case StreambufCallback::CB_WRITE_OK:
+        case StreambufCallback::CB_OPENED:
+            return StreambufCallback::CB_NONE;
+
+        case StreambufCallback::CB_CLOSED:
+        default:
+            return StreambufCallback::CB_DROP_STREAM;
+        }
+        return StreambufCallback::CB_NONE;
+    }
+
+public:
+    InitialMonitoredStreamCB(OperationCoordinator &p) :
+        m_parent(p) {}
+
+};
+
+OperationCoordinator::OperationCoordinator() :
+    nameMap(), operationMap(), operationIdMap(),
+    cb(new InitialMonitoredStreamCB(*this))
+{
+
+}
+
+#define OPERATION_SEED 0x5bd1e995
+
+void OperationCoordinator::SetInvokeCallback(const std::string &s, InvokeCB i)
+{
+    uint64_t hash = mhash64(s.c_str(), s.length(), OPERATION_SEED);
+    nameMap[s] = i;
+    operationMap[i] = s;
+    operationIdMap[hash] = i;
+}
+
+void OperationCoordinator::MonitorStreambuf(std::streambuf *b,
+                                            SNACCEncodeDecodeRules r)
+{
+    monbufs.push(b, *cb, false);
+    bufEncodeMap[b] = r;
+}
+
+void OperationCoordinator::RemoveStreambuf(std::streambuf *b)
+{
+    monbufs.pop(b);
+    bufEncodeMap.erase(b);
+}
+
+bool OperationCoordinator::ReceiveInvoke(const ROSEInvoke *i)
+{
+    return false;
+}
+
+bool OperationCoordinator::ReceiveResult(const ROSEResult *r)
+{
+    return false;
+}
+
+bool OperationCoordinator::ReceiveReject(const ROSEReject *r)
+{
+    return false;
+}
+
+bool OperationCoordinator::ReceiveError(const ROSEError *e)
+{
+    return false;
+}
+
+bool OperationCoordinator::ReceiveMsg(const ROSEMessage &m)
+{
+    bool result = false;
+    switch(m.choiceId) {
+    case ROSEMessage::invokeCid:
+        if (!m.invoke) {
+            throw SnaccException(__FILE__, __LINE__, "ReceiveMsg",
+                                 "Empty invoke requested");
+        }
+        result = ReceiveInvoke(m.invoke);
+        break;
+    case ROSEMessage::resultCid:
+        if (!m.result) {
+            throw SnaccException(__FILE__, __LINE__, "ReceiveMsg",
+                                 "Empty result returned");
+        }
+        result = ReceiveResult(m.result);
+        break;
+    case ROSEMessage::rejectCid:
+        if (!m.reject) {
+            throw SnaccException(__FILE__, __LINE__, "ReceiveMsg",
+                                 "Empty reject returned");
+        }
+        result = ReceiveReject(m.reject);
+        break;
+    case ROSEMessage::errorCid:
+        if (!m.error) {
+            throw SnaccException(__FILE__, __LINE__, "ReceiveMsg",
+                                 "Empty reject returned");
+        }
+        result = ReceiveError(m.error);
+        break;
+    }
+    return result;
+}
+
+bool OperationCoordinator::SendMsg(std::streambuf *b, ROSEMessage &r)
+{
+    AsnBuf buf(b); AsnLen l;
+    switch (StreambufEncodingType(b)) {
+    case BER:
+        l = r.BEnc(buf);
+        break;
+    case PER:
+    default:
+        throw SnaccException(__FILE__, __LINE__, "SendMsg",
+                             "Unsupported encoding type");
+        break;
+    }
+    return l;
+}
+
+SNACCEncodeDecodeRules OperationCoordinator::StreambufEncodingType(std::streambuf *b)
+{
+    return bufEncodeMap[b];
+}
diff --git a/debian/libesnacc-dev.install b/debian/libesnacc-dev.install
index b4a6dfb..067189d 100644
--- a/debian/libesnacc-dev.install
+++ b/debian/libesnacc-dev.install
@@ -4,5 +4,8 @@  debian/tmp/usr/lib/libcasn1.a
 debian/tmp/usr/lib/libcasn1.la
 debian/tmp/usr/lib/libcxxasn1.a
 debian/tmp/usr/lib/libcxxasn1.la
+debian/tmp/usr/lib/libcxxasn1rose.a
+debian/tmp/usr/lib/libcxxasn1rose.la
 debian/tmp/usr/lib/pkgconfig/libesnacc.pc
 debian/tmp/usr/lib/pkgconfig/libesnaccxx.pc
+debian/tmp/usr/lib/pkgconfig/libesnaccxxrose.pc
diff --git a/debian/libesnacc180.install b/debian/libesnacc180.install
index 7cfeac5..a1b9d0f 100644
--- a/debian/libesnacc180.install
+++ b/debian/libesnacc180.install
@@ -4,3 +4,6 @@  debian/tmp/usr/lib/libcasn1.so.0.0.0
 debian/tmp/usr/lib/libcxxasn1.so
 debian/tmp/usr/lib/libcxxasn1.so.0
 debian/tmp/usr/lib/libcxxasn1.so.0.0.0
+debian/tmp/usr/lib/libcxxasn1rose.so
+debian/tmp/usr/lib/libcxxasn1rose.so.0
+debian/tmp/usr/lib/libcxxasn1rose.so.0.0.0
diff --git a/redhat/esnacc.spec.in b/redhat/esnacc.spec.in
index 9ac9ccf..4ef6dd2 100644
--- a/redhat/esnacc.spec.in
+++ b/redhat/esnacc.spec.in
@@ -88,8 +88,12 @@  make DESTDIR=%{buildroot} install
 %_libdir/lib*.la
 %_libdir/pkgconfig/libesnacc.pc
 %_libdir/pkgconfig/libesnaccxx.pc
+%_libdir/pkgconfig/libesnaccxxrose.pc
 
 %changelog
+* Wed May 31 2017 Aaron Conole <aconole@bytheb.org> - 1.9.0-1
+- Add the esnacc ROSE support packages.
+
 * Fri Mar 17 2017 Aaron Conole <aconole@bytheb.org> - 1.8.0-2
 - Fix up the esnacc package for fedpkg compliance.
 
diff --git a/snacc.h.in b/snacc.h.in
index 2593270..431236e 100644
--- a/snacc.h.in
+++ b/snacc.h.in
@@ -165,4 +165,11 @@ 
 #else
 # define ESNACC_UNUSED
 #endif
+
+#if defined(_MSC_VER)
+# define ESNACC_CONST_ULL(x) (x)
+#else
+# define ESNACC_CONST_ULL(x) (x##ULL)
+#endif
+
 #endif