You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by gs...@apache.org on 2014/11/26 21:05:48 UTC

[01/35] qpid-proton git commit: PROTON-745: update DataImpl to return arrays of Symbol as Symbol[] instance rather than Object[] instance, and enable Data#putObject() to accept the Symbol[].

Repository: qpid-proton
Updated Branches:
  refs/heads/examples 0fd8b1fc5 -> 2f4d1ba29


PROTON-745: update DataImpl to return arrays of Symbol as Symbol[] instance rather than Object[] instance, and enable Data#putObject() to accept the Symbol[].


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/a04193d2
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/a04193d2
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/a04193d2

Branch: refs/heads/examples
Commit: a04193d2c745bbf045fcc191a5d5de8fbdba9812
Parents: c5c1879
Author: Robert Gemmell <ro...@apache.org>
Authored: Fri Nov 14 15:46:44 2014 +0000
Committer: Robert Gemmell <ro...@apache.org>
Committed: Fri Nov 14 15:46:44 2014 +0000

----------------------------------------------------------------------
 .../qpid/proton/codec/impl/ArrayElement.java    | 13 +++
 .../apache/qpid/proton/codec/impl/DataImpl.java | 10 +++
 .../qpid/proton/codec/impl/DataImplTest.java    | 84 ++++++++++++++++++++
 3 files changed, 107 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a04193d2/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/ArrayElement.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/ArrayElement.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/ArrayElement.java
index 2ac9668..22251fe 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/ArrayElement.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/ArrayElement.java
@@ -24,6 +24,7 @@ package org.apache.qpid.proton.codec.impl;
 import java.nio.ByteBuffer;
 
 import org.apache.qpid.proton.amqp.DescribedType;
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.codec.Data;
 
 class ArrayElement extends AbstractElement<Object[]>
@@ -160,6 +161,18 @@ class ArrayElement extends AbstractElement<Object[]>
             }
             return rVal;
         }
+        else if(_arrayType == Data.DataType.SYMBOL)
+        {
+            Symbol[] rVal = new Symbol[(int) count()];
+            SymbolElement element = (SymbolElement) _first;
+            int i = 0;
+            while (element!=null)
+            {
+                rVal[i++] = element.getValue();
+                element = (SymbolElement) element.next();
+            }
+            return rVal;
+        }
         else
         {
             Object[] rVal = new Object[(int) count()];

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a04193d2/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/DataImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/DataImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/DataImpl.java
index b22ae30..c6520ed 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/DataImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/impl/DataImpl.java
@@ -458,6 +458,16 @@ public class DataImpl implements Data
         {
             putDescribedType((DescribedType)o);
         }
+        else if(o instanceof Symbol[])
+        {
+            putArray(false, Data.DataType.SYMBOL);
+            enter();
+            for(Symbol s : (Symbol[]) o)
+            {
+                putSymbol(s);
+            }
+            exit();
+        }
         else if(o instanceof Object[])
         {
             putJavaArray((Object[]) o);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a04193d2/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/DataImplTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/DataImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/DataImplTest.java
new file mode 100644
index 0000000..6bb3f2c
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/DataImplTest.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.proton.codec.impl;
+
+import static org.junit.Assert.*;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.codec.Data;
+import org.junit.Test;
+
+public class DataImplTest
+{
+    @Test
+    public void testEncodeDecodeSymbolArrayUsingPutArray()
+    {
+        Symbol symbol1 = Symbol.valueOf("testRoundtripSymbolArray1");
+        Symbol symbol2 = Symbol.valueOf("testRoundtripSymbolArray2");
+
+        Data data1 = new DataImpl();
+        data1.putArray(false, Data.DataType.SYMBOL);
+        data1.enter();
+        data1.putSymbol(symbol1);
+        data1.putSymbol(symbol2);
+        data1.exit();
+
+        Binary encoded = data1.encode();
+        encoded.asByteBuffer();
+
+        Data data2 = new DataImpl();
+        data2.decode(encoded.asByteBuffer());
+
+        assertEquals("unexpected array length", 2, data2.getArray());
+        assertEquals("unexpected array length", Data.DataType.SYMBOL, data2.getArrayType());
+
+        Object[] array = data2.getJavaArray();
+        assertNotNull("Array should not be null", array);
+        assertEquals("Expected a Symbol array", Symbol[].class, array.getClass());
+        assertEquals("unexpected array length", 2, array.length);
+        assertEquals("unexpected value", symbol1, array[0]);
+        assertEquals("unexpected value", symbol2, array[1]);
+    }
+
+    @Test
+    public void testEncodeDecodeSymbolArrayUsingPutObject()
+    {
+        Symbol symbol1 = Symbol.valueOf("testRoundtripSymbolArray1");
+        Symbol symbol2 = Symbol.valueOf("testRoundtripSymbolArray2");
+        Symbol[] input = new Symbol[]{symbol1, symbol2};
+
+        Data data1 = new DataImpl();
+        data1.putObject(input);
+
+        Binary encoded = data1.encode();
+        encoded.asByteBuffer();
+
+        Data data2 = new DataImpl();
+        data2.decode(encoded.asByteBuffer());
+
+        assertEquals("unexpected array length", 2, data2.getArray());
+        assertEquals("unexpected array length", Data.DataType.SYMBOL, data2.getArrayType());
+
+        Object[] array = data2.getJavaArray();
+        assertArrayEquals("Array not as expected", input, array);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[33/35] qpid-proton git commit: fix installation of new package

Posted by gs...@apache.org.
fix installation of new package


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/805cd17e
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/805cd17e
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/805cd17e

Branch: refs/heads/examples
Commit: 805cd17e360fd77eab29d60955a2193c7e7f0635
Parents: d02fdad
Author: Gordon Sim <gs...@redhat.com>
Authored: Wed Nov 26 17:15:38 2014 +0000
Committer: Gordon Sim <gs...@redhat.com>
Committed: Wed Nov 26 17:15:38 2014 +0000

----------------------------------------------------------------------
 proton-c/bindings/python/CMakeLists.txt | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/805cd17e/proton-c/bindings/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/CMakeLists.txt b/proton-c/bindings/python/CMakeLists.txt
index 6be421e..eb53174 100644
--- a/proton-c/bindings/python/CMakeLists.txt
+++ b/proton-c/bindings/python/CMakeLists.txt
@@ -55,20 +55,20 @@ endif()
 set (pysrc-generated cproton.py)
 set (pysrc proton/__init__.py)
 
-macro (py_compile directory files)
+macro (py_compile directory files artifacts)
   foreach (src_file ${files})
     install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile ${src_file}
                                   WORKING_DIRECTORY ${directory})")
     install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile ${src_file}
                                   WORKING_DIRECTORY ${directory})")
-    list(APPEND PYTHON_ARTIFACTS ${directory}/${src_file}
+    list(APPEND ${artifacts} ${directory}/${src_file}
       ${directory}/${src_file}c
       ${directory}/${src_file}o)
   endforeach (src_file)
 endmacro(py_compile)
 
-py_compile(${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated})
-py_compile(${CMAKE_CURRENT_SOURCE_DIR} ${pysrc})
+py_compile(${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated} CPROTON_ARTIFACTS)
+py_compile(${CMAKE_CURRENT_SOURCE_DIR} ${pysrc} PROTON_ARTIFACTS)
 
 find_program(EPYDOC_EXE epydoc)
 mark_as_advanced (EPYDOC_EXE)
@@ -84,9 +84,12 @@ if (EPYDOC_EXE)
            ${OPTIONAL_ARG})
 endif (EPYDOC_EXE)
 
-install(FILES ${PYTHON_ARTIFACTS}
+install(FILES ${CPROTON_ARTIFACTS}
         DESTINATION ${PYTHON_SITEARCH_PACKAGES}
         COMPONENT Python)
+install(FILES ${PROTON_ARTIFACTS}
+        DESTINATION "${PYTHON_SITEARCH_PACKAGES}/proton/"
+        COMPONENT Python)
 install(TARGETS ${SWIG_MODULE_cproton_REAL_NAME}
         DESTINATION ${PYTHON_SITEARCH_PACKAGES}
         COMPONENT Python)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[29/35] qpid-proton git commit: NO-JIRA: Fix protocol tracing for transactional states.

Posted by gs...@apache.org.
NO-JIRA: Fix protocol tracing for transactional states.

Add transactions.xml to the set of files processed by protocol.py.
Logs "state=@transactional-state(52)" instead of just "state=52"
'


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/061da30b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/061da30b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/061da30b

Branch: refs/heads/examples
Commit: 061da30be815467217ecb365cfc1d7581367ba32
Parents: 3ac2e3b
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Nov 19 20:31:29 2014 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Nov 24 14:58:48 2014 -0500

----------------------------------------------------------------------
 proton-c/src/protocol.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/061da30b/proton-c/src/protocol.py
----------------------------------------------------------------------
diff --git a/proton-c/src/protocol.py b/proton-c/src/protocol.py
index 685e63b..ae65150 100644
--- a/proton-c/src/protocol.py
+++ b/proton-c/src/protocol.py
@@ -22,6 +22,7 @@ doc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transport.xml"))
 mdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "messaging.xml"))
 tdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transactions.xml"))
 sdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "security.xml"))
+tdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transactions.xml"))
 
 def eq(attr, value):
   return lambda nd: nd[attr] == value
@@ -30,12 +31,14 @@ TYPES = doc.query["amqp/section/type", eq("@class", "composite")] + \
     mdoc.query["amqp/section/type", eq("@class", "composite")] + \
     tdoc.query["amqp/section/type", eq("@class", "composite")] + \
     sdoc.query["amqp/section/type", eq("@class", "composite")] + \
-    mdoc.query["amqp/section/type", eq("@provides", "section")]
+    mdoc.query["amqp/section/type", eq("@provides", "section")] + \
+    tdoc.query["amqp/section/type", eq("@class", "composite")]
+
 RESTRICTIONS = {}
 COMPOSITES = {}
 
 for type in doc.query["amqp/section/type"] + mdoc.query["amqp/section/type"] + \
-      sdoc.query["amqp/section/type"]:
+      sdoc.query["amqp/section/type"] + tdoc.query["amqp/section/type"]:
   source = type["@source"]
   if source:
     RESTRICTIONS[type["@name"]] = source


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[23/35] qpid-proton git commit: Revert "PROTON-755: Update Ruby smoke tests to use Minitest"

Posted by gs...@apache.org.
Revert "PROTON-755: Update Ruby smoke tests to use Minitest"

This reverts commit 1d3a13863117cfca5aef56244b20773760428796.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2276c097
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2276c097
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2276c097

Branch: refs/heads/examples
Commit: 2276c09715683ace9e761a6d5aab5b74add3b7b9
Parents: b13222b
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Sat Nov 22 05:51:13 2014 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Sat Nov 22 06:03:01 2014 -0500

----------------------------------------------------------------------
 tests/ruby/proton-test             | 2 +-
 tests/ruby/proton_tests/interop.rb | 4 ++--
 tests/ruby/proton_tests/smoke.rb   | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2276c097/tests/ruby/proton-test
----------------------------------------------------------------------
diff --git a/tests/ruby/proton-test b/tests/ruby/proton-test
index acb0d43..748e6f0 100755
--- a/tests/ruby/proton-test
+++ b/tests/ruby/proton-test
@@ -1,5 +1,5 @@
 #!/usr/bin/env ruby
 
-require 'minitest/autorun'
+require 'test/unit'
 require 'proton_tests/interop.rb'
 require 'proton_tests/smoke.rb'

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2276c097/tests/ruby/proton_tests/interop.rb
----------------------------------------------------------------------
diff --git a/tests/ruby/proton_tests/interop.rb b/tests/ruby/proton_tests/interop.rb
index 21d92d9..e14cba1 100755
--- a/tests/ruby/proton_tests/interop.rb
+++ b/tests/ruby/proton_tests/interop.rb
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-require 'minitest/autorun'
+require 'test/unit'
 require 'qpid_proton'
 
 if ((RUBY_VERSION.split(".").map {|x| x.to_i}  <=> [1, 9]) < 0)
@@ -12,7 +12,7 @@ if ((RUBY_VERSION.split(".").map {|x| x.to_i}  <=> [1, 9]) < 0)
   end
 end
 
-class InteropTest < Minitest::Test
+class InteropTest < Test::Unit::TestCase
   Data = Qpid::Proton::Data
   Message = Qpid::Proton::Message
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2276c097/tests/ruby/proton_tests/smoke.rb
----------------------------------------------------------------------
diff --git a/tests/ruby/proton_tests/smoke.rb b/tests/ruby/proton_tests/smoke.rb
index a382a0b..b9265e8 100644
--- a/tests/ruby/proton_tests/smoke.rb
+++ b/tests/ruby/proton_tests/smoke.rb
@@ -1,9 +1,9 @@
 #!/usr/bin/env ruby
 
-require 'minitest/autorun'
+require 'test/unit'
 require 'qpid_proton'
 
-class SmokeTest < Minitest::Test
+class SmokeTest < Test::Unit::TestCase
 
   Messenger = Qpid::Proton::Messenger
   Message = Qpid::Proton::Message


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[13/35] qpid-proton git commit: PROTON-749: Split transport into server/client sides - This allows the server and client sides of the transport to have different default behaviours. - We set the SASL client/server from the transport setting - There are

Posted by gs...@apache.org.
PROTON-749: Split transport into server/client sides
- This allows the server and client sides of the transport
  to have different default behaviours.
- We set the SASL client/server from the transport setting
- There are some workarounds in the tests because the full logic isn't
  implemented in proton-j, but the shared python tests must run against both.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9c9872b5
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9c9872b5
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9c9872b5

Branch: refs/heads/examples
Commit: 9c9872b570664229b3199448c69fd27bf7d325bc
Parents: df02900
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Aug 15 18:25:31 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Nov 19 17:21:29 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/proton.py              | 35 ++++++++++++--------
 proton-c/include/proton/cproton.i               | 14 +-------
 proton-c/include/proton/sasl.h                  | 21 +-----------
 proton-c/include/proton/transport.h             | 20 ++++++++++-
 proton-c/src/engine/engine-internal.h           |  1 +
 proton-c/src/messenger/messenger.c              |  3 +-
 proton-c/src/posix/driver.c                     |  8 +++--
 proton-c/src/proton.c                           | 10 ++----
 proton-c/src/sasl/sasl.c                        | 33 +++++-------------
 proton-c/src/tests/engine.c                     |  3 ++
 proton-c/src/transport/transport.c              |  9 ++++-
 proton-c/src/windows/driver.c                   |  7 ++--
 .../qpid/proton/engine/impl/SaslImpl.java       |  7 +++-
 proton-j/src/main/resources/cengine.py          |  5 ++-
 proton-j/src/main/resources/csasl.py            | 14 ++++----
 tests/python/proton_tests/common.py             |  1 -
 tests/python/proton_tests/engine.py             |  3 --
 tests/python/proton_tests/sasl.py               | 14 ++------
 18 files changed, 95 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/bindings/python/proton.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton.py b/proton-c/bindings/python/proton.py
index 81104f0..573ec14 100644
--- a/proton-c/bindings/python/proton.py
+++ b/proton-c/bindings/python/proton.py
@@ -2984,12 +2984,28 @@ class Transport(object):
   TRACE_FRM = PN_TRACE_FRM
   TRACE_RAW = PN_TRACE_RAW
 
-  def __init__(self, _trans=None):
-    if not _trans:
+  CLIENT = 1
+  SERVER = 2
+
+  @staticmethod
+  def _wrap_transport(c_trans):
+    if not c_trans: return None
+    wrapper = Transport(_trans=c_trans)
+    return wrapper
+
+  def __init__(self, mode=None, _trans=None):
+    if not mode and not _trans:
       self._trans = pn_transport()
-    else:
+    elif not mode:
       self._shared_trans = True
       self._trans = _trans
+    elif mode==Transport.CLIENT:
+      self._trans = pn_transport()
+    elif mode==Transport.SERVER:
+      self._trans = pn_transport()
+      pn_transport_set_server(self._trans)
+    else:
+      raise TransportException("Cannot initialise Transport from mode: %s" % str(mode))
     self._sasl = None
     self._ssl = None
 
@@ -3177,12 +3193,6 @@ class SASL(object):
   def mechanisms(self, mechs):
     pn_sasl_mechanisms(self._sasl, mechs)
 
-  def client(self):
-    pn_sasl_client(self._sasl)
-
-  def server(self):
-    pn_sasl_server(self._sasl)
-
   def allow_skip(self, allow):
     pn_sasl_allow_skip(self._sasl, allow)
 
@@ -3216,7 +3226,6 @@ class SASL(object):
   def done(self, outcome):
     pn_sasl_done(self._sasl, outcome)
 
-  STATE_CONF = PN_SASL_CONF
   STATE_IDLE = PN_SASL_IDLE
   STATE_STEP = PN_SASL_STEP
   STATE_PASS = PN_SASL_PASS
@@ -3355,7 +3364,7 @@ wrappers = {
   "pn_session": lambda x: Session._wrap_session(pn_cast_pn_session(x)),
   "pn_link": lambda x: Link._wrap_link(pn_cast_pn_link(x)),
   "pn_delivery": lambda x: Delivery._wrap_delivery(pn_cast_pn_delivery(x)),
-  "pn_transport": lambda x: Transport(pn_cast_pn_transport(x))
+  "pn_transport": lambda x: Transport._wrap_transport(pn_cast_pn_transport(x))
 }
 
 class Collector:
@@ -3590,9 +3599,7 @@ class Connector(object):
   @property
   def transport(self):
     trans = pn_connector_transport(self._cxtr)
-    if trans:
-      return Transport(trans)
-    return None
+    return Transport._wrap_transport(trans)
 
   def close(self):
     return pn_connector_close(self._cxtr)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/include/proton/cproton.i
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/cproton.i b/proton-c/include/proton/cproton.i
index dd35c0a..3c5a1a6 100644
--- a/proton-c/include/proton/cproton.i
+++ b/proton-c/include/proton/cproton.i
@@ -87,7 +87,7 @@ typedef unsigned long int uintptr_t;
                  PN_SASL_SYS, PN_SASL_PERM, PN_SASL_TEMP, PN_SASL_SKIPPED);
 
 %aggregate_check(int, check_sasl_state,
-                 PN_SASL_CONF, PN_SASL_IDLE, PN_SASL_STEP,
+                 PN_SASL_IDLE, PN_SASL_STEP,
                  PN_SASL_PASS, PN_SASL_FAIL);
 
 
@@ -995,18 +995,6 @@ typedef unsigned long int uintptr_t;
   sasl != NULL;
 }
 
-%contract pn_sasl_client(pn_sasl_t *sasl)
-{
- require:
-  sasl != NULL;
-}
-
-%contract pn_sasl_server(pn_sasl_t *sasl)
-{
- require:
-  sasl != NULL;
-}
-
 %contract pn_sasl_allow_skip(pn_sasl_t *sasl, bool allow)
 {
  require:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/include/proton/sasl.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/sasl.h b/proton-c/include/proton/sasl.h
index 84ddf10..ab64e13 100644
--- a/proton-c/include/proton/sasl.h
+++ b/proton-c/include/proton/sasl.h
@@ -60,7 +60,6 @@ typedef enum {
 
 /** The state of the SASL negotiation process */
 typedef enum {
-  PN_SASL_CONF,    /** Pending configuration by application */
   PN_SASL_IDLE,    /** Pending SASL Init */
   PN_SASL_STEP,    /** negotiation in progress */
   PN_SASL_PASS,    /** negotiation completed successfully */
@@ -96,24 +95,6 @@ PN_EXTERN void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms);
  */
 PN_EXTERN const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl);
 
-/** Configure the SASL layer to act as a SASL client.
- *
- * The role of client is similar to a TCP client - the peer requesting
- * the connection.
- *
- * @param[in] sasl the SASL layer to configure as a client
- */
-PN_EXTERN void pn_sasl_client(pn_sasl_t *sasl);
-
-/** Configure the SASL layer to act as a server.
- *
- * The role of server is similar to a TCP server - the peer accepting
- * the connection.
- *
- * @param[in] sasl the SASL layer to configure as a server
- */
-PN_EXTERN void pn_sasl_server(pn_sasl_t *sasl);
-
 /** Configure a SASL server layer to permit the client to skip the SASL exchange.
  *
  * If the peer client skips the SASL exchange (i.e. goes right to the AMQP header)
@@ -124,7 +105,7 @@ PN_EXTERN void pn_sasl_server(pn_sasl_t *sasl);
  * @param[in] sasl the SASL layer to configure
  * @param[in] allow true -> allow skip; false -> forbid skip
  */
-    PN_EXTERN void pn_sasl_allow_skip(pn_sasl_t *sasl, bool allow);
+PN_EXTERN void pn_sasl_allow_skip(pn_sasl_t *sasl, bool allow);
 
 /** Configure the SASL layer to use the "PLAIN" mechanism.
  *

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/include/proton/transport.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/transport.h b/proton-c/include/proton/transport.h
index 2262e7c..537e27d 100644
--- a/proton-c/include/proton/transport.h
+++ b/proton-c/include/proton/transport.h
@@ -84,16 +84,34 @@ typedef void (*pn_tracer_t)(pn_transport_t *transport, const char *message);
 
 /**
  * Factory for creating a transport.
- *
  * A transport is used by a connection to interface with the network.
  * There can only be one connection associated with a transport. See
  * pn_transport_bind().
  *
+ * Initially a transport is configured to be a client transport. Use pn_transport_set_server()
+ * to configure the transport as a server transport.
+ *
+ * A client transport initiates outgoing connections.
+ *
+ * A client transport must be configured with the protocol layers to use and cannot
+ * configure itself automatically.
+ *
+ * A server transport accepts incoming connections. It can automatically
+ * configure itself to include the various protocol layers depending on
+ * the incoming protocol headers.
+ *
  * @return pointer to new transport
  */
 PN_EXTERN pn_transport_t *pn_transport(void);
 
 /**
+ * Configure a transport as a server
+ *
+ * @param[in] transport a transport object
+ */
+PN_EXTERN void pn_transport_set_server(pn_transport_t *transport);
+
+/**
  * Free a transport object.
  *
  * When a transport is freed, it is automatically unbound from its

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index 3960acf..ab66ef5 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -178,6 +178,7 @@ struct pn_transport_t {
   bool head_closed;
   bool done_processing; // if true, don't call pn_process again
   bool posted_idle_timeout;
+  bool server;
 };
 
 struct pn_connection_t {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/messenger/messenger.c
----------------------------------------------------------------------
diff --git a/proton-c/src/messenger/messenger.c b/proton-c/src/messenger/messenger.c
index f0df36a..b4d7fe2 100644
--- a/proton-c/src/messenger/messenger.c
+++ b/proton-c/src/messenger/messenger.c
@@ -328,13 +328,13 @@ static void pni_listener_readable(pn_selectable_t *sel)
   pn_socket_t sock = pn_accept(ctx->messenger->io, pn_selectable_fd(sel), name, 1024);
 
   pn_transport_t *t = pn_transport();
+  pn_transport_set_server(t);
 
   pn_ssl_t *ssl = pn_ssl(t);
   pn_ssl_init(ssl, ctx->domain, NULL);
   pn_sasl_t *sasl = pn_sasl(t);
 
   pn_sasl_mechanisms(sasl, "ANONYMOUS");
-  pn_sasl_server(sasl);
   pn_sasl_done(sasl, PN_SASL_OK);
 
   pn_connection_t *conn = pn_messenger_connection(ctx->messenger, sock, scheme, NULL, NULL, NULL, NULL, ctx);
@@ -960,7 +960,6 @@ static int pn_transport_config(pn_messenger_t *messenger,
     pn_sasl_plain(sasl, ctx->user, ctx->pass);
   } else {
     pn_sasl_mechanisms(sasl, "ANONYMOUS");
-    pn_sasl_client(sasl);
   }
 
   return 0;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/posix/driver.c
----------------------------------------------------------------------
diff --git a/proton-c/src/posix/driver.c b/proton-c/src/posix/driver.c
index 4bc71bb..fc583ec 100644
--- a/proton-c/src/posix/driver.c
+++ b/proton-c/src/posix/driver.c
@@ -208,6 +208,9 @@ pn_connector_t *pn_listener_accept(pn_listener_t *l)
     pn_connector_t *c = pn_connector_fd(l->driver, sock, NULL);
     snprintf(c->name, PN_NAME_MAX, "%s", name);
     c->listener = l;
+    c->transport = pn_transport();
+    pn_transport_set_server(c->transport);
+    c->sasl = pn_sasl(c->transport);
     return c;
   }
 }
@@ -264,6 +267,8 @@ pn_connector_t *pn_connector(pn_driver_t *driver, const char *host,
   pn_socket_t sock = pn_connect(driver->io, host, port);
 
   pn_connector_t *c = pn_connector_fd(driver, sock, context);
+  c->transport = pn_transport();
+  c->sasl = pn_sasl(c->transport);
   snprintf(c->name, PN_NAME_MAX, "%s:%s", host, port);
   if (driver->trace & (PN_TRACE_FRM | PN_TRACE_RAW | PN_TRACE_DRV))
     fprintf(stderr, "Connected to %s\n", c->name);
@@ -290,8 +295,7 @@ pn_connector_t *pn_connector_fd(pn_driver_t *driver, int fd, void *context)
   c->closed = false;
   c->wakeup = 0;
   c->connection = NULL;
-  c->transport = pn_transport();
-  c->sasl = pn_sasl(c->transport);
+  c->transport = NULL;
   c->input_done = false;
   c->output_done = false;
   c->context = context;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/proton.c
----------------------------------------------------------------------
diff --git a/proton-c/src/proton.c b/proton-c/src/proton.c
index 495659a..6e4f69d 100644
--- a/proton-c/src/proton.c
+++ b/proton-c/src/proton.c
@@ -132,11 +132,8 @@ void server_callback(pn_connector_t *ctor)
   while (pn_sasl_state(sasl) != PN_SASL_PASS) {
     switch (pn_sasl_state(sasl)) {
     case PN_SASL_IDLE:
-      return;
-    case PN_SASL_CONF:
       pn_sasl_mechanisms(sasl, "PLAIN ANONYMOUS");
-      pn_sasl_server(sasl);
-      break;
+      return;
     case PN_SASL_STEP:
       {
         size_t n = pn_sasl_pending(sasl);
@@ -283,15 +280,12 @@ void client_callback(pn_connector_t *ctor)
     pn_sasl_state_t st = pn_sasl_state(sasl);
     switch (st) {
     case PN_SASL_IDLE:
-      return;
-    case PN_SASL_CONF:
       if (ctx->mechanism && !strcmp(ctx->mechanism, "PLAIN")) {
         pn_sasl_plain(sasl, ctx->username, ctx->password);
       } else {
         pn_sasl_mechanisms(sasl, ctx->mechanism);
-        pn_sasl_client(sasl);
       }
-      break;
+      return;
     case PN_SASL_STEP:
       if (pn_sasl_pending(sasl)) {
         fprintf(stderr, "challenge failed\n");

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index ffa310b..90adcf6 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -42,7 +42,6 @@ struct pni_sasl_t {
   pn_buffer_t *recv_data;
   pn_sasl_outcome_t outcome;
   bool client;
-  bool configured;
   bool allow_skip;
   bool sent_init;
   bool rcvd_init;
@@ -104,8 +103,7 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
     sasl->disp = pn_dispatcher(1, transport);
     sasl->disp->batch = false;
 
-    sasl->client = false;
-    sasl->configured = false;
+    sasl->client = !transport->server;
     sasl->mechanisms = NULL;
     sasl->remote_mechanisms = NULL;
     sasl->send_data = pn_buffer(16);
@@ -131,7 +129,6 @@ pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl0)
 {
   pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
-    if (!sasl->configured) return PN_SASL_CONF;
     if (sasl->outcome == PN_SASL_NONE) {
       return sasl->rcvd_init ? PN_SASL_STEP : PN_SASL_IDLE;
     } else {
@@ -200,24 +197,6 @@ ssize_t pn_sasl_recv(pn_sasl_t *sasl0, char *bytes, size_t size)
   }
 }
 
-void pn_sasl_client(pn_sasl_t *sasl0)
-{
-  pni_sasl_t *sasl = get_sasl_internal(sasl0);
-  if (sasl) {
-    sasl->client = true;
-    sasl->configured = true;
-  }
-}
-
-void pn_sasl_server(pn_sasl_t *sasl0)
-{
-  pni_sasl_t *sasl = get_sasl_internal(sasl0);
-  if (sasl) {
-    sasl->client = false;
-    sasl->configured = true;
-  }
-}
-
 void pn_sasl_allow_skip(pn_sasl_t *sasl0, bool allow)
 {
   pni_sasl_t *sasl = get_sasl_internal(sasl0);
@@ -244,7 +223,6 @@ void pn_sasl_plain(pn_sasl_t *sasl0, const char *username, const char *password)
 
   pn_sasl_mechanisms(sasl0, "PLAIN");
   pn_sasl_send(sasl0, iresp, size);
-  pn_sasl_client(sasl0);
   free(iresp);
 }
 
@@ -253,6 +231,13 @@ void pn_sasl_done(pn_sasl_t *sasl0, pn_sasl_outcome_t outcome)
   pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     sasl->outcome = outcome;
+    // If we do this on the client it is a hack to tell us that
+    // no actual negatiation is going to happen and we can go
+    // straight to the AMQP layer
+    if (sasl->client) {
+      sasl->rcvd_done = true;
+      sasl->sent_done = true;
+    }
   }
 }
 
@@ -330,8 +315,6 @@ void pn_server_done(pn_sasl_t *sasl0)
 void pn_sasl_process(pn_transport_t *transport)
 {
   pni_sasl_t *sasl = transport->sasl;
-  if (!sasl->configured) return;
-
   if (!sasl->sent_init) {
     if (sasl->client) {
       pn_client_init(sasl);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/tests/engine.c
----------------------------------------------------------------------
diff --git a/proton-c/src/tests/engine.c b/proton-c/src/tests/engine.c
index e10e13f..87d8d95 100644
--- a/proton-c/src/tests/engine.c
+++ b/proton-c/src/tests/engine.c
@@ -129,6 +129,7 @@ int test_free_connection(int argc, char **argv)
 
     pn_connection_t *c2 = pn_connection();
     pn_transport_t  *t2 = pn_transport();
+    pn_transport_set_server(t2);
     pn_transport_bind(t2, c2);
 
     //pn_transport_trace(t1, PN_TRACE_FRM);
@@ -181,6 +182,7 @@ int test_free_session(int argc, char **argv)
 
     pn_connection_t *c2 = pn_connection();
     pn_transport_t  *t2 = pn_transport();
+    pn_transport_set_server(t2);
     pn_transport_bind(t2, c2);
 
     //pn_transport_trace(t1, PN_TRACE_FRM);
@@ -243,6 +245,7 @@ int test_free_link(int argc, char **argv)
 
     pn_connection_t *c2 = pn_connection();
     pn_transport_t  *t2 = pn_transport();
+    pn_transport_set_server(t2);
     pn_transport_bind(t2, c2);
 
     //pn_transport_trace(t1, PN_TRACE_FRM);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index 865f8c9..2d5f93a 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -199,6 +199,8 @@ static void pn_transport_initialize(void *object)
   transport->done_processing = false;
 
   transport->posted_idle_timeout = false;
+
+  transport->server = false;
 }
 
 pn_session_t *pn_channel_state(pn_transport_t *transport, uint16_t channel)
@@ -232,7 +234,7 @@ static void pn_transport_finalize(void *object);
 #define pn_transport_compare NULL
 #define pn_transport_inspect NULL
 
-pn_transport_t *pn_transport()
+pn_transport_t *pn_transport(void)
 {
   static const pn_class_t clazz = PN_CLASS(pn_transport);
   pn_transport_t *transport =
@@ -253,6 +255,11 @@ pn_transport_t *pn_transport()
   return transport;
 }
 
+void pn_transport_set_server(pn_transport_t *transport)
+{
+  transport->server = true;
+}
+
 void pn_transport_free(pn_transport_t *transport)
 {
   if (!transport) return;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-c/src/windows/driver.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/driver.c b/proton-c/src/windows/driver.c
index 43662f9..013b422 100644
--- a/proton-c/src/windows/driver.c
+++ b/proton-c/src/windows/driver.c
@@ -285,6 +285,8 @@ pn_connector_t *pn_listener_accept(pn_listener_t *l)
     pn_connector_t *c = pn_connector_fd(l->driver, sock, NULL);
     snprintf(c->name, PN_NAME_MAX, "%s", name);
     c->listener = l;
+    c->transport = pn_transport_server();
+    c->sasl = pn_sasl(c->transport);
     return c;
   }
 }
@@ -383,6 +385,8 @@ pn_connector_t *pn_connector(pn_driver_t *driver, const char *host,
 
   pn_socket_t sock = pn_connect(driver->io, host, port);
   pn_connector_t *c = pn_connector_fd(driver, sock, context);
+  c->transport = pn_transport_client();
+  c->sasl = pn_sasl(c->transport);
   snprintf(c->name, PN_NAME_MAX, "%s:%s", host, port);
   if (driver->trace & (PN_TRACE_FRM | PN_TRACE_RAW | PN_TRACE_DRV))
     fprintf(stderr, "Connected to %s\n", c->name);
@@ -412,8 +416,7 @@ pn_connector_t *pn_connector_fd(pn_driver_t *driver, pn_socket_t fd, void *conte
   c->wakeup = 0;
   c->posted_wakeup = 0;
   c->connection = NULL;
-  c->transport = pn_transport();
-  c->sasl = pn_sasl(c->transport);
+  c->transport = NULL;
   c->input_done = false;
   c->output_done = false;
   c->context = context;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
index d587abb..1a933bf 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
@@ -340,7 +340,12 @@ public class SaslImpl implements Sasl, SaslFrameBody.SaslFrameBodyHandler<Void>,
     @Override
     public void done(SaslOutcome outcome)
     {
-        checkRole(Role.SERVER);
+        // Support current hack in C code to allow producing sasl frames for
+        // ANONYMOUS in a single chunk
+        if(_role == Role.CLIENT)
+        {
+            return;
+        }
         _outcome = outcome;
         _done = true;
         _state = classifyStateFromOutcome(outcome);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-j/src/main/resources/cengine.py
----------------------------------------------------------------------
diff --git a/proton-j/src/main/resources/cengine.py b/proton-j/src/main/resources/cengine.py
index f9d4ddb..8f25a0e 100644
--- a/proton-j/src/main/resources/cengine.py
+++ b/proton-j/src/main/resources/cengine.py
@@ -865,14 +865,17 @@ def pn_delivery_settle(dlv):
   dlv.impl.settle()
 
 class pn_transport_wrapper:
-
   def __init__(self, impl):
     self.impl = impl
+    self.server = False
     self.condition = pn_condition()
 
 def pn_transport():
   return wrap(Proton.transport(), pn_transport_wrapper)
 
+def pn_transport_set_server(trans):
+  trans.server = True;
+
 def pn_transport_get_max_frame(trans):
   return trans.impl.getMaxFrameSize()
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/proton-j/src/main/resources/csasl.py
----------------------------------------------------------------------
diff --git a/proton-j/src/main/resources/csasl.py b/proton-j/src/main/resources/csasl.py
index a24246d..fe184d8 100644
--- a/proton-j/src/main/resources/csasl.py
+++ b/proton-j/src/main/resources/csasl.py
@@ -38,10 +38,14 @@ PN_SASL_PASS = 3
 PN_SASL_FAIL = 4
 
 def pn_sasl(tp):
-  return tp.impl.sasl()
+  sasl = tp.impl.sasl()
+  if tp.server:
+    sasl.server()
+  else:
+    sasl.client()
+  return sasl
 
 SASL_STATES = {
-  Sasl.SaslState.PN_SASL_CONF: PN_SASL_CONF,
   Sasl.SaslState.PN_SASL_IDLE: PN_SASL_IDLE,
   Sasl.SaslState.PN_SASL_STEP: PN_SASL_STEP,
   Sasl.SaslState.PN_SASL_PASS: PN_SASL_PASS,
@@ -74,12 +78,6 @@ def pn_sasl_state(sasl):
 def pn_sasl_mechanisms(sasl, mechs):
   sasl.setMechanisms(*mechs.split())
 
-def pn_sasl_client(sasl):
-  sasl.client()
-
-def pn_sasl_server(sasl):
-  sasl.server()
-
 def pn_sasl_allow_skip(sasl, allow):
   sasl.allowSkip(allow)
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/tests/python/proton_tests/common.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/common.py b/tests/python/proton_tests/common.py
index e0887e6..d159214 100644
--- a/tests/python/proton_tests/common.py
+++ b/tests/python/proton_tests/common.py
@@ -178,7 +178,6 @@ class TestServer(object):
     """
     sasl = cxtr.sasl()
     sasl.mechanisms("ANONYMOUS")
-    sasl.server()
     cxtr.connection = Connection()
     if "idle_timeout" in self.args:
       cxtr.transport.idle_timeout = self.args["idle_timeout"]

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/tests/python/proton_tests/engine.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/engine.py b/tests/python/proton_tests/engine.py
index d17a57c..6a07aea 100644
--- a/tests/python/proton_tests/engine.py
+++ b/tests/python/proton_tests/engine.py
@@ -1823,7 +1823,6 @@ class ServerTest(Test):
     self.cxtr = self.driver.connector(self.server.host, self.server.port)
     self.cxtr.transport.idle_timeout = idle_timeout_secs
     self.cxtr.sasl().mechanisms("ANONYMOUS")
-    self.cxtr.sasl().client()
     self.conn = Connection()
     self.cxtr.connection = self.conn
     self.conn.open()
@@ -1869,7 +1868,6 @@ class ServerTest(Test):
     self.driver = Driver()
     self.cxtr = self.driver.connector(self.server.host, self.server.port)
     self.cxtr.sasl().mechanisms("ANONYMOUS")
-    self.cxtr.sasl().client()
     self.conn = Connection()
     self.cxtr.connection = self.conn
     self.conn.open()
@@ -2438,5 +2436,4 @@ class IdleTimeoutEventTest(PeerTest):
 
   def testTimeoutWithZombieServerAndSASL(self):
     sasl = self.transport.sasl()
-    sasl.client()
     self.testTimeoutWithZombieServer()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c9872b5/tests/python/proton_tests/sasl.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/sasl.py b/tests/python/proton_tests/sasl.py
index 5e353d5..c2dc005 100644
--- a/tests/python/proton_tests/sasl.py
+++ b/tests/python/proton_tests/sasl.py
@@ -29,7 +29,7 @@ class SaslTest(Test):
   def setup(self):
     self.t1 = Transport()
     self.s1 = SASL(self.t1)
-    self.t2 = Transport()
+    self.t2 = Transport(Transport.SERVER)
     self.s2 = SASL(self.t2)
 
   def pump(self):
@@ -37,12 +37,10 @@ class SaslTest(Test):
 
   def testPipelined(self):
     self.s1.mechanisms("ANONYMOUS")
-    self.s1.client()
 
     assert self.s1.outcome is None
 
     self.s2.mechanisms("ANONYMOUS")
-    self.s2.server()
     self.s2.done(SASL.OK)
 
     out1 = self.t1.peek(1024)
@@ -60,13 +58,13 @@ class SaslTest(Test):
 
   def testSaslAndAmqpInSingleChunk(self):
     self.s1.mechanisms("ANONYMOUS")
-    self.s1.client()
+    self.s1.done(SASL.OK)
 
     self.s2.mechanisms("ANONYMOUS")
-    self.s2.server()
     self.s2.done(SASL.OK)
 
     # send the server's OK to the client
+    # This is still needed for the Java impl
     out2 = self.t2.peek(1024)
     self.t2.pop(len(out2))
     self.t1.push(out2)
@@ -106,9 +104,7 @@ class SaslTest(Test):
 
   def testChallengeResponse(self):
     self.s1.mechanisms("FAKE_MECH")
-    self.s1.client()
     self.s2.mechanisms("FAKE_MECH")
-    self.s2.server()
     self.pump()
     challenge = "Who goes there!"
     self.s2.send(challenge)
@@ -130,14 +126,12 @@ class SaslTest(Test):
 
   def testPipelined2(self):
     self.s1.mechanisms("ANONYMOUS")
-    self.s1.client()
 
     out1 = self.t1.peek(1024)
     self.t1.pop(len(out1))
     self.t2.push(out1)
 
     self.s2.mechanisms("ANONYMOUS")
-    self.s2.server()
     self.s2.done(SASL.OK)
     c2 = Connection()
     c2.open()
@@ -154,7 +148,6 @@ class SaslTest(Test):
     """ PROTON-235
     """
     self.s1.mechanisms("ANONYMOUS")
-    self.s1.client()
     assert self.s1.outcome is None
 
     # self.t1.trace(Transport.TRACE_FRM)
@@ -196,7 +189,6 @@ class SaslTest(Test):
     """Verify that the server (with SASL) correctly handles a client without SASL"""
     self.t1 = Transport()
     self.s2.mechanisms("ANONYMOUS")
-    self.s2.server()
     self.s2.allow_skip(True)
     self.pump()
     assert self.s2.outcome == SASL.SKIPPED


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[35/35] qpid-proton git commit: moved supporting code into proton package

Posted by gs...@apache.org.
moved supporting code into proton package


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2f4d1ba2
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2f4d1ba2
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2f4d1ba2

Branch: refs/heads/examples
Commit: 2f4d1ba298ca69a731754d8d8d441d96c4ef211d
Parents: 805cd17
Author: Gordon Sim <gs...@redhat.com>
Authored: Wed Nov 26 17:51:36 2014 +0000
Committer: Gordon Sim <gs...@redhat.com>
Committed: Wed Nov 26 17:51:36 2014 +0000

----------------------------------------------------------------------
 proton-c/bindings/python/CMakeLists.txt     |  18 +-
 proton-c/bindings/python/proton/handlers.py | 409 +++++++++++++
 proton-c/bindings/python/proton/reactors.py | 749 +++++++++++++++++++++++
 proton-c/bindings/python/proton/utils.py    | 115 ++++
 tutorial/client.py                          |   4 +-
 tutorial/client_http.py                     |   2 +-
 tutorial/db_recv.py                         |   3 +-
 tutorial/db_send.py                         |   3 +-
 tutorial/helloworld.py                      |   4 +-
 tutorial/helloworld_blocking.py             |   4 +-
 tutorial/helloworld_direct.py               |   4 +-
 tutorial/helloworld_direct_tornado.py       |   2 +-
 tutorial/helloworld_tornado.py              |   2 +-
 tutorial/proton_handlers.py                 | 409 -------------
 tutorial/proton_reactors.py                 | 749 -----------------------
 tutorial/proton_server.py                   |   4 +-
 tutorial/proton_tornado.py                  |   2 +-
 tutorial/proton_utils.py                    | 115 ----
 tutorial/recurring_timer.py                 |   2 +-
 tutorial/selected_recv.py                   |  12 +-
 tutorial/server.py                          |   4 +-
 tutorial/server_tx.py                       |   4 +-
 tutorial/simple_recv.py                     |   4 +-
 tutorial/simple_send.py                     |   4 +-
 tutorial/sync_client.py                     |   4 +-
 tutorial/tx_recv.py                         |   4 +-
 tutorial/tx_recv_interactive.py             |   4 +-
 tutorial/tx_send.py                         |   4 +-
 tutorial/tx_send_sync.py                    |   4 +-
 29 files changed, 1331 insertions(+), 1317 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/proton-c/bindings/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/CMakeLists.txt b/proton-c/bindings/python/CMakeLists.txt
index eb53174..a369661 100644
--- a/proton-c/bindings/python/CMakeLists.txt
+++ b/proton-c/bindings/python/CMakeLists.txt
@@ -53,9 +53,14 @@ if (NOT PYTHON_SITEARCH_PACKAGES)
 endif()
 
 set (pysrc-generated cproton.py)
-set (pysrc proton/__init__.py)
+set (pysrc
+    proton/__init__.py
+    proton/handlers.py
+    proton/reactors.py
+    proton/utils.py
+    )
 
-macro (py_compile directory files artifacts)
+macro (py_compile artifacts directory files)
   foreach (src_file ${files})
     install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile ${src_file}
                                   WORKING_DIRECTORY ${directory})")
@@ -67,8 +72,13 @@ macro (py_compile directory files artifacts)
   endforeach (src_file)
 endmacro(py_compile)
 
-py_compile(${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated} CPROTON_ARTIFACTS)
-py_compile(${CMAKE_CURRENT_SOURCE_DIR} ${pysrc} PROTON_ARTIFACTS)
+py_compile(CPROTON_ARTIFACTS ${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated})
+#FIXME: can't get following to work; only appends artefacts for first in list
+#py_compile(PROTON_ARTIFACTS ${CMAKE_CURRENT_SOURCE_DIR} ${pysrc})
+py_compile(PROTON_ARTIFACTS ${CMAKE_CURRENT_SOURCE_DIR} proton/__init__.py)
+py_compile(PROTON_ARTIFACTS ${CMAKE_CURRENT_SOURCE_DIR} proton/handlers.py)
+py_compile(PROTON_ARTIFACTS ${CMAKE_CURRENT_SOURCE_DIR} proton/reactors.py)
+py_compile(PROTON_ARTIFACTS ${CMAKE_CURRENT_SOURCE_DIR} proton/utils.py)
 
 find_program(EPYDOC_EXE epydoc)
 mark_as_advanced (EPYDOC_EXE)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/proton-c/bindings/python/proton/handlers.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton/handlers.py b/proton-c/bindings/python/proton/handlers.py
new file mode 100644
index 0000000..c0d9685
--- /dev/null
+++ b/proton-c/bindings/python/proton/handlers.py
@@ -0,0 +1,409 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+import heapq, os, Queue, re, socket, time, types
+from proton import dispatch, generate_uuid, PN_ACCEPTED, SASL, symbol, ulong, Url
+from proton import Collector, Connection, Delivery, Described, Endpoint, Event, Link, Terminus, Timeout
+from proton import Message, Handler, ProtonException, Transport, TransportException, ConnectionException
+from select import select
+
+class FlowController(Handler):
+
+    def __init__(self, window=1):
+        self.window = window
+
+    def top_up(self, link):
+        delta = self.window - link.credit
+        link.flow(delta)
+
+    def on_link_local_open(self, event):
+        if event.link.is_receiver:
+            self.top_up(event.link)
+
+    def on_link_remote_open(self, event):
+        if event.link.is_receiver:
+            self.top_up(event.link)
+
+    def on_link_flow(self, event):
+        if event.link.is_receiver:
+            self.top_up(event.link)
+
+    def on_delivery(self, event):
+        if not event.delivery.released and event.delivery.link.is_receiver:
+            self.top_up(event.delivery.link)
+
+def nested_handlers(handlers):
+    # currently only allows for a single level of nesting
+    nested = []
+    for h in handlers:
+        nested.append(h)
+        if hasattr(h, 'handlers'):
+            nested.extend(getattr(h, 'handlers'))
+    return nested
+
+def add_nested_handler(handler, nested):
+    if hasattr(handler, 'handlers'):
+        getattr(handler, 'handlers').append(nested)
+    else:
+        handler.handlers = [nested]
+
+class ScopedHandler(Handler):
+
+    scopes = {
+        "pn_connection": ["connection"],
+        "pn_session": ["session", "connection"],
+        "pn_link": ["link", "session", "connection"],
+        "pn_delivery": ["delivery", "link", "session", "connection"]
+    }
+
+    def on_unhandled(self, method, args):
+        event = args[0]
+        if event.type in [Event.CONNECTION_FINAL, Event.SESSION_FINAL, Event.LINK_FINAL]:
+            return
+        objects = [getattr(event, attr) for attr in self.scopes.get(event.clazz, [])]
+        targets = [getattr(o, "context") for o in objects if hasattr(o, "context")]
+        handlers = [getattr(t, event.type.method) for t in nested_handlers(targets) if hasattr(t, event.type.method)]
+        for h in handlers:
+            h(event)
+
+class OutgoingMessageHandler(Handler):
+    def __init__(self, auto_settle=True, delegate=None):
+        self.auto_settle = auto_settle
+        self.delegate = delegate
+
+    def on_link_flow(self, event):
+        if event.link.is_sender and event.link.credit:
+            self.on_credit(event)
+
+    def on_delivery(self, event):
+        dlv = event.delivery
+        if dlv.released: return
+        if dlv.link.is_sender and dlv.updated:
+            if dlv.remote_state == Delivery.ACCEPTED:
+                self.on_accepted(event)
+            elif dlv.remote_state == Delivery.REJECTED:
+                self.on_rejected(event)
+            elif dlv.remote_state == Delivery.RELEASED:
+                self.on_released(event)
+            elif dlv.remote_state == Delivery.MODIFIED:
+                self.on_modified(event)
+            if dlv.settled:
+                self.on_settled(event)
+            if self.auto_settle:
+                dlv.settle()
+
+    def on_credit(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_credit', event)
+
+    def on_accepted(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_accepted', event)
+
+    def on_rejected(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_rejected', event)
+
+    def on_released(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_released', event)
+
+    def on_modified(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_modified', event)
+
+    def on_settled(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_settled', event)
+
+def recv_msg(delivery):
+    msg = Message()
+    msg.decode(delivery.link.recv(delivery.pending))
+    delivery.link.advance()
+    return msg
+
+class Reject(ProtonException):
+  """
+  An exception that indicate a message should be rejected
+  """
+  pass
+
+class Acking(object):
+    def accept(self, delivery):
+        self.settle(delivery, Delivery.ACCEPTED)
+
+    def reject(self, delivery):
+        self.settle(delivery, Delivery.REJECTED)
+
+    def release(self, delivery, delivered=True):
+        if delivered:
+            self.settle(delivery, Delivery.MODIFIED)
+        else:
+            self.settle(delivery, Delivery.RELEASED)
+
+    def settle(self, delivery, state=None):
+        if state:
+            delivery.update(state)
+        delivery.settle()
+
+class IncomingMessageHandler(Handler, Acking):
+    def __init__(self, auto_accept=True, delegate=None):
+        self.delegate = delegate
+        self.auto_accept = auto_accept
+
+    def on_delivery(self, event):
+        dlv = event.delivery
+        if dlv.released or not dlv.link.is_receiver: return
+        if dlv.readable and not dlv.partial:
+            event.message = recv_msg(dlv)
+            try:
+                self.on_message(event)
+                if self.auto_accept:
+                    dlv.update(Delivery.ACCEPTED)
+                    dlv.settle()
+            except Reject:
+                dlv.update(Delivery.REJECTED)
+                dlv.settle()
+        elif dlv.updated and dlv.settled:
+            self.on_settled(event)
+
+    def on_message(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_message', event)
+
+    def on_settled(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_settled', event)
+
+class EndpointStateHandler(Handler):
+    def __init__(self, peer_close_is_error=False, delegate=None):
+        self.delegate = delegate
+        self.peer_close_is_error = peer_close_is_error
+
+    def is_local_open(self, endpoint):
+        return endpoint.state & Endpoint.LOCAL_ACTIVE
+
+    def is_local_uninitialised(self, endpoint):
+        return endpoint.state & Endpoint.LOCAL_UNINIT
+
+    def is_local_closed(self, endpoint):
+        return endpoint.state & Endpoint.LOCAL_CLOSED
+
+    def is_remote_open(self, endpoint):
+        return endpoint.state & Endpoint.REMOTE_ACTIVE
+
+    def is_remote_closed(self, endpoint):
+        return endpoint.state & Endpoint.REMOTE_CLOSED
+
+    def print_error(self, endpoint, endpoint_type):
+        if endpoint.remote_condition:
+            print endpoint.remote_condition.description
+        elif self.is_local_open(endpoint) and self.is_remote_closed(endpoint):
+            print "%s closed by peer" % endpoint_type
+
+    def on_link_remote_close(self, event):
+        if event.link.remote_condition:
+            self.on_link_error(event)
+        elif self.is_local_closed(event.link):
+            self.on_link_closed(event)
+        else:
+            self.on_link_closing(event)
+        event.link.close()
+
+    def on_session_remote_close(self, event):
+        if event.session.remote_condition:
+            self.on_session_error(event)
+        elif self.is_local_closed(event.session):
+            self.on_session_closed(event)
+        else:
+            self.on_session_closing(event)
+        event.session.close()
+
+    def on_connection_remote_close(self, event):
+        if event.connection.remote_condition:
+            self.on_connection_error(event)
+        elif self.is_local_closed(event.connection):
+            self.on_connection_closed(event)
+        else:
+            self.on_connection_closing(event)
+        event.connection.close()
+
+    def on_connection_local_open(self, event):
+        if self.is_remote_open(event.connection):
+            self.on_connection_opened(event)
+
+    def on_connection_remote_open(self, event):
+        if self.is_local_open(event.connection):
+            self.on_connection_opened(event)
+        elif self.is_local_uninitialised(event.connection):
+            self.on_connection_opening(event)
+            event.connection.open()
+
+    def on_session_local_open(self, event):
+        if self.is_remote_open(event.session):
+            self.on_session_opened(event)
+
+    def on_session_remote_open(self, event):
+        if self.is_local_open(event.session):
+            self.on_session_opened(event)
+        elif self.is_local_uninitialised(event.session):
+            self.on_session_opening(event)
+            event.session.open()
+
+    def on_link_local_open(self, event):
+        if self.is_remote_open(event.link):
+            self.on_link_opened(event)
+
+    def on_link_remote_open(self, event):
+        if self.is_local_open(event.link):
+            self.on_link_opened(event)
+        elif self.is_local_uninitialised(event.link):
+            self.on_link_opening(event)
+            event.link.open()
+
+    def on_connection_opened(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_connection_opened', event)
+
+    def on_session_opened(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_session_opened', event)
+
+    def on_link_opened(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_link_opened', event)
+
+    def on_connection_opening(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_connection_opening', event)
+
+    def on_session_opening(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_session_opening', event)
+
+    def on_link_opening(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_link_opening', event)
+
+    def on_connection_error(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_connection_error', event)
+        else:
+            self.print_error(event.connection, "connection")
+
+    def on_session_error(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_session_error', event)
+        else:
+            self.print_error(event.session, "session")
+            event.connection.close()
+
+    def on_link_error(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_link_error', event)
+        else:
+            self.print_error(event.link, "link")
+            event.connection.close()
+
+    def on_connection_closed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_connection_closed', event)
+
+    def on_session_closed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_session_closed', event)
+
+    def on_link_closed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_link_closed', event)
+
+    def on_connection_closing(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_connection_closing', event)
+        elif self.peer_close_is_error:
+            self.on_connection_error(event)
+
+    def on_session_closing(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_session_closing', event)
+        elif self.peer_close_is_error:
+            self.on_session_error(event)
+
+    def on_link_closing(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_link_closing', event)
+        elif self.peer_close_is_error:
+            self.on_link_error(event)
+
+class MessagingHandler(Handler, Acking):
+    def __init__(self, prefetch=10, auto_accept=True, auto_settle=True, peer_close_is_error=False):
+        self.handlers = []
+        # FlowController if used needs to see event before
+        # IncomingMessageHandler, as the latter may involve the
+        # delivery being released
+        if prefetch:
+            self.handlers.append(FlowController(prefetch))
+        self.handlers.append(EndpointStateHandler(peer_close_is_error, self))
+        self.handlers.append(IncomingMessageHandler(auto_accept, self))
+        self.handlers.append(OutgoingMessageHandler(auto_settle, self))
+
+class TransactionalAcking(object):
+    def accept(self, delivery, transaction):
+        transaction.accept(delivery)
+
+class TransactionHandler(OutgoingMessageHandler, TransactionalAcking):
+    def __init__(self, auto_settle=True, delegate=None):
+        super(TransactionHandler, self).__init__(auto_settle, delegate)
+
+    def on_settled(self, event):
+        if hasattr(event.delivery, "transaction"):
+            event.transaction = event.delivery.transaction
+            event.delivery.transaction.handle_outcome(event)
+
+    def on_transaction_declared(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_transaction_declared', event)
+
+    def on_transaction_committed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_transaction_committed', event)
+
+    def on_transaction_aborted(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_transaction_aborted', event)
+
+    def on_transaction_declare_failed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_transaction_declare_failed', event)
+
+    def on_transaction_commit_failed(self, event):
+        if self.delegate:
+            dispatch(self.delegate, 'on_transaction_commit_failed', event)
+
+class TransactionalClientHandler(Handler, TransactionalAcking):
+    def __init__(self, prefetch=10, auto_accept=False, auto_settle=True, peer_close_is_error=False):
+        super(TransactionalClientHandler, self).__init__()
+        self.handlers = []
+        # FlowController if used needs to see event before
+        # IncomingMessageHandler, as the latter may involve the
+        # delivery being released
+        if prefetch:
+            self.handlers.append(FlowController(prefetch))
+        self.handlers.append(EndpointStateHandler(peer_close_is_error, self))
+        self.handlers.append(IncomingMessageHandler(auto_accept, self))
+        self.handlers.append(TransactionHandler(auto_settle, self))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/proton-c/bindings/python/proton/reactors.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton/reactors.py b/proton-c/bindings/python/proton/reactors.py
new file mode 100644
index 0000000..3e96a56
--- /dev/null
+++ b/proton-c/bindings/python/proton/reactors.py
@@ -0,0 +1,749 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+import heapq, os, Queue, socket, time, types
+from proton import dispatch, generate_uuid, PN_ACCEPTED, SASL, symbol, ulong, Url
+from proton import Collector, Connection, Delivery, Described, Endpoint, Event, Link, Terminus, Timeout
+from proton import Message, Handler, ProtonException, Transport, TransportException, ConnectionException
+from select import select
+from proton.handlers import nested_handlers, ScopedHandler
+
+
+class AmqpSocket(object):
+
+    def __init__(self, conn, sock, events, heartbeat=None):
+        self.events = events
+        self.conn = conn
+        self.transport = Transport()
+        if heartbeat: self.transport.idle_timeout = heartbeat
+        self.transport.bind(self.conn)
+        self.socket = sock
+        self.socket.setblocking(0)
+        self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+        self.write_done = False
+        self.read_done = False
+        self._closed = False
+
+    def accept(self, force_sasl=True):
+        if force_sasl:
+            sasl = self.transport.sasl()
+            sasl.mechanisms("ANONYMOUS")
+            sasl.server()
+            sasl.done(SASL.OK)
+        #TODO: use SASL anyway if requested by peer
+        return self
+
+    def connect(self, host, port=None, username=None, password=None, force_sasl=True):
+        if username and password:
+            sasl = self.transport.sasl()
+            sasl.plain(username, password)
+        elif force_sasl:
+            sasl = self.transport.sasl()
+            sasl.mechanisms('ANONYMOUS')
+            sasl.client()
+        try:
+            self.socket.connect_ex((host, port or 5672))
+        except socket.gaierror, e:
+            raise ConnectionException("Cannot resolve '%s': %s" % (host, e))
+        return self
+
+    def _closed_cleanly(self):
+        return self.conn.state & Endpoint.LOCAL_CLOSED and self.conn.state & Endpoint.REMOTE_CLOSED
+
+    def closed(self):
+        if not self._closed and self.write_done and self.read_done:
+            self.close()
+            return True
+        else:
+            return False
+
+    def close(self):
+        self.socket.close()
+        self._closed = True
+
+    def fileno(self):
+        return self.socket.fileno()
+
+    def reading(self):
+        if self.read_done: return False
+        c = self.transport.capacity()
+        if c > 0:
+            return True
+        elif c < 0:
+            self.read_done = True
+        return False
+
+    def writing(self):
+        if self.write_done: return False
+        try:
+            p = self.transport.pending()
+            if p > 0:
+                return True
+            elif p < 0:
+                self.write_done = True
+                return False
+            else: # p == 0
+                return False
+        except TransportException, e:
+            self.write_done = True
+            return False
+
+    def readable(self):
+        c = self.transport.capacity()
+        if c > 0:
+            try:
+                data = self.socket.recv(c)
+                if data:
+                    self.transport.push(data)
+                else:
+                    if not self._closed_cleanly():
+                        self.read_done = True
+                        self.write_done = True
+                    else:
+                        self.transport.close_tail()
+            except TransportException, e:
+                print "Error on read: %s" % e
+                self.read_done = True
+            except socket.error, e:
+                print "Error on recv: %s" % e
+                self.read_done = True
+                self.write_done = True
+        elif c < 0:
+            self.read_done = True
+
+    def writable(self):
+        try:
+            p = self.transport.pending()
+            if p > 0:
+                data = self.transport.peek(p)
+                n = self.socket.send(data)
+                self.transport.pop(n)
+            elif p < 0:
+                self.write_done = True
+        except TransportException, e:
+            print "Error on write: %s" % e
+            self.write_done = True
+        except socket.error, e:
+            print "Error on send: %s" % e
+            self.write_done = True
+
+    def removed(self):
+        if not self._closed_cleanly():
+            self.transport.unbind()
+            self.events.dispatch(ApplicationEvent("disconnected", connection=self.conn))
+
+    def tick(self):
+        t = self.transport.tick(time.time())
+        if t: return t - time.time()
+        else: return None
+
+class Acceptor:
+
+    def __init__(self, events, loop, host, port):
+        self.events = events
+        self.loop = loop
+        self.socket = socket.socket()
+        self.socket.setblocking(0)
+        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.socket.bind((host, port))
+        self.socket.listen(5)
+        self.loop.add(self)
+        self._closed = False
+
+    def closed(self):
+        if self._closed:
+            self.socket.close()
+            return True
+        else:
+            return False
+
+    def close(self):
+        self._closed = True
+
+    def fileno(self):
+        return self.socket.fileno()
+
+    def reading(self):
+        return not self._closed
+
+    def writing(self):
+        return False
+
+    def readable(self):
+        sock, addr = self.socket.accept()
+        if sock:
+            self.loop.add(AmqpSocket(self.events.connection(), sock, self.events).accept())
+
+    def removed(self): pass
+    def tick(self): return None
+
+class EventInjector(object):
+    def __init__(self, events):
+        self.events = events
+        self.queue = Queue.Queue()
+        self.pipe = os.pipe()
+        self._closed = False
+
+    def trigger(self, event):
+        self.queue.put(event)
+        os.write(self.pipe[1], "!")
+
+    def closed(self):
+        return self._closed and self.queue.empty()
+
+    def close(self):
+        self._closed = True
+
+    def fileno(self):
+        return self.pipe[0]
+
+    def reading(self):
+        return True
+
+    def writing(self):
+        return False
+
+    def readable(self):
+        os.read(self.pipe[0], 512)
+        while not self.queue.empty():
+            self.events.dispatch(self.queue.get())
+
+    def removed(self): pass
+    def tick(self): return None
+
+class Events(object):
+    def __init__(self, *handlers):
+        self.collector = Collector()
+        self.handlers = handlers
+
+    def connection(self):
+        conn = Connection()
+        conn.collect(self.collector)
+        return conn
+
+    def process(self):
+        while True:
+            ev = self.collector.peek()
+            if ev:
+                self.dispatch(ev)
+                self.collector.pop()
+            else:
+                return
+
+    def dispatch(self, event):
+        for h in self.handlers:
+            event.dispatch(h)
+
+    @property
+    def next_interval(self):
+        return None
+
+    @property
+    def empty(self):
+        return self.collector.peek() == None
+
+class ExtendedEventType(object):
+    def __init__(self, name):
+        self.name = name
+        self.method = "on_%s" % name
+
+class ApplicationEvent(Event):
+    def __init__(self, typename, connection=None, session=None, link=None, delivery=None, subject=None):
+        self.type = ExtendedEventType(typename)
+        self.subject = subject
+        if delivery:
+            self.context = delivery
+            self.clazz = "pn_delivery"
+        elif link:
+            self.context = link
+            self.clazz = "pn_link"
+        elif session:
+            self.context = session
+            self.clazz = "pn_session"
+        elif connection:
+            self.context = connection
+            self.clazz = "pn_connection"
+        else:
+            self.context = None
+            self.clazz = "none"
+
+    def __repr__(self):
+        objects = [self.context, self.subject]
+        return "%s(%s)" % (self.type.name,
+                           ", ".join([str(o) for o in objects if o is not None]))
+
+class StartEvent(ApplicationEvent):
+    def __init__(self, reactor):
+        super(StartEvent, self).__init__("start")
+        self.reactor = reactor
+
+class ScheduledEvents(Events):
+    def __init__(self, *handlers):
+        super(ScheduledEvents, self).__init__(*handlers)
+        self._events = []
+
+    def schedule(self, deadline, event):
+        heapq.heappush(self._events, (deadline, event))
+
+    def process(self):
+        super(ScheduledEvents, self).process()
+        while self._events and self._events[0][0] <= time.time():
+            self.dispatch(heapq.heappop(self._events)[1])
+
+    @property
+    def next_interval(self):
+        if len(self._events):
+            deadline = self._events[0][0]
+            now = time.time()
+            return deadline - now if deadline > now else 0
+        else:
+            return None
+
+    @property
+    def empty(self):
+        return super(ScheduledEvents, self).empty and len(self._events) == 0
+
+def _min(a, b):
+    if a and b: return min(a, b)
+    elif a: return a
+    else: return b
+
+class SelectLoop(object):
+
+    def __init__(self, events):
+        self.events = events
+        self.selectables = []
+        self._abort = False
+
+    def abort(self):
+        self._abort = True
+
+    def add(self, selectable):
+        self.selectables.append(selectable)
+
+    def remove(self, selectable):
+        self.selectables.remove(selectable)
+
+    @property
+    def redundant(self):
+        return self.events.empty and not self.selectables
+
+    @property
+    def aborted(self):
+        return self._abort
+
+    def run(self):
+        while not (self._abort or self.redundant):
+            self.do_work()
+
+    def do_work(self, timeout=None):
+        """@return True if some work was done, False if time-out expired"""
+        self.events.process()
+        if self._abort: return
+
+        stable = False
+        while not stable:
+            reading = []
+            writing = []
+            closed = []
+            tick = None
+            for s in self.selectables:
+                if s.reading(): reading.append(s)
+                if s.writing(): writing.append(s)
+                if s.closed(): closed.append(s)
+                else: tick = _min(tick, s.tick())
+
+            for s in closed:
+                self.selectables.remove(s)
+                s.removed()
+            stable = len(closed) == 0
+
+        if self.redundant:
+            return
+
+        if timeout and timeout < 0:
+            timeout = 0
+        if self.events.next_interval and (timeout is None or self.events.next_interval < timeout):
+            timeout = self.events.next_interval
+        if tick:
+            timeout = _min(tick, timeout)
+        if reading or writing or timeout:
+            readable, writable, _ = select(reading, writing, [], timeout)
+            for s in self.selectables:
+                s.tick()
+            for s in readable:
+                s.readable()
+            for s in writable:
+                s.writable()
+
+            return bool(readable or writable)
+        else:
+            return False
+
+def delivery_tags():
+    count = 1
+    while True:
+        yield str(count)
+        count += 1
+
+def send_msg(sender, msg, tag=None, handler=None, transaction=None):
+    dlv = sender.delivery(tag or next(sender.tags))
+    if transaction:
+        dlv.local.data = [transaction.id]
+        dlv.update(0x34)
+    if handler:
+        dlv.context = handler
+    sender.send(msg.encode())
+    sender.advance()
+    return dlv
+
+def _send_msg(self, msg, tag=None, handler=None, transaction=None):
+    return send_msg(self, msg, tag, handler, transaction)
+
+
+class Transaction(object):
+    def __init__(self, txn_ctrl, handler, settle_before_discharge=False):
+        self.txn_ctrl = txn_ctrl
+        self.handler = handler
+        self.id = None
+        self._declare = None
+        self._discharge = None
+        self.failed = False
+        self._pending = []
+        self.settle_before_discharge = settle_before_discharge
+        self.declare()
+
+    def commit(self):
+        self.discharge(False)
+
+    def abort(self):
+        self.discharge(True)
+
+    def declare(self):
+        self._declare = self._send_ctrl(symbol(u'amqp:declare:list'), [None])
+
+    def discharge(self, failed):
+        self.failed = failed
+        self._discharge = self._send_ctrl(symbol(u'amqp:discharge:list'), [self.id, failed])
+
+    def _send_ctrl(self, descriptor, value):
+        delivery = self.txn_ctrl.send_msg(Message(body=Described(descriptor, value)), handler=self.handler)
+        delivery.transaction = self
+        return delivery
+
+    def accept(self, delivery):
+        self.update(delivery, PN_ACCEPTED)
+        if self.settle_before_discharge:
+            delivery.settle()
+        else:
+            self._pending.append(delivery)
+
+    def update(self, delivery, state=None):
+        if state:
+            delivery.local.data = [self.id, Described(ulong(state), [])]
+            delivery.update(0x34)
+
+    def _release_pending(self):
+        for d in self._pending:
+            d.update(Delivery.RELEASED)
+            d.settle()
+        self._clear_pending()
+
+    def _clear_pending(self):
+        self._pending = []
+
+    def handle_outcome(self, event):
+        if event.delivery == self._declare:
+            if event.delivery.remote.data:
+                self.id = event.delivery.remote.data[0]
+                self.handler.on_transaction_declared(event)
+            elif event.delivery.remote_state == Delivery.REJECTED:
+                self.handler.on_transaction_declare_failed(event)
+            else:
+                print "Unexpected outcome for declare: %s" % event.delivery.remote_state
+                self.handler.on_transaction_declare_failed(event)
+        elif event.delivery == self._discharge:
+            if event.delivery.remote_state == Delivery.REJECTED:
+                if not self.failed:
+                    self.handler.on_transaction_commit_failed(event)
+                    self._release_pending() # make this optional?
+            else:
+                if self.failed:
+                    self.handler.on_transaction_aborted(event)
+                    self._release_pending()
+                else:
+                    self.handler.on_transaction_committed(event)
+            self._clear_pending()
+
+class LinkOption(object):
+    def apply(self, link): pass
+    def test(self, link): return True
+
+class AtMostOnce(LinkOption):
+    def apply(self, link):
+        link.snd_settle_mode = Link.SND_SETTLED
+
+class AtLeastOnce(LinkOption):
+    def apply(self, link):
+        link.snd_settle_mode = Link.SND_UNSETTLED
+        link.rcv_settle_mode = Link.RCV_FIRST
+
+class SenderOption(LinkOption):
+    def apply(self, sender): pass
+    def test(self, link): return link.is_sender
+
+class ReceiverOption(LinkOption):
+    def apply(self, receiver): pass
+    def test(self, link): return link.is_receiver
+
+class Filter(ReceiverOption):
+    def __init__(self, filter_set={}):
+        self.filter_set = filter_set
+
+    def apply(self, receiver):
+        receiver.source.filter.put_dict(self.filter_set)
+
+class Selector(Filter):
+    def __init__(self, value, name='selector'):
+        super(Selector, self).__init__({symbol(name): Described(symbol('apache.org:selector-filter:string'), value)})
+
+def _apply_link_options(options, link):
+    if options:
+        if isinstance(options, list):
+            for o in options:
+                if o.test(link): o.apply(link)
+        else:
+            if options.test(link): options.apply(link)
+
+
+class MessagingContext(object):
+    def __init__(self, conn, handler=None, ssn=None):
+        self.conn = conn
+        if handler:
+            self.conn.context = handler
+        self.conn._mc = self
+        self.ssn = ssn
+        self.txn_ctrl = None
+
+    def _get_handler(self):
+        return self.conn.context
+
+    def _set_handler(self, value):
+        self.conn.context = value
+
+    handler = property(_get_handler, _set_handler)
+
+    def create_sender(self, target, source=None, name=None, handler=None, tags=None, options=None):
+        snd = self._get_ssn().sender(name or self._get_id(target, source))
+        if source:
+            snd.source.address = source
+        if target:
+            snd.target.address = target
+        if handler:
+            snd.context = handler
+        snd.tags = tags or delivery_tags()
+        snd.send_msg = types.MethodType(_send_msg, snd)
+        _apply_link_options(options, snd)
+        snd.open()
+        return snd
+
+    def create_receiver(self, source, target=None, name=None, dynamic=False, handler=None, options=None):
+        rcv = self._get_ssn().receiver(name or self._get_id(source, target))
+        if source:
+            rcv.source.address = source
+        if dynamic:
+            rcv.source.dynamic = True
+        if target:
+            rcv.target.address = target
+        if handler:
+            rcv.context = handler
+        _apply_link_options(options, rcv)
+        rcv.open()
+        return rcv
+
+    def create_session(self):
+        return MessageContext(conn=None, ssn=self._new_ssn())
+
+    def declare_transaction(self, handler=None, settle_before_discharge=False):
+        if not self.txn_ctrl:
+            self.txn_ctrl = self.create_sender(None, name="txn-ctrl")
+            self.txn_ctrl.target.type = Terminus.COORDINATOR
+            self.txn_ctrl.target.capabilities.put_object(symbol(u'amqp:local-transactions'))
+        return Transaction(self.txn_ctrl, handler, settle_before_discharge)
+
+    def close(self):
+        if self.ssn:
+            self.ssn.close()
+        if self.conn:
+            self.conn.close()
+
+    def _get_id(self, remote, local):
+        if local and remote: "%s-%s-%s" % (self.conn.container, remote, local)
+        elif local: return "%s-%s" % (self.conn.container, local)
+        elif remote: return "%s-%s" % (self.conn.container, remote)
+        else: return "%s-%s" % (self.conn.container, str(generate_uuid()))
+
+    def _get_ssn(self):
+        if not self.ssn:
+            self.ssn = self._new_ssn()
+            self.ssn.context = self
+        return self.ssn
+
+    def _new_ssn(self):
+        ssn = self.conn.session()
+        ssn.open()
+        return ssn
+
+    def on_session_remote_close(self, event):
+        if self.conn:
+            self.conn.close()
+
+class Connector(Handler):
+    def attach_to(self, loop):
+        self.loop = loop
+
+    def _connect(self, connection):
+        host, port = connection.address.next()
+        #print "connecting to %s:%i" % (host, port)
+        heartbeat = connection.heartbeat if hasattr(connection, 'heartbeat') else None
+        self.loop.add(AmqpSocket(connection, socket.socket(), self.loop.events, heartbeat=heartbeat).connect(host, port))
+
+    def on_connection_local_open(self, event):
+        if hasattr(event.connection, "address"):
+            self._connect(event.connection)
+
+    def on_connection_remote_open(self, event):
+        if hasattr(event.connection, "reconnect"):
+            event.connection.reconnect.reset()
+
+    def on_disconnected(self, event):
+        if hasattr(event.connection, "reconnect"):
+            delay = event.connection.reconnect.next()
+            if delay == 0:
+                print "Disconnected, reconnecting..."
+                self._connect(event.connection)
+            else:
+                print "Disconnected will try to reconnect after %s seconds" % delay
+                self.loop.schedule(time.time() + delay, connection=event.connection, subject=self)
+        else:
+            print "Disconnected"
+
+    def on_timer(self, event):
+        if event.subject == self and event.connection:
+            self._connect(event.connection)
+
+class Backoff(object):
+    def __init__(self):
+        self.delay = 0
+
+    def reset(self):
+        self.delay = 0
+
+    def next(self):
+        current = self.delay
+        if current == 0:
+            self.delay = 0.1
+        else:
+            self.delay = min(10, 2*current)
+        return current
+
+class Urls(object):
+    def __init__(self, values):
+        self.values = [Url(v) for v in values]
+        self.i = iter(self.values)
+
+    def __iter__(self):
+        return self
+
+    def _as_pair(self, url):
+        return (url.host, url.port)
+
+    def next(self):
+        try:
+            return self._as_pair(self.i.next())
+        except StopIteration:
+            self.i = iter(self.values)
+            return self._as_pair(self.i.next())
+
+class EventLoop(object):
+    def __init__(self, *handlers):
+        self.connector = Connector()
+        h = [self.connector, ScopedHandler()]
+        h.extend(nested_handlers(handlers))
+        self.events = ScheduledEvents(*h)
+        self.loop = SelectLoop(self.events)
+        self.connector.attach_to(self)
+        self.trigger = None
+        self.container_id = str(generate_uuid())
+
+    def connect(self, url=None, urls=None, address=None, handler=None, reconnect=None, heartbeat=None):
+        context = MessagingContext(self.events.connection(), handler=handler)
+        context.conn.container = self.container_id or str(generate_uuid())
+        context.conn.heartbeat = heartbeat
+        if url: context.conn.address = Urls([url])
+        elif urls: context.conn.address = Urls(urls)
+        elif address: context.conn.address = address
+        else: raise ValueError("One of url, urls or address required")
+        if reconnect:
+            context.conn.reconnect = reconnect
+        elif reconnect is None:
+            context.conn.reconnect = Backoff()
+        context.conn.open()
+        return context
+
+    def listen(self, url):
+        host, port = Urls([url]).next()
+        return Acceptor(self.events, self, host, port)
+
+    def schedule(self, deadline, connection=None, session=None, link=None, delivery=None, subject=None):
+        self.events.schedule(deadline, ApplicationEvent("timer", connection, session, link, delivery, subject))
+
+    def get_event_trigger(self):
+        if not self.trigger or self.trigger.closed():
+            self.trigger = EventInjector(self.events)
+            self.add(self.trigger)
+        return self.trigger
+
+    def add(self, selectable):
+        self.loop.add(selectable)
+
+    def remove(self, selectable):
+        self.loop.remove(selectable)
+
+    def run(self):
+        self.events.dispatch(StartEvent(self))
+        self.loop.run()
+
+    def stop(self):
+        self.loop.abort()
+
+    def do_work(self, timeout=None):
+        return self.loop.do_work(timeout)
+
+EventLoop.DEFAULT = EventLoop()
+
+def connect(url=None, urls=None, address=None, handler=None, reconnect=None, eventloop=None, heartbeat=None):
+    if not eventloop:
+        eventloop = EventLoop.DEFAULT
+    return eventloop.connect(url=url, urls=urls, address=address, handler=handler, reconnect=reconnect, heartbeat=heartbeat)
+
+def run(eventloop=None):
+    if not eventloop:
+        eventloop = EventLoop.DEFAULT
+    eventloop.run()
+

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/proton-c/bindings/python/proton/utils.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton/utils.py b/proton-c/bindings/python/proton/utils.py
new file mode 100644
index 0000000..db23e55
--- /dev/null
+++ b/proton-c/bindings/python/proton/utils.py
@@ -0,0 +1,115 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+import Queue, socket, time
+from proton import ConnectionException, Endpoint, Handler, Message, Url
+from proton.reactors import AmqpSocket, Events, MessagingContext, SelectLoop, send_msg
+from proton.handlers import ScopedHandler
+
+class BlockingLink(object):
+    def __init__(self, connection, link):
+        self.connection = connection
+        self.link = link
+        self.connection.wait(lambda: not (self.link.state & Endpoint.REMOTE_UNINIT),
+                             msg="Opening link %s" % link.name)
+
+    def close(self):
+        self.connection.wait(not (self.link.state & Endpoint.REMOTE_ACTIVE),
+                             msg="Closing link %s" % link.name)
+
+    # Access to other link attributes.
+    def __getattr__(self, name): return getattr(self.link, name)
+
+class BlockingSender(BlockingLink):
+    def __init__(self, connection, sender):
+        super(BlockingSender, self).__init__(connection, sender)
+
+    def send_msg(self, msg):
+        delivery = send_msg(self.link, msg)
+        self.connection.wait(lambda: delivery.settled, msg="Sending on sender %s" % self.link.name)
+
+class BlockingReceiver(BlockingLink):
+    def __init__(self, connection, receiver, credit=1):
+        super(BlockingReceiver, self).__init__(connection, receiver)
+        if credit: receiver.flow(credit)
+
+class BlockingConnection(Handler):
+    def __init__(self, url, timeout=None):
+        self.timeout = timeout
+        self.events = Events(ScopedHandler())
+        self.loop = SelectLoop(self.events)
+        self.context = MessagingContext(self.loop.events.connection(), handler=self)
+        if isinstance(url, basestring):
+            self.url = Url(url)
+        else:
+            self.url = url
+        self.loop.add(
+            AmqpSocket(self.context.conn, socket.socket(), self.events).connect(self.url.host, self.url.port))
+        self.context.conn.open()
+        self.wait(lambda: not (self.context.conn.state & Endpoint.REMOTE_UNINIT),
+                  msg="Opening connection")
+
+    def create_sender(self, address, handler=None):
+        return BlockingSender(self, self.context.create_sender(address, handler=handler))
+
+    def create_receiver(self, address, credit=1, dynamic=False, handler=None):
+        return BlockingReceiver(
+            self, self.context.create_receiver(address, dynamic=dynamic, handler=handler), credit=credit)
+
+    def close(self):
+        self.context.conn.close()
+        self.wait(lambda: not (self.context.conn.state & Endpoint.REMOTE_ACTIVE),
+                  msg="Closing connection")
+
+    def run(self):
+        """ Hand control over to the event loop (e.g. if waiting indefinitely for incoming messages) """
+        self.loop.run()
+
+    def wait(self, condition, timeout=False, msg=None):
+        """Call do_work until condition() is true"""
+        if timeout is False:
+            timeout = self.timeout
+        if timeout is None:
+            while not condition():
+                self.loop.do_work()
+        else:
+            deadline = time.time() + timeout
+            while not condition():
+                if not self.loop.do_work(deadline - time.time()):
+                    txt = "Connection %s timed out" % self.url
+                    if msg: txt += ": " + msg
+                    raise Timeout(txt)
+
+    def on_link_remote_close(self, event):
+        if event.link.state & Endpoint.LOCAL_ACTIVE:
+            self.closed(event.link.remote_condition)
+
+    def on_connection_remote_close(self, event):
+        if event.connection.state & Endpoint.LOCAL_ACTIVE:
+            self.closed(event.connection.remote_condition)
+
+    def on_disconnected(self, event):
+        raise ConnectionException("Connection %s disconnected" % self.url);
+
+    def closed(self, error=None):
+        txt = "Connection %s closed" % self.url
+        if error:
+            txt += " due to: %s" % error
+        else:
+            txt += " by peer"
+        raise ConnectionException(txt)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/client.py
----------------------------------------------------------------------
diff --git a/tutorial/client.py b/tutorial/client.py
index f2bc866..a649dec 100755
--- a/tutorial/client.py
+++ b/tutorial/client.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class Client(MessagingHandler):
     def __init__(self, host, address, requests):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/client_http.py
----------------------------------------------------------------------
diff --git a/tutorial/client_http.py b/tutorial/client_http.py
index 9e7333b..ab7b1cd 100755
--- a/tutorial/client_http.py
+++ b/tutorial/client_http.py
@@ -19,7 +19,7 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
+from proton.handlers import MessagingHandler
 from proton_tornado import TornadoLoop
 from tornado.ioloop import IOLoop
 import tornado.web

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/db_recv.py
----------------------------------------------------------------------
diff --git a/tutorial/db_recv.py b/tutorial/db_recv.py
index 1dfb3e3..5779403 100755
--- a/tutorial/db_recv.py
+++ b/tutorial/db_recv.py
@@ -18,7 +18,8 @@
 # under the License.
 #
 
-from proton_events import ApplicationEvent, MessagingHandler, EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import ApplicationEvent, EventLoop
 from db_common import Db
 
 class Recv(MessagingHandler):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/db_send.py
----------------------------------------------------------------------
diff --git a/tutorial/db_send.py b/tutorial/db_send.py
index 4701fae..b3a26fd 100755
--- a/tutorial/db_send.py
+++ b/tutorial/db_send.py
@@ -21,7 +21,8 @@
 import Queue
 import time
 from proton import Message
-from proton_events import ApplicationEvent, MessagingHandler, EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import ApplicationEvent, EventLoop
 from db_common import Db
 
 class Send(MessagingHandler):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/helloworld.py
----------------------------------------------------------------------
diff --git a/tutorial/helloworld.py b/tutorial/helloworld.py
index 35a93da..5aa1482 100755
--- a/tutorial/helloworld.py
+++ b/tutorial/helloworld.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class HelloWorld(MessagingHandler):
     def __init__(self, server, address):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/helloworld_blocking.py
----------------------------------------------------------------------
diff --git a/tutorial/helloworld_blocking.py b/tutorial/helloworld_blocking.py
index 2c4dca2..9c5e062 100755
--- a/tutorial/helloworld_blocking.py
+++ b/tutorial/helloworld_blocking.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_utils import BlockingConnection
-from proton_handlers import IncomingMessageHandler
+from proton.utils import BlockingConnection
+from proton.handlers import IncomingMessageHandler
 
 class HelloWorldReceiver(IncomingMessageHandler):
     def on_message(self, event):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/helloworld_direct.py
----------------------------------------------------------------------
diff --git a/tutorial/helloworld_direct.py b/tutorial/helloworld_direct.py
index 652039b..35ac597 100755
--- a/tutorial/helloworld_direct.py
+++ b/tutorial/helloworld_direct.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class HelloWorld(MessagingHandler):
     def __init__(self, server, address):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/helloworld_direct_tornado.py
----------------------------------------------------------------------
diff --git a/tutorial/helloworld_direct_tornado.py b/tutorial/helloworld_direct_tornado.py
index 1a8365a..45926c6 100755
--- a/tutorial/helloworld_direct_tornado.py
+++ b/tutorial/helloworld_direct_tornado.py
@@ -19,7 +19,7 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
+from proton.handlers import MessagingHandler
 from proton_tornado import TornadoLoop
 
 class HelloWorld(MessagingHandler):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/helloworld_tornado.py
----------------------------------------------------------------------
diff --git a/tutorial/helloworld_tornado.py b/tutorial/helloworld_tornado.py
index 541eec4..6a82b69 100755
--- a/tutorial/helloworld_tornado.py
+++ b/tutorial/helloworld_tornado.py
@@ -19,7 +19,7 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
+from proton.handlers import MessagingHandler
 from proton_tornado import TornadoLoop
 
 class HelloWorld(MessagingHandler):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/proton_handlers.py
----------------------------------------------------------------------
diff --git a/tutorial/proton_handlers.py b/tutorial/proton_handlers.py
deleted file mode 100644
index 1381f31..0000000
--- a/tutorial/proton_handlers.py
+++ /dev/null
@@ -1,409 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-import heapq, os, Queue, re, socket, time, types
-from proton import dispatch, generate_uuid, PN_ACCEPTED, SASL, symbol, ulong, Url
-from proton import Collector, Connection, Delivery, Described, Endpoint, Event, Link, Terminus, Timeout
-from proton import Message, Handler, ProtonException, Transport, TransportException, ConnectionException
-from select import select
-
-class FlowController(Handler):
-
-    def __init__(self, window=1):
-        self.window = window
-
-    def top_up(self, link):
-        delta = self.window - link.credit
-        link.flow(delta)
-
-    def on_link_local_open(self, event):
-        if event.link.is_receiver:
-            self.top_up(event.link)
-
-    def on_link_remote_open(self, event):
-        if event.link.is_receiver:
-            self.top_up(event.link)
-
-    def on_link_flow(self, event):
-        if event.link.is_receiver:
-            self.top_up(event.link)
-
-    def on_delivery(self, event):
-        if not event.delivery.released and event.delivery.link.is_receiver:
-            self.top_up(event.delivery.link)
-
-def nested_handlers(handlers):
-    # currently only allows for a single level of nesting
-    nested = []
-    for h in handlers:
-        nested.append(h)
-        if hasattr(h, 'handlers'):
-            nested.extend(getattr(h, 'handlers'))
-    return nested
-
-def add_nested_handler(handler, nested):
-    if hasattr(handler, 'handlers'):
-        getattr(handler, 'handlers').append(nested)
-    else:
-        handler.handlers = [nested]
-
-class ScopedHandler(Handler):
-
-    scopes = {
-        "pn_connection": ["connection"],
-        "pn_session": ["session", "connection"],
-        "pn_link": ["link", "session", "connection"],
-        "pn_delivery": ["delivery", "link", "session", "connection"]
-    }
-
-    def on_unhandled(self, method, args):
-        event = args[0]
-        if event.type in [Event.CONNECTION_FINAL, Event.SESSION_FINAL, Event.LINK_FINAL]:
-            return
-        objects = [getattr(event, attr) for attr in self.scopes.get(event.clazz, [])]
-        targets = [getattr(o, "context") for o in objects if hasattr(o, "context")]
-        handlers = [getattr(t, event.type.method) for t in nested_handlers(targets) if hasattr(t, event.type.method)]
-        for h in handlers:
-            h(event)
-
-class OutgoingMessageHandler(Handler):
-    def __init__(self, auto_settle=True, delegate=None):
-        self.auto_settle = auto_settle
-        self.delegate = delegate
-
-    def on_link_flow(self, event):
-        if event.link.is_sender and event.link.credit:
-            self.on_credit(event)
-
-    def on_delivery(self, event):
-        dlv = event.delivery
-        if dlv.released: return
-        if dlv.link.is_sender and dlv.updated:
-            if dlv.remote_state == Delivery.ACCEPTED:
-                self.on_accepted(event)
-            elif dlv.remote_state == Delivery.REJECTED:
-                self.on_rejected(event)
-            elif dlv.remote_state == Delivery.RELEASED:
-                self.on_released(event)
-            elif dlv.remote_state == Delivery.MODIFIED:
-                self.on_modified(event)
-            if dlv.settled:
-                self.on_settled(event)
-            if self.auto_settle:
-                dlv.settle()
-
-    def on_credit(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_credit', event)
-
-    def on_accepted(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_accepted', event)
-
-    def on_rejected(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_rejected', event)
-
-    def on_released(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_released', event)
-
-    def on_modified(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_modified', event)
-
-    def on_settled(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_settled', event)
-
-def recv_msg(delivery):
-    msg = Message()
-    msg.decode(delivery.link.recv(delivery.pending))
-    delivery.link.advance()
-    return msg
-
-class Reject(ProtonException):
-  """
-  An exception that indicate a message should be rejected
-  """
-  pass
-
-class Acking(object):
-    def accept(self, delivery):
-        self.settle(delivery, Delivery.ACCEPTED)
-
-    def reject(self, delivery):
-        self.settle(delivery, Delivery.REJECTED)
-
-    def release(self, delivery, delivered=True):
-        if delivered:
-            self.settle(delivery, Delivery.MODIFIED)
-        else:
-            self.settle(delivery, Delivery.RELEASED)
-
-    def settle(self, delivery, state=None):
-        if state:
-            delivery.update(state)
-        delivery.settle()
-
-class IncomingMessageHandler(Handler, Acking):
-    def __init__(self, auto_accept=True, delegate=None):
-        self.delegate = delegate
-        self.auto_accept = auto_accept
-
-    def on_delivery(self, event):
-        dlv = event.delivery
-        if dlv.released or not dlv.link.is_receiver: return
-        if dlv.readable and not dlv.partial:
-            event.message = recv_msg(dlv)
-            try:
-                self.on_message(event)
-                if self.auto_accept:
-                    dlv.update(Delivery.ACCEPTED)
-                    dlv.settle()
-            except Reject:
-                dlv.update(Delivery.REJECTED)
-                dlv.settle()
-        elif dlv.updated and dlv.settled:
-            self.on_settled(event)
-
-    def on_message(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_message', event)
-
-    def on_settled(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_settled', event)
-
-class EndpointStateHandler(Handler):
-    def __init__(self, peer_close_is_error=False, delegate=None):
-        self.delegate = delegate
-        self.peer_close_is_error = peer_close_is_error
-
-    def is_local_open(self, endpoint):
-        return endpoint.state & Endpoint.LOCAL_ACTIVE
-
-    def is_local_uninitialised(self, endpoint):
-        return endpoint.state & Endpoint.LOCAL_UNINIT
-
-    def is_local_closed(self, endpoint):
-        return endpoint.state & Endpoint.LOCAL_CLOSED
-
-    def is_remote_open(self, endpoint):
-        return endpoint.state & Endpoint.REMOTE_ACTIVE
-
-    def is_remote_closed(self, endpoint):
-        return endpoint.state & Endpoint.REMOTE_CLOSED
-
-    def print_error(self, endpoint, endpoint_type):
-        if endpoint.remote_condition:
-            print endpoint.remote_condition.description
-        elif self.is_local_open(endpoint) and self.is_remote_closed(endpoint):
-            print "%s closed by peer" % endpoint_type
-
-    def on_link_remote_close(self, event):
-        if event.link.remote_condition:
-            self.on_link_error(event)
-        elif self.is_local_closed(event.link):
-            self.on_link_closed(event)
-        else:
-            self.on_link_closing(event)
-        event.link.close()
-
-    def on_session_remote_close(self, event):
-        if event.session.remote_condition:
-            self.on_session_error(event)
-        elif self.is_local_closed(event.session):
-            self.on_session_closed(event)
-        else:
-            self.on_session_closing(event)
-        event.session.close()
-
-    def on_connection_remote_close(self, event):
-        if event.connection.remote_condition:
-            self.on_connection_error(event)
-        elif self.is_local_closed(event.connection):
-            self.on_connection_closed(event)
-        else:
-            self.on_connection_closing(event)
-        event.connection.close()
-
-    def on_connection_local_open(self, event):
-        if self.is_remote_open(event.connection):
-            self.on_connection_opened(event)
-
-    def on_connection_remote_open(self, event):
-        if self.is_local_open(event.connection):
-            self.on_connection_opened(event)
-        elif self.is_local_uninitialised(event.connection):
-            self.on_connection_opening(event)
-            event.connection.open()
-
-    def on_session_local_open(self, event):
-        if self.is_remote_open(event.session):
-            self.on_session_opened(event)
-
-    def on_session_remote_open(self, event):
-        if self.is_local_open(event.session):
-            self.on_session_opened(event)
-        elif self.is_local_uninitialised(event.session):
-            self.on_session_opening(event)
-            event.session.open()
-
-    def on_link_local_open(self, event):
-        if self.is_remote_open(event.link):
-            self.on_link_opened(event)
-
-    def on_link_remote_open(self, event):
-        if self.is_local_open(event.link):
-            self.on_link_opened(event)
-        elif self.is_local_uninitialised(event.link):
-            self.on_link_opening(event)
-            event.link.open()
-
-    def on_connection_opened(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_connection_opened', event)
-
-    def on_session_opened(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_session_opened', event)
-
-    def on_link_opened(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_link_opened', event)
-
-    def on_connection_opening(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_connection_opening', event)
-
-    def on_session_opening(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_session_opening', event)
-
-    def on_link_opening(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_link_opening', event)
-
-    def on_connection_error(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_connection_error', event)
-        else:
-            self.print_error(event.connection, "connection")
-
-    def on_session_error(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_session_error', event)
-        else:
-            self.print_error(event.session, "session")
-            event.connection.close()
-
-    def on_link_error(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_link_error', event)
-        else:
-            self.print_error(event.link, "link")
-            event.connection.close()
-
-    def on_connection_closed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_connection_closed', event)
-
-    def on_session_closed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_session_closed', event)
-
-    def on_link_closed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_link_closed', event)
-
-    def on_connection_closing(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_connection_closing', event)
-        elif self.peer_close_is_error:
-            self.on_connection_error(event)
-
-    def on_session_closing(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_session_closing', event)
-        elif self.peer_close_is_error:
-            self.on_session_error(event)
-
-    def on_link_closing(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_link_closing', event)
-        elif self.peer_close_is_error:
-            self.on_link_error(event)
-
-class MessagingHandler(Handler, Acking):
-    def __init__(self, prefetch=10, auto_accept=True, auto_settle=True, peer_close_is_error=False):
-        self.handlers = []
-        # FlowController if used needs to see event before
-        # IncomingMessageHandler, as the latter may involve the
-        # delivery being released
-        if prefetch:
-            self.handlers.append(FlowController(prefetch))
-        self.handlers.append(EndpointStateHandler(peer_close_is_error, self))
-        self.handlers.append(IncomingMessageHandler(auto_accept, self))
-        self.handlers.append(OutgoingMessageHandler(auto_settle, self))
-
-class TransactionalAcking(object):
-    def accept(self, delivery, transaction, settle=True):
-        transaction.accept(delivery, settle)
-
-class TransactionHandler(OutgoingMessageHandler, TransactionalAcking):
-    def __init__(self, auto_settle=True, delegate=None):
-        super(TransactionHandler, self).__init__(auto_settle, delegate)
-
-    def on_settled(self, event):
-        if hasattr(event.delivery, "transaction"):
-            event.transaction = event.delivery.transaction
-            event.delivery.transaction.handle_outcome(event)
-
-    def on_transaction_declared(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_transaction_declared', event)
-
-    def on_transaction_committed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_transaction_committed', event)
-
-    def on_transaction_aborted(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_transaction_aborted', event)
-
-    def on_transaction_declare_failed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_transaction_declare_failed', event)
-
-    def on_transaction_commit_failed(self, event):
-        if self.delegate:
-            dispatch(self.delegate, 'on_transaction_commit_failed', event)
-
-class TransactionalClientHandler(Handler, TransactionalAcking):
-    def __init__(self, prefetch=10, auto_accept=False, auto_settle=True, peer_close_is_error=False):
-        super(TransactionalClientHandler, self).__init__()
-        self.handlers = []
-        # FlowController if used needs to see event before
-        # IncomingMessageHandler, as the latter may involve the
-        # delivery being released
-        if prefetch:
-            self.handlers.append(FlowController(prefetch))
-        self.handlers.append(EndpointStateHandler(peer_close_is_error, self))
-        self.handlers.append(IncomingMessageHandler(auto_accept, self))
-        self.handlers.append(TransactionHandler(auto_settle, self))


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[24/35] qpid-proton git commit: Revert "PROTON-630: add setup.py for python bindings"

Posted by gs...@apache.org.
Revert "PROTON-630: add setup.py for python bindings"

This reverts commit 4252758bd3772470bd255d034d3abea157429504.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/f5cbab5e
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/f5cbab5e
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/f5cbab5e

Branch: refs/heads/examples
Commit: f5cbab5eafeae5bf9e713db1c897c77b2022bfdc
Parents: 2276c09
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Fri Nov 21 22:32:34 2014 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Sat Nov 22 06:03:01 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/CMakeLists.txt |  79 +++++++++-----------
 proton-c/bindings/python/setup.py.in    | 107 ---------------------------
 2 files changed, 34 insertions(+), 152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f5cbab5e/proton-c/bindings/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/CMakeLists.txt b/proton-c/bindings/python/CMakeLists.txt
index b8cdb57..c7eb4aa 100644
--- a/proton-c/bindings/python/CMakeLists.txt
+++ b/proton-c/bindings/python/CMakeLists.txt
@@ -17,8 +17,8 @@
 # under the License.
 #
 
-# NB For python the SWIG module name must have the same name as the
-# input .i file for CMake to generate the correct dependencies
+# NB For python the SWIG module name must have the same name as the input .i file for CMake to generate the
+# correct dependencies
 
 set(CMAKE_SWIG_FLAGS "-threads")
 
@@ -39,15 +39,27 @@ set_target_properties(${SWIG_MODULE_cproton_REAL_NAME}
 
 find_package(PythonInterp REQUIRED)
 
-# configure the files needed for generating Pypi packages. Packages
-# can be generated by running "python setup.py" from the build
-# directory.
-get_filename_component(PN_SWIG_PYTHON_C_WRAPPER
-                       ${swig_generated_file_fullname} NAME)
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/proton.py
-               ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
-               ${CMAKE_CURRENT_BINARY_DIR}/setup.py @ONLY)
+if (CHECK_SYSINSTALL_PYTHON)
+  execute_process(COMMAND ${PYTHON_EXECUTABLE}
+    -c "from distutils.sysconfig import get_python_lib; print get_python_lib(True)"
+    OUTPUT_VARIABLE PYTHON_SITEARCH_PACKAGES_DEFAULT
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+else ()
+  set (PYTHON_SITEARCH_PACKAGES_DEFAULT ${BINDINGS_DIR}/python)
+endif ()
+
+if (NOT PYTHON_SITEARCH_PACKAGES)
+  set (PYTHON_SITEARCH_PACKAGES ${PYTHON_SITEARCH_PACKAGES_DEFAULT})
+endif()
+
+install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cproton.py
+                              WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
+install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cproton.py
+                              WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
+install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile proton.py
+                              WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
+install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile proton.py
+                              WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
 
 find_program(EPYDOC_EXE epydoc)
 mark_as_advanced (EPYDOC_EXE)
@@ -63,37 +75,14 @@ if (EPYDOC_EXE)
            ${OPTIONAL_ARG})
 endif (EPYDOC_EXE)
 
-if (CHECK_SYSINSTALL_PYTHON)
-  # use the python-native install paths:
-
-  install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} setup.py sdist
-                                WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-  install(CODE "execute_process(COMMAND
-   ${PYTHON_EXECUTABLE} setup.py --proton-install-prefix ${CMAKE_INSTALL_PREFIX} install
-                          WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-
-else ()
-  # install the bindings using the CMAKE path variables:
-  set (PYTHON_SITEARCH_PACKAGES ${BINDINGS_DIR}/python)
-
-  install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cproton.py
-                                WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-  install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cproton.py
-                                WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-  install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile proton.py
-                                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
-  install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile proton.py
-                                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
-
-  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cproton.py
-                ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyc
-                ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyo
-                ${CMAKE_CURRENT_SOURCE_DIR}/proton.py
-                ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyc
-                ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyo
-          DESTINATION ${PYTHON_SITEARCH_PACKAGES}
-          COMPONENT Python)
-  install(TARGETS ${SWIG_MODULE_cproton_REAL_NAME}
-          DESTINATION ${PYTHON_SITEARCH_PACKAGES}
-          COMPONENT Python)
-endif()
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cproton.py
+              ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyc
+              ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyo
+              ${CMAKE_CURRENT_SOURCE_DIR}/proton.py
+              ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyc
+              ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyo
+        DESTINATION ${PYTHON_SITEARCH_PACKAGES}
+        COMPONENT Python)
+install(TARGETS ${SWIG_MODULE_cproton_REAL_NAME}
+        DESTINATION ${PYTHON_SITEARCH_PACKAGES}
+        COMPONENT Python)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f5cbab5e/proton-c/bindings/python/setup.py.in
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/setup.py.in b/proton-c/bindings/python/setup.py.in
deleted file mode 100644
index 94f3dfc..0000000
--- a/proton-c/bindings/python/setup.py.in
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/env python
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-from distutils.core import setup, Extension
-import logging
-import os
-import sys
-
-_c_module = '@SWIG_MODULE_cproton_REAL_NAME@'
-_src_file = '@PN_SWIG_PYTHON_C_WRAPPER@'
-_version =  '@PN_VERSION@'
-_release = 0
-
-if "--proton-install-prefix" in sys.argv:
-    # special option used only if the python headers and library have been
-    # installed to a non-standard directory.  This can be done during 'make
-    # install' from the proton build tree by using the cmake option
-    # -DCMAKE_INSTALL_PREFIX.  The location of the headers and library must be
-    # specified so we can build the binding's C extension.
-    i = sys.argv.index("--proton-install-prefix") + 1
-    if i >= len(sys.argv):
-        raise ValueError("--proton-install-prefix requires a path parameter.")
-    _prefix = sys.argv[i]
-    # remove the proton arguments to they don't conflict with setup.py's other
-    # command arguments:
-    del sys.argv[i]
-    sys.argv.remove("--proton-install-prefix")
-    _destdir = os.environ.get("DESTDIR", "")
-    if _destdir and os.path.isabs(_prefix):
-        # DESTDIR may be used on unix systems to put the entire install tree
-        # under a particular directory.  However, if _prefix is an absolute
-        # path, os.path.join will discard DESTDIR, so strip off the leading
-        # separator
-        _prefix = _prefix.lstrip(os.path.sep)
-
-    _inc_dir = os.path.join(_destdir,
-                            _prefix,
-                            '@INCLUDE_INSTALL_DIR@')
-    _lib_dir = os.path.join(_destdir,
-                            _prefix,
-                            '@LIB_INSTALL_DIR@')
-
-    swig_ext = Extension(_c_module, [_src_file],
-                         libraries=['qpid-proton'],
-                         include_dirs=[_inc_dir],
-                         library_dirs=[_lib_dir])
-else:
-    swig_ext = Extension(_c_module, [_src_file],
-                         libraries=['qpid-proton'])
-
-_help_description = """Before you can build or install these bindings, you must
-first install version @PN_VERSION@ of the Proton development library
-(libqpid-proton) and its C header files. These files must be available in order
-to build this packages' C-based extension.
-
-Packages for the Proton development library may be provided by your system's
-distribution. For example, the qpid-proton-c-devel RPM is available for
-Centos/RHEL via EPEL.  A libqpid-proton2-dev deb file is available for Ubuntu
-via the Apache Qpid PPA (ppa:qpid/released).
-
-If your distribution does not make these packages available, you can download
-the Proton sources directly from the Apache Qpid project:
-
- http://qpid.apache.org
-
-This package is compatible with the @PN_VERSION@ release of the Proton
-development library.
-
-If you need additional help, see http://qpid.apache.org/discussion.html
-"""
-
-_long_description = """This package contains the Python bindings for the Apache
-QPID Proton library.\n%s""" % _help_description
-
-try:
-    setup(name="python-qpid-proton",
-          version="%s-%d" % (_version, _release),
-          author="Apache Qpid",
-          author_email="dev@qpid.apache.org",
-          py_modules=["proton", "cproton"],
-          url="http://qpid.apache.org/",
-          description="Python bindings for the Proton library",
-          long_description=_long_description,
-          license="Apache Software License",
-          classifiers=["License :: OSI Approved :: Apache Software License",
-                       "Intended Audience :: Developers",
-                       "Programming Language :: Python"],
-          ext_modules=[swig_ext])
-except:
-    logging.error("setup failed!\n%s", _help_description)
-    raise


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[27/35] qpid-proton git commit: PROTON-752: Provide a non-blocking means to receive messages in Ruby.

Posted by gs...@apache.org.
PROTON-752: Provide a non-blocking means to receive messages in Ruby.

To avoid changing the APIs or their intentions, a new class method is
added:

  Qpid::Proton::Receiver::receive_and_call

The method takes as arguments either an existing instance of Messenger
or else the parameters to create an instance, and also a code block to
be called with each message received.

The messenger is then put into passive mode and a new thread started. It
then monitors the messenger and, when a new message is received, passes
it to the block for processing.

To exit the messenger, the code would call Messenger#interrupt. The
thread then exits and the messenger stops processing.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/0820a372
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/0820a372
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/0820a372

Branch: refs/heads/examples
Commit: 0820a3722b6ab5c2a5a4dbfac3428de7d22c1c6e
Parents: 2335465
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Fri Nov 21 09:57:40 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Mon Nov 24 12:58:10 2014 -0500

----------------------------------------------------------------------
 examples/messenger/ruby/passive_recv.rb         | 122 +++---------------
 .../bindings/ruby/lib/qpid_proton/messenger.rb  | 128 +++++++++++++++++++
 .../bindings/ruby/lib/qpid_proton/selectable.rb |  21 ++-
 3 files changed, 163 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0820a372/examples/messenger/ruby/passive_recv.rb
----------------------------------------------------------------------
diff --git a/examples/messenger/ruby/passive_recv.rb b/examples/messenger/ruby/passive_recv.rb
index a3625ac..878c801 100644
--- a/examples/messenger/ruby/passive_recv.rb
+++ b/examples/messenger/ruby/passive_recv.rb
@@ -31,110 +31,26 @@ end
 
 addresses = ["~0.0.0.0"] if addresses.empty?
 
-messenger = Qpid::Proton::Messenger.new
-messenger.passive = true
-
-begin
-  messenger.start
-rescue ProtonError => error
-  puts "ERROR: #{error.message}"
-  puts error.backtrace.join("\n")
-  exit
-end
-
-addresses.each do |address|
-  begin
-    messenger.subscribe(address)
-  rescue Qpid::Proton::ProtonError => error
-    puts "ERROR: #{error.message}"
-    exit
-  end
-end
-
-msg = Qpid::Proton::Message.new
-
-read_array = []
-write_array = []
-selectables = {}
-
-loop do
-
-  # wait for incoming messages
-  sel = messenger.selectable
-  while !sel.nil?
-    if sel.terminal?
-      selectables.delete(sel.fileno)
-      read_array.delete(sel)
-      write_array.delete(sel)
-      sel.free
-    else
-      sel.capacity
-      sel.pending
-      if !sel.registered?
-        read_array << sel
-        write_array << sel
-        selectables[sel.fileno] = sel
-        sel.registered = true
-      end
-    end
-    sel = messenger.selectable
+msgr = Qpid::Proton::Messenger.receive_and_call(nil, :addresses => addresses) do |message|
+  puts "Address: #{message.address}"
+  subject = message.subject || "(no subject)"
+  puts "Subject: #{subject}"
+  puts "Body: #{message.body}"
+  puts "Properties: #{message.properties}"
+  puts "Instructions: #{message.instructions}"
+  puts "Annotations: #{message.annotations}"
+
+  if message.reply_to
+    puts "=== Sending a reply to #{message.reply_to}"
+    reply = Qpid::Proton::Message.new
+    reply.address = message.reply_to
+    reply.subject = "RE: #{message.subject}"
+    reply.content = "Thanks for the message!"
+
+    messenger.put(reply)
+    messenger.send
   end
 
-  unless selectables.empty?
-    rarray = []; read_array.each {|fd| rarray << fd.to_io }
-    warray = []; write_array.each {|fd| warray << fd.to_io }
-
-    if messenger.deadline > 0.0
-      result = IO.select(rarray, warray, nil, messenger.deadline)
-    else
-      result = IO.select(rarray, warray)
-    end
-
-    unless result.nil? && result.empty?
-      result.flatten.each do |io|
-        sel = selectables[io.fileno]
-
-        sel.writable if sel.pending > 0
-        sel.readable if sel.capacity > 0
-      end
-    end
-
-    begin
-      messenger.receive(10)
-    rescue Qpid::Proton::ProtonError => error
-      puts "ERROR: #{error.message}"
-      exit
-    end
-
-    while messenger.incoming.nonzero?
-      begin
-        messenger.get(msg)
-      rescue Qpid::Proton::Error => error
-        puts "ERROR: #{error.message}"
-        exit
-      end
-
-      puts "Address: #{msg.address}"
-      subject = msg.subject || "(no subject)"
-      puts "Subject: #{subject}"
-      puts "Body: #{msg.body}"
-      puts "Properties: #{msg.properties}"
-      puts "Instructions: #{msg.instructions}"
-      puts "Annotations: #{msg.annotations}"
-
-      if msg.reply_to
-        puts "=== Sending a reply to #{msg.reply_to}"
-        reply = Qpid::Proton::Message.new
-        reply.address = msg.reply_to
-        reply.subject = "RE: #{msg.subject}"
-        reply.content = "Thanks for the message!"
-
-        messenger.put(reply)
-        messenger.send
-      end
-    end
-  end
 end
 
-messenger.stop
-
+Thread.list[1].join

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0820a372/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index 5a16c50..a8f7330 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -75,6 +75,7 @@ module Qpid # :nodoc:
       #
       def initialize(name = nil)
         @impl = Cproton.pn_messenger(name)
+        @interrupted = false
         @selectables = {}
         ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
       end
@@ -407,6 +408,7 @@ module Qpid # :nodoc:
       # originated the interrupt.
       #
       def interrupt
+        @interrupted = true
         Cproton.pn_messenger_interrupt(@impl)
       end
 
@@ -695,6 +697,132 @@ module Qpid # :nodoc:
         !window.nil? && [Float, Fixnum].include?(window.class)
       end
 
+      public
+
+
+      #--
+      # The following are class methods.
+      #++
+
+      # Receives messages from the provided instance of Messenger, and then
+      # calls the supplied block for each Message received. If no instance
+      # is provided then one is created using the provided list of options.
+      #
+      # This starts a new thread which will loop, waiting for and processing
+      # incoming messages.
+      #
+      # ==== Arguments
+      #
+      # * messenger - The instance of Messenger.
+      #
+      # ==== Options
+      #
+      # * :addresses - An array of addresses to which to subscribe. Addresses
+      #   are required if no Messenger was supplied.
+      #
+      # ==== Examples
+      #
+      #   # create a Messenger
+      #   messenger = Qpid::Proton::Messenger.new
+      #   # begin receiving messages
+      #   Qpid::Proton::Messenger.receive_and_call(messenger) do |message|
+      #      puts "Received: #{message.body}"
+      #   end
+      #
+      def self.receive_and_call(messenger, options = {}, &block)
+        # if the messenger wasn't created then create one
+        if messenger.nil?
+          # if no addresses were supplied then raise an exception
+          raise ArgumentError.new("no addresses") if options[:addresses].nil?
+          # if no block was supplied then raise an exception
+          raise ArgumentError.new("missing block") if block.nil?
+
+          messenger = Qpid::Proton::Messenger.new
+          Array(options[:addresses]).each do |address|
+            messenger.subscribe address
+          end
+        end
+
+        # set the messenger to passive mode
+        messenger.passive = true
+        messenger.start
+
+        Thread.new(messenger, block) do |messenger, &block|
+          read_array = []
+          write_array = []
+          selectables = {}
+
+          aborted = false
+
+          while !aborted do
+            # refresh the list of fds to be processed
+            sel = messenger.selectable
+            while !sel.nil?
+              if sel.terminal?
+                selectables.delete(sel.fileno)
+                read_array.delete(sel)
+                write_array.delete(sel)
+                sel.free
+              else
+                sel.capacity
+                sel.pending
+                if !sel.registered?
+                  read_array << sel
+                  write_array << sel
+                  selectables[sel.fileno] = sel
+                  sel.registered = true
+                end
+              end
+              sel = messenger.selectable
+            end
+
+            unless selectables.empty?
+              rarray = []; read_array.each {|fd| rarray << fd.to_io}
+              warray = []; write_array.each {|fd| warray << fd.to_io}
+
+              if messenger.deadline > 0.0
+                result = IO.select(rarray, warray, nil, messenger.deadline)
+              else
+                result = IO.select(rarray, warray)
+              end
+
+              unless result.nil? && result.empty?
+                result.flatten.each do |io|
+                  sel = selectables[io.fileno]
+
+                  sel.writable if sel.pending > 0
+                  sel.readable if sel.capacity > 0
+                end
+              end
+
+              messenger.receive(10)
+
+              # if this was interrupted then exit
+              messenger.instance_eval do
+                aborted = @interrupted
+                @interrupted = false
+              end
+
+              if !aborted
+                # process each message received
+                while messenger.incoming.nonzero?
+                  message = Qpid::Proton::Message.new
+                  messenger.get(message)
+                  yield message
+                end
+              end
+
+            end
+
+          end
+
+        end
+
+        # return the messenger
+        messenger
+
+      end
+
     end
 
   end

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0820a372/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
index 33554cd..8b1214a 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
@@ -37,6 +37,14 @@ module Qpid # :nodoc:
         @impl = impl
         @io = nil
         @freed = false
+
+        ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
+      end
+
+      def self.finalize!(impl) # :nodoc:
+        proc {
+          impl.free
+        }
       end
 
       # Returns the underlying file descriptor.
@@ -48,7 +56,11 @@ module Qpid # :nodoc:
       end
 
       def to_io
-        @io ||= IO.new(fileno)
+        if @io.nil?
+          fileno = self.fileno
+          @io = IO.new(fileno)
+        end
+        @io
       end
 
       # The number of bytes the selectable is capable of consuming.
@@ -97,15 +109,14 @@ module Qpid # :nodoc:
       end
 
       def to_s
-        "fileno=#{self.fileno} registered=#{self.registered?} terminal=#{self.terminal?}"
+        return super if @freed
+        "#{super} fileno=#{self.fileno} registered=#{self.registered?} terminal=#{self.terminal?}"
       end
 
       def free
-        return if @freed
         @freed = true
         @messenger.unregister_selectable(fileno)
-        @io.close unless @io.nil?
-        Cproton.pn_selectable_free(@impl)
+        @messenger = nil
         @impl = nil
       end
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[30/35] qpid-proton git commit: Revert "NO-JIRA: Fix protocol tracing for transactional states."

Posted by gs...@apache.org.
Revert "NO-JIRA: Fix protocol tracing for transactional states."

This reverts commit 061da30be815467217ecb365cfc1d7581367ba32.

The fix had already been made by:

4c6f212 * PROTON-723: based on gordon's patch, added support for the coordinator target


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/36f81e09
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/36f81e09
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/36f81e09

Branch: refs/heads/examples
Commit: 36f81e0941e616b1b3ed0df4035f994ea40df159
Parents: 061da30
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Nov 25 09:44:02 2014 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Nov 25 09:44:02 2014 -0500

----------------------------------------------------------------------
 proton-c/src/protocol.py | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/36f81e09/proton-c/src/protocol.py
----------------------------------------------------------------------
diff --git a/proton-c/src/protocol.py b/proton-c/src/protocol.py
index ae65150..685e63b 100644
--- a/proton-c/src/protocol.py
+++ b/proton-c/src/protocol.py
@@ -22,7 +22,6 @@ doc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transport.xml"))
 mdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "messaging.xml"))
 tdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transactions.xml"))
 sdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "security.xml"))
-tdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transactions.xml"))
 
 def eq(attr, value):
   return lambda nd: nd[attr] == value
@@ -31,14 +30,12 @@ TYPES = doc.query["amqp/section/type", eq("@class", "composite")] + \
     mdoc.query["amqp/section/type", eq("@class", "composite")] + \
     tdoc.query["amqp/section/type", eq("@class", "composite")] + \
     sdoc.query["amqp/section/type", eq("@class", "composite")] + \
-    mdoc.query["amqp/section/type", eq("@provides", "section")] + \
-    tdoc.query["amqp/section/type", eq("@class", "composite")]
-
+    mdoc.query["amqp/section/type", eq("@provides", "section")]
 RESTRICTIONS = {}
 COMPOSITES = {}
 
 for type in doc.query["amqp/section/type"] + mdoc.query["amqp/section/type"] + \
-      sdoc.query["amqp/section/type"] + tdoc.query["amqp/section/type"]:
+      sdoc.query["amqp/section/type"]:
   source = type["@source"]
   if source:
     RESTRICTIONS[type["@name"]] = source


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[32/35] qpid-proton git commit: Merge branch 'master' into examples

Posted by gs...@apache.org.
Merge branch 'master' into examples


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d02fdad1
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d02fdad1
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d02fdad1

Branch: refs/heads/examples
Commit: d02fdad17003d17f9a6ebce71757ab39f6bdc241
Parents: 0fd8b1f 36f81e0
Author: Gordon Sim <gs...@redhat.com>
Authored: Wed Nov 26 16:03:07 2014 +0000
Committer: Gordon Sim <gs...@redhat.com>
Committed: Wed Nov 26 16:03:07 2014 +0000

----------------------------------------------------------------------
 proton-c/CMakeLists.txt                         |    1 +
 .../bindings/perl/lib/qpid/proton/Message.pm    |    2 +-
 proton-c/bindings/perl/lib/qpid/proton/utils.pm |    2 +-
 proton-c/bindings/perl/lib/qpid_proton.pm       |    1 +
 proton-c/bindings/python/CMakeLists.txt         |   83 +-
 proton-c/bindings/python/proton.py              | 3875 -----------------
 proton-c/bindings/python/proton/__init__.py     | 3894 ++++++++++++++++++
 proton-c/bindings/python/setup.py.in            |  107 -
 proton-c/bindings/ruby/lib/qpid_proton.rb       |    4 +-
 proton-c/bindings/ruby/lib/qpid_proton/array.rb |   10 +-
 proton-c/bindings/ruby/lib/qpid_proton/data.rb  |   10 +-
 .../bindings/ruby/lib/qpid_proton/described.rb  |    4 +-
 .../ruby/lib/qpid_proton/exception_handling.rb  |   53 +-
 .../bindings/ruby/lib/qpid_proton/exceptions.rb |    8 +-
 .../bindings/ruby/lib/qpid_proton/filters.rb    |    8 +-
 proton-c/bindings/ruby/lib/qpid_proton/hash.rb  |    6 +-
 .../bindings/ruby/lib/qpid_proton/mapping.rb    |   11 +-
 .../bindings/ruby/lib/qpid_proton/message.rb    |    8 +-
 .../ruby/lib/qpid_proton/message_format.rb      |    8 +-
 .../bindings/ruby/lib/qpid_proton/messenger.rb  |   92 +-
 .../bindings/ruby/lib/qpid_proton/selectable.rb |    8 +-
 .../bindings/ruby/lib/qpid_proton/strings.rb    |    6 +-
 .../ruby/lib/qpid_proton/subscription.rb        |    8 +-
 .../bindings/ruby/lib/qpid_proton/tracker.rb    |    8 +-
 .../ruby/lib/qpid_proton/tracker_status.rb      |    8 +-
 .../bindings/ruby/lib/qpid_proton/version.rb    |   11 +-
 .../ruby/spec/qpid/proton/messenger_spec.rb     |   16 +
 proton-c/include/proton/cproton.i               |    2 +-
 proton-c/include/proton/sasl.h                  |   20 +-
 proton-c/include/proton/ssl.h                   |    6 +
 proton-c/include/proton/transport.h             |   20 +-
 proton-c/src/engine/engine-internal.h           |   36 +-
 proton-c/src/messenger/messenger.c              |    3 +-
 proton-c/src/posix/driver.c                     |    8 +-
 proton-c/src/proton.c                           |   10 +-
 proton-c/src/sasl/sasl-internal.h               |    6 +-
 proton-c/src/sasl/sasl.c                        |  294 +-
 proton-c/src/ssl/openssl.c                      |  452 +-
 proton-c/src/ssl/ssl-internal.h                 |    6 +-
 proton-c/src/ssl/ssl_stub.c                     |   22 +-
 proton-c/src/tests/engine.c                     |    3 +
 proton-c/src/transport/autodetect.c             |  135 +
 proton-c/src/transport/autodetect.h             |   40 +
 proton-c/src/transport/transport.c              |  422 +-
 proton-c/src/windows/driver.c                   |    8 +-
 proton-c/src/windows/schannel.c                 |  371 +-
 .../qpid/proton/amqp/messaging/Accepted.java    |    3 +
 .../qpid/proton/amqp/messaging/Modified.java    |    3 +
 .../qpid/proton/amqp/messaging/Rejected.java    |    2 +
 .../qpid/proton/amqp/messaging/Released.java    |    3 +
 .../qpid/proton/amqp/transaction/Declared.java  |    3 +
 .../qpid/proton/codec/impl/ArrayElement.java    |   13 +
 .../apache/qpid/proton/codec/impl/DataImpl.java |   10 +
 .../qpid/proton/engine/impl/SaslImpl.java       |    7 +-
 proton-j/src/main/resources/cengine.py          |    5 +-
 proton-j/src/main/resources/csasl.py            |   14 +-
 proton-j/src/main/resources/cssl.py             |    3 +
 .../qpid/proton/codec/impl/DataImplTest.java    |   84 +
 tests/python/proton_tests/common.py             |   13 +-
 tests/python/proton_tests/engine.py             |    3 -
 tests/python/proton_tests/sasl.py               |   14 +-
 tests/ruby/proton_tests/smoke.rb                |    4 +-
 62 files changed, 5354 insertions(+), 4946 deletions(-)
----------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[06/35] qpid-proton git commit: PROTON-749: Remove transport pointer from ssl and sasl structs - Change means that API pn_ssl_t and pn_sasl_t pointers are really pn_transport_t pointers and need to be cast internally on use

Posted by gs...@apache.org.
PROTON-749: Remove transport pointer from ssl and sasl structs
- Change means that API pn_ssl_t and pn_sasl_t pointers are really
  pn_transport_t pointers and need to be cast internally on use


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/df029005
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/df029005
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/df029005

Branch: refs/heads/examples
Commit: df02900597cb25de9841b6d8c4763acdc0a40fad
Parents: 120639b
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Aug 14 18:22:39 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Mon Nov 17 14:55:36 2014 -0500

----------------------------------------------------------------------
 proton-c/src/engine/engine-internal.h |   7 +-
 proton-c/src/sasl/sasl-internal.h     |   4 +-
 proton-c/src/sasl/sasl.c              | 132 +++++++++------
 proton-c/src/ssl/openssl.c            | 258 ++++++++++++++++-------------
 proton-c/src/ssl/ssl-internal.h       |   4 +-
 proton-c/src/transport/transport.c    |   8 +-
 proton-c/src/windows/schannel.c       | 164 ++++++++++--------
 7 files changed, 326 insertions(+), 251 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index 40a839b..3960acf 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -108,10 +108,13 @@ typedef struct pn_io_layer_t {
 
 extern const pn_io_layer_t pni_passthru_layer;
 
+typedef struct pni_sasl_t pni_sasl_t;
+typedef struct pni_ssl_t pni_ssl_t;
+
 struct pn_transport_t {
   pn_tracer_t tracer;
-  pn_sasl_t *sasl;
-  pn_ssl_t *ssl;
+  pni_sasl_t *sasl;
+  pni_ssl_t *ssl;
   pn_connection_t *connection;  // reference counted
   pn_dispatcher_t *disp;
   char *remote_container;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/sasl/sasl-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl-internal.h b/proton-c/src/sasl/sasl-internal.h
index e362547..15fd0b1 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -48,13 +48,13 @@ ssize_t pn_sasl_input(pn_sasl_t *sasl, const char *bytes, size_t available);
  */
 ssize_t pn_sasl_output(pn_sasl_t *sasl, char *bytes, size_t size);
 
-void pn_sasl_trace(pn_sasl_t *sasl, pn_trace_t trace);
+void pn_sasl_trace(pn_transport_t *transport, pn_trace_t trace);
 
 /** Destructor for the given SASL layer.
  *
  * @param[in] sasl the SASL object to free. No longer valid on
  *                 return.
  */
-void pn_sasl_free(pn_sasl_t *sasl);
+void pn_sasl_free(pn_transport_t *transport);
 
 #endif /* sasl-internal.h */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 5034eb7..ffa310b 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -34,8 +34,7 @@
 #include "util.h"
 
 
-struct pn_sasl_t {
-  pn_transport_t *transport;
+struct pni_sasl_t {
   pn_dispatcher_t *disp;
   char *mechanisms;
   char *remote_mechanisms;
@@ -53,6 +52,18 @@ struct pn_sasl_t {
   bool output_bypass;
 };
 
+static inline pn_transport_t *get_transport_internal(pn_sasl_t *sasl)
+{
+    // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+    return ((pn_transport_t *)sasl);
+}
+
+static inline pni_sasl_t *get_sasl_internal(pn_sasl_t *sasl)
+{
+    // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+    return sasl ? ((pn_transport_t *)sasl)->sasl : NULL;
+}
+
 static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available);
 static ssize_t pn_input_read_sasl(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
 static ssize_t pn_output_write_sasl_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t size);
@@ -89,7 +100,7 @@ const pn_io_layer_t sasl_layer = {
 pn_sasl_t *pn_sasl(pn_transport_t *transport)
 {
   if (!transport->sasl) {
-    pn_sasl_t *sasl = (pn_sasl_t *) malloc(sizeof(pn_sasl_t));
+    pni_sasl_t *sasl = (pni_sasl_t *) malloc(sizeof(pni_sasl_t));
     sasl->disp = pn_dispatcher(1, transport);
     sasl->disp->batch = false;
 
@@ -109,15 +120,16 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
     sasl->output_bypass = false;
 
     transport->sasl = sasl;
-    sasl->transport = transport;
     transport->io_layers[PN_IO_SASL] = &sasl_headers_layer;
   }
 
-  return transport->sasl;
+  // The actual external pn_sasl_t pointer is a pointer to its enclosing pn_transport_t
+  return (pn_sasl_t *)transport;
 }
 
-pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl)
+pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     if (!sasl->configured) return PN_SASL_CONF;
     if (sasl->outcome == PN_SASL_NONE) {
@@ -133,19 +145,22 @@ pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl)
   }
 }
 
-void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms)
+void pn_sasl_mechanisms(pn_sasl_t *sasl0, const char *mechanisms)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (!sasl) return;
   sasl->mechanisms = pn_strdup(mechanisms);
 }
 
-const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl)
+const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   return sasl ? sasl->remote_mechanisms : NULL;
 }
 
-ssize_t pn_sasl_send(pn_sasl_t *sasl, const char *bytes, size_t size)
+ssize_t pn_sasl_send(pn_sasl_t *sasl0, const char *bytes, size_t size)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     if (pn_buffer_size(sasl->send_data)) {
       // XXX: need better error
@@ -159,8 +174,9 @@ ssize_t pn_sasl_send(pn_sasl_t *sasl, const char *bytes, size_t size)
   }
 }
 
-size_t pn_sasl_pending(pn_sasl_t *sasl)
+size_t pn_sasl_pending(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl && pn_buffer_size(sasl->recv_data)) {
     return pn_buffer_size(sasl->recv_data);
   } else {
@@ -168,8 +184,9 @@ size_t pn_sasl_pending(pn_sasl_t *sasl)
   }
 }
 
-ssize_t pn_sasl_recv(pn_sasl_t *sasl, char *bytes, size_t size)
+ssize_t pn_sasl_recv(pn_sasl_t *sasl0, char *bytes, size_t size)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (!sasl) return PN_ARG_ERR;
 
   size_t bsize = pn_buffer_size(sasl->recv_data);
@@ -183,30 +200,34 @@ ssize_t pn_sasl_recv(pn_sasl_t *sasl, char *bytes, size_t size)
   }
 }
 
-void pn_sasl_client(pn_sasl_t *sasl)
+void pn_sasl_client(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     sasl->client = true;
     sasl->configured = true;
   }
 }
 
-void pn_sasl_server(pn_sasl_t *sasl)
+void pn_sasl_server(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     sasl->client = false;
     sasl->configured = true;
   }
 }
 
-void pn_sasl_allow_skip(pn_sasl_t *sasl, bool allow)
+void pn_sasl_allow_skip(pn_sasl_t *sasl0, bool allow)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl)
     sasl->allow_skip = allow;
 }
 
-void pn_sasl_plain(pn_sasl_t *sasl, const char *username, const char *password)
+void pn_sasl_plain(pn_sasl_t *sasl0, const char *username, const char *password)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (!sasl) return;
 
   const char *user = username ? username : "";
@@ -221,42 +242,47 @@ void pn_sasl_plain(pn_sasl_t *sasl, const char *username, const char *password)
   iresp[usize + 1] = 0;
   memmove(iresp + usize + 2, pass, psize);
 
-  pn_sasl_mechanisms(sasl, "PLAIN");
-  pn_sasl_send(sasl, iresp, size);
-  pn_sasl_client(sasl);
+  pn_sasl_mechanisms(sasl0, "PLAIN");
+  pn_sasl_send(sasl0, iresp, size);
+  pn_sasl_client(sasl0);
   free(iresp);
 }
 
-void pn_sasl_done(pn_sasl_t *sasl, pn_sasl_outcome_t outcome)
+void pn_sasl_done(pn_sasl_t *sasl0, pn_sasl_outcome_t outcome)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   if (sasl) {
     sasl->outcome = outcome;
   }
 }
 
-pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl)
+pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   return sasl ? sasl->outcome : PN_SASL_NONE;
 }
 
-void pn_sasl_trace(pn_sasl_t *sasl, pn_trace_t trace)
+void pn_sasl_trace(pn_transport_t *transport, pn_trace_t trace)
 {
-  sasl->disp->trace = trace;
+  transport->sasl->disp->trace = trace;
 }
 
-void pn_sasl_free(pn_sasl_t *sasl)
+void pn_sasl_free(pn_transport_t *transport)
 {
-  if (sasl) {
-    free(sasl->mechanisms);
-    free(sasl->remote_mechanisms);
-    pn_buffer_free(sasl->send_data);
-    pn_buffer_free(sasl->recv_data);
-    pn_dispatcher_free(sasl->disp);
-    free(sasl);
+  if (transport) {
+    pni_sasl_t *sasl = transport->sasl;
+    if (sasl) {
+      free(sasl->mechanisms);
+      free(sasl->remote_mechanisms);
+      pn_buffer_free(sasl->send_data);
+      pn_buffer_free(sasl->recv_data);
+      pn_dispatcher_free(sasl->disp);
+      free(sasl);
+    }
   }
 }
 
-void pn_client_init(pn_sasl_t *sasl)
+void pn_client_init(pni_sasl_t *sasl)
 {
   pn_buffer_memory_t bytes = pn_buffer_memory(sasl->send_data);
   pn_post_frame(sasl->disp, 0, "DL[sz]", SASL_INIT, sasl->mechanisms,
@@ -264,7 +290,7 @@ void pn_client_init(pn_sasl_t *sasl)
   pn_buffer_clear(sasl->send_data);
 }
 
-void pn_server_init(pn_sasl_t *sasl)
+void pn_server_init(pni_sasl_t *sasl)
 {
   // XXX
   char *mechs[16];
@@ -295,13 +321,15 @@ void pn_server_init(pn_sasl_t *sasl)
   pn_post_frame(sasl->disp, 0, "DL[@T[*s]]", SASL_MECHANISMS, PN_SYMBOL, count, mechs);
 }
 
-void pn_server_done(pn_sasl_t *sasl)
+void pn_server_done(pn_sasl_t *sasl0)
 {
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
   pn_post_frame(sasl->disp, 0, "DL[B]", SASL_OUTCOME, sasl->outcome);
 }
 
-void pn_sasl_process(pn_sasl_t *sasl)
+void pn_sasl_process(pn_transport_t *transport)
 {
+  pni_sasl_t *sasl = transport->sasl;
   if (!sasl->configured) return;
 
   if (!sasl->sent_init) {
@@ -321,7 +349,7 @@ void pn_sasl_process(pn_sasl_t *sasl)
   }
 
   if (!sasl->client && sasl->outcome != PN_SASL_NONE && !sasl->sent_done) {
-    pn_server_done(sasl);
+    pn_server_done((pn_sasl_t *)transport);
     sasl->sent_done = true;
   }
 
@@ -335,15 +363,16 @@ void pn_sasl_process(pn_sasl_t *sasl)
   }
 }
 
-ssize_t pn_sasl_input(pn_sasl_t *sasl, const char *bytes, size_t available)
+ssize_t pn_sasl_input(pn_transport_t *transport, const char *bytes, size_t available)
 {
+  pni_sasl_t *sasl = transport->sasl;
   ssize_t n = pn_dispatcher_input(sasl->disp, bytes, available);
   if (n < 0) return n;
 
-  pn_sasl_process(sasl);
+  pn_sasl_process(transport);
 
   if (sasl->rcvd_done) {
-    if (pn_sasl_state(sasl) == PN_SASL_PASS) {
+    if (pn_sasl_state((pn_sasl_t *)transport) == PN_SASL_PASS) {
       if (n) {
         return n;
       } else {
@@ -358,12 +387,13 @@ ssize_t pn_sasl_input(pn_sasl_t *sasl, const char *bytes, size_t available)
   }
 }
 
-ssize_t pn_sasl_output(pn_sasl_t *sasl, char *bytes, size_t size)
+ssize_t pn_sasl_output(pn_transport_t *transport, char *bytes, size_t size)
 {
-  pn_sasl_process(sasl);
+  pn_sasl_process(transport);
 
+  pni_sasl_t *sasl = transport->sasl;
   if (sasl->disp->available == 0 && sasl->sent_done) {
-    if (pn_sasl_state(sasl) == PN_SASL_PASS) {
+    if (pn_sasl_state((pn_sasl_t *)transport) == PN_SASL_PASS) {
       return PN_EOS;
     } else {
       // XXX: should probably do something better here
@@ -376,7 +406,7 @@ ssize_t pn_sasl_output(pn_sasl_t *sasl, char *bytes, size_t size)
 
 int pn_do_init(pn_dispatcher_t *disp)
 {
-  pn_sasl_t *sasl = disp->transport->sasl;
+  pni_sasl_t *sasl = disp->transport->sasl;
   pn_bytes_t mech;
   pn_bytes_t recv;
   int err = pn_scan_args(disp, "D.[sz]", &mech, &recv);
@@ -389,14 +419,14 @@ int pn_do_init(pn_dispatcher_t *disp)
 
 int pn_do_mechanisms(pn_dispatcher_t *disp)
 {
-  pn_sasl_t *sasl = disp->transport->sasl;
+  pni_sasl_t *sasl = disp->transport->sasl;
   sasl->rcvd_init = true;
   return 0;
 }
 
 int pn_do_recv(pn_dispatcher_t *disp)
 {
-  pn_sasl_t *sasl = disp->transport->sasl;
+  pni_sasl_t *sasl = disp->transport->sasl;
   pn_bytes_t recv;
   int err = pn_scan_args(disp, "D.[z]", &recv);
   if (err) return err;
@@ -416,7 +446,7 @@ int pn_do_response(pn_dispatcher_t *disp)
 
 int pn_do_outcome(pn_dispatcher_t *disp)
 {
-  pn_sasl_t *sasl = disp->transport->sasl;
+  pni_sasl_t *sasl = disp->transport->sasl;
   uint8_t outcome;
   int err = pn_scan_args(disp, "D.[B]", &outcome);
   if (err) return err;
@@ -433,7 +463,7 @@ int pn_do_outcome(pn_dispatcher_t *disp)
 
 static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = transport->sasl;
+  pni_sasl_t *sasl = transport->sasl;
   if (available > 0) {
     if (available < SASL_HEADER_LEN) {
       if (memcmp(bytes, SASL_HEADER, available) == 0 ||
@@ -472,9 +502,9 @@ static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int
 
 static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = transport->sasl;
+  pni_sasl_t *sasl = transport->sasl;
   if (!sasl->input_bypass) {
-    ssize_t n = pn_sasl_input(sasl, bytes, available);
+    ssize_t n = pn_sasl_input(transport, bytes, available);
     if (n != PN_EOS) return n;
 
     sasl->input_bypass = true;
@@ -486,7 +516,7 @@ static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer,
 
 static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t size)
 {
-  pn_sasl_t *sasl = transport->sasl;
+  pni_sasl_t *sasl = transport->sasl;
   if (sasl->disp->trace & PN_TRACE_FRM)
     pn_transport_logf(transport, "  -> %s", "SASL");
   assert(size >= SASL_HEADER_LEN);
@@ -501,14 +531,14 @@ static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned i
 
 static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = transport->sasl;
+  pni_sasl_t *sasl = transport->sasl;
   if (!sasl->output_bypass) {
     // this accounts for when pn_do_error is invoked, e.g. by idle timeout
     ssize_t n;
     if (transport->close_sent) {
         n = PN_EOS;
     } else {
-        n = pn_sasl_output(sasl, bytes, available);
+        n = pn_sasl_output(transport, bytes, available);
     }
     if (n != PN_EOS) return n;
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index 7202f7a..41e36b5 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -86,8 +86,7 @@ struct pn_ssl_domain_t {
 };
 
 
-struct pn_ssl_t {
-  pn_transport_t   *transport;
+struct pni_ssl_t {
   pn_ssl_domain_t  *domain;
   const char    *session_id;
   const char *peer_hostname;
@@ -117,6 +116,18 @@ struct pn_ssl_t {
   bool write_blocked;   // SSL blocked until data is written to network
 };
 
+static inline pn_transport_t *get_transport_internal(pn_ssl_t *ssl)
+{
+    // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+    return ((pn_transport_t *)ssl);
+}
+
+static inline pni_ssl_t *get_ssl_internal(pn_ssl_t *ssl)
+{
+    // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+    return ssl ? ((pn_transport_t *)ssl)->ssl : NULL;
+}
+
 struct pn_ssl_session_t {
   const char       *id;
   SSL_SESSION      *session;
@@ -139,53 +150,55 @@ static ssize_t process_output_unknown( pn_transport_t *transport, unsigned int l
 static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
 static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
 static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
-static int init_ssl_socket( pn_ssl_t * );
-static void release_ssl_socket( pn_ssl_t * );
+static int init_ssl_socket(pn_transport_t *, pni_ssl_t *);
+static void release_ssl_socket( pni_ssl_t * );
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
 static void ssl_session_free( pn_ssl_session_t *);
 static size_t buffered_output( pn_transport_t *transport );
 
 // @todo: used to avoid littering the code with calls to printf...
-static void _log_error(pn_ssl_t *ssl, const char *fmt, ...)
+static void ssl_log(pn_transport_t *transport, const char *fmt, ...)
 {
-  va_list ap;
-  va_start(ap, fmt);
-  pn_transport_vlogf(ssl ? ssl->transport : NULL, fmt, ap);
-  va_end(ap);
-}
-
-// @todo: used to avoid littering the code with calls to printf...
-static void _log(pn_ssl_t *ssl, const char *fmt, ...)
-{
-  if (PN_TRACE_DRV & ssl->trace) {
+  if (PN_TRACE_DRV & transport->ssl->trace) {
     va_list ap;
     va_start(ap, fmt);
-    pn_transport_vlogf(ssl->transport, fmt, ap);
+    pn_transport_vlogf(transport, fmt, ap);
     va_end(ap);
   }
 }
 
-// log an error and dump the SSL error stack
-static void _log_ssl_error(pn_ssl_t *ssl, const char *fmt, ...)
+static void ssl_log_flush(pn_transport_t* transport)
 {
   char buf[128];        // see "man ERR_error_string_n()"
+  unsigned long err = ERR_get_error();
+  while (err) {
+    ERR_error_string_n(err, buf, sizeof(buf));
+    pn_transport_logf(transport, "%s", buf);
+    err = ERR_get_error();
+  }
+}
+
+// log an error and dump the SSL error stack
+static void ssl_log_error(const char *fmt, ...)
+{
   va_list ap;
 
   if (fmt) {
     va_start(ap, fmt);
-    pn_transport_vlogf(ssl ? ssl->transport : NULL, fmt, ap);
+    pn_transport_vlogf(NULL, fmt, ap);
     va_end(ap);
   }
 
+  char buf[128];        // see "man ERR_error_string_n()"
   unsigned long err = ERR_get_error();
   while (err) {
     ERR_error_string_n(err, buf, sizeof(buf));
-    _log_error(ssl, "%s", buf);
+    pn_transport_logf(NULL, "%s", buf);
     err = ERR_get_error();
   }
 }
 
-static void _log_clear_data(pn_ssl_t *ssl, const char *data, size_t len)
+static void ssl_log_clear_data(pni_ssl_t *ssl, const char *data, size_t len)
 {
   if (PN_TRACE_RAW & ssl->trace) {
     fprintf(stderr, "SSL decrypted data: \"");
@@ -195,9 +208,10 @@ static void _log_clear_data(pn_ssl_t *ssl, const char *data, size_t len)
 }
 
 // unrecoverable SSL failure occured, notify transport and generate error code.
-static int ssl_failed(pn_ssl_t *ssl)
+static int ssl_failed(pn_transport_t *transport)
 {
-    SSL_set_shutdown(ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+  pni_ssl_t *ssl = transport->ssl;
+  SSL_set_shutdown(ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
   ssl->ssl_closed = true;
   ssl->app_input_closed = ssl->app_output_closed = PN_EOS;
   // fake a shutdown so the i/o processing code will close properly
@@ -208,8 +222,8 @@ static int ssl_failed(pn_ssl_t *ssl)
   if (ssl_err) {
     ERR_error_string_n( ssl_err, buf, sizeof(buf) );
   }
-  _log_ssl_error(ssl, NULL);    // spit out any remaining errors to the log file
-  pn_do_error(ssl->transport, "amqp:connection:framing-error", "SSL Failure: %s", buf);
+  ssl_log_flush(transport);    // spit out any remaining errors to the log file
+  pn_do_error(transport, "amqp:connection:framing-error", "SSL Failure: %s", buf);
   return PN_EOS;
 }
 
@@ -280,23 +294,24 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
   X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
   SSL *ssn = (SSL *) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
   if (!ssn) {
-    _log_error(NULL, "Error: unexpected error - SSL session info not available for peer verify!");
+    pn_transport_logf(NULL, "Error: unexpected error - SSL session info not available for peer verify!");
     return 0;  // fail connection
   }
 
-  pn_ssl_t *ssl = (pn_ssl_t *)SSL_get_ex_data(ssn, ssl_ex_data_index);
-  if (!ssl) {
-    _log_error(NULL, "Error: unexpected error - SSL context info not available for peer verify!");
+  pn_transport_t *transport = (pn_transport_t *)SSL_get_ex_data(ssn, ssl_ex_data_index);
+  if (!transport) {
+    pn_transport_logf(NULL, "Error: unexpected error - SSL context info not available for peer verify!");
     return 0;  // fail connection
   }
 
+  pni_ssl_t *ssl = transport->ssl;
   if (ssl->domain->verify_mode != PN_SSL_VERIFY_PEER_NAME) return preverify_ok;
   if (!ssl->peer_hostname) {
-    _log_error(ssl, "Error: configuration error: PN_SSL_VERIFY_PEER_NAME configured, but no peer hostname set!");
+    pn_transport_logf(transport, "Error: configuration error: PN_SSL_VERIFY_PEER_NAME configured, but no peer hostname set!");
     return 0;  // fail connection
   }
 
-  _log( ssl, "Checking identifying name in peer cert against '%s'", ssl->peer_hostname);
+  ssl_log(transport, "Checking identifying name in peer cert against '%s'", ssl->peer_hostname);
 
   bool matched = false;
 
@@ -313,7 +328,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
           unsigned char *str;
           int len = ASN1_STRING_to_UTF8( &str, asn1 );
           if (len >= 0) {
-            _log( ssl, "SubjectAltName (dns) from peer cert = '%.*s'", len, str );
+            ssl_log(transport, "SubjectAltName (dns) from peer cert = '%.*s'", len, str );
             matched = match_dns_pattern( ssl->peer_hostname, (const char *)str, len );
             OPENSSL_free( str );
           }
@@ -333,7 +348,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
       unsigned char *str;
       int len = ASN1_STRING_to_UTF8( &str, name_asn1);
       if (len >= 0) {
-        _log( ssl, "commonName from peer cert = '%.*s'", len, str );
+        ssl_log(transport, "commonName from peer cert = '%.*s'", len, str);
         matched = match_dns_pattern( ssl->peer_hostname, (const char *)str, len );
         OPENSSL_free(str);
       }
@@ -341,14 +356,14 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
   }
 
   if (!matched) {
-    _log( ssl, "Error: no name matching %s found in peer cert - rejecting handshake.",
+    ssl_log(transport, "Error: no name matching %s found in peer cert - rejecting handshake.",
           ssl->peer_hostname);
     preverify_ok = 0;
 #ifdef X509_V_ERR_APPLICATION_VERIFICATION
     X509_STORE_CTX_set_error( ctx, X509_V_ERR_APPLICATION_VERIFICATION );
 #endif
   } else {
-    _log( ssl, "Name from peer cert matched - peer is valid." );
+    ssl_log(transport, "Name from peer cert matched - peer is valid.");
   }
   return preverify_ok;
 }
@@ -460,7 +475,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
   case PN_SSL_MODE_CLIENT:
     domain->ctx = SSL_CTX_new(SSLv23_client_method()); // and TLSv1+
     if (!domain->ctx) {
-      _log_ssl_error(NULL, "Unable to initialize OpenSSL context.");
+      ssl_log_error("Unable to initialize OpenSSL context.");
       free(domain);
       return NULL;
     }
@@ -469,14 +484,14 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
   case PN_SSL_MODE_SERVER:
     domain->ctx = SSL_CTX_new(SSLv23_server_method()); // and TLSv1+
     if (!domain->ctx) {
-      _log_ssl_error(NULL, "Unable to initialize OpenSSL context.");
+      ssl_log_error("Unable to initialize OpenSSL context.");
       free(domain);
       return NULL;
     }
     break;
 
   default:
-    _log_error(NULL, "Invalid value for pn_ssl_mode_t: %d", mode);
+    pn_transport_logf(NULL, "Invalid value for pn_ssl_mode_t: %d", mode);
     free(domain);
     return NULL;
   }
@@ -489,7 +504,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
 
   // by default, allow anonymous ciphers so certificates are not required 'out of the box'
   if (!SSL_CTX_set_cipher_list( domain->ctx, CIPHERS_ANONYMOUS )) {
-    _log_ssl_error(NULL, "Failed to set cipher list to %s", CIPHERS_ANONYMOUS);
+    ssl_log_error("Failed to set cipher list to %s", CIPHERS_ANONYMOUS);
     pn_ssl_domain_free(domain);
     return NULL;
   }
@@ -538,7 +553,7 @@ int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
   if (!domain || !domain->ctx) return -1;
 
   if (SSL_CTX_use_certificate_chain_file(domain->ctx, certificate_file) != 1) {
-    _log_ssl_error(NULL, "SSL_CTX_use_certificate_chain_file( %s ) failed", certificate_file);
+    ssl_log_error("SSL_CTX_use_certificate_chain_file( %s ) failed", certificate_file);
     return -3;
   }
 
@@ -549,12 +564,12 @@ int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
   }
 
   if (SSL_CTX_use_PrivateKey_file(domain->ctx, private_key_file, SSL_FILETYPE_PEM) != 1) {
-    _log_ssl_error(NULL, "SSL_CTX_use_PrivateKey_file( %s ) failed", private_key_file);
+    ssl_log_error("SSL_CTX_use_PrivateKey_file( %s ) failed", private_key_file);
     return -4;
   }
 
   if (SSL_CTX_check_private_key(domain->ctx) != 1) {
-    _log_ssl_error(NULL, "The key file %s is not consistent with the certificate %s",
+    ssl_log_error("The key file %s is not consistent with the certificate %s",
                    private_key_file, certificate_file);
     return -5;
   }
@@ -565,7 +580,7 @@ int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
   // cipher was negotiated.  TLSv1 will reject such a request.  Hack: once a cert is
   // configured, allow only authenticated ciphers.
   if (!SSL_CTX_set_cipher_list( domain->ctx, CIPHERS_AUTHENTICATE )) {
-      _log_ssl_error(NULL, "Failed to set cipher list to %s", CIPHERS_AUTHENTICATE);
+      ssl_log_error("Failed to set cipher list to %s", CIPHERS_AUTHENTICATE);
       return -6;
   }
 
@@ -582,7 +597,7 @@ int pn_ssl_domain_set_trusted_ca_db(pn_ssl_domain_t *domain,
   // to SSL_CTX_load_verify_locations()
   struct stat sbuf;
   if (stat( certificate_db, &sbuf ) != 0) {
-    _log_error(NULL, "stat(%s) failed: %s", certificate_db, strerror(errno));
+    pn_transport_logf(NULL, "stat(%s) failed: %s", certificate_db, strerror(errno));
     return -1;
   }
 
@@ -597,7 +612,7 @@ int pn_ssl_domain_set_trusted_ca_db(pn_ssl_domain_t *domain,
   }
 
   if (SSL_CTX_load_verify_locations( domain->ctx, file, dir ) != 1) {
-    _log_ssl_error(NULL, "SSL_CTX_load_verify_locations( %s ) failed", certificate_db);
+    ssl_log_error("SSL_CTX_load_verify_locations( %s ) failed", certificate_db);
     return -1;
   }
 
@@ -618,7 +633,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
   case PN_SSL_VERIFY_PEER_NAME:
 
     if (!domain->has_ca_db) {
-      _log_error(NULL, "Error: cannot verify peer without a trusted CA configured.\n"
+      pn_transport_logf(NULL, "Error: cannot verify peer without a trusted CA configured.\n"
                  "       Use pn_ssl_domain_set_trusted_ca_db()");
       return -1;
     }
@@ -627,11 +642,11 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
       // openssl requires that server connections supply a list of trusted CAs which is
       // sent to the client
       if (!trusted_CAs) {
-        _log_error(NULL, "Error: a list of trusted CAs must be provided.");
+        pn_transport_logf(NULL, "Error: a list of trusted CAs must be provided.");
         return -1;
       }
       if (!domain->has_certificate) {
-        _log_error(NULL, "Error: Server cannot verify peer without configuring a certificate.\n"
+        pn_transport_logf(NULL, "Error: Server cannot verify peer without configuring a certificate.\n"
                    "       Use pn_ssl_domain_set_credentials()");
       }
 
@@ -642,7 +657,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
       if (cert_names != NULL)
         SSL_CTX_set_client_CA_list(domain->ctx, cert_names);
       else {
-        _log_error(NULL, "Error: Unable to process file of trusted CAs: %s", trusted_CAs);
+        pn_transport_logf(NULL, "Error: Unable to process file of trusted CAs: %s", trusted_CAs);
         return -1;
       }
     }
@@ -659,7 +674,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
     break;
 
   default:
-    _log_error(NULL, "Invalid peer authentication mode given." );
+    pn_transport_logf(NULL, "Invalid peer authentication mode given." );
     return -1;
   }
 
@@ -702,21 +717,23 @@ const pn_io_layer_t ssl_closed_layer = {
     buffered_output
 };
 
-int pn_ssl_init( pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
+int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char *session_id)
 {
+  pn_transport_t *transport = get_transport_internal(ssl0);
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl || !domain || ssl->domain) return -1;
 
   ssl->domain = domain;
   domain->ref_count++;
   if (domain->allow_unsecured) {
-    ssl->transport->io_layers[PN_IO_SSL] = &unknown_layer;
+    transport->io_layers[PN_IO_SSL] = &unknown_layer;
   } else {
-    ssl->transport->io_layers[PN_IO_SSL] = &ssl_layer;
+    transport->io_layers[PN_IO_SSL] = &ssl_layer;
   }
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
 
-  return init_ssl_socket(ssl);
+  return init_ssl_socket(transport, ssl);
 }
 
 
@@ -724,7 +741,7 @@ int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
 {
   if (!domain) return -1;
   if (domain->mode != PN_SSL_MODE_SERVER) {
-    _log_error(NULL, "Cannot permit unsecured clients - not a server.");
+    pn_transport_log(NULL, "Cannot permit unsecured clients - not a server.");
     return -1;
   }
   domain->allow_unsecured = true;
@@ -732,10 +749,11 @@ int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
 }
 
 
-bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *buffer, size_t size )
+bool pn_ssl_get_cipher_name(pn_ssl_t *ssl0, char *buffer, size_t size )
 {
   const SSL_CIPHER *c;
 
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   *buffer = '\0';
   if (ssl->ssl && (c = SSL_get_current_cipher( ssl->ssl ))) {
     const char *v = SSL_CIPHER_get_name(c);
@@ -747,10 +765,11 @@ bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *buffer, size_t size )
   return false;
 }
 
-bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *buffer, size_t size )
+bool pn_ssl_get_protocol_name(pn_ssl_t *ssl0, char *buffer, size_t size )
 {
   const SSL_CIPHER *c;
 
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   *buffer = '\0';
   if (ssl->ssl && (c = SSL_get_current_cipher( ssl->ssl ))) {
     const char *v = SSL_CIPHER_get_version(c);
@@ -763,10 +782,11 @@ bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *buffer, size_t size )
 }
 
 
-void pn_ssl_free( pn_ssl_t *ssl)
+void pn_ssl_free(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl) return;
-  _log( ssl, "SSL socket freed." );
+  ssl_log(transport, "SSL socket freed." );
   release_ssl_socket( ssl );
   if (ssl->domain) pn_ssl_domain_free(ssl->domain);
   if (ssl->session_id) free((void *)ssl->session_id);
@@ -779,9 +799,9 @@ void pn_ssl_free( pn_ssl_t *ssl)
 pn_ssl_t *pn_ssl(pn_transport_t *transport)
 {
   if (!transport) return NULL;
-  if (transport->ssl) return transport->ssl;
+  if (transport->ssl) return (pn_ssl_t *) transport;
 
-  pn_ssl_t *ssl = (pn_ssl_t *) calloc(1, sizeof(pn_ssl_t));
+  pni_ssl_t *ssl = (pni_ssl_t *) calloc(1, sizeof(pni_ssl_t));
   if (!ssl) return NULL;
   ssl->out_size = APP_BUF_SIZE;
   uint32_t max_frame = pn_transport_get_max_frame(transport);
@@ -798,14 +818,11 @@ pn_ssl_t *pn_ssl(pn_transport_t *transport)
     return NULL;
   }
 
-  ssl->transport = transport;
   transport->ssl = ssl;
 
-  transport->io_layers[PN_IO_SSL] = &pni_passthru_layer;
-
   ssl->trace = (transport->disp) ? transport->disp->trace : PN_TRACE_OFF;
 
-  return ssl;
+  return (pn_ssl_t *) transport;
 }
 
 
@@ -819,10 +836,11 @@ static int keyfile_pw_cb(char *buf, int size, int rwflag, void *userdata)
 }
 
 
-static int start_ssl_shutdown( pn_ssl_t *ssl )
+static int start_ssl_shutdown(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl->ssl_shutdown) {
-    _log(ssl, "Shutting down SSL connection...");
+    ssl_log(transport, "Shutting down SSL connection...");
     if (ssl->session_id) {
       // save the negotiated credentials before we close the connection
       pn_ssl_session_t *ssn = (pn_ssl_session_t *)calloc( 1, sizeof(pn_ssl_session_t));
@@ -830,7 +848,7 @@ static int start_ssl_shutdown( pn_ssl_t *ssl )
         ssn->id = pn_strdup( ssl->session_id );
         ssn->session = SSL_get1_session( ssl->ssl );
         if (ssn->session) {
-          _log( ssl, "Saving SSL session as %s", ssl->session_id );
+          ssl_log(transport, "Saving SSL session as %s", ssl->session_id );
           LL_ADD( ssl->domain, ssn_cache, ssn );
         } else {
           ssl_session_free( ssn );
@@ -858,10 +876,10 @@ static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
 // SSL socket and pass it to the application.
 static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available)
 {
-  pn_ssl_t *ssl = transport->ssl;
-  if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_EOS;
+  pni_ssl_t *ssl = transport->ssl;
+  if (ssl->ssl == NULL && init_ssl_socket(transport, ssl)) return PN_EOS;
 
-  _log( ssl, "process_input_ssl( data size=%d )",available );
+  ssl_log( transport, "process_input_ssl( data size=%d )",available );
 
   ssize_t consumed = 0;
   bool work_pending;
@@ -880,12 +898,12 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
         consumed += written;
         ssl->read_blocked = false;
         work_pending = (available > 0);
-        _log( ssl, "Wrote %d bytes to BIO Layer, %d left over", written, available );
+        ssl_log( transport, "Wrote %d bytes to BIO Layer, %d left over", written, available );
       }
     } else if (shutdown_input) {
       // lower layer (caller) has closed.  Close the WRITE side of the BIO.  This will cause
       // an EOF to be passed to SSL once all pending inbound data has been consumed.
-      _log( ssl, "Lower layer closed - shutting down BIO write side");
+      ssl_log( transport, "Lower layer closed - shutting down BIO write side");
       (void)BIO_shutdown_wr( ssl->bio_net_io );
       shutdown_input = false;
     }
@@ -895,8 +913,8 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
     if (!ssl->ssl_closed && ssl->in_count < ssl->in_size) {
       int read = BIO_read( ssl->bio_ssl, &ssl->inbuf[ssl->in_count], ssl->in_size - ssl->in_count );
       if (read > 0) {
-        _log( ssl, "Read %d bytes from SSL socket for app", read );
-        _log_clear_data( ssl, &ssl->inbuf[ssl->in_count], read );
+        ssl_log( transport, "Read %d bytes from SSL socket for app", read );
+        ssl_log_clear_data( ssl, &ssl->inbuf[ssl->in_count], read );
         ssl->in_count += read;
         work_pending = true;
       } else {
@@ -905,22 +923,22 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
           switch (reason) {
           case SSL_ERROR_ZERO_RETURN:
             // SSL closed cleanly
-            _log(ssl, "SSL connection has closed");
-            start_ssl_shutdown(ssl);  // KAG: not sure - this may not be necessary
+            ssl_log(transport, "SSL connection has closed");
+            start_ssl_shutdown(transport);  // KAG: not sure - this may not be necessary
             ssl->ssl_closed = true;
             break;
           default:
             // unexpected error
-            return (ssize_t)ssl_failed(ssl);
+            return (ssize_t)ssl_failed(transport);
           }
         } else {
           if (BIO_should_write( ssl->bio_ssl )) {
             ssl->write_blocked = true;
-            _log(ssl, "Detected write-blocked");
+            ssl_log(transport, "Detected write-blocked");
           }
           if (BIO_should_read( ssl->bio_ssl )) {
             ssl->read_blocked = true;
-            _log(ssl, "Detected read-blocked");
+            ssl_log(transport, "Detected read-blocked");
           }
         }
       }
@@ -936,22 +954,22 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
           if (ssl->in_count)
             memmove( ssl->inbuf, ssl->inbuf + consumed, ssl->in_count );
           work_pending = true;
-          _log( ssl, "Application consumed %d bytes from peer", (int) consumed );
+          ssl_log( transport, "Application consumed %d bytes from peer", (int) consumed );
         } else if (consumed < 0) {
-          _log(ssl, "Application layer closed its input, error=%d (discarding %d bytes)",
+          ssl_log(transport, "Application layer closed its input, error=%d (discarding %d bytes)",
                (int) consumed, (int)ssl->in_count);
           ssl->in_count = 0;    // discard any pending input
           ssl->app_input_closed = consumed;
           if (ssl->app_output_closed && ssl->out_count == 0) {
             // both sides of app closed, and no more app output pending:
-            start_ssl_shutdown(ssl);
+            start_ssl_shutdown(transport);
           }
         } else {
           // app did not consume any bytes, must be waiting for a full frame
           if (ssl->in_count == ssl->in_size) {
             // but the buffer is full, not enough room for a full frame.
             // can we grow the buffer?
-            uint32_t max_frame = pn_transport_get_max_frame(ssl->transport);
+            uint32_t max_frame = pn_transport_get_max_frame(transport);
             if (!max_frame) max_frame = ssl->in_size * 2;  // no limit
             if (ssl->in_size < max_frame) {
               // no max frame limit - grow it.
@@ -968,7 +986,7 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
               // the application _must_ have enough data to process.  If
               // this is an oversized frame, the app _must_ handle it
               // by returning an error code to SSL.
-              _log_error(ssl, "Error: application unable to consume input.");
+              pn_transport_log(transport, "Error: application unable to consume input.");
             }
           }
         }
@@ -998,15 +1016,15 @@ static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer,
       transport->io_layers[layer] = &ssl_input_closed_layer;
     }
   }
-  _log(ssl, "process_input_ssl() returning %d", (int) consumed);
+  ssl_log(transport, "process_input_ssl() returning %d", (int) consumed);
   return consumed;
 }
 
 static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_len)
 {
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl) return PN_EOS;
-  if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_EOS;
+  if (ssl->ssl == NULL && init_ssl_socket(transport, ssl)) return PN_EOS;
 
   ssize_t written = 0;
   bool work_pending;
@@ -1020,10 +1038,10 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
       if (app_bytes > 0) {
         ssl->out_count += app_bytes;
         work_pending = true;
-        _log( ssl, "Gathered %d bytes from app to send to peer", app_bytes );
+        ssl_log(transport, "Gathered %d bytes from app to send to peer", app_bytes );
       } else {
         if (app_bytes < 0) {
-          _log(ssl, "Application layer closed its output, error=%d (%d bytes pending send)",
+          ssl_log(transport, "Application layer closed its output, error=%d (%d bytes pending send)",
                (int) app_bytes, (int) ssl->out_count);
           ssl->app_output_closed = app_bytes;
         }
@@ -1040,30 +1058,30 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
           data += wrote;
           ssl->out_count -= wrote;
           work_pending = true;
-          _log( ssl, "Wrote %d bytes from app to socket", wrote );
+          ssl_log( transport, "Wrote %d bytes from app to socket", wrote );
         } else {
           if (!BIO_should_retry(ssl->bio_ssl)) {
             int reason = SSL_get_error( ssl->ssl, wrote );
             switch (reason) {
             case SSL_ERROR_ZERO_RETURN:
               // SSL closed cleanly
-              _log(ssl, "SSL connection has closed");
-              start_ssl_shutdown(ssl); // KAG: not sure - this may not be necessary
+              ssl_log(transport, "SSL connection has closed");
+              start_ssl_shutdown(transport); // KAG: not sure - this may not be necessary
               ssl->out_count = 0;      // can no longer write to socket, so erase app output data
               ssl->ssl_closed = true;
               break;
             default:
               // unexpected error
-              return (ssize_t)ssl_failed(ssl);
+              return (ssize_t)ssl_failed(transport);
             }
           } else {
             if (BIO_should_read( ssl->bio_ssl )) {
               ssl->read_blocked = true;
-              _log(ssl, "Detected read-blocked");
+              ssl_log(transport, "Detected read-blocked");
             }
             if (BIO_should_write( ssl->bio_ssl )) {
               ssl->write_blocked = true;
-              _log(ssl, "Detected write-blocked");
+              ssl_log(transport, "Detected write-blocked");
             }
           }
         }
@@ -1073,7 +1091,7 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
         if (ssl->app_input_closed && ssl->app_output_closed) {
           // application is done sending/receiving data, and all buffered output data has
           // been written to the SSL socket
-          start_ssl_shutdown(ssl);
+          start_ssl_shutdown(transport);
         }
       } else if (data != ssl->outbuf) {
         memmove( ssl->outbuf, data, ssl->out_count );
@@ -1089,7 +1107,7 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
         written += available;
         ssl->write_blocked = false;
         work_pending = work_pending || max_len > 0;
-        _log( ssl, "Read %d bytes from BIO Layer", available );
+        ssl_log(transport, "Read %d bytes from BIO Layer", available );
       }
     }
 
@@ -1114,23 +1132,23 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
       transport->io_layers[layer] = &ssl_output_closed_layer;
     }
   }
-  _log(ssl, "process_output_ssl() returning %d", (int) written);
+  ssl_log(transport, "process_output_ssl() returning %d", (int) written);
   return written;
 }
 
-static int init_ssl_socket( pn_ssl_t *ssl )
+static int init_ssl_socket(pn_transport_t* transport, pni_ssl_t *ssl)
 {
   if (ssl->ssl) return 0;
   if (!ssl->domain) return -1;
 
   ssl->ssl = SSL_new(ssl->domain->ctx);
   if (!ssl->ssl) {
-    _log_error(ssl, "SSL socket setup failure." );
+    pn_transport_logf(transport, "SSL socket setup failure." );
     return -1;
   }
 
-  // store backpointer to pn_ssl_t in SSL object:
-  SSL_set_ex_data(ssl->ssl, ssl_ex_data_index, ssl);
+  // store backpointer to pn_transport_t in SSL object:
+  SSL_set_ex_data(ssl->ssl, ssl_ex_data_index, transport);
 
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
   if (ssl->peer_hostname && ssl->domain->mode == PN_SSL_MODE_CLIENT) {
@@ -1142,10 +1160,10 @@ static int init_ssl_socket( pn_ssl_t *ssl )
   if (ssl->session_id) {
     pn_ssl_session_t *ssn = ssn_cache_find( ssl->domain, ssl->session_id );
     if (ssn) {
-      _log( ssl, "Restoring previous session id=%s", ssn->id );
+      ssl_log( transport, "Restoring previous session id=%s", ssn->id );
       int rc = SSL_set_session( ssl->ssl, ssn->session );
       if (rc != 1) {
-        _log( ssl, "Session restore failed, id=%s", ssn->id );
+        ssl_log( transport, "Session restore failed, id=%s", ssn->id );
       }
       LL_REMOVE( ssl->domain, ssn_cache, ssn );
       ssl_session_free( ssn );
@@ -1155,14 +1173,14 @@ static int init_ssl_socket( pn_ssl_t *ssl )
   // now layer a BIO over the SSL socket
   ssl->bio_ssl = BIO_new(BIO_f_ssl());
   if (!ssl->bio_ssl) {
-    _log_error(ssl, "BIO setup failure." );
+    pn_transport_log(transport, "BIO setup failure." );
     return -1;
   }
   (void)BIO_set_ssl(ssl->bio_ssl, ssl->ssl, BIO_NOCLOSE);
 
   // create the "lower" BIO "pipe", and attach it below the SSL layer
   if (!BIO_new_bio_pair(&ssl->bio_ssl_io, 0, &ssl->bio_net_io, 0)) {
-    _log_error(ssl, "BIO setup failure." );
+    pn_transport_log(transport, "BIO setup failure." );
     return -1;
   }
   SSL_set_bio(ssl->ssl, ssl->bio_ssl_io, ssl->bio_ssl_io);
@@ -1170,16 +1188,16 @@ static int init_ssl_socket( pn_ssl_t *ssl )
   if (ssl->domain->mode == PN_SSL_MODE_SERVER) {
     SSL_set_accept_state(ssl->ssl);
     BIO_set_ssl_mode(ssl->bio_ssl, 0);  // server mode
-    _log( ssl, "Server SSL socket created." );
+    ssl_log( transport, "Server SSL socket created." );
   } else {      // client mode
     SSL_set_connect_state(ssl->ssl);
     BIO_set_ssl_mode(ssl->bio_ssl, 1);  // client mode
-    _log( ssl, "Client SSL socket created." );
+    ssl_log( transport, "Client SSL socket created." );
   }
   return 0;
 }
 
-static void release_ssl_socket( pn_ssl_t *ssl )
+static void release_ssl_socket(pni_ssl_t *ssl)
 {
   if (ssl->bio_ssl) BIO_free(ssl->bio_ssl);
   if (ssl->ssl) {
@@ -1206,14 +1224,13 @@ static int setup_cleartext_connection(pn_transport_t *transport, unsigned int la
 
 static ssize_t process_input_unknown(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
-  pn_ssl_t *ssl = transport->ssl;
   switch (check_for_ssl_connection( input_data, len )) {
   case SSL_CONNECTION:
-    _log( ssl, "SSL connection detected.\n");
+    ssl_log( transport, "SSL connection detected.");
     setup_ssl_connection(transport, layer);
     break;
   case CLEAR_CONNECTION:
-    _log( ssl, "Cleartext connection detected.\n");
+    ssl_log( transport, "Cleartext connection detected.");
     setup_cleartext_connection(transport, layer);
     break;
   default:
@@ -1281,14 +1298,15 @@ static connection_mode_t check_for_ssl_connection( const char *data, size_t len
   return UNKNOWN_CONNECTION;
 }
 
-void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace)
+void pn_ssl_trace(pn_transport_t *transport, pn_trace_t trace)
 {
-  ssl->trace = trace;
+  transport->ssl->trace = trace;
 }
 
 
-pn_ssl_resume_status_t pn_ssl_resume_status( pn_ssl_t *ssl )
+pn_ssl_resume_status_t pn_ssl_resume_status(pn_ssl_t *ssl0)
 {
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl || !ssl->ssl) return PN_SSL_RESUME_UNKNOWN;
   switch (SSL_session_reused( ssl->ssl )) {
   case 0: return PN_SSL_RESUME_NEW;
@@ -1299,8 +1317,9 @@ pn_ssl_resume_status_t pn_ssl_resume_status( pn_ssl_t *ssl )
 }
 
 
-int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname )
+int pn_ssl_set_peer_hostname(pn_ssl_t *ssl0, const char *hostname)
 {
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl) return -1;
 
   if (ssl->peer_hostname) free((void *)ssl->peer_hostname);
@@ -1317,8 +1336,9 @@ int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname )
   return 0;
 }
 
-int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
+int pn_ssl_get_peer_hostname(pn_ssl_t *ssl0, char *hostname, size_t *bufsize)
 {
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl) return -1;
   if (!ssl->peer_hostname) {
     *bufsize = 0;
@@ -1347,7 +1367,7 @@ static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer
 static size_t buffered_output(pn_transport_t *transport)
 {
   size_t count = 0;
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   if (ssl) {
     count += ssl->out_count;
     if (ssl->bio_net_io) { // pick up any bytes waiting for network io

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/ssl/ssl-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/ssl-internal.h b/proton-c/src/ssl/ssl-internal.h
index c72e513..f1cd637 100644
--- a/proton-c/src/ssl/ssl-internal.h
+++ b/proton-c/src/ssl/ssl-internal.h
@@ -29,8 +29,8 @@
  */
 
 // release the SSL context
-void pn_ssl_free( pn_ssl_t *ssl);
+void pn_ssl_free(pn_transport_t *transport);
 
-void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace);
+void pn_ssl_trace(pn_transport_t *transport, pn_trace_t trace);
 
 #endif /* ssl-internal.h */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index 2c086db..865f8c9 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -268,8 +268,8 @@ static void pn_transport_finalize(void *object)
 {
   pn_transport_t *transport = (pn_transport_t *) object;
 
-  pn_ssl_free(transport->ssl);
-  pn_sasl_free(transport->sasl);
+  pn_ssl_free(transport);
+  pn_sasl_free(transport);
   pn_dispatcher_free(transport->disp);
   free(transport->remote_container);
   free(transport->remote_hostname);
@@ -1945,8 +1945,8 @@ ssize_t pn_transport_output(pn_transport_t *transport, char *bytes, size_t size)
 
 void pn_transport_trace(pn_transport_t *transport, pn_trace_t trace)
 {
-  if (transport->sasl) pn_sasl_trace(transport->sasl, trace);
-  if (transport->ssl) pn_ssl_trace(transport->ssl, trace);
+  if (transport->sasl) pn_sasl_trace(transport, trace);
+  if (transport->ssl) pn_ssl_trace(transport, trace);
   transport->disp->trace = trace;
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/df029005/proton-c/src/windows/schannel.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/windows/schannel.c
index 7f47745..231349c 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/windows/schannel.c
@@ -80,8 +80,7 @@ struct pn_ssl_domain_t {
 typedef enum { CREATED, CLIENT_HELLO, NEGOTIATING,
                RUNNING, SHUTTING_DOWN, SSL_CLOSED } ssl_state_t;
 
-struct pn_ssl_t {
-  pn_transport_t   *transport;
+struct pni_ssl_t {
   pn_ssl_domain_t  *domain;
   const char    *session_id;
   const char *peer_hostname;
@@ -127,6 +126,18 @@ struct pn_ssl_t {
   SecPkgContext_StreamSizes sc_sizes;
 };
 
+static inline pn_transport_t *get_transport_internal(pn_ssl_t *ssl)
+{
+  // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+  return ((pn_transport_t *)ssl);
+}
+
+static inline pni_ssl_t *get_ssl_internal(pn_ssl_t *ssl)
+{
+  // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+  return ssl ? ((pn_transport_t *)ssl)->ssl : NULL;
+}
+
 struct pn_ssl_session_t {
   const char       *id;
 // TODO
@@ -145,9 +156,9 @@ static connection_mode_t check_for_ssl_connection( const char *data, size_t len
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
 static void ssl_session_free( pn_ssl_session_t *);
 static size_t buffered_output( pn_transport_t *transport );
-static void start_ssl_shutdown(pn_ssl_t *ssl);
-static void rewind_sc_inbuf(pn_ssl_t *ssl);
-static bool grow_inbuf2(pn_ssl_t *ssl, size_t minimum_size);
+static void start_ssl_shutdown(pn_transport_t *transport);
+static void rewind_sc_inbuf(pni_ssl_t *ssl);
+static bool grow_inbuf2(pn_transport_t *ssl, size_t minimum_size);
 
 
 // @todo: used to avoid littering the code with calls to printf...
@@ -161,7 +172,7 @@ static void ssl_log_error(const char *fmt, ...)
 }
 
 // @todo: used to avoid littering the code with calls to printf...
-static void ssl_log(pn_ssl_t *ssl, const char *fmt, ...)
+static void ssl_log(pni_ssl_t *ssl, const char *fmt, ...)
 {
   if (PN_TRACE_DRV & ssl->trace) {
     va_list ap;
@@ -192,7 +203,7 @@ static void ssl_log_error_status(HRESULT status, const char *fmt, ...)
   fflush(stderr);
 }
 
-static void ssl_log_clear_data(pn_ssl_t *ssl, const char *data, size_t len)
+static void ssl_log_clear_data(pni_ssl_t *ssl, const char *data, size_t len)
 {
   if (PN_TRACE_RAW & ssl->trace) {
     fprintf(stderr, "SSL decrypted data: \"");
@@ -207,7 +218,7 @@ static size_t _pni_min(size_t a, size_t b)
 }
 
 // unrecoverable SSL failure occured, notify transport and generate error code.
-static int ssl_failed(pn_ssl_t *ssl, const char *reason)
+static int ssl_failed(pn_transport_t *transport, const char *reason)
 {
   char buf[512] = "Unknown error.";
   if (!reason) {
@@ -217,10 +228,11 @@ static int ssl_failed(pn_ssl_t *ssl, const char *reason)
                   0, status, 0, buf, sizeof(buf), 0);
     reason = buf;
   }
+  pni_ssl_t *ssl = transport->ssl;
   ssl->ssl_closed = true;
   ssl->app_input_closed = ssl->app_output_closed = PN_EOS;
   ssl->state = SSL_CLOSED;
-  pn_do_error(ssl->transport, "amqp:connection:framing-error", "SSL Failure: %s", reason);
+  pn_do_error(transport, "amqp:connection:framing-error", "SSL Failure: %s", reason);
   return PN_EOS;
 }
 
@@ -383,18 +395,20 @@ const pn_io_layer_t ssl_closed_layer = {
     buffered_output
 };
 
-int pn_ssl_init(pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
+int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char *session_id)
 {
+  pn_transport_t *transport = get_transport_internal(ssl0);
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl || !domain || ssl->domain) return -1;
   if (ssl->state != CREATED) return -1;
 
   ssl->domain = domain;
   domain->ref_count++;
   if (domain->allow_unsecured) {
-    ssl->transport->io_layers[PN_IO_SSL] = &unknown_layer;
+    transport->io_layers[PN_IO_SSL] = &unknown_layer;
   }
   else {
-    ssl->transport->io_layers[PN_IO_SSL] = &ssl_layer;
+    transport->io_layers[PN_IO_SSL] = &ssl_layer;
   }
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
@@ -440,8 +454,9 @@ bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *buffer, size_t size )
 }
 
 
-void pn_ssl_free( pn_ssl_t *ssl)
+void pn_ssl_free( pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl) return;
   ssl_log( ssl, "SSL socket freed.\n" );
   // clean up Windows per TLS session data before releasing the domain count
@@ -462,9 +477,9 @@ void pn_ssl_free( pn_ssl_t *ssl)
 pn_ssl_t *pn_ssl(pn_transport_t *transport)
 {
   if (!transport) return NULL;
-  if (transport->ssl) return transport->ssl;
+  if (transport->ssl) return (pn_ssl_t *)transport;
 
-  pn_ssl_t *ssl = (pn_ssl_t *) calloc(1, sizeof(pn_ssl_t));
+  pni_ssl_t *ssl = (pni_ssl_t *) calloc(1, sizeof(pni_ssl_t));
   if (!ssl) return NULL;
   ssl->sc_out_size = ssl->sc_in_size = SSL_BUF_SIZE;
 
@@ -488,23 +503,20 @@ pn_ssl_t *pn_ssl(pn_transport_t *transport)
     return NULL;
   }
 
-  ssl->transport = transport;
   transport->ssl = ssl;
 
-  transport->io_layers[PN_IO_SSL] = &pni_passthru_layer;
-
   ssl->trace = (transport->disp) ? transport->disp->trace : PN_TRACE_OFF;
   SecInvalidateHandle(&ssl->cred_handle);
   SecInvalidateHandle(&ssl->ctxt_handle);
   ssl->state = CREATED;
   ssl->decrypting = true;
 
-  return ssl;
+  return (pn_ssl_t *)transport;
 }
 
-void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace)
+void pn_ssl_trace(pn_transport_t *transport, pn_trace_t trace)
 {
-  ssl->trace = trace;
+  transport->ssl->trace = trace;
 }
 
 
@@ -515,8 +527,9 @@ pn_ssl_resume_status_t pn_ssl_resume_status( pn_ssl_t *ssl )
 }
 
 
-int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname )
+int pn_ssl_set_peer_hostname( pn_ssl_t *ssl0, const char *hostname )
 {
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl) return -1;
 
   if (ssl->peer_hostname) free((void *)ssl->peer_hostname);
@@ -528,8 +541,9 @@ int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname )
   return 0;
 }
 
-int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
+int pn_ssl_get_peer_hostname( pn_ssl_t *ssl0, char *hostname, size_t *bufsize )
 {
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl) return -1;
   if (!ssl->peer_hostname) {
     *bufsize = 0;
@@ -548,7 +562,7 @@ int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
 
 /** SChannel specific: */
 
-const char *tls_version_check(pn_ssl_t *ssl)
+const char *tls_version_check(pni_ssl_t *ssl)
 {
   SecPkgContext_ConnectionInfo info;
   QueryContextAttributes(&ssl->ctxt_handle, SECPKG_ATTR_CONNECTION_INFO, &info);
@@ -558,7 +572,7 @@ const char *tls_version_check(pn_ssl_t *ssl)
     "peer does not support TLS 1.0 security" : NULL;
 }
 
-static void ssl_encrypt(pn_ssl_t *ssl, char *app_data, size_t count)
+static void ssl_encrypt(pni_ssl_t *ssl, char *app_data, size_t count)
 {
   // Get SChannel to encrypt exactly one Record.
   SecBuffer buffs[4];
@@ -591,8 +605,9 @@ static void ssl_encrypt(pn_ssl_t *ssl, char *app_data, size_t count)
 }
 
 // Returns true if decryption succeeded (even for empty content)
-static bool ssl_decrypt(pn_ssl_t *ssl)
+static bool ssl_decrypt(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   // Get SChannel to decrypt input.  May have an incomplete Record,
   // exactly one, or more than one.  Check also for session ending,
   // session renegotiation.
@@ -630,7 +645,7 @@ static bool ssl_decrypt(pn_ssl_t *ssl)
     case SEC_I_RENEGOTIATE:
       // TODO.  Fall through for now.
     default:
-      ssl_failed(ssl, 0);
+      ssl_failed(transport, 0);
       return false;
     }
   }
@@ -657,8 +672,9 @@ static bool ssl_decrypt(pn_ssl_t *ssl)
   return true;
 }
 
-static void client_handshake_init(pn_ssl_t *ssl)
+static void client_handshake_init(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   // Tell SChannel to create the first handshake token (ClientHello)
   // and place it in sc_outbuf
   SEC_CHAR *host = const_cast<SEC_CHAR *>(ssl->peer_hostname);
@@ -689,11 +705,12 @@ static void client_handshake_init(pn_ssl_t *ssl)
     ssl_log(ssl, "Sending client hello %d bytes\n", ssl->network_out_pending);
   } else {
     ssl_log_error_status(status, "InitializeSecurityContext failed");
-    ssl_failed(ssl, 0);
+    ssl_failed(transport, 0);
   }
 }
 
-static void client_handshake( pn_ssl_t* ssl) {
+static void client_handshake( pn_transport_t* transport) {
+  pni_ssl_t *ssl = transport->ssl;
   // Feed SChannel ongoing responses from the server until the handshake is complete.
   SEC_CHAR *host = const_cast<SEC_CHAR *>(ssl->peer_hostname);
   ULONG ctxt_requested = ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS;
@@ -766,11 +783,11 @@ static void client_handshake( pn_ssl_t* ssl) {
       return;
     }
     if (send_buffs[0].cbBuffer != 0) {
-      ssl_failed(ssl, "unexpected final server token");
+      ssl_failed(transport, "unexpected final server token");
       break;
     }
     if (const char *err = tls_version_check(ssl)) {
-      ssl_failed(ssl, err);
+      ssl_failed(transport, err);
       break;
     }
     if (token_buffs[1].BufferType == SECBUFFER_EXTRA && token_buffs[1].cbBuffer > 0) {
@@ -787,8 +804,8 @@ static void client_handshake( pn_ssl_t* ssl) {
       ssl_log_error("Buffer size mismatch have %d, need %d\n", (int) ssl->sc_out_size, (int) max);
       ssl->state = SHUTTING_DOWN;
       ssl->app_input_closed = ssl->app_output_closed = PN_ERR;
-      start_ssl_shutdown(ssl);
-      pn_do_error(ssl->transport, "amqp:connection:framing-error", "SSL Failure: buffer size");
+      start_ssl_shutdown(transport);
+      pn_do_error(transport, "amqp:connection:framing-error", "SSL Failure: buffer size");
       break;
     }
 
@@ -801,7 +818,7 @@ static void client_handshake( pn_ssl_t* ssl) {
     // ended before we got going
   default:
     ssl_log(ssl, "client handshake failed %d\n", (int) status);
-    ssl_failed(ssl, 0);
+    ssl_failed(transport, 0);
     break;
   }
   ssl->decrypting = false;
@@ -809,28 +826,29 @@ static void client_handshake( pn_ssl_t* ssl) {
 }
 
 
-static void ssl_handshake(pn_ssl_t* ssl) {
-  if (ssl->domain->mode == PN_SSL_MODE_CLIENT)
-    client_handshake(ssl);
+static void ssl_handshake(pn_transport_t* transport) {
+  if (transport->ssl->domain->mode == PN_SSL_MODE_CLIENT)
+    client_handshake(transport);
   else {
-    ssl_log( ssl, "TODO: server handshake.\n" );
-    ssl_failed(ssl, "internal runtime error, not yet implemented");
+    ssl_log(transport->ssl, "TODO: server handshake.\n" );
+    ssl_failed(transport, "internal runtime error, not yet implemented");
   }
 }
 
-static bool grow_inbuf2(pn_ssl_t *ssl, size_t minimum_size) {
+static bool grow_inbuf2(pn_transport_t *transport, size_t minimum_size) {
+  pni_ssl_t *ssl = transport->ssl;
   size_t old_capacity = pn_buffer_capacity(ssl->inbuf2);
   size_t new_capacity = old_capacity ? old_capacity * 2 : 1024;
 
   while (new_capacity < minimum_size)
     new_capacity *= 2;
 
-  uint32_t max_frame = pn_transport_get_max_frame(ssl->transport);
+  uint32_t max_frame = pn_transport_get_max_frame(transport);
   if (max_frame != 0) {
     if (old_capacity >= max_frame) {
       //  already big enough
-      ssl_log(ssl, "Application expecting %d bytes (> negotiated maximum frame)\n", new_capacity);
-      ssl_failed(ssl, "TLS: transport maximimum frame size error");
+      ssl_log(transport->ssl, "Application expecting %d bytes (> negotiated maximum frame)\n", new_capacity);
+      ssl_failed(transport, "TLS: transport maximimum frame size error");
       return false;
     }
   }
@@ -839,7 +857,7 @@ static bool grow_inbuf2(pn_ssl_t *ssl, size_t minimum_size) {
   int err = pn_buffer_ensure(ssl->inbuf2, extra_bytes);
   if (err) {
     ssl_log(ssl, "TLS memory allocation failed for %d bytes\n", max_frame);
-    ssl_failed(ssl, "TLS memory allocation failed");
+    ssl_failed(transport, "TLS memory allocation failed");
     return false;
   }
   return true;
@@ -851,8 +869,9 @@ static bool grow_inbuf2(pn_ssl_t *ssl, size_t minimum_size) {
 // for the peer shutdown alert). Stop processing input immediately, and stop processing
 // output once this is sent.
 
-static void start_ssl_shutdown(pn_ssl_t *ssl)
+static void start_ssl_shutdown(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   assert(ssl->network_out_pending == 0);
   if (ssl->queued_shutdown)
     return;
@@ -871,7 +890,7 @@ static void start_ssl_shutdown(pn_ssl_t *ssl)
   ::ApplyControlToken(&ssl->ctxt_handle, &desc);
 
   // Next handshake will generate the shudown alert token
-  ssl_handshake(ssl);
+  ssl_handshake(transport);
 }
 
 static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
@@ -880,7 +899,7 @@ static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
   return 0;
 }
 
-static void rewind_sc_inbuf(pn_ssl_t *ssl)
+static void rewind_sc_inbuf(pni_ssl_t *ssl)
 {
   // Decrypted bytes have been drained or double buffered.  Prepare for the next SSL Record.
   assert(ssl->in_data_count == 0);
@@ -898,8 +917,9 @@ static void rewind_sc_inbuf(pn_ssl_t *ssl)
   }
 }
 
-static void app_inbytes_add(pn_ssl_t *ssl)
+static void app_inbytes_add(pn_transport_t *transport)
 {
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl->app_inbytes.start) {
     ssl->app_inbytes.start = ssl->in_data;
     ssl->app_inbytes.size = ssl->in_data_count;
@@ -908,7 +928,7 @@ static void app_inbytes_add(pn_ssl_t *ssl)
 
   if (ssl->double_buffered) {
     if (pn_buffer_available(ssl->inbuf2) == 0) {
-      if (!grow_inbuf2(ssl, 1024))
+      if (!grow_inbuf2(transport, 1024))
         // could not add room
         return;
     }
@@ -925,8 +945,9 @@ static void app_inbytes_add(pn_ssl_t *ssl)
 }
 
 
-static void app_inbytes_progress(pn_ssl_t *ssl, size_t minimum)
+static void app_inbytes_progress(pn_transport_t *transport, size_t minimum)
 {
+  pni_ssl_t *ssl = transport->ssl;
   // Make more decrypted data available, if possible.  Otherwise, move
   // unread bytes to front of inbuf2 to make room for next bulk decryption.
   // SSL may have chopped up data that app layer expects to be
@@ -947,7 +968,7 @@ static void app_inbytes_progress(pn_ssl_t *ssl, size_t minimum)
         pn_buffer_trim(ssl->inbuf2, 0, consumed);
       }
       if (!pn_buffer_available(ssl->inbuf2)) {
-        if (!grow_inbuf2(ssl, minimum))
+        if (!grow_inbuf2(transport, minimum))
           // could not add room
           return;
       }
@@ -963,7 +984,7 @@ static void app_inbytes_progress(pn_ssl_t *ssl, size_t minimum)
       ssl->double_buffered = true;
       pn_buffer_clear(ssl->inbuf2);
       if (!pn_buffer_available(ssl->inbuf2)) {
-        if (!grow_inbuf2(ssl, minimum))
+        if (!grow_inbuf2(transport, minimum))
           // could not add room
           return;
       }
@@ -981,11 +1002,12 @@ static void app_inbytes_progress(pn_ssl_t *ssl, size_t minimum)
 }
 
 
-static void app_inbytes_advance(pn_ssl_t *ssl, size_t consumed)
+static void app_inbytes_advance(pn_transport_t *transport, size_t consumed)
 {
+  pni_ssl_t *ssl = transport->ssl;
   if (consumed == 0) {
     // more contiguous bytes required
-    app_inbytes_progress(ssl, ssl->app_inbytes.size + 1);
+    app_inbytes_progress(transport, ssl->app_inbytes.size + 1);
     return;
   }
   assert(consumed <= ssl->app_inbytes.size);
@@ -996,12 +1018,12 @@ static void app_inbytes_advance(pn_ssl_t *ssl, size_t consumed)
     ssl->in_data_count -= consumed;
   }
   if (ssl->app_inbytes.size == 0)
-    app_inbytes_progress(ssl, 0);
+    app_inbytes_progress(transport, 0);
 }
 
 static void read_closed(pn_transport_t *transport, unsigned int layer, ssize_t error)
 {
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   if (ssl->app_input_closed)
     return;
   if (ssl->state == RUNNING && !error) {
@@ -1015,7 +1037,7 @@ static void read_closed(pn_transport_t *transport, unsigned int layer, ssize_t e
     // both sides of app closed, and no more app output pending:
     ssl->state = SHUTTING_DOWN;
     if (ssl->network_out_pending == 0 && !ssl->queued_shutdown) {
-      start_ssl_shutdown(ssl);
+      start_ssl_shutdown(transport);
     }
   }
 }
@@ -1025,7 +1047,7 @@ static void read_closed(pn_transport_t *transport, unsigned int layer, ssize_t e
 
 static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available)
 {
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   ssl_log( ssl, "process_input_ssl( data size=%d )\n",available );
   ssize_t consumed = 0;
   ssize_t forwarded = 0;
@@ -1091,13 +1113,13 @@ static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer,
 
     if (ssl->sc_in_count > 0 && ssl->state <= SHUTTING_DOWN) {
       if (ssl->state == NEGOTIATING) {
-        ssl_handshake(ssl);
+        ssl_handshake(transport);
       } else {
-        if (ssl_decrypt(ssl)) {
+        if (ssl_decrypt(transport)) {
           // Ignore TLS Record with 0 length data (does not mean EOS)
           if (ssl->in_data_size > 0) {
             new_app_input = true;
-            app_inbytes_add(ssl);
+            app_inbytes_add(transport);
           } else {
             assert(ssl->decrypting == false);
             rewind_sc_inbuf(ssl);
@@ -1109,7 +1131,7 @@ static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer,
 
     if (ssl->state == SHUTTING_DOWN) {
       if (ssl->network_out_pending == 0 && !ssl->queued_shutdown) {
-        start_ssl_shutdown(ssl);
+        start_ssl_shutdown(transport);
       }
     } else if (ssl->state == SSL_CLOSED) {
       return consumed ? consumed : -1;
@@ -1124,11 +1146,11 @@ static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer,
           if (count > 0) {
             forwarded += count;
             // advance() can increase app_inbytes.size if double buffered
-            app_inbytes_advance(ssl, count);
+            app_inbytes_advance(transport, count);
             ssl_log(ssl, "Application consumed %d bytes from peer\n", (int) count);
           } else if (count == 0) {
             size_t old_size = ssl->app_inbytes.size;
-            app_inbytes_advance(ssl, 0);
+            app_inbytes_advance(transport, 0);
             if (ssl->app_inbytes.size == old_size) {
               break;  // no additional contiguous decrypted data available, get more network data
             }
@@ -1136,13 +1158,13 @@ static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer,
             // count < 0
             ssl_log(ssl, "Application layer closed its input, error=%d (discarding %d bytes)\n",
                  (int) count, (int)ssl->app_inbytes.size);
-            app_inbytes_advance(ssl, ssl->app_inbytes.size);    // discard
+            app_inbytes_advance(transport, ssl->app_inbytes.size);    // discard
             read_closed(transport, layer, count);
           }
         } else {
           ssl_log(ssl, "Input closed discard %d bytes\n",
                (int)ssl->app_inbytes.size);
-          app_inbytes_advance(ssl, ssl->app_inbytes.size);      // discard
+          app_inbytes_advance(transport, ssl->app_inbytes.size);      // discard
         }
       }
     }
@@ -1162,7 +1184,7 @@ static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer,
 
 static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_len)
 {
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   if (!ssl) return PN_EOS;
   ssl_log( ssl, "process_output_ssl( max_len=%d )\n",max_len );
 
@@ -1172,7 +1194,7 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
 
   if (ssl->state == CLIENT_HELLO) {
     // output buffers eclusively for internal handshake use until negotiation complete
-    client_handshake_init(ssl);
+    client_handshake_init(transport);
     if (ssl->state == SSL_CLOSED)
       return PN_EOS;
     ssl->state = NEGOTIATING;
@@ -1227,7 +1249,7 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
 
     if (ssl->network_out_pending == 0 && ssl->state == SHUTTING_DOWN) {
       if (!ssl->queued_shutdown) {
-        start_ssl_shutdown(ssl);
+        start_ssl_shutdown(transport);
         work_pending = true;
       } else {
         ssl->state = SSL_CLOSED;
@@ -1348,7 +1370,7 @@ static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer
 static size_t buffered_output(pn_transport_t *transport)
 {
   size_t count = 0;
-  pn_ssl_t *ssl = transport->ssl;
+  pni_ssl_t *ssl = transport->ssl;
   if (ssl) {
     count += ssl->network_out_pending;
     if (count == 0 && ssl->state == SHUTTING_DOWN && ssl->queued_shutdown)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[15/35] qpid-proton git commit: PROTON-749: Add the deprecated C APIs back in for backward compatibility.

Posted by gs...@apache.org.
PROTON-749: Add the deprecated C APIs back in for backward compatibility.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/0fd34e83
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/0fd34e83
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/0fd34e83

Branch: refs/heads/examples
Commit: 0fd34e837db645c323fa1407c07ef41642501cbf
Parents: 1b2be03
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon Nov 17 14:34:29 2014 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Nov 19 17:50:26 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/proton.py |  8 ++++++++
 proton-c/include/proton/cproton.i  | 12 ++++++++++++
 proton-c/include/proton/sasl.h     | 23 +++++++++++++++++++++++
 proton-c/src/sasl/sasl.c           | 12 ++++++++++++
 4 files changed, 55 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0fd34e83/proton-c/bindings/python/proton.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton.py b/proton-c/bindings/python/proton.py
index 573ec14..fce3255 100644
--- a/proton-c/bindings/python/proton.py
+++ b/proton-c/bindings/python/proton.py
@@ -3193,6 +3193,14 @@ class SASL(object):
   def mechanisms(self, mechs):
     pn_sasl_mechanisms(self._sasl, mechs)
 
+  # @deprecated
+  def client(self):
+    pn_sasl_client(self._sasl)
+
+  # @deprecated
+  def server(self):
+    pn_sasl_server(self._sasl)
+
   def allow_skip(self, allow):
     pn_sasl_allow_skip(self._sasl, allow)
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0fd34e83/proton-c/include/proton/cproton.i
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/cproton.i b/proton-c/include/proton/cproton.i
index 3c5a1a6..3b347f2 100644
--- a/proton-c/include/proton/cproton.i
+++ b/proton-c/include/proton/cproton.i
@@ -995,6 +995,18 @@ typedef unsigned long int uintptr_t;
   sasl != NULL;
 }
 
+%contract pn_sasl_client(pn_sasl_t *sasl)
+{
+ require:
+  sasl != NULL;
+}
+
+%contract pn_sasl_server(pn_sasl_t *sasl)
+{
+ require:
+  sasl != NULL;
+}
+
 %contract pn_sasl_allow_skip(pn_sasl_t *sasl, bool allow)
 {
  require:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0fd34e83/proton-c/include/proton/sasl.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/sasl.h b/proton-c/include/proton/sasl.h
index ab64e13..104e156 100644
--- a/proton-c/include/proton/sasl.h
+++ b/proton-c/include/proton/sasl.h
@@ -95,6 +95,29 @@ PN_EXTERN void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms);
  */
 PN_EXTERN const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl);
 
+/**
+ * @deprecated
+ * Configure the SASL layer to act as a SASL client.
+ *
+ * This is now unnecessary, and performs no function. The server/clientness
+ * of the sasl layer is determined from the role of the transport that is used to create
+ * it. The API is retained here so as not to break existing code.
+ *
+ * @param[in] sasl the SASL layer to configure as a client
+ */
+PN_EXTERN void pn_sasl_client(pn_sasl_t *sasl);
+
+/**
+ * @deprecated
+ * Configure the SASL layer to act as a server.
+ *
+ * This is now only necessary for backwards compatibility if creating a server pn_sasl_t
+ * from a pn_transport_t which was created implicitly as a client by pn_transport().
+ *
+ * @param[in] sasl the SASL layer to configure as a server
+ */
+PN_EXTERN void pn_sasl_server(pn_sasl_t *sasl);
+
 /** Configure a SASL server layer to permit the client to skip the SASL exchange.
  *
  * If the peer client skips the SASL exchange (i.e. goes right to the AMQP header)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0fd34e83/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 1ee8f9b..4ed9f84 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -197,6 +197,18 @@ ssize_t pn_sasl_recv(pn_sasl_t *sasl0, char *bytes, size_t size)
   }
 }
 
+void pn_sasl_client(pn_sasl_t *sasl)
+{
+}
+
+void pn_sasl_server(pn_sasl_t *sasl0)
+{
+  pni_sasl_t *sasl = get_sasl_internal(sasl0);
+  if (sasl) {
+    sasl->client = false;
+  }
+}
+
 void pn_sasl_allow_skip(pn_sasl_t *sasl0, bool allow)
 {
   pni_sasl_t *sasl = get_sasl_internal(sasl0);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[22/35] qpid-proton git commit: changed proton.py from a module into a package

Posted by gs...@apache.org.
changed proton.py from a module into a package


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/6a78d2f7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/6a78d2f7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/6a78d2f7

Branch: refs/heads/examples
Commit: 6a78d2f774a287070d12622556d6d5504fdfd581
Parents: 1913040
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Sat Nov 22 05:50:52 2014 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Sat Nov 22 06:03:01 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/CMakeLists.txt     |    2 +-
 proton-c/bindings/python/proton.py          | 3891 ----------------------
 proton-c/bindings/python/proton/__init__.py | 3891 ++++++++++++++++++++++
 3 files changed, 3892 insertions(+), 3892 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6a78d2f7/proton-c/bindings/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/CMakeLists.txt b/proton-c/bindings/python/CMakeLists.txt
index 6ab1e67..6be421e 100644
--- a/proton-c/bindings/python/CMakeLists.txt
+++ b/proton-c/bindings/python/CMakeLists.txt
@@ -53,7 +53,7 @@ if (NOT PYTHON_SITEARCH_PACKAGES)
 endif()
 
 set (pysrc-generated cproton.py)
-set (pysrc proton.py)
+set (pysrc proton/__init__.py)
 
 macro (py_compile directory files)
   foreach (src_file ${files})


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[08/35] qpid-proton git commit: PROTON-736: Replace missed force_encoding with encode

Posted by gs...@apache.org.
PROTON-736: Replace missed force_encoding with encode


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d770a1ef
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d770a1ef
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d770a1ef

Branch: refs/heads/examples
Commit: d770a1ef689d859888f8cc610486b0dba4ea5fa9
Parents: 6504db6
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Tue Nov 18 09:01:33 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Tue Nov 18 09:01:33 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/lib/qpid_proton/strings.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d770a1ef/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/strings.rb b/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
index dad96ad..d8f5851 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
@@ -31,7 +31,7 @@ module Qpid # :nodoc:
       # exception then we'll treat it as binary.
       if RUBY_VERSION >= "1.9"
         return true if (value.encoding == "UTF-8" ||
-                        value.force_encoding("UTF-8").valid_encoding?)
+                        value.encode("UTF-8").valid_encoding?)
 
         return false
       else


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[18/35] qpid-proton git commit: PROTON-755: Update Ruby smoke tests to use Minitest

Posted by gs...@apache.org.
PROTON-755: Update Ruby smoke tests to use Minitest

The old test framework module names have changed.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1d3a1386
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1d3a1386
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1d3a1386

Branch: refs/heads/examples
Commit: 1d3a13863117cfca5aef56244b20773760428796
Parents: b4e06d3
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Thu Nov 20 13:42:41 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Thu Nov 20 13:45:06 2014 -0500

----------------------------------------------------------------------
 tests/ruby/proton-test             | 2 +-
 tests/ruby/proton_tests/interop.rb | 4 ++--
 tests/ruby/proton_tests/smoke.rb   | 8 ++++----
 3 files changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1d3a1386/tests/ruby/proton-test
----------------------------------------------------------------------
diff --git a/tests/ruby/proton-test b/tests/ruby/proton-test
index 748e6f0..acb0d43 100755
--- a/tests/ruby/proton-test
+++ b/tests/ruby/proton-test
@@ -1,5 +1,5 @@
 #!/usr/bin/env ruby
 
-require 'test/unit'
+require 'minitest/autorun'
 require 'proton_tests/interop.rb'
 require 'proton_tests/smoke.rb'

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1d3a1386/tests/ruby/proton_tests/interop.rb
----------------------------------------------------------------------
diff --git a/tests/ruby/proton_tests/interop.rb b/tests/ruby/proton_tests/interop.rb
index e14cba1..21d92d9 100755
--- a/tests/ruby/proton_tests/interop.rb
+++ b/tests/ruby/proton_tests/interop.rb
@@ -1,6 +1,6 @@
 #!/usr/bin/env ruby
 
-require 'test/unit'
+require 'minitest/autorun'
 require 'qpid_proton'
 
 if ((RUBY_VERSION.split(".").map {|x| x.to_i}  <=> [1, 9]) < 0)
@@ -12,7 +12,7 @@ if ((RUBY_VERSION.split(".").map {|x| x.to_i}  <=> [1, 9]) < 0)
   end
 end
 
-class InteropTest < Test::Unit::TestCase
+class InteropTest < Minitest::Test
   Data = Qpid::Proton::Data
   Message = Qpid::Proton::Message
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1d3a1386/tests/ruby/proton_tests/smoke.rb
----------------------------------------------------------------------
diff --git a/tests/ruby/proton_tests/smoke.rb b/tests/ruby/proton_tests/smoke.rb
index 6368283..a382a0b 100644
--- a/tests/ruby/proton_tests/smoke.rb
+++ b/tests/ruby/proton_tests/smoke.rb
@@ -1,9 +1,9 @@
 #!/usr/bin/env ruby
 
-require 'test/unit'
+require 'minitest/autorun'
 require 'qpid_proton'
 
-class SmokeTest < Test::Unit::TestCase
+class SmokeTest < Minitest::Test
 
   Messenger = Qpid::Proton::Messenger
   Message = Qpid::Proton::Message
@@ -29,8 +29,8 @@ class SmokeTest < Test::Unit::TestCase
 
     pump()
 
-    assert @client.stopped
-    assert @server.stopped
+    assert @client.stopped?
+    assert @server.stopped?
   end
 
   def testSmoke(count=10)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[31/35] qpid-proton git commit: Merge branch 'master' into examples

Posted by gs...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d02fdad1/proton-c/bindings/python/proton/__init__.py
----------------------------------------------------------------------
diff --cc proton-c/bindings/python/proton/__init__.py
index 0000000,fce3255..e375723
mode 000000,100644..100644
--- a/proton-c/bindings/python/proton/__init__.py
+++ b/proton-c/bindings/python/proton/__init__.py
@@@ -1,0 -1,3891 +1,3894 @@@
+ #
+ # Licensed to the Apache Software Foundation (ASF) under one
+ # or more contributor license agreements.  See the NOTICE file
+ # distributed with this work for additional information
+ # regarding copyright ownership.  The ASF licenses this file
+ # to you under the Apache License, Version 2.0 (the
+ # "License"); you may not use this file except in compliance
+ # with the License.  You may obtain a copy of the License at
+ #
+ #   http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing,
+ # software distributed under the License is distributed on an
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ # KIND, either express or implied.  See the License for the
+ # specific language governing permissions and limitations
+ # under the License.
+ #
+ 
+ """
+ The proton module defines a suite of APIs that implement the AMQP 1.0
+ protocol.
+ 
+ The proton APIs consist of the following classes:
+ 
+  - L{Messenger} -- A messaging endpoint.
+  - L{Message}   -- A class for creating and/or accessing AMQP message content.
+  - L{Data}      -- A class for creating and/or accessing arbitrary AMQP encoded
+                   data.
+ 
+ """
+ 
+ from cproton import *
+ 
+ import weakref, re, socket
+ try:
+   import uuid
+ except ImportError:
+   """
+   No 'native' UUID support.  Provide a very basic UUID type that is a compatible subset of the uuid type provided by more modern python releases.
+   """
+   import struct
+   class uuid:
+     class UUID:
+       def __init__(self, hex=None, bytes=None):
+         if [hex, bytes].count(None) != 1:
+           raise TypeError("need one of hex or bytes")
+         if bytes is not None:
+           self.bytes = bytes
+         elif hex is not None:
+           fields=hex.split("-")
+           fields[4:5] = [fields[4][:4], fields[4][4:]]
+           self.bytes = struct.pack("!LHHHHL", *[int(x,16) for x in fields])
+ 
+       def __cmp__(self, other):
+         if isinstance(other, uuid.UUID):
+           return cmp(self.bytes, other.bytes)
+         else:
+           return -1
+ 
+       def __str__(self):
+         return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
+ 
+       def __repr__(self):
+         return "UUID(%r)" % str(self)
+ 
+       def __hash__(self):
+         return self.bytes.__hash__()
+ 
+   import os, random, socket, time
+   rand = random.Random()
+   rand.seed((os.getpid(), time.time(), socket.gethostname()))
+   def random_uuid():
+     bytes = [rand.randint(0, 255) for i in xrange(16)]
+ 
+     # From RFC4122, the version bits are set to 0100
+     bytes[7] &= 0x0F
+     bytes[7] |= 0x40
+ 
+     # From RFC4122, the top two bits of byte 8 get set to 01
+     bytes[8] &= 0x3F
+     bytes[8] |= 0x80
+     return "".join(map(chr, bytes))
+ 
+   def uuid4():
+     return uuid.UUID(bytes=random_uuid())
+ 
++def generate_uuid():
++  return uuid.uuid4()
++
+ try:
+   bytes()
+ except NameError:
+   bytes = str
+ 
+ VERSION_MAJOR = PN_VERSION_MAJOR
+ VERSION_MINOR = PN_VERSION_MINOR
+ API_LANGUAGE = "C"
+ IMPLEMENTATION_LANGUAGE = "C"
+ 
+ class Constant(object):
+ 
+   def __init__(self, name):
+     self.name = name
+ 
+   def __repr__(self):
+     return self.name
+ 
+ class ProtonException(Exception):
+   """
+   The root of the proton exception hierarchy. All proton exception
+   classes derive from this exception.
+   """
+   pass
+ 
+ class Timeout(ProtonException):
+   """
+   A timeout exception indicates that a blocking operation has timed
+   out.
+   """
+   pass
+ 
+ class Interrupt(ProtonException):
+   """
+   An interrupt exception indicaes that a blocking operation was interrupted.
+   """
+   pass
+ 
+ class MessengerException(ProtonException):
+   """
+   The root of the messenger exception hierarchy. All exceptions
+   generated by the messenger class derive from this exception.
+   """
+   pass
+ 
+ class MessageException(ProtonException):
+   """
+   The MessageException class is the root of the message exception
+   hierarhcy. All exceptions generated by the Message class derive from
+   this exception.
+   """
+   pass
+ 
+ EXCEPTIONS = {
+   PN_TIMEOUT: Timeout,
+   PN_INTR: Interrupt
+   }
+ 
+ PENDING = Constant("PENDING")
+ ACCEPTED = Constant("ACCEPTED")
+ REJECTED = Constant("REJECTED")
+ RELEASED = Constant("RELEASED")
+ ABORTED = Constant("ABORTED")
+ SETTLED = Constant("SETTLED")
+ 
+ STATUSES = {
+   PN_STATUS_ABORTED: ABORTED,
+   PN_STATUS_ACCEPTED: ACCEPTED,
+   PN_STATUS_REJECTED: REJECTED,
+   PN_STATUS_RELEASED: RELEASED,
+   PN_STATUS_PENDING: PENDING,
+   PN_STATUS_SETTLED: SETTLED,
+   PN_STATUS_UNKNOWN: None
+   }
+ 
+ AUTOMATIC = Constant("AUTOMATIC")
+ MANUAL = Constant("MANUAL")
+ 
+ class Messenger(object):
+   """
+   The L{Messenger} class defines a high level interface for sending
+   and receiving L{Messages<Message>}. Every L{Messenger} contains a
+   single logical queue of incoming messages and a single logical queue
+   of outgoing messages. These messages in these queues may be destined
+   for, or originate from, a variety of addresses.
+ 
+   The messenger interface is single-threaded.  All methods
+   except one (L{interrupt}) are intended to be used from within
+   the messenger thread.
+ 
+ 
+   Address Syntax
+   ==============
+ 
+   An address has the following form::
+ 
+     [ amqp[s]:// ] [user[:password]@] domain [/[name]]
+ 
+   Where domain can be one of::
+ 
+     host | host:port | ip | ip:port | name
+ 
+   The following are valid examples of addresses:
+ 
+    - example.org
+    - example.org:1234
+    - amqp://example.org
+    - amqps://example.org
+    - example.org/incoming
+    - amqps://example.org/outgoing
+    - amqps://fred:trustno1@example.org
+    - 127.0.0.1:1234
+    - amqps://127.0.0.1:1234
+ 
+   Sending & Receiving Messages
+   ============================
+ 
+   The L{Messenger} class works in conjuction with the L{Message} class. The
+   L{Message} class is a mutable holder of message content.
+ 
+   The L{put} method copies its L{Message} to the outgoing queue, and may
+   send queued messages if it can do so without blocking.  The L{send}
+   method blocks until it has sent the requested number of messages,
+   or until a timeout interrupts the attempt.
+ 
+ 
+     >>> message = Message()
+     >>> for i in range(3):
+     ...   message.address = "amqp://host/queue"
+     ...   message.subject = "Hello World %i" % i
+     ...   messenger.put(message)
+     >>> messenger.send()
+ 
+   Similarly, the L{recv} method receives messages into the incoming
+   queue, and may block as it attempts to receive the requested number
+   of messages,  or until timeout is reached. It may receive fewer
+   than the requested number.  The L{get} method pops the
+   eldest L{Message} off the incoming queue and copies it into the L{Message}
+   object that you supply.  It will not block.
+ 
+ 
+     >>> message = Message()
+     >>> messenger.recv(10):
+     >>> while messenger.incoming > 0:
+     ...   messenger.get(message)
+     ...   print message.subject
+     Hello World 0
+     Hello World 1
+     Hello World 2
+ 
+   The blocking flag allows you to turn off blocking behavior entirely,
+   in which case L{send} and L{recv} will do whatever they can without
+   blocking, and then return.  You can then look at the number
+   of incoming and outgoing messages to see how much outstanding work
+   still remains.
+   """
+ 
+   def __init__(self, name=None):
+     """
+     Construct a new L{Messenger} with the given name. The name has
+     global scope. If a NULL name is supplied, a UUID based name will
+     be chosen.
+ 
+     @type name: string
+     @param name: the name of the messenger or None
+ 
+     """
+     self._mng = pn_messenger(name)
+     self._selectables = {}
+ 
+   def __del__(self):
+     """
+     Destroy the L{Messenger}.  This will close all connections that
+     are managed by the L{Messenger}.  Call the L{stop} method before
+     destroying the L{Messenger}.
+     """
+     if hasattr(self, "_mng"):
+       pn_messenger_free(self._mng)
+       del self._mng
+ 
+   def _check(self, err):
+     if err < 0:
+       if (err == PN_INPROGRESS):
+         return
+       exc = EXCEPTIONS.get(err, MessengerException)
+       raise exc("[%s]: %s" % (err, pn_error_text(pn_messenger_error(self._mng))))
+     else:
+       return err
+ 
+   @property
+   def name(self):
+     """
+     The name of the L{Messenger}.
+     """
+     return pn_messenger_name(self._mng)
+ 
+   def _get_certificate(self):
+     return pn_messenger_get_certificate(self._mng)
+ 
+   def _set_certificate(self, value):
+     self._check(pn_messenger_set_certificate(self._mng, value))
+ 
+   certificate = property(_get_certificate, _set_certificate,
+                          doc="""
+ Path to a certificate file for the L{Messenger}. This certificate is
+ used when the L{Messenger} accepts or establishes SSL/TLS connections.
+ This property must be specified for the L{Messenger} to accept
+ incoming SSL/TLS connections and to establish client authenticated
+ outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS
+ connections do not require this property.
+ """)
+ 
+   def _get_private_key(self):
+     return pn_messenger_get_private_key(self._mng)
+ 
+   def _set_private_key(self, value):
+     self._check(pn_messenger_set_private_key(self._mng, value))
+ 
+   private_key = property(_get_private_key, _set_private_key,
+                          doc="""
+ Path to a private key file for the L{Messenger's<Messenger>}
+ certificate. This property must be specified for the L{Messenger} to
+ accept incoming SSL/TLS connections and to establish client
+ authenticated outgoing SSL/TLS connection. Non client authenticated
+ SSL/TLS connections do not require this property.
+ """)
+ 
+   def _get_password(self):
+     return pn_messenger_get_password(self._mng)
+ 
+   def _set_password(self, value):
+     self._check(pn_messenger_set_password(self._mng, value))
+ 
+   password = property(_get_password, _set_password,
+                       doc="""
+ This property contains the password for the L{Messenger.private_key}
+ file, or None if the file is not encrypted.
+ """)
+ 
+   def _get_trusted_certificates(self):
+     return pn_messenger_get_trusted_certificates(self._mng)
+ 
+   def _set_trusted_certificates(self, value):
+     self._check(pn_messenger_set_trusted_certificates(self._mng, value))
+ 
+   trusted_certificates = property(_get_trusted_certificates,
+                                   _set_trusted_certificates,
+                                   doc="""
+ A path to a database of trusted certificates for use in verifying the
+ peer on an SSL/TLS connection. If this property is None, then the peer
+ will not be verified.
+ """)
+ 
+   def _get_timeout(self):
+     t = pn_messenger_get_timeout(self._mng)
+     if t == -1:
+       return None
+     else:
+       return millis2secs(t)
+ 
+   def _set_timeout(self, value):
+     if value is None:
+       t = -1
+     else:
+       t = secs2millis(value)
+     self._check(pn_messenger_set_timeout(self._mng, t))
+ 
+   timeout = property(_get_timeout, _set_timeout,
+                      doc="""
+ The timeout property contains the default timeout for blocking
+ operations performed by the L{Messenger}.
+ """)
+ 
+   def _is_blocking(self):
+     return pn_messenger_is_blocking(self._mng)
+ 
+   def _set_blocking(self, b):
+     self._check(pn_messenger_set_blocking(self._mng, b))
+ 
+   blocking = property(_is_blocking, _set_blocking,
+                       doc="""
+ Enable or disable blocking behavior during L{Message} sending
+ and receiving.  This affects every blocking call, with the
+ exception of L{work}.  Currently, the affected calls are
+ L{send}, L{recv}, and L{stop}.
+ """)
+ 
+   def _is_passive(self):
+     return pn_messenger_is_passive(self._mng)
+ 
+   def _set_passive(self, b):
+     self._check(pn_messenger_set_passive(self._mng, b))
+ 
+   passive = property(_is_passive, _set_passive,
+                       doc="""
+ When passive is set to true, Messenger will not attempt to perform I/O
+ internally. In this mode it is necessary to use the selectables API to
+ drive any I/O needed to perform requested actions. In this mode
+ Messenger will never block.
+ """)
+ 
+   def _get_incoming_window(self):
+     return pn_messenger_get_incoming_window(self._mng)
+ 
+   def _set_incoming_window(self, window):
+     self._check(pn_messenger_set_incoming_window(self._mng, window))
+ 
+   incoming_window = property(_get_incoming_window, _set_incoming_window,
+                              doc="""
+ The incoming tracking window for the messenger. The messenger will
+ track the remote status of this many incoming deliveries after they
+ have been accepted or rejected. Defaults to zero.
+ 
+ L{Messages<Message>} enter this window only when you take them into your application
+ using L{get}.  If your incoming window size is I{n}, and you get I{n}+1 L{messages<Message>}
+ without explicitly accepting or rejecting the oldest message, then the
+ message that passes beyond the edge of the incoming window will be assigned
+ the default disposition of its link.
+ """)
+ 
+   def _get_outgoing_window(self):
+     return pn_messenger_get_outgoing_window(self._mng)
+ 
+   def _set_outgoing_window(self, window):
+     self._check(pn_messenger_set_outgoing_window(self._mng, window))
+ 
+   outgoing_window = property(_get_outgoing_window, _set_outgoing_window,
+                              doc="""
+ The outgoing tracking window for the messenger. The messenger will
+ track the remote status of this many outgoing deliveries after calling
+ send. Defaults to zero.
+ 
+ A L{Message} enters this window when you call the put() method with the
+ message.  If your outgoing window size is I{n}, and you call L{put} I{n}+1
+ times, status information will no longer be available for the
+ first message.
+ """)
+ 
+   def start(self):
+     """
+     Currently a no-op placeholder.
+     For future compatibility, do not L{send} or L{recv} messages
+     before starting the L{Messenger}.
+     """
+     self._check(pn_messenger_start(self._mng))
+ 
+   def stop(self):
+     """
+     Transitions the L{Messenger} to an inactive state. An inactive
+     L{Messenger} will not send or receive messages from its internal
+     queues. A L{Messenger} should be stopped before being discarded to
+     ensure a clean shutdown handshake occurs on any internally managed
+     connections.
+     """
+     self._check(pn_messenger_stop(self._mng))
+ 
+   @property
+   def stopped(self):
+     """
+     Returns true iff a L{Messenger} is in the stopped state.
+     This function does not block.
+     """
+     return pn_messenger_stopped(self._mng)
+ 
+   def subscribe(self, source):
+     """
+     Subscribes the L{Messenger} to messages originating from the
+     specified source. The source is an address as specified in the
+     L{Messenger} introduction with the following addition. If the
+     domain portion of the address begins with the '~' character, the
+     L{Messenger} will interpret the domain as host/port, bind to it,
+     and listen for incoming messages. For example "~0.0.0.0",
+     "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any
+     local interface and listen for incoming messages with the last
+     variant only permitting incoming SSL connections.
+ 
+     @type source: string
+     @param source: the source of messages to subscribe to
+     """
+     sub_impl = pn_messenger_subscribe(self._mng, source)
+     if not sub_impl:
+       self._check(pn_error_code(pn_messenger_error(self._mng)))
+       raise MessengerException("Cannot subscribe to %s"%source)
+     return Subscription(sub_impl)
+ 
+   def put(self, message):
+     """
+     Places the content contained in the message onto the outgoing
+     queue of the L{Messenger}. This method will never block, however
+     it will send any unblocked L{Messages<Message>} in the outgoing
+     queue immediately and leave any blocked L{Messages<Message>}
+     remaining in the outgoing queue. The L{send} call may be used to
+     block until the outgoing queue is empty. The L{outgoing} property
+     may be used to check the depth of the outgoing queue.
+ 
+     When the content in a given L{Message} object is copied to the outgoing
+     message queue, you may then modify or discard the L{Message} object
+     without having any impact on the content in the outgoing queue.
+ 
+     This method returns an outgoing tracker for the L{Message}.  The tracker
+     can be used to determine the delivery status of the L{Message}.
+ 
+     @type message: Message
+     @param message: the message to place in the outgoing queue
+     @return: a tracker
+     """
+     message._pre_encode()
+     self._check(pn_messenger_put(self._mng, message._msg))
+     return pn_messenger_outgoing_tracker(self._mng)
+ 
+   def status(self, tracker):
+     """
+     Gets the last known remote state of the delivery associated with
+     the given tracker.
+ 
+     @type tracker: tracker
+     @param tracker: the tracker whose status is to be retrieved
+ 
+     @return: one of None, PENDING, REJECTED, or ACCEPTED
+     """
+     disp = pn_messenger_status(self._mng, tracker);
+     return STATUSES.get(disp, disp)
+ 
+   def buffered(self, tracker):
+     """
+     Checks if the delivery associated with the given tracker is still
+     waiting to be sent.
+ 
+     @type tracker: tracker
+     @param tracker: the tracker whose status is to be retrieved
+ 
+     @return: true if delivery is still buffered
+     """
+     return pn_messenger_buffered(self._mng, tracker);
+ 
+   def settle(self, tracker=None):
+     """
+     Frees a L{Messenger} from tracking the status associated with a given
+     tracker. If you don't supply a tracker, all outgoing L{messages<Message>} up
+     to the most recent will be settled.
+     """
+     if tracker is None:
+       tracker = pn_messenger_outgoing_tracker(self._mng)
+       flags = PN_CUMULATIVE
+     else:
+       flags = 0
+     self._check(pn_messenger_settle(self._mng, tracker, flags))
+ 
+   def send(self, n=-1):
+     """
+     This call will block until the indicated number of L{messages<Message>}
+     have been sent, or until the operation times out.  If n is -1 this call will
+     block until all outgoing L{messages<Message>} have been sent. If n is 0 then
+     this call will send whatever it can without blocking.
+     """
+     self._check(pn_messenger_send(self._mng, n))
+ 
+   def recv(self, n=None):
+     """
+     Receives up to I{n} L{messages<Message>} into the incoming queue.  If no value
+     for I{n} is supplied, this call will receive as many L{messages<Message>} as it
+     can buffer internally.  If the L{Messenger} is in blocking mode, this
+     call will block until at least one L{Message} is available in the
+     incoming queue.
+     """
+     if n is None:
+       n = -1
+     self._check(pn_messenger_recv(self._mng, n))
+ 
+   def work(self, timeout=None):
+     """
+     Sends or receives any outstanding L{messages<Message>} queued for a L{Messenger}.
+     This will block for the indicated timeout.
+     This method may also do I/O work other than sending and receiving
+     L{messages<Message>}.  For example, closing connections after messenger.L{stop}()
+     has been called.
+     """
+     if timeout is None:
+       t = -1
+     else:
+       t = secs2millis(timeout)
+     err = pn_messenger_work(self._mng, t)
+     if (err == PN_TIMEOUT):
+       return False
+     else:
+       self._check(err)
+       return True
+ 
+   @property
+   def receiving(self):
+     return pn_messenger_receiving(self._mng)
+ 
+   def interrupt(self):
+     """
+     The L{Messenger} interface is single-threaded.
+     This is the only L{Messenger} function intended to be called
+     from outside of the L{Messenger} thread.
+     Call this from a non-messenger thread to interrupt
+     a L{Messenger} that is blocking.
+     This will cause any in-progress blocking call to throw
+     the L{Interrupt} exception.  If there is no currently blocking
+     call, then the next blocking call will be affected, even if it
+     is within the same thread that interrupt was called from.
+     """
+     self._check(pn_messenger_interrupt(self._mng))
+ 
+   def get(self, message=None):
+     """
+     Moves the message from the head of the incoming message queue into
+     the supplied message object. Any content in the message will be
+     overwritten.
+ 
+     A tracker for the incoming L{Message} is returned.  The tracker can
+     later be used to communicate your acceptance or rejection of the
+     L{Message}.
+ 
+     If None is passed in for the L{Message} object, the L{Message}
+     popped from the head of the queue is discarded.
+ 
+     @type message: Message
+     @param message: the destination message object
+     @return: a tracker
+     """
+     if message is None:
+       impl = None
+     else:
+       impl = message._msg
+     self._check(pn_messenger_get(self._mng, impl))
+     if message is not None:
+       message._post_decode()
+     return pn_messenger_incoming_tracker(self._mng)
+ 
+   def accept(self, tracker=None):
+     """
+     Signal the sender that you have acted on the L{Message}
+     pointed to by the tracker.  If no tracker is supplied,
+     then all messages that have been returned by the L{get}
+     method are accepted, except those that have already been
+     auto-settled by passing beyond your incoming window size.
+ 
+     @type tracker: tracker
+     @param tracker: a tracker as returned by get
+     """
+     if tracker is None:
+       tracker = pn_messenger_incoming_tracker(self._mng)
+       flags = PN_CUMULATIVE
+     else:
+       flags = 0
+     self._check(pn_messenger_accept(self._mng, tracker, flags))
+ 
+   def reject(self, tracker=None):
+     """
+     Rejects the L{Message} indicated by the tracker.  If no tracker
+     is supplied, all messages that have been returned by the L{get}
+     method are rejected, except those that have already been auto-settled
+     by passing beyond your outgoing window size.
+ 
+     @type tracker: tracker
+     @param tracker: a tracker as returned by get
+     """
+     if tracker is None:
+       tracker = pn_messenger_incoming_tracker(self._mng)
+       flags = PN_CUMULATIVE
+     else:
+       flags = 0
+     self._check(pn_messenger_reject(self._mng, tracker, flags))
+ 
+   @property
+   def outgoing(self):
+     """
+     The outgoing queue depth.
+     """
+     return pn_messenger_outgoing(self._mng)
+ 
+   @property
+   def incoming(self):
+     """
+     The incoming queue depth.
+     """
+     return pn_messenger_incoming(self._mng)
+ 
+   def route(self, pattern, address):
+     """
+           Adds a routing rule to a L{Messenger's<Messenger>} internal routing table.
+ 
+           The route procedure may be used to influence how a L{Messenger} will
+           internally treat a given address or class of addresses. Every call
+           to the route procedure will result in L{Messenger} appending a routing
+           rule to its internal routing table.
+ 
+           Whenever a L{Message} is presented to a L{Messenger} for delivery, it
+           will match the address of this message against the set of routing
+           rules in order. The first rule to match will be triggered, and
+           instead of routing based on the address presented in the message,
+           the L{Messenger} will route based on the address supplied in the rule.
+ 
+           The pattern matching syntax supports two types of matches, a '%'
+           will match any character except a '/', and a '*' will match any
+           character including a '/'.
+ 
+           A routing address is specified as a normal AMQP address, however it
+           may additionally use substitution variables from the pattern match
+           that triggered the rule.
+ 
+           Any message sent to "foo" will be routed to "amqp://foo.com":
+ 
+              >>> messenger.route("foo", "amqp://foo.com");
+ 
+           Any message sent to "foobar" will be routed to
+           "amqp://foo.com/bar":
+ 
+              >>> messenger.route("foobar", "amqp://foo.com/bar");
+ 
+           Any message sent to bar/<path> will be routed to the corresponding
+           path within the amqp://bar.com domain:
+ 
+              >>> messenger.route("bar/*", "amqp://bar.com/$1");
+ 
+           Route all L{messages<Message>} over TLS:
+ 
+              >>> messenger.route("amqp:*", "amqps:$1")
+ 
+           Supply credentials for foo.com:
+ 
+              >>> messenger.route("amqp://foo.com/*", "amqp://user:password@foo.com/$1");
+ 
+           Supply credentials for all domains:
+ 
+              >>> messenger.route("amqp://*", "amqp://user:password@$1");
+ 
+           Route all addresses through a single proxy while preserving the
+           original destination:
+ 
+              >>> messenger.route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
+ 
+           Route any address through a single broker:
+ 
+              >>> messenger.route("*", "amqp://user:password@broker/$1");
+     """
+     self._check(pn_messenger_route(self._mng, pattern, address))
+ 
+   def rewrite(self, pattern, address):
+     """
+     Similar to route(), except that the destination of
+     the L{Message} is determined before the message address is rewritten.
+ 
+     The outgoing address is only rewritten after routing has been
+     finalized.  If a message has an outgoing address of
+     "amqp://0.0.0.0:5678", and a rewriting rule that changes its
+     outgoing address to "foo", it will still arrive at the peer that
+     is listening on "amqp://0.0.0.0:5678", but when it arrives there,
+     the receiver will see its outgoing address as "foo".
+ 
+     The default rewrite rule removes username and password from addresses
+     before they are transmitted.
+     """
+     self._check(pn_messenger_rewrite(self._mng, pattern, address))
+ 
+   def selectable(self):
+     impl = pn_messenger_selectable(self._mng)
+     if impl:
+       fd = pn_selectable_fd(impl)
+       sel = self._selectables.get(fd, None)
+       if sel is None:
+         sel = Selectable(self, impl)
+         self._selectables[fd] = sel
+       return sel
+     else:
+       return None
+ 
+   @property
+   def deadline(self):
+     tstamp = pn_messenger_deadline(self._mng)
+     if tstamp:
+       return millis2secs(tstamp)
+     else:
+       return None
+ 
+ class Message(object):
+   """The L{Message} class is a mutable holder of message content.
+ 
+   @ivar instructions: delivery instructions for the message
+   @type instructions: dict
+   @ivar annotations: infrastructure defined message annotations
+   @type annotations: dict
+   @ivar properties: application defined message properties
+   @type properties: dict
+   @ivar body: message body
+   @type body: bytes | unicode | dict | list | int | long | float | UUID
+   """
+ 
+   DATA = PN_DATA
+   TEXT = PN_TEXT
+   AMQP = PN_AMQP
+   JSON = PN_JSON
+ 
+   DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
+ 
+   def __init__(self, **kwargs):
+     """
+     @param kwargs: Message property name/value pairs to initialise the Message
+     """
+     self._msg = pn_message()
+     self._id = Data(pn_message_id(self._msg))
+     self._correlation_id = Data(pn_message_correlation_id(self._msg))
+     self.instructions = None
+     self.annotations = None
+     self.properties = None
+     self.body = None
+     for k,v in kwargs.iteritems():
+       getattr(self, k)          # Raise exception if it's not a valid attribute.
+       setattr(self, k, v)
+ 
+   def __del__(self):
+     if hasattr(self, "_msg"):
+       pn_message_free(self._msg)
+       del self._msg
+ 
+   def _check(self, err):
+     if err < 0:
+       exc = EXCEPTIONS.get(err, MessageException)
+       raise exc("[%s]: %s" % (err, pn_error_text(pn_message_error(self._msg))))
+     else:
+       return err
+ 
+   def _pre_encode(self):
+     inst = Data(pn_message_instructions(self._msg))
+     ann = Data(pn_message_annotations(self._msg))
+     props = Data(pn_message_properties(self._msg))
+     body = Data(pn_message_body(self._msg))
+ 
+     inst.clear()
+     if self.instructions is not None:
+       inst.put_object(self.instructions)
+     ann.clear()
+     if self.annotations is not None:
+       ann.put_object(self.annotations)
+     props.clear()
+     if self.properties is not None:
+       props.put_object(self.properties)
+     body.clear()
+     if self.body is not None:
+       body.put_object(self.body)
+ 
+   def _post_decode(self):
+     inst = Data(pn_message_instructions(self._msg))
+     ann = Data(pn_message_annotations(self._msg))
+     props = Data(pn_message_properties(self._msg))
+     body = Data(pn_message_body(self._msg))
+ 
+     if inst.next():
+       self.instructions = inst.get_object()
+     else:
+       self.instructions = None
+     if ann.next():
+       self.annotations = ann.get_object()
+     else:
+       self.annotations = None
+     if props.next():
+       self.properties = props.get_object()
+     else:
+       self.properties = None
+     if body.next():
+       self.body = body.get_object()
+     else:
+       self.body = None
+ 
+   def clear(self):
+     """
+     Clears the contents of the L{Message}. All fields will be reset to
+     their default values.
+     """
+     pn_message_clear(self._msg)
+     self.instructions = None
+     self.annotations = None
+     self.properties = None
+     self.body = None
+ 
+   def _is_inferred(self):
+     return pn_message_is_inferred(self._msg)
+ 
+   def _set_inferred(self, value):
+     self._check(pn_message_set_inferred(self._msg, bool(value)))
+ 
+   inferred = property(_is_inferred, _set_inferred, doc="""
+ The inferred flag for a message indicates how the message content
+ is encoded into AMQP sections. If inferred is true then binary and
+ list values in the body of the message will be encoded as AMQP DATA
+ and AMQP SEQUENCE sections, respectively. If inferred is false,
+ then all values in the body of the message will be encoded as AMQP
+ VALUE sections regardless of their type.
+ """)
+ 
+   def _is_durable(self):
+     return pn_message_is_durable(self._msg)
+ 
+   def _set_durable(self, value):
+     self._check(pn_message_set_durable(self._msg, bool(value)))
+ 
+   durable = property(_is_durable, _set_durable,
+                      doc="""
+ The durable property indicates that the message should be held durably
+ by any intermediaries taking responsibility for the message.
+ """)
+ 
+   def _get_priority(self):
+     return pn_message_get_priority(self._msg)
+ 
+   def _set_priority(self, value):
+     self._check(pn_message_set_priority(self._msg, value))
+ 
+   priority = property(_get_priority, _set_priority,
+                       doc="""
+ The priority of the message.
+ """)
+ 
+   def _get_ttl(self):
+     return millis2secs(pn_message_get_ttl(self._msg))
+ 
+   def _set_ttl(self, value):
+     self._check(pn_message_set_ttl(self._msg, secs2millis(value)))
+ 
+   ttl = property(_get_ttl, _set_ttl,
+                  doc="""
+ The time to live of the message measured in seconds. Expired messages
+ may be dropped.
+ """)
+ 
+   def _is_first_acquirer(self):
+     return pn_message_is_first_acquirer(self._msg)
+ 
+   def _set_first_acquirer(self, value):
+     self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
+ 
+   first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
+                             doc="""
+ True iff the recipient is the first to acquire the message.
+ """)
+ 
+   def _get_delivery_count(self):
+     return pn_message_get_delivery_count(self._msg)
+ 
+   def _set_delivery_count(self, value):
+     self._check(pn_message_set_delivery_count(self._msg, value))
+ 
+   delivery_count = property(_get_delivery_count, _set_delivery_count,
+                             doc="""
+ The number of delivery attempts made for this message.
+ """)
+ 
+ 
+   def _get_id(self):
+     return self._id.get_object()
+   def _set_id(self, value):
+     if type(value) in (int, long):
+       value = ulong(value)
+     self._id.rewind()
+     self._id.put_object(value)
+   id = property(_get_id, _set_id,
+                 doc="""
+ The id of the message.
+ """)
+ 
+   def _get_user_id(self):
+     return pn_message_get_user_id(self._msg)
+ 
+   def _set_user_id(self, value):
+     self._check(pn_message_set_user_id(self._msg, value))
+ 
+   user_id = property(_get_user_id, _set_user_id,
+                      doc="""
+ The user id of the message creator.
+ """)
+ 
+   def _get_address(self):
+     return pn_message_get_address(self._msg)
+ 
+   def _set_address(self, value):
+     self._check(pn_message_set_address(self._msg, value))
+ 
+   address = property(_get_address, _set_address,
+                      doc="""
+ The address of the message.
+ """)
+ 
+   def _get_subject(self):
+     return pn_message_get_subject(self._msg)
+ 
+   def _set_subject(self, value):
+     self._check(pn_message_set_subject(self._msg, value))
+ 
+   subject = property(_get_subject, _set_subject,
+                      doc="""
+ The subject of the message.
+ """)
+ 
+   def _get_reply_to(self):
+     return pn_message_get_reply_to(self._msg)
+ 
+   def _set_reply_to(self, value):
+     self._check(pn_message_set_reply_to(self._msg, value))
+ 
+   reply_to = property(_get_reply_to, _set_reply_to,
+                       doc="""
+ The reply-to address for the message.
+ """)
+ 
+   def _get_correlation_id(self):
+     return self._correlation_id.get_object()
+   def _set_correlation_id(self, value):
+     if type(value) in (int, long):
+       value = ulong(value)
+     self._correlation_id.rewind()
+     self._correlation_id.put_object(value)
+ 
+   correlation_id = property(_get_correlation_id, _set_correlation_id,
+                             doc="""
+ The correlation-id for the message.
+ """)
+ 
+   def _get_content_type(self):
+     return pn_message_get_content_type(self._msg)
+ 
+   def _set_content_type(self, value):
+     self._check(pn_message_set_content_type(self._msg, value))
+ 
+   content_type = property(_get_content_type, _set_content_type,
+                           doc="""
+ The content-type of the message.
+ """)
+ 
+   def _get_content_encoding(self):
+     return pn_message_get_content_encoding(self._msg)
+ 
+   def _set_content_encoding(self, value):
+     self._check(pn_message_set_content_encoding(self._msg, value))
+ 
+   content_encoding = property(_get_content_encoding, _set_content_encoding,
+                               doc="""
+ The content-encoding of the message.
+ """)
+ 
+   def _get_expiry_time(self):
+     return millis2secs(pn_message_get_expiry_time(self._msg))
+ 
+   def _set_expiry_time(self, value):
+     self._check(pn_message_set_expiry_time(self._msg, secs2millis(value)))
+ 
+   expiry_time = property(_get_expiry_time, _set_expiry_time,
+                          doc="""
+ The expiry time of the message.
+ """)
+ 
+   def _get_creation_time(self):
+     return millis2secs(pn_message_get_creation_time(self._msg))
+ 
+   def _set_creation_time(self, value):
+     self._check(pn_message_set_creation_time(self._msg, secs2millis(value)))
+ 
+   creation_time = property(_get_creation_time, _set_creation_time,
+                            doc="""
+ The creation time of the message.
+ """)
+ 
+   def _get_group_id(self):
+     return pn_message_get_group_id(self._msg)
+ 
+   def _set_group_id(self, value):
+     self._check(pn_message_set_group_id(self._msg, value))
+ 
+   group_id = property(_get_group_id, _set_group_id,
+                       doc="""
+ The group id of the message.
+ """)
+ 
+   def _get_group_sequence(self):
+     return pn_message_get_group_sequence(self._msg)
+ 
+   def _set_group_sequence(self, value):
+     self._check(pn_message_set_group_sequence(self._msg, value))
+ 
+   group_sequence = property(_get_group_sequence, _set_group_sequence,
+                             doc="""
+ The sequence of the message within its group.
+ """)
+ 
+   def _get_reply_to_group_id(self):
+     return pn_message_get_reply_to_group_id(self._msg)
+ 
+   def _set_reply_to_group_id(self, value):
+     self._check(pn_message_set_reply_to_group_id(self._msg, value))
+ 
+   reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
+                                doc="""
+ The group-id for any replies.
+ """)
+ 
+   # XXX
+   def _get_format(self):
+     return pn_message_get_format(self._msg)
+ 
+   def _set_format(self, value):
+     self._check(pn_message_set_format(self._msg, value))
+ 
+   format = property(_get_format, _set_format,
+                     doc="""
+ The format of the message.
+ """)
+ 
+   def encode(self):
+     self._pre_encode()
+     sz = 16
+     while True:
+       err, data = pn_message_encode(self._msg, sz)
+       if err == PN_OVERFLOW:
+         sz *= 2
+         continue
+       else:
+         self._check(err)
+         return data
+ 
+   def decode(self, data):
+     self._check(pn_message_decode(self._msg, data, len(data)))
+     self._post_decode()
+ 
+   def load(self, data):
+     self._check(pn_message_load(self._msg, data))
+ 
+   def save(self):
+     sz = 16
+     while True:
+       err, data = pn_message_save(self._msg, sz)
+       if err == PN_OVERFLOW:
+         sz *= 2
+         continue
+       else:
+         self._check(err)
+         return data
+ 
+   def __repr2__(self):
+     props = []
+     for attr in ("inferred", "address", "reply_to", "durable", "ttl",
+                  "priority", "first_acquirer", "delivery_count", "id",
+                  "correlation_id", "user_id", "group_id", "group_sequence",
+                  "reply_to_group_id", "instructions", "annotations",
+                  "properties", "body"):
+       value = getattr(self, attr)
+       if value: props.append("%s=%r" % (attr, value))
+     return "Message(%s)" % ", ".join(props)
+ 
+   def __repr__(self):
+     tmp = pn_string(None)
+     err = pn_inspect(self._msg, tmp)
+     result = pn_string_get(tmp)
+     pn_free(tmp)
+     self._check(err)
+     return result
+ 
+ class Subscription(object):
+ 
+   def __init__(self, impl):
+     self._impl = impl
+ 
+   @property
+   def address(self):
+     return pn_subscription_address(self._impl)
+ 
+ class Selectable(object):
+ 
+   def __init__(self, messenger, impl):
+     self.messenger = messenger
+     self._impl = impl
+ 
+   def fileno(self):
+     if not self._impl: raise ValueError("selectable freed")
+     return pn_selectable_fd(self._impl)
+ 
+   @property
+   def capacity(self):
+     if not self._impl: raise ValueError("selectable freed")
+     return pn_selectable_capacity(self._impl)
+ 
+   @property
+   def pending(self):
+     if not self._impl: raise ValueError("selectable freed")
+     return pn_selectable_pending(self._impl)
+ 
+   @property
+   def deadline(self):
+     if not self._impl: raise ValueError("selectable freed")
+     tstamp = pn_selectable_deadline(self._impl)
+     if tstamp:
+       return millis2secs(tstamp)
+     else:
+       return None
+ 
+   def readable(self):
+     if not self._impl: raise ValueError("selectable freed")
+     pn_selectable_readable(self._impl)
+ 
+   def writable(self):
+     if not self._impl: raise ValueError("selectable freed")
+     pn_selectable_writable(self._impl)
+ 
+   def expired(self):
+     if not self._impl: raise ValueError("selectable freed")
+     pn_selectable_expired(self._impl)
+ 
+   def _is_registered(self):
+     if not self._impl: raise ValueError("selectable freed")
+     return pn_selectable_is_registered(self._impl)
+ 
+   def _set_registered(self, registered):
+     if not self._impl: raise ValueError("selectable freed")
+     pn_selectable_set_registered(self._impl, registered)
+ 
+   registered = property(_is_registered, _set_registered,
+                     doc="""
+ The registered property may be get/set by an I/O polling system to
+ indicate whether the fd has been registered or not.
+ """)
+ 
+   @property
+   def is_terminal(self):
+     if not self._impl: return True
+     return pn_selectable_is_terminal(self._impl)
+ 
+   def free(self):
+     if self._impl:
+       del self.messenger._selectables[self.fileno()]
+       pn_selectable_free(self._impl)
+       self._impl = None
+ 
+   def __del__(self):
+     self.free()
+ 
+ class DataException(ProtonException):
+   """
+   The DataException class is the root of the Data exception hierarchy.
+   All exceptions raised by the Data class extend this exception.
+   """
+   pass
+ 
+ class UnmappedType:
+ 
+   def __init__(self, msg):
+     self.msg = msg
+ 
+   def __repr__(self):
+     return "UnmappedType(%s)" % self.msg
+ 
+ class ulong(long):
+ 
+   def __repr__(self):
+     return "ulong(%s)" % long.__repr__(self)
+ 
+ class timestamp(long):
+ 
+   def __repr__(self):
+     return "timestamp(%s)" % long.__repr__(self)
+ 
+ class symbol(unicode):
+ 
+   def __repr__(self):
+     return "symbol(%s)" % unicode.__repr__(self)
+ 
+ class char(unicode):
+ 
+   def __repr__(self):
+     return "char(%s)" % unicode.__repr__(self)
+ 
+ class Described(object):
+ 
+   def __init__(self, descriptor, value):
+     self.descriptor = descriptor
+     self.value = value
+ 
+   def __repr__(self):
+     return "Described(%r, %r)" % (self.descriptor, self.value)
+ 
+   def __eq__(self, o):
+     if isinstance(o, Described):
+       return self.descriptor == o.descriptor and self.value == o.value
+     else:
+       return False
+ 
+ UNDESCRIBED = Constant("UNDESCRIBED")
+ 
+ class Array(object):
+ 
+   def __init__(self, descriptor, type, *elements):
+     self.descriptor = descriptor
+     self.type = type
+     self.elements = elements
+ 
+   def __repr__(self):
+     if self.elements:
+       els = ", %s"  % (", ".join(map(repr, self.elements)))
+     else:
+       els = ""
+     return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
+ 
+   def __eq__(self, o):
+     if isinstance(o, Array):
+       return self.descriptor == o.descriptor and \
+           self.type == o.type and self.elements == o.elements
+     else:
+       return False
+ 
+ class Data:
+   """
+   The L{Data} class provides an interface for decoding, extracting,
+   creating, and encoding arbitrary AMQP data. A L{Data} object
+   contains a tree of AMQP values. Leaf nodes in this tree correspond
+   to scalars in the AMQP type system such as L{ints<INT>} or
+   L{strings<STRING>}. Non-leaf nodes in this tree correspond to
+   compound values in the AMQP type system such as L{lists<LIST>},
+   L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
+   The root node of the tree is the L{Data} object itself and can have
+   an arbitrary number of children.
+ 
+   A L{Data} object maintains the notion of the current sibling node
+   and a current parent node. Siblings are ordered within their parent.
+   Values are accessed and/or added by using the L{next}, L{prev},
+   L{enter}, and L{exit} methods to navigate to the desired location in
+   the tree and using the supplied variety of put_*/get_* methods to
+   access or add a value of the desired type.
+ 
+   The put_* methods will always add a value I{after} the current node
+   in the tree. If the current node has a next sibling the put_* method
+   will overwrite the value on this node. If there is no current node
+   or the current node has no next sibling then one will be added. The
+   put_* methods always set the added/modified node to the current
+   node. The get_* methods read the value of the current node and do
+   not change which node is current.
+ 
+   The following types of scalar values are supported:
+ 
+    - L{NULL}
+    - L{BOOL}
+    - L{UBYTE}
+    - L{USHORT}
+    - L{SHORT}
+    - L{UINT}
+    - L{INT}
+    - L{ULONG}
+    - L{LONG}
+    - L{FLOAT}
+    - L{DOUBLE}
+    - L{BINARY}
+    - L{STRING}
+    - L{SYMBOL}
+ 
+   The following types of compound values are supported:
+ 
+    - L{DESCRIBED}
+    - L{ARRAY}
+    - L{LIST}
+    - L{MAP}
+   """
+ 
+   NULL = PN_NULL; "A null value."
+   BOOL = PN_BOOL; "A boolean value."
+   UBYTE = PN_UBYTE; "An unsigned byte value."
+   BYTE = PN_BYTE; "A signed byte value."
+   USHORT = PN_USHORT; "An unsigned short value."
+   SHORT = PN_SHORT; "A short value."
+   UINT = PN_UINT; "An unsigned int value."
+   INT = PN_INT; "A signed int value."
+   CHAR = PN_CHAR; "A character value."
+   ULONG = PN_ULONG; "An unsigned long value."
+   LONG = PN_LONG; "A signed long value."
+   TIMESTAMP = PN_TIMESTAMP; "A timestamp value."
+   FLOAT = PN_FLOAT; "A float value."
+   DOUBLE = PN_DOUBLE; "A double value."
+   DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value."
+   DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value."
+   DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value."
+   UUID = PN_UUID; "A UUID value."
+   BINARY = PN_BINARY; "A binary string."
+   STRING = PN_STRING; "A unicode string."
+   SYMBOL = PN_SYMBOL; "A symbolic string."
+   DESCRIBED = PN_DESCRIBED; "A described value."
+   ARRAY = PN_ARRAY; "An array value."
+   LIST = PN_LIST; "A list value."
+   MAP = PN_MAP; "A map value."
+ 
+   type_names = {
+     NULL: "null",
+     BOOL: "bool",
+     BYTE: "byte",
+     UBYTE: "ubyte",
+     SHORT: "short",
+     USHORT: "ushort",
+     INT: "int",
+     UINT: "uint",
+     CHAR: "char",
+     LONG: "long",
+     ULONG: "ulong",
+     TIMESTAMP: "timestamp",
+     FLOAT: "float",
+     DOUBLE: "double",
+     DECIMAL32: "decimal32",
+     DECIMAL64: "decimal64",
+     DECIMAL128: "decimal128",
+     UUID: "uuid",
+     BINARY: "binary",
+     STRING: "string",
+     SYMBOL: "symbol",
+     DESCRIBED: "described",
+     ARRAY: "array",
+     LIST: "list",
+     MAP: "map"
+     }
+ 
+   @classmethod
+   def type_name(type): return Data.type_names[type]
+ 
+   def __init__(self, capacity=16):
+     if type(capacity) in (int, long):
+       self._data = pn_data(capacity)
+       self._free = True
+     else:
+       self._data = capacity
+       self._free = False
+ 
+   def __del__(self):
+     if self._free and hasattr(self, "_data"):
+       pn_data_free(self._data)
+       del self._data
+ 
+   def _check(self, err):
+     if err < 0:
+       exc = EXCEPTIONS.get(err, DataException)
+       raise exc("[%s]: %s" % (err, pn_error_text(pn_data_error(self._data))))
+     else:
+       return err
+ 
+   def clear(self):
+     """
+     Clears the data object.
+     """
+     pn_data_clear(self._data)
+ 
+   def rewind(self):
+     """
+     Clears current node and sets the parent to the root node.  Clearing the
+     current node sets it _before_ the first node, calling next() will advance to
+     the first node.
+     """
+     assert self._data is not None
+     pn_data_rewind(self._data)
+ 
+   def next(self):
+     """
+     Advances the current node to its next sibling and returns its
+     type. If there is no next sibling the current node remains
+     unchanged and None is returned.
+     """
+     found = pn_data_next(self._data)
+     if found:
+       return self.type()
+     else:
+       return None
+ 
+   def prev(self):
+     """
+     Advances the current node to its previous sibling and returns its
+     type. If there is no previous sibling the current node remains
+     unchanged and None is returned.
+     """
+     found = pn_data_prev(self._data)
+     if found:
+       return self.type()
+     else:
+       return None
+ 
+   def enter(self):
+     """
+     Sets the parent node to the current node and clears the current node.
+     Clearing the current node sets it _before_ the first child,
+     call next() advances to the first child.
+     """
+     return pn_data_enter(self._data)
+ 
+   def exit(self):
+     """
+     Sets the current node to the parent node and the parent node to
+     its own parent.
+     """
+     return pn_data_exit(self._data)
+ 
+   def lookup(self, name):
+     return pn_data_lookup(self._data, name)
+ 
+   def narrow(self):
+     pn_data_narrow(self._data)
+ 
+   def widen(self):
+     pn_data_widen(self._data)
+ 
+   def type(self):
+     """
+     Returns the type of the current node.
+     """
+     dtype = pn_data_type(self._data)
+     if dtype == -1:
+       return None
+     else:
+       return dtype
+ 
+   def encode(self):
+     """
+     Returns a representation of the data encoded in AMQP format.
+     """
+     size = 1024
+     while True:
+       cd, enc = pn_data_encode(self._data, size)
+       if cd == PN_OVERFLOW:
+         size *= 2
+       elif cd >= 0:
+         return enc
+       else:
+         self._check(cd)
+ 
+   def decode(self, encoded):
+     """
+     Decodes the first value from supplied AMQP data and returns the
+     number of bytes consumed.
+ 
+     @type encoded: binary
+     @param encoded: AMQP encoded binary data
+     """
+     return self._check(pn_data_decode(self._data, encoded))
+ 
+   def put_list(self):
+     """
+     Puts a list value. Elements may be filled by entering the list
+     node and putting element values.
+ 
+       >>> data = Data()
+       >>> data.put_list()
+       >>> data.enter()
+       >>> data.put_int(1)
+       >>> data.put_int(2)
+       >>> data.put_int(3)
+       >>> data.exit()
+     """
+     self._check(pn_data_put_list(self._data))
+ 
+   def put_map(self):
+     """
+     Puts a map value. Elements may be filled by entering the map node
+     and putting alternating key value pairs.
+ 
+       >>> data = Data()
+       >>> data.put_map()
+       >>> data.enter()
+       >>> data.put_string("key")
+       >>> data.put_string("value")
+       >>> data.exit()
+     """
+     self._check(pn_data_put_map(self._data))
+ 
+   def put_array(self, described, element_type):
+     """
+     Puts an array value. Elements may be filled by entering the array
+     node and putting the element values. The values must all be of the
+     specified array element type. If an array is described then the
+     first child value of the array is the descriptor and may be of any
+     type.
+ 
+       >>> data = Data()
+       >>>
+       >>> data.put_array(False, Data.INT)
+       >>> data.enter()
+       >>> data.put_int(1)
+       >>> data.put_int(2)
+       >>> data.put_int(3)
+       >>> data.exit()
+       >>>
+       >>> data.put_array(True, Data.DOUBLE)
+       >>> data.enter()
+       >>> data.put_symbol("array-descriptor")
+       >>> data.put_double(1.1)
+       >>> data.put_double(1.2)
+       >>> data.put_double(1.3)
+       >>> data.exit()
+ 
+     @type described: bool
+     @param described: specifies whether the array is described
+     @type element_type: int
+     @param element_type: the type of the array elements
+     """
+     self._check(pn_data_put_array(self._data, described, element_type))
+ 
+   def put_described(self):
+     """
+     Puts a described value. A described node has two children, the
+     descriptor and the value. These are specified by entering the node
+     and putting the desired values.
+ 
+       >>> data = Data()
+       >>> data.put_described()
+       >>> data.enter()
+       >>> data.put_symbol("value-descriptor")
+       >>> data.put_string("the value")
+       >>> data.exit()
+     """
+     self._check(pn_data_put_described(self._data))
+ 
+   def put_null(self):
+     """
+     Puts a null value.
+     """
+     self._check(pn_data_put_null(self._data))
+ 
+   def put_bool(self, b):
+     """
+     Puts a boolean value.
+ 
+     @param b: a boolean value
+     """
+     self._check(pn_data_put_bool(self._data, b))
+ 
+   def put_ubyte(self, ub):
+     """
+     Puts an unsigned byte value.
+ 
+     @param ub: an integral value
+     """
+     self._check(pn_data_put_ubyte(self._data, ub))
+ 
+   def put_byte(self, b):
+     """
+     Puts a signed byte value.
+ 
+     @param b: an integral value
+     """
+     self._check(pn_data_put_byte(self._data, b))
+ 
+   def put_ushort(self, us):
+     """
+     Puts an unsigned short value.
+ 
+     @param us: an integral value.
+     """
+     self._check(pn_data_put_ushort(self._data, us))
+ 
+   def put_short(self, s):
+     """
+     Puts a signed short value.
+ 
+     @param s: an integral value
+     """
+     self._check(pn_data_put_short(self._data, s))
+ 
+   def put_uint(self, ui):
+     """
+     Puts an unsigned int value.
+ 
+     @param ui: an integral value
+     """
+     self._check(pn_data_put_uint(self._data, ui))
+ 
+   def put_int(self, i):
+     """
+     Puts a signed int value.
+ 
+     @param i: an integral value
+     """
+     self._check(pn_data_put_int(self._data, i))
+ 
+   def put_char(self, c):
+     """
+     Puts a char value.
+ 
+     @param c: a single character
+     """
+     self._check(pn_data_put_char(self._data, ord(c)))
+ 
+   def put_ulong(self, ul):
+     """
+     Puts an unsigned long value.
+ 
+     @param ul: an integral value
+     """
+     self._check(pn_data_put_ulong(self._data, ul))
+ 
+   def put_long(self, l):
+     """
+     Puts a signed long value.
+ 
+     @param l: an integral value
+     """
+     self._check(pn_data_put_long(self._data, l))
+ 
+   def put_timestamp(self, t):
+     """
+     Puts a timestamp value.
+ 
+     @param t: an integral value
+     """
+     self._check(pn_data_put_timestamp(self._data, t))
+ 
+   def put_float(self, f):
+     """
+     Puts a float value.
+ 
+     @param f: a floating point value
+     """
+     self._check(pn_data_put_float(self._data, f))
+ 
+   def put_double(self, d):
+     """
+     Puts a double value.
+ 
+     @param d: a floating point value.
+     """
+     self._check(pn_data_put_double(self._data, d))
+ 
+   def put_decimal32(self, d):
+     """
+     Puts a decimal32 value.
+ 
+     @param d: a decimal32 value
+     """
+     self._check(pn_data_put_decimal32(self._data, d))
+ 
+   def put_decimal64(self, d):
+     """
+     Puts a decimal64 value.
+ 
+     @param d: a decimal64 value
+     """
+     self._check(pn_data_put_decimal64(self._data, d))
+ 
+   def put_decimal128(self, d):
+     """
+     Puts a decimal128 value.
+ 
+     @param d: a decimal128 value
+     """
+     self._check(pn_data_put_decimal128(self._data, d))
+ 
+   def put_uuid(self, u):
+     """
+     Puts a UUID value.
+ 
+     @param u: a uuid value
+     """
+     self._check(pn_data_put_uuid(self._data, u.bytes))
+ 
+   def put_binary(self, b):
+     """
+     Puts a binary value.
+ 
+     @type b: binary
+     @param b: a binary value
+     """
+     self._check(pn_data_put_binary(self._data, b))
+ 
+   def put_string(self, s):
+     """
+     Puts a unicode value.
+ 
+     @type s: unicode
+     @param s: a unicode value
+     """
+     self._check(pn_data_put_string(self._data, s.encode("utf8")))
+ 
+   def put_symbol(self, s):
+     """
+     Puts a symbolic value.
+ 
+     @type s: string
+     @param s: the symbol name
+     """
+     self._check(pn_data_put_symbol(self._data, s))
+ 
+   def get_list(self):
+     """
+     If the current node is a list, return the number of elements,
+     otherwise return zero. List elements can be accessed by entering
+     the list.
+ 
+       >>> count = data.get_list()
+       >>> data.enter()
+       >>> for i in range(count):
+       ...   type = data.next()
+       ...   if type == Data.STRING:
+       ...     print data.get_string()
+       ...   elif type == ...:
+       ...     ...
+       >>> data.exit()
+     """
+     return pn_data_get_list(self._data)
+ 
+   def get_map(self):
+     """
+     If the current node is a map, return the number of child elements,
+     otherwise return zero. Key value pairs can be accessed by entering
+     the map.
+ 
+       >>> count = data.get_map()
+       >>> data.enter()
+       >>> for i in range(count/2):
+       ...   type = data.next()
+       ...   if type == Data.STRING:
+       ...     print data.get_string()
+       ...   elif type == ...:
+       ...     ...
+       >>> data.exit()
+     """
+     return pn_data_get_map(self._data)
+ 
+   def get_array(self):
+     """
+     If the current node is an array, return a tuple of the element
+     count, a boolean indicating whether the array is described, and
+     the type of each element, otherwise return (0, False, None). Array
+     data can be accessed by entering the array.
+ 
+       >>> # read an array of strings with a symbolic descriptor
+       >>> count, described, type = data.get_array()
+       >>> data.enter()
+       >>> data.next()
+       >>> print "Descriptor:", data.get_symbol()
+       >>> for i in range(count):
+       ...    data.next()
+       ...    print "Element:", data.get_string()
+       >>> data.exit()
+     """
+     count = pn_data_get_array(self._data)
+     described = pn_data_is_array_described(self._data)
+     type = pn_data_get_array_type(self._data)
+     if type == -1:
+       type = None
+     return count, described, type
+ 
+   def is_described(self):
+     """
+     Checks if the current node is a described value. The descriptor
+     and value may be accessed by entering the described value.
+ 
+       >>> # read a symbolically described string
+       >>> assert data.is_described() # will error if the current node is not described
+       >>> data.enter()
+       >>> print data.get_symbol()
+       >>> print data.get_string()
+       >>> data.exit()
+     """
+     return pn_data_is_described(self._data)
+ 
+   def is_null(self):
+     """
+     Checks if the current node is a null.
+     """
+     return pn_data_is_null(self._data)
+ 
+   def get_bool(self):
+     """
+     If the current node is a boolean, returns its value, returns False
+     otherwise.
+     """
+     return pn_data_get_bool(self._data)
+ 
+   def get_ubyte(self):
+     """
+     If the current node is an unsigned byte, returns its value,
+     returns 0 otherwise.
+     """
+     return pn_data_get_ubyte(self._data)
+ 
+   def get_byte(self):
+     """
+     If the current node is a signed byte, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_byte(self._data)
+ 
+   def get_ushort(self):
+     """
+     If the current node is an unsigned short, returns its value,
+     returns 0 otherwise.
+     """
+     return pn_data_get_ushort(self._data)
+ 
+   def get_short(self):
+     """
+     If the current node is a signed short, returns its value, returns
+     0 otherwise.
+     """
+     return pn_data_get_short(self._data)
+ 
+   def get_uint(self):
+     """
+     If the current node is an unsigned int, returns its value, returns
+     0 otherwise.
+     """
+     return pn_data_get_uint(self._data)
+ 
+   def get_int(self):
+     """
+     If the current node is a signed int, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_int(self._data)
+ 
+   def get_char(self):
+     """
+     If the current node is a char, returns its value, returns 0
+     otherwise.
+     """
+     return char(unichr(pn_data_get_char(self._data)))
+ 
+   def get_ulong(self):
+     """
+     If the current node is an unsigned long, returns its value,
+     returns 0 otherwise.
+     """
+     return ulong(pn_data_get_ulong(self._data))
+ 
+   def get_long(self):
+     """
+     If the current node is an signed long, returns its value, returns
+     0 otherwise.
+     """
+     return pn_data_get_long(self._data)
+ 
+   def get_timestamp(self):
+     """
+     If the current node is a timestamp, returns its value, returns 0
+     otherwise.
+     """
+     return timestamp(pn_data_get_timestamp(self._data))
+ 
+   def get_float(self):
+     """
+     If the current node is a float, returns its value, raises 0
+     otherwise.
+     """
+     return pn_data_get_float(self._data)
+ 
+   def get_double(self):
+     """
+     If the current node is a double, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_double(self._data)
+ 
+   # XXX: need to convert
+   def get_decimal32(self):
+     """
+     If the current node is a decimal32, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_decimal32(self._data)
+ 
+   # XXX: need to convert
+   def get_decimal64(self):
+     """
+     If the current node is a decimal64, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_decimal64(self._data)
+ 
+   # XXX: need to convert
+   def get_decimal128(self):
+     """
+     If the current node is a decimal128, returns its value, returns 0
+     otherwise.
+     """
+     return pn_data_get_decimal128(self._data)
+ 
+   def get_uuid(self):
+     """
+     If the current node is a UUID, returns its value, returns None
+     otherwise.
+     """
+     if pn_data_type(self._data) == Data.UUID:
+       return uuid.UUID(bytes=pn_data_get_uuid(self._data))
+     else:
+       return None
+ 
+   def get_binary(self):
+     """
+     If the current node is binary, returns its value, returns ""
+     otherwise.
+     """
+     return pn_data_get_binary(self._data)
+ 
+   def get_string(self):
+     """
+     If the current node is a string, returns its value, returns ""
+     otherwise.
+     """
+     return pn_data_get_string(self._data).decode("utf8")
+ 
+   def get_symbol(self):
+     """
+     If the current node is a symbol, returns its value, returns ""
+     otherwise.
+     """
+     return symbol(pn_data_get_symbol(self._data))
+ 
+   def copy(self, src):
+     self._check(pn_data_copy(self._data, src._data))
+ 
+   def format(self):
+     sz = 16
+     while True:
+       err, result = pn_data_format(self._data, sz)
+       if err == PN_OVERFLOW:
+         sz *= 2
+         continue
+       else:
+         self._check(err)
+         return result
+ 
+   def dump(self):
+     pn_data_dump(self._data)
+ 
+   def put_dict(self, d):
+     self.put_map()
+     self.enter()
+     try:
+       for k, v in d.items():
+         self.put_object(k)
+         self.put_object(v)
+     finally:
+       self.exit()
+ 
+   def get_dict(self):
+     if self.enter():
+       try:
+         result = {}
+         while self.next():
+           k = self.get_object()
+           if self.next():
+             v = self.get_object()
+           else:
+             v = None
+           result[k] = v
+       finally:
+         self.exit()
+       return result
+ 
+   def put_sequence(self, s):
+     self.put_list()
+     self.enter()
+     try:
+       for o in s:
+         self.put_object(o)
+     finally:
+       self.exit()
+ 
+   def get_sequence(self):
+     if self.enter():
+       try:
+         result = []
+         while self.next():
+           result.append(self.get_object())
+       finally:
+         self.exit()
+       return result
+ 
+   def get_py_described(self):
+     if self.enter():
+       try:
+         self.next()
+         descriptor = self.get_object()
+         self.next()
+         value = self.get_object()
+       finally:
+         self.exit()
+       return Described(descriptor, value)
+ 
+   def put_py_described(self, d):
+     self.put_described()
+     self.enter()
+     try:
+       self.put_object(d.descriptor)
+       self.put_object(d.value)
+     finally:
+       self.exit()
+ 
+   def get_py_array(self):
+     """
+     If the current node is an array, return an Array object
+     representing the array and its contents. Otherwise return None.
+     This is a convenience wrapper around get_array, enter, etc.
+     """
+ 
+     count, described, type = self.get_array()
+     if type is None: return None
+     if self.enter():
+       try:
+         if described:
+           self.next()
+           descriptor = self.get_object()
+         else:
+           descriptor = UNDESCRIBED
+         elements = []
+         while self.next():
+           elements.append(self.get_object())
+       finally:
+         self.exit()
+       return Array(descriptor, type, *elements)
+ 
+   def put_py_array(self, a):
+     described = a.descriptor != UNDESCRIBED
+     self.put_array(described, a.type)
+     self.enter()
+     try:
+       if described:
+         self.put_object(a.descriptor)
+       for e in a.elements:
+         self.put_object(e)
+     finally:
+       self.exit()
+ 
+   put_mappings = {
+     None.__class__: lambda s, _: s.put_null(),
+     bool: put_bool,
+     dict: put_dict,
+     list: put_sequence,
+     tuple: put_sequence,
+     unicode: put_string,
+     bytes: put_binary,
+     symbol: put_symbol,
+     int: put_long,
+     char: put_char,
+     long: put_long,
+     ulong: put_ulong,
+     timestamp: put_timestamp,
+     float: put_double,
+     uuid.UUID: put_uuid,
+     Described: put_py_described,
+     Array: put_py_array
+     }
+   get_mappings = {
+     NULL: lambda s: None,
+     BOOL: get_bool,
+     BYTE: get_byte,
+     UBYTE: get_ubyte,
+     SHORT: get_short,
+     USHORT: get_ushort,
+     INT: get_int,
+     UINT: get_uint,
+     CHAR: get_char,
+     LONG: get_long,
+     ULONG: get_ulong,
+     TIMESTAMP: get_timestamp,
+     FLOAT: get_float,
+     DOUBLE: get_double,
+     DECIMAL32: get_decimal32,
+     DECIMAL64: get_decimal64,
+     DECIMAL128: get_decimal128,
+     UUID: get_uuid,
+     BINARY: get_binary,
+     STRING: get_string,
+     SYMBOL: get_symbol,
+     DESCRIBED: get_py_described,
+     ARRAY: get_py_array,
+     LIST: get_sequence,
+     MAP: get_dict
+     }
+ 
+ 
+   def put_object(self, obj):
+     putter = self.put_mappings[obj.__class__]
+     putter(self, obj)
+ 
+   def get_object(self):
+     type = self.type()
+     if type is None: return None
+     getter = self.get_mappings.get(type)
+     if getter:
+       return getter(self)
+     else:
+       return UnmappedType(str(type))
+ 
+ class ConnectionException(ProtonException):
+   pass
+ 
+ class Endpoint(object):
+ 
+   LOCAL_UNINIT = PN_LOCAL_UNINIT
+   REMOTE_UNINIT = PN_REMOTE_UNINIT
+   LOCAL_ACTIVE = PN_LOCAL_ACTIVE
+   REMOTE_ACTIVE = PN_REMOTE_ACTIVE
+   LOCAL_CLOSED = PN_LOCAL_CLOSED
+   REMOTE_CLOSED  = PN_REMOTE_CLOSED
+ 
+   def __init__(self):
+     self.condition = None
+     self._release_invoked = False
+ 
+   def _release(self):
+     """Release the underlying C Engine resource."""
+     if not self._release_invoked:
+       for c in self._children:
+         c._release()
+       self._free_resource()
+       self.connection._releasing(self)
+       self._release_invoked = True
+ 
+   def _update_cond(self):
+     obj2cond(self.condition, self._get_cond_impl())
+ 
+   @property
+   def remote_condition(self):
+     return cond2obj(self._get_remote_cond_impl())
+ 
+   # the following must be provided by subclasses
+   def _get_cond_impl(self):
+       assert False, "Subclass must override this!"
+ 
+   def _get_remote_cond_impl(self):
+       assert False, "Subclass must override this!"
+ 
+ class Condition:
+ 
+   def __init__(self, name, description=None, info=None):
+     self.name = name
+     self.description = description
+     self.info = info
+ 
+   def __repr__(self):
+     return "Condition(%s)" % ", ".join([repr(x) for x in
+                                         (self.name, self.description, self.info)
+                                         if x])
+ 
+   def __eq__(self, o):
+     if not isinstance(o, Condition): return False
+     return self.name == o.name and \
+         self.description == o.description and \
+         self.info == o.info
+ 
+ def obj2cond(obj, cond):
+   pn_condition_clear(cond)
+   if obj:
+     pn_condition_set_name(cond, str(obj.name))
+     pn_condition_set_description(cond, obj.description)
+     info = Data(pn_condition_info(cond))
+     if obj.info:
+       info.put_object(obj.info)
+ 
+ def cond2obj(cond):
+   if pn_condition_is_set(cond):
+     return Condition(pn_condition_get_name(cond),
+                      pn_condition_get_description(cond),
+                      dat2obj(pn_condition_info(cond)))
+   else:
+     return None
+ 
+ def dat2obj(dimpl):
+   if dimpl:
+     d = Data(dimpl)
+     d.rewind()
+     d.next()
+     obj = d.get_object()
+     d.rewind()
+     return obj
+ 
+ def obj2dat(obj, dimpl):
+   if obj is not None:
+     d = Data(dimpl)
+     d.put_object(obj)
+ 
+ def secs2millis(secs):
+   return long(secs*1000)
+ 
+ def millis2secs(millis):
+   return float(millis)/1000.0
+ 
+ class Connection(Endpoint):
+ 
+   @staticmethod
+   def _wrap_connection(c_conn):
+     """Maintain only a single instance of this class for each Connection
+     object that exists in the the C Engine.  This is done by storing a (weak)
+     reference to the python instance in the context field of the C object.
+     """
+     if not c_conn: return None
+     py_conn = pn_void2py(pn_connection_get_context(c_conn))
+     if py_conn: return py_conn
+     wrapper = Connection(_conn=c_conn)
+     return wrapper
+ 
+   def __init__(self, _conn=None):
+     Endpoint.__init__(self)
+     if _conn:
+       self._conn = _conn
+     else:
+       self._conn = pn_connection()
+     pn_connection_set_context(self._conn, pn_py2void(self))
+     self.offered_capabilities = None
+     self.desired_capabilities = None
+     self.properties = None
+     self._sessions = set()
+ 
+   def __del__(self):
+     if hasattr(self, "_conn") and self._conn:
+       self._release()
+ 
+   def free(self):
+     self._release()
+ 
+   @property
+   def _children(self):
+     return self._sessions
+ 
+   @property
+   def connection(self):
+     return self
+ 
+   def _free_resource(self):
+     pn_connection_free(self._conn)
+ 
+   def _released(self):
+     self._conn = None
+ 
+   def _releasing(self, child):
+     coll = getattr(self, "_collector", None)
+     if coll: coll = coll()
+     if coll:
+       coll._contexts.add(child)
+     else:
+       child._released()
+ 
+   def _check(self, err):
+     if err < 0:
+       exc = EXCEPTIONS.get(err, ConnectionException)
+       raise exc("[%s]: %s" % (err, pn_connection_error(self._conn)))
+     else:
+       return err
+ 
+   def _get_cond_impl(self):
+     return pn_connection_condition(self._conn)
+ 
+   def _get_remote_cond_impl(self):
+     return pn_connection_remote_condition(self._conn)
+ 
+   def collect(self, collector):
+     if collector is None:
+       pn_connection_collect(self._conn, None)
+     else:
+       pn_connection_collect(self._conn, collector._impl)
+     self._collector = weakref.ref(collector)
+ 
+   def _get_container(self):
+     return pn_connection_get_container(self._conn)
+   def _set_container(self, name):
+     return pn_connection_set_container(self._conn, name)
+ 
+   container = property(_get_container, _set_container)
+ 
+   def _get_hostname(self):
+     return pn_connection_get_hostname(self._conn)
+   def _set_hostname(self, name):
+     return pn_connection_set_hostname(self._conn, name)
+ 
+   hostname = property(_get_hostname, _set_hostname)
+ 
+   @property
+   def remote_container(self):
+     return pn_connection_remote_container(self._conn)
+ 
+   @property
+   def remote_hostname(self):
+     return pn_connection_remote_hostname(self._conn)
+ 
+   @property
+   def remote_offered_capabilities(self):
+     return dat2obj(pn_connection_remote_offered_capabilities(self._conn))
+ 
+   @property
+   def remote_desired_capabilities(self):
+     return dat2obj(pn_connection_remote_desired_capabilities(self._conn))
+ 
+   @property
+   def remote_properties(self):
+     return dat2obj(pn_connection_remote_properties(self._conn))
+ 
+   def open(self):
+     obj2dat(self.offered_capabilities,
+             pn_connection_offered_capabilities(self._conn))
+     obj2dat(self.desired_capabilities,
+             pn_connection_desired_capabilities(self._conn))
+     obj2dat(self.properties, pn_connection_properties(self._conn))
+     pn_connection_open(self._conn)
+ 
+   def close(self):
+     self._update_cond()
+     pn_connection_close(self._conn)
+ 
+   @property
+   def state(self):
+     return pn_connection_state(self._conn)
+ 
+   def session(self):
+     return Session._wrap_session(pn_session(self._conn))
+ 
+   def session_head(self, mask):
+     return Session._wrap_session(pn_session_head(self._conn, mask))
+ 
+   def link_head(self, mask):
+     return Link._wrap_link(pn_link_head(self._conn, mask))
+ 
+   @property
+   def work_head(self):
+     return Delivery._wrap_delivery(pn_work_head(self._conn))
+ 
+   @property
+   def error(self):
+     return pn_error_code(pn_connection_error(self._conn))
+ 
+ class SessionException(ProtonException):
+   pass
+ 
+ class Session(Endpoint):
+ 
+   @staticmethod
+   def _wrap_session(c_ssn):
+     """Maintain only a single instance of this class for each Session object that
+     exists in the C Engine.
+     """
+     if c_ssn is None: return None
+     py_ssn = pn_void2py(pn_session_get_context(c_ssn))
+     if py_ssn: return py_ssn
+     wrapper = Session(c_ssn)
+     return wrapper
+ 
+   def __init__(self, ssn):
+     Endpoint.__init__(self)
+     self._ssn = ssn
+     pn_session_set_context(self._ssn, pn_py2void(self))
+     self._links = set()
+     self.connection._sessions.add(self)
+ 
+   @property
+   def _children(self):
+     return self._links
+ 
+   def _free_resource(self):
+     pn_session_free(self._ssn)
+ 
+   def _released(self):
+     self._ssn = None
+ 
+   def free(self):
+     """Release the Session, freeing its resources.
+ 
+     Call this when you no longer need the session.  This will allow the
+     session's resources to be reclaimed.  Once called, you should no longer
+     reference the session.
+ 
+     """
+     self.connection._sessions.remove(self)
+     self._release()
+ 
+   def _get_cond_impl(self):
+     return pn_session_condition(self._ssn)
+ 
+   def _get_remote_cond_impl(self):
+     return pn_session_remote_condition(self._ssn)
+ 
+   def _get_incoming_capacity(self):
+     return pn_session_get_incoming_capacity(self._ssn)
+ 
+   def _set_incoming_capacity(self, capacity):
+     pn_session_set_incoming_capacity(self._ssn, capacity)
+ 
+   incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity)
+ 
+   @property
+   def outgoing_bytes(self):
+     return pn_session_outgoing_bytes(self._ssn)
+ 
+   @property
+   def incoming_bytes(self):
+     return pn_session_incoming_bytes(self._ssn)
+ 
+   def open(self):
+     pn_session_open(self._ssn)
+ 
+   def close(self):
+     self._update_cond()
+     pn_session_close(self._ssn)
+ 
+   def next(self, mask):
+     return Session._wrap_session(pn_session_next(self._ssn, mask))
+ 
+   @property
+   def state(self):
+     return pn_session_state(self._ssn)
+ 
+   @property
+   def connection(self):
+     return Connection._wrap_connection(pn_session_connection(self._ssn))
+ 
+   def sender(self, name):
+     return Link._wrap_link(pn_sender(self._ssn, name))
+ 
+   def receiver(self, name):
+     return Link._wrap_link(pn_receiver(self._ssn, name))
+ 
+ class LinkException(ProtonException):
+   pass
+ 
+ class Link(Endpoint):
+ 
+   SND_UNSETTLED = PN_SND_UNSETTLED
+   SND_SETTLED = PN_SND_SETTLED
+   SND_MIXED = PN_SND_MIXED
+ 
+   RCV_FIRST = PN_RCV_FIRST
+   RCV_SECOND = PN_RCV_SECOND
+ 
+   @staticmethod
+   def _wrap_link(c_link):
+     """Maintain only a single instance of this class for each Session object that
+     exists in the C Engine.
+     """
+     if c_link is None: return None
+     py_link = pn_void2py(pn_link_get_context(c_link))
+     if py_link: return py_link
+     if pn_link_is_sender(c_link):
+       wrapper = Sender(c_link)
+     else:
+       wrapper = Receiver(c_link)
+     return wrapper
+ 
+   def __init__(self, c_link):
+     Endpoint.__init__(self)
+     self._link = c_link
+     pn_link_set_context(self._link, pn_py2void(self))
+     self._deliveries = set()
+     self.session._links.add(self)
+ 
+   @property
+   def _children(self):
+     return self._deliveries
+ 
+   def _free_resource(self):
+     pn_link_free(self._link)
+ 
+   def _released(self):
+     self._link = None
+ 
+   def free(self):
+     """Release the Link, freeing its resources"""
+     self.session._links.remove(self)
+     self._release()
+ 
+   def _check(self, err):
+     if err < 0:
+       exc = EXCEPTIONS.get(err, LinkException)
+       raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
+     else:
+       return err
+ 
+   def _get_cond_impl(self):
+     return pn_link_condition(self._link)
+ 
+   def _get_remote_cond_impl(self):
+     return pn_link_remote_condition(self._link)
+ 
+   def open(self):
+     pn_link_open(self._link)
+ 
+   def close(self):
+     self._update_cond()
+     pn_link_close(self._link)
+ 
+   @property
+   def state(self):
+     return pn_link_state(self._link)
+ 
+   @property
+   def source(self):
+     return Terminus(pn_link_source(self._link))
+ 
+   @property
+   def target(self):
+     return Terminus(pn_link_target(self._link))
+ 
+   @property
+   def remote_source(self):
+     return Terminus(pn_link_remote_source(self._link))
+   @property
+   def remote_target(self):
+     return Terminus(pn_link_remote_target(self._link))
+ 
+   @property
+   def session(self):
+     return Session._wrap_session(pn_link_session(self._link))
+ 
+   @property
+   def connection(self):
+     return self.session.connection
+ 
+   def delivery(self, tag):
+     return Delivery._wrap_delivery(pn_delivery(self._link, tag))
+ 
+   @property
+   def current(self):
+     return Delivery._wrap_delivery(pn_link_current(self._link))
+ 
+   def advance(self):
+     return pn_link_advance(self._link)
+ 
+   @property
+   def unsettled(self):
+     return pn_link_unsettled(self._link)
+ 
+   @property
+   def credit(self):
+     return pn_link_credit(self._link)
+ 
+   @property
+   def available(self):
+     return pn_link_available(self._link)
+ 
+   @property
+   def queued(self):
+     return pn_link_queued(self._link)
+ 
+   def next(self, mask):
+     return Link._wrap_link(pn_link_next(self._link, mask))
+ 
+   @property
+   def name(self):
+       return pn_link_name(self._link)
+ 
+   @property
+   def is_sender(self):
+     return pn_link_is_sender(self._link)
+ 
+   @property
+   def is_receiver(self):
+     return pn_link_is_receiver(self._link)
+ 
+   @property
+   def remote_snd_settle_mode(self):
+     return pn_link_remote_snd_settle_mode(self._link)
+ 
+   @property
+   def remote_rcv_settle_mode(self):
+     return pn_link_remote_rcv_settle_mode(self._link)
+ 
+   def _get_snd_settle_mode(self):
+     return pn_link_snd_settle_mode(self._link)
+   def _set_snd_settle_mode(self, mode):
+     pn_link_set_snd_settle_mode(self._link, mode)
+   snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode)
+ 
+   def _get_rcv_settle_mode(self):
+     return pn_link_rcv_settle_mode(self._link)
+   def _set_rcv_settle_mode(self, mode):
+     pn_link_set_rcv_settle_mode(self._link, mode)
+   rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode)
+ 
+   def drained(self):
+     return pn_link_drained(self._link)
+ 
+   def detach(self):
+     return pn_link_detach(self._link)
+ 
+ class Terminus(object):
+ 
+   UNSPECIFIED = PN_UNSPECIFIED
+   SOURCE = PN_SOURCE
+   TARGET = PN_TARGET
+   COORDINATOR = PN_COORDINATOR
+ 
+   NONDURABLE = PN_NONDURABLE
+   CONFIGURATION = PN_CONFIGURATION
+   DELIVERIES = PN_DELIVERIES
+ 
+   DIST_MODE_UNSPECIFIED = PN_DIST_MODE_UNSPECIFIED
+   DIST_MODE_COPY = PN_DIST_MODE_COPY
+   DIST_MODE_MOVE = PN_DIST_MODE_MOVE
+ 
+   def __init__(self, impl):
+     self._impl = impl
+ 
+   def _check(self, err):
+     if err < 0:
+       exc = EXCEPTIONS.get(err, LinkException)
+       raise exc("[%s]" % err)
+     else:
+       return err
+ 
+   def _get_type(self):
+     return pn_terminus_get_type(self._impl)
+   def _set_type(self, type):
+     self._check(pn_terminus_set_type(self._impl, type))
+   type = property(_get_type, _set_type)
+ 
+   def _get_address(self):
+     return pn_terminus_get_address(self._impl)
+   def _set_address(self, address):
+     self._check(pn_terminus_set_address(self._impl, address))
+   address = property(_get_address, _set_address)
+ 
+   def _get_durability(self):
+     return pn_terminus_get_durability(self._impl)
+   def _set_durability(self, seconds):
+     self._check(pn_terminus_set_durability(self._impl, seconds))
+   durability = property(_get_durability, _set_durability)
+ 
+   def _get_expiry_policy(self):
+     return pn_terminus_get_expiry_policy(self._impl)
+   def _set_expiry_policy(self, seconds):
+     self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
+   expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
+ 
+   def _get_timeout(self):
+     return pn_terminus_get_timeout(self._impl)
+   def _set_timeout(self, seconds):
+     self._check(pn_terminus_set_timeout(self._impl, seconds))
+   timeout = property(_get_timeout, _set_timeout)
+ 
+   def _is_dynamic(self):
+     return pn_terminus_is_dynamic(self._impl)
+   def _set_dynamic(self, dynamic):
+     self._check(pn_terminus_set_dynamic(self._impl, dynamic))
+   dynamic = property(_is_dynamic, _set_dynamic)
+ 
+   def _get_distribution_mode(self):
+     return pn_terminus_get_distribution_mode(self._impl)
+   def _set_distribution_mode(self, mode):
+     self._check(pn_terminus_set_distribution_mode(self._impl, mode))
+   distribution_mode = property(_get_distribution_mode, _set_distribution_mode)
+ 
+   @property
+   def properties(self):
+     return Data(pn_terminus_properties(self._impl))
+ 
+   @property
+   def capabilities(self):
+     return Data(pn_terminus_capabilities(self._impl))
+ 
+   @property
+   def outcomes(self):
+     return Data(pn_terminus_outcomes(self._impl))
+ 
+   @property
+   def filter(self):
+     return Data(pn_terminus_filter(self._impl))
+ 
+   def copy(self, src):
+     self._check(pn_terminus_copy(self._impl, src._impl))
+ 
+ class Sender(Link):
+ 
+   def __init__(self, c_link):
+     super(Sender, self).__init__(c_link)
+ 
+   def offered(self, n):
+     pn_link_offered(self._link, n)
+ 
+   def send(self, bytes):
+     return self._check(pn_link_send(self._link, bytes))
+ 
+ class Receiver(Link):
+ 
+   def __init__(self, c_link):
+     super(Receiver, self).__init__(c_link)
+ 
+   def flow(self, n):
+     pn_link_flow(self._link, n)
+ 
+   def recv(self, limit):
+     n, bytes = pn_link_recv(self._link, limit)
+     if n == PN_EOS:
+       return None
+     else:
+       self._check(n)
+       return bytes
+ 
+   def drain(self, n):
+     pn_link_drain(self._link, n)
+ 
+   def draining(self):
+     return pn_link_draining(self._link)
+ 
+ class NamedInt(int):
+ 
+   values = {}
+ 
+   def __new__(cls, i, name):
+     ni = super(NamedInt, cls).__new__(cls, i)
+     cls.values[i] = ni
+     return ni
+ 
+   def __init__(self, i, name):
+     self.name = name
+ 
+   def __repr__(self):
+     return self.name
+ 
+   def __str__(self):
+     return self.name
+ 
+   @classmethod
+   def get(cls, i):
+     return cls.values.get(i, i)
+ 
+ class DispositionType(NamedInt):
+   values = {}
+ 
+ class Disposition(object):
+ 
+   RECEIVED = DispositionType(PN_RECEIVED, "RECEIVED")
+   ACCEPTED = DispositionType(PN_ACCEPTED, "ACCEPTED")
+   REJECTED = DispositionType(PN_REJECTED, "REJECTED")
+   RELEASED = DispositionType(PN_RELEASED, "RELEASED")
+   MODIFIED = DispositionType(PN_MODIFIED, "MODIFIED")
+ 
+   def __init__(self, impl, local):
+     self._impl = impl
+     self.local = local
+     self._data = None
+     self._condition = None
+     self._annotations = None
+ 
+   @property
+   def type(self):
+     return DispositionType.get(pn_disposition_type(self._impl))
+ 
+   def _get_section_number(self):
+     return pn_disposition_get_section_number(self._impl)
+   def _set_section_number(self, n):
+     pn_disposition_set_section_number(self._impl, n)
+   section_number = property(_get_section_number, _set_section_number)
+ 
+   def _get_section_offset(self):
+     return pn_disposition_get_section_offset(self._impl)
+   def _set_section_offset(self, n):
+     pn_disposition_set_section_offset(self._impl, n)
+   section_offset = property(_get_section_offset, _set_section_offset)
+ 
+   def _get_failed(self):
+     return pn_disposition_is_failed(self._impl)
+   def _set_failed(self, b):
+     pn_disposition_set_failed(self._impl, b)
+   failed = property(_get_failed, _set_failed)
+ 
+   def _get_undeliverable(self):
+     return pn_disposition_is_undeliverable(self._impl)
+   def _set_undeliverable(self, b):
+     pn_disposition_set_undeliverable(self._impl, b)
+   undeliverable = property(_get_undeliverable, _set_undeliverable)
+ 
+   def _get_data(self):
+     if self.local:
+       return self._data
+     else:
+       return dat2obj(pn_disposition_data(self._impl))
+   def _set_data(self, obj):
+     if self.local:
+       self._data = obj
+     else:
+       raise AttributeError("data attribute is read-only")
+   data = property(_get_data, _set_data)
+ 
+   def _get_annotations(self):
+     if self.local:
+       return self._annotations
+     else:
+       return dat2obj(pn_disposition_annotations(self._impl))
+   def _set_annotations(self, obj):
+     if self.local:
+       self._annotations = obj
+     else:
+       raise AttributeError("annotations attribute is read-only")
+   annotations = property(_get_annotations, _set_annotations)
+ 
+   def _get_condition(self):
+     if self.local:
+       return self._condition
+     else:
+       return cond2obj(pn_disposition_condition(self._impl))
+   def _set_condition(self, obj):
+     if self.local:
+       self._condition = obj
+     else:
+       raise AttributeError("condition attribute is read-only")
+   condition = property(_get_condition, _set_condition)
+ 
+ class Delivery(object):
+ 
+   RECEIVED = Disposition.RECEIVED
+   ACCEPTED = Disposition.ACCEPTED
+   REJECTED = Disposition.REJECTED
+   RELEASED = Disposition.RELEASED
+   MODIFIED = Disposition.MODIFIED
+ 
+   @staticmethod
+   def _wrap_delivery(c_dlv):
+     """Maintain only a single instance of this class for each Delivery object that
+     exists in the C Engine.
+     """
+     if not c_dlv: return None
+     py_dlv = pn_void2py(pn_delivery_get_context(c_dlv))
+     if py_dlv: return py_dlv
+     wrapper = Delivery(c_dlv)
+     return wrapper
+ 
+   def __init__(self, dlv):
+     self._dlv = dlv
+     pn_delivery_set_context(self._dlv, pn_py2void(self))
+     self.local = Disposition(pn_delivery_local(self._dlv), True)
+     self.remote = Disposition(pn_delivery_remote(self._dlv), False)
+     self.link._deliveries.add(self)
+ 
+   def __del__(self):
+     self._release()
+ 
+   def _release(self):
+     """Release the underlying C Engine resource."""
+     if self._dlv:
+       pn_delivery_set_context(self._dlv, pn_py2void(None))
+       pn_delivery_settle(self._dlv)
+       self._dlv = None
+ 
+   @property
+   def released(self):
+     return self._dlv is None
+ 
+   @property
+   def tag(self):
+     return pn_delivery_tag(self._dlv)
+ 
+   @property
+   def writable(self):
+     return pn_delivery_writable(self._dlv)
+ 
+   @property
+   def readable(self):
+     return pn_delivery_readable(self._dlv)
+ 
+   @property
+   def updated(self):
+     return pn_delivery_updated(self._dlv)
+ 
+   def update(self, state):
+     obj2dat(self.local._data, pn_disposition_data(self.local._impl))
+     obj2dat(self.local._annotations, pn_disposition_annotations(self.local._impl))
+     obj2cond(self.local._condition, pn_disposition_condition(self.local._impl))
+     pn_delivery_update(self._dlv, state)
+ 
+   @property
+   def pending(self):
+     return pn_delivery_pending(self._dlv)
+ 
+   @property
+   def partial(self):
+     return pn_delivery_partial(self._dlv)
+ 
+   @property
+   def local_state(self):
+     return DispositionType.get(pn_delivery_local_state(self._dlv))
+ 
+   @property
+   def remote_state(self):
+     return DispositionType.get(pn_delivery_remote_state(self._dlv))
+ 
+   @property
+   def settled(self):
+     return pn_delivery_settled(self._dlv)
+ 
+   def settle(self):
+     """Release the delivery"""
+     self.link._deliveries.remove(self)
+     self._release()
+ 
+   @property
+   def work_next(self):
+     return Delivery._wrap_delivery(pn_work_next(self._dlv))
+ 
+   @property
+   def link(self):
+     return Link._wrap_link(pn_delivery_link(self._dlv))
+ 
+ class TransportException(ProtonException):
+   pass
+ 
+ class Transport(object):
+ 
+   TRACE_OFF = PN_TRACE_OFF
+   TRACE_DRV = PN_TRACE_DRV
+   TRACE_FRM = PN_TRACE_FRM
+   TRACE_RAW = PN_TRACE_RAW
+ 
+   CLIENT = 1
+   SERVER = 2
+ 
+   @staticmethod
+   def _wrap_transport(c_trans):
+     if not c_trans: return None
+     wrapper = Transport(_trans=c_trans)
+     return

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d02fdad1/proton-c/src/transport/transport.c
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[17/35] qpid-proton git commit: PROTON-749, PROTON-750: Merge these changes into development stream.

Posted by gs...@apache.org.
PROTON-749, PROTON-750: Merge these changes into development stream.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/b4e06d34
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/b4e06d34
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/b4e06d34

Branch: refs/heads/examples
Commit: b4e06d34a83cd942ea88a5e19ad938be312ed2ae
Parents: 7b91e1f 0cc9134
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Nov 20 10:51:10 2014 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Thu Nov 20 10:51:10 2014 -0500

----------------------------------------------------------------------
 proton-c/CMakeLists.txt                         |   1 +
 proton-c/bindings/python/proton.py              |  35 +-
 proton-c/include/proton/cproton.i               |   2 +-
 proton-c/include/proton/sasl.h                  |  20 +-
 proton-c/include/proton/ssl.h                   |   6 +
 proton-c/include/proton/transport.h             |  20 +-
 proton-c/src/engine/engine-internal.h           |  36 +-
 proton-c/src/messenger/messenger.c              |   3 +-
 proton-c/src/posix/driver.c                     |   8 +-
 proton-c/src/proton.c                           |  10 +-
 proton-c/src/sasl/sasl-internal.h               |   6 +-
 proton-c/src/sasl/sasl.c                        | 294 +++++++-----
 proton-c/src/ssl/openssl.c                      | 452 ++++++++-----------
 proton-c/src/ssl/ssl-internal.h                 |   6 +-
 proton-c/src/ssl/ssl_stub.c                     |  22 +-
 proton-c/src/tests/engine.c                     |   3 +
 proton-c/src/transport/autodetect.c             | 135 ++++++
 proton-c/src/transport/autodetect.h             |  40 ++
 proton-c/src/transport/transport.c              | 422 +++++++++++------
 proton-c/src/windows/driver.c                   |   8 +-
 proton-c/src/windows/schannel.c                 | 371 +++++++--------
 .../qpid/proton/engine/impl/SaslImpl.java       |   7 +-
 proton-j/src/main/resources/cengine.py          |   5 +-
 proton-j/src/main/resources/csasl.py            |  14 +-
 proton-j/src/main/resources/cssl.py             |   3 +
 tests/python/proton_tests/common.py             |  13 +-
 tests/python/proton_tests/engine.py             |   3 -
 tests/python/proton_tests/sasl.py               |  14 +-
 28 files changed, 1132 insertions(+), 827 deletions(-)
----------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[19/35] qpid-proton git commit: NO-JIRA: Fix a few Ruby method names to fit naming conventions.

Posted by gs...@apache.org.
NO-JIRA: Fix a few Ruby method names to fit naming conventions.

Messenger::receiving and Messenger::stopped renamed to
Messenger::receiving? and Messenger::stopped?

Also fixed a typo in one rdoc and added rdoc to receiving?


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/b13222b8
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/b13222b8
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/b13222b8

Branch: refs/heads/examples
Commit: b13222b8214f4690c169eefc13354ff5f6479c2e
Parents: 1d3a138
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Thu Nov 20 13:45:15 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Thu Nov 20 13:46:17 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/lib/qpid_proton/messenger.rb | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b13222b8/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index 66a2f93..f17205d 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -208,10 +208,10 @@ module Qpid
         Cproton.pn_messenger_stop(@impl)
       end
 
-      # Returns true iff a Messenger is in the stopped state.
+      # Returns true if a Messenger is in the stopped state.
       # This function does not block.
       #
-      def stopped
+      def stopped?
         Cproton.pn_messenger_stopped(@impl)
       end
 
@@ -389,7 +389,8 @@ module Qpid
         Cproton.pn_messenger_recv(@impl, limit)
       end
 
-      def receiving
+      # Returns true if the messenger is currently receiving data.
+      def receiving?
         Cproton.pn_messenger_receiving(@impl)
       end
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[34/35] qpid-proton git commit: moved supporting code into proton package

Posted by gs...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/proton_reactors.py
----------------------------------------------------------------------
diff --git a/tutorial/proton_reactors.py b/tutorial/proton_reactors.py
deleted file mode 100644
index f431b24..0000000
--- a/tutorial/proton_reactors.py
+++ /dev/null
@@ -1,749 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-import heapq, os, Queue, socket, time, types
-from proton import dispatch, generate_uuid, PN_ACCEPTED, SASL, symbol, ulong, Url
-from proton import Collector, Connection, Delivery, Described, Endpoint, Event, Link, Terminus, Timeout
-from proton import Message, Handler, ProtonException, Transport, TransportException, ConnectionException
-from select import select
-from proton_handlers import nested_handlers, ScopedHandler
-
-
-class AmqpSocket(object):
-
-    def __init__(self, conn, sock, events, heartbeat=None):
-        self.events = events
-        self.conn = conn
-        self.transport = Transport()
-        if heartbeat: self.transport.idle_timeout = heartbeat
-        self.transport.bind(self.conn)
-        self.socket = sock
-        self.socket.setblocking(0)
-        self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        self.write_done = False
-        self.read_done = False
-        self._closed = False
-
-    def accept(self, force_sasl=True):
-        if force_sasl:
-            sasl = self.transport.sasl()
-            sasl.mechanisms("ANONYMOUS")
-            sasl.server()
-            sasl.done(SASL.OK)
-        #TODO: use SASL anyway if requested by peer
-        return self
-
-    def connect(self, host, port=None, username=None, password=None, force_sasl=True):
-        if username and password:
-            sasl = self.transport.sasl()
-            sasl.plain(username, password)
-        elif force_sasl:
-            sasl = self.transport.sasl()
-            sasl.mechanisms('ANONYMOUS')
-            sasl.client()
-        try:
-            self.socket.connect_ex((host, port or 5672))
-        except socket.gaierror, e:
-            raise ConnectionException("Cannot resolve '%s': %s" % (host, e))
-        return self
-
-    def _closed_cleanly(self):
-        return self.conn.state & Endpoint.LOCAL_CLOSED and self.conn.state & Endpoint.REMOTE_CLOSED
-
-    def closed(self):
-        if not self._closed and self.write_done and self.read_done:
-            self.close()
-            return True
-        else:
-            return False
-
-    def close(self):
-        self.socket.close()
-        self._closed = True
-
-    def fileno(self):
-        return self.socket.fileno()
-
-    def reading(self):
-        if self.read_done: return False
-        c = self.transport.capacity()
-        if c > 0:
-            return True
-        elif c < 0:
-            self.read_done = True
-        return False
-
-    def writing(self):
-        if self.write_done: return False
-        try:
-            p = self.transport.pending()
-            if p > 0:
-                return True
-            elif p < 0:
-                self.write_done = True
-                return False
-            else: # p == 0
-                return False
-        except TransportException, e:
-            self.write_done = True
-            return False
-
-    def readable(self):
-        c = self.transport.capacity()
-        if c > 0:
-            try:
-                data = self.socket.recv(c)
-                if data:
-                    self.transport.push(data)
-                else:
-                    if not self._closed_cleanly():
-                        self.read_done = True
-                        self.write_done = True
-                    else:
-                        self.transport.close_tail()
-            except TransportException, e:
-                print "Error on read: %s" % e
-                self.read_done = True
-            except socket.error, e:
-                print "Error on recv: %s" % e
-                self.read_done = True
-                self.write_done = True
-        elif c < 0:
-            self.read_done = True
-
-    def writable(self):
-        try:
-            p = self.transport.pending()
-            if p > 0:
-                data = self.transport.peek(p)
-                n = self.socket.send(data)
-                self.transport.pop(n)
-            elif p < 0:
-                self.write_done = True
-        except TransportException, e:
-            print "Error on write: %s" % e
-            self.write_done = True
-        except socket.error, e:
-            print "Error on send: %s" % e
-            self.write_done = True
-
-    def removed(self):
-        if not self._closed_cleanly():
-            self.transport.unbind()
-            self.events.dispatch(ApplicationEvent("disconnected", connection=self.conn))
-
-    def tick(self):
-        t = self.transport.tick(time.time())
-        if t: return t - time.time()
-        else: return None
-
-class Acceptor:
-
-    def __init__(self, events, loop, host, port):
-        self.events = events
-        self.loop = loop
-        self.socket = socket.socket()
-        self.socket.setblocking(0)
-        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self.socket.bind((host, port))
-        self.socket.listen(5)
-        self.loop.add(self)
-        self._closed = False
-
-    def closed(self):
-        if self._closed:
-            self.socket.close()
-            return True
-        else:
-            return False
-
-    def close(self):
-        self._closed = True
-
-    def fileno(self):
-        return self.socket.fileno()
-
-    def reading(self):
-        return not self._closed
-
-    def writing(self):
-        return False
-
-    def readable(self):
-        sock, addr = self.socket.accept()
-        if sock:
-            self.loop.add(AmqpSocket(self.events.connection(), sock, self.events).accept())
-
-    def removed(self): pass
-    def tick(self): return None
-
-class EventInjector(object):
-    def __init__(self, events):
-        self.events = events
-        self.queue = Queue.Queue()
-        self.pipe = os.pipe()
-        self._closed = False
-
-    def trigger(self, event):
-        self.queue.put(event)
-        os.write(self.pipe[1], "!")
-
-    def closed(self):
-        return self._closed and self.queue.empty()
-
-    def close(self):
-        self._closed = True
-
-    def fileno(self):
-        return self.pipe[0]
-
-    def reading(self):
-        return True
-
-    def writing(self):
-        return False
-
-    def readable(self):
-        os.read(self.pipe[0], 512)
-        while not self.queue.empty():
-            self.events.dispatch(self.queue.get())
-
-    def removed(self): pass
-    def tick(self): return None
-
-class Events(object):
-    def __init__(self, *handlers):
-        self.collector = Collector()
-        self.handlers = handlers
-
-    def connection(self):
-        conn = Connection()
-        conn.collect(self.collector)
-        return conn
-
-    def process(self):
-        while True:
-            ev = self.collector.peek()
-            if ev:
-                self.dispatch(ev)
-                self.collector.pop()
-            else:
-                return
-
-    def dispatch(self, event):
-        for h in self.handlers:
-            event.dispatch(h)
-
-    @property
-    def next_interval(self):
-        return None
-
-    @property
-    def empty(self):
-        return self.collector.peek() == None
-
-class ExtendedEventType(object):
-    def __init__(self, name):
-        self.name = name
-        self.method = "on_%s" % name
-
-class ApplicationEvent(Event):
-    def __init__(self, typename, connection=None, session=None, link=None, delivery=None, subject=None):
-        self.type = ExtendedEventType(typename)
-        self.subject = subject
-        if delivery:
-            self.context = delivery
-            self.clazz = "pn_delivery"
-        elif link:
-            self.context = link
-            self.clazz = "pn_link"
-        elif session:
-            self.context = session
-            self.clazz = "pn_session"
-        elif connection:
-            self.context = connection
-            self.clazz = "pn_connection"
-        else:
-            self.context = None
-            self.clazz = "none"
-
-    def __repr__(self):
-        objects = [self.context, self.subject]
-        return "%s(%s)" % (self.type.name,
-                           ", ".join([str(o) for o in objects if o is not None]))
-
-class StartEvent(ApplicationEvent):
-    def __init__(self, reactor):
-        super(StartEvent, self).__init__("start")
-        self.reactor = reactor
-
-class ScheduledEvents(Events):
-    def __init__(self, *handlers):
-        super(ScheduledEvents, self).__init__(*handlers)
-        self._events = []
-
-    def schedule(self, deadline, event):
-        heapq.heappush(self._events, (deadline, event))
-
-    def process(self):
-        super(ScheduledEvents, self).process()
-        while self._events and self._events[0][0] <= time.time():
-            self.dispatch(heapq.heappop(self._events)[1])
-
-    @property
-    def next_interval(self):
-        if len(self._events):
-            deadline = self._events[0][0]
-            now = time.time()
-            return deadline - now if deadline > now else 0
-        else:
-            return None
-
-    @property
-    def empty(self):
-        return super(ScheduledEvents, self).empty and len(self._events) == 0
-
-def _min(a, b):
-    if a and b: return min(a, b)
-    elif a: return a
-    else: return b
-
-class SelectLoop(object):
-
-    def __init__(self, events):
-        self.events = events
-        self.selectables = []
-        self._abort = False
-
-    def abort(self):
-        self._abort = True
-
-    def add(self, selectable):
-        self.selectables.append(selectable)
-
-    def remove(self, selectable):
-        self.selectables.remove(selectable)
-
-    @property
-    def redundant(self):
-        return self.events.empty and not self.selectables
-
-    @property
-    def aborted(self):
-        return self._abort
-
-    def run(self):
-        while not (self._abort or self.redundant):
-            self.do_work()
-
-    def do_work(self, timeout=None):
-        """@return True if some work was done, False if time-out expired"""
-        self.events.process()
-        if self._abort: return
-
-        stable = False
-        while not stable:
-            reading = []
-            writing = []
-            closed = []
-            tick = None
-            for s in self.selectables:
-                if s.reading(): reading.append(s)
-                if s.writing(): writing.append(s)
-                if s.closed(): closed.append(s)
-                else: tick = _min(tick, s.tick())
-
-            for s in closed:
-                self.selectables.remove(s)
-                s.removed()
-            stable = len(closed) == 0
-
-        if self.redundant:
-            return
-
-        if timeout and timeout < 0:
-            timeout = 0
-        if self.events.next_interval and (timeout is None or self.events.next_interval < timeout):
-            timeout = self.events.next_interval
-        if tick:
-            timeout = _min(tick, timeout)
-        if reading or writing or timeout:
-            readable, writable, _ = select(reading, writing, [], timeout)
-            for s in self.selectables:
-                s.tick()
-            for s in readable:
-                s.readable()
-            for s in writable:
-                s.writable()
-
-            return bool(readable or writable)
-        else:
-            return False
-
-def delivery_tags():
-    count = 1
-    while True:
-        yield str(count)
-        count += 1
-
-def send_msg(sender, msg, tag=None, handler=None, transaction=None):
-    dlv = sender.delivery(tag or next(sender.tags))
-    if transaction:
-        dlv.local.data = [transaction.id]
-        dlv.update(0x34)
-    if handler:
-        dlv.context = handler
-    sender.send(msg.encode())
-    sender.advance()
-    return dlv
-
-def _send_msg(self, msg, tag=None, handler=None, transaction=None):
-    return send_msg(self, msg, tag, handler, transaction)
-
-
-class Transaction(object):
-    def __init__(self, txn_ctrl, handler, settle_before_discharge=False):
-        self.txn_ctrl = txn_ctrl
-        self.handler = handler
-        self.id = None
-        self._declare = None
-        self._discharge = None
-        self.failed = False
-        self._pending = []
-        self.settle_before_discharge = settle_before_discharge
-        self.declare()
-
-    def commit(self):
-        self.discharge(False)
-
-    def abort(self):
-        self.discharge(True)
-
-    def declare(self):
-        self._declare = self._send_ctrl(symbol(u'amqp:declare:list'), [None])
-
-    def discharge(self, failed):
-        self.failed = failed
-        self._discharge = self._send_ctrl(symbol(u'amqp:discharge:list'), [self.id, failed])
-
-    def _send_ctrl(self, descriptor, value):
-        delivery = self.txn_ctrl.send_msg(Message(body=Described(descriptor, value)), handler=self.handler)
-        delivery.transaction = self
-        return delivery
-
-    def accept(self, delivery):
-        self.update(delivery, PN_ACCEPTED)
-        if self.settle_before_discharge:
-            delivery.settle()
-        else:
-            self._pending.append(delivery)
-
-    def update(self, delivery, state=None):
-        if state:
-            delivery.local.data = [self.id, Described(ulong(state), [])]
-            delivery.update(0x34)
-
-    def _release_pending(self):
-        for d in self._pending:
-            d.update(Delivery.RELEASED)
-            d.settle()
-        self._clear_pending()
-
-    def _clear_pending(self):
-        self._pending = []
-
-    def handle_outcome(self, event):
-        if event.delivery == self._declare:
-            if event.delivery.remote.data:
-                self.id = event.delivery.remote.data[0]
-                self.handler.on_transaction_declared(event)
-            elif event.delivery.remote_state == Delivery.REJECTED:
-                self.handler.on_transaction_declare_failed(event)
-            else:
-                print "Unexpected outcome for declare: %s" % event.delivery.remote_state
-                self.handler.on_transaction_declare_failed(event)
-        elif event.delivery == self._discharge:
-            if event.delivery.remote_state == Delivery.REJECTED:
-                if not self.failed:
-                    self.handler.on_transaction_commit_failed(event)
-                    self._release_pending() # make this optional?
-            else:
-                if self.failed:
-                    self.handler.on_transaction_aborted(event)
-                    self._release_pending()
-                else:
-                    self.handler.on_transaction_committed(event)
-            self._clear_pending()
-
-class LinkOption(object):
-    def apply(self, link): pass
-    def test(self, link): return True
-
-class AtMostOnce(LinkOption):
-    def apply(self, link):
-        link.snd_settle_mode = Link.SND_SETTLED
-
-class AtLeastOnce(LinkOption):
-    def apply(self, link):
-        link.snd_settle_mode = Link.SND_UNSETTLED
-        link.rcv_settle_mode = Link.RCV_FIRST
-
-class SenderOption(LinkOption):
-    def apply(self, sender): pass
-    def test(self, link): return link.is_sender
-
-class ReceiverOption(LinkOption):
-    def apply(self, receiver): pass
-    def test(self, link): return link.is_receiver
-
-class Filter(ReceiverOption):
-    def __init__(self, filter_set={}):
-        self.filter_set = filter_set
-
-    def apply(self, receiver):
-        receiver.source.filter.put_dict(self.filter_set)
-
-class Selector(Filter):
-    def __init__(self, value, name='selector'):
-        super(Selector, self).__init__({symbol(name): Described(symbol('apache.org:selector-filter:string'), value)})
-
-def _apply_link_options(options, link):
-    if options:
-        if isinstance(options, list):
-            for o in options:
-                if o.test(link): o.apply(link)
-        else:
-            if options.test(link): options.apply(link)
-
-
-class MessagingContext(object):
-    def __init__(self, conn, handler=None, ssn=None):
-        self.conn = conn
-        if handler:
-            self.conn.context = handler
-        self.conn._mc = self
-        self.ssn = ssn
-        self.txn_ctrl = None
-
-    def _get_handler(self):
-        return self.conn.context
-
-    def _set_handler(self, value):
-        self.conn.context = value
-
-    handler = property(_get_handler, _set_handler)
-
-    def create_sender(self, target, source=None, name=None, handler=None, tags=None, options=None):
-        snd = self._get_ssn().sender(name or self._get_id(target, source))
-        if source:
-            snd.source.address = source
-        if target:
-            snd.target.address = target
-        if handler:
-            snd.context = handler
-        snd.tags = tags or delivery_tags()
-        snd.send_msg = types.MethodType(_send_msg, snd)
-        _apply_link_options(options, snd)
-        snd.open()
-        return snd
-
-    def create_receiver(self, source, target=None, name=None, dynamic=False, handler=None, options=None):
-        rcv = self._get_ssn().receiver(name or self._get_id(source, target))
-        if source:
-            rcv.source.address = source
-        if dynamic:
-            rcv.source.dynamic = True
-        if target:
-            rcv.target.address = target
-        if handler:
-            rcv.context = handler
-        _apply_link_options(options, rcv)
-        rcv.open()
-        return rcv
-
-    def create_session(self):
-        return MessageContext(conn=None, ssn=self._new_ssn())
-
-    def declare_transaction(self, handler=None, settle_before_discharge=False):
-        if not self.txn_ctrl:
-            self.txn_ctrl = self.create_sender(None, name="txn-ctrl")
-            self.txn_ctrl.target.type = Terminus.COORDINATOR
-            self.txn_ctrl.target.capabilities.put_object(symbol(u'amqp:local-transactions'))
-        return Transaction(self.txn_ctrl, handler, settle_before_discharge)
-
-    def close(self):
-        if self.ssn:
-            self.ssn.close()
-        if self.conn:
-            self.conn.close()
-
-    def _get_id(self, remote, local):
-        if local and remote: "%s-%s-%s" % (self.conn.container, remote, local)
-        elif local: return "%s-%s" % (self.conn.container, local)
-        elif remote: return "%s-%s" % (self.conn.container, remote)
-        else: return "%s-%s" % (self.conn.container, str(generate_uuid()))
-
-    def _get_ssn(self):
-        if not self.ssn:
-            self.ssn = self._new_ssn()
-            self.ssn.context = self
-        return self.ssn
-
-    def _new_ssn(self):
-        ssn = self.conn.session()
-        ssn.open()
-        return ssn
-
-    def on_session_remote_close(self, event):
-        if self.conn:
-            self.conn.close()
-
-class Connector(Handler):
-    def attach_to(self, loop):
-        self.loop = loop
-
-    def _connect(self, connection):
-        host, port = connection.address.next()
-        #print "connecting to %s:%i" % (host, port)
-        heartbeat = connection.heartbeat if hasattr(connection, 'heartbeat') else None
-        self.loop.add(AmqpSocket(connection, socket.socket(), self.loop.events, heartbeat=heartbeat).connect(host, port))
-
-    def on_connection_local_open(self, event):
-        if hasattr(event.connection, "address"):
-            self._connect(event.connection)
-
-    def on_connection_remote_open(self, event):
-        if hasattr(event.connection, "reconnect"):
-            event.connection.reconnect.reset()
-
-    def on_disconnected(self, event):
-        if hasattr(event.connection, "reconnect"):
-            delay = event.connection.reconnect.next()
-            if delay == 0:
-                print "Disconnected, reconnecting..."
-                self._connect(event.connection)
-            else:
-                print "Disconnected will try to reconnect after %s seconds" % delay
-                self.loop.schedule(time.time() + delay, connection=event.connection, subject=self)
-        else:
-            print "Disconnected"
-
-    def on_timer(self, event):
-        if event.subject == self and event.connection:
-            self._connect(event.connection)
-
-class Backoff(object):
-    def __init__(self):
-        self.delay = 0
-
-    def reset(self):
-        self.delay = 0
-
-    def next(self):
-        current = self.delay
-        if current == 0:
-            self.delay = 0.1
-        else:
-            self.delay = min(10, 2*current)
-        return current
-
-class Urls(object):
-    def __init__(self, values):
-        self.values = [Url(v) for v in values]
-        self.i = iter(self.values)
-
-    def __iter__(self):
-        return self
-
-    def _as_pair(self, url):
-        return (url.host, url.port)
-
-    def next(self):
-        try:
-            return self._as_pair(self.i.next())
-        except StopIteration:
-            self.i = iter(self.values)
-            return self._as_pair(self.i.next())
-
-class EventLoop(object):
-    def __init__(self, *handlers):
-        self.connector = Connector()
-        h = [self.connector, ScopedHandler()]
-        h.extend(nested_handlers(handlers))
-        self.events = ScheduledEvents(*h)
-        self.loop = SelectLoop(self.events)
-        self.connector.attach_to(self)
-        self.trigger = None
-        self.container_id = str(generate_uuid())
-
-    def connect(self, url=None, urls=None, address=None, handler=None, reconnect=None, heartbeat=None):
-        context = MessagingContext(self.events.connection(), handler=handler)
-        context.conn.container = self.container_id or str(generate_uuid())
-        context.conn.heartbeat = heartbeat
-        if url: context.conn.address = Urls([url])
-        elif urls: context.conn.address = Urls(urls)
-        elif address: context.conn.address = address
-        else: raise ValueError("One of url, urls or address required")
-        if reconnect:
-            context.conn.reconnect = reconnect
-        elif reconnect is None:
-            context.conn.reconnect = Backoff()
-        context.conn.open()
-        return context
-
-    def listen(self, url):
-        host, port = Urls([url]).next()
-        return Acceptor(self.events, self, host, port)
-
-    def schedule(self, deadline, connection=None, session=None, link=None, delivery=None, subject=None):
-        self.events.schedule(deadline, ApplicationEvent("timer", connection, session, link, delivery, subject))
-
-    def get_event_trigger(self):
-        if not self.trigger or self.trigger.closed():
-            self.trigger = EventInjector(self.events)
-            self.add(self.trigger)
-        return self.trigger
-
-    def add(self, selectable):
-        self.loop.add(selectable)
-
-    def remove(self, selectable):
-        self.loop.remove(selectable)
-
-    def run(self):
-        self.events.dispatch(StartEvent(self))
-        self.loop.run()
-
-    def stop(self):
-        self.loop.abort()
-
-    def do_work(self, timeout=None):
-        return self.loop.do_work(timeout)
-
-EventLoop.DEFAULT = EventLoop()
-
-def connect(url=None, urls=None, address=None, handler=None, reconnect=None, eventloop=None, heartbeat=None):
-    if not eventloop:
-        eventloop = EventLoop.DEFAULT
-    return eventloop.connect(url=url, urls=urls, address=address, handler=handler, reconnect=reconnect, heartbeat=heartbeat)
-
-def run(eventloop=None):
-    if not eventloop:
-        eventloop = EventLoop.DEFAULT
-    eventloop.run()
-

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/proton_server.py
----------------------------------------------------------------------
diff --git a/tutorial/proton_server.py b/tutorial/proton_server.py
index 3ebf366..b2e2027 100644
--- a/tutorial/proton_server.py
+++ b/tutorial/proton_server.py
@@ -18,8 +18,8 @@
 #
 
 from proton import Message
-from proton_reactors import EventLoop
-from proton_handlers import FlowController, IncomingMessageHandler
+from proton.reactors import EventLoop
+from proton.handlers import FlowController, IncomingMessageHandler
 
 class Server(IncomingMessageHandler):
     def __init__(self, host, address):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/proton_tornado.py
----------------------------------------------------------------------
diff --git a/tutorial/proton_tornado.py b/tutorial/proton_tornado.py
index a5ec82c..e49b28e 100644
--- a/tutorial/proton_tornado.py
+++ b/tutorial/proton_tornado.py
@@ -18,7 +18,7 @@
 # under the License.
 #
 
-from proton_reactors import ApplicationEvent, EventLoop, StartEvent
+from proton.reactors import ApplicationEvent, EventLoop, StartEvent
 import tornado.ioloop
 
 class TornadoLoop(EventLoop):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/proton_utils.py
----------------------------------------------------------------------
diff --git a/tutorial/proton_utils.py b/tutorial/proton_utils.py
deleted file mode 100644
index fce0cf5..0000000
--- a/tutorial/proton_utils.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-import Queue, socket, time
-from proton import ConnectionException, Endpoint, Handler, Message, Url
-from proton_reactors import AmqpSocket, Events, MessagingContext, SelectLoop, send_msg
-from proton_handlers import ScopedHandler
-
-class BlockingLink(object):
-    def __init__(self, connection, link):
-        self.connection = connection
-        self.link = link
-        self.connection.wait(lambda: not (self.link.state & Endpoint.REMOTE_UNINIT),
-                             msg="Opening link %s" % link.name)
-
-    def close(self):
-        self.connection.wait(not (self.link.state & Endpoint.REMOTE_ACTIVE),
-                             msg="Closing link %s" % link.name)
-
-    # Access to other link attributes.
-    def __getattr__(self, name): return getattr(self.link, name)
-
-class BlockingSender(BlockingLink):
-    def __init__(self, connection, sender):
-        super(BlockingSender, self).__init__(connection, sender)
-
-    def send_msg(self, msg):
-        delivery = send_msg(self.link, msg)
-        self.connection.wait(lambda: delivery.settled, msg="Sending on sender %s" % self.link.name)
-
-class BlockingReceiver(BlockingLink):
-    def __init__(self, connection, receiver, credit=1):
-        super(BlockingReceiver, self).__init__(connection, receiver)
-        if credit: receiver.flow(credit)
-
-class BlockingConnection(Handler):
-    def __init__(self, url, timeout=None):
-        self.timeout = timeout
-        self.events = Events(ScopedHandler())
-        self.loop = SelectLoop(self.events)
-        self.context = MessagingContext(self.loop.events.connection(), handler=self)
-        if isinstance(url, basestring):
-            self.url = Url(url)
-        else:
-            self.url = url
-        self.loop.add(
-            AmqpSocket(self.context.conn, socket.socket(), self.events).connect(self.url.host, self.url.port))
-        self.context.conn.open()
-        self.wait(lambda: not (self.context.conn.state & Endpoint.REMOTE_UNINIT),
-                  msg="Opening connection")
-
-    def create_sender(self, address, handler=None):
-        return BlockingSender(self, self.context.create_sender(address, handler=handler))
-
-    def create_receiver(self, address, credit=1, dynamic=False, handler=None):
-        return BlockingReceiver(
-            self, self.context.create_receiver(address, dynamic=dynamic, handler=handler), credit=credit)
-
-    def close(self):
-        self.context.conn.close()
-        self.wait(lambda: not (self.context.conn.state & Endpoint.REMOTE_ACTIVE),
-                  msg="Closing connection")
-
-    def run(self):
-        """ Hand control over to the event loop (e.g. if waiting indefinitely for incoming messages) """
-        self.loop.run()
-
-    def wait(self, condition, timeout=False, msg=None):
-        """Call do_work until condition() is true"""
-        if timeout is False:
-            timeout = self.timeout
-        if timeout is None:
-            while not condition():
-                self.loop.do_work()
-        else:
-            deadline = time.time() + timeout
-            while not condition():
-                if not self.loop.do_work(deadline - time.time()):
-                    txt = "Connection %s timed out" % self.url
-                    if msg: txt += ": " + msg
-                    raise Timeout(txt)
-
-    def on_link_remote_close(self, event):
-        if event.link.state & Endpoint.LOCAL_ACTIVE:
-            self.closed(event.link.remote_condition)
-
-    def on_connection_remote_close(self, event):
-        if event.connection.state & Endpoint.LOCAL_ACTIVE:
-            self.closed(event.connection.remote_condition)
-
-    def on_disconnected(self, event):
-        raise ConnectionException("Connection %s disconnected" % self.url);
-
-    def closed(self, error=None):
-        txt = "Connection %s closed" % self.url
-        if error:
-            txt += " due to: %s" % error
-        else:
-            txt += " by peer"
-        raise ConnectionException(txt)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/recurring_timer.py
----------------------------------------------------------------------
diff --git a/tutorial/recurring_timer.py b/tutorial/recurring_timer.py
index 2bd7b9f..c641ec6 100755
--- a/tutorial/recurring_timer.py
+++ b/tutorial/recurring_timer.py
@@ -19,7 +19,7 @@
 #
 
 import time
-from proton_reactors import EventLoop, Handler
+from proton.reactors import EventLoop, Handler
 
 class Recurring(Handler):
     def __init__(self, period):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/selected_recv.py
----------------------------------------------------------------------
diff --git a/tutorial/selected_recv.py b/tutorial/selected_recv.py
index b31862a..8425f3d 100755
--- a/tutorial/selected_recv.py
+++ b/tutorial/selected_recv.py
@@ -18,20 +18,22 @@
 # under the License.
 #
 
-import proton_reactors
-from proton_handlers import MessagingHandler
+from proton.reactors import EventLoop, Selector
+from proton.handlers import MessagingHandler
 
 class Recv(MessagingHandler):
     def __init__(self):
         super(Recv, self).__init__()
 
+    def on_start(self, event):
+        conn = event.reactor.connect("localhost:5672")
+        conn.create_receiver("examples", options=Selector(u"colour = 'green'"))
+
     def on_message(self, event):
         print event.message.body
 
 try:
-    conn = proton_reactors.connect("localhost:5672", handler=Recv())
-    conn.create_receiver("examples", options=proton_reactors.Selector(u"colour = 'green'"))
-    proton_reactors.run()
+    EventLoop(Recv()).run()
 except KeyboardInterrupt: pass
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/server.py
----------------------------------------------------------------------
diff --git a/tutorial/server.py b/tutorial/server.py
index 3969688..6ab5671 100755
--- a/tutorial/server.py
+++ b/tutorial/server.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class Server(MessagingHandler):
     def __init__(self, host, address):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/server_tx.py
----------------------------------------------------------------------
diff --git a/tutorial/server_tx.py b/tutorial/server_tx.py
index 179c1c8..cda2d0b 100755
--- a/tutorial/server_tx.py
+++ b/tutorial/server_tx.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_reactors import EventLoop
-from proton_handlers import MessagingHandler, TransactionHandler
+from proton.reactors import EventLoop
+from proton.handlers import MessagingHandler, TransactionHandler
 
 class TxRequest(TransactionHandler):
     def __init__(self, response, sender, request_delivery, context):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/simple_recv.py
----------------------------------------------------------------------
diff --git a/tutorial/simple_recv.py b/tutorial/simple_recv.py
index aac549c..ea80aa6 100755
--- a/tutorial/simple_recv.py
+++ b/tutorial/simple_recv.py
@@ -18,8 +18,8 @@
 # under the License.
 #
 
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class Recv(MessagingHandler):
     def __init__(self, host, address):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/simple_send.py
----------------------------------------------------------------------
diff --git a/tutorial/simple_send.py b/tutorial/simple_send.py
index 3af5cff..bbd30ac 100755
--- a/tutorial/simple_send.py
+++ b/tutorial/simple_send.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_handlers import MessagingHandler
-from proton_reactors import EventLoop
+from proton.handlers import MessagingHandler
+from proton.reactors import EventLoop
 
 class Send(MessagingHandler):
     def __init__(self, host, address, messages):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/sync_client.py
----------------------------------------------------------------------
diff --git a/tutorial/sync_client.py b/tutorial/sync_client.py
index eb79fc5..362385a 100755
--- a/tutorial/sync_client.py
+++ b/tutorial/sync_client.py
@@ -25,8 +25,8 @@ Demonstrates the client side of the synchronous request-response pattern
 """
 
 from proton import Message, Url, ConnectionException, Timeout
-from proton_utils import BlockingConnection
-from proton_handlers import IncomingMessageHandler
+from proton.utils import BlockingConnection
+from proton.handlers import IncomingMessageHandler
 import sys
 
 class SyncRequestClient(IncomingMessageHandler):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/tx_recv.py
----------------------------------------------------------------------
diff --git a/tutorial/tx_recv.py b/tutorial/tx_recv.py
index 5f14fd8..a28a3df 100755
--- a/tutorial/tx_recv.py
+++ b/tutorial/tx_recv.py
@@ -18,8 +18,8 @@
 # under the License.
 #
 
-from proton_reactors import EventLoop
-from proton_handlers import TransactionalClientHandler
+from proton.reactors import EventLoop
+from proton.handlers import TransactionalClientHandler
 
 class TxRecv(TransactionalClientHandler):
     def __init__(self, batch_size):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/tx_recv_interactive.py
----------------------------------------------------------------------
diff --git a/tutorial/tx_recv_interactive.py b/tutorial/tx_recv_interactive.py
index 4e36534..a822992 100755
--- a/tutorial/tx_recv_interactive.py
+++ b/tutorial/tx_recv_interactive.py
@@ -20,8 +20,8 @@
 
 import sys
 import threading
-from proton_reactors import ApplicationEvent, EventLoop
-from proton_handlers import TransactionalClientHandler
+from proton.reactors import ApplicationEvent, EventLoop
+from proton.handlers import TransactionalClientHandler
 
 class TxRecv(TransactionalClientHandler):
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/tx_send.py
----------------------------------------------------------------------
diff --git a/tutorial/tx_send.py b/tutorial/tx_send.py
index 44c78bf..b2f12b2 100755
--- a/tutorial/tx_send.py
+++ b/tutorial/tx_send.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_reactors import EventLoop
-from proton_handlers import TransactionalClientHandler
+from proton.reactors import EventLoop
+from proton.handlers import TransactionalClientHandler
 
 class TxSend(TransactionalClientHandler):
     def __init__(self, messages, batch_size):

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2f4d1ba2/tutorial/tx_send_sync.py
----------------------------------------------------------------------
diff --git a/tutorial/tx_send_sync.py b/tutorial/tx_send_sync.py
index 6e4d4d8..0c50838 100755
--- a/tutorial/tx_send_sync.py
+++ b/tutorial/tx_send_sync.py
@@ -19,8 +19,8 @@
 #
 
 from proton import Message
-from proton_reactors import EventLoop
-from proton_handlers import TransactionalClientHandler
+from proton.reactors import EventLoop
+from proton.handlers import TransactionalClientHandler
 
 class TxSend(TransactionalClientHandler):
     def __init__(self, messages, batch_size):


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[03/35] qpid-proton git commit: PROTON-750: Have explicit API to detect ssl if present - avoids overloading other functionality for this purpose.

Posted by gs...@apache.org.
PROTON-750: Have explicit API to detect ssl if present
- avoids overloading other functionality for this purpose.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2794da59
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2794da59
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2794da59

Branch: refs/heads/examples
Commit: 2794da59b7ee8810a88b4393dacd87a947c10fe7
Parents: b57f45d
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Oct 30 15:03:32 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Mon Nov 17 14:50:29 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/proton.py  |  4 ++++
 proton-c/include/proton/ssl.h       |  6 ++++++
 proton-c/src/ssl/openssl.c          |  5 +++++
 proton-c/src/ssl/ssl_stub.c         |  5 +++++
 proton-c/src/windows/schannel.c     |  7 +++++--
 proton-j/src/main/resources/cssl.py |  3 +++
 tests/python/proton_tests/common.py | 12 ++----------
 7 files changed, 30 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-c/bindings/python/proton.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton.py b/proton-c/bindings/python/proton.py
index 00c36c0..81104f0 100644
--- a/proton-c/bindings/python/proton.py
+++ b/proton-c/bindings/python/proton.py
@@ -3270,6 +3270,10 @@ class SSLDomain(object):
 
 class SSL(object):
 
+  @staticmethod
+  def present():
+    return pn_ssl_present()
+
   def _check(self, err):
     if err < 0:
       exc = EXCEPTIONS.get(err, SSLException)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-c/include/proton/ssl.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/ssl.h b/proton-c/include/proton/ssl.h
index 013478e..09d386b 100644
--- a/proton-c/include/proton/ssl.h
+++ b/proton-c/include/proton/ssl.h
@@ -90,6 +90,12 @@ typedef enum {
   PN_SSL_RESUME_REUSED          /**< Session resumed from previous session. */
 } pn_ssl_resume_status_t;
 
+/** Tests for SSL implementation present
+ *
+ *  @return true if we support SSL, false if not
+ */
+PN_EXTERN bool pn_ssl_present( void );
+
 /** Create an SSL configuration domain
  *
  * This method allocates an SSL domain object.  This object is used to hold the SSL

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index ea2bd5b..dd1b88b 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -434,6 +434,11 @@ static void ssl_session_free( pn_ssl_session_t *ssn)
 
 /** Public API - visible to application code */
 
+bool pn_ssl_present(void)
+{
+  return true;
+}
+
 pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
 {
   if (!ssl_initialized) {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-c/src/ssl/ssl_stub.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/ssl_stub.c b/proton-c/src/ssl/ssl_stub.c
index 300215a..a5fce02 100644
--- a/proton-c/src/ssl/ssl_stub.c
+++ b/proton-c/src/ssl/ssl_stub.c
@@ -31,6 +31,11 @@
  * used if there is no SSL/TLS support in the system's environment.
  */
 
+bool pn_ssl_present(void)
+{
+  return false;
+}
+
 pn_ssl_t *pn_ssl(pn_transport_t *transport)
 {
   return NULL;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-c/src/windows/schannel.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/windows/schannel.c
index 9437582..de6e117 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/windows/schannel.c
@@ -252,10 +252,13 @@ static void ssl_session_free( pn_ssl_session_t *ssn)
 
 /** Public API - visible to application code */
 
+bool pn_ssl_present(void)
+{
+  return false;
+}
+
 pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
 {
-  if (mode == PN_SSL_MODE_SERVER)
-    return NULL;  // Temporary: not ready for ctest, hide from isSSLPresent()
   pn_ssl_domain_t *domain = (pn_ssl_domain_t *) calloc(1, sizeof(pn_ssl_domain_t));
   if (!domain) return NULL;
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/proton-j/src/main/resources/cssl.py
----------------------------------------------------------------------
diff --git a/proton-j/src/main/resources/cssl.py b/proton-j/src/main/resources/cssl.py
index 97740e3..74497ef 100644
--- a/proton-j/src/main/resources/cssl.py
+++ b/proton-j/src/main/resources/cssl.py
@@ -44,6 +44,9 @@ PN_SSL_MODE_P2J = {
   PN_SSL_MODE_SERVER: SslDomain.Mode.SERVER
 }
 
+def pn_ssl_present():
+  return True
+
 def pn_ssl_domain(mode):
   domain = Proton.sslDomain()
   domain.init(PN_SSL_MODE_P2J[mode])

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2794da59/tests/python/proton_tests/common.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/common.py b/tests/python/proton_tests/common.py
index cfb7e3d..e0887e6 100644
--- a/tests/python/proton_tests/common.py
+++ b/tests/python/proton_tests/common.py
@@ -22,8 +22,7 @@ from threading import Thread
 from socket import socket, AF_INET, SOCK_STREAM
 from subprocess import Popen,PIPE,STDOUT
 import sys, os, string
-from proton import Driver, Connection, Transport, SASL, Endpoint, Delivery, \
-    SSLDomain, SSLUnavailable
+from proton import Driver, Connection, Transport, SASL, Endpoint, Delivery, SSL
 
 
 def free_tcp_ports(count=1):
@@ -79,14 +78,7 @@ def pump(transport1, transport2, buffer_size=1024):
     pass
 
 def isSSLPresent():
-    """ True if a suitable SSL library is available.
-    """
-    try:
-        xxx = SSLDomain(SSLDomain.MODE_SERVER)
-        return True
-    except SSLUnavailable, e:
-        # SSL libraries not installed
-        return False
+    return SSL.present()
 
 class Test(object):
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[09/35] qpid-proton git commit: NO-JIRA: Removed trailing spaces from the Ruby Messenger class.

Posted by gs...@apache.org.
NO-JIRA: Removed trailing spaces from the Ruby Messenger class.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/0d1b8a86
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/0d1b8a86
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/0d1b8a86

Branch: refs/heads/examples
Commit: 0d1b8a8683b116dbcbe420a58f074e77f00d5570
Parents: d770a1e
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Fri Nov 14 16:27:10 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Tue Nov 18 09:09:40 2014 -0500

----------------------------------------------------------------------
 .../ruby/lib/qpid_proton/exception_handling.rb  |  2 +-
 .../bindings/ruby/lib/qpid_proton/messenger.rb  | 22 ++++++++++----------
 2 files changed, 12 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0d1b8a86/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
index 6789c90..f8ac8c6 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
@@ -32,7 +32,7 @@ module Qpid
 
         raise ::ArgumentError.new("Invalid error code: #{code}") if code.nil?
 
-	return code if code > 0
+        return code if code > 0
 
         case(code)
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0d1b8a86/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index 2581e2b..044a3ad 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -297,10 +297,10 @@ module Qpid
       # Places the content contained in the message onto the outgoing
       # queue of the Messenger.
       #
-      # This method will never block, however it will send any unblocked 
+      # This method will never block, however it will send any unblocked
       # Messages in the outgoing queue immediately and leave any blocked
       # Messages remaining in the outgoing queue.
-      # The send call may then be used to block until the outgoing queue 
+      # The send call may then be used to block until the outgoing queue
       # is empty.  The outgoing attribute may be used to check the depth
       # of the outgoing queue.
       #
@@ -319,8 +319,8 @@ module Qpid
 
       # This call will block until the indicated number of messages
       # have been sent, or until the operation times out.
-      # If n is -1 this call will block until all outgoing messages 
-      # have been sent. If n is 0 then this call will send whatever 
+      # If n is -1 this call will block until all outgoing messages
+      # have been sent. If n is 0 then this call will send whatever
       # it can without blocking.
       #
       def send(n = -1)
@@ -392,7 +392,7 @@ module Qpid
       # This will block for the indicated timeout.  This method may also do I/O
       # other than sending and receiving messages.  For example, closing
       # connections after stop() has been called.
-      # 
+      #
       def work(timeout=-1)
         err = Cproton.pn_messenger_work(@impl, timeout)
         if (err == Cproton::PN_TIMEOUT) then
@@ -572,9 +572,9 @@ module Qpid
       end
 
       # Gets the last known remote state of the delivery associated with
-      # the given tracker, as long as the Message is still within your 
-      # outgoing window. (Also works on incoming messages that are still 
-      # within your incoming queue. See TrackerStatus for details on the 
+      # the given tracker, as long as the Message is still within your
+      # outgoing window. (Also works on incoming messages that are still
+      # within your incoming queue. See TrackerStatus for details on the
       # values returned.
       #
       # ==== Options
@@ -609,13 +609,13 @@ module Qpid
 
       # Sets the incoming window.
       #
-      # The Messenger will track the remote status of this many incoming 
+      # The Messenger will track the remote status of this many incoming
       # deliveries after they have been accepted or rejected.
       #
       # Messages enter this window only when you take them into your application
       # using get().  If your incoming window size is n, and you get n+1 messages
       # without explicitly accepting or rejecting the oldest message, then the
-      # message that passes beyond the edge of the incoming window will be 
+      # message that passes beyond the edge of the incoming window will be
       # assigned the default disposition of its link.
       #
       # ==== Options
@@ -635,7 +635,7 @@ module Qpid
 
       # Sets the outgoing window.
       #
-      # The Messenger will track the remote status of this many outgoing 
+      # The Messenger will track the remote status of this many outgoing
       # deliveries after calling send.
       # A Message enters this window when you call the put() method with the
       # message.  If your outgoing window size is n, and you call put n+1


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[14/35] qpid-proton git commit: PROTON-749: Server transport autodetect: - Defer layer initialisation until first send/receive - Move layer initialisation entirely to transport - Server transports will now autodetect the client protocol layers talking

Posted by gs...@apache.org.
PROTON-749: Server transport autodetect:
- Defer layer initialisation until first send/receive
- Move layer initialisation entirely to transport
- Server transports will now autodetect the client protocol layers
  talking to them and configure themselves automatically
- There are still some hacks in here to make SSL work.
  It's not obvious why we need these hacks.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1b2be03c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1b2be03c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1b2be03c

Branch: refs/heads/examples
Commit: 1b2be03c748ef5a57cf181f8373b9b6e8f8cfd22
Parents: 9c9872b
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Aug 20 23:39:34 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Nov 19 17:50:21 2014 -0500

----------------------------------------------------------------------
 proton-c/CMakeLists.txt               |   1 +
 proton-c/src/engine/engine-internal.h |   8 +-
 proton-c/src/sasl/sasl-internal.h     |   2 +
 proton-c/src/sasl/sasl.c              |  55 +++----
 proton-c/src/ssl/openssl.c            | 112 +------------
 proton-c/src/ssl/ssl-internal.h       |   2 +
 proton-c/src/ssl/ssl_stub.c           |  17 +-
 proton-c/src/transport/autodetect.c   | 135 ++++++++++++++++
 proton-c/src/transport/autodetect.h   |  40 +++++
 proton-c/src/transport/transport.c    | 249 +++++++++++++++++++++++------
 proton-c/src/windows/schannel.c       | 113 +------------
 11 files changed, 428 insertions(+), 306 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index 6b6b730..b09e1c4 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -297,6 +297,7 @@ set (qpid-proton-core
   src/dispatcher/dispatcher.c
   src/engine/engine.c
   src/events/event.c
+  src/transport/autodetect.c
   src/transport/transport.c
   src/message/message.c
   src/sasl/sasl.c

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index ab66ef5..f53e88b 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -107,6 +107,9 @@ typedef struct pn_io_layer_t {
 } pn_io_layer_t;
 
 extern const pn_io_layer_t pni_passthru_layer;
+extern const pn_io_layer_t ssl_layer;
+extern const pn_io_layer_t sasl_header_layer;
+extern const pn_io_layer_t sasl_write_header_layer;
 
 typedef struct pni_sasl_t pni_sasl_t;
 typedef struct pni_ssl_t pni_ssl_t;
@@ -131,10 +134,7 @@ struct pn_transport_t {
   pn_condition_t condition;
   pn_error_t *error;
 
-#define PN_IO_SSL  0
-#define PN_IO_SASL 1
-#define PN_IO_AMQP 2
-#define PN_IO_LAYER_CT (PN_IO_AMQP+1)
+#define PN_IO_LAYER_CT 3
   const pn_io_layer_t *io_layers[PN_IO_LAYER_CT];
 
   /* dead remote detection */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/sasl/sasl-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl-internal.h b/proton-c/src/sasl/sasl-internal.h
index 15fd0b1..ca4c80e 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -57,4 +57,6 @@ void pn_sasl_trace(pn_transport_t *transport, pn_trace_t trace);
  */
 void pn_sasl_free(pn_transport_t *transport);
 
+bool pn_sasl_skipping_allowed(pn_transport_t *transport);
+
 #endif /* sasl-internal.h */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 90adcf6..1ee8f9b 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -32,6 +32,7 @@
 #include "engine/engine-internal.h"
 #include "dispatcher/dispatcher.h"
 #include "util.h"
+#include "transport/autodetect.h"
 
 
 struct pni_sasl_t {
@@ -68,7 +69,7 @@ static ssize_t pn_input_read_sasl(pn_transport_t *transport, unsigned int layer,
 static ssize_t pn_output_write_sasl_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t size);
 static ssize_t pn_output_write_sasl(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
 
-const pn_io_layer_t sasl_headers_layer = {
+const pn_io_layer_t sasl_header_layer = {
     pn_input_read_sasl_header,
     pn_output_write_sasl_header,
     NULL,
@@ -118,7 +119,6 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
     sasl->output_bypass = false;
 
     transport->sasl = sasl;
-    transport->io_layers[PN_IO_SASL] = &sasl_headers_layer;
   }
 
   // The actual external pn_sasl_t pointer is a pointer to its enclosing pn_transport_t
@@ -204,6 +204,11 @@ void pn_sasl_allow_skip(pn_sasl_t *sasl0, bool allow)
     sasl->allow_skip = allow;
 }
 
+bool pn_sasl_skipping_allowed(pn_transport_t *transport)
+{
+  return transport && transport->sasl && transport->sasl->allow_skip;
+}
+
 void pn_sasl_plain(pn_sasl_t *sasl0, const char *username, const char *password)
 {
   pni_sasl_t *sasl = get_sasl_internal(sasl0);
@@ -441,45 +446,33 @@ int pn_do_outcome(pn_dispatcher_t *disp)
 }
 
 #define SASL_HEADER ("AMQP\x03\x01\x00\x00")
-#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
 #define SASL_HEADER_LEN 8
 
 static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pni_sasl_t *sasl = transport->sasl;
-  if (available > 0) {
-    if (available < SASL_HEADER_LEN) {
-      if (memcmp(bytes, SASL_HEADER, available) == 0 ||
-          memcmp(bytes, AMQP_HEADER, available) == 0)
-        return 0;
+  bool eos = pn_transport_capacity(transport)==PN_EOS;
+  pni_protocol_type_t protocol = pni_sniff_header(bytes, available);
+  switch (protocol) {
+  case PNI_PROTOCOL_AMQP_SASL:
+    if (transport->io_layers[layer] == &sasl_read_header_layer) {
+        transport->io_layers[layer] = &sasl_layer;
     } else {
-      if (memcmp(bytes, SASL_HEADER, SASL_HEADER_LEN) == 0) {
-        if (transport->io_layers[layer] == &sasl_read_header_layer) {
-          transport->io_layers[layer] = &sasl_layer;
-        } else {
-          transport->io_layers[layer] = &sasl_write_header_layer;
-        }
-        if (sasl->disp->trace & PN_TRACE_FRM)
-          pn_transport_logf(transport, "  <- %s", "SASL");
-        return SASL_HEADER_LEN;
-      }
-      if (memcmp(bytes, AMQP_HEADER, SASL_HEADER_LEN) == 0) {
-        if (sasl->allow_skip) {
-          sasl->outcome = PN_SASL_SKIPPED;
-          transport->io_layers[layer] = &pni_passthru_layer;
-          return pni_passthru_layer.process_input(transport, layer, bytes, available);
-        } else {
-            pn_do_error(transport, "amqp:connection:policy-error",
-                        "Client skipped SASL exchange - forbidden");
-            return PN_EOS;
-        }
-      }
+        transport->io_layers[layer] = &sasl_write_header_layer;
     }
+    if (transport->sasl->disp->trace & PN_TRACE_FRM)
+        pn_transport_logf(transport, "  <- %s", "SASL");
+    return SASL_HEADER_LEN;
+  case PNI_PROTOCOL_INSUFFICIENT:
+    if (!eos) return 0;
+    /* Fallthru */
+  default:
+    break;
   }
   char quoted[1024];
   pn_quote_data(quoted, 1024, bytes, available);
   pn_do_error(transport, "amqp:connection:framing-error",
-              "%s header mismatch: '%s'", "SASL", quoted);
+              "%s header mismatch: %s ['%s']%s", "SASL", pni_protocol_name(protocol), quoted,
+              !eos ? "" : " (connection aborted)");
   return PN_EOS;
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index 41e36b5..0562cae 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -60,7 +60,6 @@
 static int ssl_initialized;
 static int ssl_ex_data_index;
 
-typedef enum { UNKNOWN_CONNECTION, SSL_CONNECTION, CLEAR_CONNECTION } connection_mode_t;
 typedef struct pn_ssl_session_t pn_ssl_session_t;
 
 struct pn_ssl_domain_t {
@@ -145,11 +144,8 @@ struct pn_ssl_session_t {
 static int keyfile_pw_cb(char *buf, int size, int rwflag, void *userdata);
 static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
 static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
-static ssize_t process_input_unknown( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
-static ssize_t process_output_unknown( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
 static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
 static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
-static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
 static int init_ssl_socket(pn_transport_t *, pni_ssl_t *);
 static void release_ssl_socket( pni_ssl_t * );
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
@@ -682,13 +678,6 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
   return 0;
 }
 
-const pn_io_layer_t unknown_layer = {
-    process_input_unknown,
-    process_output_unknown,
-    NULL,
-    NULL
-};
-
 const pn_io_layer_t ssl_layer = {
     process_input_ssl,
     process_output_ssl,
@@ -725,11 +714,6 @@ int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char *session_id)
 
   ssl->domain = domain;
   domain->ref_count++;
-  if (domain->allow_unsecured) {
-    transport->io_layers[PN_IO_SSL] = &unknown_layer;
-  } else {
-    transport->io_layers[PN_IO_SSL] = &ssl_layer;
-  }
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
 
@@ -748,6 +732,10 @@ int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
   return 0;
 }
 
+bool pn_ssl_allow_unsecured(pn_transport_t *transport)
+{
+  return transport && transport->ssl && transport->ssl->domain && transport->ssl->domain->allow_unsecured;
+}
 
 bool pn_ssl_get_cipher_name(pn_ssl_t *ssl0, char *buffer, size_t size )
 {
@@ -862,13 +850,6 @@ static int start_ssl_shutdown(pn_transport_t *transport)
 }
 
 
-
-static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
-{
-  transport->io_layers[layer] = &ssl_layer;
-  return 0;
-}
-
 //////// SSL Connections
 
 
@@ -1213,91 +1194,6 @@ static void release_ssl_socket(pni_ssl_t *ssl)
 }
 
 
-static int setup_cleartext_connection(pn_transport_t *transport, unsigned int layer)
-{
-  transport->io_layers[layer] = &pni_passthru_layer;
-  return 0;
-}
-
-
-// until we determine if the client is using SSL or not:
-
-static ssize_t process_input_unknown(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
-{
-  switch (check_for_ssl_connection( input_data, len )) {
-  case SSL_CONNECTION:
-    ssl_log( transport, "SSL connection detected.");
-    setup_ssl_connection(transport, layer);
-    break;
-  case CLEAR_CONNECTION:
-    ssl_log( transport, "Cleartext connection detected.");
-    setup_cleartext_connection(transport, layer);
-    break;
-  default:
-    return 0;
-  }
-  return transport->io_layers[layer]->process_input(transport, layer, input_data, len );
-}
-
-static ssize_t process_output_unknown(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
-{
-  // do not do output until we know if SSL is used or not
-  return 0;
-}
-
-static connection_mode_t check_for_ssl_connection( const char *data, size_t len )
-{
-  if (len >= 5) {
-    const unsigned char *buf = (unsigned char *)data;
-    /*
-     * SSLv2 Client Hello format
-     * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
-     *
-     * Bytes 0-1: RECORD-LENGTH
-     * Byte    2: MSG-CLIENT-HELLO (1)
-     * Byte    3: CLIENT-VERSION-MSB
-     * Byte    4: CLIENT-VERSION-LSB
-     *
-     * Allowed versions:
-     * 2.0 - SSLv2
-     * 3.0 - SSLv3
-     * 3.1 - TLS 1.0
-     * 3.2 - TLS 1.1
-     * 3.3 - TLS 1.2
-     *
-     * The version sent in the Client-Hello is the latest version supported by
-     * the client. NSS may send version 3.x in an SSLv2 header for
-     * maximum compatibility.
-     */
-    int isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
-      ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
-       (buf[3] == 2 && buf[4] == 0));     // SSL 2
-
-    /*
-     * SSLv3/TLS Client Hello format
-     * RFC 2246
-     *
-     * Byte    0: ContentType (handshake - 22)
-     * Bytes 1-2: ProtocolVersion {major, minor}
-     *
-     * Allowed versions:
-     * 3.0 - SSLv3
-     * 3.1 - TLS 1.0
-     * 3.2 - TLS 1.1
-     * 3.3 - TLS 1.2
-     */
-    int isSSL3Handshake = buf[0] == 22 &&  // handshake
-      (buf[1] == 3 && buf[2] <= 3);       // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
-
-    if (isSSL2Handshake || isSSL3Handshake) {
-      return SSL_CONNECTION;
-    } else {
-      return CLEAR_CONNECTION;
-    }
-  }
-  return UNKNOWN_CONNECTION;
-}
-
 void pn_ssl_trace(pn_transport_t *transport, pn_trace_t trace)
 {
   transport->ssl->trace = trace;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/ssl/ssl-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/ssl-internal.h b/proton-c/src/ssl/ssl-internal.h
index f1cd637..9430af0 100644
--- a/proton-c/src/ssl/ssl-internal.h
+++ b/proton-c/src/ssl/ssl-internal.h
@@ -33,4 +33,6 @@ void pn_ssl_free(pn_transport_t *transport);
 
 void pn_ssl_trace(pn_transport_t *transport, pn_trace_t trace);
 
+bool pn_ssl_allow_unsecured(pn_transport_t *transport);
+
 #endif /* ssl-internal.h */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/ssl/ssl_stub.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/ssl_stub.c b/proton-c/src/ssl/ssl_stub.c
index a5fce02..cea5dc4 100644
--- a/proton-c/src/ssl/ssl_stub.c
+++ b/proton-c/src/ssl/ssl_stub.c
@@ -22,6 +22,7 @@
 #include <proton/ssl.h>
 #include <proton/error.h>
 #include <proton/transport.h>
+#include "engine/engine-internal.h"
 
 
 /** @file
@@ -55,16 +56,23 @@ void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace)
 {
 }
 
-ssize_t pn_ssl_input(pn_ssl_t *ssl, const char *bytes, size_t available)
+ssize_t pn_ssl_input(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available)
 {
   return PN_EOS;
 }
 
-ssize_t pn_ssl_output(pn_ssl_t *ssl, char *buffer, size_t max_size)
+ssize_t pn_ssl_output(pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_size)
 {
   return PN_EOS;
 }
 
+const pn_io_layer_t ssl_layer = {
+    pn_ssl_input,
+    pn_ssl_output,
+    NULL,
+    NULL
+};
+
 bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *buffer, size_t size)
 {
   return false;
@@ -110,6 +118,11 @@ int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
   return -1;
 }
 
+bool pn_ssl_allow_unsecured(pn_ssl_t *ssl)
+{
+  return true;
+}
+
 pn_ssl_resume_status_t pn_ssl_resume_status( pn_ssl_t *s )
 {
   return PN_SSL_RESUME_UNKNOWN;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/transport/autodetect.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/autodetect.c b/proton-c/src/transport/autodetect.c
new file mode 100644
index 0000000..00f6d98
--- /dev/null
+++ b/proton-c/src/transport/autodetect.c
@@ -0,0 +1,135 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "autodetect.h"
+
+#define SASL_HEADER ("AMQP\x03\x01\x00\x00")
+#define SSL_HEADER  ("AMQP\x02\x01\x00\x00")
+#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
+
+#define SASL_HEADER_LEN 8
+
+/*
+ * SSLv2 Client Hello format
+ * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
+ *
+ * Bytes 0-1: RECORD-LENGTH
+ * Byte    2: MSG-CLIENT-HELLO (1)
+ * Byte    3: CLIENT-VERSION-MSB
+ * Byte    4: CLIENT-VERSION-LSB
+ *
+ * Allowed versions:
+ * 2.0 - SSLv2
+ * 3.0 - SSLv3
+ * 3.1 - TLS 1.0
+ * 3.2 - TLS 1.1
+ * 3.3 - TLS 1.2
+ *
+ * The version sent in the Client-Hello is the latest version supported by
+ * the client. NSS may send version 3.x in an SSLv2 header for
+ * maximum compatibility.
+ */
+/*
+ * SSLv3/TLS Client Hello format
+ * RFC 2246
+ *
+ * Byte    0: ContentType (handshake - 22)
+ * Bytes 1-2: ProtocolVersion {major, minor}
+ *
+ * Allowed versions:
+ * 3.0 - SSLv3
+ * 3.1 - TLS 1.0
+ * 3.2 - TLS 1.1
+ * 3.3 - TLS 1.2
+ */
+/*
+ * AMQP 1.0 Header
+ *
+ * Bytes 0-3: "AMQP"
+ * Byte    4: 0==AMQP, 2==SSL, 3==SASL
+ * Byte    5: 1
+ * Bytes 6-7: 0
+ */
+/*
+ * AMQP Pre 1.0 Header
+ *
+ * Bytes 0-3: 'AMQP'
+ * Byte    4: 1
+ * Byte    5: 1
+ * Byte    6: 0 (major version)
+ * Byte    7: Minor version
+ */
+pni_protocol_type_t pni_sniff_header(const char *buf, size_t len)
+{
+  if (len < 3) return PNI_PROTOCOL_INSUFFICIENT;
+  bool isSSL3Handshake = buf[0]==22 &&            // handshake
+                         buf[1]==3  && buf[2]<=3; // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
+  if (isSSL3Handshake) return PNI_PROTOCOL_SSL;
+
+  bool isFirst3AMQP = buf[0]=='A' && buf[1]=='M' && buf[2]=='Q';
+  bool isFirst3SSL2CLientHello = buf[2]==1;       // Client Hello
+  if (!isFirst3AMQP && !isFirst3SSL2CLientHello) return PNI_PROTOCOL_UNKNOWN;
+
+
+  if (len < 4) return PNI_PROTOCOL_INSUFFICIENT;
+  bool isAMQP = isFirst3AMQP && buf[3]=='P';
+  bool isFirst4SSL2ClientHello = isFirst3SSL2CLientHello && (buf[3]==2 || buf[3]==3);
+  if (!isAMQP && !isFirst4SSL2ClientHello) return PNI_PROTOCOL_UNKNOWN;
+
+  if (len < 5) return PNI_PROTOCOL_INSUFFICIENT;
+  bool isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
+      ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
+       (buf[3] == 2 && buf[4] == 0));     // SSL 2
+  if (isSSL2Handshake) return PNI_PROTOCOL_SSL;
+
+  bool isFirst5OldAMQP = isAMQP && buf[4]==1;
+  bool isFirst5AMQP = isAMQP && (buf[4]==0 || buf[4]==2 || buf[4]==3);
+  if (!isFirst5AMQP && !isFirst5OldAMQP) return PNI_PROTOCOL_UNKNOWN;
+
+  if (len < 6) return PNI_PROTOCOL_INSUFFICIENT;
+
+  // Both old and new versions of AMQP have 1 in byte 5
+  if (buf[5]!=1) return PNI_PROTOCOL_UNKNOWN;
+
+  // From here on it must be some sort of AMQP
+  if (len < 8) return PNI_PROTOCOL_INSUFFICIENT;
+  if (buf[6]==0 && buf[7]==0) {
+    // AM<QP 1.0
+      if (buf[4]==0) return PNI_PROTOCOL_AMQP1;
+      if (buf[4]==2) return PNI_PROTOCOL_AMQP_SSL;
+      if (buf[4]==3) return PNI_PROTOCOL_AMQP_SASL;
+  }
+  return PNI_PROTOCOL_AMQP_OTHER;
+}
+
+const char* pni_protocol_name(pni_protocol_type_t p)
+{
+  static const char* names[] = {
+  "Insufficient data to determine protocol",
+  "Unknown protocol",
+  "SSL/TLS connection",
+  "AMQP TLS layer",
+  "AMQP SASL layer",
+  "AMQP 1.0 layer",
+  "Pre standard AMQP connection"
+  };
+  return names[p];
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/transport/autodetect.h
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/autodetect.h b/proton-c/src/transport/autodetect.h
new file mode 100644
index 0000000..12cb7d8
--- /dev/null
+++ b/proton-c/src/transport/autodetect.h
@@ -0,0 +1,40 @@
+#ifndef PROTON_AUTODETECT_H
+#define PROTON_AUTODETECT_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/types.h"
+
+typedef enum {
+  PNI_PROTOCOL_INSUFFICIENT,
+  PNI_PROTOCOL_UNKNOWN,
+  PNI_PROTOCOL_SSL,
+  PNI_PROTOCOL_AMQP_SSL,
+  PNI_PROTOCOL_AMQP_SASL,
+  PNI_PROTOCOL_AMQP1,
+  PNI_PROTOCOL_AMQP_OTHER
+} pni_protocol_type_t;
+
+pni_protocol_type_t pni_sniff_header(const char *data, size_t len);
+const char* pni_protocol_name(pni_protocol_type_t p);
+
+#endif

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index 2d5f93a..67fd3ab 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -19,22 +19,25 @@
  *
  */
 
+#include "proton/framing.h"
+
 #include "engine/engine-internal.h"
-#include <stdlib.h>
-#include <string.h>
-#include <proton/framing.h>
+#include "sasl/sasl-internal.h"
+#include "ssl/ssl-internal.h"
+
+#include "autodetect.h"
 #include "protocol.h"
 #include "dispatch_actions.h"
+#include "proton/event.h"
+#include "platform.h"
+#include "platform_fmt.h"
 
+#include <stdlib.h>
+#include <string.h>
 #include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
 
-#include "sasl/sasl-internal.h"
-#include "ssl/ssl-internal.h"
-#include "platform.h"
-#include "platform_fmt.h"
-
 static ssize_t transport_consume(pn_transport_t *transport);
 
 // delivery buffers
@@ -92,26 +95,25 @@ void pn_delivery_map_clear(pn_delivery_map_t *dm)
   dm->next = 0;
 }
 
+static void pni_default_tracer(pn_transport_t *transport, const char *message)
+{
+  fprintf(stderr, "[%p]:%s\n", (void *) transport, message);
+}
+
 static ssize_t pn_io_layer_input_passthru(pn_transport_t *, unsigned int, const char *, size_t );
 static ssize_t pn_io_layer_output_passthru(pn_transport_t *, unsigned int, char *, size_t );
 
+static ssize_t pn_io_layer_input_setup(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
+static ssize_t pn_io_layer_output_setup(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
+
 static ssize_t pn_input_read_amqp_header(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
 static ssize_t pn_input_read_amqp(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
 static ssize_t pn_output_write_amqp_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
 static ssize_t pn_output_write_amqp(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
 static pn_timestamp_t pn_tick_amqp(pn_transport_t *transport, unsigned int layer, pn_timestamp_t now);
 
-static void pni_default_tracer(pn_transport_t *transport, const char *message)
-{
-  fprintf(stderr, "[%p]:%s\n", (void *) transport, message);
-}
-
-const pn_io_layer_t pni_passthru_layer = {
-    pn_io_layer_input_passthru,
-    pn_io_layer_output_passthru,
-    NULL,
-    NULL
-};
+static ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
+static ssize_t pn_io_layer_output_null(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
 
 const pn_io_layer_t amqp_header_layer = {
     pn_input_read_amqp_header,
@@ -141,6 +143,158 @@ const pn_io_layer_t amqp_layer = {
     NULL
 };
 
+const pn_io_layer_t pni_setup_layer = {
+    pn_io_layer_input_setup,
+    pn_io_layer_output_setup,
+    NULL,
+    NULL
+};
+
+const pn_io_layer_t pni_autodetect_layer = {
+    pn_io_layer_input_autodetect,
+    pn_io_layer_output_null,
+    NULL,
+    NULL
+};
+
+const pn_io_layer_t pni_passthru_layer = {
+    pn_io_layer_input_passthru,
+    pn_io_layer_output_passthru,
+    NULL,
+    NULL
+};
+
+/* Set up the transport protocol layers depending on what is configured */
+static void pn_io_layer_setup(pn_transport_t *transport, unsigned int layer)
+{
+  assert(layer == 0);
+  // Figure out if we are server or not
+  if (transport->server)
+  {
+    // XXX: This is currently a large hack to work around the SSL
+    // code not handling a connection error before being set up fully
+    if (transport->ssl && pn_ssl_allow_unsecured(transport)) {
+      transport->io_layers[layer++] = &pni_autodetect_layer;
+      return;
+    }
+  }
+  if (transport->ssl) {
+    transport->io_layers[layer++] = &ssl_layer;
+  }
+  if (transport->server) {
+    transport->io_layers[layer++] = &pni_autodetect_layer;
+    return;
+  }
+  if (transport->sasl) {
+    transport->io_layers[layer++] = &sasl_header_layer;
+  }
+  transport->io_layers[layer++] = &amqp_header_layer;
+}
+
+ssize_t pn_io_layer_input_setup(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available)
+{
+  pn_io_layer_setup(transport, layer);
+  return transport->io_layers[layer]->process_input(transport, layer, bytes, available);
+}
+
+ssize_t pn_io_layer_output_setup(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available)
+{
+  pn_io_layer_setup(transport, layer);
+  return transport->io_layers[layer]->process_output(transport, layer, bytes, available);
+}
+
+// Autodetect the layer by reading the protocol header
+ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available)
+{
+  const char* error;
+  bool eos = pn_transport_capacity(transport)==PN_EOS;
+  if (eos && available==0) {
+    pn_do_error(transport, "amqp:connection:framing-error", "No valid protocol header found");
+    return PN_EOS;
+  }
+  pni_protocol_type_t protocol = pni_sniff_header(bytes, available);
+  if (transport->disp->trace & PN_TRACE_DRV)
+      pn_transport_logf(transport, "%s detected", pni_protocol_name(protocol));
+  switch (protocol) {
+  case PNI_PROTOCOL_SSL:
+    if (!transport->ssl) {
+      pn_ssl(transport);
+    }
+    transport->io_layers[layer] = &ssl_layer;
+    transport->io_layers[layer+1] = &pni_autodetect_layer;
+    return ssl_layer.process_input(transport, layer, bytes, available);
+  case PNI_PROTOCOL_AMQP_SSL:
+    if (!transport->ssl) {
+      pn_ssl(transport);
+    }
+    transport->io_layers[layer] = &ssl_layer;
+    transport->io_layers[layer+1] = &pni_autodetect_layer;
+    return 8;
+  case PNI_PROTOCOL_AMQP_SASL:
+    if (!transport->sasl) {
+      pn_sasl(transport);
+    }
+    transport->io_layers[layer] = &sasl_write_header_layer;
+    transport->io_layers[layer+1] = &pni_autodetect_layer;
+    if (transport->disp->trace & PN_TRACE_FRM)
+        pn_transport_logf(transport, "  <- %s", "SASL");
+    return 8;
+  case PNI_PROTOCOL_AMQP1:
+    if (transport->sasl && pn_sasl_state((pn_sasl_t *)transport)==PN_SASL_IDLE) {
+      if (pn_sasl_skipping_allowed(transport)) {
+        pn_sasl_done((pn_sasl_t *)transport, PN_SASL_SKIPPED);
+      } else {
+        pn_do_error(transport, "amqp:connection:policy-error",
+                    "Client skipped SASL exchange - forbidden");
+        return PN_EOS;
+      }
+    }
+    transport->io_layers[layer] = &amqp_write_header_layer;
+    if (transport->disp->trace & PN_TRACE_FRM)
+        pn_transport_logf(transport, "  <- %s", "AMQP");
+    return 8;
+  case PNI_PROTOCOL_INSUFFICIENT:
+    if (!eos) return 0;
+    error = "End of input stream before protocol detection";
+    break;
+  case PNI_PROTOCOL_AMQP_OTHER:
+    error = "Incompatible AMQP connection detected";
+    break;
+  case PNI_PROTOCOL_UNKNOWN:
+  default:
+    error = "Unknown protocol detected";
+    break;
+  }
+  char quoted[1024];
+  pn_quote_data(quoted, 1024, bytes, available);
+  pn_do_error(transport, "amqp:connection:framing-error",
+              "%s: '%s'%s", error, quoted,
+              !eos ? "" : " (connection aborted)");
+  return PN_EOS;
+}
+
+// We don't know what the output should be - do nothing
+ssize_t pn_io_layer_output_null(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available)
+{
+  return 0;
+}
+
+/** Pass through input handler */
+ssize_t pn_io_layer_input_passthru(pn_transport_t *transport, unsigned int layer, const char *data, size_t available)
+{
+    if (layer+1<PN_IO_LAYER_CT)
+        return transport->io_layers[layer+1]->process_input(transport, layer+1, data, available);
+    return PN_EOS;
+}
+
+/** Pass through output handler */
+ssize_t pn_io_layer_output_passthru(pn_transport_t *transport, unsigned int layer, char *data, size_t available)
+{
+    if (layer+1<PN_IO_LAYER_CT)
+        return transport->io_layers[layer+1]->process_output(transport, layer+1, data, available);
+    return PN_EOS;
+}
+
 static void pn_transport_initialize(void *object)
 {
   pn_transport_t *transport = (pn_transport_t *)object;
@@ -157,9 +311,11 @@ static void pn_transport_initialize(void *object)
   transport->connection = NULL;
 
   for (int layer=0; layer<PN_IO_LAYER_CT; ++layer) {
-    transport->io_layers[layer] = &pni_passthru_layer;
+    transport->io_layers[layer] = NULL;
   }
-  transport->io_layers[PN_IO_AMQP] = &amqp_header_layer;
+
+  // Defer setting up the layers until the first data arrives or is sent
+  transport->io_layers[0] = &pni_setup_layer;
 
   transport->open_sent = false;
   transport->open_rcvd = false;
@@ -1127,20 +1283,12 @@ static ssize_t transport_consume(pn_transport_t *transport)
   return consumed;
 }
 
-#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
-
 static ssize_t pn_input_read_amqp_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  unsigned readable = pn_min(8, available);
   bool eos = pn_transport_capacity(transport)==PN_EOS;
-  if (memcmp(bytes, AMQP_HEADER, readable) || (readable<8 && eos) ) {
-    char quoted[1024];
-    pn_quote_data(quoted, 1024, bytes, available);
-    pn_do_error(transport, "amqp:connection:framing-error",
-                "%s header mismatch: '%s'%s", "AMQP", quoted,
-                !eos ? "" : " (connection aborted)");
-    return PN_EOS;
-  } else if (readable==8) {
+  pni_protocol_type_t protocol = pni_sniff_header(bytes, available);
+  switch (protocol) {
+  case PNI_PROTOCOL_AMQP1:
     if (transport->io_layers[layer] == &amqp_read_header_layer) {
       transport->io_layers[layer] = &amqp_layer;
     } else {
@@ -1149,8 +1297,18 @@ static ssize_t pn_input_read_amqp_header(pn_transport_t* transport, unsigned int
     if (transport->disp->trace & PN_TRACE_FRM)
       pn_transport_logf(transport, "  <- %s", "AMQP");
     return 8;
+  case PNI_PROTOCOL_INSUFFICIENT:
+    if (!eos) return 0;
+    /* Fallthru */
+  default:
+    break;
   }
-  return 0;
+  char quoted[1024];
+  pn_quote_data(quoted, 1024, bytes, available);
+  pn_do_error(transport, "amqp:connection:framing-error",
+              "%s header mismatch: %s ['%s']%s", "AMQP", pni_protocol_name(protocol), quoted,
+              !eos ? "" : " (connection aborted)");
+  return PN_EOS;
 }
 
 static ssize_t pn_input_read_amqp(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
@@ -1842,6 +2000,8 @@ int pn_process(pn_transport_t *transport)
   return 0;
 }
 
+#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
+
 static ssize_t pn_output_write_amqp_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
 {
   if (transport->disp->trace & PN_TRACE_FRM)
@@ -2061,7 +2221,7 @@ pn_timestamp_t pn_transport_tick(pn_transport_t *transport, pn_timestamp_t now)
 {
   pn_timestamp_t r = 0;
   for (int i = 0; i<PN_IO_LAYER_CT; ++i) {
-    if (transport->io_layers[i]->process_tick)
+    if (transport->io_layers[i] && transport->io_layers[i]->process_tick)
       r = pn_timestamp_min(r, transport->io_layers[i]->process_tick(transport, i, now));
   }
   return r;
@@ -2081,24 +2241,6 @@ uint64_t pn_transport_get_frames_input(const pn_transport_t *transport)
   return 0;
 }
 
-/** Pass through input handler */
-ssize_t pn_io_layer_input_passthru(pn_transport_t *transport, unsigned int layer, const char *data, size_t available)
-{
-  if (layer+1<PN_IO_LAYER_CT)
-    return transport->io_layers[layer+1]->process_input(transport, layer+1, data, available);
-  return PN_EOS;
-}
-
-/** Pass through output handler */
-ssize_t pn_io_layer_output_passthru(pn_transport_t *transport, unsigned int layer, char *data, size_t available)
-{
-  if (layer+1<PN_IO_LAYER_CT)
-      return transport->io_layers[layer+1]->process_output(transport, layer+1, data, available);
-  return PN_EOS;
-}
-
-///
-
 // input
 ssize_t pn_transport_capacity(pn_transport_t *transport)  /* <0 == done */
 {
@@ -2252,7 +2394,8 @@ bool pn_transport_quiesced(pn_transport_t *transport)
   else if (pending > 0) return false;
   // no pending at transport, but check if data is buffered in I/O layers
   for (int layer = 0; layer<PN_IO_LAYER_CT; ++layer) {
-    if (transport->io_layers[layer]->buffered_output &&
+    if (transport->io_layers[layer] &&
+        transport->io_layers[layer]->buffered_output &&
         transport->io_layers[layer]->buffered_output( transport ))
       return false;
   }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b2be03c/proton-c/src/windows/schannel.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/windows/schannel.c
index 231349c..e7ef5fd 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/windows/schannel.c
@@ -148,11 +148,8 @@ struct pn_ssl_session_t {
 
 static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
 static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
-static ssize_t process_input_unknown( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
-static ssize_t process_output_unknown( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
 static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
 static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
-static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
 static void ssl_session_free( pn_ssl_session_t *);
 static size_t buffered_output( pn_transport_t *transport );
@@ -360,13 +357,6 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
   return 0;
 }
 
-const pn_io_layer_t unknown_layer = {
-    process_input_unknown,
-    process_output_unknown,
-    NULL,
-    NULL
-};
-
 const pn_io_layer_t ssl_layer = {
     process_input_ssl,
     process_output_ssl,
@@ -404,12 +394,6 @@ int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char *session_id)
 
   ssl->domain = domain;
   domain->ref_count++;
-  if (domain->allow_unsecured) {
-    transport->io_layers[PN_IO_SSL] = &unknown_layer;
-  }
-  else {
-    transport->io_layers[PN_IO_SSL] = &ssl_layer;
-  }
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
 
@@ -439,6 +423,11 @@ int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
 }
 
 
+bool pn_ssl_allow_unsecured(pn_transport_t *transport)
+{
+  return transport && transport->ssl && transport->ssl->domain && transport->ssl->domain->allow_unsecured;
+}
+
 bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *buffer, size_t size )
 {
   *buffer = '\0';
@@ -893,12 +882,6 @@ static void start_ssl_shutdown(pn_transport_t *transport)
   ssl_handshake(transport);
 }
 
-static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
-{
-  transport->io_layers[layer] = &ssl_layer;
-  return 0;
-}
-
 static void rewind_sc_inbuf(pni_ssl_t *ssl)
 {
   // Decrypted bytes have been drained or double buffered.  Prepare for the next SSL Record.
@@ -1270,92 +1253,6 @@ static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer
 }
 
 
-static int setup_cleartext_connection(pn_transport_t *transport, unsigned int layer)
-{
-  transport->io_layers[layer] = &pni_passthru_layer;
-  return 0;
-}
-
-
-// until we determine if the client is using SSL or not:
-
-static ssize_t process_input_unknown(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
-{
-  pn_ssl_t *ssl = transport->ssl;
-  switch (check_for_ssl_connection( input_data, len )) {
-  case SSL_CONNECTION:
-	ssl_log(ssl, "SSL connection detected.\n");
-    setup_ssl_connection(transport, layer);
-	break;
-  case CLEAR_CONNECTION:
-	ssl_log(ssl, "Cleartext connection detected.\n");
-    setup_cleartext_connection(transport, layer);
-	break;
-  default:
-    return 0;
-  }
-  return transport->io_layers[layer]->process_input(transport, layer, input_data, len);
-}
-
-static ssize_t process_output_unknown(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
-{
-  // do not do output until we know if SSL is used or not
-  return 0;
-}
-
-static connection_mode_t check_for_ssl_connection( const char *data, size_t len )
-{
-  if (len >= 5) {
-    const unsigned char *buf = (unsigned char *)data;
-    /*
-     * SSLv2 Client Hello format
-     * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
-     *
-     * Bytes 0-1: RECORD-LENGTH
-     * Byte    2: MSG-CLIENT-HELLO (1)
-     * Byte    3: CLIENT-VERSION-MSB
-     * Byte    4: CLIENT-VERSION-LSB
-     *
-     * Allowed versions:
-     * 2.0 - SSLv2
-     * 3.0 - SSLv3
-     * 3.1 - TLS 1.0
-     * 3.2 - TLS 1.1
-     * 3.3 - TLS 1.2
-     *
-     * The version sent in the Client-Hello is the latest version supported by
-     * the client. NSS may send version 3.x in an SSLv2 header for
-     * maximum compatibility.
-     */
-    int isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
-      ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
-       (buf[3] == 2 && buf[4] == 0));     // SSL 2
-
-    /*
-     * SSLv3/TLS Client Hello format
-     * RFC 2246
-     *
-     * Byte    0: ContentType (handshake - 22)
-     * Bytes 1-2: ProtocolVersion {major, minor}
-     *
-     * Allowed versions:
-     * 3.0 - SSLv3
-     * 3.1 - TLS 1.0
-     * 3.2 - TLS 1.1
-     * 3.3 - TLS 1.2
-     */
-    int isSSL3Handshake = buf[0] == 22 &&  // handshake
-      (buf[1] == 3 && buf[2] <= 3);       // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
-
-    if (isSSL2Handshake || isSSL3Handshake) {
-      return SSL_CONNECTION;
-    } else {
-      return CLEAR_CONNECTION;
-    }
-  }
-  return UNKNOWN_CONNECTION;
-}
-
 static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
   return PN_EOS;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[11/35] qpid-proton git commit: NO-JIRA: Fix how Perl uses the utils module.

Posted by gs...@apache.org.
NO-JIRA: Fix how Perl uses the utils module.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/02f1c577
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/02f1c577
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/02f1c577

Branch: refs/heads/examples
Commit: 02f1c5772128a4ca1c0d176f98e4b425a88b5e71
Parents: 66150aa
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Tue Nov 18 11:43:43 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Tue Nov 18 17:13:31 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/perl/lib/qpid/proton/Message.pm | 2 +-
 proton-c/bindings/perl/lib/qpid/proton/utils.pm   | 2 +-
 proton-c/bindings/perl/lib/qpid_proton.pm         | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/02f1c577/proton-c/bindings/perl/lib/qpid/proton/Message.pm
----------------------------------------------------------------------
diff --git a/proton-c/bindings/perl/lib/qpid/proton/Message.pm b/proton-c/bindings/perl/lib/qpid/proton/Message.pm
index 49aeccd..a46717a 100644
--- a/proton-c/bindings/perl/lib/qpid/proton/Message.pm
+++ b/proton-c/bindings/perl/lib/qpid/proton/Message.pm
@@ -448,7 +448,7 @@ sub set_body {
     # if no body type was defined, then attempt to infer what it should
     # be, which is going to be a best guess
     if (!defined($body_type)) {
-        if (qpid::proton::is_num($body)) {
+        if (qpid::proton::utils::is_num($body)) {
             if (qpid::proton::is_float($body)) {
                 $body_type = qpid::proton::FLOAT;
             } else {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/02f1c577/proton-c/bindings/perl/lib/qpid/proton/utils.pm
----------------------------------------------------------------------
diff --git a/proton-c/bindings/perl/lib/qpid/proton/utils.pm b/proton-c/bindings/perl/lib/qpid/proton/utils.pm
index 75af498..5652535 100644
--- a/proton-c/bindings/perl/lib/qpid/proton/utils.pm
+++ b/proton-c/bindings/perl/lib/qpid/proton/utils.pm
@@ -17,7 +17,7 @@
 # under the License.
 #
 
-package qpid::proton;
+package qpid::proton::utils;
 
 sub is_num {
     my $val = $_[0];

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/02f1c577/proton-c/bindings/perl/lib/qpid_proton.pm
----------------------------------------------------------------------
diff --git a/proton-c/bindings/perl/lib/qpid_proton.pm b/proton-c/bindings/perl/lib/qpid_proton.pm
index de4e224..cbee98d 100644
--- a/proton-c/bindings/perl/lib/qpid_proton.pm
+++ b/proton-c/bindings/perl/lib/qpid_proton.pm
@@ -31,6 +31,7 @@ use qpid::proton::Messenger;
 use qpid::proton::Message;
 
 use qpid::proton;
+use qpid::proton::utils;
 
 package qpid_proton;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[20/35] qpid-proton git commit: changed proton.py from a module into a package

Posted by gs...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6a78d2f7/proton-c/bindings/python/proton/__init__.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton/__init__.py b/proton-c/bindings/python/proton/__init__.py
new file mode 100644
index 0000000..fce3255
--- /dev/null
+++ b/proton-c/bindings/python/proton/__init__.py
@@ -0,0 +1,3891 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+"""
+The proton module defines a suite of APIs that implement the AMQP 1.0
+protocol.
+
+The proton APIs consist of the following classes:
+
+ - L{Messenger} -- A messaging endpoint.
+ - L{Message}   -- A class for creating and/or accessing AMQP message content.
+ - L{Data}      -- A class for creating and/or accessing arbitrary AMQP encoded
+                  data.
+
+"""
+
+from cproton import *
+
+import weakref, re, socket
+try:
+  import uuid
+except ImportError:
+  """
+  No 'native' UUID support.  Provide a very basic UUID type that is a compatible subset of the uuid type provided by more modern python releases.
+  """
+  import struct
+  class uuid:
+    class UUID:
+      def __init__(self, hex=None, bytes=None):
+        if [hex, bytes].count(None) != 1:
+          raise TypeError("need one of hex or bytes")
+        if bytes is not None:
+          self.bytes = bytes
+        elif hex is not None:
+          fields=hex.split("-")
+          fields[4:5] = [fields[4][:4], fields[4][4:]]
+          self.bytes = struct.pack("!LHHHHL", *[int(x,16) for x in fields])
+
+      def __cmp__(self, other):
+        if isinstance(other, uuid.UUID):
+          return cmp(self.bytes, other.bytes)
+        else:
+          return -1
+
+      def __str__(self):
+        return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
+
+      def __repr__(self):
+        return "UUID(%r)" % str(self)
+
+      def __hash__(self):
+        return self.bytes.__hash__()
+
+  import os, random, socket, time
+  rand = random.Random()
+  rand.seed((os.getpid(), time.time(), socket.gethostname()))
+  def random_uuid():
+    bytes = [rand.randint(0, 255) for i in xrange(16)]
+
+    # From RFC4122, the version bits are set to 0100
+    bytes[7] &= 0x0F
+    bytes[7] |= 0x40
+
+    # From RFC4122, the top two bits of byte 8 get set to 01
+    bytes[8] &= 0x3F
+    bytes[8] |= 0x80
+    return "".join(map(chr, bytes))
+
+  def uuid4():
+    return uuid.UUID(bytes=random_uuid())
+
+try:
+  bytes()
+except NameError:
+  bytes = str
+
+VERSION_MAJOR = PN_VERSION_MAJOR
+VERSION_MINOR = PN_VERSION_MINOR
+API_LANGUAGE = "C"
+IMPLEMENTATION_LANGUAGE = "C"
+
+class Constant(object):
+
+  def __init__(self, name):
+    self.name = name
+
+  def __repr__(self):
+    return self.name
+
+class ProtonException(Exception):
+  """
+  The root of the proton exception hierarchy. All proton exception
+  classes derive from this exception.
+  """
+  pass
+
+class Timeout(ProtonException):
+  """
+  A timeout exception indicates that a blocking operation has timed
+  out.
+  """
+  pass
+
+class Interrupt(ProtonException):
+  """
+  An interrupt exception indicaes that a blocking operation was interrupted.
+  """
+  pass
+
+class MessengerException(ProtonException):
+  """
+  The root of the messenger exception hierarchy. All exceptions
+  generated by the messenger class derive from this exception.
+  """
+  pass
+
+class MessageException(ProtonException):
+  """
+  The MessageException class is the root of the message exception
+  hierarhcy. All exceptions generated by the Message class derive from
+  this exception.
+  """
+  pass
+
+EXCEPTIONS = {
+  PN_TIMEOUT: Timeout,
+  PN_INTR: Interrupt
+  }
+
+PENDING = Constant("PENDING")
+ACCEPTED = Constant("ACCEPTED")
+REJECTED = Constant("REJECTED")
+RELEASED = Constant("RELEASED")
+ABORTED = Constant("ABORTED")
+SETTLED = Constant("SETTLED")
+
+STATUSES = {
+  PN_STATUS_ABORTED: ABORTED,
+  PN_STATUS_ACCEPTED: ACCEPTED,
+  PN_STATUS_REJECTED: REJECTED,
+  PN_STATUS_RELEASED: RELEASED,
+  PN_STATUS_PENDING: PENDING,
+  PN_STATUS_SETTLED: SETTLED,
+  PN_STATUS_UNKNOWN: None
+  }
+
+AUTOMATIC = Constant("AUTOMATIC")
+MANUAL = Constant("MANUAL")
+
+class Messenger(object):
+  """
+  The L{Messenger} class defines a high level interface for sending
+  and receiving L{Messages<Message>}. Every L{Messenger} contains a
+  single logical queue of incoming messages and a single logical queue
+  of outgoing messages. These messages in these queues may be destined
+  for, or originate from, a variety of addresses.
+
+  The messenger interface is single-threaded.  All methods
+  except one (L{interrupt}) are intended to be used from within
+  the messenger thread.
+
+
+  Address Syntax
+  ==============
+
+  An address has the following form::
+
+    [ amqp[s]:// ] [user[:password]@] domain [/[name]]
+
+  Where domain can be one of::
+
+    host | host:port | ip | ip:port | name
+
+  The following are valid examples of addresses:
+
+   - example.org
+   - example.org:1234
+   - amqp://example.org
+   - amqps://example.org
+   - example.org/incoming
+   - amqps://example.org/outgoing
+   - amqps://fred:trustno1@example.org
+   - 127.0.0.1:1234
+   - amqps://127.0.0.1:1234
+
+  Sending & Receiving Messages
+  ============================
+
+  The L{Messenger} class works in conjuction with the L{Message} class. The
+  L{Message} class is a mutable holder of message content.
+
+  The L{put} method copies its L{Message} to the outgoing queue, and may
+  send queued messages if it can do so without blocking.  The L{send}
+  method blocks until it has sent the requested number of messages,
+  or until a timeout interrupts the attempt.
+
+
+    >>> message = Message()
+    >>> for i in range(3):
+    ...   message.address = "amqp://host/queue"
+    ...   message.subject = "Hello World %i" % i
+    ...   messenger.put(message)
+    >>> messenger.send()
+
+  Similarly, the L{recv} method receives messages into the incoming
+  queue, and may block as it attempts to receive the requested number
+  of messages,  or until timeout is reached. It may receive fewer
+  than the requested number.  The L{get} method pops the
+  eldest L{Message} off the incoming queue and copies it into the L{Message}
+  object that you supply.  It will not block.
+
+
+    >>> message = Message()
+    >>> messenger.recv(10):
+    >>> while messenger.incoming > 0:
+    ...   messenger.get(message)
+    ...   print message.subject
+    Hello World 0
+    Hello World 1
+    Hello World 2
+
+  The blocking flag allows you to turn off blocking behavior entirely,
+  in which case L{send} and L{recv} will do whatever they can without
+  blocking, and then return.  You can then look at the number
+  of incoming and outgoing messages to see how much outstanding work
+  still remains.
+  """
+
+  def __init__(self, name=None):
+    """
+    Construct a new L{Messenger} with the given name. The name has
+    global scope. If a NULL name is supplied, a UUID based name will
+    be chosen.
+
+    @type name: string
+    @param name: the name of the messenger or None
+
+    """
+    self._mng = pn_messenger(name)
+    self._selectables = {}
+
+  def __del__(self):
+    """
+    Destroy the L{Messenger}.  This will close all connections that
+    are managed by the L{Messenger}.  Call the L{stop} method before
+    destroying the L{Messenger}.
+    """
+    if hasattr(self, "_mng"):
+      pn_messenger_free(self._mng)
+      del self._mng
+
+  def _check(self, err):
+    if err < 0:
+      if (err == PN_INPROGRESS):
+        return
+      exc = EXCEPTIONS.get(err, MessengerException)
+      raise exc("[%s]: %s" % (err, pn_error_text(pn_messenger_error(self._mng))))
+    else:
+      return err
+
+  @property
+  def name(self):
+    """
+    The name of the L{Messenger}.
+    """
+    return pn_messenger_name(self._mng)
+
+  def _get_certificate(self):
+    return pn_messenger_get_certificate(self._mng)
+
+  def _set_certificate(self, value):
+    self._check(pn_messenger_set_certificate(self._mng, value))
+
+  certificate = property(_get_certificate, _set_certificate,
+                         doc="""
+Path to a certificate file for the L{Messenger}. This certificate is
+used when the L{Messenger} accepts or establishes SSL/TLS connections.
+This property must be specified for the L{Messenger} to accept
+incoming SSL/TLS connections and to establish client authenticated
+outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS
+connections do not require this property.
+""")
+
+  def _get_private_key(self):
+    return pn_messenger_get_private_key(self._mng)
+
+  def _set_private_key(self, value):
+    self._check(pn_messenger_set_private_key(self._mng, value))
+
+  private_key = property(_get_private_key, _set_private_key,
+                         doc="""
+Path to a private key file for the L{Messenger's<Messenger>}
+certificate. This property must be specified for the L{Messenger} to
+accept incoming SSL/TLS connections and to establish client
+authenticated outgoing SSL/TLS connection. Non client authenticated
+SSL/TLS connections do not require this property.
+""")
+
+  def _get_password(self):
+    return pn_messenger_get_password(self._mng)
+
+  def _set_password(self, value):
+    self._check(pn_messenger_set_password(self._mng, value))
+
+  password = property(_get_password, _set_password,
+                      doc="""
+This property contains the password for the L{Messenger.private_key}
+file, or None if the file is not encrypted.
+""")
+
+  def _get_trusted_certificates(self):
+    return pn_messenger_get_trusted_certificates(self._mng)
+
+  def _set_trusted_certificates(self, value):
+    self._check(pn_messenger_set_trusted_certificates(self._mng, value))
+
+  trusted_certificates = property(_get_trusted_certificates,
+                                  _set_trusted_certificates,
+                                  doc="""
+A path to a database of trusted certificates for use in verifying the
+peer on an SSL/TLS connection. If this property is None, then the peer
+will not be verified.
+""")
+
+  def _get_timeout(self):
+    t = pn_messenger_get_timeout(self._mng)
+    if t == -1:
+      return None
+    else:
+      return millis2secs(t)
+
+  def _set_timeout(self, value):
+    if value is None:
+      t = -1
+    else:
+      t = secs2millis(value)
+    self._check(pn_messenger_set_timeout(self._mng, t))
+
+  timeout = property(_get_timeout, _set_timeout,
+                     doc="""
+The timeout property contains the default timeout for blocking
+operations performed by the L{Messenger}.
+""")
+
+  def _is_blocking(self):
+    return pn_messenger_is_blocking(self._mng)
+
+  def _set_blocking(self, b):
+    self._check(pn_messenger_set_blocking(self._mng, b))
+
+  blocking = property(_is_blocking, _set_blocking,
+                      doc="""
+Enable or disable blocking behavior during L{Message} sending
+and receiving.  This affects every blocking call, with the
+exception of L{work}.  Currently, the affected calls are
+L{send}, L{recv}, and L{stop}.
+""")
+
+  def _is_passive(self):
+    return pn_messenger_is_passive(self._mng)
+
+  def _set_passive(self, b):
+    self._check(pn_messenger_set_passive(self._mng, b))
+
+  passive = property(_is_passive, _set_passive,
+                      doc="""
+When passive is set to true, Messenger will not attempt to perform I/O
+internally. In this mode it is necessary to use the selectables API to
+drive any I/O needed to perform requested actions. In this mode
+Messenger will never block.
+""")
+
+  def _get_incoming_window(self):
+    return pn_messenger_get_incoming_window(self._mng)
+
+  def _set_incoming_window(self, window):
+    self._check(pn_messenger_set_incoming_window(self._mng, window))
+
+  incoming_window = property(_get_incoming_window, _set_incoming_window,
+                             doc="""
+The incoming tracking window for the messenger. The messenger will
+track the remote status of this many incoming deliveries after they
+have been accepted or rejected. Defaults to zero.
+
+L{Messages<Message>} enter this window only when you take them into your application
+using L{get}.  If your incoming window size is I{n}, and you get I{n}+1 L{messages<Message>}
+without explicitly accepting or rejecting the oldest message, then the
+message that passes beyond the edge of the incoming window will be assigned
+the default disposition of its link.
+""")
+
+  def _get_outgoing_window(self):
+    return pn_messenger_get_outgoing_window(self._mng)
+
+  def _set_outgoing_window(self, window):
+    self._check(pn_messenger_set_outgoing_window(self._mng, window))
+
+  outgoing_window = property(_get_outgoing_window, _set_outgoing_window,
+                             doc="""
+The outgoing tracking window for the messenger. The messenger will
+track the remote status of this many outgoing deliveries after calling
+send. Defaults to zero.
+
+A L{Message} enters this window when you call the put() method with the
+message.  If your outgoing window size is I{n}, and you call L{put} I{n}+1
+times, status information will no longer be available for the
+first message.
+""")
+
+  def start(self):
+    """
+    Currently a no-op placeholder.
+    For future compatibility, do not L{send} or L{recv} messages
+    before starting the L{Messenger}.
+    """
+    self._check(pn_messenger_start(self._mng))
+
+  def stop(self):
+    """
+    Transitions the L{Messenger} to an inactive state. An inactive
+    L{Messenger} will not send or receive messages from its internal
+    queues. A L{Messenger} should be stopped before being discarded to
+    ensure a clean shutdown handshake occurs on any internally managed
+    connections.
+    """
+    self._check(pn_messenger_stop(self._mng))
+
+  @property
+  def stopped(self):
+    """
+    Returns true iff a L{Messenger} is in the stopped state.
+    This function does not block.
+    """
+    return pn_messenger_stopped(self._mng)
+
+  def subscribe(self, source):
+    """
+    Subscribes the L{Messenger} to messages originating from the
+    specified source. The source is an address as specified in the
+    L{Messenger} introduction with the following addition. If the
+    domain portion of the address begins with the '~' character, the
+    L{Messenger} will interpret the domain as host/port, bind to it,
+    and listen for incoming messages. For example "~0.0.0.0",
+    "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any
+    local interface and listen for incoming messages with the last
+    variant only permitting incoming SSL connections.
+
+    @type source: string
+    @param source: the source of messages to subscribe to
+    """
+    sub_impl = pn_messenger_subscribe(self._mng, source)
+    if not sub_impl:
+      self._check(pn_error_code(pn_messenger_error(self._mng)))
+      raise MessengerException("Cannot subscribe to %s"%source)
+    return Subscription(sub_impl)
+
+  def put(self, message):
+    """
+    Places the content contained in the message onto the outgoing
+    queue of the L{Messenger}. This method will never block, however
+    it will send any unblocked L{Messages<Message>} in the outgoing
+    queue immediately and leave any blocked L{Messages<Message>}
+    remaining in the outgoing queue. The L{send} call may be used to
+    block until the outgoing queue is empty. The L{outgoing} property
+    may be used to check the depth of the outgoing queue.
+
+    When the content in a given L{Message} object is copied to the outgoing
+    message queue, you may then modify or discard the L{Message} object
+    without having any impact on the content in the outgoing queue.
+
+    This method returns an outgoing tracker for the L{Message}.  The tracker
+    can be used to determine the delivery status of the L{Message}.
+
+    @type message: Message
+    @param message: the message to place in the outgoing queue
+    @return: a tracker
+    """
+    message._pre_encode()
+    self._check(pn_messenger_put(self._mng, message._msg))
+    return pn_messenger_outgoing_tracker(self._mng)
+
+  def status(self, tracker):
+    """
+    Gets the last known remote state of the delivery associated with
+    the given tracker.
+
+    @type tracker: tracker
+    @param tracker: the tracker whose status is to be retrieved
+
+    @return: one of None, PENDING, REJECTED, or ACCEPTED
+    """
+    disp = pn_messenger_status(self._mng, tracker);
+    return STATUSES.get(disp, disp)
+
+  def buffered(self, tracker):
+    """
+    Checks if the delivery associated with the given tracker is still
+    waiting to be sent.
+
+    @type tracker: tracker
+    @param tracker: the tracker whose status is to be retrieved
+
+    @return: true if delivery is still buffered
+    """
+    return pn_messenger_buffered(self._mng, tracker);
+
+  def settle(self, tracker=None):
+    """
+    Frees a L{Messenger} from tracking the status associated with a given
+    tracker. If you don't supply a tracker, all outgoing L{messages<Message>} up
+    to the most recent will be settled.
+    """
+    if tracker is None:
+      tracker = pn_messenger_outgoing_tracker(self._mng)
+      flags = PN_CUMULATIVE
+    else:
+      flags = 0
+    self._check(pn_messenger_settle(self._mng, tracker, flags))
+
+  def send(self, n=-1):
+    """
+    This call will block until the indicated number of L{messages<Message>}
+    have been sent, or until the operation times out.  If n is -1 this call will
+    block until all outgoing L{messages<Message>} have been sent. If n is 0 then
+    this call will send whatever it can without blocking.
+    """
+    self._check(pn_messenger_send(self._mng, n))
+
+  def recv(self, n=None):
+    """
+    Receives up to I{n} L{messages<Message>} into the incoming queue.  If no value
+    for I{n} is supplied, this call will receive as many L{messages<Message>} as it
+    can buffer internally.  If the L{Messenger} is in blocking mode, this
+    call will block until at least one L{Message} is available in the
+    incoming queue.
+    """
+    if n is None:
+      n = -1
+    self._check(pn_messenger_recv(self._mng, n))
+
+  def work(self, timeout=None):
+    """
+    Sends or receives any outstanding L{messages<Message>} queued for a L{Messenger}.
+    This will block for the indicated timeout.
+    This method may also do I/O work other than sending and receiving
+    L{messages<Message>}.  For example, closing connections after messenger.L{stop}()
+    has been called.
+    """
+    if timeout is None:
+      t = -1
+    else:
+      t = secs2millis(timeout)
+    err = pn_messenger_work(self._mng, t)
+    if (err == PN_TIMEOUT):
+      return False
+    else:
+      self._check(err)
+      return True
+
+  @property
+  def receiving(self):
+    return pn_messenger_receiving(self._mng)
+
+  def interrupt(self):
+    """
+    The L{Messenger} interface is single-threaded.
+    This is the only L{Messenger} function intended to be called
+    from outside of the L{Messenger} thread.
+    Call this from a non-messenger thread to interrupt
+    a L{Messenger} that is blocking.
+    This will cause any in-progress blocking call to throw
+    the L{Interrupt} exception.  If there is no currently blocking
+    call, then the next blocking call will be affected, even if it
+    is within the same thread that interrupt was called from.
+    """
+    self._check(pn_messenger_interrupt(self._mng))
+
+  def get(self, message=None):
+    """
+    Moves the message from the head of the incoming message queue into
+    the supplied message object. Any content in the message will be
+    overwritten.
+
+    A tracker for the incoming L{Message} is returned.  The tracker can
+    later be used to communicate your acceptance or rejection of the
+    L{Message}.
+
+    If None is passed in for the L{Message} object, the L{Message}
+    popped from the head of the queue is discarded.
+
+    @type message: Message
+    @param message: the destination message object
+    @return: a tracker
+    """
+    if message is None:
+      impl = None
+    else:
+      impl = message._msg
+    self._check(pn_messenger_get(self._mng, impl))
+    if message is not None:
+      message._post_decode()
+    return pn_messenger_incoming_tracker(self._mng)
+
+  def accept(self, tracker=None):
+    """
+    Signal the sender that you have acted on the L{Message}
+    pointed to by the tracker.  If no tracker is supplied,
+    then all messages that have been returned by the L{get}
+    method are accepted, except those that have already been
+    auto-settled by passing beyond your incoming window size.
+
+    @type tracker: tracker
+    @param tracker: a tracker as returned by get
+    """
+    if tracker is None:
+      tracker = pn_messenger_incoming_tracker(self._mng)
+      flags = PN_CUMULATIVE
+    else:
+      flags = 0
+    self._check(pn_messenger_accept(self._mng, tracker, flags))
+
+  def reject(self, tracker=None):
+    """
+    Rejects the L{Message} indicated by the tracker.  If no tracker
+    is supplied, all messages that have been returned by the L{get}
+    method are rejected, except those that have already been auto-settled
+    by passing beyond your outgoing window size.
+
+    @type tracker: tracker
+    @param tracker: a tracker as returned by get
+    """
+    if tracker is None:
+      tracker = pn_messenger_incoming_tracker(self._mng)
+      flags = PN_CUMULATIVE
+    else:
+      flags = 0
+    self._check(pn_messenger_reject(self._mng, tracker, flags))
+
+  @property
+  def outgoing(self):
+    """
+    The outgoing queue depth.
+    """
+    return pn_messenger_outgoing(self._mng)
+
+  @property
+  def incoming(self):
+    """
+    The incoming queue depth.
+    """
+    return pn_messenger_incoming(self._mng)
+
+  def route(self, pattern, address):
+    """
+          Adds a routing rule to a L{Messenger's<Messenger>} internal routing table.
+
+          The route procedure may be used to influence how a L{Messenger} will
+          internally treat a given address or class of addresses. Every call
+          to the route procedure will result in L{Messenger} appending a routing
+          rule to its internal routing table.
+
+          Whenever a L{Message} is presented to a L{Messenger} for delivery, it
+          will match the address of this message against the set of routing
+          rules in order. The first rule to match will be triggered, and
+          instead of routing based on the address presented in the message,
+          the L{Messenger} will route based on the address supplied in the rule.
+
+          The pattern matching syntax supports two types of matches, a '%'
+          will match any character except a '/', and a '*' will match any
+          character including a '/'.
+
+          A routing address is specified as a normal AMQP address, however it
+          may additionally use substitution variables from the pattern match
+          that triggered the rule.
+
+          Any message sent to "foo" will be routed to "amqp://foo.com":
+
+             >>> messenger.route("foo", "amqp://foo.com");
+
+          Any message sent to "foobar" will be routed to
+          "amqp://foo.com/bar":
+
+             >>> messenger.route("foobar", "amqp://foo.com/bar");
+
+          Any message sent to bar/<path> will be routed to the corresponding
+          path within the amqp://bar.com domain:
+
+             >>> messenger.route("bar/*", "amqp://bar.com/$1");
+
+          Route all L{messages<Message>} over TLS:
+
+             >>> messenger.route("amqp:*", "amqps:$1")
+
+          Supply credentials for foo.com:
+
+             >>> messenger.route("amqp://foo.com/*", "amqp://user:password@foo.com/$1");
+
+          Supply credentials for all domains:
+
+             >>> messenger.route("amqp://*", "amqp://user:password@$1");
+
+          Route all addresses through a single proxy while preserving the
+          original destination:
+
+             >>> messenger.route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
+
+          Route any address through a single broker:
+
+             >>> messenger.route("*", "amqp://user:password@broker/$1");
+    """
+    self._check(pn_messenger_route(self._mng, pattern, address))
+
+  def rewrite(self, pattern, address):
+    """
+    Similar to route(), except that the destination of
+    the L{Message} is determined before the message address is rewritten.
+
+    The outgoing address is only rewritten after routing has been
+    finalized.  If a message has an outgoing address of
+    "amqp://0.0.0.0:5678", and a rewriting rule that changes its
+    outgoing address to "foo", it will still arrive at the peer that
+    is listening on "amqp://0.0.0.0:5678", but when it arrives there,
+    the receiver will see its outgoing address as "foo".
+
+    The default rewrite rule removes username and password from addresses
+    before they are transmitted.
+    """
+    self._check(pn_messenger_rewrite(self._mng, pattern, address))
+
+  def selectable(self):
+    impl = pn_messenger_selectable(self._mng)
+    if impl:
+      fd = pn_selectable_fd(impl)
+      sel = self._selectables.get(fd, None)
+      if sel is None:
+        sel = Selectable(self, impl)
+        self._selectables[fd] = sel
+      return sel
+    else:
+      return None
+
+  @property
+  def deadline(self):
+    tstamp = pn_messenger_deadline(self._mng)
+    if tstamp:
+      return millis2secs(tstamp)
+    else:
+      return None
+
+class Message(object):
+  """The L{Message} class is a mutable holder of message content.
+
+  @ivar instructions: delivery instructions for the message
+  @type instructions: dict
+  @ivar annotations: infrastructure defined message annotations
+  @type annotations: dict
+  @ivar properties: application defined message properties
+  @type properties: dict
+  @ivar body: message body
+  @type body: bytes | unicode | dict | list | int | long | float | UUID
+  """
+
+  DATA = PN_DATA
+  TEXT = PN_TEXT
+  AMQP = PN_AMQP
+  JSON = PN_JSON
+
+  DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
+
+  def __init__(self, **kwargs):
+    """
+    @param kwargs: Message property name/value pairs to initialise the Message
+    """
+    self._msg = pn_message()
+    self._id = Data(pn_message_id(self._msg))
+    self._correlation_id = Data(pn_message_correlation_id(self._msg))
+    self.instructions = None
+    self.annotations = None
+    self.properties = None
+    self.body = None
+    for k,v in kwargs.iteritems():
+      getattr(self, k)          # Raise exception if it's not a valid attribute.
+      setattr(self, k, v)
+
+  def __del__(self):
+    if hasattr(self, "_msg"):
+      pn_message_free(self._msg)
+      del self._msg
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, MessageException)
+      raise exc("[%s]: %s" % (err, pn_error_text(pn_message_error(self._msg))))
+    else:
+      return err
+
+  def _pre_encode(self):
+    inst = Data(pn_message_instructions(self._msg))
+    ann = Data(pn_message_annotations(self._msg))
+    props = Data(pn_message_properties(self._msg))
+    body = Data(pn_message_body(self._msg))
+
+    inst.clear()
+    if self.instructions is not None:
+      inst.put_object(self.instructions)
+    ann.clear()
+    if self.annotations is not None:
+      ann.put_object(self.annotations)
+    props.clear()
+    if self.properties is not None:
+      props.put_object(self.properties)
+    body.clear()
+    if self.body is not None:
+      body.put_object(self.body)
+
+  def _post_decode(self):
+    inst = Data(pn_message_instructions(self._msg))
+    ann = Data(pn_message_annotations(self._msg))
+    props = Data(pn_message_properties(self._msg))
+    body = Data(pn_message_body(self._msg))
+
+    if inst.next():
+      self.instructions = inst.get_object()
+    else:
+      self.instructions = None
+    if ann.next():
+      self.annotations = ann.get_object()
+    else:
+      self.annotations = None
+    if props.next():
+      self.properties = props.get_object()
+    else:
+      self.properties = None
+    if body.next():
+      self.body = body.get_object()
+    else:
+      self.body = None
+
+  def clear(self):
+    """
+    Clears the contents of the L{Message}. All fields will be reset to
+    their default values.
+    """
+    pn_message_clear(self._msg)
+    self.instructions = None
+    self.annotations = None
+    self.properties = None
+    self.body = None
+
+  def _is_inferred(self):
+    return pn_message_is_inferred(self._msg)
+
+  def _set_inferred(self, value):
+    self._check(pn_message_set_inferred(self._msg, bool(value)))
+
+  inferred = property(_is_inferred, _set_inferred, doc="""
+The inferred flag for a message indicates how the message content
+is encoded into AMQP sections. If inferred is true then binary and
+list values in the body of the message will be encoded as AMQP DATA
+and AMQP SEQUENCE sections, respectively. If inferred is false,
+then all values in the body of the message will be encoded as AMQP
+VALUE sections regardless of their type.
+""")
+
+  def _is_durable(self):
+    return pn_message_is_durable(self._msg)
+
+  def _set_durable(self, value):
+    self._check(pn_message_set_durable(self._msg, bool(value)))
+
+  durable = property(_is_durable, _set_durable,
+                     doc="""
+The durable property indicates that the message should be held durably
+by any intermediaries taking responsibility for the message.
+""")
+
+  def _get_priority(self):
+    return pn_message_get_priority(self._msg)
+
+  def _set_priority(self, value):
+    self._check(pn_message_set_priority(self._msg, value))
+
+  priority = property(_get_priority, _set_priority,
+                      doc="""
+The priority of the message.
+""")
+
+  def _get_ttl(self):
+    return millis2secs(pn_message_get_ttl(self._msg))
+
+  def _set_ttl(self, value):
+    self._check(pn_message_set_ttl(self._msg, secs2millis(value)))
+
+  ttl = property(_get_ttl, _set_ttl,
+                 doc="""
+The time to live of the message measured in seconds. Expired messages
+may be dropped.
+""")
+
+  def _is_first_acquirer(self):
+    return pn_message_is_first_acquirer(self._msg)
+
+  def _set_first_acquirer(self, value):
+    self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
+
+  first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
+                            doc="""
+True iff the recipient is the first to acquire the message.
+""")
+
+  def _get_delivery_count(self):
+    return pn_message_get_delivery_count(self._msg)
+
+  def _set_delivery_count(self, value):
+    self._check(pn_message_set_delivery_count(self._msg, value))
+
+  delivery_count = property(_get_delivery_count, _set_delivery_count,
+                            doc="""
+The number of delivery attempts made for this message.
+""")
+
+
+  def _get_id(self):
+    return self._id.get_object()
+  def _set_id(self, value):
+    if type(value) in (int, long):
+      value = ulong(value)
+    self._id.rewind()
+    self._id.put_object(value)
+  id = property(_get_id, _set_id,
+                doc="""
+The id of the message.
+""")
+
+  def _get_user_id(self):
+    return pn_message_get_user_id(self._msg)
+
+  def _set_user_id(self, value):
+    self._check(pn_message_set_user_id(self._msg, value))
+
+  user_id = property(_get_user_id, _set_user_id,
+                     doc="""
+The user id of the message creator.
+""")
+
+  def _get_address(self):
+    return pn_message_get_address(self._msg)
+
+  def _set_address(self, value):
+    self._check(pn_message_set_address(self._msg, value))
+
+  address = property(_get_address, _set_address,
+                     doc="""
+The address of the message.
+""")
+
+  def _get_subject(self):
+    return pn_message_get_subject(self._msg)
+
+  def _set_subject(self, value):
+    self._check(pn_message_set_subject(self._msg, value))
+
+  subject = property(_get_subject, _set_subject,
+                     doc="""
+The subject of the message.
+""")
+
+  def _get_reply_to(self):
+    return pn_message_get_reply_to(self._msg)
+
+  def _set_reply_to(self, value):
+    self._check(pn_message_set_reply_to(self._msg, value))
+
+  reply_to = property(_get_reply_to, _set_reply_to,
+                      doc="""
+The reply-to address for the message.
+""")
+
+  def _get_correlation_id(self):
+    return self._correlation_id.get_object()
+  def _set_correlation_id(self, value):
+    if type(value) in (int, long):
+      value = ulong(value)
+    self._correlation_id.rewind()
+    self._correlation_id.put_object(value)
+
+  correlation_id = property(_get_correlation_id, _set_correlation_id,
+                            doc="""
+The correlation-id for the message.
+""")
+
+  def _get_content_type(self):
+    return pn_message_get_content_type(self._msg)
+
+  def _set_content_type(self, value):
+    self._check(pn_message_set_content_type(self._msg, value))
+
+  content_type = property(_get_content_type, _set_content_type,
+                          doc="""
+The content-type of the message.
+""")
+
+  def _get_content_encoding(self):
+    return pn_message_get_content_encoding(self._msg)
+
+  def _set_content_encoding(self, value):
+    self._check(pn_message_set_content_encoding(self._msg, value))
+
+  content_encoding = property(_get_content_encoding, _set_content_encoding,
+                              doc="""
+The content-encoding of the message.
+""")
+
+  def _get_expiry_time(self):
+    return millis2secs(pn_message_get_expiry_time(self._msg))
+
+  def _set_expiry_time(self, value):
+    self._check(pn_message_set_expiry_time(self._msg, secs2millis(value)))
+
+  expiry_time = property(_get_expiry_time, _set_expiry_time,
+                         doc="""
+The expiry time of the message.
+""")
+
+  def _get_creation_time(self):
+    return millis2secs(pn_message_get_creation_time(self._msg))
+
+  def _set_creation_time(self, value):
+    self._check(pn_message_set_creation_time(self._msg, secs2millis(value)))
+
+  creation_time = property(_get_creation_time, _set_creation_time,
+                           doc="""
+The creation time of the message.
+""")
+
+  def _get_group_id(self):
+    return pn_message_get_group_id(self._msg)
+
+  def _set_group_id(self, value):
+    self._check(pn_message_set_group_id(self._msg, value))
+
+  group_id = property(_get_group_id, _set_group_id,
+                      doc="""
+The group id of the message.
+""")
+
+  def _get_group_sequence(self):
+    return pn_message_get_group_sequence(self._msg)
+
+  def _set_group_sequence(self, value):
+    self._check(pn_message_set_group_sequence(self._msg, value))
+
+  group_sequence = property(_get_group_sequence, _set_group_sequence,
+                            doc="""
+The sequence of the message within its group.
+""")
+
+  def _get_reply_to_group_id(self):
+    return pn_message_get_reply_to_group_id(self._msg)
+
+  def _set_reply_to_group_id(self, value):
+    self._check(pn_message_set_reply_to_group_id(self._msg, value))
+
+  reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
+                               doc="""
+The group-id for any replies.
+""")
+
+  # XXX
+  def _get_format(self):
+    return pn_message_get_format(self._msg)
+
+  def _set_format(self, value):
+    self._check(pn_message_set_format(self._msg, value))
+
+  format = property(_get_format, _set_format,
+                    doc="""
+The format of the message.
+""")
+
+  def encode(self):
+    self._pre_encode()
+    sz = 16
+    while True:
+      err, data = pn_message_encode(self._msg, sz)
+      if err == PN_OVERFLOW:
+        sz *= 2
+        continue
+      else:
+        self._check(err)
+        return data
+
+  def decode(self, data):
+    self._check(pn_message_decode(self._msg, data, len(data)))
+    self._post_decode()
+
+  def load(self, data):
+    self._check(pn_message_load(self._msg, data))
+
+  def save(self):
+    sz = 16
+    while True:
+      err, data = pn_message_save(self._msg, sz)
+      if err == PN_OVERFLOW:
+        sz *= 2
+        continue
+      else:
+        self._check(err)
+        return data
+
+  def __repr2__(self):
+    props = []
+    for attr in ("inferred", "address", "reply_to", "durable", "ttl",
+                 "priority", "first_acquirer", "delivery_count", "id",
+                 "correlation_id", "user_id", "group_id", "group_sequence",
+                 "reply_to_group_id", "instructions", "annotations",
+                 "properties", "body"):
+      value = getattr(self, attr)
+      if value: props.append("%s=%r" % (attr, value))
+    return "Message(%s)" % ", ".join(props)
+
+  def __repr__(self):
+    tmp = pn_string(None)
+    err = pn_inspect(self._msg, tmp)
+    result = pn_string_get(tmp)
+    pn_free(tmp)
+    self._check(err)
+    return result
+
+class Subscription(object):
+
+  def __init__(self, impl):
+    self._impl = impl
+
+  @property
+  def address(self):
+    return pn_subscription_address(self._impl)
+
+class Selectable(object):
+
+  def __init__(self, messenger, impl):
+    self.messenger = messenger
+    self._impl = impl
+
+  def fileno(self):
+    if not self._impl: raise ValueError("selectable freed")
+    return pn_selectable_fd(self._impl)
+
+  @property
+  def capacity(self):
+    if not self._impl: raise ValueError("selectable freed")
+    return pn_selectable_capacity(self._impl)
+
+  @property
+  def pending(self):
+    if not self._impl: raise ValueError("selectable freed")
+    return pn_selectable_pending(self._impl)
+
+  @property
+  def deadline(self):
+    if not self._impl: raise ValueError("selectable freed")
+    tstamp = pn_selectable_deadline(self._impl)
+    if tstamp:
+      return millis2secs(tstamp)
+    else:
+      return None
+
+  def readable(self):
+    if not self._impl: raise ValueError("selectable freed")
+    pn_selectable_readable(self._impl)
+
+  def writable(self):
+    if not self._impl: raise ValueError("selectable freed")
+    pn_selectable_writable(self._impl)
+
+  def expired(self):
+    if not self._impl: raise ValueError("selectable freed")
+    pn_selectable_expired(self._impl)
+
+  def _is_registered(self):
+    if not self._impl: raise ValueError("selectable freed")
+    return pn_selectable_is_registered(self._impl)
+
+  def _set_registered(self, registered):
+    if not self._impl: raise ValueError("selectable freed")
+    pn_selectable_set_registered(self._impl, registered)
+
+  registered = property(_is_registered, _set_registered,
+                    doc="""
+The registered property may be get/set by an I/O polling system to
+indicate whether the fd has been registered or not.
+""")
+
+  @property
+  def is_terminal(self):
+    if not self._impl: return True
+    return pn_selectable_is_terminal(self._impl)
+
+  def free(self):
+    if self._impl:
+      del self.messenger._selectables[self.fileno()]
+      pn_selectable_free(self._impl)
+      self._impl = None
+
+  def __del__(self):
+    self.free()
+
+class DataException(ProtonException):
+  """
+  The DataException class is the root of the Data exception hierarchy.
+  All exceptions raised by the Data class extend this exception.
+  """
+  pass
+
+class UnmappedType:
+
+  def __init__(self, msg):
+    self.msg = msg
+
+  def __repr__(self):
+    return "UnmappedType(%s)" % self.msg
+
+class ulong(long):
+
+  def __repr__(self):
+    return "ulong(%s)" % long.__repr__(self)
+
+class timestamp(long):
+
+  def __repr__(self):
+    return "timestamp(%s)" % long.__repr__(self)
+
+class symbol(unicode):
+
+  def __repr__(self):
+    return "symbol(%s)" % unicode.__repr__(self)
+
+class char(unicode):
+
+  def __repr__(self):
+    return "char(%s)" % unicode.__repr__(self)
+
+class Described(object):
+
+  def __init__(self, descriptor, value):
+    self.descriptor = descriptor
+    self.value = value
+
+  def __repr__(self):
+    return "Described(%r, %r)" % (self.descriptor, self.value)
+
+  def __eq__(self, o):
+    if isinstance(o, Described):
+      return self.descriptor == o.descriptor and self.value == o.value
+    else:
+      return False
+
+UNDESCRIBED = Constant("UNDESCRIBED")
+
+class Array(object):
+
+  def __init__(self, descriptor, type, *elements):
+    self.descriptor = descriptor
+    self.type = type
+    self.elements = elements
+
+  def __repr__(self):
+    if self.elements:
+      els = ", %s"  % (", ".join(map(repr, self.elements)))
+    else:
+      els = ""
+    return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
+
+  def __eq__(self, o):
+    if isinstance(o, Array):
+      return self.descriptor == o.descriptor and \
+          self.type == o.type and self.elements == o.elements
+    else:
+      return False
+
+class Data:
+  """
+  The L{Data} class provides an interface for decoding, extracting,
+  creating, and encoding arbitrary AMQP data. A L{Data} object
+  contains a tree of AMQP values. Leaf nodes in this tree correspond
+  to scalars in the AMQP type system such as L{ints<INT>} or
+  L{strings<STRING>}. Non-leaf nodes in this tree correspond to
+  compound values in the AMQP type system such as L{lists<LIST>},
+  L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
+  The root node of the tree is the L{Data} object itself and can have
+  an arbitrary number of children.
+
+  A L{Data} object maintains the notion of the current sibling node
+  and a current parent node. Siblings are ordered within their parent.
+  Values are accessed and/or added by using the L{next}, L{prev},
+  L{enter}, and L{exit} methods to navigate to the desired location in
+  the tree and using the supplied variety of put_*/get_* methods to
+  access or add a value of the desired type.
+
+  The put_* methods will always add a value I{after} the current node
+  in the tree. If the current node has a next sibling the put_* method
+  will overwrite the value on this node. If there is no current node
+  or the current node has no next sibling then one will be added. The
+  put_* methods always set the added/modified node to the current
+  node. The get_* methods read the value of the current node and do
+  not change which node is current.
+
+  The following types of scalar values are supported:
+
+   - L{NULL}
+   - L{BOOL}
+   - L{UBYTE}
+   - L{USHORT}
+   - L{SHORT}
+   - L{UINT}
+   - L{INT}
+   - L{ULONG}
+   - L{LONG}
+   - L{FLOAT}
+   - L{DOUBLE}
+   - L{BINARY}
+   - L{STRING}
+   - L{SYMBOL}
+
+  The following types of compound values are supported:
+
+   - L{DESCRIBED}
+   - L{ARRAY}
+   - L{LIST}
+   - L{MAP}
+  """
+
+  NULL = PN_NULL; "A null value."
+  BOOL = PN_BOOL; "A boolean value."
+  UBYTE = PN_UBYTE; "An unsigned byte value."
+  BYTE = PN_BYTE; "A signed byte value."
+  USHORT = PN_USHORT; "An unsigned short value."
+  SHORT = PN_SHORT; "A short value."
+  UINT = PN_UINT; "An unsigned int value."
+  INT = PN_INT; "A signed int value."
+  CHAR = PN_CHAR; "A character value."
+  ULONG = PN_ULONG; "An unsigned long value."
+  LONG = PN_LONG; "A signed long value."
+  TIMESTAMP = PN_TIMESTAMP; "A timestamp value."
+  FLOAT = PN_FLOAT; "A float value."
+  DOUBLE = PN_DOUBLE; "A double value."
+  DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value."
+  DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value."
+  DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value."
+  UUID = PN_UUID; "A UUID value."
+  BINARY = PN_BINARY; "A binary string."
+  STRING = PN_STRING; "A unicode string."
+  SYMBOL = PN_SYMBOL; "A symbolic string."
+  DESCRIBED = PN_DESCRIBED; "A described value."
+  ARRAY = PN_ARRAY; "An array value."
+  LIST = PN_LIST; "A list value."
+  MAP = PN_MAP; "A map value."
+
+  type_names = {
+    NULL: "null",
+    BOOL: "bool",
+    BYTE: "byte",
+    UBYTE: "ubyte",
+    SHORT: "short",
+    USHORT: "ushort",
+    INT: "int",
+    UINT: "uint",
+    CHAR: "char",
+    LONG: "long",
+    ULONG: "ulong",
+    TIMESTAMP: "timestamp",
+    FLOAT: "float",
+    DOUBLE: "double",
+    DECIMAL32: "decimal32",
+    DECIMAL64: "decimal64",
+    DECIMAL128: "decimal128",
+    UUID: "uuid",
+    BINARY: "binary",
+    STRING: "string",
+    SYMBOL: "symbol",
+    DESCRIBED: "described",
+    ARRAY: "array",
+    LIST: "list",
+    MAP: "map"
+    }
+
+  @classmethod
+  def type_name(type): return Data.type_names[type]
+
+  def __init__(self, capacity=16):
+    if type(capacity) in (int, long):
+      self._data = pn_data(capacity)
+      self._free = True
+    else:
+      self._data = capacity
+      self._free = False
+
+  def __del__(self):
+    if self._free and hasattr(self, "_data"):
+      pn_data_free(self._data)
+      del self._data
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, DataException)
+      raise exc("[%s]: %s" % (err, pn_error_text(pn_data_error(self._data))))
+    else:
+      return err
+
+  def clear(self):
+    """
+    Clears the data object.
+    """
+    pn_data_clear(self._data)
+
+  def rewind(self):
+    """
+    Clears current node and sets the parent to the root node.  Clearing the
+    current node sets it _before_ the first node, calling next() will advance to
+    the first node.
+    """
+    assert self._data is not None
+    pn_data_rewind(self._data)
+
+  def next(self):
+    """
+    Advances the current node to its next sibling and returns its
+    type. If there is no next sibling the current node remains
+    unchanged and None is returned.
+    """
+    found = pn_data_next(self._data)
+    if found:
+      return self.type()
+    else:
+      return None
+
+  def prev(self):
+    """
+    Advances the current node to its previous sibling and returns its
+    type. If there is no previous sibling the current node remains
+    unchanged and None is returned.
+    """
+    found = pn_data_prev(self._data)
+    if found:
+      return self.type()
+    else:
+      return None
+
+  def enter(self):
+    """
+    Sets the parent node to the current node and clears the current node.
+    Clearing the current node sets it _before_ the first child,
+    call next() advances to the first child.
+    """
+    return pn_data_enter(self._data)
+
+  def exit(self):
+    """
+    Sets the current node to the parent node and the parent node to
+    its own parent.
+    """
+    return pn_data_exit(self._data)
+
+  def lookup(self, name):
+    return pn_data_lookup(self._data, name)
+
+  def narrow(self):
+    pn_data_narrow(self._data)
+
+  def widen(self):
+    pn_data_widen(self._data)
+
+  def type(self):
+    """
+    Returns the type of the current node.
+    """
+    dtype = pn_data_type(self._data)
+    if dtype == -1:
+      return None
+    else:
+      return dtype
+
+  def encode(self):
+    """
+    Returns a representation of the data encoded in AMQP format.
+    """
+    size = 1024
+    while True:
+      cd, enc = pn_data_encode(self._data, size)
+      if cd == PN_OVERFLOW:
+        size *= 2
+      elif cd >= 0:
+        return enc
+      else:
+        self._check(cd)
+
+  def decode(self, encoded):
+    """
+    Decodes the first value from supplied AMQP data and returns the
+    number of bytes consumed.
+
+    @type encoded: binary
+    @param encoded: AMQP encoded binary data
+    """
+    return self._check(pn_data_decode(self._data, encoded))
+
+  def put_list(self):
+    """
+    Puts a list value. Elements may be filled by entering the list
+    node and putting element values.
+
+      >>> data = Data()
+      >>> data.put_list()
+      >>> data.enter()
+      >>> data.put_int(1)
+      >>> data.put_int(2)
+      >>> data.put_int(3)
+      >>> data.exit()
+    """
+    self._check(pn_data_put_list(self._data))
+
+  def put_map(self):
+    """
+    Puts a map value. Elements may be filled by entering the map node
+    and putting alternating key value pairs.
+
+      >>> data = Data()
+      >>> data.put_map()
+      >>> data.enter()
+      >>> data.put_string("key")
+      >>> data.put_string("value")
+      >>> data.exit()
+    """
+    self._check(pn_data_put_map(self._data))
+
+  def put_array(self, described, element_type):
+    """
+    Puts an array value. Elements may be filled by entering the array
+    node and putting the element values. The values must all be of the
+    specified array element type. If an array is described then the
+    first child value of the array is the descriptor and may be of any
+    type.
+
+      >>> data = Data()
+      >>>
+      >>> data.put_array(False, Data.INT)
+      >>> data.enter()
+      >>> data.put_int(1)
+      >>> data.put_int(2)
+      >>> data.put_int(3)
+      >>> data.exit()
+      >>>
+      >>> data.put_array(True, Data.DOUBLE)
+      >>> data.enter()
+      >>> data.put_symbol("array-descriptor")
+      >>> data.put_double(1.1)
+      >>> data.put_double(1.2)
+      >>> data.put_double(1.3)
+      >>> data.exit()
+
+    @type described: bool
+    @param described: specifies whether the array is described
+    @type element_type: int
+    @param element_type: the type of the array elements
+    """
+    self._check(pn_data_put_array(self._data, described, element_type))
+
+  def put_described(self):
+    """
+    Puts a described value. A described node has two children, the
+    descriptor and the value. These are specified by entering the node
+    and putting the desired values.
+
+      >>> data = Data()
+      >>> data.put_described()
+      >>> data.enter()
+      >>> data.put_symbol("value-descriptor")
+      >>> data.put_string("the value")
+      >>> data.exit()
+    """
+    self._check(pn_data_put_described(self._data))
+
+  def put_null(self):
+    """
+    Puts a null value.
+    """
+    self._check(pn_data_put_null(self._data))
+
+  def put_bool(self, b):
+    """
+    Puts a boolean value.
+
+    @param b: a boolean value
+    """
+    self._check(pn_data_put_bool(self._data, b))
+
+  def put_ubyte(self, ub):
+    """
+    Puts an unsigned byte value.
+
+    @param ub: an integral value
+    """
+    self._check(pn_data_put_ubyte(self._data, ub))
+
+  def put_byte(self, b):
+    """
+    Puts a signed byte value.
+
+    @param b: an integral value
+    """
+    self._check(pn_data_put_byte(self._data, b))
+
+  def put_ushort(self, us):
+    """
+    Puts an unsigned short value.
+
+    @param us: an integral value.
+    """
+    self._check(pn_data_put_ushort(self._data, us))
+
+  def put_short(self, s):
+    """
+    Puts a signed short value.
+
+    @param s: an integral value
+    """
+    self._check(pn_data_put_short(self._data, s))
+
+  def put_uint(self, ui):
+    """
+    Puts an unsigned int value.
+
+    @param ui: an integral value
+    """
+    self._check(pn_data_put_uint(self._data, ui))
+
+  def put_int(self, i):
+    """
+    Puts a signed int value.
+
+    @param i: an integral value
+    """
+    self._check(pn_data_put_int(self._data, i))
+
+  def put_char(self, c):
+    """
+    Puts a char value.
+
+    @param c: a single character
+    """
+    self._check(pn_data_put_char(self._data, ord(c)))
+
+  def put_ulong(self, ul):
+    """
+    Puts an unsigned long value.
+
+    @param ul: an integral value
+    """
+    self._check(pn_data_put_ulong(self._data, ul))
+
+  def put_long(self, l):
+    """
+    Puts a signed long value.
+
+    @param l: an integral value
+    """
+    self._check(pn_data_put_long(self._data, l))
+
+  def put_timestamp(self, t):
+    """
+    Puts a timestamp value.
+
+    @param t: an integral value
+    """
+    self._check(pn_data_put_timestamp(self._data, t))
+
+  def put_float(self, f):
+    """
+    Puts a float value.
+
+    @param f: a floating point value
+    """
+    self._check(pn_data_put_float(self._data, f))
+
+  def put_double(self, d):
+    """
+    Puts a double value.
+
+    @param d: a floating point value.
+    """
+    self._check(pn_data_put_double(self._data, d))
+
+  def put_decimal32(self, d):
+    """
+    Puts a decimal32 value.
+
+    @param d: a decimal32 value
+    """
+    self._check(pn_data_put_decimal32(self._data, d))
+
+  def put_decimal64(self, d):
+    """
+    Puts a decimal64 value.
+
+    @param d: a decimal64 value
+    """
+    self._check(pn_data_put_decimal64(self._data, d))
+
+  def put_decimal128(self, d):
+    """
+    Puts a decimal128 value.
+
+    @param d: a decimal128 value
+    """
+    self._check(pn_data_put_decimal128(self._data, d))
+
+  def put_uuid(self, u):
+    """
+    Puts a UUID value.
+
+    @param u: a uuid value
+    """
+    self._check(pn_data_put_uuid(self._data, u.bytes))
+
+  def put_binary(self, b):
+    """
+    Puts a binary value.
+
+    @type b: binary
+    @param b: a binary value
+    """
+    self._check(pn_data_put_binary(self._data, b))
+
+  def put_string(self, s):
+    """
+    Puts a unicode value.
+
+    @type s: unicode
+    @param s: a unicode value
+    """
+    self._check(pn_data_put_string(self._data, s.encode("utf8")))
+
+  def put_symbol(self, s):
+    """
+    Puts a symbolic value.
+
+    @type s: string
+    @param s: the symbol name
+    """
+    self._check(pn_data_put_symbol(self._data, s))
+
+  def get_list(self):
+    """
+    If the current node is a list, return the number of elements,
+    otherwise return zero. List elements can be accessed by entering
+    the list.
+
+      >>> count = data.get_list()
+      >>> data.enter()
+      >>> for i in range(count):
+      ...   type = data.next()
+      ...   if type == Data.STRING:
+      ...     print data.get_string()
+      ...   elif type == ...:
+      ...     ...
+      >>> data.exit()
+    """
+    return pn_data_get_list(self._data)
+
+  def get_map(self):
+    """
+    If the current node is a map, return the number of child elements,
+    otherwise return zero. Key value pairs can be accessed by entering
+    the map.
+
+      >>> count = data.get_map()
+      >>> data.enter()
+      >>> for i in range(count/2):
+      ...   type = data.next()
+      ...   if type == Data.STRING:
+      ...     print data.get_string()
+      ...   elif type == ...:
+      ...     ...
+      >>> data.exit()
+    """
+    return pn_data_get_map(self._data)
+
+  def get_array(self):
+    """
+    If the current node is an array, return a tuple of the element
+    count, a boolean indicating whether the array is described, and
+    the type of each element, otherwise return (0, False, None). Array
+    data can be accessed by entering the array.
+
+      >>> # read an array of strings with a symbolic descriptor
+      >>> count, described, type = data.get_array()
+      >>> data.enter()
+      >>> data.next()
+      >>> print "Descriptor:", data.get_symbol()
+      >>> for i in range(count):
+      ...    data.next()
+      ...    print "Element:", data.get_string()
+      >>> data.exit()
+    """
+    count = pn_data_get_array(self._data)
+    described = pn_data_is_array_described(self._data)
+    type = pn_data_get_array_type(self._data)
+    if type == -1:
+      type = None
+    return count, described, type
+
+  def is_described(self):
+    """
+    Checks if the current node is a described value. The descriptor
+    and value may be accessed by entering the described value.
+
+      >>> # read a symbolically described string
+      >>> assert data.is_described() # will error if the current node is not described
+      >>> data.enter()
+      >>> print data.get_symbol()
+      >>> print data.get_string()
+      >>> data.exit()
+    """
+    return pn_data_is_described(self._data)
+
+  def is_null(self):
+    """
+    Checks if the current node is a null.
+    """
+    return pn_data_is_null(self._data)
+
+  def get_bool(self):
+    """
+    If the current node is a boolean, returns its value, returns False
+    otherwise.
+    """
+    return pn_data_get_bool(self._data)
+
+  def get_ubyte(self):
+    """
+    If the current node is an unsigned byte, returns its value,
+    returns 0 otherwise.
+    """
+    return pn_data_get_ubyte(self._data)
+
+  def get_byte(self):
+    """
+    If the current node is a signed byte, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_byte(self._data)
+
+  def get_ushort(self):
+    """
+    If the current node is an unsigned short, returns its value,
+    returns 0 otherwise.
+    """
+    return pn_data_get_ushort(self._data)
+
+  def get_short(self):
+    """
+    If the current node is a signed short, returns its value, returns
+    0 otherwise.
+    """
+    return pn_data_get_short(self._data)
+
+  def get_uint(self):
+    """
+    If the current node is an unsigned int, returns its value, returns
+    0 otherwise.
+    """
+    return pn_data_get_uint(self._data)
+
+  def get_int(self):
+    """
+    If the current node is a signed int, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_int(self._data)
+
+  def get_char(self):
+    """
+    If the current node is a char, returns its value, returns 0
+    otherwise.
+    """
+    return char(unichr(pn_data_get_char(self._data)))
+
+  def get_ulong(self):
+    """
+    If the current node is an unsigned long, returns its value,
+    returns 0 otherwise.
+    """
+    return ulong(pn_data_get_ulong(self._data))
+
+  def get_long(self):
+    """
+    If the current node is an signed long, returns its value, returns
+    0 otherwise.
+    """
+    return pn_data_get_long(self._data)
+
+  def get_timestamp(self):
+    """
+    If the current node is a timestamp, returns its value, returns 0
+    otherwise.
+    """
+    return timestamp(pn_data_get_timestamp(self._data))
+
+  def get_float(self):
+    """
+    If the current node is a float, returns its value, raises 0
+    otherwise.
+    """
+    return pn_data_get_float(self._data)
+
+  def get_double(self):
+    """
+    If the current node is a double, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_double(self._data)
+
+  # XXX: need to convert
+  def get_decimal32(self):
+    """
+    If the current node is a decimal32, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_decimal32(self._data)
+
+  # XXX: need to convert
+  def get_decimal64(self):
+    """
+    If the current node is a decimal64, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_decimal64(self._data)
+
+  # XXX: need to convert
+  def get_decimal128(self):
+    """
+    If the current node is a decimal128, returns its value, returns 0
+    otherwise.
+    """
+    return pn_data_get_decimal128(self._data)
+
+  def get_uuid(self):
+    """
+    If the current node is a UUID, returns its value, returns None
+    otherwise.
+    """
+    if pn_data_type(self._data) == Data.UUID:
+      return uuid.UUID(bytes=pn_data_get_uuid(self._data))
+    else:
+      return None
+
+  def get_binary(self):
+    """
+    If the current node is binary, returns its value, returns ""
+    otherwise.
+    """
+    return pn_data_get_binary(self._data)
+
+  def get_string(self):
+    """
+    If the current node is a string, returns its value, returns ""
+    otherwise.
+    """
+    return pn_data_get_string(self._data).decode("utf8")
+
+  def get_symbol(self):
+    """
+    If the current node is a symbol, returns its value, returns ""
+    otherwise.
+    """
+    return symbol(pn_data_get_symbol(self._data))
+
+  def copy(self, src):
+    self._check(pn_data_copy(self._data, src._data))
+
+  def format(self):
+    sz = 16
+    while True:
+      err, result = pn_data_format(self._data, sz)
+      if err == PN_OVERFLOW:
+        sz *= 2
+        continue
+      else:
+        self._check(err)
+        return result
+
+  def dump(self):
+    pn_data_dump(self._data)
+
+  def put_dict(self, d):
+    self.put_map()
+    self.enter()
+    try:
+      for k, v in d.items():
+        self.put_object(k)
+        self.put_object(v)
+    finally:
+      self.exit()
+
+  def get_dict(self):
+    if self.enter():
+      try:
+        result = {}
+        while self.next():
+          k = self.get_object()
+          if self.next():
+            v = self.get_object()
+          else:
+            v = None
+          result[k] = v
+      finally:
+        self.exit()
+      return result
+
+  def put_sequence(self, s):
+    self.put_list()
+    self.enter()
+    try:
+      for o in s:
+        self.put_object(o)
+    finally:
+      self.exit()
+
+  def get_sequence(self):
+    if self.enter():
+      try:
+        result = []
+        while self.next():
+          result.append(self.get_object())
+      finally:
+        self.exit()
+      return result
+
+  def get_py_described(self):
+    if self.enter():
+      try:
+        self.next()
+        descriptor = self.get_object()
+        self.next()
+        value = self.get_object()
+      finally:
+        self.exit()
+      return Described(descriptor, value)
+
+  def put_py_described(self, d):
+    self.put_described()
+    self.enter()
+    try:
+      self.put_object(d.descriptor)
+      self.put_object(d.value)
+    finally:
+      self.exit()
+
+  def get_py_array(self):
+    """
+    If the current node is an array, return an Array object
+    representing the array and its contents. Otherwise return None.
+    This is a convenience wrapper around get_array, enter, etc.
+    """
+
+    count, described, type = self.get_array()
+    if type is None: return None
+    if self.enter():
+      try:
+        if described:
+          self.next()
+          descriptor = self.get_object()
+        else:
+          descriptor = UNDESCRIBED
+        elements = []
+        while self.next():
+          elements.append(self.get_object())
+      finally:
+        self.exit()
+      return Array(descriptor, type, *elements)
+
+  def put_py_array(self, a):
+    described = a.descriptor != UNDESCRIBED
+    self.put_array(described, a.type)
+    self.enter()
+    try:
+      if described:
+        self.put_object(a.descriptor)
+      for e in a.elements:
+        self.put_object(e)
+    finally:
+      self.exit()
+
+  put_mappings = {
+    None.__class__: lambda s, _: s.put_null(),
+    bool: put_bool,
+    dict: put_dict,
+    list: put_sequence,
+    tuple: put_sequence,
+    unicode: put_string,
+    bytes: put_binary,
+    symbol: put_symbol,
+    int: put_long,
+    char: put_char,
+    long: put_long,
+    ulong: put_ulong,
+    timestamp: put_timestamp,
+    float: put_double,
+    uuid.UUID: put_uuid,
+    Described: put_py_described,
+    Array: put_py_array
+    }
+  get_mappings = {
+    NULL: lambda s: None,
+    BOOL: get_bool,
+    BYTE: get_byte,
+    UBYTE: get_ubyte,
+    SHORT: get_short,
+    USHORT: get_ushort,
+    INT: get_int,
+    UINT: get_uint,
+    CHAR: get_char,
+    LONG: get_long,
+    ULONG: get_ulong,
+    TIMESTAMP: get_timestamp,
+    FLOAT: get_float,
+    DOUBLE: get_double,
+    DECIMAL32: get_decimal32,
+    DECIMAL64: get_decimal64,
+    DECIMAL128: get_decimal128,
+    UUID: get_uuid,
+    BINARY: get_binary,
+    STRING: get_string,
+    SYMBOL: get_symbol,
+    DESCRIBED: get_py_described,
+    ARRAY: get_py_array,
+    LIST: get_sequence,
+    MAP: get_dict
+    }
+
+
+  def put_object(self, obj):
+    putter = self.put_mappings[obj.__class__]
+    putter(self, obj)
+
+  def get_object(self):
+    type = self.type()
+    if type is None: return None
+    getter = self.get_mappings.get(type)
+    if getter:
+      return getter(self)
+    else:
+      return UnmappedType(str(type))
+
+class ConnectionException(ProtonException):
+  pass
+
+class Endpoint(object):
+
+  LOCAL_UNINIT = PN_LOCAL_UNINIT
+  REMOTE_UNINIT = PN_REMOTE_UNINIT
+  LOCAL_ACTIVE = PN_LOCAL_ACTIVE
+  REMOTE_ACTIVE = PN_REMOTE_ACTIVE
+  LOCAL_CLOSED = PN_LOCAL_CLOSED
+  REMOTE_CLOSED  = PN_REMOTE_CLOSED
+
+  def __init__(self):
+    self.condition = None
+    self._release_invoked = False
+
+  def _release(self):
+    """Release the underlying C Engine resource."""
+    if not self._release_invoked:
+      for c in self._children:
+        c._release()
+      self._free_resource()
+      self.connection._releasing(self)
+      self._release_invoked = True
+
+  def _update_cond(self):
+    obj2cond(self.condition, self._get_cond_impl())
+
+  @property
+  def remote_condition(self):
+    return cond2obj(self._get_remote_cond_impl())
+
+  # the following must be provided by subclasses
+  def _get_cond_impl(self):
+      assert False, "Subclass must override this!"
+
+  def _get_remote_cond_impl(self):
+      assert False, "Subclass must override this!"
+
+class Condition:
+
+  def __init__(self, name, description=None, info=None):
+    self.name = name
+    self.description = description
+    self.info = info
+
+  def __repr__(self):
+    return "Condition(%s)" % ", ".join([repr(x) for x in
+                                        (self.name, self.description, self.info)
+                                        if x])
+
+  def __eq__(self, o):
+    if not isinstance(o, Condition): return False
+    return self.name == o.name and \
+        self.description == o.description and \
+        self.info == o.info
+
+def obj2cond(obj, cond):
+  pn_condition_clear(cond)
+  if obj:
+    pn_condition_set_name(cond, str(obj.name))
+    pn_condition_set_description(cond, obj.description)
+    info = Data(pn_condition_info(cond))
+    if obj.info:
+      info.put_object(obj.info)
+
+def cond2obj(cond):
+  if pn_condition_is_set(cond):
+    return Condition(pn_condition_get_name(cond),
+                     pn_condition_get_description(cond),
+                     dat2obj(pn_condition_info(cond)))
+  else:
+    return None
+
+def dat2obj(dimpl):
+  if dimpl:
+    d = Data(dimpl)
+    d.rewind()
+    d.next()
+    obj = d.get_object()
+    d.rewind()
+    return obj
+
+def obj2dat(obj, dimpl):
+  if obj is not None:
+    d = Data(dimpl)
+    d.put_object(obj)
+
+def secs2millis(secs):
+  return long(secs*1000)
+
+def millis2secs(millis):
+  return float(millis)/1000.0
+
+class Connection(Endpoint):
+
+  @staticmethod
+  def _wrap_connection(c_conn):
+    """Maintain only a single instance of this class for each Connection
+    object that exists in the the C Engine.  This is done by storing a (weak)
+    reference to the python instance in the context field of the C object.
+    """
+    if not c_conn: return None
+    py_conn = pn_void2py(pn_connection_get_context(c_conn))
+    if py_conn: return py_conn
+    wrapper = Connection(_conn=c_conn)
+    return wrapper
+
+  def __init__(self, _conn=None):
+    Endpoint.__init__(self)
+    if _conn:
+      self._conn = _conn
+    else:
+      self._conn = pn_connection()
+    pn_connection_set_context(self._conn, pn_py2void(self))
+    self.offered_capabilities = None
+    self.desired_capabilities = None
+    self.properties = None
+    self._sessions = set()
+
+  def __del__(self):
+    if hasattr(self, "_conn") and self._conn:
+      self._release()
+
+  def free(self):
+    self._release()
+
+  @property
+  def _children(self):
+    return self._sessions
+
+  @property
+  def connection(self):
+    return self
+
+  def _free_resource(self):
+    pn_connection_free(self._conn)
+
+  def _released(self):
+    self._conn = None
+
+  def _releasing(self, child):
+    coll = getattr(self, "_collector", None)
+    if coll: coll = coll()
+    if coll:
+      coll._contexts.add(child)
+    else:
+      child._released()
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, ConnectionException)
+      raise exc("[%s]: %s" % (err, pn_connection_error(self._conn)))
+    else:
+      return err
+
+  def _get_cond_impl(self):
+    return pn_connection_condition(self._conn)
+
+  def _get_remote_cond_impl(self):
+    return pn_connection_remote_condition(self._conn)
+
+  def collect(self, collector):
+    if collector is None:
+      pn_connection_collect(self._conn, None)
+    else:
+      pn_connection_collect(self._conn, collector._impl)
+    self._collector = weakref.ref(collector)
+
+  def _get_container(self):
+    return pn_connection_get_container(self._conn)
+  def _set_container(self, name):
+    return pn_connection_set_container(self._conn, name)
+
+  container = property(_get_container, _set_container)
+
+  def _get_hostname(self):
+    return pn_connection_get_hostname(self._conn)
+  def _set_hostname(self, name):
+    return pn_connection_set_hostname(self._conn, name)
+
+  hostname = property(_get_hostname, _set_hostname)
+
+  @property
+  def remote_container(self):
+    return pn_connection_remote_container(self._conn)
+
+  @property
+  def remote_hostname(self):
+    return pn_connection_remote_hostname(self._conn)
+
+  @property
+  def remote_offered_capabilities(self):
+    return dat2obj(pn_connection_remote_offered_capabilities(self._conn))
+
+  @property
+  def remote_desired_capabilities(self):
+    return dat2obj(pn_connection_remote_desired_capabilities(self._conn))
+
+  @property
+  def remote_properties(self):
+    return dat2obj(pn_connection_remote_properties(self._conn))
+
+  def open(self):
+    obj2dat(self.offered_capabilities,
+            pn_connection_offered_capabilities(self._conn))
+    obj2dat(self.desired_capabilities,
+            pn_connection_desired_capabilities(self._conn))
+    obj2dat(self.properties, pn_connection_properties(self._conn))
+    pn_connection_open(self._conn)
+
+  def close(self):
+    self._update_cond()
+    pn_connection_close(self._conn)
+
+  @property
+  def state(self):
+    return pn_connection_state(self._conn)
+
+  def session(self):
+    return Session._wrap_session(pn_session(self._conn))
+
+  def session_head(self, mask):
+    return Session._wrap_session(pn_session_head(self._conn, mask))
+
+  def link_head(self, mask):
+    return Link._wrap_link(pn_link_head(self._conn, mask))
+
+  @property
+  def work_head(self):
+    return Delivery._wrap_delivery(pn_work_head(self._conn))
+
+  @property
+  def error(self):
+    return pn_error_code(pn_connection_error(self._conn))
+
+class SessionException(ProtonException):
+  pass
+
+class Session(Endpoint):
+
+  @staticmethod
+  def _wrap_session(c_ssn):
+    """Maintain only a single instance of this class for each Session object that
+    exists in the C Engine.
+    """
+    if c_ssn is None: return None
+    py_ssn = pn_void2py(pn_session_get_context(c_ssn))
+    if py_ssn: return py_ssn
+    wrapper = Session(c_ssn)
+    return wrapper
+
+  def __init__(self, ssn):
+    Endpoint.__init__(self)
+    self._ssn = ssn
+    pn_session_set_context(self._ssn, pn_py2void(self))
+    self._links = set()
+    self.connection._sessions.add(self)
+
+  @property
+  def _children(self):
+    return self._links
+
+  def _free_resource(self):
+    pn_session_free(self._ssn)
+
+  def _released(self):
+    self._ssn = None
+
+  def free(self):
+    """Release the Session, freeing its resources.
+
+    Call this when you no longer need the session.  This will allow the
+    session's resources to be reclaimed.  Once called, you should no longer
+    reference the session.
+
+    """
+    self.connection._sessions.remove(self)
+    self._release()
+
+  def _get_cond_impl(self):
+    return pn_session_condition(self._ssn)
+
+  def _get_remote_cond_impl(self):
+    return pn_session_remote_condition(self._ssn)
+
+  def _get_incoming_capacity(self):
+    return pn_session_get_incoming_capacity(self._ssn)
+
+  def _set_incoming_capacity(self, capacity):
+    pn_session_set_incoming_capacity(self._ssn, capacity)
+
+  incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity)
+
+  @property
+  def outgoing_bytes(self):
+    return pn_session_outgoing_bytes(self._ssn)
+
+  @property
+  def incoming_bytes(self):
+    return pn_session_incoming_bytes(self._ssn)
+
+  def open(self):
+    pn_session_open(self._ssn)
+
+  def close(self):
+    self._update_cond()
+    pn_session_close(self._ssn)
+
+  def next(self, mask):
+    return Session._wrap_session(pn_session_next(self._ssn, mask))
+
+  @property
+  def state(self):
+    return pn_session_state(self._ssn)
+
+  @property
+  def connection(self):
+    return Connection._wrap_connection(pn_session_connection(self._ssn))
+
+  def sender(self, name):
+    return Link._wrap_link(pn_sender(self._ssn, name))
+
+  def receiver(self, name):
+    return Link._wrap_link(pn_receiver(self._ssn, name))
+
+class LinkException(ProtonException):
+  pass
+
+class Link(Endpoint):
+
+  SND_UNSETTLED = PN_SND_UNSETTLED
+  SND_SETTLED = PN_SND_SETTLED
+  SND_MIXED = PN_SND_MIXED
+
+  RCV_FIRST = PN_RCV_FIRST
+  RCV_SECOND = PN_RCV_SECOND
+
+  @staticmethod
+  def _wrap_link(c_link):
+    """Maintain only a single instance of this class for each Session object that
+    exists in the C Engine.
+    """
+    if c_link is None: return None
+    py_link = pn_void2py(pn_link_get_context(c_link))
+    if py_link: return py_link
+    if pn_link_is_sender(c_link):
+      wrapper = Sender(c_link)
+    else:
+      wrapper = Receiver(c_link)
+    return wrapper
+
+  def __init__(self, c_link):
+    Endpoint.__init__(self)
+    self._link = c_link
+    pn_link_set_context(self._link, pn_py2void(self))
+    self._deliveries = set()
+    self.session._links.add(self)
+
+  @property
+  def _children(self):
+    return self._deliveries
+
+  def _free_resource(self):
+    pn_link_free(self._link)
+
+  def _released(self):
+    self._link = None
+
+  def free(self):
+    """Release the Link, freeing its resources"""
+    self.session._links.remove(self)
+    self._release()
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, LinkException)
+      raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
+    else:
+      return err
+
+  def _get_cond_impl(self):
+    return pn_link_condition(self._link)
+
+  def _get_remote_cond_impl(self):
+    return pn_link_remote_condition(self._link)
+
+  def open(self):
+    pn_link_open(self._link)
+
+  def close(self):
+    self._update_cond()
+    pn_link_close(self._link)
+
+  @property
+  def state(self):
+    return pn_link_state(self._link)
+
+  @property
+  def source(self):
+    return Terminus(pn_link_source(self._link))
+
+  @property
+  def target(self):
+    return Terminus(pn_link_target(self._link))
+
+  @property
+  def remote_source(self):
+    return Terminus(pn_link_remote_source(self._link))
+  @property
+  def remote_target(self):
+    return Terminus(pn_link_remote_target(self._link))
+
+  @property
+  def session(self):
+    return Session._wrap_session(pn_link_session(self._link))
+
+  @property
+  def connection(self):
+    return self.session.connection
+
+  def delivery(self, tag):
+    return Delivery._wrap_delivery(pn_delivery(self._link, tag))
+
+  @property
+  def current(self):
+    return Delivery._wrap_delivery(pn_link_current(self._link))
+
+  def advance(self):
+    return pn_link_advance(self._link)
+
+  @property
+  def unsettled(self):
+    return pn_link_unsettled(self._link)
+
+  @property
+  def credit(self):
+    return pn_link_credit(self._link)
+
+  @property
+  def available(self):
+    return pn_link_available(self._link)
+
+  @property
+  def queued(self):
+    return pn_link_queued(self._link)
+
+  def next(self, mask):
+    return Link._wrap_link(pn_link_next(self._link, mask))
+
+  @property
+  def name(self):
+      return pn_link_name(self._link)
+
+  @property
+  def is_sender(self):
+    return pn_link_is_sender(self._link)
+
+  @property
+  def is_receiver(self):
+    return pn_link_is_receiver(self._link)
+
+  @property
+  def remote_snd_settle_mode(self):
+    return pn_link_remote_snd_settle_mode(self._link)
+
+  @property
+  def remote_rcv_settle_mode(self):
+    return pn_link_remote_rcv_settle_mode(self._link)
+
+  def _get_snd_settle_mode(self):
+    return pn_link_snd_settle_mode(self._link)
+  def _set_snd_settle_mode(self, mode):
+    pn_link_set_snd_settle_mode(self._link, mode)
+  snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode)
+
+  def _get_rcv_settle_mode(self):
+    return pn_link_rcv_settle_mode(self._link)
+  def _set_rcv_settle_mode(self, mode):
+    pn_link_set_rcv_settle_mode(self._link, mode)
+  rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode)
+
+  def drained(self):
+    return pn_link_drained(self._link)
+
+  def detach(self):
+    return pn_link_detach(self._link)
+
+class Terminus(object):
+
+  UNSPECIFIED = PN_UNSPECIFIED
+  SOURCE = PN_SOURCE
+  TARGET = PN_TARGET
+  COORDINATOR = PN_COORDINATOR
+
+  NONDURABLE = PN_NONDURABLE
+  CONFIGURATION = PN_CONFIGURATION
+  DELIVERIES = PN_DELIVERIES
+
+  DIST_MODE_UNSPECIFIED = PN_DIST_MODE_UNSPECIFIED
+  DIST_MODE_COPY = PN_DIST_MODE_COPY
+  DIST_MODE_MOVE = PN_DIST_MODE_MOVE
+
+  def __init__(self, impl):
+    self._impl = impl
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, LinkException)
+      raise exc("[%s]" % err)
+    else:
+      return err
+
+  def _get_type(self):
+    return pn_terminus_get_type(self._impl)
+  def _set_type(self, type):
+    self._check(pn_terminus_set_type(self._impl, type))
+  type = property(_get_type, _set_type)
+
+  def _get_address(self):
+    return pn_terminus_get_address(self._impl)
+  def _set_address(self, address):
+    self._check(pn_terminus_set_address(self._impl, address))
+  address = property(_get_address, _set_address)
+
+  def _get_durability(self):
+    return pn_terminus_get_durability(self._impl)
+  def _set_durability(self, seconds):
+    self._check(pn_terminus_set_durability(self._impl, seconds))
+  durability = property(_get_durability, _set_durability)
+
+  def _get_expiry_policy(self):
+    return pn_terminus_get_expiry_policy(self._impl)
+  def _set_expiry_policy(self, seconds):
+    self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
+  expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
+
+  def _get_timeout(self):
+    return pn_terminus_get_timeout(self._impl)
+  def _set_timeout(self, seconds):
+    self._check(pn_terminus_set_timeout(self._impl, seconds))
+  timeout = property(_get_timeout, _set_timeout)
+
+  def _is_dynamic(self):
+    return pn_terminus_is_dynamic(self._impl)
+  def _set_dynamic(self, dynamic):
+    self._check(pn_terminus_set_dynamic(self._impl, dynamic))
+  dynamic = property(_is_dynamic, _set_dynamic)
+
+  def _get_distribution_mode(self):
+    return pn_terminus_get_distribution_mode(self._impl)
+  def _set_distribution_mode(self, mode):
+    self._check(pn_terminus_set_distribution_mode(self._impl, mode))
+  distribution_mode = property(_get_distribution_mode, _set_distribution_mode)
+
+  @property
+  def properties(self):
+    return Data(pn_terminus_properties(self._impl))
+
+  @property
+  def capabilities(self):
+    return Data(pn_terminus_capabilities(self._impl))
+
+  @property
+  def outcomes(self):
+    return Data(pn_terminus_outcomes(self._impl))
+
+  @property
+  def filter(self):
+    return Data(pn_terminus_filter(self._impl))
+
+  def copy(self, src):
+    self._check(pn_terminus_copy(self._impl, src._impl))
+
+class Sender(Link):
+
+  def __init__(self, c_link):
+    super(Sender, self).__init__(c_link)
+
+  def offered(self, n):
+    pn_link_offered(self._link, n)
+
+  def send(self, bytes):
+    return self._check(pn_link_send(self._link, bytes))
+
+class Receiver(Link):
+
+  def __init__(self, c_link):
+    super(Receiver, self).__init__(c_link)
+
+  def flow(self, n):
+    pn_link_flow(self._link, n)
+
+  def recv(self, limit):
+    n, bytes = pn_link_recv(self._link, limit)
+    if n == PN_EOS:
+      return None
+    else:
+      self._check(n)
+      return bytes
+
+  def drain(self, n):
+    pn_link_drain(self._link, n)
+
+  def draining(self):
+    return pn_link_draining(self._link)
+
+class NamedInt(int):
+
+  values = {}
+
+  def __new__(cls, i, name):
+    ni = super(NamedInt, cls).__new__(cls, i)
+    cls.values[i] = ni
+    return ni
+
+  def __init__(self, i, name):
+    self.name = name
+
+  def __repr__(self):
+    return self.name
+
+  def __str__(self):
+    return self.name
+
+  @classmethod
+  def get(cls, i):
+    return cls.values.get(i, i)
+
+class DispositionType(NamedInt):
+  values = {}
+
+class Disposition(object):
+
+  RECEIVED = DispositionType(PN_RECEIVED, "RECEIVED")
+  ACCEPTED = DispositionType(PN_ACCEPTED, "ACCEPTED")
+  REJECTED = DispositionType(PN_REJECTED, "REJECTED")
+  RELEASED = DispositionType(PN_RELEASED, "RELEASED")
+  MODIFIED = DispositionType(PN_MODIFIED, "MODIFIED")
+
+  def __init__(self, impl, local):
+    self._impl = impl
+    self.local = local
+    self._data = None
+    self._condition = None
+    self._annotations = None
+
+  @property
+  def type(self):
+    return DispositionType.get(pn_disposition_type(self._impl))
+
+  def _get_section_number(self):
+    return pn_disposition_get_section_number(self._impl)
+  def _set_section_number(self, n):
+    pn_disposition_set_section_number(self._impl, n)
+  section_number = property(_get_section_number, _set_section_number)
+
+  def _get_section_offset(self):
+    return pn_disposition_get_section_offset(self._impl)
+  def _set_section_offset(self, n):
+    pn_disposition_set_section_offset(self._impl, n)
+  section_offset = property(_get_section_offset, _set_section_offset)
+
+  def _get_failed(self):
+    return pn_disposition_is_failed(self._impl)
+  def _set_failed(self, b):
+    pn_disposition_set_failed(self._impl, b)
+  failed = property(_get_failed, _set_failed)
+
+  def _get_undeliverable(self):
+    return pn_disposition_is_undeliverable(self._impl)
+  def _set_undeliverable(self, b):
+    pn_disposition_set_undeliverable(self._impl, b)
+  undeliverable = property(_get_undeliverable, _set_undeliverable)
+
+  def _get_data(self):
+    if self.local:
+      return self._data
+    else:
+      return dat2obj(pn_disposition_data(self._impl))
+  def _set_data(self, obj):
+    if self.local:
+      self._data = obj
+    else:
+      raise AttributeError("data attribute is read-only")
+  data = property(_get_data, _set_data)
+
+  def _get_annotations(self):
+    if self.local:
+      return self._annotations
+    else:
+      return dat2obj(pn_disposition_annotations(self._impl))
+  def _set_annotations(self, obj):
+    if self.local:
+      self._annotations = obj
+    else:
+      raise AttributeError("annotations attribute is read-only")
+  annotations = property(_get_annotations, _set_annotations)
+
+  def _get_condition(self):
+    if self.local:
+      return self._condition
+    else:
+      return cond2obj(pn_disposition_condition(self._impl))
+  def _set_condition(self, obj):
+    if self.local:
+      self._condition = obj
+    else:
+      raise AttributeError("condition attribute is read-only")
+  condition = property(_get_condition, _set_condition)
+
+class Delivery(object):
+
+  RECEIVED = Disposition.RECEIVED
+  ACCEPTED = Disposition.ACCEPTED
+  REJECTED = Disposition.REJECTED
+  RELEASED = Disposition.RELEASED
+  MODIFIED = Disposition.MODIFIED
+
+  @staticmethod
+  def _wrap_delivery(c_dlv):
+    """Maintain only a single instance of this class for each Delivery object that
+    exists in the C Engine.
+    """
+    if not c_dlv: return None
+    py_dlv = pn_void2py(pn_delivery_get_context(c_dlv))
+    if py_dlv: return py_dlv
+    wrapper = Delivery(c_dlv)
+    return wrapper
+
+  def __init__(self, dlv):
+    self._dlv = dlv
+    pn_delivery_set_context(self._dlv, pn_py2void(self))
+    self.local = Disposition(pn_delivery_local(self._dlv), True)
+    self.remote = Disposition(pn_delivery_remote(self._dlv), False)
+    self.link._deliveries.add(self)
+
+  def __del__(self):
+    self._release()
+
+  def _release(self):
+    """Release the underlying C Engine resource."""
+    if self._dlv:
+      pn_delivery_set_context(self._dlv, pn_py2void(None))
+      pn_delivery_settle(self._dlv)
+      self._dlv = None
+
+  @property
+  def released(self):
+    return self._dlv is None
+
+  @property
+  def tag(self):
+    return pn_delivery_tag(self._dlv)
+
+  @property
+  def writable(self):
+    return pn_delivery_writable(self._dlv)
+
+  @property
+  def readable(self):
+    return pn_delivery_readable(self._dlv)
+
+  @property
+  def updated(self):
+    return pn_delivery_updated(self._dlv)
+
+  def update(self, state):
+    obj2dat(self.local._data, pn_disposition_data(self.local._impl))
+    obj2dat(self.local._annotations, pn_disposition_annotations(self.local._impl))
+    obj2cond(self.local._condition, pn_disposition_condition(self.local._impl))
+    pn_delivery_update(self._dlv, state)
+
+  @property
+  def pending(self):
+    return pn_delivery_pending(self._dlv)
+
+  @property
+  def partial(self):
+    return pn_delivery_partial(self._dlv)
+
+  @property
+  def local_state(self):
+    return DispositionType.get(pn_delivery_local_state(self._dlv))
+
+  @property
+  def remote_state(self):
+    return DispositionType.get(pn_delivery_remote_state(self._dlv))
+
+  @property
+  def settled(self):
+    return pn_delivery_settled(self._dlv)
+
+  def settle(self):
+    """Release the delivery"""
+    self.link._deliveries.remove(self)
+    self._release()
+
+  @property
+  def work_next(self):
+    return Delivery._wrap_delivery(pn_work_next(self._dlv))
+
+  @property
+  def link(self):
+    return Link._wrap_link(pn_delivery_link(self._dlv))
+
+class TransportException(ProtonException):
+  pass
+
+class Transport(object):
+
+  TRACE_OFF = PN_TRACE_OFF
+  TRACE_DRV = PN_TRACE_DRV
+  TRACE_FRM = PN_TRACE_FRM
+  TRACE_RAW = PN_TRACE_RAW
+
+  CLIENT = 1
+  SERVER = 2
+
+  @staticmethod
+  def _wrap_transport(c_trans):
+    if not c_trans: return None
+    wrapper = Transport(_trans=c_trans)
+    return wrapper
+
+  def __init__(self, mode=None, _trans=None):
+    if not mode and not _trans:
+      self._trans = pn_transport()
+    elif not mode:
+      self._shared_trans = True
+      self._trans = _trans
+    elif mode==Transport.CLIENT:
+      self._trans = pn_transport()
+    elif mode==Transport.SERVER:
+      self._trans = pn_transport()
+      pn_transport_set_server(self._trans)
+    else:
+      raise TransportException("Cannot initialise Transport from mode: %s" % str(mode))
+    self._sasl = None
+    self._ssl = None
+
+  def __del__(self):
+    if hasattr(self, "_trans"):
+      if not hasattr(self, "_shared_trans"):
+        pn_transport_free(self._trans)
+        if hasattr(self, "_sasl") and self._sasl:
+            # pn_transport_free deallocs the C sasl associated with the
+            # transport, so erase the reference if a SASL object was used.
+            self._sasl._sasl = None
+            self._sasl = None
+        if hasattr(self, "_ssl") and self._ssl:
+            # ditto the owned c SSL object
+            self._ssl._ssl = None
+            self._ssl = None
+      del self._trans
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, TransportException)
+      raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans))))
+    else:
+      return err
+
+  def bind(self, connection):
+    """Assign a connection to the transport"""
+    self._check(pn_transport_bind(self._trans, connection._conn))
+    # keep python connection from being garbage collected:
+    self._connection = connection
+
+  def unbind(self):
+    """Release the connection"""
+    self._check(pn_transport_unbind(self._trans))
+    self._connection = None
+
+  def trace(self, n):
+    pn_transport_trace(self._trans, n)
+
+  def tick(self, now):
+    """Process any timed events (like heartbeat generation).
+    now = seconds since epoch (float).
+    """
+    return millis2secs(pn_transport_tick(self._trans, secs2millis(now)))
+
+  def capacity(self):
+    c = pn_transport_capacity(self._trans)
+    if c >= PN_EOS:
+      return c
+    else:
+      return self._check(c)
+
+  def push(self, bytes):
+    n = self._check(pn_transport_push(self._trans, bytes))
+    if n != len(bytes):
+      raise OverflowError("unable to process all bytes")
+
+  def close_tail(self):
+    self._check(pn_transport_close_tail(self._trans))
+
+  def pending(self):
+    p = pn_transport_pending(self._trans)
+    if p >= PN_EOS:
+      return p
+    else:
+      return self._check(p)
+
+  def peek(self, size):
+    cd, out = pn_transport_peek(self._trans, size)
+    if cd == PN_EOS:
+      return None
+    else:
+      self._check(cd)
+      return out
+
+  def pop(self, size):
+    pn_transport_pop(self._trans, size)
+
+  def close_head(self):
+    self._check(pn_transport_close_head(self._trans))
+
+  @property
+  def closed(self):
+    return pn_transport_closed(self._trans)
+
+  # AMQP 1.0 max-frame-size
+  def _get_max_frame_size(self):
+    return pn_transport_get_max_frame(self._tra

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[10/35] qpid-proton git commit: PROTON-747: Around wrappers for Ruby Messenger methods that raise errors

Posted by gs...@apache.org.
PROTON-747: Around wrappers for Ruby Messenger methods that raise errors

Each method that could potentially raise an exception in
Qpid::Proton::Message is now wrapped by a method which checks for, and
then raises, the appropriate runtime error based on the error code.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/66150aa7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/66150aa7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/66150aa7

Branch: refs/heads/examples
Commit: 66150aa7a845c2210ab7c1b0c0e011988a60de2e
Parents: 0d1b8a8
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Fri Nov 14 09:45:17 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Tue Nov 18 09:34:43 2014 -0500

----------------------------------------------------------------------
 .../ruby/lib/qpid_proton/exception_handling.rb  | 43 +++++++++++++++++
 .../bindings/ruby/lib/qpid_proton/messenger.rb  | 50 ++++++++++++++------
 2 files changed, 79 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/66150aa7/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
index f8ac8c6..4dce3ef 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
@@ -25,6 +25,49 @@ module Qpid
     #
     module ExceptionHandling
 
+      def self.included(base)
+        base.extend(self)
+
+        unless defined? base.to_be_wrapped
+          class << base
+            @@to_be_wrapped = []
+          end
+        end
+
+        define_method :method_added do |name|
+          if (!@@to_be_wrapped.nil?) && (@@to_be_wrapped.include? name)
+            @@to_be_wrapped.delete name
+            create_exception_handler_wrapper(name)
+          end
+        end
+      end
+
+      def can_raise_exception(method_names)
+        # coerce the names to be an array
+        Array(method_names).each do |method_name|
+          # if the method doesn't already exist then queue this aliasing
+          unless self.method_defined? method_name
+            @@to_be_wrapped ||= []
+            @@to_be_wrapped << method_name
+          else
+            create_exception_handler_wrapper(method_name)
+          end
+        end
+      end
+
+      def create_exception_handler_wrapper(method_name)
+        original_method_name = method_name.to_s
+        wrapped_method_name = "_excwrap_#{original_method_name}"
+        alias_method wrapped_method_name, original_method_name
+        define_method original_method_name do |*args, &block|
+          # need to get a reference to the method object itself since
+          # calls to Class.send interfere with Messenger.send
+          method = self.method(wrapped_method_name.to_sym)
+          rc = method.call(*args, &block)
+          check_for_error(rc)
+        end
+      end
+
       # Raises an Proton-specific error if a return code is non-zero.
       #
       # Expects the class to provide an +error+ method.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/66150aa7/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index 044a3ad..66a2f93 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -59,6 +59,11 @@ module Qpid
 
       include Qpid::Proton::ExceptionHandling
 
+      can_raise_exception [:send, :receive, :password=, :start, :stop,
+                           :perform_put, :perform_get, :interrupt,
+                           :route, :rewrite, :accept, :reject,
+                           :incoming_window=, :outgoing_window=]
+
       # Creates a new +Messenger+.
       #
       # The +name+ parameter is optional. If one is not provided then
@@ -94,7 +99,7 @@ module Qpid
       # * password - the password
       #
       def password=(password)
-        check_for_error(Cproton.pn_messenger_set_password(@impl, password))
+        Cproton.pn_messenger_set_password(@impl, password)
       end
 
       # Returns the password property for the Messenger.private_key file.
@@ -193,14 +198,14 @@ module Qpid
       # before starting the +Messenger+.
       #
       def start
-        check_for_error(Cproton.pn_messenger_start(@impl))
+        Cproton.pn_messenger_start(@impl)
       end
 
       # Stops the +Messenger+, preventing it from sending or receiving
       # any more messages.
       #
       def stop
-        check_for_error(Cproton.pn_messenger_stop(@impl))
+        Cproton.pn_messenger_stop(@impl)
       end
 
       # Returns true iff a Messenger is in the stopped state.
@@ -313,10 +318,19 @@ module Qpid
         raise ArgumentError.new("invalid message type: #{message.class}") unless message.kind_of?(Message)
         # encode the message first
         message.pre_encode
-        check_for_error(Cproton.pn_messenger_put(@impl, message.impl))
+        perform_put(message)
         return outgoing_tracker
       end
 
+      private
+
+      def perform_put(message) # :nodoc:
+        Cproton.pn_messenger_put(@impl, message.impl)
+      end
+
+      public
+
+
       # This call will block until the indicated number of messages
       # have been sent, or until the operation times out.
       # If n is -1 this call will block until all outgoing messages
@@ -324,7 +338,7 @@ module Qpid
       # it can without blocking.
       #
       def send(n = -1)
-        check_for_error(Cproton.pn_messenger_send(@impl, n))
+        Cproton.pn_messenger_send(@impl, n)
       end
 
       # Moves the message from the head of the incoming message queue into
@@ -348,11 +362,19 @@ module Qpid
         else
           msg_impl = msg.impl
         end
-        check_for_error(Cproton.pn_messenger_get(@impl, msg_impl))
+        perform_get(msg_impl)
         msg.post_decode unless msg.nil?
         return incoming_tracker
       end
 
+      private
+
+      def perform_get(msg) # :nodoc:
+        Cproton.pn_messenger_get(@impl, msg)
+      end
+
+      public
+
       # Receives up to limit messages into the incoming queue.  If no value
       # for limit is supplied, this call will receive as many messages as it
       # can buffer internally.  If the Messenger is in blocking mode, this
@@ -364,7 +386,7 @@ module Qpid
       # * limit - the maximum number of messages to receive
       #
       def receive(limit = -1)
-        check_for_error(Cproton.pn_messenger_recv(@impl, limit))
+        Cproton.pn_messenger_recv(@impl, limit)
       end
 
       def receiving
@@ -384,7 +406,7 @@ module Qpid
       # originated the interrupt.
       #
       def interrupt
-        check_for_error(Cproton.pn_messenger_interrupt(@impl))
+        Cproton.pn_messenger_interrupt(@impl)
       end
 
       # Sends or receives any outstanding messages queued for a Messenger.
@@ -472,7 +494,7 @@ module Qpid
       #   messenger.route("*", "amqp://user:password@broker/$1")
       #
       def route(pattern, address)
-        check_for_error(Cproton.pn_messenger_route(@impl, pattern, address))
+        Cproton.pn_messenger_route(@impl, pattern, address)
       end
 
       # Similar to #route, except that the destination of
@@ -494,7 +516,7 @@ module Qpid
       # * address - the target address
       #
       def rewrite(pattern, address)
-        check_for_error(Cproton.pn_messenger_rewrite(@impl, pattern, address))
+        Cproton.pn_messenger_rewrite(@impl, pattern, address)
       end
 
       def selectable
@@ -548,7 +570,7 @@ module Qpid
         else
           flag = 0
         end
-        check_for_error(Cproton.pn_messenger_accept(@impl, tracker.impl, flag))
+        Cproton.pn_messenger_accept(@impl, tracker.impl, flag)
       end
 
       # Rejects the incoming message identified by the tracker.
@@ -568,7 +590,7 @@ module Qpid
         else
           flag = 0
         end
-        check_for_error(Cproton.pn_messenger_reject(@impl, tracker.impl, flag))
+        Cproton.pn_messenger_reject(@impl, tracker.impl, flag)
       end
 
       # Gets the last known remote state of the delivery associated with
@@ -624,7 +646,7 @@ module Qpid
       #
       def incoming_window=(window)
         raise TypeError.new("invalid window: #{window}") unless valid_window?(window)
-        check_for_error(Cproton.pn_messenger_set_incoming_window(@impl, window))
+        Cproton.pn_messenger_set_incoming_window(@impl, window)
       end
 
       # Returns the incoming window.
@@ -648,7 +670,7 @@ module Qpid
       #
       def outgoing_window=(window)
         raise TypeError.new("invalid window: #{window}") unless valid_window?(window)
-        check_for_error(Cproton.pn_messenger_set_outgoing_window(@impl, window))
+        Cproton.pn_messenger_set_outgoing_window(@impl, window)
       end
 
       # Returns the outgoing window.


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[04/35] qpid-proton git commit: PROTON-749: Refactoring of io layers: - Eliminate some unnecessary stuff. - Make pn_io_layer_t a pure interface. - Simplify amqp header code; remove header_count member from pn_transport_t

Posted by gs...@apache.org.
PROTON-749: Refactoring of io layers:
- Eliminate some unnecessary stuff.
- Make pn_io_layer_t a pure interface.
- Simplify amqp header code; remove header_count member from pn_transport_t


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/c814d5c3
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/c814d5c3
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/c814d5c3

Branch: refs/heads/examples
Commit: c814d5c39147afa642e95e1b1ad51650b04d9739
Parents: 2794da5
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Aug 6 17:57:56 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Mon Nov 17 14:55:03 2014 -0500

----------------------------------------------------------------------
 proton-c/src/engine/engine-internal.h |  20 ++-
 proton-c/src/sasl/sasl.c              | 128 +++++++++++-------
 proton-c/src/ssl/openssl.c            | 143 +++++++++++---------
 proton-c/src/transport/transport.c    | 204 ++++++++++++++---------------
 proton-c/src/windows/schannel.c       | 155 ++++++++++++----------
 5 files changed, 354 insertions(+), 296 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c814d5c3/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index dd4c44e..86f5161 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -100,18 +100,16 @@ typedef struct {
 #include <proton/ssl.h>
 
 typedef struct pn_io_layer_t {
-  void *context;
-  struct pn_io_layer_t *next;
-  ssize_t (*process_input)(struct pn_io_layer_t *io_layer, const char *, size_t);
-  ssize_t (*process_output)(struct pn_io_layer_t *io_layer, char *, size_t);
-  pn_timestamp_t (*process_tick)(struct pn_io_layer_t *io_layer, pn_timestamp_t);
-  size_t (*buffered_output)(struct pn_io_layer_t *);  // how much output is held
-  size_t (*buffered_input)(struct pn_io_layer_t *);   // how much input is held
+  ssize_t (*process_input)(struct pn_transport_t *transport, unsigned int layer, const char *, size_t);
+  ssize_t (*process_output)(struct pn_transport_t *transport, unsigned int layer, char *, size_t);
+  pn_timestamp_t (*process_tick)(struct pn_transport_t *transport, unsigned int layer, pn_timestamp_t);
+  size_t (*buffered_output)(struct pn_transport_t *);  // how much output is held
 } pn_io_layer_t;
 
+extern const pn_io_layer_t pni_passthru_layer;
+
 struct pn_transport_t {
   pn_tracer_t tracer;
-  size_t header_count;
   pn_sasl_t *sasl;
   pn_ssl_t *ssl;
   pn_connection_t *connection;  // reference counted
@@ -134,7 +132,7 @@ struct pn_transport_t {
 #define PN_IO_SASL 1
 #define PN_IO_AMQP 2
 #define PN_IO_LAYER_CT (PN_IO_AMQP+1)
-  pn_io_layer_t io_layers[PN_IO_LAYER_CT];
+  const pn_io_layer_t *io_layers[PN_IO_LAYER_CT];
 
   /* dead remote detection */
   pn_millis_t local_idle_timeout;
@@ -302,9 +300,7 @@ void pn_link_dump(pn_link_t *link);
 void pn_dump(pn_connection_t *conn);
 void pn_transport_sasl_init(pn_transport_t *transport);
 
-ssize_t pn_io_layer_input_passthru(pn_io_layer_t *, const char *, size_t );
-ssize_t pn_io_layer_output_passthru(pn_io_layer_t *, char *, size_t );
-pn_timestamp_t pn_io_layer_tick_passthru(pn_io_layer_t *, pn_timestamp_t);
+pn_timestamp_t pn_io_layer_tick_passthru(pn_transport_t *, unsigned int, pn_timestamp_t);
 
 void pn_condition_init(pn_condition_t *condition);
 void pn_condition_tini(pn_condition_t *condition);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c814d5c3/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index a82ec02..97bead4 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -36,7 +36,6 @@
 
 struct pn_sasl_t {
   pn_transport_t *transport;
-  pn_io_layer_t *io_layer;
   pn_dispatcher_t *disp;
   char *mechanisms;
   char *remote_mechanisms;
@@ -50,12 +49,42 @@ struct pn_sasl_t {
   bool rcvd_init;
   bool sent_done;
   bool rcvd_done;
+  bool input_bypass;
+  bool output_bypass;
 };
 
-static ssize_t pn_input_read_sasl_header(pn_io_layer_t *io_layer, const char *bytes, size_t available);
-static ssize_t pn_input_read_sasl(pn_io_layer_t *io_layer, const char *bytes, size_t available);
-static ssize_t pn_output_write_sasl_header(pn_io_layer_t *io_layer, char *bytes, size_t available);
-static ssize_t pn_output_write_sasl(pn_io_layer_t *io_layer, char *bytes, size_t available);
+static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available);
+static ssize_t pn_input_read_sasl(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
+static ssize_t pn_output_write_sasl_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t size);
+static ssize_t pn_output_write_sasl(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
+
+const pn_io_layer_t sasl_headers_layer = {
+    pn_input_read_sasl_header,
+    pn_output_write_sasl_header,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t sasl_write_header_layer = {
+    pn_input_read_sasl,
+    pn_output_write_sasl_header,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t sasl_read_header_layer = {
+    pn_input_read_sasl_header,
+    pn_output_write_sasl,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t sasl_layer = {
+    pn_input_read_sasl,
+    pn_output_write_sasl,
+    pn_io_layer_tick_passthru,
+    NULL
+};
 
 pn_sasl_t *pn_sasl(pn_transport_t *transport)
 {
@@ -76,14 +105,12 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
     sasl->rcvd_init = false;
     sasl->sent_done = false;
     sasl->rcvd_done = false;
+    sasl->input_bypass = false;
+    sasl->output_bypass = false;
 
     transport->sasl = sasl;
     sasl->transport = transport;
-    sasl->io_layer = &transport->io_layers[PN_IO_SASL];
-    sasl->io_layer->context = sasl;
-    sasl->io_layer->process_input = pn_input_read_sasl_header;
-    sasl->io_layer->process_output = pn_output_write_sasl_header;
-    sasl->io_layer->process_tick = pn_io_layer_tick_passthru;
+    transport->io_layers[PN_IO_SASL] = &sasl_headers_layer;
   }
 
   return transport->sasl;
@@ -404,9 +431,9 @@ int pn_do_outcome(pn_dispatcher_t *disp)
 #define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
 #define SASL_HEADER_LEN 8
 
-static ssize_t pn_input_read_sasl_header(pn_io_layer_t *io_layer, const char *bytes, size_t available)
+static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = (pn_sasl_t *)io_layer->context;
+  pn_sasl_t *sasl = transport->sasl;
   if (available > 0) {
     if (available < SASL_HEADER_LEN) {
       if (memcmp(bytes, SASL_HEADER, available) == 0 ||
@@ -414,20 +441,22 @@ static ssize_t pn_input_read_sasl_header(pn_io_layer_t *io_layer, const char *by
         return 0;
     } else {
       if (memcmp(bytes, SASL_HEADER, SASL_HEADER_LEN) == 0) {
-        sasl->io_layer->process_input = pn_input_read_sasl;
+        if (transport->io_layers[layer] == &sasl_read_header_layer) {
+          transport->io_layers[layer] = &sasl_layer;
+        } else {
+          transport->io_layers[layer] = &sasl_write_header_layer;
+        }
         if (sasl->disp->trace & PN_TRACE_FRM)
-          pn_transport_logf(sasl->transport, "  <- %s", "SASL");
+          pn_transport_logf(transport, "  <- %s", "SASL");
         return SASL_HEADER_LEN;
       }
       if (memcmp(bytes, AMQP_HEADER, SASL_HEADER_LEN) == 0) {
         if (sasl->allow_skip) {
           sasl->outcome = PN_SASL_SKIPPED;
-          sasl->io_layer->process_input = pn_io_layer_input_passthru;
-          sasl->io_layer->process_output = pn_io_layer_output_passthru;
-          pn_io_layer_t *io_next = sasl->io_layer->next;
-          return io_next->process_input( io_next, bytes, available );
+          transport->io_layers[layer] = &pni_passthru_layer;
+          return pni_passthru_layer.process_input(transport, layer, bytes, available);
         } else {
-            pn_do_error(sasl->transport, "amqp:connection:policy-error",
+            pn_do_error(transport, "amqp:connection:policy-error",
                         "Client skipped SASL exchange - forbidden");
             return PN_EOS;
         }
@@ -436,50 +465,57 @@ static ssize_t pn_input_read_sasl_header(pn_io_layer_t *io_layer, const char *by
   }
   char quoted[1024];
   pn_quote_data(quoted, 1024, bytes, available);
-  pn_do_error(sasl->transport, "amqp:connection:framing-error",
+  pn_do_error(transport, "amqp:connection:framing-error",
               "%s header mismatch: '%s'", "SASL", quoted);
   return PN_EOS;
 }
 
-static ssize_t pn_input_read_sasl(pn_io_layer_t *io_layer, const char *bytes, size_t available)
+static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = (pn_sasl_t *)io_layer->context;
-  ssize_t n = pn_sasl_input(sasl, bytes, available);
-  if (n == PN_EOS) {
-    sasl->io_layer->process_input = pn_io_layer_input_passthru;
-    pn_io_layer_t *io_next = sasl->io_layer->next;
-    return io_next->process_input( io_next, bytes, available );
+  pn_sasl_t *sasl = transport->sasl;
+  if (!sasl->input_bypass) {
+    ssize_t n = pn_sasl_input(sasl, bytes, available);
+    if (n != PN_EOS) return n;
+
+    sasl->input_bypass = true;
+    if (sasl->output_bypass)
+        transport->io_layers[layer] = &pni_passthru_layer;
   }
-  return n;
+  return pni_passthru_layer.process_input(transport, layer, bytes, available );
 }
 
-static ssize_t pn_output_write_sasl_header(pn_io_layer_t *io_layer, char *bytes, size_t size)
+static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t size)
 {
-  pn_sasl_t *sasl = (pn_sasl_t *)io_layer->context;
+  pn_sasl_t *sasl = transport->sasl;
   if (sasl->disp->trace & PN_TRACE_FRM)
-    pn_transport_logf(sasl->transport, "  -> %s", "SASL");
+    pn_transport_logf(transport, "  -> %s", "SASL");
   assert(size >= SASL_HEADER_LEN);
   memmove(bytes, SASL_HEADER, SASL_HEADER_LEN);
-  sasl->io_layer->process_output = pn_output_write_sasl;
+  if (transport->io_layers[layer]==&sasl_write_header_layer) {
+      transport->io_layers[layer] = &sasl_layer;
+  } else {
+      transport->io_layers[layer] = &sasl_read_header_layer;
+  }
   return SASL_HEADER_LEN;
 }
 
-static ssize_t pn_output_write_sasl(pn_io_layer_t *io_layer, char *bytes, size_t size)
+static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
 {
-  pn_sasl_t *sasl = (pn_sasl_t *)io_layer->context;
-  // this accounts for when pn_do_error is invoked, e.g. by idle timeout
-  ssize_t n;
-  if (sasl->transport->close_sent) {
-    n = PN_EOS;
-  } else {
-    n = pn_sasl_output(sasl, bytes, size);
-  }
+  pn_sasl_t *sasl = transport->sasl;
+  if (!sasl->output_bypass) {
+    // this accounts for when pn_do_error is invoked, e.g. by idle timeout
+    ssize_t n;
+    if (transport->close_sent) {
+        n = PN_EOS;
+    } else {
+        n = pn_sasl_output(sasl, bytes, available);
+    }
+    if (n != PN_EOS) return n;
 
-  if (n == PN_EOS) {
-    sasl->io_layer->process_output = pn_io_layer_output_passthru;
-    pn_io_layer_t *io_next = sasl->io_layer->next;
-    return io_next->process_output( io_next, bytes, size );
+    sasl->output_bypass = true;
+    if (sasl->input_bypass)
+        transport->io_layers[layer] = &pni_passthru_layer;
   }
-  return n;
+  return pni_passthru_layer.process_output(transport, layer, bytes, available );
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c814d5c3/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index dd1b88b..a763cfb 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -87,9 +87,7 @@ struct pn_ssl_domain_t {
 
 
 struct pn_ssl_t {
-
   pn_transport_t   *transport;
-  pn_io_layer_t    *io_layer;
   pn_ssl_domain_t  *domain;
   const char    *session_id;
   const char *peer_hostname;
@@ -134,19 +132,18 @@ struct pn_ssl_session_t {
 
 /* */
 static int keyfile_pw_cb(char *buf, int size, int rwflag, void *userdata);
-static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *input_data, size_t len);
-static ssize_t process_input_unknown( pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_unknown( pn_io_layer_t *io_layer, char *input_data, size_t len);
-static ssize_t process_input_done(pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_done(pn_io_layer_t *io_layer, char *input_data, size_t len);
+static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
+static ssize_t process_input_unknown( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_unknown( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
+static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
 static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
 static int init_ssl_socket( pn_ssl_t * );
 static void release_ssl_socket( pn_ssl_t * );
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
 static void ssl_session_free( pn_ssl_session_t *);
-static size_t buffered_output( pn_io_layer_t *io_layer );
-static size_t buffered_input( pn_io_layer_t *io_layer );
+static size_t buffered_output( pn_transport_t *transport );
 
 // @todo: used to avoid littering the code with calls to printf...
 static void _log_error(pn_ssl_t *ssl, const char *fmt, ...)
@@ -670,6 +667,40 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
   return 0;
 }
 
+const pn_io_layer_t unknown_layer = {
+    process_input_unknown,
+    process_output_unknown,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t ssl_layer = {
+    process_input_ssl,
+    process_output_ssl,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_input_closed_layer = {
+    process_input_done,
+    process_output_ssl,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_output_closed_layer = {
+    process_input_ssl,
+    process_output_done,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_closed_layer = {
+    process_input_done,
+    process_output_done,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
 
 int pn_ssl_init( pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
 {
@@ -678,13 +709,10 @@ int pn_ssl_init( pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
   ssl->domain = domain;
   domain->ref_count++;
   if (domain->allow_unsecured) {
-    ssl->io_layer->process_input = process_input_unknown;
-    ssl->io_layer->process_output = process_output_unknown;
+    ssl->transport->io_layers[PN_IO_SSL] = &unknown_layer;
   } else {
-    ssl->io_layer->process_input = process_input_ssl;
-    ssl->io_layer->process_output = process_output_ssl;
+    ssl->transport->io_layers[PN_IO_SSL] = &ssl_layer;
   }
-
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
 
@@ -773,13 +801,7 @@ pn_ssl_t *pn_ssl(pn_transport_t *transport)
   ssl->transport = transport;
   transport->ssl = ssl;
 
-  ssl->io_layer = &transport->io_layers[PN_IO_SSL];
-  ssl->io_layer->context = ssl;
-  ssl->io_layer->process_input = pn_io_layer_input_passthru;
-  ssl->io_layer->process_output = pn_io_layer_output_passthru;
-  ssl->io_layer->process_tick = pn_io_layer_tick_passthru;
-  ssl->io_layer->buffered_output = buffered_output;
-  ssl->io_layer->buffered_input = buffered_input;
+  transport->io_layers[PN_IO_SSL] = &pni_passthru_layer;
 
   ssl->trace = (transport->disp) ? transport->disp->trace : PN_TRACE_OFF;
 
@@ -823,11 +845,9 @@ static int start_ssl_shutdown( pn_ssl_t *ssl )
 
 
 
-static int setup_ssl_connection( pn_ssl_t *ssl )
+static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
 {
-  _log( ssl, "SSL connection detected.");
-  ssl->io_layer->process_input = process_input_ssl;
-  ssl->io_layer->process_output = process_output_ssl;
+  transport->io_layers[layer] = &ssl_layer;
   return 0;
 }
 
@@ -836,9 +856,9 @@ static int setup_ssl_connection( pn_ssl_t *ssl )
 
 // take data from the network, and pass it into SSL.  Attempt to read decrypted data from
 // SSL socket and pass it to the application.
-static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_data, size_t available)
+static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_EOS;
 
   _log( ssl, "process_input_ssl( data size=%d )",available );
@@ -910,8 +930,7 @@ static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_dat
 
     if (!ssl->app_input_closed) {
       if (ssl->in_count > 0 || ssl->ssl_closed) {  /* if ssl_closed, send 0 count */
-        pn_io_layer_t *io_next = ssl->io_layer->next;
-        ssize_t consumed = io_next->process_input( io_next, ssl->inbuf, ssl->in_count);
+        ssize_t consumed = transport->io_layers[layer+1]->process_input(transport, layer+1, ssl->inbuf, ssl->in_count);
         if (consumed > 0) {
           ssl->in_count -= consumed;
           if (ssl->in_count)
@@ -973,15 +992,19 @@ static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_dat
   //}
   if (ssl->app_input_closed && (SSL_get_shutdown(ssl->ssl) & SSL_SENT_SHUTDOWN) ) {
     consumed = ssl->app_input_closed;
-    ssl->io_layer->process_input = process_input_done;
+    if (transport->io_layers[layer]==&ssl_output_closed_layer) {
+      transport->io_layers[layer] = &ssl_closed_layer;
+    } else {
+      transport->io_layers[layer] = &ssl_input_closed_layer;
+    }
   }
   _log(ssl, "process_input_ssl() returning %d", (int) consumed);
   return consumed;
 }
 
-static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t max_len)
+static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_len)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   if (!ssl) return PN_EOS;
   if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_EOS;
 
@@ -993,8 +1016,7 @@ static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t
     // first, get any pending application output, if possible
 
     if (!ssl->app_output_closed && ssl->out_count < ssl->out_size) {
-      pn_io_layer_t *io_next = ssl->io_layer->next;
-      ssize_t app_bytes = io_next->process_output( io_next, &ssl->outbuf[ssl->out_count], ssl->out_size - ssl->out_count);
+      ssize_t app_bytes = transport->io_layers[layer+1]->process_output(transport, layer+1, &ssl->outbuf[ssl->out_count], ssl->out_size - ssl->out_count);
       if (app_bytes > 0) {
         ssl->out_count += app_bytes;
         work_pending = true;
@@ -1086,7 +1108,11 @@ static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t
   //}
   if (written == 0 && (SSL_get_shutdown(ssl->ssl) & SSL_SENT_SHUTDOWN) && BIO_pending(ssl->bio_net_io) == 0) {
     written = ssl->app_output_closed ? ssl->app_output_closed : PN_EOS;
-    ssl->io_layer->process_output = process_output_done;
+    if (transport->io_layers[layer]==&ssl_input_closed_layer) {
+      transport->io_layers[layer] = &ssl_closed_layer;
+    } else {
+      transport->io_layers[layer] = &ssl_output_closed_layer;
+    }
   }
   _log(ssl, "process_output_ssl() returning %d", (int) written);
   return written;
@@ -1169,33 +1195,34 @@ static void release_ssl_socket( pn_ssl_t *ssl )
 }
 
 
-static int setup_cleartext_connection( pn_ssl_t *ssl )
+static int setup_cleartext_connection(pn_transport_t *transport, unsigned int layer)
 {
-  _log( ssl, "Cleartext connection detected.");
-  ssl->io_layer->process_input = pn_io_layer_input_passthru;
-  ssl->io_layer->process_output = pn_io_layer_output_passthru;
+  transport->io_layers[layer] = &pni_passthru_layer;
   return 0;
 }
 
 
 // until we determine if the client is using SSL or not:
 
-static ssize_t process_input_unknown(pn_io_layer_t *io_layer, const char *input_data, size_t len)
+static ssize_t process_input_unknown(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   switch (check_for_ssl_connection( input_data, len )) {
   case SSL_CONNECTION:
-    setup_ssl_connection( ssl );
-    return ssl->io_layer->process_input( ssl->io_layer, input_data, len );
+    _log( ssl, "SSL connection detected.\n");
+    setup_ssl_connection(transport, layer);
+    break;
   case CLEAR_CONNECTION:
-    setup_cleartext_connection( ssl );
-    return ssl->io_layer->process_input( ssl->io_layer, input_data, len );
+    _log( ssl, "Cleartext connection detected.\n");
+    setup_cleartext_connection(transport, layer);
+    break;
   default:
     return 0;
   }
+  return transport->io_layers[layer]->process_input(transport, layer, input_data, len );
 }
 
-static ssize_t process_output_unknown(pn_io_layer_t *io_layer, char *input_data, size_t len)
+static ssize_t process_output_unknown(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
 {
   // do not do output until we know if SSL is used or not
   return 0;
@@ -1307,20 +1334,20 @@ int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
   return 0;
 }
 
-static ssize_t process_input_done(pn_io_layer_t *io_layer, const char *input_data, size_t len)
+static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
   return PN_EOS;
 }
-static ssize_t process_output_done(pn_io_layer_t *io_layer, char *input_data, size_t len)
+static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
 {
   return PN_EOS;
 }
 
 // return # output bytes sitting in this layer
-static size_t buffered_output(pn_io_layer_t *io_layer)
+static size_t buffered_output(pn_transport_t *transport)
 {
   size_t count = 0;
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   if (ssl) {
     count += ssl->out_count;
     if (ssl->bio_net_io) { // pick up any bytes waiting for network io
@@ -1329,17 +1356,3 @@ static size_t buffered_output(pn_io_layer_t *io_layer)
   }
   return count;
 }
-
-// return # input bytes sitting in this layer
-static size_t buffered_input( pn_io_layer_t *io_layer )
-{
-  size_t count = 0;
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
-  if (ssl) {
-    count += ssl->in_count;
-    if (ssl->bio_ssl) { // pick up any bytes waiting to be read
-      count += BIO_ctrl_pending(ssl->bio_ssl);
-    }
-  }
-  return count;
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c814d5c3/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index 601d6a2..d93e16f 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -92,17 +92,55 @@ void pn_delivery_map_clear(pn_delivery_map_t *dm)
   dm->next = 0;
 }
 
-static ssize_t pn_input_read_amqp_header(pn_io_layer_t *io_layer, const char *bytes, size_t available);
-static ssize_t pn_input_read_amqp(pn_io_layer_t *io_layer, const char *bytes, size_t available);
-static ssize_t pn_output_write_amqp_header(pn_io_layer_t *io_layer, char *bytes, size_t available);
-static ssize_t pn_output_write_amqp(pn_io_layer_t *io_layer, char *bytes, size_t available);
-static pn_timestamp_t pn_tick_amqp(pn_io_layer_t *io_layer, pn_timestamp_t now);
+static ssize_t pn_io_layer_input_passthru(pn_transport_t *, unsigned int, const char *, size_t );
+static ssize_t pn_io_layer_output_passthru(pn_transport_t *, unsigned int, char *, size_t );
+
+static ssize_t pn_input_read_amqp_header(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
+static ssize_t pn_input_read_amqp(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
+static ssize_t pn_output_write_amqp_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
+static ssize_t pn_output_write_amqp(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
+static pn_timestamp_t pn_tick_amqp(pn_transport_t *transport, unsigned int layer, pn_timestamp_t now);
 
 static void pni_default_tracer(pn_transport_t *transport, const char *message)
 {
   fprintf(stderr, "[%p]:%s\n", (void *) transport, message);
 }
 
+const pn_io_layer_t pni_passthru_layer = {
+    pn_io_layer_input_passthru,
+    pn_io_layer_output_passthru,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t amqp_header_layer = {
+    pn_input_read_amqp_header,
+    pn_output_write_amqp_header,
+    pn_tick_amqp,
+    NULL
+};
+
+const pn_io_layer_t amqp_write_header_layer = {
+    pn_input_read_amqp,
+    pn_output_write_amqp_header,
+    pn_tick_amqp,
+    NULL
+};
+
+const pn_io_layer_t amqp_read_header_layer = {
+    pn_input_read_amqp_header,
+    pn_output_write_amqp,
+    pn_tick_amqp,
+    NULL
+};
+
+const pn_io_layer_t amqp_layer = {
+    pn_input_read_amqp,
+    pn_output_write_amqp,
+    pn_tick_amqp,
+    NULL
+};
+
 static void pn_transport_initialize(void *object)
 {
   pn_transport_t *transport = (pn_transport_t *)object;
@@ -112,33 +150,16 @@ static void pn_transport_initialize(void *object)
   transport->input_buf = NULL;
   transport->input_size =  PN_DEFAULT_MAX_FRAME_SIZE ? PN_DEFAULT_MAX_FRAME_SIZE : 16 * 1024;
   transport->tracer = pni_default_tracer;
-  transport->header_count = 0;
   transport->sasl = NULL;
   transport->ssl = NULL;
   transport->scratch = pn_string(NULL);
   transport->disp = pn_dispatcher(0, transport);
   transport->connection = NULL;
 
-  pn_io_layer_t *io_layer = transport->io_layers;
-  while (io_layer != &transport->io_layers[PN_IO_AMQP]) {
-    io_layer->context = NULL;
-    io_layer->next = io_layer + 1;
-    io_layer->process_input = pn_io_layer_input_passthru;
-    io_layer->process_output = pn_io_layer_output_passthru;
-    io_layer->process_tick = pn_io_layer_tick_passthru;
-    io_layer->buffered_output = NULL;
-    io_layer->buffered_input = NULL;
-    ++io_layer;
-  }
-
-  pn_io_layer_t *amqp = &transport->io_layers[PN_IO_AMQP];
-  amqp->context = transport;
-  amqp->process_input = pn_input_read_amqp_header;
-  amqp->process_output = pn_output_write_amqp_header;
-  amqp->process_tick = pn_io_layer_tick_passthru;
-  amqp->buffered_output = NULL;
-  amqp->buffered_input = NULL;
-  amqp->next = NULL;
+  for (int layer=0; layer<PN_IO_LAYER_CT; ++layer) {
+    transport->io_layers[layer] = &pni_passthru_layer;
+  }
+  transport->io_layers[PN_IO_AMQP] = &amqp_header_layer;
 
   transport->open_sent = false;
   transport->open_rcvd = false;
@@ -550,8 +571,6 @@ int pn_do_open(pn_dispatcher_t *disp)
   } else {
     transport->disp->halt = true;
   }
-  if (transport->remote_idle_timeout)
-    transport->io_layers[PN_IO_AMQP].process_tick = pn_tick_amqp;  // enable timeouts
   transport->open_rcvd = true;
   return 0;
 }
@@ -1072,14 +1091,14 @@ ssize_t pn_transport_input(pn_transport_t *transport, const char *bytes, size_t
 // process pending input until none remaining or EOS
 static ssize_t transport_consume(pn_transport_t *transport)
 {
-  pn_io_layer_t *io_layer = transport->io_layers;
   size_t consumed = 0;
 
   while (transport->input_pending || transport->tail_closed) {
     ssize_t n;
-    n = io_layer->process_input( io_layer,
-                                 transport->input_buf + consumed,
-                                 transport->input_pending );
+    n = transport->io_layers[PN_IO_SSL]->
+      process_input( transport, PN_IO_SSL,
+                     transport->input_buf + consumed,
+                     transport->input_pending );
     if (n > 0) {
       consumed += n;
       transport->input_pending -= n;
@@ -1101,44 +1120,34 @@ static ssize_t transport_consume(pn_transport_t *transport)
   return consumed;
 }
 
-static ssize_t pn_input_read_header(pn_transport_t *transport, const char *bytes, size_t available,
-                                    const char *header, size_t size, const char *protocol,
-                                    ssize_t (*next)(pn_io_layer_t *, const char *, size_t))
+#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
+
+static ssize_t pn_input_read_amqp_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  const char *point = header + transport->header_count;
-  int delta = pn_min(available, size - transport->header_count);
-  if (!available || memcmp(bytes, point, delta)) {
+  unsigned readable = pn_min(8, available);
+  bool eos = pn_transport_capacity(transport)==PN_EOS;
+  if (memcmp(bytes, AMQP_HEADER, readable) || (readable<8 && eos) ) {
     char quoted[1024];
     pn_quote_data(quoted, 1024, bytes, available);
     pn_do_error(transport, "amqp:connection:framing-error",
-                "%s header mismatch: '%s'%s", protocol, quoted,
-                available ? "" : " (connection aborted)");
+                "%s header mismatch: '%s'%s", "AMQP", quoted,
+                !eos ? "" : " (connection aborted)");
     return PN_EOS;
-  } else {
-    transport->header_count += delta;
-    if (transport->header_count == size) {
-      transport->header_count = 0;
-      transport->io_layers[PN_IO_AMQP].process_input = next;
-
-      if (transport->disp->trace & PN_TRACE_FRM)
-        pn_transport_logf(transport, "  <- %s", protocol);
+  } else if (readable==8) {
+    if (transport->io_layers[layer] == &amqp_read_header_layer) {
+      transport->io_layers[layer] = &amqp_layer;
+    } else {
+      transport->io_layers[layer] = &amqp_write_header_layer;
     }
-    return delta;
+    if (transport->disp->trace & PN_TRACE_FRM)
+      pn_transport_logf(transport, "  <- %s", "AMQP");
+    return 8;
   }
+  return 0;
 }
 
-#define AMQP_HEADER ("AMQP\x00\x01\x00\x00")
-
-static ssize_t pn_input_read_amqp_header(pn_io_layer_t *io_layer, const char *bytes, size_t available)
-{
-  pn_transport_t *transport = (pn_transport_t *)io_layer->context;
-  return pn_input_read_header(transport, bytes, available, AMQP_HEADER, 8,
-                              "AMQP", pn_input_read_amqp);
-}
-
-static ssize_t pn_input_read_amqp(pn_io_layer_t *io_layer, const char *bytes, size_t available)
+static ssize_t pn_input_read_amqp(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
 {
-  pn_transport_t *transport = (pn_transport_t *)io_layer->context;
   if (transport->close_rcvd) {
     if (available > 0) {
       pn_do_error(transport, "amqp:connection:framing-error", "data after close");
@@ -1164,10 +1173,9 @@ static ssize_t pn_input_read_amqp(pn_io_layer_t *io_layer, const char *bytes, si
 }
 
 /* process AMQP related timer events */
-static pn_timestamp_t pn_tick_amqp(pn_io_layer_t *io_layer, pn_timestamp_t now)
+static pn_timestamp_t pn_tick_amqp(pn_transport_t* transport, unsigned int layer, pn_timestamp_t now)
 {
   pn_timestamp_t timeout = 0;
-  pn_transport_t *transport = (pn_transport_t *)io_layer->context;
 
   if (transport->local_idle_timeout) {
     if (transport->dead_remote_deadline == 0 ||
@@ -1827,30 +1835,22 @@ int pn_process(pn_transport_t *transport)
   return 0;
 }
 
-static ssize_t pn_output_write_header(pn_transport_t *transport,
-                                      char *bytes, size_t size,
-                                      const char *header, size_t hdrsize,
-                                      const char *protocol,
-                                      ssize_t (*next)(pn_io_layer_t *, char *, size_t))
+static ssize_t pn_output_write_amqp_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
 {
   if (transport->disp->trace & PN_TRACE_FRM)
-    pn_transport_logf(transport, "  -> %s", protocol);
-  assert(size >= hdrsize);
-  memmove(bytes, header, hdrsize);
-  transport->io_layers[PN_IO_AMQP].process_output = next;
-  return hdrsize;
-}
-
-static ssize_t pn_output_write_amqp_header(pn_io_layer_t *io_layer, char *bytes, size_t size)
-{
-  pn_transport_t *transport = (pn_transport_t *)io_layer->context;
-  return pn_output_write_header(transport, bytes, size, AMQP_HEADER, 8, "AMQP",
-                                pn_output_write_amqp);
+    pn_transport_logf(transport, "  -> %s", "AMQP");
+  assert(available >= 8);
+  memmove(bytes, AMQP_HEADER, 8);
+  if (transport->io_layers[layer] == &amqp_write_header_layer) {
+    transport->io_layers[layer] = &amqp_layer;
+  } else {
+    transport->io_layers[layer] = &amqp_read_header_layer;
+  }
+  return 8;
 }
 
-static ssize_t pn_output_write_amqp(pn_io_layer_t *io_layer, char *bytes, size_t size)
+static ssize_t pn_output_write_amqp(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
 {
-  pn_transport_t *transport = (pn_transport_t *)io_layer->context;
   if (transport->connection && !transport->done_processing) {
     int err = pn_process(transport);
     if (err) {
@@ -1866,7 +1866,7 @@ static ssize_t pn_output_write_amqp(pn_io_layer_t *io_layer, char *bytes, size_t
     return PN_EOS;
   }
 
-  return pn_dispatcher_output(transport->disp, bytes, size);
+  return pn_dispatcher_output(transport->disp, bytes, available);
 }
 
 static void pni_close_head(pn_transport_t *transport)
@@ -1884,7 +1884,6 @@ static ssize_t transport_produce(pn_transport_t *transport)
 {
   if (transport->head_closed) return PN_EOS;
 
-  pn_io_layer_t *io_layer = transport->io_layers;
   ssize_t space = transport->output_size - transport->output_pending;
 
   if (space <= 0) {     // can we expand the buffer?
@@ -1905,9 +1904,10 @@ static ssize_t transport_produce(pn_transport_t *transport)
 
   while (space > 0) {
     ssize_t n;
-    n = io_layer->process_output( io_layer,
-                                  &transport->output_buf[transport->output_pending],
-                                  space );
+    n = transport->io_layers[PN_IO_SSL]->
+      process_output( transport, PN_IO_SSL,
+                      &transport->output_buf[transport->output_pending],
+                      space );
     if (n > 0) {
       space -= n;
       transport->output_pending += n;
@@ -2043,7 +2043,6 @@ pn_millis_t pn_transport_get_idle_timeout(pn_transport_t *transport)
 void pn_transport_set_idle_timeout(pn_transport_t *transport, pn_millis_t timeout)
 {
   transport->local_idle_timeout = timeout;
-  transport->io_layers[PN_IO_AMQP].process_tick = pn_tick_amqp;
 }
 
 pn_millis_t pn_transport_get_remote_idle_timeout(pn_transport_t *transport)
@@ -2053,8 +2052,7 @@ pn_millis_t pn_transport_get_remote_idle_timeout(pn_transport_t *transport)
 
 pn_timestamp_t pn_transport_tick(pn_transport_t *transport, pn_timestamp_t now)
 {
-  pn_io_layer_t *io_layer = transport->io_layers;
-  return io_layer->process_tick( io_layer, now );
+  return transport->io_layers[PN_IO_SSL]->process_tick(transport, PN_IO_SSL, now);
 }
 
 uint64_t pn_transport_get_frames_output(const pn_transport_t *transport)
@@ -2072,29 +2070,26 @@ uint64_t pn_transport_get_frames_input(const pn_transport_t *transport)
 }
 
 /** Pass through input handler */
-ssize_t pn_io_layer_input_passthru(pn_io_layer_t *io_layer, const char *data, size_t available)
+ssize_t pn_io_layer_input_passthru(pn_transport_t *transport, unsigned int layer, const char *data, size_t available)
 {
-  pn_io_layer_t *next = io_layer->next;
-  if (next)
-    return next->process_input( next, data, available );
+  if (layer+1<PN_IO_LAYER_CT)
+    return transport->io_layers[layer+1]->process_input(transport, layer+1, data, available);
   return PN_EOS;
 }
 
 /** Pass through output handler */
-ssize_t pn_io_layer_output_passthru(pn_io_layer_t *io_layer, char *bytes, size_t size)
+ssize_t pn_io_layer_output_passthru(pn_transport_t *transport, unsigned int layer, char *data, size_t available)
 {
-  pn_io_layer_t *next = io_layer->next;
-  if (next)
-    return next->process_output( next, bytes, size );
+  if (layer+1<PN_IO_LAYER_CT)
+      return transport->io_layers[layer+1]->process_output(transport, layer+1, data, available);
   return PN_EOS;
 }
 
 /** Pass through tick handler */
-pn_timestamp_t pn_io_layer_tick_passthru(pn_io_layer_t *io_layer, pn_timestamp_t now)
+pn_timestamp_t pn_io_layer_tick_passthru(pn_transport_t *transport, unsigned int layer, pn_timestamp_t now)
 {
-  pn_io_layer_t *next = io_layer->next;
-  if (next)
-    return next->process_tick( next, now );
+  if (layer+1<PN_IO_LAYER_CT)
+      return transport->io_layers[layer+1]->process_tick(transport, layer+1, now);
   return 0;
 }
 
@@ -2253,11 +2248,10 @@ bool pn_transport_quiesced(pn_transport_t *transport)
   if (pending < 0) return true; // output done
   else if (pending > 0) return false;
   // no pending at transport, but check if data is buffered in I/O layers
-  pn_io_layer_t *io_layer = transport->io_layers;
-  while (io_layer != &transport->io_layers[PN_IO_LAYER_CT]) {
-    if (io_layer->buffered_output && io_layer->buffered_output( io_layer ))
+  for (int layer = 0; layer<PN_IO_LAYER_CT; ++layer) {
+    if (transport->io_layers[layer]->buffered_output &&
+        transport->io_layers[layer]->buffered_output( transport ))
       return false;
-    ++io_layer;
   }
   return true;
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c814d5c3/proton-c/src/windows/schannel.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/windows/schannel.c
index de6e117..397fa21 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/windows/schannel.c
@@ -82,7 +82,6 @@ typedef enum { CREATED, CLIENT_HELLO, NEGOTIATING,
 
 struct pn_ssl_t {
   pn_transport_t   *transport;
-  pn_io_layer_t    *io_layer;
   pn_ssl_domain_t  *domain;
   const char    *session_id;
   const char *peer_hostname;
@@ -136,17 +135,16 @@ struct pn_ssl_session_t {
 };
 
 
-static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *input_data, size_t len);
-static ssize_t process_input_unknown( pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_unknown( pn_io_layer_t *io_layer, char *input_data, size_t len);
-static ssize_t process_input_done(pn_io_layer_t *io_layer, const char *input_data, size_t len);
-static ssize_t process_output_done(pn_io_layer_t *io_layer, char *input_data, size_t len);
+static ssize_t process_input_ssl( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
+static ssize_t process_input_unknown( pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_unknown( pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
+static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len);
+static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len);
 static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
 static pn_ssl_session_t *ssn_cache_find( pn_ssl_domain_t *, const char * );
 static void ssl_session_free( pn_ssl_session_t *);
-static size_t buffered_output( pn_io_layer_t *io_layer );
-static size_t buffered_input( pn_io_layer_t *io_layer );
+static size_t buffered_output( pn_transport_t *transport );
 static void start_ssl_shutdown(pn_ssl_t *ssl);
 static void rewind_sc_inbuf(pn_ssl_t *ssl);
 static bool grow_inbuf2(pn_ssl_t *ssl, size_t minimum_size);
@@ -350,6 +348,41 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
   return 0;
 }
 
+const pn_io_layer_t unknown_layer = {
+    process_input_unknown,
+    process_output_unknown,
+    pn_io_layer_tick_passthru,
+    NULL
+};
+
+const pn_io_layer_t ssl_layer = {
+    process_input_ssl,
+    process_output_ssl,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_input_closed_layer = {
+    process_input_done,
+    process_output_ssl,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_output_closed_layer = {
+    process_input_ssl,
+    process_output_done,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
+const pn_io_layer_t ssl_closed_layer = {
+    process_input_done,
+    process_output_done,
+    pn_io_layer_tick_passthru,
+    buffered_output
+};
+
 int pn_ssl_init(pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
 {
   if (!ssl || !domain || ssl->domain) return -1;
@@ -358,13 +391,11 @@ int pn_ssl_init(pn_ssl_t *ssl, pn_ssl_domain_t *domain, const char *session_id)
   ssl->domain = domain;
   domain->ref_count++;
   if (domain->allow_unsecured) {
-    ssl->io_layer->process_input = process_input_unknown;
-    ssl->io_layer->process_output = process_output_unknown;
-  } else {
-    ssl->io_layer->process_input = process_input_ssl;
-    ssl->io_layer->process_output = process_output_ssl;
+    ssl->transport->io_layers[PN_IO_SSL] = &unknown_layer;
+  }
+  else {
+    ssl->transport->io_layers[PN_IO_SSL] = &ssl_layer;
   }
-
   if (session_id && domain->mode == PN_SSL_MODE_CLIENT)
     ssl->session_id = pn_strdup(session_id);
 
@@ -460,13 +491,7 @@ pn_ssl_t *pn_ssl(pn_transport_t *transport)
   ssl->transport = transport;
   transport->ssl = ssl;
 
-  ssl->io_layer = &transport->io_layers[PN_IO_SSL];
-  ssl->io_layer->context = ssl;
-  ssl->io_layer->process_input = pn_io_layer_input_passthru;
-  ssl->io_layer->process_output = pn_io_layer_output_passthru;
-  ssl->io_layer->process_tick = pn_io_layer_tick_passthru;
-  ssl->io_layer->buffered_output = buffered_output;
-  ssl->io_layer->buffered_input = buffered_input;
+  transport->io_layers[PN_IO_SSL] = &pni_passthru_layer;
 
   ssl->trace = (transport->disp) ? transport->disp->trace : PN_TRACE_OFF;
   SecInvalidateHandle(&ssl->cred_handle);
@@ -849,11 +874,9 @@ static void start_ssl_shutdown(pn_ssl_t *ssl)
   ssl_handshake(ssl);
 }
 
-static int setup_ssl_connection(pn_ssl_t *ssl)
+static int setup_ssl_connection(pn_transport_t *transport, unsigned int layer)
 {
-  ssl_log( ssl, "SSL connection detected.\n");
-  ssl->io_layer->process_input = process_input_ssl;
-  ssl->io_layer->process_output = process_output_ssl;
+  transport->io_layers[layer] = &ssl_layer;
   return 0;
 }
 
@@ -976,14 +999,14 @@ static void app_inbytes_advance(pn_ssl_t *ssl, size_t consumed)
     app_inbytes_progress(ssl, 0);
 }
 
-static void read_closed(pn_ssl_t *ssl, ssize_t error)
+static void read_closed(pn_transport_t *transport, unsigned int layer, ssize_t error)
 {
+  pn_ssl_t *ssl = transport->ssl;
   if (ssl->app_input_closed)
     return;
   if (ssl->state == RUNNING && !error) {
-    pn_io_layer_t *io_next = ssl->io_layer->next;
     // Signal end of stream
-    ssl->app_input_closed = io_next->process_input(io_next, ssl->app_inbytes.start, 0);
+    ssl->app_input_closed = transport->io_layers[layer+1]->process_input(transport, layer+1, ssl->app_inbytes.start, 0);
   }
   if (!ssl->app_input_closed)
     ssl->app_input_closed = error ? error : PN_ERR;
@@ -1000,9 +1023,9 @@ static void read_closed(pn_ssl_t *ssl, ssize_t error)
 
 // Read up to "available" bytes from the network, decrypt it and pass plaintext to application.
 
-static ssize_t process_input_ssl(pn_io_layer_t *io_layer, const char *input_data, size_t available)
+static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   ssl_log( ssl, "process_input_ssl( data size=%d )\n",available );
   ssize_t consumed = 0;
   ssize_t forwarded = 0;
@@ -1010,14 +1033,14 @@ static ssize_t process_input_ssl(pn_io_layer_t *io_layer, const char *input_data
 
   if (available == 0) {
     // No more inbound network data
-    read_closed(ssl,0);
+    read_closed(transport, layer, 0);
     return 0;
   }
 
   do {
     if (ssl->sc_input_shutdown) {
       // TLS protocol shutdown detected on input
-      read_closed(ssl,0);
+      read_closed(transport, layer, 0);
       return consumed;
     }
 
@@ -1097,8 +1120,7 @@ static ssize_t process_input_ssl(pn_io_layer_t *io_layer, const char *input_data
       // present app_inbytes to io_next only if it has new content
       while (ssl->app_inbytes.size > 0) {
         if (!ssl->app_input_closed) {
-          pn_io_layer_t *io_next = ssl->io_layer->next;
-          ssize_t count = io_next->process_input(io_next, ssl->app_inbytes.start, ssl->app_inbytes.size);
+          ssize_t count = transport->io_layers[layer+1]->process_input(transport, layer+1, ssl->app_inbytes.start, ssl->app_inbytes.size);
           if (count > 0) {
             forwarded += count;
             // advance() can increase app_inbytes.size if double buffered
@@ -1115,7 +1137,7 @@ static ssize_t process_input_ssl(pn_io_layer_t *io_layer, const char *input_data
             ssl_log(ssl, "Application layer closed its input, error=%d (discarding %d bytes)\n",
                  (int) count, (int)ssl->app_inbytes.size);
             app_inbytes_advance(ssl, ssl->app_inbytes.size);    // discard
-            read_closed(ssl, count);
+            read_closed(transport, layer, count);
           }
         } else {
           ssl_log(ssl, "Input closed discard %d bytes\n",
@@ -1128,15 +1150,19 @@ static ssize_t process_input_ssl(pn_io_layer_t *io_layer, const char *input_data
 
   if (ssl->app_input_closed && ssl->state >= SHUTTING_DOWN) {
     consumed = ssl->app_input_closed;
-    ssl->io_layer->process_input = process_input_done;
+    if (transport->io_layers[layer]==&ssl_output_closed_layer) {
+      transport->io_layers[layer] = &ssl_closed_layer;
+    } else {
+      transport->io_layers[layer] = &ssl_input_closed_layer;
+    }
   }
   ssl_log(ssl, "process_input_ssl() returning %d, forwarded %d\n", (int) consumed, (int) forwarded);
   return consumed;
 }
 
-static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t max_len)
+static ssize_t process_output_ssl( pn_transport_t *transport, unsigned int layer, char *buffer, size_t max_len)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   if (!ssl) return PN_EOS;
   ssl_log( ssl, "process_output_ssl( max_len=%d )\n",max_len );
 
@@ -1173,8 +1199,7 @@ static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t
       size_t remaining = ssl->max_data_size;
       ssize_t app_bytes;
       do {
-        pn_io_layer_t *io_next = ssl->io_layer->next;
-        app_bytes = io_next->process_output(io_next, app_outp, remaining);
+        app_bytes = transport->io_layers[layer+1]->process_output(transport, layer+1, app_outp, remaining);
         if (app_bytes > 0) {
           app_outp += app_bytes;
           remaining -= app_bytes;
@@ -1212,40 +1237,45 @@ static ssize_t process_output_ssl( pn_io_layer_t *io_layer, char *buffer, size_t
 
   if (written == 0 && ssl->state == SSL_CLOSED) {
     written = ssl->app_output_closed ? ssl->app_output_closed : PN_EOS;
-    ssl->io_layer->process_output = process_output_done;
+    if (transport->io_layers[layer]==&ssl_input_closed_layer) {
+      transport->io_layers[layer] = &ssl_closed_layer;
+    } else {
+      transport->io_layers[layer] = &ssl_output_closed_layer;
+    }
   }
   ssl_log(ssl, "process_output_ssl() returning %d\n", (int) written);
   return written;
 }
 
 
-static int setup_cleartext_connection( pn_ssl_t *ssl )
+static int setup_cleartext_connection(pn_transport_t *transport, unsigned int layer)
 {
-  ssl_log( ssl, "Cleartext connection detected.\n");
-  ssl->io_layer->process_input = pn_io_layer_input_passthru;
-  ssl->io_layer->process_output = pn_io_layer_output_passthru;
+  transport->io_layers[layer] = &pni_passthru_layer;
   return 0;
 }
 
 
 // until we determine if the client is using SSL or not:
 
-static ssize_t process_input_unknown(pn_io_layer_t *io_layer, const char *input_data, size_t len)
+static ssize_t process_input_unknown(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   switch (check_for_ssl_connection( input_data, len )) {
   case SSL_CONNECTION:
-    setup_ssl_connection( ssl );
-    return ssl->io_layer->process_input( ssl->io_layer, input_data, len );
+	ssl_log(ssl, "SSL connection detected.\n");
+    setup_ssl_connection(transport, layer);
+	break;
   case CLEAR_CONNECTION:
-    setup_cleartext_connection( ssl );
-    return ssl->io_layer->process_input( ssl->io_layer, input_data, len );
+	ssl_log(ssl, "Cleartext connection detected.\n");
+    setup_cleartext_connection(transport, layer);
+	break;
   default:
     return 0;
   }
+  return transport->io_layers[layer]->process_input(transport, layer, input_data, len);
 }
 
-static ssize_t process_output_unknown(pn_io_layer_t *io_layer, char *input_data, size_t len)
+static ssize_t process_output_unknown(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
 {
   // do not do output until we know if SSL is used or not
   return 0;
@@ -1304,21 +1334,21 @@ static connection_mode_t check_for_ssl_connection( const char *data, size_t len
   return UNKNOWN_CONNECTION;
 }
 
-static ssize_t process_input_done(pn_io_layer_t *io_layer, const char *input_data, size_t len)
+static ssize_t process_input_done(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t len)
 {
   return PN_EOS;
 }
 
-static ssize_t process_output_done(pn_io_layer_t *io_layer, char *input_data, size_t len)
+static ssize_t process_output_done(pn_transport_t *transport, unsigned int layer, char *input_data, size_t len)
 {
   return PN_EOS;
 }
 
 // return # output bytes sitting in this layer
-static size_t buffered_output(pn_io_layer_t *io_layer)
+static size_t buffered_output(pn_transport_t *transport)
 {
   size_t count = 0;
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
+  pn_ssl_t *ssl = transport->ssl;
   if (ssl) {
     count += ssl->network_out_pending;
     if (count == 0 && ssl->state == SHUTTING_DOWN && ssl->queued_shutdown)
@@ -1326,14 +1356,3 @@ static size_t buffered_output(pn_io_layer_t *io_layer)
   }
   return count;
 }
-
-// return # input bytes sitting in this layer
-static size_t buffered_input( pn_io_layer_t *io_layer )
-{
-  size_t count = 0;
-  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
-  if (ssl) {
-    count += ssl->in_data_count;
-  }
-  return count;
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[12/35] qpid-proton git commit: PROTON-753: add constants for the delivery outcome symbol descriptors, for use in setting the supported outcomes on a Source

Posted by gs...@apache.org.
PROTON-753: add constants for the delivery outcome symbol descriptors, for use in setting the supported outcomes on a Source


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/7b91e1ff
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/7b91e1ff
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/7b91e1ff

Branch: refs/heads/examples
Commit: 7b91e1ffe986c8b3f4ee9f4b6c3fe24cafedbe05
Parents: 02f1c57
Author: Robert Gemmell <ro...@apache.org>
Authored: Wed Nov 19 12:53:41 2014 +0000
Committer: Robert Gemmell <ro...@apache.org>
Committed: Wed Nov 19 16:31:43 2014 +0000

----------------------------------------------------------------------
 .../main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java | 3 +++
 .../main/java/org/apache/qpid/proton/amqp/messaging/Modified.java | 3 +++
 .../main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java | 2 ++
 .../main/java/org/apache/qpid/proton/amqp/messaging/Released.java | 3 +++
 .../java/org/apache/qpid/proton/amqp/transaction/Declared.java    | 3 +++
 5 files changed, 14 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b91e1ff/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java
index a2bac32..d21caaa 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Accepted.java
@@ -23,12 +23,15 @@
 
 package org.apache.qpid.proton.amqp.messaging;
 
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.transport.DeliveryState;
 
 
 public final class Accepted
       implements DeliveryState, Outcome
 {
+    public static final Symbol DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:accepted:list");
+
     private static final Accepted INSTANCE = new Accepted();
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b91e1ff/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Modified.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Modified.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Modified.java
index d727e25..9b9a3a3 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Modified.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Modified.java
@@ -22,11 +22,14 @@
 package org.apache.qpid.proton.amqp.messaging;
 
 import java.util.Map;
+
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.transport.DeliveryState;
 
 public final class Modified
       implements DeliveryState, Outcome
 {
+    public static final Symbol DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:modified:list");
 
     private Boolean _deliveryFailed;
     private Boolean _undeliverableHere;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b91e1ff/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java
index 022c277..3ea3a5b 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Rejected.java
@@ -23,6 +23,7 @@
 
 package org.apache.qpid.proton.amqp.messaging;
 
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.transport.DeliveryState;
 import org.apache.qpid.proton.amqp.transport.ErrorCondition;
 
@@ -30,6 +31,7 @@ import org.apache.qpid.proton.amqp.transport.ErrorCondition;
 public final class Rejected
       implements DeliveryState, Outcome
 {
+    public static final Symbol DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:rejected:list");
 
     private ErrorCondition _error;
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b91e1ff/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Released.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Released.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Released.java
index a9878c1..c67917f 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Released.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/messaging/Released.java
@@ -23,12 +23,15 @@
 
 package org.apache.qpid.proton.amqp.messaging;
 
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.transport.DeliveryState;
 
 
 public final class Released
       implements DeliveryState, Outcome
 {
+    public static final Symbol DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:released:list");
+
     private static final Released INSTANCE = new Released();
 
     @Override

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b91e1ff/proton-j/src/main/java/org/apache/qpid/proton/amqp/transaction/Declared.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/transaction/Declared.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/transaction/Declared.java
index 18b508c..e049cd5 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/transaction/Declared.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/transaction/Declared.java
@@ -24,6 +24,7 @@
 package org.apache.qpid.proton.amqp.transaction;
 
 import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.messaging.Outcome;
 import org.apache.qpid.proton.amqp.transport.DeliveryState;
 
@@ -31,6 +32,8 @@ import org.apache.qpid.proton.amqp.transport.DeliveryState;
 public final class Declared
       implements DeliveryState, Outcome
 {
+    public static final Symbol DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:declared:list");
+
     private Binary _txnId;
 
     public Binary getTxnId()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[02/35] qpid-proton git commit: PROTON-746: Fix encoding a Ruby symbol into a message body.

Posted by gs...@apache.org.
PROTON-746: Fix encoding a Ruby symbol into a message body.

The symbol needs to be converted to a string before being encoded.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/b57f45d3
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/b57f45d3
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/b57f45d3

Branch: refs/heads/examples
Commit: b57f45d30b2643e2275219c286eab79b5efa76a2
Parents: a04193d
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Fri Nov 14 16:09:52 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Fri Nov 14 17:29:11 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/lib/qpid_proton/mapping.rb | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b57f45d3/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb b/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
index 778f936..836bcd9 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
@@ -112,6 +112,9 @@ module Qpid # :nodoc:
 
     class << STRING
       def put(data, value)
+        # if we have a symbol then convert it to a string
+        value = value.to_s if value.is_a?(Symbol)
+
         isutf = false
 
         if value.is_a?(Qpid::Proton::UTFString)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[28/35] qpid-proton git commit: Revert "PROTON-752: Provide a non-blocking means to receive messages in Ruby."

Posted by gs...@apache.org.
Revert "PROTON-752: Provide a non-blocking means to receive messages in Ruby."

This reverts commit 0820a3722b6ab5c2a5a4dbfac3428de7d22c1c6e.

Reverting this change so we can have a review first.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/3ac2e3bd
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/3ac2e3bd
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/3ac2e3bd

Branch: refs/heads/examples
Commit: 3ac2e3bd34b90a7026103af47b1cb8fd2f7d5271
Parents: 0820a37
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Mon Nov 24 14:25:26 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Mon Nov 24 14:25:26 2014 -0500

----------------------------------------------------------------------
 examples/messenger/ruby/passive_recv.rb         | 122 +++++++++++++++---
 .../bindings/ruby/lib/qpid_proton/messenger.rb  | 128 -------------------
 .../bindings/ruby/lib/qpid_proton/selectable.rb |  21 +--
 3 files changed, 108 insertions(+), 163 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3ac2e3bd/examples/messenger/ruby/passive_recv.rb
----------------------------------------------------------------------
diff --git a/examples/messenger/ruby/passive_recv.rb b/examples/messenger/ruby/passive_recv.rb
index 878c801..a3625ac 100644
--- a/examples/messenger/ruby/passive_recv.rb
+++ b/examples/messenger/ruby/passive_recv.rb
@@ -31,26 +31,110 @@ end
 
 addresses = ["~0.0.0.0"] if addresses.empty?
 
-msgr = Qpid::Proton::Messenger.receive_and_call(nil, :addresses => addresses) do |message|
-  puts "Address: #{message.address}"
-  subject = message.subject || "(no subject)"
-  puts "Subject: #{subject}"
-  puts "Body: #{message.body}"
-  puts "Properties: #{message.properties}"
-  puts "Instructions: #{message.instructions}"
-  puts "Annotations: #{message.annotations}"
-
-  if message.reply_to
-    puts "=== Sending a reply to #{message.reply_to}"
-    reply = Qpid::Proton::Message.new
-    reply.address = message.reply_to
-    reply.subject = "RE: #{message.subject}"
-    reply.content = "Thanks for the message!"
-
-    messenger.put(reply)
-    messenger.send
+messenger = Qpid::Proton::Messenger.new
+messenger.passive = true
+
+begin
+  messenger.start
+rescue ProtonError => error
+  puts "ERROR: #{error.message}"
+  puts error.backtrace.join("\n")
+  exit
+end
+
+addresses.each do |address|
+  begin
+    messenger.subscribe(address)
+  rescue Qpid::Proton::ProtonError => error
+    puts "ERROR: #{error.message}"
+    exit
+  end
+end
+
+msg = Qpid::Proton::Message.new
+
+read_array = []
+write_array = []
+selectables = {}
+
+loop do
+
+  # wait for incoming messages
+  sel = messenger.selectable
+  while !sel.nil?
+    if sel.terminal?
+      selectables.delete(sel.fileno)
+      read_array.delete(sel)
+      write_array.delete(sel)
+      sel.free
+    else
+      sel.capacity
+      sel.pending
+      if !sel.registered?
+        read_array << sel
+        write_array << sel
+        selectables[sel.fileno] = sel
+        sel.registered = true
+      end
+    end
+    sel = messenger.selectable
   end
 
+  unless selectables.empty?
+    rarray = []; read_array.each {|fd| rarray << fd.to_io }
+    warray = []; write_array.each {|fd| warray << fd.to_io }
+
+    if messenger.deadline > 0.0
+      result = IO.select(rarray, warray, nil, messenger.deadline)
+    else
+      result = IO.select(rarray, warray)
+    end
+
+    unless result.nil? && result.empty?
+      result.flatten.each do |io|
+        sel = selectables[io.fileno]
+
+        sel.writable if sel.pending > 0
+        sel.readable if sel.capacity > 0
+      end
+    end
+
+    begin
+      messenger.receive(10)
+    rescue Qpid::Proton::ProtonError => error
+      puts "ERROR: #{error.message}"
+      exit
+    end
+
+    while messenger.incoming.nonzero?
+      begin
+        messenger.get(msg)
+      rescue Qpid::Proton::Error => error
+        puts "ERROR: #{error.message}"
+        exit
+      end
+
+      puts "Address: #{msg.address}"
+      subject = msg.subject || "(no subject)"
+      puts "Subject: #{subject}"
+      puts "Body: #{msg.body}"
+      puts "Properties: #{msg.properties}"
+      puts "Instructions: #{msg.instructions}"
+      puts "Annotations: #{msg.annotations}"
+
+      if msg.reply_to
+        puts "=== Sending a reply to #{msg.reply_to}"
+        reply = Qpid::Proton::Message.new
+        reply.address = msg.reply_to
+        reply.subject = "RE: #{msg.subject}"
+        reply.content = "Thanks for the message!"
+
+        messenger.put(reply)
+        messenger.send
+      end
+    end
+  end
 end
 
-Thread.list[1].join
+messenger.stop
+

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3ac2e3bd/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index a8f7330..5a16c50 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -75,7 +75,6 @@ module Qpid # :nodoc:
       #
       def initialize(name = nil)
         @impl = Cproton.pn_messenger(name)
-        @interrupted = false
         @selectables = {}
         ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
       end
@@ -408,7 +407,6 @@ module Qpid # :nodoc:
       # originated the interrupt.
       #
       def interrupt
-        @interrupted = true
         Cproton.pn_messenger_interrupt(@impl)
       end
 
@@ -697,132 +695,6 @@ module Qpid # :nodoc:
         !window.nil? && [Float, Fixnum].include?(window.class)
       end
 
-      public
-
-
-      #--
-      # The following are class methods.
-      #++
-
-      # Receives messages from the provided instance of Messenger, and then
-      # calls the supplied block for each Message received. If no instance
-      # is provided then one is created using the provided list of options.
-      #
-      # This starts a new thread which will loop, waiting for and processing
-      # incoming messages.
-      #
-      # ==== Arguments
-      #
-      # * messenger - The instance of Messenger.
-      #
-      # ==== Options
-      #
-      # * :addresses - An array of addresses to which to subscribe. Addresses
-      #   are required if no Messenger was supplied.
-      #
-      # ==== Examples
-      #
-      #   # create a Messenger
-      #   messenger = Qpid::Proton::Messenger.new
-      #   # begin receiving messages
-      #   Qpid::Proton::Messenger.receive_and_call(messenger) do |message|
-      #      puts "Received: #{message.body}"
-      #   end
-      #
-      def self.receive_and_call(messenger, options = {}, &block)
-        # if the messenger wasn't created then create one
-        if messenger.nil?
-          # if no addresses were supplied then raise an exception
-          raise ArgumentError.new("no addresses") if options[:addresses].nil?
-          # if no block was supplied then raise an exception
-          raise ArgumentError.new("missing block") if block.nil?
-
-          messenger = Qpid::Proton::Messenger.new
-          Array(options[:addresses]).each do |address|
-            messenger.subscribe address
-          end
-        end
-
-        # set the messenger to passive mode
-        messenger.passive = true
-        messenger.start
-
-        Thread.new(messenger, block) do |messenger, &block|
-          read_array = []
-          write_array = []
-          selectables = {}
-
-          aborted = false
-
-          while !aborted do
-            # refresh the list of fds to be processed
-            sel = messenger.selectable
-            while !sel.nil?
-              if sel.terminal?
-                selectables.delete(sel.fileno)
-                read_array.delete(sel)
-                write_array.delete(sel)
-                sel.free
-              else
-                sel.capacity
-                sel.pending
-                if !sel.registered?
-                  read_array << sel
-                  write_array << sel
-                  selectables[sel.fileno] = sel
-                  sel.registered = true
-                end
-              end
-              sel = messenger.selectable
-            end
-
-            unless selectables.empty?
-              rarray = []; read_array.each {|fd| rarray << fd.to_io}
-              warray = []; write_array.each {|fd| warray << fd.to_io}
-
-              if messenger.deadline > 0.0
-                result = IO.select(rarray, warray, nil, messenger.deadline)
-              else
-                result = IO.select(rarray, warray)
-              end
-
-              unless result.nil? && result.empty?
-                result.flatten.each do |io|
-                  sel = selectables[io.fileno]
-
-                  sel.writable if sel.pending > 0
-                  sel.readable if sel.capacity > 0
-                end
-              end
-
-              messenger.receive(10)
-
-              # if this was interrupted then exit
-              messenger.instance_eval do
-                aborted = @interrupted
-                @interrupted = false
-              end
-
-              if !aborted
-                # process each message received
-                while messenger.incoming.nonzero?
-                  message = Qpid::Proton::Message.new
-                  messenger.get(message)
-                  yield message
-                end
-              end
-
-            end
-
-          end
-
-        end
-
-        # return the messenger
-        messenger
-
-      end
-
     end
 
   end

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3ac2e3bd/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
index 8b1214a..33554cd 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
@@ -37,14 +37,6 @@ module Qpid # :nodoc:
         @impl = impl
         @io = nil
         @freed = false
-
-        ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
-      end
-
-      def self.finalize!(impl) # :nodoc:
-        proc {
-          impl.free
-        }
       end
 
       # Returns the underlying file descriptor.
@@ -56,11 +48,7 @@ module Qpid # :nodoc:
       end
 
       def to_io
-        if @io.nil?
-          fileno = self.fileno
-          @io = IO.new(fileno)
-        end
-        @io
+        @io ||= IO.new(fileno)
       end
 
       # The number of bytes the selectable is capable of consuming.
@@ -109,14 +97,15 @@ module Qpid # :nodoc:
       end
 
       def to_s
-        return super if @freed
-        "#{super} fileno=#{self.fileno} registered=#{self.registered?} terminal=#{self.terminal?}"
+        "fileno=#{self.fileno} registered=#{self.registered?} terminal=#{self.terminal?}"
       end
 
       def free
+        return if @freed
         @freed = true
         @messenger.unregister_selectable(fileno)
-        @messenger = nil
+        @io.close unless @io.nil?
+        Cproton.pn_selectable_free(@impl)
         @impl = nil
       end
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[05/35] qpid-proton git commit: PROTON-749: Change tick layer callbacks so that they're not chained just called in sequence

Posted by gs...@apache.org.
PROTON-749: Change tick layer callbacks so that they're not chained just called in sequence


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/120639bf
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/120639bf
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/120639bf

Branch: refs/heads/examples
Commit: 120639bf6ebed39fa52c4743baf92a90df87d497
Parents: c814d5c
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Aug 15 17:58:37 2014 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Mon Nov 17 14:55:18 2014 -0500

----------------------------------------------------------------------
 proton-c/src/engine/engine-internal.h |  2 --
 proton-c/src/sasl/sasl.c              |  8 ++++----
 proton-c/src/ssl/openssl.c            | 10 +++++-----
 proton-c/src/transport/transport.c    | 26 +++++++++++---------------
 proton-c/src/windows/schannel.c       | 10 +++++-----
 5 files changed, 25 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/120639bf/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index 86f5161..40a839b 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -300,8 +300,6 @@ void pn_link_dump(pn_link_t *link);
 void pn_dump(pn_connection_t *conn);
 void pn_transport_sasl_init(pn_transport_t *transport);
 
-pn_timestamp_t pn_io_layer_tick_passthru(pn_transport_t *, unsigned int, pn_timestamp_t);
-
 void pn_condition_init(pn_condition_t *condition);
 void pn_condition_tini(pn_condition_t *condition);
 void pn_modified(pn_connection_t *connection, pn_endpoint_t *endpoint, bool emit);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/120639bf/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 97bead4..5034eb7 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -61,28 +61,28 @@ static ssize_t pn_output_write_sasl(pn_transport_t *transport, unsigned int laye
 const pn_io_layer_t sasl_headers_layer = {
     pn_input_read_sasl_header,
     pn_output_write_sasl_header,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
 const pn_io_layer_t sasl_write_header_layer = {
     pn_input_read_sasl,
     pn_output_write_sasl_header,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
 const pn_io_layer_t sasl_read_header_layer = {
     pn_input_read_sasl_header,
     pn_output_write_sasl,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
 const pn_io_layer_t sasl_layer = {
     pn_input_read_sasl,
     pn_output_write_sasl,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/120639bf/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index a763cfb..7202f7a 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -670,35 +670,35 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
 const pn_io_layer_t unknown_layer = {
     process_input_unknown,
     process_output_unknown,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
 const pn_io_layer_t ssl_layer = {
     process_input_ssl,
     process_output_ssl,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_input_closed_layer = {
     process_input_done,
     process_output_ssl,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_output_closed_layer = {
     process_input_ssl,
     process_output_done,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_closed_layer = {
     process_input_done,
     process_output_done,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/120639bf/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index d93e16f..2c086db 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -109,7 +109,7 @@ static void pni_default_tracer(pn_transport_t *transport, const char *message)
 const pn_io_layer_t pni_passthru_layer = {
     pn_io_layer_input_passthru,
     pn_io_layer_output_passthru,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
@@ -1095,8 +1095,8 @@ static ssize_t transport_consume(pn_transport_t *transport)
 
   while (transport->input_pending || transport->tail_closed) {
     ssize_t n;
-    n = transport->io_layers[PN_IO_SSL]->
-      process_input( transport, PN_IO_SSL,
+    n = transport->io_layers[0]->
+      process_input( transport, 0,
                      transport->input_buf + consumed,
                      transport->input_pending );
     if (n > 0) {
@@ -1904,8 +1904,8 @@ static ssize_t transport_produce(pn_transport_t *transport)
 
   while (space > 0) {
     ssize_t n;
-    n = transport->io_layers[PN_IO_SSL]->
-      process_output( transport, PN_IO_SSL,
+    n = transport->io_layers[0]->
+      process_output( transport, 0,
                       &transport->output_buf[transport->output_pending],
                       space );
     if (n > 0) {
@@ -2052,7 +2052,12 @@ pn_millis_t pn_transport_get_remote_idle_timeout(pn_transport_t *transport)
 
 pn_timestamp_t pn_transport_tick(pn_transport_t *transport, pn_timestamp_t now)
 {
-  return transport->io_layers[PN_IO_SSL]->process_tick(transport, PN_IO_SSL, now);
+  pn_timestamp_t r = 0;
+  for (int i = 0; i<PN_IO_LAYER_CT; ++i) {
+    if (transport->io_layers[i]->process_tick)
+      r = pn_timestamp_min(r, transport->io_layers[i]->process_tick(transport, i, now));
+  }
+  return r;
 }
 
 uint64_t pn_transport_get_frames_output(const pn_transport_t *transport)
@@ -2085,15 +2090,6 @@ ssize_t pn_io_layer_output_passthru(pn_transport_t *transport, unsigned int laye
   return PN_EOS;
 }
 
-/** Pass through tick handler */
-pn_timestamp_t pn_io_layer_tick_passthru(pn_transport_t *transport, unsigned int layer, pn_timestamp_t now)
-{
-  if (layer+1<PN_IO_LAYER_CT)
-      return transport->io_layers[layer+1]->process_tick(transport, layer+1, now);
-  return 0;
-}
-
-
 ///
 
 // input

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/120639bf/proton-c/src/windows/schannel.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/schannel.c b/proton-c/src/windows/schannel.c
index 397fa21..7f47745 100644
--- a/proton-c/src/windows/schannel.c
+++ b/proton-c/src/windows/schannel.c
@@ -351,35 +351,35 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
 const pn_io_layer_t unknown_layer = {
     process_input_unknown,
     process_output_unknown,
-    pn_io_layer_tick_passthru,
+    NULL,
     NULL
 };
 
 const pn_io_layer_t ssl_layer = {
     process_input_ssl,
     process_output_ssl,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_input_closed_layer = {
     process_input_done,
     process_output_ssl,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_output_closed_layer = {
     process_input_ssl,
     process_output_done,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 
 const pn_io_layer_t ssl_closed_layer = {
     process_input_done,
     process_output_done,
-    pn_io_layer_tick_passthru,
+    NULL,
     buffered_output
 };
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[21/35] qpid-proton git commit: changed proton.py from a module into a package

Posted by gs...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6a78d2f7/proton-c/bindings/python/proton.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/proton.py b/proton-c/bindings/python/proton.py
deleted file mode 100644
index fce3255..0000000
--- a/proton-c/bindings/python/proton.py
+++ /dev/null
@@ -1,3891 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-"""
-The proton module defines a suite of APIs that implement the AMQP 1.0
-protocol.
-
-The proton APIs consist of the following classes:
-
- - L{Messenger} -- A messaging endpoint.
- - L{Message}   -- A class for creating and/or accessing AMQP message content.
- - L{Data}      -- A class for creating and/or accessing arbitrary AMQP encoded
-                  data.
-
-"""
-
-from cproton import *
-
-import weakref, re, socket
-try:
-  import uuid
-except ImportError:
-  """
-  No 'native' UUID support.  Provide a very basic UUID type that is a compatible subset of the uuid type provided by more modern python releases.
-  """
-  import struct
-  class uuid:
-    class UUID:
-      def __init__(self, hex=None, bytes=None):
-        if [hex, bytes].count(None) != 1:
-          raise TypeError("need one of hex or bytes")
-        if bytes is not None:
-          self.bytes = bytes
-        elif hex is not None:
-          fields=hex.split("-")
-          fields[4:5] = [fields[4][:4], fields[4][4:]]
-          self.bytes = struct.pack("!LHHHHL", *[int(x,16) for x in fields])
-
-      def __cmp__(self, other):
-        if isinstance(other, uuid.UUID):
-          return cmp(self.bytes, other.bytes)
-        else:
-          return -1
-
-      def __str__(self):
-        return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
-
-      def __repr__(self):
-        return "UUID(%r)" % str(self)
-
-      def __hash__(self):
-        return self.bytes.__hash__()
-
-  import os, random, socket, time
-  rand = random.Random()
-  rand.seed((os.getpid(), time.time(), socket.gethostname()))
-  def random_uuid():
-    bytes = [rand.randint(0, 255) for i in xrange(16)]
-
-    # From RFC4122, the version bits are set to 0100
-    bytes[7] &= 0x0F
-    bytes[7] |= 0x40
-
-    # From RFC4122, the top two bits of byte 8 get set to 01
-    bytes[8] &= 0x3F
-    bytes[8] |= 0x80
-    return "".join(map(chr, bytes))
-
-  def uuid4():
-    return uuid.UUID(bytes=random_uuid())
-
-try:
-  bytes()
-except NameError:
-  bytes = str
-
-VERSION_MAJOR = PN_VERSION_MAJOR
-VERSION_MINOR = PN_VERSION_MINOR
-API_LANGUAGE = "C"
-IMPLEMENTATION_LANGUAGE = "C"
-
-class Constant(object):
-
-  def __init__(self, name):
-    self.name = name
-
-  def __repr__(self):
-    return self.name
-
-class ProtonException(Exception):
-  """
-  The root of the proton exception hierarchy. All proton exception
-  classes derive from this exception.
-  """
-  pass
-
-class Timeout(ProtonException):
-  """
-  A timeout exception indicates that a blocking operation has timed
-  out.
-  """
-  pass
-
-class Interrupt(ProtonException):
-  """
-  An interrupt exception indicaes that a blocking operation was interrupted.
-  """
-  pass
-
-class MessengerException(ProtonException):
-  """
-  The root of the messenger exception hierarchy. All exceptions
-  generated by the messenger class derive from this exception.
-  """
-  pass
-
-class MessageException(ProtonException):
-  """
-  The MessageException class is the root of the message exception
-  hierarhcy. All exceptions generated by the Message class derive from
-  this exception.
-  """
-  pass
-
-EXCEPTIONS = {
-  PN_TIMEOUT: Timeout,
-  PN_INTR: Interrupt
-  }
-
-PENDING = Constant("PENDING")
-ACCEPTED = Constant("ACCEPTED")
-REJECTED = Constant("REJECTED")
-RELEASED = Constant("RELEASED")
-ABORTED = Constant("ABORTED")
-SETTLED = Constant("SETTLED")
-
-STATUSES = {
-  PN_STATUS_ABORTED: ABORTED,
-  PN_STATUS_ACCEPTED: ACCEPTED,
-  PN_STATUS_REJECTED: REJECTED,
-  PN_STATUS_RELEASED: RELEASED,
-  PN_STATUS_PENDING: PENDING,
-  PN_STATUS_SETTLED: SETTLED,
-  PN_STATUS_UNKNOWN: None
-  }
-
-AUTOMATIC = Constant("AUTOMATIC")
-MANUAL = Constant("MANUAL")
-
-class Messenger(object):
-  """
-  The L{Messenger} class defines a high level interface for sending
-  and receiving L{Messages<Message>}. Every L{Messenger} contains a
-  single logical queue of incoming messages and a single logical queue
-  of outgoing messages. These messages in these queues may be destined
-  for, or originate from, a variety of addresses.
-
-  The messenger interface is single-threaded.  All methods
-  except one (L{interrupt}) are intended to be used from within
-  the messenger thread.
-
-
-  Address Syntax
-  ==============
-
-  An address has the following form::
-
-    [ amqp[s]:// ] [user[:password]@] domain [/[name]]
-
-  Where domain can be one of::
-
-    host | host:port | ip | ip:port | name
-
-  The following are valid examples of addresses:
-
-   - example.org
-   - example.org:1234
-   - amqp://example.org
-   - amqps://example.org
-   - example.org/incoming
-   - amqps://example.org/outgoing
-   - amqps://fred:trustno1@example.org
-   - 127.0.0.1:1234
-   - amqps://127.0.0.1:1234
-
-  Sending & Receiving Messages
-  ============================
-
-  The L{Messenger} class works in conjuction with the L{Message} class. The
-  L{Message} class is a mutable holder of message content.
-
-  The L{put} method copies its L{Message} to the outgoing queue, and may
-  send queued messages if it can do so without blocking.  The L{send}
-  method blocks until it has sent the requested number of messages,
-  or until a timeout interrupts the attempt.
-
-
-    >>> message = Message()
-    >>> for i in range(3):
-    ...   message.address = "amqp://host/queue"
-    ...   message.subject = "Hello World %i" % i
-    ...   messenger.put(message)
-    >>> messenger.send()
-
-  Similarly, the L{recv} method receives messages into the incoming
-  queue, and may block as it attempts to receive the requested number
-  of messages,  or until timeout is reached. It may receive fewer
-  than the requested number.  The L{get} method pops the
-  eldest L{Message} off the incoming queue and copies it into the L{Message}
-  object that you supply.  It will not block.
-
-
-    >>> message = Message()
-    >>> messenger.recv(10):
-    >>> while messenger.incoming > 0:
-    ...   messenger.get(message)
-    ...   print message.subject
-    Hello World 0
-    Hello World 1
-    Hello World 2
-
-  The blocking flag allows you to turn off blocking behavior entirely,
-  in which case L{send} and L{recv} will do whatever they can without
-  blocking, and then return.  You can then look at the number
-  of incoming and outgoing messages to see how much outstanding work
-  still remains.
-  """
-
-  def __init__(self, name=None):
-    """
-    Construct a new L{Messenger} with the given name. The name has
-    global scope. If a NULL name is supplied, a UUID based name will
-    be chosen.
-
-    @type name: string
-    @param name: the name of the messenger or None
-
-    """
-    self._mng = pn_messenger(name)
-    self._selectables = {}
-
-  def __del__(self):
-    """
-    Destroy the L{Messenger}.  This will close all connections that
-    are managed by the L{Messenger}.  Call the L{stop} method before
-    destroying the L{Messenger}.
-    """
-    if hasattr(self, "_mng"):
-      pn_messenger_free(self._mng)
-      del self._mng
-
-  def _check(self, err):
-    if err < 0:
-      if (err == PN_INPROGRESS):
-        return
-      exc = EXCEPTIONS.get(err, MessengerException)
-      raise exc("[%s]: %s" % (err, pn_error_text(pn_messenger_error(self._mng))))
-    else:
-      return err
-
-  @property
-  def name(self):
-    """
-    The name of the L{Messenger}.
-    """
-    return pn_messenger_name(self._mng)
-
-  def _get_certificate(self):
-    return pn_messenger_get_certificate(self._mng)
-
-  def _set_certificate(self, value):
-    self._check(pn_messenger_set_certificate(self._mng, value))
-
-  certificate = property(_get_certificate, _set_certificate,
-                         doc="""
-Path to a certificate file for the L{Messenger}. This certificate is
-used when the L{Messenger} accepts or establishes SSL/TLS connections.
-This property must be specified for the L{Messenger} to accept
-incoming SSL/TLS connections and to establish client authenticated
-outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS
-connections do not require this property.
-""")
-
-  def _get_private_key(self):
-    return pn_messenger_get_private_key(self._mng)
-
-  def _set_private_key(self, value):
-    self._check(pn_messenger_set_private_key(self._mng, value))
-
-  private_key = property(_get_private_key, _set_private_key,
-                         doc="""
-Path to a private key file for the L{Messenger's<Messenger>}
-certificate. This property must be specified for the L{Messenger} to
-accept incoming SSL/TLS connections and to establish client
-authenticated outgoing SSL/TLS connection. Non client authenticated
-SSL/TLS connections do not require this property.
-""")
-
-  def _get_password(self):
-    return pn_messenger_get_password(self._mng)
-
-  def _set_password(self, value):
-    self._check(pn_messenger_set_password(self._mng, value))
-
-  password = property(_get_password, _set_password,
-                      doc="""
-This property contains the password for the L{Messenger.private_key}
-file, or None if the file is not encrypted.
-""")
-
-  def _get_trusted_certificates(self):
-    return pn_messenger_get_trusted_certificates(self._mng)
-
-  def _set_trusted_certificates(self, value):
-    self._check(pn_messenger_set_trusted_certificates(self._mng, value))
-
-  trusted_certificates = property(_get_trusted_certificates,
-                                  _set_trusted_certificates,
-                                  doc="""
-A path to a database of trusted certificates for use in verifying the
-peer on an SSL/TLS connection. If this property is None, then the peer
-will not be verified.
-""")
-
-  def _get_timeout(self):
-    t = pn_messenger_get_timeout(self._mng)
-    if t == -1:
-      return None
-    else:
-      return millis2secs(t)
-
-  def _set_timeout(self, value):
-    if value is None:
-      t = -1
-    else:
-      t = secs2millis(value)
-    self._check(pn_messenger_set_timeout(self._mng, t))
-
-  timeout = property(_get_timeout, _set_timeout,
-                     doc="""
-The timeout property contains the default timeout for blocking
-operations performed by the L{Messenger}.
-""")
-
-  def _is_blocking(self):
-    return pn_messenger_is_blocking(self._mng)
-
-  def _set_blocking(self, b):
-    self._check(pn_messenger_set_blocking(self._mng, b))
-
-  blocking = property(_is_blocking, _set_blocking,
-                      doc="""
-Enable or disable blocking behavior during L{Message} sending
-and receiving.  This affects every blocking call, with the
-exception of L{work}.  Currently, the affected calls are
-L{send}, L{recv}, and L{stop}.
-""")
-
-  def _is_passive(self):
-    return pn_messenger_is_passive(self._mng)
-
-  def _set_passive(self, b):
-    self._check(pn_messenger_set_passive(self._mng, b))
-
-  passive = property(_is_passive, _set_passive,
-                      doc="""
-When passive is set to true, Messenger will not attempt to perform I/O
-internally. In this mode it is necessary to use the selectables API to
-drive any I/O needed to perform requested actions. In this mode
-Messenger will never block.
-""")
-
-  def _get_incoming_window(self):
-    return pn_messenger_get_incoming_window(self._mng)
-
-  def _set_incoming_window(self, window):
-    self._check(pn_messenger_set_incoming_window(self._mng, window))
-
-  incoming_window = property(_get_incoming_window, _set_incoming_window,
-                             doc="""
-The incoming tracking window for the messenger. The messenger will
-track the remote status of this many incoming deliveries after they
-have been accepted or rejected. Defaults to zero.
-
-L{Messages<Message>} enter this window only when you take them into your application
-using L{get}.  If your incoming window size is I{n}, and you get I{n}+1 L{messages<Message>}
-without explicitly accepting or rejecting the oldest message, then the
-message that passes beyond the edge of the incoming window will be assigned
-the default disposition of its link.
-""")
-
-  def _get_outgoing_window(self):
-    return pn_messenger_get_outgoing_window(self._mng)
-
-  def _set_outgoing_window(self, window):
-    self._check(pn_messenger_set_outgoing_window(self._mng, window))
-
-  outgoing_window = property(_get_outgoing_window, _set_outgoing_window,
-                             doc="""
-The outgoing tracking window for the messenger. The messenger will
-track the remote status of this many outgoing deliveries after calling
-send. Defaults to zero.
-
-A L{Message} enters this window when you call the put() method with the
-message.  If your outgoing window size is I{n}, and you call L{put} I{n}+1
-times, status information will no longer be available for the
-first message.
-""")
-
-  def start(self):
-    """
-    Currently a no-op placeholder.
-    For future compatibility, do not L{send} or L{recv} messages
-    before starting the L{Messenger}.
-    """
-    self._check(pn_messenger_start(self._mng))
-
-  def stop(self):
-    """
-    Transitions the L{Messenger} to an inactive state. An inactive
-    L{Messenger} will not send or receive messages from its internal
-    queues. A L{Messenger} should be stopped before being discarded to
-    ensure a clean shutdown handshake occurs on any internally managed
-    connections.
-    """
-    self._check(pn_messenger_stop(self._mng))
-
-  @property
-  def stopped(self):
-    """
-    Returns true iff a L{Messenger} is in the stopped state.
-    This function does not block.
-    """
-    return pn_messenger_stopped(self._mng)
-
-  def subscribe(self, source):
-    """
-    Subscribes the L{Messenger} to messages originating from the
-    specified source. The source is an address as specified in the
-    L{Messenger} introduction with the following addition. If the
-    domain portion of the address begins with the '~' character, the
-    L{Messenger} will interpret the domain as host/port, bind to it,
-    and listen for incoming messages. For example "~0.0.0.0",
-    "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any
-    local interface and listen for incoming messages with the last
-    variant only permitting incoming SSL connections.
-
-    @type source: string
-    @param source: the source of messages to subscribe to
-    """
-    sub_impl = pn_messenger_subscribe(self._mng, source)
-    if not sub_impl:
-      self._check(pn_error_code(pn_messenger_error(self._mng)))
-      raise MessengerException("Cannot subscribe to %s"%source)
-    return Subscription(sub_impl)
-
-  def put(self, message):
-    """
-    Places the content contained in the message onto the outgoing
-    queue of the L{Messenger}. This method will never block, however
-    it will send any unblocked L{Messages<Message>} in the outgoing
-    queue immediately and leave any blocked L{Messages<Message>}
-    remaining in the outgoing queue. The L{send} call may be used to
-    block until the outgoing queue is empty. The L{outgoing} property
-    may be used to check the depth of the outgoing queue.
-
-    When the content in a given L{Message} object is copied to the outgoing
-    message queue, you may then modify or discard the L{Message} object
-    without having any impact on the content in the outgoing queue.
-
-    This method returns an outgoing tracker for the L{Message}.  The tracker
-    can be used to determine the delivery status of the L{Message}.
-
-    @type message: Message
-    @param message: the message to place in the outgoing queue
-    @return: a tracker
-    """
-    message._pre_encode()
-    self._check(pn_messenger_put(self._mng, message._msg))
-    return pn_messenger_outgoing_tracker(self._mng)
-
-  def status(self, tracker):
-    """
-    Gets the last known remote state of the delivery associated with
-    the given tracker.
-
-    @type tracker: tracker
-    @param tracker: the tracker whose status is to be retrieved
-
-    @return: one of None, PENDING, REJECTED, or ACCEPTED
-    """
-    disp = pn_messenger_status(self._mng, tracker);
-    return STATUSES.get(disp, disp)
-
-  def buffered(self, tracker):
-    """
-    Checks if the delivery associated with the given tracker is still
-    waiting to be sent.
-
-    @type tracker: tracker
-    @param tracker: the tracker whose status is to be retrieved
-
-    @return: true if delivery is still buffered
-    """
-    return pn_messenger_buffered(self._mng, tracker);
-
-  def settle(self, tracker=None):
-    """
-    Frees a L{Messenger} from tracking the status associated with a given
-    tracker. If you don't supply a tracker, all outgoing L{messages<Message>} up
-    to the most recent will be settled.
-    """
-    if tracker is None:
-      tracker = pn_messenger_outgoing_tracker(self._mng)
-      flags = PN_CUMULATIVE
-    else:
-      flags = 0
-    self._check(pn_messenger_settle(self._mng, tracker, flags))
-
-  def send(self, n=-1):
-    """
-    This call will block until the indicated number of L{messages<Message>}
-    have been sent, or until the operation times out.  If n is -1 this call will
-    block until all outgoing L{messages<Message>} have been sent. If n is 0 then
-    this call will send whatever it can without blocking.
-    """
-    self._check(pn_messenger_send(self._mng, n))
-
-  def recv(self, n=None):
-    """
-    Receives up to I{n} L{messages<Message>} into the incoming queue.  If no value
-    for I{n} is supplied, this call will receive as many L{messages<Message>} as it
-    can buffer internally.  If the L{Messenger} is in blocking mode, this
-    call will block until at least one L{Message} is available in the
-    incoming queue.
-    """
-    if n is None:
-      n = -1
-    self._check(pn_messenger_recv(self._mng, n))
-
-  def work(self, timeout=None):
-    """
-    Sends or receives any outstanding L{messages<Message>} queued for a L{Messenger}.
-    This will block for the indicated timeout.
-    This method may also do I/O work other than sending and receiving
-    L{messages<Message>}.  For example, closing connections after messenger.L{stop}()
-    has been called.
-    """
-    if timeout is None:
-      t = -1
-    else:
-      t = secs2millis(timeout)
-    err = pn_messenger_work(self._mng, t)
-    if (err == PN_TIMEOUT):
-      return False
-    else:
-      self._check(err)
-      return True
-
-  @property
-  def receiving(self):
-    return pn_messenger_receiving(self._mng)
-
-  def interrupt(self):
-    """
-    The L{Messenger} interface is single-threaded.
-    This is the only L{Messenger} function intended to be called
-    from outside of the L{Messenger} thread.
-    Call this from a non-messenger thread to interrupt
-    a L{Messenger} that is blocking.
-    This will cause any in-progress blocking call to throw
-    the L{Interrupt} exception.  If there is no currently blocking
-    call, then the next blocking call will be affected, even if it
-    is within the same thread that interrupt was called from.
-    """
-    self._check(pn_messenger_interrupt(self._mng))
-
-  def get(self, message=None):
-    """
-    Moves the message from the head of the incoming message queue into
-    the supplied message object. Any content in the message will be
-    overwritten.
-
-    A tracker for the incoming L{Message} is returned.  The tracker can
-    later be used to communicate your acceptance or rejection of the
-    L{Message}.
-
-    If None is passed in for the L{Message} object, the L{Message}
-    popped from the head of the queue is discarded.
-
-    @type message: Message
-    @param message: the destination message object
-    @return: a tracker
-    """
-    if message is None:
-      impl = None
-    else:
-      impl = message._msg
-    self._check(pn_messenger_get(self._mng, impl))
-    if message is not None:
-      message._post_decode()
-    return pn_messenger_incoming_tracker(self._mng)
-
-  def accept(self, tracker=None):
-    """
-    Signal the sender that you have acted on the L{Message}
-    pointed to by the tracker.  If no tracker is supplied,
-    then all messages that have been returned by the L{get}
-    method are accepted, except those that have already been
-    auto-settled by passing beyond your incoming window size.
-
-    @type tracker: tracker
-    @param tracker: a tracker as returned by get
-    """
-    if tracker is None:
-      tracker = pn_messenger_incoming_tracker(self._mng)
-      flags = PN_CUMULATIVE
-    else:
-      flags = 0
-    self._check(pn_messenger_accept(self._mng, tracker, flags))
-
-  def reject(self, tracker=None):
-    """
-    Rejects the L{Message} indicated by the tracker.  If no tracker
-    is supplied, all messages that have been returned by the L{get}
-    method are rejected, except those that have already been auto-settled
-    by passing beyond your outgoing window size.
-
-    @type tracker: tracker
-    @param tracker: a tracker as returned by get
-    """
-    if tracker is None:
-      tracker = pn_messenger_incoming_tracker(self._mng)
-      flags = PN_CUMULATIVE
-    else:
-      flags = 0
-    self._check(pn_messenger_reject(self._mng, tracker, flags))
-
-  @property
-  def outgoing(self):
-    """
-    The outgoing queue depth.
-    """
-    return pn_messenger_outgoing(self._mng)
-
-  @property
-  def incoming(self):
-    """
-    The incoming queue depth.
-    """
-    return pn_messenger_incoming(self._mng)
-
-  def route(self, pattern, address):
-    """
-          Adds a routing rule to a L{Messenger's<Messenger>} internal routing table.
-
-          The route procedure may be used to influence how a L{Messenger} will
-          internally treat a given address or class of addresses. Every call
-          to the route procedure will result in L{Messenger} appending a routing
-          rule to its internal routing table.
-
-          Whenever a L{Message} is presented to a L{Messenger} for delivery, it
-          will match the address of this message against the set of routing
-          rules in order. The first rule to match will be triggered, and
-          instead of routing based on the address presented in the message,
-          the L{Messenger} will route based on the address supplied in the rule.
-
-          The pattern matching syntax supports two types of matches, a '%'
-          will match any character except a '/', and a '*' will match any
-          character including a '/'.
-
-          A routing address is specified as a normal AMQP address, however it
-          may additionally use substitution variables from the pattern match
-          that triggered the rule.
-
-          Any message sent to "foo" will be routed to "amqp://foo.com":
-
-             >>> messenger.route("foo", "amqp://foo.com");
-
-          Any message sent to "foobar" will be routed to
-          "amqp://foo.com/bar":
-
-             >>> messenger.route("foobar", "amqp://foo.com/bar");
-
-          Any message sent to bar/<path> will be routed to the corresponding
-          path within the amqp://bar.com domain:
-
-             >>> messenger.route("bar/*", "amqp://bar.com/$1");
-
-          Route all L{messages<Message>} over TLS:
-
-             >>> messenger.route("amqp:*", "amqps:$1")
-
-          Supply credentials for foo.com:
-
-             >>> messenger.route("amqp://foo.com/*", "amqp://user:password@foo.com/$1");
-
-          Supply credentials for all domains:
-
-             >>> messenger.route("amqp://*", "amqp://user:password@$1");
-
-          Route all addresses through a single proxy while preserving the
-          original destination:
-
-             >>> messenger.route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
-
-          Route any address through a single broker:
-
-             >>> messenger.route("*", "amqp://user:password@broker/$1");
-    """
-    self._check(pn_messenger_route(self._mng, pattern, address))
-
-  def rewrite(self, pattern, address):
-    """
-    Similar to route(), except that the destination of
-    the L{Message} is determined before the message address is rewritten.
-
-    The outgoing address is only rewritten after routing has been
-    finalized.  If a message has an outgoing address of
-    "amqp://0.0.0.0:5678", and a rewriting rule that changes its
-    outgoing address to "foo", it will still arrive at the peer that
-    is listening on "amqp://0.0.0.0:5678", but when it arrives there,
-    the receiver will see its outgoing address as "foo".
-
-    The default rewrite rule removes username and password from addresses
-    before they are transmitted.
-    """
-    self._check(pn_messenger_rewrite(self._mng, pattern, address))
-
-  def selectable(self):
-    impl = pn_messenger_selectable(self._mng)
-    if impl:
-      fd = pn_selectable_fd(impl)
-      sel = self._selectables.get(fd, None)
-      if sel is None:
-        sel = Selectable(self, impl)
-        self._selectables[fd] = sel
-      return sel
-    else:
-      return None
-
-  @property
-  def deadline(self):
-    tstamp = pn_messenger_deadline(self._mng)
-    if tstamp:
-      return millis2secs(tstamp)
-    else:
-      return None
-
-class Message(object):
-  """The L{Message} class is a mutable holder of message content.
-
-  @ivar instructions: delivery instructions for the message
-  @type instructions: dict
-  @ivar annotations: infrastructure defined message annotations
-  @type annotations: dict
-  @ivar properties: application defined message properties
-  @type properties: dict
-  @ivar body: message body
-  @type body: bytes | unicode | dict | list | int | long | float | UUID
-  """
-
-  DATA = PN_DATA
-  TEXT = PN_TEXT
-  AMQP = PN_AMQP
-  JSON = PN_JSON
-
-  DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
-
-  def __init__(self, **kwargs):
-    """
-    @param kwargs: Message property name/value pairs to initialise the Message
-    """
-    self._msg = pn_message()
-    self._id = Data(pn_message_id(self._msg))
-    self._correlation_id = Data(pn_message_correlation_id(self._msg))
-    self.instructions = None
-    self.annotations = None
-    self.properties = None
-    self.body = None
-    for k,v in kwargs.iteritems():
-      getattr(self, k)          # Raise exception if it's not a valid attribute.
-      setattr(self, k, v)
-
-  def __del__(self):
-    if hasattr(self, "_msg"):
-      pn_message_free(self._msg)
-      del self._msg
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, MessageException)
-      raise exc("[%s]: %s" % (err, pn_error_text(pn_message_error(self._msg))))
-    else:
-      return err
-
-  def _pre_encode(self):
-    inst = Data(pn_message_instructions(self._msg))
-    ann = Data(pn_message_annotations(self._msg))
-    props = Data(pn_message_properties(self._msg))
-    body = Data(pn_message_body(self._msg))
-
-    inst.clear()
-    if self.instructions is not None:
-      inst.put_object(self.instructions)
-    ann.clear()
-    if self.annotations is not None:
-      ann.put_object(self.annotations)
-    props.clear()
-    if self.properties is not None:
-      props.put_object(self.properties)
-    body.clear()
-    if self.body is not None:
-      body.put_object(self.body)
-
-  def _post_decode(self):
-    inst = Data(pn_message_instructions(self._msg))
-    ann = Data(pn_message_annotations(self._msg))
-    props = Data(pn_message_properties(self._msg))
-    body = Data(pn_message_body(self._msg))
-
-    if inst.next():
-      self.instructions = inst.get_object()
-    else:
-      self.instructions = None
-    if ann.next():
-      self.annotations = ann.get_object()
-    else:
-      self.annotations = None
-    if props.next():
-      self.properties = props.get_object()
-    else:
-      self.properties = None
-    if body.next():
-      self.body = body.get_object()
-    else:
-      self.body = None
-
-  def clear(self):
-    """
-    Clears the contents of the L{Message}. All fields will be reset to
-    their default values.
-    """
-    pn_message_clear(self._msg)
-    self.instructions = None
-    self.annotations = None
-    self.properties = None
-    self.body = None
-
-  def _is_inferred(self):
-    return pn_message_is_inferred(self._msg)
-
-  def _set_inferred(self, value):
-    self._check(pn_message_set_inferred(self._msg, bool(value)))
-
-  inferred = property(_is_inferred, _set_inferred, doc="""
-The inferred flag for a message indicates how the message content
-is encoded into AMQP sections. If inferred is true then binary and
-list values in the body of the message will be encoded as AMQP DATA
-and AMQP SEQUENCE sections, respectively. If inferred is false,
-then all values in the body of the message will be encoded as AMQP
-VALUE sections regardless of their type.
-""")
-
-  def _is_durable(self):
-    return pn_message_is_durable(self._msg)
-
-  def _set_durable(self, value):
-    self._check(pn_message_set_durable(self._msg, bool(value)))
-
-  durable = property(_is_durable, _set_durable,
-                     doc="""
-The durable property indicates that the message should be held durably
-by any intermediaries taking responsibility for the message.
-""")
-
-  def _get_priority(self):
-    return pn_message_get_priority(self._msg)
-
-  def _set_priority(self, value):
-    self._check(pn_message_set_priority(self._msg, value))
-
-  priority = property(_get_priority, _set_priority,
-                      doc="""
-The priority of the message.
-""")
-
-  def _get_ttl(self):
-    return millis2secs(pn_message_get_ttl(self._msg))
-
-  def _set_ttl(self, value):
-    self._check(pn_message_set_ttl(self._msg, secs2millis(value)))
-
-  ttl = property(_get_ttl, _set_ttl,
-                 doc="""
-The time to live of the message measured in seconds. Expired messages
-may be dropped.
-""")
-
-  def _is_first_acquirer(self):
-    return pn_message_is_first_acquirer(self._msg)
-
-  def _set_first_acquirer(self, value):
-    self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
-
-  first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
-                            doc="""
-True iff the recipient is the first to acquire the message.
-""")
-
-  def _get_delivery_count(self):
-    return pn_message_get_delivery_count(self._msg)
-
-  def _set_delivery_count(self, value):
-    self._check(pn_message_set_delivery_count(self._msg, value))
-
-  delivery_count = property(_get_delivery_count, _set_delivery_count,
-                            doc="""
-The number of delivery attempts made for this message.
-""")
-
-
-  def _get_id(self):
-    return self._id.get_object()
-  def _set_id(self, value):
-    if type(value) in (int, long):
-      value = ulong(value)
-    self._id.rewind()
-    self._id.put_object(value)
-  id = property(_get_id, _set_id,
-                doc="""
-The id of the message.
-""")
-
-  def _get_user_id(self):
-    return pn_message_get_user_id(self._msg)
-
-  def _set_user_id(self, value):
-    self._check(pn_message_set_user_id(self._msg, value))
-
-  user_id = property(_get_user_id, _set_user_id,
-                     doc="""
-The user id of the message creator.
-""")
-
-  def _get_address(self):
-    return pn_message_get_address(self._msg)
-
-  def _set_address(self, value):
-    self._check(pn_message_set_address(self._msg, value))
-
-  address = property(_get_address, _set_address,
-                     doc="""
-The address of the message.
-""")
-
-  def _get_subject(self):
-    return pn_message_get_subject(self._msg)
-
-  def _set_subject(self, value):
-    self._check(pn_message_set_subject(self._msg, value))
-
-  subject = property(_get_subject, _set_subject,
-                     doc="""
-The subject of the message.
-""")
-
-  def _get_reply_to(self):
-    return pn_message_get_reply_to(self._msg)
-
-  def _set_reply_to(self, value):
-    self._check(pn_message_set_reply_to(self._msg, value))
-
-  reply_to = property(_get_reply_to, _set_reply_to,
-                      doc="""
-The reply-to address for the message.
-""")
-
-  def _get_correlation_id(self):
-    return self._correlation_id.get_object()
-  def _set_correlation_id(self, value):
-    if type(value) in (int, long):
-      value = ulong(value)
-    self._correlation_id.rewind()
-    self._correlation_id.put_object(value)
-
-  correlation_id = property(_get_correlation_id, _set_correlation_id,
-                            doc="""
-The correlation-id for the message.
-""")
-
-  def _get_content_type(self):
-    return pn_message_get_content_type(self._msg)
-
-  def _set_content_type(self, value):
-    self._check(pn_message_set_content_type(self._msg, value))
-
-  content_type = property(_get_content_type, _set_content_type,
-                          doc="""
-The content-type of the message.
-""")
-
-  def _get_content_encoding(self):
-    return pn_message_get_content_encoding(self._msg)
-
-  def _set_content_encoding(self, value):
-    self._check(pn_message_set_content_encoding(self._msg, value))
-
-  content_encoding = property(_get_content_encoding, _set_content_encoding,
-                              doc="""
-The content-encoding of the message.
-""")
-
-  def _get_expiry_time(self):
-    return millis2secs(pn_message_get_expiry_time(self._msg))
-
-  def _set_expiry_time(self, value):
-    self._check(pn_message_set_expiry_time(self._msg, secs2millis(value)))
-
-  expiry_time = property(_get_expiry_time, _set_expiry_time,
-                         doc="""
-The expiry time of the message.
-""")
-
-  def _get_creation_time(self):
-    return millis2secs(pn_message_get_creation_time(self._msg))
-
-  def _set_creation_time(self, value):
-    self._check(pn_message_set_creation_time(self._msg, secs2millis(value)))
-
-  creation_time = property(_get_creation_time, _set_creation_time,
-                           doc="""
-The creation time of the message.
-""")
-
-  def _get_group_id(self):
-    return pn_message_get_group_id(self._msg)
-
-  def _set_group_id(self, value):
-    self._check(pn_message_set_group_id(self._msg, value))
-
-  group_id = property(_get_group_id, _set_group_id,
-                      doc="""
-The group id of the message.
-""")
-
-  def _get_group_sequence(self):
-    return pn_message_get_group_sequence(self._msg)
-
-  def _set_group_sequence(self, value):
-    self._check(pn_message_set_group_sequence(self._msg, value))
-
-  group_sequence = property(_get_group_sequence, _set_group_sequence,
-                            doc="""
-The sequence of the message within its group.
-""")
-
-  def _get_reply_to_group_id(self):
-    return pn_message_get_reply_to_group_id(self._msg)
-
-  def _set_reply_to_group_id(self, value):
-    self._check(pn_message_set_reply_to_group_id(self._msg, value))
-
-  reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
-                               doc="""
-The group-id for any replies.
-""")
-
-  # XXX
-  def _get_format(self):
-    return pn_message_get_format(self._msg)
-
-  def _set_format(self, value):
-    self._check(pn_message_set_format(self._msg, value))
-
-  format = property(_get_format, _set_format,
-                    doc="""
-The format of the message.
-""")
-
-  def encode(self):
-    self._pre_encode()
-    sz = 16
-    while True:
-      err, data = pn_message_encode(self._msg, sz)
-      if err == PN_OVERFLOW:
-        sz *= 2
-        continue
-      else:
-        self._check(err)
-        return data
-
-  def decode(self, data):
-    self._check(pn_message_decode(self._msg, data, len(data)))
-    self._post_decode()
-
-  def load(self, data):
-    self._check(pn_message_load(self._msg, data))
-
-  def save(self):
-    sz = 16
-    while True:
-      err, data = pn_message_save(self._msg, sz)
-      if err == PN_OVERFLOW:
-        sz *= 2
-        continue
-      else:
-        self._check(err)
-        return data
-
-  def __repr2__(self):
-    props = []
-    for attr in ("inferred", "address", "reply_to", "durable", "ttl",
-                 "priority", "first_acquirer", "delivery_count", "id",
-                 "correlation_id", "user_id", "group_id", "group_sequence",
-                 "reply_to_group_id", "instructions", "annotations",
-                 "properties", "body"):
-      value = getattr(self, attr)
-      if value: props.append("%s=%r" % (attr, value))
-    return "Message(%s)" % ", ".join(props)
-
-  def __repr__(self):
-    tmp = pn_string(None)
-    err = pn_inspect(self._msg, tmp)
-    result = pn_string_get(tmp)
-    pn_free(tmp)
-    self._check(err)
-    return result
-
-class Subscription(object):
-
-  def __init__(self, impl):
-    self._impl = impl
-
-  @property
-  def address(self):
-    return pn_subscription_address(self._impl)
-
-class Selectable(object):
-
-  def __init__(self, messenger, impl):
-    self.messenger = messenger
-    self._impl = impl
-
-  def fileno(self):
-    if not self._impl: raise ValueError("selectable freed")
-    return pn_selectable_fd(self._impl)
-
-  @property
-  def capacity(self):
-    if not self._impl: raise ValueError("selectable freed")
-    return pn_selectable_capacity(self._impl)
-
-  @property
-  def pending(self):
-    if not self._impl: raise ValueError("selectable freed")
-    return pn_selectable_pending(self._impl)
-
-  @property
-  def deadline(self):
-    if not self._impl: raise ValueError("selectable freed")
-    tstamp = pn_selectable_deadline(self._impl)
-    if tstamp:
-      return millis2secs(tstamp)
-    else:
-      return None
-
-  def readable(self):
-    if not self._impl: raise ValueError("selectable freed")
-    pn_selectable_readable(self._impl)
-
-  def writable(self):
-    if not self._impl: raise ValueError("selectable freed")
-    pn_selectable_writable(self._impl)
-
-  def expired(self):
-    if not self._impl: raise ValueError("selectable freed")
-    pn_selectable_expired(self._impl)
-
-  def _is_registered(self):
-    if not self._impl: raise ValueError("selectable freed")
-    return pn_selectable_is_registered(self._impl)
-
-  def _set_registered(self, registered):
-    if not self._impl: raise ValueError("selectable freed")
-    pn_selectable_set_registered(self._impl, registered)
-
-  registered = property(_is_registered, _set_registered,
-                    doc="""
-The registered property may be get/set by an I/O polling system to
-indicate whether the fd has been registered or not.
-""")
-
-  @property
-  def is_terminal(self):
-    if not self._impl: return True
-    return pn_selectable_is_terminal(self._impl)
-
-  def free(self):
-    if self._impl:
-      del self.messenger._selectables[self.fileno()]
-      pn_selectable_free(self._impl)
-      self._impl = None
-
-  def __del__(self):
-    self.free()
-
-class DataException(ProtonException):
-  """
-  The DataException class is the root of the Data exception hierarchy.
-  All exceptions raised by the Data class extend this exception.
-  """
-  pass
-
-class UnmappedType:
-
-  def __init__(self, msg):
-    self.msg = msg
-
-  def __repr__(self):
-    return "UnmappedType(%s)" % self.msg
-
-class ulong(long):
-
-  def __repr__(self):
-    return "ulong(%s)" % long.__repr__(self)
-
-class timestamp(long):
-
-  def __repr__(self):
-    return "timestamp(%s)" % long.__repr__(self)
-
-class symbol(unicode):
-
-  def __repr__(self):
-    return "symbol(%s)" % unicode.__repr__(self)
-
-class char(unicode):
-
-  def __repr__(self):
-    return "char(%s)" % unicode.__repr__(self)
-
-class Described(object):
-
-  def __init__(self, descriptor, value):
-    self.descriptor = descriptor
-    self.value = value
-
-  def __repr__(self):
-    return "Described(%r, %r)" % (self.descriptor, self.value)
-
-  def __eq__(self, o):
-    if isinstance(o, Described):
-      return self.descriptor == o.descriptor and self.value == o.value
-    else:
-      return False
-
-UNDESCRIBED = Constant("UNDESCRIBED")
-
-class Array(object):
-
-  def __init__(self, descriptor, type, *elements):
-    self.descriptor = descriptor
-    self.type = type
-    self.elements = elements
-
-  def __repr__(self):
-    if self.elements:
-      els = ", %s"  % (", ".join(map(repr, self.elements)))
-    else:
-      els = ""
-    return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
-
-  def __eq__(self, o):
-    if isinstance(o, Array):
-      return self.descriptor == o.descriptor and \
-          self.type == o.type and self.elements == o.elements
-    else:
-      return False
-
-class Data:
-  """
-  The L{Data} class provides an interface for decoding, extracting,
-  creating, and encoding arbitrary AMQP data. A L{Data} object
-  contains a tree of AMQP values. Leaf nodes in this tree correspond
-  to scalars in the AMQP type system such as L{ints<INT>} or
-  L{strings<STRING>}. Non-leaf nodes in this tree correspond to
-  compound values in the AMQP type system such as L{lists<LIST>},
-  L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
-  The root node of the tree is the L{Data} object itself and can have
-  an arbitrary number of children.
-
-  A L{Data} object maintains the notion of the current sibling node
-  and a current parent node. Siblings are ordered within their parent.
-  Values are accessed and/or added by using the L{next}, L{prev},
-  L{enter}, and L{exit} methods to navigate to the desired location in
-  the tree and using the supplied variety of put_*/get_* methods to
-  access or add a value of the desired type.
-
-  The put_* methods will always add a value I{after} the current node
-  in the tree. If the current node has a next sibling the put_* method
-  will overwrite the value on this node. If there is no current node
-  or the current node has no next sibling then one will be added. The
-  put_* methods always set the added/modified node to the current
-  node. The get_* methods read the value of the current node and do
-  not change which node is current.
-
-  The following types of scalar values are supported:
-
-   - L{NULL}
-   - L{BOOL}
-   - L{UBYTE}
-   - L{USHORT}
-   - L{SHORT}
-   - L{UINT}
-   - L{INT}
-   - L{ULONG}
-   - L{LONG}
-   - L{FLOAT}
-   - L{DOUBLE}
-   - L{BINARY}
-   - L{STRING}
-   - L{SYMBOL}
-
-  The following types of compound values are supported:
-
-   - L{DESCRIBED}
-   - L{ARRAY}
-   - L{LIST}
-   - L{MAP}
-  """
-
-  NULL = PN_NULL; "A null value."
-  BOOL = PN_BOOL; "A boolean value."
-  UBYTE = PN_UBYTE; "An unsigned byte value."
-  BYTE = PN_BYTE; "A signed byte value."
-  USHORT = PN_USHORT; "An unsigned short value."
-  SHORT = PN_SHORT; "A short value."
-  UINT = PN_UINT; "An unsigned int value."
-  INT = PN_INT; "A signed int value."
-  CHAR = PN_CHAR; "A character value."
-  ULONG = PN_ULONG; "An unsigned long value."
-  LONG = PN_LONG; "A signed long value."
-  TIMESTAMP = PN_TIMESTAMP; "A timestamp value."
-  FLOAT = PN_FLOAT; "A float value."
-  DOUBLE = PN_DOUBLE; "A double value."
-  DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value."
-  DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value."
-  DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value."
-  UUID = PN_UUID; "A UUID value."
-  BINARY = PN_BINARY; "A binary string."
-  STRING = PN_STRING; "A unicode string."
-  SYMBOL = PN_SYMBOL; "A symbolic string."
-  DESCRIBED = PN_DESCRIBED; "A described value."
-  ARRAY = PN_ARRAY; "An array value."
-  LIST = PN_LIST; "A list value."
-  MAP = PN_MAP; "A map value."
-
-  type_names = {
-    NULL: "null",
-    BOOL: "bool",
-    BYTE: "byte",
-    UBYTE: "ubyte",
-    SHORT: "short",
-    USHORT: "ushort",
-    INT: "int",
-    UINT: "uint",
-    CHAR: "char",
-    LONG: "long",
-    ULONG: "ulong",
-    TIMESTAMP: "timestamp",
-    FLOAT: "float",
-    DOUBLE: "double",
-    DECIMAL32: "decimal32",
-    DECIMAL64: "decimal64",
-    DECIMAL128: "decimal128",
-    UUID: "uuid",
-    BINARY: "binary",
-    STRING: "string",
-    SYMBOL: "symbol",
-    DESCRIBED: "described",
-    ARRAY: "array",
-    LIST: "list",
-    MAP: "map"
-    }
-
-  @classmethod
-  def type_name(type): return Data.type_names[type]
-
-  def __init__(self, capacity=16):
-    if type(capacity) in (int, long):
-      self._data = pn_data(capacity)
-      self._free = True
-    else:
-      self._data = capacity
-      self._free = False
-
-  def __del__(self):
-    if self._free and hasattr(self, "_data"):
-      pn_data_free(self._data)
-      del self._data
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, DataException)
-      raise exc("[%s]: %s" % (err, pn_error_text(pn_data_error(self._data))))
-    else:
-      return err
-
-  def clear(self):
-    """
-    Clears the data object.
-    """
-    pn_data_clear(self._data)
-
-  def rewind(self):
-    """
-    Clears current node and sets the parent to the root node.  Clearing the
-    current node sets it _before_ the first node, calling next() will advance to
-    the first node.
-    """
-    assert self._data is not None
-    pn_data_rewind(self._data)
-
-  def next(self):
-    """
-    Advances the current node to its next sibling and returns its
-    type. If there is no next sibling the current node remains
-    unchanged and None is returned.
-    """
-    found = pn_data_next(self._data)
-    if found:
-      return self.type()
-    else:
-      return None
-
-  def prev(self):
-    """
-    Advances the current node to its previous sibling and returns its
-    type. If there is no previous sibling the current node remains
-    unchanged and None is returned.
-    """
-    found = pn_data_prev(self._data)
-    if found:
-      return self.type()
-    else:
-      return None
-
-  def enter(self):
-    """
-    Sets the parent node to the current node and clears the current node.
-    Clearing the current node sets it _before_ the first child,
-    call next() advances to the first child.
-    """
-    return pn_data_enter(self._data)
-
-  def exit(self):
-    """
-    Sets the current node to the parent node and the parent node to
-    its own parent.
-    """
-    return pn_data_exit(self._data)
-
-  def lookup(self, name):
-    return pn_data_lookup(self._data, name)
-
-  def narrow(self):
-    pn_data_narrow(self._data)
-
-  def widen(self):
-    pn_data_widen(self._data)
-
-  def type(self):
-    """
-    Returns the type of the current node.
-    """
-    dtype = pn_data_type(self._data)
-    if dtype == -1:
-      return None
-    else:
-      return dtype
-
-  def encode(self):
-    """
-    Returns a representation of the data encoded in AMQP format.
-    """
-    size = 1024
-    while True:
-      cd, enc = pn_data_encode(self._data, size)
-      if cd == PN_OVERFLOW:
-        size *= 2
-      elif cd >= 0:
-        return enc
-      else:
-        self._check(cd)
-
-  def decode(self, encoded):
-    """
-    Decodes the first value from supplied AMQP data and returns the
-    number of bytes consumed.
-
-    @type encoded: binary
-    @param encoded: AMQP encoded binary data
-    """
-    return self._check(pn_data_decode(self._data, encoded))
-
-  def put_list(self):
-    """
-    Puts a list value. Elements may be filled by entering the list
-    node and putting element values.
-
-      >>> data = Data()
-      >>> data.put_list()
-      >>> data.enter()
-      >>> data.put_int(1)
-      >>> data.put_int(2)
-      >>> data.put_int(3)
-      >>> data.exit()
-    """
-    self._check(pn_data_put_list(self._data))
-
-  def put_map(self):
-    """
-    Puts a map value. Elements may be filled by entering the map node
-    and putting alternating key value pairs.
-
-      >>> data = Data()
-      >>> data.put_map()
-      >>> data.enter()
-      >>> data.put_string("key")
-      >>> data.put_string("value")
-      >>> data.exit()
-    """
-    self._check(pn_data_put_map(self._data))
-
-  def put_array(self, described, element_type):
-    """
-    Puts an array value. Elements may be filled by entering the array
-    node and putting the element values. The values must all be of the
-    specified array element type. If an array is described then the
-    first child value of the array is the descriptor and may be of any
-    type.
-
-      >>> data = Data()
-      >>>
-      >>> data.put_array(False, Data.INT)
-      >>> data.enter()
-      >>> data.put_int(1)
-      >>> data.put_int(2)
-      >>> data.put_int(3)
-      >>> data.exit()
-      >>>
-      >>> data.put_array(True, Data.DOUBLE)
-      >>> data.enter()
-      >>> data.put_symbol("array-descriptor")
-      >>> data.put_double(1.1)
-      >>> data.put_double(1.2)
-      >>> data.put_double(1.3)
-      >>> data.exit()
-
-    @type described: bool
-    @param described: specifies whether the array is described
-    @type element_type: int
-    @param element_type: the type of the array elements
-    """
-    self._check(pn_data_put_array(self._data, described, element_type))
-
-  def put_described(self):
-    """
-    Puts a described value. A described node has two children, the
-    descriptor and the value. These are specified by entering the node
-    and putting the desired values.
-
-      >>> data = Data()
-      >>> data.put_described()
-      >>> data.enter()
-      >>> data.put_symbol("value-descriptor")
-      >>> data.put_string("the value")
-      >>> data.exit()
-    """
-    self._check(pn_data_put_described(self._data))
-
-  def put_null(self):
-    """
-    Puts a null value.
-    """
-    self._check(pn_data_put_null(self._data))
-
-  def put_bool(self, b):
-    """
-    Puts a boolean value.
-
-    @param b: a boolean value
-    """
-    self._check(pn_data_put_bool(self._data, b))
-
-  def put_ubyte(self, ub):
-    """
-    Puts an unsigned byte value.
-
-    @param ub: an integral value
-    """
-    self._check(pn_data_put_ubyte(self._data, ub))
-
-  def put_byte(self, b):
-    """
-    Puts a signed byte value.
-
-    @param b: an integral value
-    """
-    self._check(pn_data_put_byte(self._data, b))
-
-  def put_ushort(self, us):
-    """
-    Puts an unsigned short value.
-
-    @param us: an integral value.
-    """
-    self._check(pn_data_put_ushort(self._data, us))
-
-  def put_short(self, s):
-    """
-    Puts a signed short value.
-
-    @param s: an integral value
-    """
-    self._check(pn_data_put_short(self._data, s))
-
-  def put_uint(self, ui):
-    """
-    Puts an unsigned int value.
-
-    @param ui: an integral value
-    """
-    self._check(pn_data_put_uint(self._data, ui))
-
-  def put_int(self, i):
-    """
-    Puts a signed int value.
-
-    @param i: an integral value
-    """
-    self._check(pn_data_put_int(self._data, i))
-
-  def put_char(self, c):
-    """
-    Puts a char value.
-
-    @param c: a single character
-    """
-    self._check(pn_data_put_char(self._data, ord(c)))
-
-  def put_ulong(self, ul):
-    """
-    Puts an unsigned long value.
-
-    @param ul: an integral value
-    """
-    self._check(pn_data_put_ulong(self._data, ul))
-
-  def put_long(self, l):
-    """
-    Puts a signed long value.
-
-    @param l: an integral value
-    """
-    self._check(pn_data_put_long(self._data, l))
-
-  def put_timestamp(self, t):
-    """
-    Puts a timestamp value.
-
-    @param t: an integral value
-    """
-    self._check(pn_data_put_timestamp(self._data, t))
-
-  def put_float(self, f):
-    """
-    Puts a float value.
-
-    @param f: a floating point value
-    """
-    self._check(pn_data_put_float(self._data, f))
-
-  def put_double(self, d):
-    """
-    Puts a double value.
-
-    @param d: a floating point value.
-    """
-    self._check(pn_data_put_double(self._data, d))
-
-  def put_decimal32(self, d):
-    """
-    Puts a decimal32 value.
-
-    @param d: a decimal32 value
-    """
-    self._check(pn_data_put_decimal32(self._data, d))
-
-  def put_decimal64(self, d):
-    """
-    Puts a decimal64 value.
-
-    @param d: a decimal64 value
-    """
-    self._check(pn_data_put_decimal64(self._data, d))
-
-  def put_decimal128(self, d):
-    """
-    Puts a decimal128 value.
-
-    @param d: a decimal128 value
-    """
-    self._check(pn_data_put_decimal128(self._data, d))
-
-  def put_uuid(self, u):
-    """
-    Puts a UUID value.
-
-    @param u: a uuid value
-    """
-    self._check(pn_data_put_uuid(self._data, u.bytes))
-
-  def put_binary(self, b):
-    """
-    Puts a binary value.
-
-    @type b: binary
-    @param b: a binary value
-    """
-    self._check(pn_data_put_binary(self._data, b))
-
-  def put_string(self, s):
-    """
-    Puts a unicode value.
-
-    @type s: unicode
-    @param s: a unicode value
-    """
-    self._check(pn_data_put_string(self._data, s.encode("utf8")))
-
-  def put_symbol(self, s):
-    """
-    Puts a symbolic value.
-
-    @type s: string
-    @param s: the symbol name
-    """
-    self._check(pn_data_put_symbol(self._data, s))
-
-  def get_list(self):
-    """
-    If the current node is a list, return the number of elements,
-    otherwise return zero. List elements can be accessed by entering
-    the list.
-
-      >>> count = data.get_list()
-      >>> data.enter()
-      >>> for i in range(count):
-      ...   type = data.next()
-      ...   if type == Data.STRING:
-      ...     print data.get_string()
-      ...   elif type == ...:
-      ...     ...
-      >>> data.exit()
-    """
-    return pn_data_get_list(self._data)
-
-  def get_map(self):
-    """
-    If the current node is a map, return the number of child elements,
-    otherwise return zero. Key value pairs can be accessed by entering
-    the map.
-
-      >>> count = data.get_map()
-      >>> data.enter()
-      >>> for i in range(count/2):
-      ...   type = data.next()
-      ...   if type == Data.STRING:
-      ...     print data.get_string()
-      ...   elif type == ...:
-      ...     ...
-      >>> data.exit()
-    """
-    return pn_data_get_map(self._data)
-
-  def get_array(self):
-    """
-    If the current node is an array, return a tuple of the element
-    count, a boolean indicating whether the array is described, and
-    the type of each element, otherwise return (0, False, None). Array
-    data can be accessed by entering the array.
-
-      >>> # read an array of strings with a symbolic descriptor
-      >>> count, described, type = data.get_array()
-      >>> data.enter()
-      >>> data.next()
-      >>> print "Descriptor:", data.get_symbol()
-      >>> for i in range(count):
-      ...    data.next()
-      ...    print "Element:", data.get_string()
-      >>> data.exit()
-    """
-    count = pn_data_get_array(self._data)
-    described = pn_data_is_array_described(self._data)
-    type = pn_data_get_array_type(self._data)
-    if type == -1:
-      type = None
-    return count, described, type
-
-  def is_described(self):
-    """
-    Checks if the current node is a described value. The descriptor
-    and value may be accessed by entering the described value.
-
-      >>> # read a symbolically described string
-      >>> assert data.is_described() # will error if the current node is not described
-      >>> data.enter()
-      >>> print data.get_symbol()
-      >>> print data.get_string()
-      >>> data.exit()
-    """
-    return pn_data_is_described(self._data)
-
-  def is_null(self):
-    """
-    Checks if the current node is a null.
-    """
-    return pn_data_is_null(self._data)
-
-  def get_bool(self):
-    """
-    If the current node is a boolean, returns its value, returns False
-    otherwise.
-    """
-    return pn_data_get_bool(self._data)
-
-  def get_ubyte(self):
-    """
-    If the current node is an unsigned byte, returns its value,
-    returns 0 otherwise.
-    """
-    return pn_data_get_ubyte(self._data)
-
-  def get_byte(self):
-    """
-    If the current node is a signed byte, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_byte(self._data)
-
-  def get_ushort(self):
-    """
-    If the current node is an unsigned short, returns its value,
-    returns 0 otherwise.
-    """
-    return pn_data_get_ushort(self._data)
-
-  def get_short(self):
-    """
-    If the current node is a signed short, returns its value, returns
-    0 otherwise.
-    """
-    return pn_data_get_short(self._data)
-
-  def get_uint(self):
-    """
-    If the current node is an unsigned int, returns its value, returns
-    0 otherwise.
-    """
-    return pn_data_get_uint(self._data)
-
-  def get_int(self):
-    """
-    If the current node is a signed int, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_int(self._data)
-
-  def get_char(self):
-    """
-    If the current node is a char, returns its value, returns 0
-    otherwise.
-    """
-    return char(unichr(pn_data_get_char(self._data)))
-
-  def get_ulong(self):
-    """
-    If the current node is an unsigned long, returns its value,
-    returns 0 otherwise.
-    """
-    return ulong(pn_data_get_ulong(self._data))
-
-  def get_long(self):
-    """
-    If the current node is an signed long, returns its value, returns
-    0 otherwise.
-    """
-    return pn_data_get_long(self._data)
-
-  def get_timestamp(self):
-    """
-    If the current node is a timestamp, returns its value, returns 0
-    otherwise.
-    """
-    return timestamp(pn_data_get_timestamp(self._data))
-
-  def get_float(self):
-    """
-    If the current node is a float, returns its value, raises 0
-    otherwise.
-    """
-    return pn_data_get_float(self._data)
-
-  def get_double(self):
-    """
-    If the current node is a double, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_double(self._data)
-
-  # XXX: need to convert
-  def get_decimal32(self):
-    """
-    If the current node is a decimal32, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_decimal32(self._data)
-
-  # XXX: need to convert
-  def get_decimal64(self):
-    """
-    If the current node is a decimal64, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_decimal64(self._data)
-
-  # XXX: need to convert
-  def get_decimal128(self):
-    """
-    If the current node is a decimal128, returns its value, returns 0
-    otherwise.
-    """
-    return pn_data_get_decimal128(self._data)
-
-  def get_uuid(self):
-    """
-    If the current node is a UUID, returns its value, returns None
-    otherwise.
-    """
-    if pn_data_type(self._data) == Data.UUID:
-      return uuid.UUID(bytes=pn_data_get_uuid(self._data))
-    else:
-      return None
-
-  def get_binary(self):
-    """
-    If the current node is binary, returns its value, returns ""
-    otherwise.
-    """
-    return pn_data_get_binary(self._data)
-
-  def get_string(self):
-    """
-    If the current node is a string, returns its value, returns ""
-    otherwise.
-    """
-    return pn_data_get_string(self._data).decode("utf8")
-
-  def get_symbol(self):
-    """
-    If the current node is a symbol, returns its value, returns ""
-    otherwise.
-    """
-    return symbol(pn_data_get_symbol(self._data))
-
-  def copy(self, src):
-    self._check(pn_data_copy(self._data, src._data))
-
-  def format(self):
-    sz = 16
-    while True:
-      err, result = pn_data_format(self._data, sz)
-      if err == PN_OVERFLOW:
-        sz *= 2
-        continue
-      else:
-        self._check(err)
-        return result
-
-  def dump(self):
-    pn_data_dump(self._data)
-
-  def put_dict(self, d):
-    self.put_map()
-    self.enter()
-    try:
-      for k, v in d.items():
-        self.put_object(k)
-        self.put_object(v)
-    finally:
-      self.exit()
-
-  def get_dict(self):
-    if self.enter():
-      try:
-        result = {}
-        while self.next():
-          k = self.get_object()
-          if self.next():
-            v = self.get_object()
-          else:
-            v = None
-          result[k] = v
-      finally:
-        self.exit()
-      return result
-
-  def put_sequence(self, s):
-    self.put_list()
-    self.enter()
-    try:
-      for o in s:
-        self.put_object(o)
-    finally:
-      self.exit()
-
-  def get_sequence(self):
-    if self.enter():
-      try:
-        result = []
-        while self.next():
-          result.append(self.get_object())
-      finally:
-        self.exit()
-      return result
-
-  def get_py_described(self):
-    if self.enter():
-      try:
-        self.next()
-        descriptor = self.get_object()
-        self.next()
-        value = self.get_object()
-      finally:
-        self.exit()
-      return Described(descriptor, value)
-
-  def put_py_described(self, d):
-    self.put_described()
-    self.enter()
-    try:
-      self.put_object(d.descriptor)
-      self.put_object(d.value)
-    finally:
-      self.exit()
-
-  def get_py_array(self):
-    """
-    If the current node is an array, return an Array object
-    representing the array and its contents. Otherwise return None.
-    This is a convenience wrapper around get_array, enter, etc.
-    """
-
-    count, described, type = self.get_array()
-    if type is None: return None
-    if self.enter():
-      try:
-        if described:
-          self.next()
-          descriptor = self.get_object()
-        else:
-          descriptor = UNDESCRIBED
-        elements = []
-        while self.next():
-          elements.append(self.get_object())
-      finally:
-        self.exit()
-      return Array(descriptor, type, *elements)
-
-  def put_py_array(self, a):
-    described = a.descriptor != UNDESCRIBED
-    self.put_array(described, a.type)
-    self.enter()
-    try:
-      if described:
-        self.put_object(a.descriptor)
-      for e in a.elements:
-        self.put_object(e)
-    finally:
-      self.exit()
-
-  put_mappings = {
-    None.__class__: lambda s, _: s.put_null(),
-    bool: put_bool,
-    dict: put_dict,
-    list: put_sequence,
-    tuple: put_sequence,
-    unicode: put_string,
-    bytes: put_binary,
-    symbol: put_symbol,
-    int: put_long,
-    char: put_char,
-    long: put_long,
-    ulong: put_ulong,
-    timestamp: put_timestamp,
-    float: put_double,
-    uuid.UUID: put_uuid,
-    Described: put_py_described,
-    Array: put_py_array
-    }
-  get_mappings = {
-    NULL: lambda s: None,
-    BOOL: get_bool,
-    BYTE: get_byte,
-    UBYTE: get_ubyte,
-    SHORT: get_short,
-    USHORT: get_ushort,
-    INT: get_int,
-    UINT: get_uint,
-    CHAR: get_char,
-    LONG: get_long,
-    ULONG: get_ulong,
-    TIMESTAMP: get_timestamp,
-    FLOAT: get_float,
-    DOUBLE: get_double,
-    DECIMAL32: get_decimal32,
-    DECIMAL64: get_decimal64,
-    DECIMAL128: get_decimal128,
-    UUID: get_uuid,
-    BINARY: get_binary,
-    STRING: get_string,
-    SYMBOL: get_symbol,
-    DESCRIBED: get_py_described,
-    ARRAY: get_py_array,
-    LIST: get_sequence,
-    MAP: get_dict
-    }
-
-
-  def put_object(self, obj):
-    putter = self.put_mappings[obj.__class__]
-    putter(self, obj)
-
-  def get_object(self):
-    type = self.type()
-    if type is None: return None
-    getter = self.get_mappings.get(type)
-    if getter:
-      return getter(self)
-    else:
-      return UnmappedType(str(type))
-
-class ConnectionException(ProtonException):
-  pass
-
-class Endpoint(object):
-
-  LOCAL_UNINIT = PN_LOCAL_UNINIT
-  REMOTE_UNINIT = PN_REMOTE_UNINIT
-  LOCAL_ACTIVE = PN_LOCAL_ACTIVE
-  REMOTE_ACTIVE = PN_REMOTE_ACTIVE
-  LOCAL_CLOSED = PN_LOCAL_CLOSED
-  REMOTE_CLOSED  = PN_REMOTE_CLOSED
-
-  def __init__(self):
-    self.condition = None
-    self._release_invoked = False
-
-  def _release(self):
-    """Release the underlying C Engine resource."""
-    if not self._release_invoked:
-      for c in self._children:
-        c._release()
-      self._free_resource()
-      self.connection._releasing(self)
-      self._release_invoked = True
-
-  def _update_cond(self):
-    obj2cond(self.condition, self._get_cond_impl())
-
-  @property
-  def remote_condition(self):
-    return cond2obj(self._get_remote_cond_impl())
-
-  # the following must be provided by subclasses
-  def _get_cond_impl(self):
-      assert False, "Subclass must override this!"
-
-  def _get_remote_cond_impl(self):
-      assert False, "Subclass must override this!"
-
-class Condition:
-
-  def __init__(self, name, description=None, info=None):
-    self.name = name
-    self.description = description
-    self.info = info
-
-  def __repr__(self):
-    return "Condition(%s)" % ", ".join([repr(x) for x in
-                                        (self.name, self.description, self.info)
-                                        if x])
-
-  def __eq__(self, o):
-    if not isinstance(o, Condition): return False
-    return self.name == o.name and \
-        self.description == o.description and \
-        self.info == o.info
-
-def obj2cond(obj, cond):
-  pn_condition_clear(cond)
-  if obj:
-    pn_condition_set_name(cond, str(obj.name))
-    pn_condition_set_description(cond, obj.description)
-    info = Data(pn_condition_info(cond))
-    if obj.info:
-      info.put_object(obj.info)
-
-def cond2obj(cond):
-  if pn_condition_is_set(cond):
-    return Condition(pn_condition_get_name(cond),
-                     pn_condition_get_description(cond),
-                     dat2obj(pn_condition_info(cond)))
-  else:
-    return None
-
-def dat2obj(dimpl):
-  if dimpl:
-    d = Data(dimpl)
-    d.rewind()
-    d.next()
-    obj = d.get_object()
-    d.rewind()
-    return obj
-
-def obj2dat(obj, dimpl):
-  if obj is not None:
-    d = Data(dimpl)
-    d.put_object(obj)
-
-def secs2millis(secs):
-  return long(secs*1000)
-
-def millis2secs(millis):
-  return float(millis)/1000.0
-
-class Connection(Endpoint):
-
-  @staticmethod
-  def _wrap_connection(c_conn):
-    """Maintain only a single instance of this class for each Connection
-    object that exists in the the C Engine.  This is done by storing a (weak)
-    reference to the python instance in the context field of the C object.
-    """
-    if not c_conn: return None
-    py_conn = pn_void2py(pn_connection_get_context(c_conn))
-    if py_conn: return py_conn
-    wrapper = Connection(_conn=c_conn)
-    return wrapper
-
-  def __init__(self, _conn=None):
-    Endpoint.__init__(self)
-    if _conn:
-      self._conn = _conn
-    else:
-      self._conn = pn_connection()
-    pn_connection_set_context(self._conn, pn_py2void(self))
-    self.offered_capabilities = None
-    self.desired_capabilities = None
-    self.properties = None
-    self._sessions = set()
-
-  def __del__(self):
-    if hasattr(self, "_conn") and self._conn:
-      self._release()
-
-  def free(self):
-    self._release()
-
-  @property
-  def _children(self):
-    return self._sessions
-
-  @property
-  def connection(self):
-    return self
-
-  def _free_resource(self):
-    pn_connection_free(self._conn)
-
-  def _released(self):
-    self._conn = None
-
-  def _releasing(self, child):
-    coll = getattr(self, "_collector", None)
-    if coll: coll = coll()
-    if coll:
-      coll._contexts.add(child)
-    else:
-      child._released()
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, ConnectionException)
-      raise exc("[%s]: %s" % (err, pn_connection_error(self._conn)))
-    else:
-      return err
-
-  def _get_cond_impl(self):
-    return pn_connection_condition(self._conn)
-
-  def _get_remote_cond_impl(self):
-    return pn_connection_remote_condition(self._conn)
-
-  def collect(self, collector):
-    if collector is None:
-      pn_connection_collect(self._conn, None)
-    else:
-      pn_connection_collect(self._conn, collector._impl)
-    self._collector = weakref.ref(collector)
-
-  def _get_container(self):
-    return pn_connection_get_container(self._conn)
-  def _set_container(self, name):
-    return pn_connection_set_container(self._conn, name)
-
-  container = property(_get_container, _set_container)
-
-  def _get_hostname(self):
-    return pn_connection_get_hostname(self._conn)
-  def _set_hostname(self, name):
-    return pn_connection_set_hostname(self._conn, name)
-
-  hostname = property(_get_hostname, _set_hostname)
-
-  @property
-  def remote_container(self):
-    return pn_connection_remote_container(self._conn)
-
-  @property
-  def remote_hostname(self):
-    return pn_connection_remote_hostname(self._conn)
-
-  @property
-  def remote_offered_capabilities(self):
-    return dat2obj(pn_connection_remote_offered_capabilities(self._conn))
-
-  @property
-  def remote_desired_capabilities(self):
-    return dat2obj(pn_connection_remote_desired_capabilities(self._conn))
-
-  @property
-  def remote_properties(self):
-    return dat2obj(pn_connection_remote_properties(self._conn))
-
-  def open(self):
-    obj2dat(self.offered_capabilities,
-            pn_connection_offered_capabilities(self._conn))
-    obj2dat(self.desired_capabilities,
-            pn_connection_desired_capabilities(self._conn))
-    obj2dat(self.properties, pn_connection_properties(self._conn))
-    pn_connection_open(self._conn)
-
-  def close(self):
-    self._update_cond()
-    pn_connection_close(self._conn)
-
-  @property
-  def state(self):
-    return pn_connection_state(self._conn)
-
-  def session(self):
-    return Session._wrap_session(pn_session(self._conn))
-
-  def session_head(self, mask):
-    return Session._wrap_session(pn_session_head(self._conn, mask))
-
-  def link_head(self, mask):
-    return Link._wrap_link(pn_link_head(self._conn, mask))
-
-  @property
-  def work_head(self):
-    return Delivery._wrap_delivery(pn_work_head(self._conn))
-
-  @property
-  def error(self):
-    return pn_error_code(pn_connection_error(self._conn))
-
-class SessionException(ProtonException):
-  pass
-
-class Session(Endpoint):
-
-  @staticmethod
-  def _wrap_session(c_ssn):
-    """Maintain only a single instance of this class for each Session object that
-    exists in the C Engine.
-    """
-    if c_ssn is None: return None
-    py_ssn = pn_void2py(pn_session_get_context(c_ssn))
-    if py_ssn: return py_ssn
-    wrapper = Session(c_ssn)
-    return wrapper
-
-  def __init__(self, ssn):
-    Endpoint.__init__(self)
-    self._ssn = ssn
-    pn_session_set_context(self._ssn, pn_py2void(self))
-    self._links = set()
-    self.connection._sessions.add(self)
-
-  @property
-  def _children(self):
-    return self._links
-
-  def _free_resource(self):
-    pn_session_free(self._ssn)
-
-  def _released(self):
-    self._ssn = None
-
-  def free(self):
-    """Release the Session, freeing its resources.
-
-    Call this when you no longer need the session.  This will allow the
-    session's resources to be reclaimed.  Once called, you should no longer
-    reference the session.
-
-    """
-    self.connection._sessions.remove(self)
-    self._release()
-
-  def _get_cond_impl(self):
-    return pn_session_condition(self._ssn)
-
-  def _get_remote_cond_impl(self):
-    return pn_session_remote_condition(self._ssn)
-
-  def _get_incoming_capacity(self):
-    return pn_session_get_incoming_capacity(self._ssn)
-
-  def _set_incoming_capacity(self, capacity):
-    pn_session_set_incoming_capacity(self._ssn, capacity)
-
-  incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity)
-
-  @property
-  def outgoing_bytes(self):
-    return pn_session_outgoing_bytes(self._ssn)
-
-  @property
-  def incoming_bytes(self):
-    return pn_session_incoming_bytes(self._ssn)
-
-  def open(self):
-    pn_session_open(self._ssn)
-
-  def close(self):
-    self._update_cond()
-    pn_session_close(self._ssn)
-
-  def next(self, mask):
-    return Session._wrap_session(pn_session_next(self._ssn, mask))
-
-  @property
-  def state(self):
-    return pn_session_state(self._ssn)
-
-  @property
-  def connection(self):
-    return Connection._wrap_connection(pn_session_connection(self._ssn))
-
-  def sender(self, name):
-    return Link._wrap_link(pn_sender(self._ssn, name))
-
-  def receiver(self, name):
-    return Link._wrap_link(pn_receiver(self._ssn, name))
-
-class LinkException(ProtonException):
-  pass
-
-class Link(Endpoint):
-
-  SND_UNSETTLED = PN_SND_UNSETTLED
-  SND_SETTLED = PN_SND_SETTLED
-  SND_MIXED = PN_SND_MIXED
-
-  RCV_FIRST = PN_RCV_FIRST
-  RCV_SECOND = PN_RCV_SECOND
-
-  @staticmethod
-  def _wrap_link(c_link):
-    """Maintain only a single instance of this class for each Session object that
-    exists in the C Engine.
-    """
-    if c_link is None: return None
-    py_link = pn_void2py(pn_link_get_context(c_link))
-    if py_link: return py_link
-    if pn_link_is_sender(c_link):
-      wrapper = Sender(c_link)
-    else:
-      wrapper = Receiver(c_link)
-    return wrapper
-
-  def __init__(self, c_link):
-    Endpoint.__init__(self)
-    self._link = c_link
-    pn_link_set_context(self._link, pn_py2void(self))
-    self._deliveries = set()
-    self.session._links.add(self)
-
-  @property
-  def _children(self):
-    return self._deliveries
-
-  def _free_resource(self):
-    pn_link_free(self._link)
-
-  def _released(self):
-    self._link = None
-
-  def free(self):
-    """Release the Link, freeing its resources"""
-    self.session._links.remove(self)
-    self._release()
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, LinkException)
-      raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
-    else:
-      return err
-
-  def _get_cond_impl(self):
-    return pn_link_condition(self._link)
-
-  def _get_remote_cond_impl(self):
-    return pn_link_remote_condition(self._link)
-
-  def open(self):
-    pn_link_open(self._link)
-
-  def close(self):
-    self._update_cond()
-    pn_link_close(self._link)
-
-  @property
-  def state(self):
-    return pn_link_state(self._link)
-
-  @property
-  def source(self):
-    return Terminus(pn_link_source(self._link))
-
-  @property
-  def target(self):
-    return Terminus(pn_link_target(self._link))
-
-  @property
-  def remote_source(self):
-    return Terminus(pn_link_remote_source(self._link))
-  @property
-  def remote_target(self):
-    return Terminus(pn_link_remote_target(self._link))
-
-  @property
-  def session(self):
-    return Session._wrap_session(pn_link_session(self._link))
-
-  @property
-  def connection(self):
-    return self.session.connection
-
-  def delivery(self, tag):
-    return Delivery._wrap_delivery(pn_delivery(self._link, tag))
-
-  @property
-  def current(self):
-    return Delivery._wrap_delivery(pn_link_current(self._link))
-
-  def advance(self):
-    return pn_link_advance(self._link)
-
-  @property
-  def unsettled(self):
-    return pn_link_unsettled(self._link)
-
-  @property
-  def credit(self):
-    return pn_link_credit(self._link)
-
-  @property
-  def available(self):
-    return pn_link_available(self._link)
-
-  @property
-  def queued(self):
-    return pn_link_queued(self._link)
-
-  def next(self, mask):
-    return Link._wrap_link(pn_link_next(self._link, mask))
-
-  @property
-  def name(self):
-      return pn_link_name(self._link)
-
-  @property
-  def is_sender(self):
-    return pn_link_is_sender(self._link)
-
-  @property
-  def is_receiver(self):
-    return pn_link_is_receiver(self._link)
-
-  @property
-  def remote_snd_settle_mode(self):
-    return pn_link_remote_snd_settle_mode(self._link)
-
-  @property
-  def remote_rcv_settle_mode(self):
-    return pn_link_remote_rcv_settle_mode(self._link)
-
-  def _get_snd_settle_mode(self):
-    return pn_link_snd_settle_mode(self._link)
-  def _set_snd_settle_mode(self, mode):
-    pn_link_set_snd_settle_mode(self._link, mode)
-  snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode)
-
-  def _get_rcv_settle_mode(self):
-    return pn_link_rcv_settle_mode(self._link)
-  def _set_rcv_settle_mode(self, mode):
-    pn_link_set_rcv_settle_mode(self._link, mode)
-  rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode)
-
-  def drained(self):
-    return pn_link_drained(self._link)
-
-  def detach(self):
-    return pn_link_detach(self._link)
-
-class Terminus(object):
-
-  UNSPECIFIED = PN_UNSPECIFIED
-  SOURCE = PN_SOURCE
-  TARGET = PN_TARGET
-  COORDINATOR = PN_COORDINATOR
-
-  NONDURABLE = PN_NONDURABLE
-  CONFIGURATION = PN_CONFIGURATION
-  DELIVERIES = PN_DELIVERIES
-
-  DIST_MODE_UNSPECIFIED = PN_DIST_MODE_UNSPECIFIED
-  DIST_MODE_COPY = PN_DIST_MODE_COPY
-  DIST_MODE_MOVE = PN_DIST_MODE_MOVE
-
-  def __init__(self, impl):
-    self._impl = impl
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, LinkException)
-      raise exc("[%s]" % err)
-    else:
-      return err
-
-  def _get_type(self):
-    return pn_terminus_get_type(self._impl)
-  def _set_type(self, type):
-    self._check(pn_terminus_set_type(self._impl, type))
-  type = property(_get_type, _set_type)
-
-  def _get_address(self):
-    return pn_terminus_get_address(self._impl)
-  def _set_address(self, address):
-    self._check(pn_terminus_set_address(self._impl, address))
-  address = property(_get_address, _set_address)
-
-  def _get_durability(self):
-    return pn_terminus_get_durability(self._impl)
-  def _set_durability(self, seconds):
-    self._check(pn_terminus_set_durability(self._impl, seconds))
-  durability = property(_get_durability, _set_durability)
-
-  def _get_expiry_policy(self):
-    return pn_terminus_get_expiry_policy(self._impl)
-  def _set_expiry_policy(self, seconds):
-    self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
-  expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
-
-  def _get_timeout(self):
-    return pn_terminus_get_timeout(self._impl)
-  def _set_timeout(self, seconds):
-    self._check(pn_terminus_set_timeout(self._impl, seconds))
-  timeout = property(_get_timeout, _set_timeout)
-
-  def _is_dynamic(self):
-    return pn_terminus_is_dynamic(self._impl)
-  def _set_dynamic(self, dynamic):
-    self._check(pn_terminus_set_dynamic(self._impl, dynamic))
-  dynamic = property(_is_dynamic, _set_dynamic)
-
-  def _get_distribution_mode(self):
-    return pn_terminus_get_distribution_mode(self._impl)
-  def _set_distribution_mode(self, mode):
-    self._check(pn_terminus_set_distribution_mode(self._impl, mode))
-  distribution_mode = property(_get_distribution_mode, _set_distribution_mode)
-
-  @property
-  def properties(self):
-    return Data(pn_terminus_properties(self._impl))
-
-  @property
-  def capabilities(self):
-    return Data(pn_terminus_capabilities(self._impl))
-
-  @property
-  def outcomes(self):
-    return Data(pn_terminus_outcomes(self._impl))
-
-  @property
-  def filter(self):
-    return Data(pn_terminus_filter(self._impl))
-
-  def copy(self, src):
-    self._check(pn_terminus_copy(self._impl, src._impl))
-
-class Sender(Link):
-
-  def __init__(self, c_link):
-    super(Sender, self).__init__(c_link)
-
-  def offered(self, n):
-    pn_link_offered(self._link, n)
-
-  def send(self, bytes):
-    return self._check(pn_link_send(self._link, bytes))
-
-class Receiver(Link):
-
-  def __init__(self, c_link):
-    super(Receiver, self).__init__(c_link)
-
-  def flow(self, n):
-    pn_link_flow(self._link, n)
-
-  def recv(self, limit):
-    n, bytes = pn_link_recv(self._link, limit)
-    if n == PN_EOS:
-      return None
-    else:
-      self._check(n)
-      return bytes
-
-  def drain(self, n):
-    pn_link_drain(self._link, n)
-
-  def draining(self):
-    return pn_link_draining(self._link)
-
-class NamedInt(int):
-
-  values = {}
-
-  def __new__(cls, i, name):
-    ni = super(NamedInt, cls).__new__(cls, i)
-    cls.values[i] = ni
-    return ni
-
-  def __init__(self, i, name):
-    self.name = name
-
-  def __repr__(self):
-    return self.name
-
-  def __str__(self):
-    return self.name
-
-  @classmethod
-  def get(cls, i):
-    return cls.values.get(i, i)
-
-class DispositionType(NamedInt):
-  values = {}
-
-class Disposition(object):
-
-  RECEIVED = DispositionType(PN_RECEIVED, "RECEIVED")
-  ACCEPTED = DispositionType(PN_ACCEPTED, "ACCEPTED")
-  REJECTED = DispositionType(PN_REJECTED, "REJECTED")
-  RELEASED = DispositionType(PN_RELEASED, "RELEASED")
-  MODIFIED = DispositionType(PN_MODIFIED, "MODIFIED")
-
-  def __init__(self, impl, local):
-    self._impl = impl
-    self.local = local
-    self._data = None
-    self._condition = None
-    self._annotations = None
-
-  @property
-  def type(self):
-    return DispositionType.get(pn_disposition_type(self._impl))
-
-  def _get_section_number(self):
-    return pn_disposition_get_section_number(self._impl)
-  def _set_section_number(self, n):
-    pn_disposition_set_section_number(self._impl, n)
-  section_number = property(_get_section_number, _set_section_number)
-
-  def _get_section_offset(self):
-    return pn_disposition_get_section_offset(self._impl)
-  def _set_section_offset(self, n):
-    pn_disposition_set_section_offset(self._impl, n)
-  section_offset = property(_get_section_offset, _set_section_offset)
-
-  def _get_failed(self):
-    return pn_disposition_is_failed(self._impl)
-  def _set_failed(self, b):
-    pn_disposition_set_failed(self._impl, b)
-  failed = property(_get_failed, _set_failed)
-
-  def _get_undeliverable(self):
-    return pn_disposition_is_undeliverable(self._impl)
-  def _set_undeliverable(self, b):
-    pn_disposition_set_undeliverable(self._impl, b)
-  undeliverable = property(_get_undeliverable, _set_undeliverable)
-
-  def _get_data(self):
-    if self.local:
-      return self._data
-    else:
-      return dat2obj(pn_disposition_data(self._impl))
-  def _set_data(self, obj):
-    if self.local:
-      self._data = obj
-    else:
-      raise AttributeError("data attribute is read-only")
-  data = property(_get_data, _set_data)
-
-  def _get_annotations(self):
-    if self.local:
-      return self._annotations
-    else:
-      return dat2obj(pn_disposition_annotations(self._impl))
-  def _set_annotations(self, obj):
-    if self.local:
-      self._annotations = obj
-    else:
-      raise AttributeError("annotations attribute is read-only")
-  annotations = property(_get_annotations, _set_annotations)
-
-  def _get_condition(self):
-    if self.local:
-      return self._condition
-    else:
-      return cond2obj(pn_disposition_condition(self._impl))
-  def _set_condition(self, obj):
-    if self.local:
-      self._condition = obj
-    else:
-      raise AttributeError("condition attribute is read-only")
-  condition = property(_get_condition, _set_condition)
-
-class Delivery(object):
-
-  RECEIVED = Disposition.RECEIVED
-  ACCEPTED = Disposition.ACCEPTED
-  REJECTED = Disposition.REJECTED
-  RELEASED = Disposition.RELEASED
-  MODIFIED = Disposition.MODIFIED
-
-  @staticmethod
-  def _wrap_delivery(c_dlv):
-    """Maintain only a single instance of this class for each Delivery object that
-    exists in the C Engine.
-    """
-    if not c_dlv: return None
-    py_dlv = pn_void2py(pn_delivery_get_context(c_dlv))
-    if py_dlv: return py_dlv
-    wrapper = Delivery(c_dlv)
-    return wrapper
-
-  def __init__(self, dlv):
-    self._dlv = dlv
-    pn_delivery_set_context(self._dlv, pn_py2void(self))
-    self.local = Disposition(pn_delivery_local(self._dlv), True)
-    self.remote = Disposition(pn_delivery_remote(self._dlv), False)
-    self.link._deliveries.add(self)
-
-  def __del__(self):
-    self._release()
-
-  def _release(self):
-    """Release the underlying C Engine resource."""
-    if self._dlv:
-      pn_delivery_set_context(self._dlv, pn_py2void(None))
-      pn_delivery_settle(self._dlv)
-      self._dlv = None
-
-  @property
-  def released(self):
-    return self._dlv is None
-
-  @property
-  def tag(self):
-    return pn_delivery_tag(self._dlv)
-
-  @property
-  def writable(self):
-    return pn_delivery_writable(self._dlv)
-
-  @property
-  def readable(self):
-    return pn_delivery_readable(self._dlv)
-
-  @property
-  def updated(self):
-    return pn_delivery_updated(self._dlv)
-
-  def update(self, state):
-    obj2dat(self.local._data, pn_disposition_data(self.local._impl))
-    obj2dat(self.local._annotations, pn_disposition_annotations(self.local._impl))
-    obj2cond(self.local._condition, pn_disposition_condition(self.local._impl))
-    pn_delivery_update(self._dlv, state)
-
-  @property
-  def pending(self):
-    return pn_delivery_pending(self._dlv)
-
-  @property
-  def partial(self):
-    return pn_delivery_partial(self._dlv)
-
-  @property
-  def local_state(self):
-    return DispositionType.get(pn_delivery_local_state(self._dlv))
-
-  @property
-  def remote_state(self):
-    return DispositionType.get(pn_delivery_remote_state(self._dlv))
-
-  @property
-  def settled(self):
-    return pn_delivery_settled(self._dlv)
-
-  def settle(self):
-    """Release the delivery"""
-    self.link._deliveries.remove(self)
-    self._release()
-
-  @property
-  def work_next(self):
-    return Delivery._wrap_delivery(pn_work_next(self._dlv))
-
-  @property
-  def link(self):
-    return Link._wrap_link(pn_delivery_link(self._dlv))
-
-class TransportException(ProtonException):
-  pass
-
-class Transport(object):
-
-  TRACE_OFF = PN_TRACE_OFF
-  TRACE_DRV = PN_TRACE_DRV
-  TRACE_FRM = PN_TRACE_FRM
-  TRACE_RAW = PN_TRACE_RAW
-
-  CLIENT = 1
-  SERVER = 2
-
-  @staticmethod
-  def _wrap_transport(c_trans):
-    if not c_trans: return None
-    wrapper = Transport(_trans=c_trans)
-    return wrapper
-
-  def __init__(self, mode=None, _trans=None):
-    if not mode and not _trans:
-      self._trans = pn_transport()
-    elif not mode:
-      self._shared_trans = True
-      self._trans = _trans
-    elif mode==Transport.CLIENT:
-      self._trans = pn_transport()
-    elif mode==Transport.SERVER:
-      self._trans = pn_transport()
-      pn_transport_set_server(self._trans)
-    else:
-      raise TransportException("Cannot initialise Transport from mode: %s" % str(mode))
-    self._sasl = None
-    self._ssl = None
-
-  def __del__(self):
-    if hasattr(self, "_trans"):
-      if not hasattr(self, "_shared_trans"):
-        pn_transport_free(self._trans)
-        if hasattr(self, "_sasl") and self._sasl:
-            # pn_transport_free deallocs the C sasl associated with the
-            # transport, so erase the reference if a SASL object was used.
-            self._sasl._sasl = None
-            self._sasl = None
-        if hasattr(self, "_ssl") and self._ssl:
-            # ditto the owned c SSL object
-            self._ssl._ssl = None
-            self._ssl = None
-      del self._trans
-
-  def _check(self, err):
-    if err < 0:
-      exc = EXCEPTIONS.get(err, TransportException)
-      raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans))))
-    else:
-      return err
-
-  def bind(self, connection):
-    """Assign a connection to the transport"""
-    self._check(pn_transport_bind(self._trans, connection._conn))
-    # keep python connection from being garbage collected:
-    self._connection = connection
-
-  def unbind(self):
-    """Release the connection"""
-    self._check(pn_transport_unbind(self._trans))
-    self._connection = None
-
-  def trace(self, n):
-    pn_transport_trace(self._trans, n)
-
-  def tick(self, now):
-    """Process any timed events (like heartbeat generation).
-    now = seconds since epoch (float).
-    """
-    return millis2secs(pn_transport_tick(self._trans, secs2millis(now)))
-
-  def capacity(self):
-    c = pn_transport_capacity(self._trans)
-    if c >= PN_EOS:
-      return c
-    else:
-      return self._check(c)
-
-  def push(self, bytes):
-    n = self._check(pn_transport_push(self._trans, bytes))
-    if n != len(bytes):
-      raise OverflowError("unable to process all bytes")
-
-  def close_tail(self):
-    self._check(pn_transport_close_tail(self._trans))
-
-  def pending(self):
-    p = pn_transport_pending(self._trans)
-    if p >= PN_EOS:
-      return p
-    else:
-      return self._check(p)
-
-  def peek(self, size):
-    cd, out = pn_transport_peek(self._trans, size)
-    if cd == PN_EOS:
-      return None
-    else:
-      self._check(cd)
-      return out
-
-  def pop(self, size):
-    pn_transport_pop(self._trans, size)
-
-  def close_head(self):
-    self._check(pn_transport_close_head(self._trans))
-
-  @property
-  def closed(self):
-    return pn_transport_closed(self._trans)
-
-  # AMQP 1.0 max-frame-size
-  def _get_max_frame_size(self):
-    return pn_transport_get_max_frame(self._trans)
-
-  def _set_max_frame_size

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[26/35] qpid-proton git commit: NO-JIRA: More Ruby rdoc cleanup.

Posted by gs...@apache.org.
NO-JIRA: More Ruby rdoc cleanup.

Turn off including the licensing headers repeatedly in the documentation
generated.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/23354652
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/23354652
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/23354652

Branch: refs/heads/examples
Commit: 233546525867119f652d4b3ccc5b58ca64878745
Parents: 6a78d2f
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Fri Nov 21 08:33:50 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Mon Nov 24 08:16:48 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/lib/qpid_proton.rb                |  4 ++--
 proton-c/bindings/ruby/lib/qpid_proton/array.rb          | 10 +++++-----
 proton-c/bindings/ruby/lib/qpid_proton/data.rb           | 10 ++++------
 proton-c/bindings/ruby/lib/qpid_proton/described.rb      |  4 ++--
 .../bindings/ruby/lib/qpid_proton/exception_handling.rb  |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb     |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/filters.rb        |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/hash.rb           |  6 +++---
 proton-c/bindings/ruby/lib/qpid_proton/mapping.rb        |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/message.rb        |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/message_format.rb |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/messenger.rb      |  4 ++--
 proton-c/bindings/ruby/lib/qpid_proton/selectable.rb     |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/strings.rb        |  4 ++--
 proton-c/bindings/ruby/lib/qpid_proton/subscription.rb   |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/tracker.rb        |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb |  8 ++++----
 proton-c/bindings/ruby/lib/qpid_proton/version.rb        | 11 +++++++----
 18 files changed, 67 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton.rb b/proton-c/bindings/ruby/lib/qpid_proton.rb
index 4da4e11..0b7e77c 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,7 +15,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 require "cproton"
 require "date"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/array.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/array.rb b/proton-c/bindings/ruby/lib/qpid_proton/array.rb
index 34e1c67..a4294a3 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/array.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/array.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,16 +15,16 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 #--
 # Patch the Array class to provide methods for adding its contents
 # to a Qpid::Proton::Data instance.
 #++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # Holds the information for an AMQP Array compound type.
     #
@@ -54,7 +54,7 @@ module Qpid
 
 end
 
-class Array
+class Array # :nodoc:
 
   # Used to declare an array as an AMQP array.
   #

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/data.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/data.rb b/proton-c/bindings/ruby/lib/qpid_proton/data.rb
index 1e515c8..b6b3002 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/data.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/data.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,13 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
-
-require 'cproton'
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # +DataError+ is raised when an error occurs while encoding
     # or decoding data.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/described.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/described.rb b/proton-c/bindings/ruby/lib/qpid_proton/described.rb
index adb7f8c..98679c2 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/described.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/described.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,7 +15,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 module Qpid # :nodoc:
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
index 4dce3ef..fd66865 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/exception_handling.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # Provides mixin functionality for dealing with exception conditions.
     #

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb b/proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb
index 094f6fe..e3c3d19 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/exceptions.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     module Error
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/filters.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/filters.rb b/proton-c/bindings/ruby/lib/qpid_proton/filters.rb
index 46c9bf7..370d017 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/filters.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/filters.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     module Filters
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/hash.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/hash.rb b/proton-c/bindings/ruby/lib/qpid_proton/hash.rb
index bd7c1b5..1e19da1 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/hash.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/hash.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,14 +15,14 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 #--
 # Patch the Hash class to provide methods for adding its contents
 # to a Qpid::Proton::Data instance.
 #++
 
-class Hash
+class Hash # :nodoc:
 
   # Places the contents of the hash into the specified data object.
   #

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb b/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
index 836bcd9..b2e4b86 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,7 +15,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 module Qpid # :nodoc:
 
@@ -110,7 +110,7 @@ module Qpid # :nodoc:
                                                            UTFString,
                                                            BinaryString])
 
-    class << STRING
+    class << STRING # :nodoc:
       def put(data, value)
         # if we have a symbol then convert it to a string
         value = value.to_s if value.is_a?(Symbol)
@@ -144,7 +144,7 @@ module Qpid # :nodoc:
     LIST       = Mapping.new(Cproton::PN_LIST, "list", [::Array], "get_array")
     MAP        = Mapping.new(Cproton::PN_MAP, "map", [::Hash], "get_map")
 
-    class << MAP
+    class << MAP # :nodoc:
       def put(data, map)
         data.put_map
         data.enter

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/message.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/message.rb b/proton-c/bindings/ruby/lib/qpid_proton/message.rb
index b7a4fd0..3077ab1 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/message.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/message.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # A Message represents an addressable quantity of data.
     #

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/message_format.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/message_format.rb b/proton-c/bindings/ruby/lib/qpid_proton/message_format.rb
index 120ff5f..62b6f1a 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/message_format.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/message_format.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     class MessageFormat
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index f17205d..5a16c50 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -17,9 +17,9 @@
 # under the License.
 #
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # The +Messenger+ class defines a high level interface for
     # sending and receiving Messages. Every Messenger contains

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
index 34a030f..33554cd 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/selectable.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # Selectable enables accessing the underlying file descriptors
     # for Messenger.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/strings.rb b/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
index d8f5851..44eba02 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/strings.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,7 +15,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
 module Qpid # :nodoc:
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/subscription.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/subscription.rb b/proton-c/bindings/ruby/lib/qpid_proton/subscription.rb
index fbfafea..21d9281 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/subscription.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/subscription.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # A +Subscription+ is an opaque object for working with a +Messenger+'s
     # subscriptions.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/tracker.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/tracker.rb b/proton-c/bindings/ruby/lib/qpid_proton/tracker.rb
index bf99e30..7de271a 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/tracker.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/tracker.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # A +Tracker+ is used to track the disposition of a +Message+.
     #

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb b/proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb
index b74a4c0..81c9ea3 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/tracker_status.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,11 +15,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
     # TrackerStatus contains symbols that represent the status value for a
     # Tracker.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/23354652/proton-c/bindings/ruby/lib/qpid_proton/version.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/version.rb b/proton-c/bindings/ruby/lib/qpid_proton/version.rb
index 006353c..ebc92c5 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/version.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/version.rb
@@ -1,4 +1,4 @@
-#
+#--
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -15,13 +15,16 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#
+#++
 
-module Qpid
+module Qpid # :nodoc:
 
-  module Proton
+  module Proton # :nodoc:
 
+    # The major version for the underlying Proton library.
     VERSION_MAJOR = Cproton::PN_VERSION_MAJOR
+
+    # The minor version for the underlying Proton library.
     VERSION_MINOR = Cproton::PN_VERSION_MINOR
 
   end


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[07/35] qpid-proton git commit: PROTON-743: Provide a means to clear errors in a Ruby Messenger.

Posted by gs...@apache.org.
PROTON-743: Provide a means to clear errors in a Ruby Messenger.

Added the clear_error method to allow clearing out the error state in a
Ruby Messenger object.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/6504db6f
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/6504db6f
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/6504db6f

Branch: refs/heads/examples
Commit: 6504db6fcebc33fe57eef1b5e334b32e4b14055c
Parents: b57f45d
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Mon Nov 17 16:04:40 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Mon Nov 17 16:04:40 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/lib/qpid_proton/messenger.rb |  9 +++++++++
 .../ruby/spec/qpid/proton/messenger_spec.rb         | 16 ++++++++++++++++
 2 files changed, 25 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6504db6f/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
index 3dca86c..2581e2b 100644
--- a/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
+++ b/proton-c/bindings/ruby/lib/qpid_proton/messenger.rb
@@ -179,6 +179,15 @@ module Qpid
         Cproton.pn_error_text(Cproton.pn_messenger_error(@impl))
       end
 
+      # Clears the current error state.
+      #
+      def clear_error
+        error = Cproton.pn_messenger_error(@impl)
+        unless error.nil?
+          Cproton.pn_error_clear(error)
+        end
+      end
+
       # Currently a no-op placeholder.
       # For future compatibility, do not send or recv messages
       # before starting the +Messenger+.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6504db6f/proton-c/bindings/ruby/spec/qpid/proton/messenger_spec.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/spec/qpid/proton/messenger_spec.rb b/proton-c/bindings/ruby/spec/qpid/proton/messenger_spec.rb
index 86050ed..1b888c1 100644
--- a/proton-c/bindings/ruby/spec/qpid/proton/messenger_spec.rb
+++ b/proton-c/bindings/ruby/spec/qpid/proton/messenger_spec.rb
@@ -222,6 +222,22 @@ module Qpid
         @messenger.passive?.should_not be_true
       end
 
+      it "can clear non-existent errors with failing" do
+        expect {
+          @messenger.clear_error
+        }.to_not raise_error
+      end
+
+      it "can clear errors" do
+        begin
+          @messenger.accept # should cause an error
+        rescue; end
+
+        @messenger.error.should_not be_nil
+        @messenger.clear_error
+        @messenger.error.should be_nil
+      end
+
       describe "once started" do
 
         before (:each) do


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[25/35] qpid-proton git commit: restructured cmake file to support multiple sources

Posted by gs...@apache.org.
restructured cmake file to support multiple sources


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/19130401
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/19130401
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/19130401

Branch: refs/heads/examples
Commit: 1913040155414f7fb037a0584a9dafa4a14533f0
Parents: f5cbab5
Author: Rafael Schloming <rh...@alum.mit.edu>
Authored: Sat Nov 22 05:25:57 2014 -0500
Committer: Rafael Schloming <rh...@alum.mit.edu>
Committed: Sat Nov 22 06:03:01 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/python/CMakeLists.txt | 32 ++++++++++++++++------------
 1 file changed, 18 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/19130401/proton-c/bindings/python/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/CMakeLists.txt b/proton-c/bindings/python/CMakeLists.txt
index c7eb4aa..6ab1e67 100644
--- a/proton-c/bindings/python/CMakeLists.txt
+++ b/proton-c/bindings/python/CMakeLists.txt
@@ -52,14 +52,23 @@ if (NOT PYTHON_SITEARCH_PACKAGES)
   set (PYTHON_SITEARCH_PACKAGES ${PYTHON_SITEARCH_PACKAGES_DEFAULT})
 endif()
 
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cproton.py
-                              WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cproton.py
-                              WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile proton.py
-                              WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile proton.py
-                              WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
+set (pysrc-generated cproton.py)
+set (pysrc proton.py)
+
+macro (py_compile directory files)
+  foreach (src_file ${files})
+    install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile ${src_file}
+                                  WORKING_DIRECTORY ${directory})")
+    install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile ${src_file}
+                                  WORKING_DIRECTORY ${directory})")
+    list(APPEND PYTHON_ARTIFACTS ${directory}/${src_file}
+      ${directory}/${src_file}c
+      ${directory}/${src_file}o)
+  endforeach (src_file)
+endmacro(py_compile)
+
+py_compile(${CMAKE_CURRENT_BINARY_DIR} ${pysrc-generated})
+py_compile(${CMAKE_CURRENT_SOURCE_DIR} ${pysrc})
 
 find_program(EPYDOC_EXE epydoc)
 mark_as_advanced (EPYDOC_EXE)
@@ -75,12 +84,7 @@ if (EPYDOC_EXE)
            ${OPTIONAL_ARG})
 endif (EPYDOC_EXE)
 
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cproton.py
-              ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyc
-              ${CMAKE_CURRENT_BINARY_DIR}/cproton.pyo
-              ${CMAKE_CURRENT_SOURCE_DIR}/proton.py
-              ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyc
-              ${CMAKE_CURRENT_SOURCE_DIR}/proton.pyo
+install(FILES ${PYTHON_ARTIFACTS}
         DESTINATION ${PYTHON_SITEARCH_PACKAGES}
         COMPONENT Python)
 install(TARGETS ${SWIG_MODULE_cproton_REAL_NAME}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[16/35] qpid-proton git commit: PROTON-749: Fix erroneous windows change due to previous version to changeset.

Posted by gs...@apache.org.
PROTON-749: Fix erroneous windows change due to previous version to changeset.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/0cc91340
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/0cc91340
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/0cc91340

Branch: refs/heads/examples
Commit: 0cc91340dd8fa4701bfcf8ba55691d825a9fa03b
Parents: 0fd34e8
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Nov 20 10:46:32 2014 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Thu Nov 20 10:46:32 2014 -0500

----------------------------------------------------------------------
 proton-c/src/windows/driver.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0cc91340/proton-c/src/windows/driver.c
----------------------------------------------------------------------
diff --git a/proton-c/src/windows/driver.c b/proton-c/src/windows/driver.c
index 013b422..d446aae 100644
--- a/proton-c/src/windows/driver.c
+++ b/proton-c/src/windows/driver.c
@@ -285,7 +285,8 @@ pn_connector_t *pn_listener_accept(pn_listener_t *l)
     pn_connector_t *c = pn_connector_fd(l->driver, sock, NULL);
     snprintf(c->name, PN_NAME_MAX, "%s", name);
     c->listener = l;
-    c->transport = pn_transport_server();
+    c->transport = pn_transport();
+    pn_transport_set_server(c->transport);
     c->sasl = pn_sasl(c->transport);
     return c;
   }
@@ -385,7 +386,7 @@ pn_connector_t *pn_connector(pn_driver_t *driver, const char *host,
 
   pn_socket_t sock = pn_connect(driver->io, host, port);
   pn_connector_t *c = pn_connector_fd(driver, sock, context);
-  c->transport = pn_transport_client();
+  c->transport = pn_transport();
   c->sasl = pn_sasl(c->transport);
   snprintf(c->name, PN_NAME_MAX, "%s:%s", host, port);
   if (driver->trace & (PN_TRACE_FRM | PN_TRACE_RAW | PN_TRACE_DRV))


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org