You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2016/11/02 02:53:21 UTC

[01/50] [abbrv] qpid-proton git commit: NO-JIRA: go config.sh added env vars to Go tests directly.

Repository: qpid-proton
Updated Branches:
  refs/heads/go1 5e6024bbf -> 287eeacaf


NO-JIRA: go config.sh added env vars to Go tests directly.

You can run go tests like this:

    . config.sh
    go test qpid.apache.org/...   # All package tests
    go test qpid.apache.org/proton # proton package tests.


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

Branch: refs/heads/go1
Commit: 158ad9105b2c6adcd9415c863d6f0c29cb0ec5d4
Parents: 4bb2681
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Sep 7 15:04:05 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 20 17:39:15 2016 -0400

----------------------------------------------------------------------
 config.sh.in | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/158ad910/config.sh.in
----------------------------------------------------------------------
diff --git a/config.sh.in b/config.sh.in
index 7e58883..4902b61 100755
--- a/config.sh.in
+++ b/config.sh.in
@@ -81,3 +81,6 @@ fi
 if [[ -x "$(type -p saslpasswd2)" ]] ; then
     export SASLPASSWD=$(type -p saslpasswd2)
 fi
+
+# Location of interop test files.
+export PN_INTEROP_DIR=$PROTON_HOME/tests/interop


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


[31/50] [abbrv] qpid-proton git commit: PROTON-1319: C++ SunStudo: Move internal header files of cpp bindings

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/proton_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_bits.hpp b/proton-c/bindings/cpp/src/proton_bits.hpp
deleted file mode 100644
index 97d4bee..0000000
--- a/proton-c/bindings/cpp/src/proton_bits.hpp
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef PROTON_BITS_HPP
-#define PROTON_BITS_HPP
-/*
- * 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/link.h>
-#include <proton/session.h>
-
-#include <string>
-#include <iosfwd>
-
-/**@file
- *
- * Assorted internal proton utilities.
- */
-
-struct pn_error_t;
-
-struct pn_data_t;
-struct pn_transport_t;
-struct pn_sasl_t;
-struct pn_ssl_t;
-struct pn_connection_t;
-struct pn_session_t;
-struct pn_link_t;
-struct pn_delivery_t;
-struct pn_condition_t;
-struct pn_acceptor_t;
-struct pn_terminus_t;
-struct pn_reactor_t;
-struct pn_record_t;
-
-namespace proton {
-
-namespace internal { class data; }
-class transport;
-class sasl;
-class ssl;
-class connection;
-class session;
-class link;
-class sender;
-class receiver;
-class transfer;
-class tracker;
-class delivery;
-class error_condition;
-class acceptor;
-class terminus;
-class source;
-class target;
-class reactor;
-
-std::string error_str(long code);
-
-/** Print the error string from pn_error_t, or from code if pn_error_t has no error. */
-std::string error_str(pn_error_t*, long code=0);
-
-/** Make a void* inspectable via operator <<. */
-struct inspectable { void* value; inspectable(void* o) : value(o) {} };
-
-/** Stream a proton object via pn_inspect. */
-std::ostream& operator<<(std::ostream& o, const inspectable& object);
-
-void set_error_condition(const error_condition&, pn_condition_t*);
-
-/// Convert a const char* to std::string, convert NULL to the empty string.
-inline std::string str(const char* s) { return s ? s : std::string(); }
-
-namespace internal {
-
-// These traits relate the wrapped and wrapper classes for the templated factories below
-template <class T> struct wrapped {};
-template <> struct wrapped<internal::data> { typedef pn_data_t type; };
-template <> struct wrapped<transport> { typedef pn_transport_t type; };
-template <> struct wrapped<sasl> { typedef pn_sasl_t type; };
-template <> struct wrapped<ssl> { typedef pn_ssl_t type; };
-template <> struct wrapped<connection> { typedef pn_connection_t type; };
-template <> struct wrapped<session> { typedef pn_session_t type; };
-template <> struct wrapped<link> { typedef pn_link_t type; };
-template <> struct wrapped<sender> { typedef pn_link_t type; };
-template <> struct wrapped<receiver> { typedef pn_link_t type; };
-template <> struct wrapped<transfer> { typedef pn_delivery_t type; };
-template <> struct wrapped<tracker> { typedef pn_delivery_t type; };
-template <> struct wrapped<delivery> { typedef pn_delivery_t type; };
-template <> struct wrapped<error_condition> { typedef pn_condition_t type; };
-template <> struct wrapped<acceptor> { typedef pn_acceptor_t type; }; // TODO aconway 2016-05-13: reactor only
-template <> struct wrapped<terminus> { typedef pn_terminus_t type; };
-template <> struct wrapped<source> { typedef pn_terminus_t type; };
-template <> struct wrapped<target> { typedef pn_terminus_t type; };
-template <> struct wrapped<reactor> { typedef pn_reactor_t type; };
-
-template <class T> struct wrapper {};
-template <> struct wrapper<pn_data_t> { typedef internal::data type; };
-template <> struct wrapper<pn_transport_t> { typedef transport type; };
-template <> struct wrapper<pn_sasl_t> { typedef sasl type; };
-template <> struct wrapper<pn_ssl_t> { typedef ssl type; };
-template <> struct wrapper<pn_connection_t> { typedef connection type; };
-template <> struct wrapper<pn_session_t> { typedef session type; };
-template <> struct wrapper<pn_link_t> { typedef link type; };
-template <> struct wrapper<pn_delivery_t> { typedef transfer type; };
-template <> struct wrapper<pn_condition_t> { typedef error_condition type; };
-template <> struct wrapper<pn_acceptor_t> { typedef acceptor type; };
-template <> struct wrapper<pn_terminus_t> { typedef terminus type; };
-template <> struct wrapper<pn_reactor_t> { typedef reactor type; };
-
-// Factory for wrapper types
-template <class T>
-class factory {
-public:
-    static T wrap(typename wrapped<T>::type* t) { return t; }
-    static typename wrapped<T>::type* unwrap(T t) { return t.pn_object(); }
-};
-
-// Get attachments for various proton-c types
-template <class T>
-inline pn_record_t* get_attachments(T*);
-
-template <> inline pn_record_t* get_attachments(pn_session_t* s) { return pn_session_attachments(s); }
-template <> inline pn_record_t* get_attachments(pn_link_t* l) { return pn_link_attachments(l); }
-}
-
-template <class T>
-typename internal::wrapper<T>::type make_wrapper(T* t) { return internal::factory<typename internal::wrapper<T>::type>::wrap(t); }
-
-template <class U>
-U make_wrapper(typename internal::wrapped<U>::type* t) { return internal::factory<U>::wrap(t); }
-
-template <class T>
-typename internal::wrapped<T>::type* unwrap(T t) {return internal::factory<T>::unwrap(t); }
-
-}
-
-#endif // PROTON_BITS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/proton_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_event.hpp b/proton-c/bindings/cpp/src/proton_event.hpp
deleted file mode 100644
index 9b33701..0000000
--- a/proton-c/bindings/cpp/src/proton_event.hpp
+++ /dev/null
@@ -1,293 +0,0 @@
-#ifndef PROTON_CPP_PROTONEVENT_H
-#define PROTON_CPP_PROTONEVENT_H
-
-/*
- *
- * 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/error.hpp"
-
-#include <proton/event.h>
-
-namespace proton {
-
-class proton_handler;
-class container;
-
-/** Event information for a proton::proton_handler */
-class proton_event
-{
-  public:
-    /// The type of an event
-    enum event_type {
-    ///@name Event types
-    ///@{
-
-      /**
-      * Defined as a programming convenience. No event of this type will
-      * ever be generated.
-      */
-      EVENT_NONE=PN_EVENT_NONE,
-
-      /**
-      * A reactor has been started. Events of this type point to the reactor.
-      */
-      REACTOR_INIT=PN_REACTOR_INIT,
-
-      /**
-      * A reactor has no more events to process. Events of this type
-      * point to the reactor.
-      */
-      REACTOR_QUIESCED=PN_REACTOR_QUIESCED,
-
-      /**
-      * A reactor has been stopped. Events of this type point to the reactor.
-      */
-      REACTOR_FINAL=PN_REACTOR_FINAL,
-
-      /**
-      * A timer event has occurred.
-      */
-      TIMER_TASK=PN_TIMER_TASK,
-
-      /**
-      * The connection has been created. This is the first event that
-      * will ever be issued for a connection. Events of this type point
-      * to the relevant connection.
-      */
-      CONNECTION_INIT=PN_CONNECTION_INIT,
-
-      /**
-      * The connection has been bound to a transport. This event is
-      * issued when the transport::bind() is called.
-      */
-      CONNECTION_BOUND=PN_CONNECTION_BOUND,
-
-      /**
-      * The connection has been unbound from its transport. This event is
-      * issued when transport::unbind() is called.
-      */
-      CONNECTION_UNBOUND=PN_CONNECTION_UNBOUND,
-
-      /**
-      * The local connection endpoint has been closed. Events of this
-      * type point to the relevant connection.
-      */
-      CONNECTION_LOCAL_OPEN=PN_CONNECTION_LOCAL_OPEN,
-
-      /**
-      * The remote endpoint has opened the connection. Events of this
-      * type point to the relevant connection.
-      */
-      CONNECTION_REMOTE_OPEN=PN_CONNECTION_REMOTE_OPEN,
-
-      /**
-      * The local connection endpoint has been closed. Events of this
-      * type point to the relevant connection.
-      */
-      CONNECTION_LOCAL_CLOSE=PN_CONNECTION_LOCAL_CLOSE,
-
-      /**
-      *  The remote endpoint has closed the connection. Events of this
-      *  type point to the relevant connection.
-      */
-      CONNECTION_REMOTE_CLOSE=PN_CONNECTION_REMOTE_CLOSE,
-
-      /**
-      * The connection has been freed and any outstanding processing has
-      * been completed. This is the final event that will ever be issued
-      * for a connection.
-      */
-      CONNECTION_FINAL=PN_CONNECTION_FINAL,
-
-      /**
-      * The session has been created. This is the first event that will
-      * ever be issued for a session.
-      */
-      SESSION_INIT=PN_SESSION_INIT,
-
-      /**
-      * The local session endpoint has been opened. Events of this type
-      * point to the relevant session.
-      */
-      SESSION_LOCAL_OPEN=PN_SESSION_LOCAL_OPEN,
-
-      /**
-      * The remote endpoint has opened the session. Events of this type
-      * point to the relevant session.
-      */
-      SESSION_REMOTE_OPEN=PN_SESSION_REMOTE_OPEN,
-
-      /**
-      * The local session endpoint has been closed. Events of this type
-      * point ot the relevant session.
-      */
-      SESSION_LOCAL_CLOSE=PN_SESSION_LOCAL_CLOSE,
-
-      /**
-      * The remote endpoint has closed the session. Events of this type
-      * point to the relevant session.
-      */
-      SESSION_REMOTE_CLOSE=PN_SESSION_REMOTE_CLOSE,
-
-      /**
-      * The session has been freed and any outstanding processing has
-      * been completed. This is the final event that will ever be issued
-      * for a session.
-      */
-      SESSION_FINAL=PN_SESSION_FINAL,
-
-      /**
-      * The link has been created. This is the first event that will ever
-      * be issued for a link.
-      */
-      LINK_INIT=PN_LINK_INIT,
-
-      /**
-      * The local link endpoint has been opened. Events of this type
-      * point ot the relevant link.
-      */
-      LINK_LOCAL_OPEN=PN_LINK_LOCAL_OPEN,
-
-      /**
-      * The remote endpoint has opened the link. Events of this type
-      * point to the relevant link.
-      */
-      LINK_REMOTE_OPEN=PN_LINK_REMOTE_OPEN,
-
-      /**
-      * The local link endpoint has been closed. Events of this type
-      * point ot the relevant link.
-      */
-      LINK_LOCAL_CLOSE=PN_LINK_LOCAL_CLOSE,
-
-      /**
-      * The remote endpoint has closed the link. Events of this type
-      * point to the relevant link.
-      */
-      LINK_REMOTE_CLOSE=PN_LINK_REMOTE_CLOSE,
-
-      /**
-      * The local link endpoint has been detached. Events of this type
-      * point to the relevant link.
-      */
-      LINK_LOCAL_DETACH=PN_LINK_LOCAL_DETACH,
-
-      /**
-      * The remote endpoint has detached the link. Events of this type
-      * point to the relevant link.
-      */
-      LINK_REMOTE_DETACH=PN_LINK_REMOTE_DETACH,
-
-      /**
-      * The flow control state for a link has changed. Events of this
-      * type point to the relevant link.
-      */
-      LINK_FLOW=PN_LINK_FLOW,
-
-      /**
-      * The link has been freed and any outstanding processing has been
-      * completed. This is the final event that will ever be issued for a
-      * link. Events of this type point to the relevant link.
-      */
-      LINK_FINAL=PN_LINK_FINAL,
-
-      /**
-      * A delivery has been created or updated. Events of this type point
-      * to the relevant delivery.
-      */
-      DELIVERY=PN_DELIVERY,
-
-      /**
-      * The transport has new data to read and/or write. Events of this
-      * type point to the relevant transport.
-      */
-      TRANSPORT=PN_TRANSPORT,
-
-      /**
-      * The transport has authenticated, if this is received by a server
-      * the associated transport has authenticated an incoming connection
-      * and transport::user() can be used to obtain the authenticated
-      * user.
-      */
-      TRANSPORT_AUTHENTICATED=PN_TRANSPORT_AUTHENTICATED,
-
-      /**
-      * Indicates that a transport error has occurred. Use
-      * transport::condition() to access the details of the error
-      * from the associated transport.
-      */
-      TRANSPORT_ERROR=PN_TRANSPORT_ERROR,
-
-      /**
-      * Indicates that the head of the transport has been closed. This
-      * means the transport will never produce more bytes for output to
-      * the network. Events of this type point to the relevant transport.
-      */
-      TRANSPORT_HEAD_CLOSED=PN_TRANSPORT_HEAD_CLOSED,
-
-      /**
-      * Indicates that the tail of the transport has been closed. This
-      * means the transport will never be able to process more bytes from
-      * the network. Events of this type point to the relevant transport.
-      */
-      TRANSPORT_TAIL_CLOSED=PN_TRANSPORT_TAIL_CLOSED,
-
-      /**
-      * Indicates that the both the head and tail of the transport are
-      * closed. Events of this type point to the relevant transport.
-      */
-      TRANSPORT_CLOSED=PN_TRANSPORT_CLOSED,
-
-      SELECTABLE_INIT=PN_SELECTABLE_INIT,
-      SELECTABLE_UPDATED=PN_SELECTABLE_UPDATED,
-      SELECTABLE_READABLE=PN_SELECTABLE_READABLE,
-      SELECTABLE_WRITABLE=PN_SELECTABLE_WRITABLE,
-      SELECTABLE_ERROR=PN_SELECTABLE_ERROR,
-      SELECTABLE_EXPIRED=PN_SELECTABLE_EXPIRED,
-      SELECTABLE_FINAL=PN_SELECTABLE_FINAL
-    };
-    ///@}
-
-    proton_event(pn_event_t *ce, class container* cont) :
-      pn_event_(ce),
-      container_(cont)
-    {}
-
-    pn_event_t* pn_event() const { return pn_event_; }
-    class container& container() const {
-        if (!container_)
-            throw proton::error("event does not have a container");
-        return *container_;
-    }
-
-    /// Get type of event
-    event_type type() const { return event_type(pn_event_type(pn_event_)); }
-
-    void dispatch(proton_handler& h);
-
-  private:
-    pn_event_t *pn_event_;
-    class container* container_;
-};
-
-}
-
-#endif  /*!PROTON_CPP_PROTONEVENT_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/proton_handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_handler.hpp b/proton-c/bindings/cpp/src/proton_handler.hpp
deleted file mode 100644
index 9941396..0000000
--- a/proton-c/bindings/cpp/src/proton_handler.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef PROTON_CPP_PROTONHANDLER_H
-#define PROTON_CPP_PROTONHANDLER_H
-
-/*
- *
- * 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/internal/object.hpp"
-
-#include <vector>
-
-struct pn_handler_t;
-
-namespace proton {
-
-class event;
-class proton_event;
-
-/// Handler base class, subclass and over-ride event handling member functions.
-/// @see proton::proton_event for meaning of events.
-class proton_handler
-{
-  public:
-    proton_handler();
-    virtual ~proton_handler();
-
-    ///@name Over-ride these member functions to handle events
-    ///@{
-    virtual void on_reactor_init(proton_event &e);
-    virtual void on_reactor_quiesced(proton_event &e);
-    virtual void on_reactor_final(proton_event &e);
-    virtual void on_timer_task(proton_event &e);
-    virtual void on_connection_init(proton_event &e);
-    virtual void on_connection_bound(proton_event &e);
-    virtual void on_connection_unbound(proton_event &e);
-    virtual void on_connection_local_open(proton_event &e);
-    virtual void on_connection_local_close(proton_event &e);
-    virtual void on_connection_remote_open(proton_event &e);
-    virtual void on_connection_remote_close(proton_event &e);
-    virtual void on_connection_final(proton_event &e);
-    virtual void on_session_init(proton_event &e);
-    virtual void on_session_local_open(proton_event &e);
-    virtual void on_session_local_close(proton_event &e);
-    virtual void on_session_remote_open(proton_event &e);
-    virtual void on_session_remote_close(proton_event &e);
-    virtual void on_session_final(proton_event &e);
-    virtual void on_link_init(proton_event &e);
-    virtual void on_link_local_open(proton_event &e);
-    virtual void on_link_local_close(proton_event &e);
-    virtual void on_link_local_detach(proton_event &e);
-    virtual void on_link_remote_open(proton_event &e);
-    virtual void on_link_remote_close(proton_event &e);
-    virtual void on_link_remote_detach(proton_event &e);
-    virtual void on_link_flow(proton_event &e);
-    virtual void on_link_final(proton_event &e);
-    virtual void on_delivery(proton_event &e);
-    virtual void on_transport(proton_event &e);
-    virtual void on_transport_error(proton_event &e);
-    virtual void on_transport_head_closed(proton_event &e);
-    virtual void on_transport_tail_closed(proton_event &e);
-    virtual void on_transport_closed(proton_event &e);
-    virtual void on_selectable_init(proton_event &e);
-    virtual void on_selectable_updated(proton_event &e);
-    virtual void on_selectable_readable(proton_event &e);
-    virtual void on_selectable_writable(proton_event &e);
-    virtual void on_selectable_expired(proton_event &e);
-    virtual void on_selectable_error(proton_event &e);
-    virtual void on_selectable_final(proton_event &e);
-    virtual void on_unhandled(proton_event &e);
-    ///@}
-};
-
-}
-
-#endif  /*!PROTON_CPP_PROTONHANDLER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/reactor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/reactor.hpp b/proton-c/bindings/cpp/src/reactor.hpp
deleted file mode 100644
index c7ab915..0000000
--- a/proton-c/bindings/cpp/src/reactor.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef REACTOR_HPP
-#define REACTOR_HPP
-
-/*
- * 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.
- */
-
-/// @cond INTERNAL
-/// XXX remove
-
-#include "proton/internal/object.hpp"
-#include "proton/duration.hpp"
-#include "proton/timestamp.hpp"
-
-struct pn_reactor_t;
-struct pn_handler_t;
-struct pn_io_t;
-
-namespace proton {
-
-class connection;
-class container;
-class acceptor;
-class url;
-class messaging_handler;
-class task;
-
-class reactor : public internal::object<pn_reactor_t> {
-  public:
-    reactor(pn_reactor_t* r = 0) : internal::object<pn_reactor_t>(r) {}
-
-    /** Create a new reactor. */
-    static reactor create();
-
-    /** Open a connection to url and create a receiver with source=url.path() */
-    acceptor listen(const proton::url &);
-
-    /** Run the event loop, return when all connections and acceptors are closed. */
-    void run();
-
-    /** Start the reactor, you must call process() to process events */
-    void start();
-
-    /** Process events, return true if there are more events to process. */
-    bool process();
-
-    /** Stop the reactor, causes run() to return and process() to return false. */
-    void stop();
-
-    /// Identifier for the container
-    std::string id() const;
-
-    /// Get timeout, process() will return if there is no activity within the timeout.
-    duration timeout();
-
-    /// Set timeout, process() will return if there is no activity within the timeout.
-    void timeout(duration timeout);
-
-    timestamp mark();
-    timestamp now();
-
-    task schedule(int, pn_handler_t*);
-
-    class connection connection(pn_handler_t*) const;
-
-    class connection connection_to_host(const std::string &host, const std::string &port, pn_handler_t*) const;
-
-    pn_handler_t* pn_handler() const;
-
-    void pn_handler(pn_handler_t* );
-
-    pn_handler_t* pn_global_handler() const;
-
-    void pn_global_handler(pn_handler_t* );
-
-    pn_io_t* pn_io() const;
-
-    void wakeup();
-    bool quiesced();
-    void yield();
-
-  friend class container_impl;
-  friend class container_context;
-  friend class internal::factory<reactor>;
-};
-
-}
-
-/// @endcond
-
-#endif // REACTOR_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/scalar_test.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/scalar_test.hpp b/proton-c/bindings/cpp/src/scalar_test.hpp
deleted file mode 100644
index b075c98..0000000
--- a/proton-c/bindings/cpp/src/scalar_test.hpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#ifndef SCALAR_TEST_HPP
-#define SCALAR_TEST_HPP
-
-/*
- * 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.
- */
-
-// Template tests used by both scalar_test.cpp and value_test.hpp to test conversion
-// of scalar values via a proton::scalar or a proton::value.
-
-#include "test_bits.hpp"
-
-#include "proton/types.hpp"
-#include "proton/error.hpp"
-
-#include <sstream>
-
-
-namespace test {
-
-using namespace proton;
-
-// Inserting and extracting simple C++ values using same-type get<T> and coerce<T>
-template <class V, class T> void simple_type_test(T x, type_id tid, const std::string& s, T y) {
-    V vx(x);                    // Construct from C++ value
-    ASSERT_EQUAL(tid, vx.type());
-    ASSERT(!vx.empty());
-    ASSERT_EQUAL(x, get<T>(vx));
-    ASSERT_EQUAL(x, coerce<T>(vx));
-
-    V vxa = x;                  // Assign from C++ value
-    ASSERT_EQUAL(tid, vxa.type());
-    ASSERT(!vx.empty());
-    ASSERT_EQUAL(vx, vxa);
-    ASSERT_EQUAL(x, get<T>(vxa));
-    ASSERT_EQUAL(x, coerce<T>(vxa));
-
-    V v2;                       // Default construct
-    ASSERT(v2.type() == NULL_TYPE);
-    ASSERT(v2.empty());
-    v2 = x;                     // Assign from C++ value
-    ASSERT_EQUAL(tid, v2.type());
-    ASSERT_EQUAL(vx, v2);
-    ASSERT_EQUAL(x, get<T>(v2));
-    ASSERT_EQUAL(x, coerce<T>(v2));
-
-    V v3(vx);                   // Copy construct
-    ASSERT_EQUAL(tid, v3.type());
-    ASSERT_EQUAL(vx, v3);
-    ASSERT_EQUAL(x, get<T>(v3));
-    ASSERT_EQUAL(x, coerce<T>(v3));
-
-    V v4 = vx;                  // Copy assign
-    ASSERT_EQUAL(tid, v4.type());
-    ASSERT_EQUAL(x, get<T>(v4));
-    ASSERT_EQUAL(x, coerce<T>(v4));
-
-    ASSERT_EQUAL(s, to_string(vx));   // Stringify
-    V vy(y);
-    ASSERT(vx != vy);           // Compare
-    ASSERT(vx < vy);
-    ASSERT(vy > vx);
-}
-
-// Test native C/C++ integer types via their mapped integer type ([u]int_x_t)
-template <class V, class T> void simple_integral_test() {
-    typedef typename internal::integer_type<sizeof(T), internal::is_signed<T>::value>::type int_type;
-    simple_type_test<V>(T(3), internal::type_id_of<int_type>::value, "3", T(4));
-}
-
-// Test invalid gets, valid same-type get<T> is tested by simple_type_test
-// Templated to test both scalar and value.
-template<class V>  void bad_get_test() {
-    try { get<bool>(V(int8_t(1))); FAIL("byte as bool"); } catch (conversion_error) {}
-    try { get<uint8_t>(V(true)); FAIL("bool as uint8_t"); } catch (conversion_error) {}
-    try { get<uint8_t>(V(int8_t(1))); FAIL("int8 as uint8"); } catch (conversion_error) {}
-    try { get<int16_t>(V(uint16_t(1))); FAIL("uint16 as int16"); } catch (conversion_error) {}
-    try { get<int16_t>(V(int32_t(1))); FAIL("int32 as int16"); } catch (conversion_error) {}
-    try { get<symbol>(V(std::string())); FAIL("string as symbol"); } catch (conversion_error) {}
-    try { get<std::string>(V(binary())); FAIL("binary as string"); } catch (conversion_error) {}
-    try { get<binary>(V(symbol())); FAIL("symbol as binary"); } catch (conversion_error) {}
-    try { get<binary>(V(timestamp())); FAIL("timestamp as binary"); } catch (conversion_error) {}
-    try { get<int>(V(timestamp())); FAIL("timestamp as int"); } catch (conversion_error) {}
-    try { get<timestamp>(V(0)); FAIL("int as timestamp"); } catch (conversion_error) {}
-    try { get<timestamp>(V(std::string())); FAIL("string as timestamp"); } catch (conversion_error) {}
-}
-
-// Test some valid coercions and some bad ones with mixed types.
-// Templated to test both scalar and value.
-template<class V> void coerce_test() {
-    // Valid C++ conversions should work with coerce.
-    ASSERT_EQUAL(false, coerce<bool>(V(0)));
-    ASSERT_EQUAL(true, coerce<bool>(V(-1)));
-    ASSERT_EQUAL(true, coerce<bool>(V(int64_t(0xFFFF0000))));
-
-    ASSERT_EQUAL(1, coerce<uint8_t>(V(uint64_t(1)))); // In range.
-    ASSERT_EQUAL(1, coerce<uint8_t>(V(uint32_t(0xFF01)))); // int truncate.
-    ASSERT_EQUAL(0xFFFF, coerce<uint16_t>(V(int8_t(-1)))); // Sign extend.
-    ASSERT_EQUAL(-1, coerce<int32_t>(V(uint64_t(0xFFFFFFFFul)))); // 2s complement
-
-    ASSERT_EQUALISH(1.2f, coerce<float>(V(double(1.2))), 0.001f);
-    ASSERT_EQUALISH(3.4, coerce<double>(V(float(3.4))), 0.001);
-    ASSERT_EQUALISH(23.0, coerce<double>(V(uint64_t(23))), 0.001); // int to double.
-    ASSERT_EQUAL(-1945, coerce<int>(V(float(-1945.123))));    // round to int.
-
-    // String-like conversions.
-    ASSERT_EQUAL(std::string("foo"), coerce<std::string>(V(symbol("foo"))));
-    ASSERT_EQUAL(std::string("foo"), coerce<std::string>(V(binary("foo"))));
-
-    // Bad coercions, types are not `is_convertible`
-    V s("foo");
-    try { coerce<bool>(s); FAIL("string as bool"); } catch (conversion_error) {}
-    try { coerce<int>(s); FAIL("string as int"); } catch (conversion_error) {}
-    try { coerce<double>(s); FAIL("string as double"); } catch (conversion_error) {}
-
-    try { coerce<std::string>(V(0)); FAIL("int as string"); } catch (conversion_error) {}
-    try { coerce<symbol>(V(true)); FAIL("bool as symbol"); } catch (conversion_error) {}
-    try { coerce<binary>(V(0.0)); FAIL("double as binary"); } catch (conversion_error) {}
-    try { coerce<symbol>(V(binary())); FAIL("binary as symbol"); } catch (conversion_error) {}
-    try { coerce<binary>(V(symbol())); FAIL("symbol as binary"); } catch (conversion_error) {}
-    try { coerce<binary>(s); } catch (conversion_error) {}
-    try { coerce<symbol>(s); } catch (conversion_error) {}
-}
-
-template <class V> void null_test() {
-    V v;
-    ASSERT(v.empty());
-    ASSERT_EQUAL(NULL_TYPE, v.type());
-    get<null>(v);
-    null n;
-    get(v, n);
-    V v2(n);
-    ASSERT(v.empty());
-    ASSERT_EQUAL(NULL_TYPE, v.type());
-    v = "foo";
-    ASSERT_EQUAL(STRING, v.type());
-    try { get<null>(v); FAIL("Expected conversion_error"); } catch (conversion_error) {}
-    v = null();
-    get<null>(v);
-}
-
-// Nasty hack for uninterpreted decimal<> types.
-template <class T> T make(const char c) { T x; std::fill(x.begin(), x.end(), c); return x; }
-
-template <class V> void scalar_test_group(int& failed) {
-    // Direct AMQP-mapped types.
-    RUN_TEST(failed, simple_type_test<V>(false, BOOLEAN, "false", true));
-    RUN_TEST(failed, simple_type_test<V>(uint8_t(42), UBYTE, "42", uint8_t(50)));
-    RUN_TEST(failed, simple_type_test<V>(int8_t(-42), BYTE, "-42", int8_t(-40)));
-    RUN_TEST(failed, simple_type_test<V>(uint16_t(4242), USHORT, "4242", uint16_t(5252)));
-    RUN_TEST(failed, simple_type_test<V>(int16_t(-4242), SHORT, "-4242", int16_t(3)));
-    RUN_TEST(failed, simple_type_test<V>(uint32_t(4242), UINT, "4242", uint32_t(5252)));
-    RUN_TEST(failed, simple_type_test<V>(int32_t(-4242), INT, "-4242", int32_t(3)));
-    RUN_TEST(failed, simple_type_test<V>(uint64_t(4242), ULONG, "4242", uint64_t(5252)));
-    RUN_TEST(failed, simple_type_test<V>(int64_t(-4242), LONG, "-4242", int64_t(3)));
-    RUN_TEST(failed, simple_type_test<V>(wchar_t('X'), CHAR, "88", wchar_t('Y')));
-    RUN_TEST(failed, simple_type_test<V>(float(1.234), FLOAT, "1.234", float(2.345)));
-    RUN_TEST(failed, simple_type_test<V>(double(11.2233), DOUBLE, "11.2233", double(12)));
-    RUN_TEST(failed, simple_type_test<V>(timestamp(1234), TIMESTAMP, "1234", timestamp(12345)));
-    RUN_TEST(failed, simple_type_test<V>(make<decimal32>(1), DECIMAL32, "decimal32(0x01010101)", make<decimal32>(2)));
-    RUN_TEST(failed, simple_type_test<V>(make<decimal64>(3), DECIMAL64, "decimal64(0x0303030303030303)", make<decimal64>(4)));
-    RUN_TEST(failed, simple_type_test<V>(make<decimal128>(5), DECIMAL128, "decimal128(0x05050505050505050505050505050505)", make<decimal128>(6)));
-    RUN_TEST(failed, simple_type_test<V>(
-                 uuid::copy("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"),
-                 UUID, "00112233-4455-6677-8899-aabbccddeeff",
-                 uuid::copy("\xff\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")));
-    RUN_TEST(failed, simple_type_test<V>(std::string("xxx"), STRING, "xxx", std::string("yyy")));
-    RUN_TEST(failed, simple_type_test<V>(symbol("aaa"), SYMBOL, "aaa", symbol("aaaa")));
-    RUN_TEST(failed, simple_type_test<V>(binary("\010aaa"), BINARY, "b\"\\x08aaa\"", binary("aaaa")));
-
-    // Test native C++ integral types.
-    RUN_TEST(failed, (simple_integral_test<V, char>()));
-    RUN_TEST(failed, (simple_integral_test<V, signed char>()));
-    RUN_TEST(failed, (simple_integral_test<V, unsigned char>()));
-    RUN_TEST(failed, (simple_integral_test<V, short>()));
-    RUN_TEST(failed, (simple_integral_test<V, int>()));
-    RUN_TEST(failed, (simple_integral_test<V, long>()));
-    RUN_TEST(failed, (simple_integral_test<V, unsigned short>()));
-    RUN_TEST(failed, (simple_integral_test<V, unsigned int>()));
-    RUN_TEST(failed, (simple_integral_test<V, unsigned long>()));
-#if PN_CPP_HAS_LONG_LONG
-    RUN_TEST(failed, (simple_integral_test<V, long long>()));
-    RUN_TEST(failed, (simple_integral_test<V, unsigned long long>()));
-#endif
-
-
-    RUN_TEST(failed, (coerce_test<V>()));
-    RUN_TEST(failed, (null_test<V>()));
-    RUN_TEST(failed, (bad_get_test<V>()));
-}
-
-}
-
-#endif // SCALAR_TEST_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/test_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/test_bits.hpp b/proton-c/bindings/cpp/src/test_bits.hpp
deleted file mode 100644
index 0cfbe1f..0000000
--- a/proton-c/bindings/cpp/src/test_bits.hpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#ifndef TEST_BITS_HPP
-#define TEST_BITS_HPP
-/*
- * 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 "msg.hpp"
-#include "proton/types.hpp"
-
-#include <stdexcept>
-#include <iostream>
-#include <iterator>
-#include <sstream>
-#include <math.h>
-
-namespace test {
-
-struct fail : public std::logic_error {
-    fail(const std::string& what) : logic_error(what) {}
-};
-
-template <class T, class U>
-void assert_equal(const T& want, const U& got, const std::string& what) {
-    if (!(want == got))
-        throw fail(MSG(what << " " << want << " != " << got));
-}
-
-template <class T>
-inline void assert_equalish(T want, T got, T delta, const std::string& what)
-{
-    if (!(fabs(want-got) <= delta))
-        throw fail(MSG(what << " " << want << " !=~ " << got));
-}
-
-#define FAIL_MSG(WHAT) (MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT).str())
-#define FAIL(WHAT) throw test::fail(FAIL_MSG(WHAT))
-#define ASSERT(TEST) do { if (!(TEST)) FAIL("failed ASSERT(" #TEST ")"); } while(false)
-#define ASSERT_EQUAL(WANT, GOT) \
-    test::assert_equal((WANT), (GOT), FAIL_MSG("failed ASSERT_EQUAL(" #WANT ", " #GOT ")"))
-#define ASSERT_EQUALISH(WANT, GOT, DELTA) \
-    test::assert_equalish((WANT), (GOT), (DELTA), FAIL_MSG("failed ASSERT_EQUALISH(" #WANT ", " #GOT ")"))
-
-#define RUN_TEST(BAD_COUNT, TEST)                                       \
-    do {                                                                \
-        try {                                                           \
-            TEST;                                                       \
-            break;                                                      \
-        } catch(const test::fail& e) {                                        \
-            std::cout << "FAIL " << #TEST << std::endl << e.what() << std::endl; \
-        } catch(const std::exception& e) {                              \
-            std::cout << "ERROR " << #TEST << std::endl << __FILE__ << ":" << __LINE__ << ": " << e.what() << std::endl; \
-        }                                                               \
-            ++BAD_COUNT;                                                \
-    } while(0)
-
-template<class T> std::string str(const T& x) {
-    std::ostringstream s; s << std::boolalpha << x; return s.str();
-}
-
-// A way to easily create literal collections that can be compared to std:: collections
-// and to print std collections
-// e.g.
-//     std::vector<string> v = ...;
-//     ASSERT_EQUAL(many<string>() + "a" + "b" + "c", v);
-template <class T> struct many : public std::vector<T> {
-    many() {}
-    template<class S> explicit many(const S& s) : std::vector<T>(s.begin(), s.end()) {}
-    many& operator+=(const T& t) { this->push_back(t); return *this; }
-    many& operator<<(const T& t) { return *this += t; }
-    many operator+(const T& t) { many<T> l(*this); return l += t; }
-};
-
-template <class T, class S> bool operator==(const many<T>& m, const S& s) {
-    return m.size() == s.size() && S(m.begin(), m.end()) == s;
-}
-
-template <class T, class S> bool operator==(const S& s, const many<T>& m) {
-    return m.size() == s.size() && S(m.begin(), m.end()) == s;
-}
-
-template <class T> std::ostream& operator<<(std::ostream& o, const many<T>& m) {
-    std::ostream_iterator<T> oi(o, " ");
-    std::copy(m.begin(), m.end(), oi);
-    return o;
-}
-
-}
-
-namespace std {
-template <class T> std::ostream& operator<<(std::ostream& o, const std::vector<T>& s) {
-    return o << test::many<T>(s);
-}
-
-template <class T> std::ostream& operator<<(std::ostream& o, const std::deque<T>& s) {
-    return o << test::many<T>(s);
-}
-
-template <class T> std::ostream& operator<<(std::ostream& o, const std::list<T>& s) {
-    return o << test::many<T>(s);
-}
-
-template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::map<K, T>& x) {
-    return o << test::many<std::pair<K, T> >(x);
-}
-
-template <class U, class V> std::ostream& operator<<(std::ostream& o, const std::pair<U, V>& p) {
-    return o << "( " << p.first << " , " << p.second << " )";
-}
-
-#if PN_CPP_HAS_CPP11
-template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::unordered_map<K, T>& x) {
-    return o << test::many<std::pair<const K, T> >(x);
-}
-
-template <class T> std::ostream& operator<<(std::ostream& o, const std::forward_list<T>& s) {
-    return o << test::many<T>(s);
-}
-#endif
-}
-
-#endif // TEST_BITS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/test_dummy_container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/test_dummy_container.hpp b/proton-c/bindings/cpp/src/test_dummy_container.hpp
deleted file mode 100644
index 4af432a..0000000
--- a/proton-c/bindings/cpp/src/test_dummy_container.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef TEST_DUMMY_CONTAINER_HPP
-#define TEST_DUMMY_CONTAINER_HPP
-
-/*
- * 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/container.hpp"
-#include "proton/event_loop.hpp"
-#include "proton/thread_safe.hpp"
-
-namespace test {
-
-using namespace proton;
-
-
-class dummy_container : public standard_container {
-  public:
-    dummy_container(const std::string cid="") :
-        id_(cid), fail("not implemented for dummy_container") {}
-
-    // Pull in base class functions here so that name search finds all the overloads
-    using standard_container::stop;
-    using standard_container::connect;
-    using standard_container::listen;
-    using standard_container::open_receiver;
-    using standard_container::open_sender;
-
-    returned<connection> connect(const std::string&, const connection_options&) { throw fail; }
-    listener listen(const std::string& , listen_handler& ) { throw fail; }
-    void stop_listening(const std::string&) { throw fail; }
-    void run() { throw fail; }
-    void auto_stop(bool) { throw fail; }
-    void stop(const proton::error_condition& ) { throw fail; }
-    returned<sender> open_sender(const std::string &, const proton::sender_options &, const connection_options&) { throw fail; }
-    returned<receiver> open_receiver( const std::string &, const proton::receiver_options &, const connection_options &) { throw fail; }
-    std::string id() const { return id_; }
-    void client_connection_options(const connection_options &o) { ccopts_ = o; }
-    connection_options client_connection_options() const { return ccopts_; }
-    void server_connection_options(const connection_options &o) { scopts_ = o; }
-    connection_options server_connection_options() const { return scopts_; }
-    void sender_options(const class sender_options &o) { sopts_ = o; }
-    class sender_options sender_options() const { return sopts_; }
-    void receiver_options(const class receiver_options &o) { ropts_ = o; }
-    class receiver_options receiver_options() const { return ropts_; }
-#if PN_CPP_HAS_STD_FUNCTION
-    void schedule(duration, std::function<void()>) { throw fail; }
-#endif
-    void schedule(duration, void_function0&) { throw fail; }
-
-  private:
-    std::string id_;
-    connection_options ccopts_, scopts_;
-    class sender_options sopts_;
-    class receiver_options ropts_;
-    std::runtime_error fail;
-};
-
-class dummy_event_loop : public event_loop {
-#if PN_CPP_HAS_CPP11
-    bool inject(std::function<void()> f) PN_CPP_OVERRIDE { f(); return true; }
-#endif
-    bool inject(proton::void_function0& h) PN_CPP_OVERRIDE { h(); return true; }
-};
-
-}
-
-#endif // TEST_DUMMY_CONTAINER_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/types_internal.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types_internal.hpp b/proton-c/bindings/cpp/src/types_internal.hpp
deleted file mode 100644
index 484dfc4..0000000
--- a/proton-c/bindings/cpp/src/types_internal.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef TYPES_INTERNAL_HPP
-#define TYPES_INTERNAL_HPP
-/*
- * 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/internal/type_traits.hpp"
-#include "proton/error.hpp"
-#include "proton/binary.hpp"
-#include <sstream>
-
-///@file
-/// Inline helpers for encode/decode/type conversion/ostream operators.
-
-namespace proton {
-
-/// Byte copy between two objects, only enabled if their sizes are equal.
-template <class T, class U>
-typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) {
-    const char *p = reinterpret_cast<const char*>(&from);
-    std::copy(p, p + sizeof(T), reinterpret_cast<char*>(&to));
-}
-
-inline conversion_error
-make_conversion_error(type_id want, type_id got, const std::string& msg=std::string()) {
-    std::ostringstream s;
-    s << "unexpected type, want: " << want << " got: " << got;
-    if (!msg.empty()) s << ": " << msg;
-    return conversion_error(s.str());
-}
-
-/// Convert std::string to pn_bytes_t
-inline pn_bytes_t pn_bytes(const std::string& s) {
-    pn_bytes_t b = { s.size(), s.empty() ? 0 : const_cast<char*>(&s[0]) };
-    return b;
-}
-
-inline pn_bytes_t pn_bytes(const binary& s) {
-    pn_bytes_t b = { s.size(), s.empty() ? 0 : reinterpret_cast<const char*>(&s[0]) };
-    return b;
-}
-
-inline std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); }
-inline binary bin(const pn_bytes_t& b) { return binary(b.start, b.start+b.size); }
-
-// Save all stream format state, restore in destructor.
-struct ios_guard {
-    std::ios &guarded;
-    std::ios old;
-    ios_guard(std::ios& x) : guarded(x), old(0) { old.copyfmt(guarded); }
-    ~ios_guard() { guarded.copyfmt(old); }
-};
-
-// Convert a char (signed or unsigned) into an unsigned 1 byte integer that will ostream 
-// as a numeric byte value, not a character and will not get sign-extended.
-inline unsigned int printable_byte(uint8_t byte) { return byte; }
-
-}
-#endif // TYPES_INTERNAL_HPP


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


[16/50] [abbrv] qpid-proton git commit: PROTON-1323: update notes for releasing

Posted by ac...@apache.org.
PROTON-1323: update notes for releasing


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

Branch: refs/heads/go1
Commit: c6d366c60a58b5095a16254f5b4aec29464ddffe
Parents: 3eb1785
Author: Robert Gemmell <ro...@apache.org>
Authored: Mon Oct 10 17:02:15 2016 +0100
Committer: Robert Gemmell <ro...@apache.org>
Committed: Mon Oct 10 17:02:15 2016 +0100

----------------------------------------------------------------------
 RELEASE.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/c6d366c6/RELEASE.md
----------------------------------------------------------------------
diff --git a/RELEASE.md b/RELEASE.md
index e799ee1..8be148e 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -3,8 +3,9 @@
 1. Grab a clean checkout for safety.
 2. Run: "git checkout ${BRANCH}" to switch to a branch of the intended release point.
 3. Update the versions:
-  - Run: "bin/version.sh ${VERSION}", e.g. bin/release.sh 0.12.2.
-  - Update the version if needed in file: proton-c/bindings/python/setuputils/bundle.py
+  - Run: "bin/version.sh ${VERSION}", e.g. bin/version.sh 0.15.0.
+  - Update the version(s) if needed in file: proton-c/bindings/python/docs/conf.py
+  - Update the version(s) if needed in file: proton-c/bindings/python/setuputils/bundle.py
 4. Commit the changes, tag them.
   - Run: "git add ."
   - Run: 'git commit -m "update versions for ${TAG}"'


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


[25/50] [abbrv] qpid-proton git commit: PROTON-1329: remove the TestDecoder class

Posted by ac...@apache.org.
PROTON-1329: remove the TestDecoder 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/1bbe4351
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1bbe4351
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1bbe4351

Branch: refs/heads/go1
Commit: 1bbe43518b99fdeca100cc9c7f65ccdca00584bb
Parents: 3569e03
Author: Robert Gemmell <ro...@apache.org>
Authored: Wed Oct 19 15:13:38 2016 +0100
Committer: Robert Gemmell <ro...@apache.org>
Committed: Wed Oct 19 15:13:38 2016 +0100

----------------------------------------------------------------------
 .../org/apache/qpid/proton/TestDecoder.java     | 96 --------------------
 .../org/apache/qpid/proton/InteropTest.java     | 32 ++++---
 2 files changed, 21 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1bbe4351/proton-j/src/main/java/org/apache/qpid/proton/TestDecoder.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/TestDecoder.java b/proton-j/src/main/java/org/apache/qpid/proton/TestDecoder.java
deleted file mode 100644
index 50d53f7..0000000
--- a/proton-j/src/main/java/org/apache/qpid/proton/TestDecoder.java
+++ /dev/null
@@ -1,96 +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.
- */
-package org.apache.qpid.proton;
-
-import org.apache.qpid.proton.TestDecoder;
-import org.apache.qpid.proton.amqp.Binary;
-import org.apache.qpid.proton.amqp.Decimal128;
-import org.apache.qpid.proton.amqp.Decimal32;
-import org.apache.qpid.proton.amqp.Decimal64;
-import org.apache.qpid.proton.amqp.Symbol;
-import org.apache.qpid.proton.amqp.UnsignedByte;
-import org.apache.qpid.proton.amqp.UnsignedInteger;
-import org.apache.qpid.proton.amqp.UnsignedLong;
-import org.apache.qpid.proton.amqp.UnsignedShort;
-import org.apache.qpid.proton.codec.AMQPDefinedTypes;
-
-import org.apache.qpid.proton.codec.DecoderImpl;
-import org.apache.qpid.proton.codec.EncoderImpl;
-
-import java.nio.ByteBuffer;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-
-/**
- * TestDecoder is a stripped-down decoder used by interop tests to decode AMQP
- * data.  The native version wraps a DecoderImpl, while the JNI version wraps a
- * Data object.
- */
-
-public class TestDecoder {
-    private DecoderImpl decoder;
-    private EncoderImpl encoder;
-    private ByteBuffer buffer;
-
-    TestDecoder(byte[] data) {
-        decoder = new DecoderImpl();
-	encoder = new EncoderImpl(decoder);
-	AMQPDefinedTypes.registerAllTypes(decoder, encoder);
-	buffer = ByteBuffer.allocate(data.length);
-	buffer.put(data);
-	buffer.rewind();
-        decoder.setByteBuffer(buffer);
-    }
-
-    public Boolean readBoolean() { return decoder.readBoolean(); }
-    public Byte readByte() { return decoder.readByte(); }
-    public Short readShort() { return decoder.readShort(); }
-    public Integer readInteger() { return decoder.readInteger(); }
-    public Long readLong() { return decoder.readLong(); }
-    public UnsignedByte readUnsignedByte() { return decoder.readUnsignedByte(); }
-    public UnsignedShort readUnsignedShort() { return decoder.readUnsignedShort(); }
-    public UnsignedInteger readUnsignedInteger() { return decoder.readUnsignedInteger(); }
-    public UnsignedLong readUnsignedLong() { return decoder.readUnsignedLong(); }
-    public Character readCharacter() { return decoder.readCharacter(); }
-    public Float readFloat() { return decoder.readFloat(); }
-    public Double readDouble() { return decoder.readDouble(); }
-    public UUID readUUID() { return decoder.readUUID(); }
-    public Decimal32 readDecimal32() { return decoder.readDecimal32(); }
-    public Decimal64 readDecimal64() { return decoder.readDecimal64(); }
-    public Decimal128 readDecimal128() { return decoder.readDecimal128(); }
-    public Date readTimestamp() { return decoder.readTimestamp(); }
-    public Binary readBinary() { return decoder.readBinary(); }
-    public Symbol readSymbol() { return decoder.readSymbol(); }
-    public String readString() { return decoder.readString(); }
-    public List readList() { return decoder.readList(); }
-    public Map readMap() { return decoder.readMap(); }
-    public Object[] readArray() { return decoder.readArray(); }
-    public boolean[] readBooleanArray() { return decoder.readBooleanArray(); }
-    public byte[] readByteArray() { return decoder.readByteArray(); }
-    public short[] readShortArray() { return decoder.readShortArray(); }
-    public int[] readIntegerArray() { return decoder.readIntegerArray(); }
-    public long[] readLongArray() { return decoder.readLongArray(); }
-    public float[] readFloatArray() { return decoder.readFloatArray(); }
-    public double[] readDoubleArray() { return decoder.readDoubleArray(); }
-    public char[] readCharacterArray() { return decoder.readCharacterArray(); }
-    public Object readObject() { return decoder.readObject(); }
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1bbe4351/tests/java/org/apache/qpid/proton/InteropTest.java
----------------------------------------------------------------------
diff --git a/tests/java/org/apache/qpid/proton/InteropTest.java b/tests/java/org/apache/qpid/proton/InteropTest.java
index c875092..e9b8c58 100644
--- a/tests/java/org/apache/qpid/proton/InteropTest.java
+++ b/tests/java/org/apache/qpid/proton/InteropTest.java
@@ -18,17 +18,21 @@
  */
 package org.apache.qpid.proton;
 
-import org.apache.qpid.proton.TestDecoder;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.DescribedType;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.messaging.AmqpValue;
+import org.apache.qpid.proton.codec.AMQPDefinedTypes;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.message.Message;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertArrayEquals;
 import org.junit.Test;
 import java.lang.System;
+import java.nio.ByteBuffer;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -72,10 +76,16 @@ public class InteropTest
         return m;
     }
 
-    TestDecoder createDecoder(byte[] data)
+    Decoder createDecoder(byte[] data)
     {
-        TestDecoder td = new TestDecoder(data);
-        return td;
+        DecoderImpl decoder = new DecoderImpl();
+        AMQPDefinedTypes.registerAllTypes(decoder, new EncoderImpl(decoder));
+        ByteBuffer buffer = ByteBuffer.allocate(data.length);
+        buffer.put(data);
+        buffer.rewind();
+        decoder.setByteBuffer(buffer);
+
+        return decoder;
     }
 
     @Test
@@ -90,7 +100,7 @@ public class InteropTest
     @Test
     public void testPrimitives() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("primitives"));
+        Decoder d = createDecoder(getBytes("primitives"));
         assertEquals(true, d.readBoolean());
         assertEquals(false, d.readBoolean());
         assertEquals(d.readUnsignedByte().intValue(), 42);
@@ -107,7 +117,7 @@ public class InteropTest
     @Test
     public void testStrings() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("strings"));
+        Decoder d = createDecoder(getBytes("strings"));
         assertEquals(new Binary("abc\0defg".getBytes("UTF-8")), d.readBinary());
         assertEquals("abcdefg", d.readString());
         assertEquals(Symbol.valueOf("abcdefg"), d.readSymbol());
@@ -119,7 +129,7 @@ public class InteropTest
     @Test
     public void testDescribed() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("described"));
+        Decoder d = createDecoder(getBytes("described"));
         DescribedType dt = (DescribedType) (d.readObject());
         assertEquals(Symbol.valueOf("foo-descriptor"), dt.getDescriptor());
         assertEquals("foo-value", dt.getDescribed());
@@ -132,7 +142,7 @@ public class InteropTest
     @Test
     public void testDescribedArray() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("described_array"));
+        Decoder d = createDecoder(getBytes("described_array"));
         DescribedType a[] = (DescribedType[]) (d.readArray());
         for (int i = 0; i < 10; ++i)
         {
@@ -144,7 +154,7 @@ public class InteropTest
     @Test
     public void testArrays() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("arrays"));
+        Decoder d = createDecoder(getBytes("arrays"));
 
         // int array
         Vector<Integer> ints = new Vector<Integer>();
@@ -164,7 +174,7 @@ public class InteropTest
     @Test
     public void testLists() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("lists"));
+        Decoder d = createDecoder(getBytes("lists"));
         List<Object> l = new ArrayList<Object>()
         {
             {
@@ -182,7 +192,7 @@ public class InteropTest
     @Test
     public void testMaps() throws IOException
     {
-        TestDecoder d = createDecoder(getBytes("maps"));
+        Decoder d = createDecoder(getBytes("maps"));
         Map map = new HashMap()
         {
             {


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


[48/50] [abbrv] qpid-proton git commit: PROTON-1338: Go: update `go get`

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/proton/handlers.go
----------------------------------------------------------------------
diff --cc proton/handlers.go
index 87c43ae,0000000..961136e
mode 100644,000000..100644
--- a/proton/handlers.go
+++ b/proton/handlers.go
@@@ -1,388 -1,0 +1,395 @@@
 +/*
 +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 proton
 +
- // #include <proton/handlers.h>
- import "C"
 +import "fmt"
 +
 +// EventHandler handles core proton events.
 +type EventHandler interface {
 +	// HandleEvent is called with an event.
 +	// Typically HandleEvent() is implemented as a switch on e.Type()
 +	// Returning an error will stop the Engine.
 +	HandleEvent(e Event)
 +}
 +
- // cHandler wraps a C pn_handler_t
- type cHandler struct {
- 	pn *C.pn_handler_t
- }
- 
- func (h cHandler) HandleEvent(e Event) {
- 	C.pn_handler_dispatch(h.pn, e.pn, C.pn_event_type(e.pn))
- }
- 
 +// MessagingHandler provides an alternative interface to EventHandler.
 +// it is easier to use for most applications that send and receive messages.
 +//
 +// Implement this interface and then wrap your value with a MessagingHandlerDelegator.
 +// MessagingHandlerDelegator implements EventHandler and can be registered with a Engine.
 +//
 +type MessagingHandler interface {
 +	// HandleMessagingEvent is called with  MessagingEvent.
 +	// Typically HandleEvent() is implemented as a switch on e.Type()
 +	// Returning an error will stop the Engine.
 +	HandleMessagingEvent(MessagingEvent, Event)
 +}
 +
 +// MessagingEvent provides a set of events that are easier to work with than the
 +// core events defined by EventType
 +//
 +// There are 3 types of "endpoint": Connection, Session and Link.  For each
 +// endpoint there are 5 events: Opening, Opened, Closing, Closed and Error.
 +//
 +// The meaning of these events is as follows:
 +//
 +// Opening: The remote end opened, the local end will open automatically.
 +//
 +// Opened: Both ends are open, regardless of which end opened first.
 +//
 +// Closing: The remote end closed without error, the local end will close automatically.
 +//
 +// Error: The remote end closed with an error, the local end will close automatically.
 +//
 +// Closed: Both ends are closed, regardless of which end closed first or if there was an error.
 +// No further events will be received for the endpoint.
 +//
 +type MessagingEvent int
 +
 +const (
 +	// The event loop starts.
 +	MStart MessagingEvent = iota
 +	// The peer closes the connection with an error condition.
 +	MConnectionError
 +	// The peer closes the session with an error condition.
 +	MSessionError
 +	// The peer closes the link with an error condition.
 +	MLinkError
 +	// The peer Initiates the opening of the connection.
 +	MConnectionOpening
 +	// The peer initiates the opening of the session.
 +	MSessionOpening
 +	// The peer initiates the opening of the link.
 +	MLinkOpening
 +	// The connection is opened.
 +	MConnectionOpened
 +	// The session is opened.
 +	MSessionOpened
 +	// The link is opened.
 +	MLinkOpened
 +	// The peer initiates the closing of the connection.
 +	MConnectionClosing
 +	// The peer initiates the closing of the session.
 +	MSessionClosing
 +	// The peer initiates the closing of the link.
 +	MLinkClosing
 +	// Both ends of the connection are closed.
 +	MConnectionClosed
 +	// Both ends of the session are closed.
 +	MSessionClosed
 +	// Both ends of the link are closed.
 +	MLinkClosed
 +	// The sender link has credit and messages can
 +	// therefore be transferred.
 +	MSendable
 +	// The remote peer accepts an outgoing message.
 +	MAccepted
 +	// The remote peer rejects an outgoing message.
 +	MRejected
 +	// The peer releases an outgoing message. Note that this may be in response to
 +	// either the RELEASE or MODIFIED state as defined by the AMQP specification.
 +	MReleased
 +	// The peer has settled the outgoing message. This is the point at which it
 +	// should never be re-transmitted.
 +	MSettled
 +	// A message is received. Call Event.Delivery().Message() to decode as an amqp.Message.
 +	// To manage the outcome of this messages (e.g. to accept or reject the message)
 +	// use Event.Delivery().
 +	MMessage
 +	// A network connection was disconnected.
 +	MDisconnected
 +)
 +
 +func (t MessagingEvent) String() string {
 +	switch t {
 +	case MStart:
 +		return "Start"
 +	case MConnectionError:
 +		return "ConnectionError"
 +	case MSessionError:
 +		return "SessionError"
 +	case MLinkError:
 +		return "LinkError"
 +	case MConnectionOpening:
 +		return "ConnectionOpening"
 +	case MSessionOpening:
 +		return "SessionOpening"
 +	case MLinkOpening:
 +		return "LinkOpening"
 +	case MConnectionOpened:
 +		return "ConnectionOpened"
 +	case MSessionOpened:
 +		return "SessionOpened"
 +	case MLinkOpened:
 +		return "LinkOpened"
 +	case MConnectionClosing:
 +		return "ConnectionClosing"
 +	case MSessionClosing:
 +		return "SessionClosing"
 +	case MLinkClosing:
 +		return "LinkClosing"
 +	case MConnectionClosed:
 +		return "ConnectionClosed"
 +	case MSessionClosed:
 +		return "SessionClosed"
 +	case MLinkClosed:
 +		return "LinkClosed"
 +	case MDisconnected:
 +		return "Disconnected"
 +	case MSendable:
 +		return "Sendable"
 +	case MAccepted:
 +		return "Accepted"
 +	case MRejected:
 +		return "Rejected"
 +	case MReleased:
 +		return "Released"
 +	case MSettled:
 +		return "Settled"
 +	case MMessage:
 +		return "Message"
 +	default:
 +		return "Unknown"
 +	}
 +}
 +
 +// ResourceHandler provides a simple way to track the creation and deletion of
 +// various proton objects.
 +// endpointDelegator captures common patterns for endpoints opening/closing
 +type endpointDelegator struct {
 +	remoteOpen, remoteClose, localOpen, localClose EventType
 +	opening, opened, closing, closed, error        MessagingEvent
 +	endpoint                                       func(Event) Endpoint
 +	delegator                                      *MessagingAdapter
 +}
 +
 +// HandleEvent handles an open/close event for an endpoint in a generic way.
 +func (d endpointDelegator) HandleEvent(e Event) {
 +	endpoint := d.endpoint(e)
 +	state := endpoint.State()
 +
 +	switch e.Type() {
 +
 +	case d.localOpen:
 +		if state.RemoteActive() {
 +			d.delegator.mhandler.HandleMessagingEvent(d.opened, e)
 +		}
 +
 +	case d.remoteOpen:
++		d.delegator.mhandler.HandleMessagingEvent(d.opening, e)
 +		switch {
 +		case state.LocalActive():
 +			d.delegator.mhandler.HandleMessagingEvent(d.opened, e)
 +		case state.LocalUninit():
- 			d.delegator.mhandler.HandleMessagingEvent(d.opening, e)
 +			if d.delegator.AutoOpen {
 +				endpoint.Open()
 +			}
 +		}
 +
 +	case d.remoteClose:
 +		if endpoint.RemoteCondition().IsSet() { // Closed with error
 +			d.delegator.mhandler.HandleMessagingEvent(d.error, e)
 +		} else {
 +			d.delegator.mhandler.HandleMessagingEvent(d.closing, e)
 +		}
 +		if state.LocalClosed() {
 +			d.delegator.mhandler.HandleMessagingEvent(d.closed, e)
 +		} else if state.LocalActive() {
 +			endpoint.Close()
 +		}
 +
 +	case d.localClose:
 +		if state.RemoteClosed() {
 +			d.delegator.mhandler.HandleMessagingEvent(d.closed, e)
 +		}
 +
 +	default:
 +		// We shouldn't be called with any other event type.
 +		panic(fmt.Errorf("internal error, not an open/close event: %s", e))
 +	}
 +}
 +
++type flowcontroller struct {
++	window, drained int
++}
++
++func (d flowcontroller) HandleEvent(e Event) {
++	link := e.Link()
++
++	switch e.Type() {
++	case ELinkLocalOpen, ELinkRemoteOpen, ELinkFlow, EDelivery:
++		if link.IsReceiver() {
++			d.drained += link.Drained()
++			if d.drained != 0 {
++				link.Flow(d.window - link.Credit())
++			}
++		}
++	}
++}
++
 +// MessagingAdapter implments a EventHandler and delegates to a MessagingHandler.
 +// You can modify the exported fields before you pass the MessagingAdapter to
 +// a Engine.
 +type MessagingAdapter struct {
 +	mhandler                  MessagingHandler
 +	connection, session, link endpointDelegator
 +	flowcontroller            EventHandler
 +
 +	// AutoSettle (default true) automatically pre-settle outgoing messages.
 +	AutoSettle bool
 +	// AutoAccept (default true) automatically accept and settle incoming messages
 +	// if they are not settled by the delegate.
 +	AutoAccept bool
 +	// AutoOpen (default true) automatically open remotely opened endpoints.
 +	AutoOpen bool
 +	// Prefetch (default 10) initial credit to issue for incoming links.
 +	Prefetch int
 +	// PeerCloseIsError (default false) if true a close by the peer will be treated as an error.
 +	PeerCloseError bool
 +}
 +
 +func NewMessagingAdapter(h MessagingHandler) *MessagingAdapter {
 +	return &MessagingAdapter{
 +		mhandler:       h,
 +		flowcontroller: nil,
 +		AutoSettle:     true,
 +		AutoAccept:     true,
 +		AutoOpen:       true,
 +		Prefetch:       10,
 +		PeerCloseError: false,
 +	}
 +}
 +
 +func handleIf(h EventHandler, e Event) {
 +	if h != nil {
 +		h.HandleEvent(e)
 +	}
 +}
 +
 +// Handle a proton event by passing the corresponding MessagingEvent(s) to
 +// the MessagingHandler.
 +func (d *MessagingAdapter) HandleEvent(e Event) {
 +	handleIf(d.flowcontroller, e)
 +
 +	switch e.Type() {
 +
 +	case EConnectionInit:
 +		d.connection = endpointDelegator{
 +			EConnectionRemoteOpen, EConnectionRemoteClose, EConnectionLocalOpen, EConnectionLocalClose,
 +			MConnectionOpening, MConnectionOpened, MConnectionClosing, MConnectionClosed,
 +			MConnectionError,
 +			func(e Event) Endpoint { return e.Connection() },
 +			d,
 +		}
 +		d.session = endpointDelegator{
 +			ESessionRemoteOpen, ESessionRemoteClose, ESessionLocalOpen, ESessionLocalClose,
 +			MSessionOpening, MSessionOpened, MSessionClosing, MSessionClosed,
 +			MSessionError,
 +			func(e Event) Endpoint { return e.Session() },
 +			d,
 +		}
 +		d.link = endpointDelegator{
 +			ELinkRemoteOpen, ELinkRemoteClose, ELinkLocalOpen, ELinkLocalClose,
 +			MLinkOpening, MLinkOpened, MLinkClosing, MLinkClosed,
 +			MLinkError,
 +			func(e Event) Endpoint { return e.Link() },
 +			d,
 +		}
 +		if d.Prefetch > 0 {
- 			d.flowcontroller = cHandler{C.pn_flowcontroller(C.int(d.Prefetch))}
++			d.flowcontroller = flowcontroller{window: d.Prefetch, drained: 0}
 +		}
 +		d.mhandler.HandleMessagingEvent(MStart, e)
 +
 +	case EConnectionRemoteOpen:
 +
 +		d.connection.HandleEvent(e)
 +
 +	case EConnectionRemoteClose:
 +		d.connection.HandleEvent(e)
 +		e.Connection().Transport().CloseTail()
 +
 +	case EConnectionLocalOpen, EConnectionLocalClose:
 +		d.connection.HandleEvent(e)
 +
 +	case ESessionRemoteOpen, ESessionRemoteClose, ESessionLocalOpen, ESessionLocalClose:
 +		d.session.HandleEvent(e)
 +
 +	case ELinkRemoteOpen:
 +		e.Link().Source().Copy(e.Link().RemoteSource())
 +		e.Link().Target().Copy(e.Link().RemoteTarget())
 +		d.link.HandleEvent(e)
 +
 +	case ELinkRemoteClose, ELinkLocalOpen, ELinkLocalClose:
 +		d.link.HandleEvent(e)
 +
 +	case ELinkFlow:
 +		if e.Link().IsSender() && e.Link().Credit() > 0 {
 +			d.mhandler.HandleMessagingEvent(MSendable, e)
 +		}
 +
 +	case EDelivery:
 +		if e.Delivery().Link().IsReceiver() {
 +			d.incoming(e)
 +		} else {
 +			d.outgoing(e)
 +		}
 +
 +	case ETransportClosed:
 +		d.mhandler.HandleMessagingEvent(MDisconnected, e)
 +	}
 +}
 +
- func (d *MessagingAdapter) incoming(e Event) (err error) {
++func (d *MessagingAdapter) incoming(e Event) {
 +	delivery := e.Delivery()
 +	if delivery.HasMessage() {
 +		d.mhandler.HandleMessagingEvent(MMessage, e)
 +		if d.AutoAccept && !delivery.Settled() {
 +			delivery.Accept()
 +		}
 +		if delivery.Current() {
 +			e.Link().Advance()
 +		}
 +	} else if delivery.Updated() && delivery.Settled() {
 +		d.mhandler.HandleMessagingEvent(MSettled, e)
 +	}
 +	return
 +}
 +
- func (d *MessagingAdapter) outgoing(e Event) (err error) {
++func (d *MessagingAdapter) outgoing(e Event) {
 +	delivery := e.Delivery()
 +	if delivery.Updated() {
 +		switch delivery.Remote().Type() {
 +		case Accepted:
 +			d.mhandler.HandleMessagingEvent(MAccepted, e)
 +		case Rejected:
 +			d.mhandler.HandleMessagingEvent(MRejected, e)
 +		case Released, Modified:
 +			d.mhandler.HandleMessagingEvent(MReleased, e)
 +		}
- 		if err == nil && delivery.Settled() {
++		if delivery.Settled() {
 +			// The delivery was settled remotely, inform the local end.
 +			d.mhandler.HandleMessagingEvent(MSettled, e)
 +		}
- 		if err == nil && d.AutoSettle {
++		if d.AutoSettle {
 +			delivery.Settle() // Local settle, don't mhandler MSettled till the remote end settles.
 +		}
 +	}
 +	return
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/proton/proton_test.go
----------------------------------------------------------------------
diff --cc proton/proton_test.go
index bb3f21c,0000000..aad93eb
mode 100644,000000..100644
--- a/proton/proton_test.go
+++ b/proton/proton_test.go
@@@ -1,27 -1,0 +1,96 @@@
 +/*
 +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 proton
 +
 +import (
++	"fmt"
++	"net"
++	"path"
++	"runtime"
 +	"testing"
++	"time"
 +)
 +
- // TODO aconway 2015-10-14: placeholder, add unit tests.
- func Test(*testing.T) {}
++func errorIf(t *testing.T, err error) {
++	if err != nil {
++		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
++		if ok {
++			_, file = path.Split(file)
++		}
++		t.Errorf("(from %s:%d) %v", file, line, err)
++	}
++}
++
++func fatalIf(t *testing.T, err error) {
++	if err != nil {
++		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
++		if ok {
++			_, file = path.Split(file)
++		}
++		t.Fatalf("(from %s:%d) %v", file, line, err)
++	}
++}
++
++type events []EventType
++
++type testEngine struct {
++	Engine
++	events chan EventType
++}
++
++func newTestEngine(conn net.Conn) (*testEngine, error) {
++	testEng := &testEngine{events: make(chan EventType, 1000)}
++	return testEng, testEng.Initialize(conn, testEng)
++}
++
++func (eng *testEngine) HandleEvent(e Event) {
++	eng.events <- e.Type()
++}
++
++func (eng *testEngine) expect(events []EventType) error {
++	timer := time.After(5 * time.Second)
++	for _, want := range events {
++		select {
++		case got := <-eng.events:
++			if want != got {
++				return fmt.Errorf("want %s, got %s", want, got)
++			}
++		case <-timer:
++			return fmt.Errorf("expect timeout")
++		}
++	}
++	return nil
++}
++
++func Test(t *testing.T) {
++	cConn, sConn := net.Pipe()
++	client, err := newTestEngine(cConn)
++	fatalIf(t, err)
++	server, err := newTestEngine(sConn)
++	fatalIf(t, err)
++	server.Server()
++	go client.Run()
++	go server.Run()
++	fatalIf(t, server.expect(events{EConnectionInit, EConnectionBound}))
++	fatalIf(t, client.expect(events{EConnectionInit, EConnectionBound}))
++	fatalIf(t, client.InjectWait(func() error { client.Connection().Open(); return nil }))
++	fatalIf(t, client.expect(events{EConnectionLocalOpen}))
++	fatalIf(t, server.expect(events{EConnectionRemoteOpen}))
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/proton/wrappers.go
----------------------------------------------------------------------
diff --cc proton/wrappers.go
index 70611d3,0000000..4d55e4f
mode 100644,000000..100644
--- a/proton/wrappers.go
+++ b/proton/wrappers.go
@@@ -1,386 -1,0 +1,431 @@@
 +/*
 +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.
 +*/
 +
 +// This file contains special-case wrapper functions or wrappers that don't follow
 +// the pattern of genwrap.go.
 +
 +package proton
 +
 +//#include <proton/codec.h>
 +//#include <proton/connection.h>
 +//#include <proton/delivery.h>
 +//#include <proton/event.h>
 +//#include <proton/link.h>
 +//#include <proton/link.h>
 +//#include <proton/object.h>
++//#include <proton/sasl.h>
 +//#include <proton/session.h>
 +//#include <proton/transport.h>
 +//#include <stdlib.h>
 +import "C"
 +
 +import (
 +	"fmt"
 +	"qpid.apache.org/amqp"
 +	"reflect"
 +	"time"
 +	"unsafe"
 +)
 +
 +// TODO aconway 2015-05-05: Documentation for generated types.
 +
 +// CHandle holds an unsafe.Pointer to a proton C struct, the C type depends on the
 +// Go type implementing this interface. For low level, at-your-own-risk use only.
 +type CHandle interface {
 +	// CPtr returns the unsafe C pointer, equivalent to a C void*.
 +	CPtr() unsafe.Pointer
 +}
 +
 +// Incref increases the refcount of a proton value, which prevents the
 +// underlying C struct being freed until you call Decref().
 +//
 +// It can be useful to "pin" a proton value in memory while it is in use by
 +// goroutines other than the event loop goroutine. For example if you Incref() a
 +// Link, the underlying object is not freed when the link is closed, so means
 +// other goroutines can continue to safely use it as an index in a map or inject
 +// it into the event loop goroutine. There will of course be an error if you try
 +// to use a link after it is closed, but not a segmentation fault.
 +func Incref(c CHandle) {
 +	if p := c.CPtr(); p != nil {
 +		C.pn_incref(p)
 +	}
 +}
 +
 +// Decref decreases the refcount of a proton value, freeing the underlying C
 +// struct if this is the last reference.  Only call this if you previously
 +// called Incref() for this value.
 +func Decref(c CHandle) {
 +	if p := c.CPtr(); p != nil {
 +		C.pn_decref(p)
 +	}
 +}
 +
 +// Event is an AMQP protocol event.
 +type Event struct {
 +	pn         *C.pn_event_t
 +	eventType  EventType
 +	connection Connection
 +	transport  Transport
 +	session    Session
 +	link       Link
 +	delivery   Delivery
 +	injecter   Injecter
 +}
 +
 +func makeEvent(pn *C.pn_event_t, injecter Injecter) Event {
 +	return Event{
 +		pn:         pn,
 +		eventType:  EventType(C.pn_event_type(pn)),
 +		connection: Connection{C.pn_event_connection(pn)},
 +		transport:  Transport{C.pn_event_transport(pn)},
 +		session:    Session{C.pn_event_session(pn)},
 +		link:       Link{C.pn_event_link(pn)},
 +		delivery:   Delivery{C.pn_event_delivery(pn)},
 +		injecter:   injecter,
 +	}
 +}
 +func (e Event) IsNil() bool            { return e.eventType == EventType(0) }
 +func (e Event) Type() EventType        { return e.eventType }
 +func (e Event) Connection() Connection { return e.connection }
 +func (e Event) Transport() Transport   { return e.transport }
 +func (e Event) Session() Session       { return e.session }
 +func (e Event) Link() Link             { return e.link }
 +func (e Event) Delivery() Delivery     { return e.delivery }
 +func (e Event) String() string         { return e.Type().String() }
 +
 +// Injecter should not be used in a handler function, but it can be passed to
 +// other goroutines (via a channel or to a goroutine started by handler
 +// functions) to let them inject functions back into the handlers goroutine.
 +func (e Event) Injecter() Injecter { return e.injecter }
 +
 +// Data holds a pointer to decoded AMQP data.
 +// Use amqp.marshal/unmarshal to access it as Go data types.
 +//
 +type Data struct{ pn *C.pn_data_t }
 +
 +func NewData(p unsafe.Pointer) Data { return Data{(*C.pn_data_t)(p)} }
 +
 +func (d Data) Free()                   { C.pn_data_free(d.pn) }
 +func (d Data) Pointer() unsafe.Pointer { return unsafe.Pointer(d.pn) }
 +func (d Data) Clear()                  { C.pn_data_clear(d.pn) }
 +func (d Data) Rewind()                 { C.pn_data_rewind(d.pn) }
 +func (d Data) Error() error            { return PnError(C.pn_data_error(d.pn)) }
 +
 +// State holds the state flags for an AMQP endpoint.
 +type State byte
 +
 +const (
 +	SLocalUninit  State = C.PN_LOCAL_UNINIT
 +	SLocalActive        = C.PN_LOCAL_ACTIVE
 +	SLocalClosed        = C.PN_LOCAL_CLOSED
 +	SRemoteUninit       = C.PN_REMOTE_UNINIT
 +	SRemoteActive       = C.PN_REMOTE_ACTIVE
 +	SRemoteClosed       = C.PN_REMOTE_CLOSED
 +)
 +
 +// Has is True if bits & state is non 0.
 +func (s State) Has(bits State) bool { return s&bits != 0 }
 +
 +func (s State) LocalUninit() bool  { return s.Has(SLocalUninit) }
 +func (s State) LocalActive() bool  { return s.Has(SLocalActive) }
 +func (s State) LocalClosed() bool  { return s.Has(SLocalClosed) }
 +func (s State) RemoteUninit() bool { return s.Has(SRemoteUninit) }
 +func (s State) RemoteActive() bool { return s.Has(SRemoteActive) }
 +func (s State) RemoteClosed() bool { return s.Has(SRemoteClosed) }
 +
 +// Return a State containig just the local flags
 +func (s State) Local() State { return State(s & C.PN_LOCAL_MASK) }
 +
 +// Return a State containig just the remote flags
 +func (s State) Remote() State { return State(s & C.PN_REMOTE_MASK) }
 +
 +// Endpoint is the common interface for Connection, Link and Session.
 +type Endpoint interface {
 +	// State is the open/closed state.
 +	State() State
 +	// Open an endpoint.
 +	Open()
 +	// Close an endpoint.
 +	Close()
 +	// Condition holds a local error condition.
 +	Condition() Condition
 +	// RemoteCondition holds a remote error condition.
 +	RemoteCondition() Condition
 +	// Human readable name
 +	String() string
 +	// Human readable endpoint type "link", "session" etc.
 +	Type() string
 +}
 +
 +// CloseError sets an error condition (if err != nil) on an endpoint and closes
 +// the endpoint if not already closed
 +func CloseError(e Endpoint, err error) {
 +	if err != nil {
 +		e.Condition().SetError(err)
 +	}
 +	e.Close()
 +}
 +
 +// EndpointError returns the remote error if there is one, the local error if not
 +// nil if there is no error.
 +func EndpointError(e Endpoint) error {
 +	err := e.RemoteCondition().Error()
 +	if err == nil {
 +		err = e.Condition().Error()
 +	}
 +	return err
 +}
 +
 +const (
 +	Received uint64 = C.PN_RECEIVED
 +	Accepted        = C.PN_ACCEPTED
 +	Rejected        = C.PN_REJECTED
 +	Released        = C.PN_RELEASED
 +	Modified        = C.PN_MODIFIED
 +)
 +
 +// SettleAs is equivalent to d.Update(disposition); d.Settle()
 +func (d Delivery) SettleAs(disposition uint64) {
 +	d.Update(disposition)
 +	d.Settle()
 +}
 +
 +// Accept accepts and settles a delivery.
 +func (d Delivery) Accept() { d.SettleAs(Accepted) }
 +
 +// Reject rejects and settles a delivery
 +func (d Delivery) Reject() { d.SettleAs(Rejected) }
 +
 +// Release releases and settles a delivery
 +// If delivered is true the delivery count for the message will be increased.
 +func (d Delivery) Release(delivered bool) {
 +	if delivered {
 +		d.SettleAs(Modified)
 +	} else {
 +		d.SettleAs(Released)
 +	}
 +}
 +
 +type DeliveryTag struct{ pn C.pn_delivery_tag_t }
 +
 +func (t DeliveryTag) String() string { return C.GoStringN(t.pn.start, C.int(t.pn.size)) }
 +
 +func (l Link) Recv(buf []byte) int {
 +	if len(buf) == 0 {
 +		return 0
 +	}
 +	return int(C.pn_link_recv(l.pn, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
 +}
 +
 +func (l Link) SendBytes(bytes []byte) int {
 +	return int(C.pn_link_send(l.pn, cPtr(bytes), cLen(bytes)))
 +}
 +
 +func pnTag(tag string) C.pn_delivery_tag_t {
 +	bytes := []byte(tag)
 +	return C.pn_dtag(cPtr(bytes), cLen(bytes))
 +}
 +
 +func (l Link) Delivery(tag string) Delivery {
 +	return Delivery{C.pn_delivery(l.pn, pnTag(tag))}
 +}
 +
 +func (l Link) Connection() Connection { return l.Session().Connection() }
 +
 +// Human-readable link description including name, source, target and direction.
 +func (l Link) String() string {
 +	switch {
 +	case l.IsNil():
 +		return fmt.Sprintf("<nil-link>")
 +	case l.IsSender():
 +		return fmt.Sprintf("%s(%s->%s)", l.Name(), l.Source().Address(), l.Target().Address())
 +	default:
 +		return fmt.Sprintf("%s(%s<-%s)", l.Name(), l.Target().Address(), l.Source().Address())
 +	}
 +}
 +
 +func (l Link) Type() string {
 +	if l.IsSender() {
 +		return "link(sender)"
 +	} else {
 +		return "link(receiver)"
 +	}
 +}
 +
++// IsDrain calls pn_link_get_drain(), it conflicts with pn_link_drain() under the normal mapping.
++func (l Link) IsDrain() bool {
++	return bool(C.pn_link_get_drain(l.pn))
++}
++
 +func cPtr(b []byte) *C.char {
 +	if len(b) == 0 {
 +		return nil
 +	}
 +	return (*C.char)(unsafe.Pointer(&b[0]))
 +}
 +
 +func cLen(b []byte) C.size_t {
 +	return C.size_t(len(b))
 +}
 +
 +func (s Session) Sender(name string) Link {
 +	cname := C.CString(name)
 +	defer C.free(unsafe.Pointer(cname))
 +	return Link{C.pn_sender(s.pn, cname)}
 +}
 +
 +func (s Session) Receiver(name string) Link {
 +	cname := C.CString(name)
 +	defer C.free(unsafe.Pointer(cname))
 +	return Link{C.pn_receiver(s.pn, cname)}
 +}
 +
++func (t Transport) String() string {
++	return fmt.Sprintf("(Transport)(%p)", t.CPtr())
++}
++
 +// Unique (per process) string identifier for a connection, useful for debugging.
 +func (c Connection) String() string {
- 	return fmt.Sprintf("%x", c.pn)
++	// Use the transport address to match the default transport logs from PN_TRACE.
++	return fmt.Sprintf("(Connection)(%p)", c.Transport().CPtr())
 +}
 +
 +func (c Connection) Type() string {
 +	return "connection"
 +}
 +
 +// Head functions don't follow the normal naming conventions so missed by the generator.
 +
 +func (c Connection) LinkHead(s State) Link {
 +	return Link{C.pn_link_head(c.pn, C.pn_state_t(s))}
 +}
 +
 +func (c Connection) SessionHead(s State) Session {
 +	return Session{C.pn_session_head(c.pn, C.pn_state_t(s))}
 +}
 +
 +func (c Connection) Links(state State) (links []Link) {
 +	for l := c.LinkHead(state); !l.IsNil(); l = l.Next(state) {
 +		links = append(links, l)
 +	}
 +	return
 +}
 +
 +func (c Connection) Sessions(state State) (sessions []Session) {
 +	for s := c.SessionHead(state); !s.IsNil(); s = s.Next(state) {
 +		sessions = append(sessions, s)
 +	}
 +	return
 +}
 +
++// SetPassword takes []byte not string because it is impossible to erase a string
++// from memory reliably. Proton will not keep the password in memory longer than
++// needed, the caller should overwrite their copy on return.
++//
++// The password must not contain embedded nul characters, a trailing nul is ignored.
++func (c Connection) SetPassword(password []byte) {
++	if len(password) == 0 || password[len(password)-1] != 0 {
++		password = append(password, 0) // Proton requires a terminating null.
++	}
++	C.pn_connection_set_password(c.pn, (*C.char)(unsafe.Pointer(&password[0])))
++}
++
 +func (s Session) String() string {
- 	return fmt.Sprintf("%s/%p", s.Connection(), s.pn)
++	return fmt.Sprintf("(Session)(%p)", s.pn) // TODO aconway 2016-09-12: should print channel number.
 +}
 +
 +func (s Session) Type() string { return "session" }
 +
 +// Error returns an instance of amqp.Error or nil.
 +func (c Condition) Error() error {
 +	if c.IsNil() || !c.IsSet() {
 +		return nil
 +	}
 +	return amqp.Error{Name: c.Name(), Description: c.Description()}
 +}
 +
 +// Set a Go error into a condition.
 +// If it is not an amqp.Condition use the error type as name, error string as description.
 +func (c Condition) SetError(err error) {
 +	if err != nil {
 +		if cond, ok := err.(amqp.Error); ok {
 +			c.SetName(cond.Name)
 +			c.SetDescription(cond.Description)
 +		} else {
 +			c.SetName(reflect.TypeOf(err).Name())
 +			c.SetDescription(err.Error())
 +		}
 +	}
 +}
 +
 +func (c Connection) Session() (Session, error) {
 +	s := Session{C.pn_session(c.pn)}
 +	if s.IsNil() {
 +		return s, Connection(c).Error()
 +	}
 +	return s, nil
 +}
 +
 +// pnTime converts Go time.Time to Proton millisecond Unix time.
- func pnTime(t time.Time) C.pn_timestamp_t {
- 	secs := t.Unix()
- 	// Note: sub-second accuracy is not guaraunteed if the Unix time in
- 	// nanoseconds cannot be represented by an int64 (sometime around year 2260)
- 	msecs := (t.UnixNano() % int64(time.Second)) / int64(time.Millisecond)
- 	return C.pn_timestamp_t(secs*1000 + msecs)
++//
++// Note: t.isZero() is converted to C.pn_timestamp_t(0) and vice-versa. These
++// are used as "not set" sentinel values by the Go and Proton APIs, so it is
++// better to conserve the "zeroness" even though they don't represent the same
++// time instant.
++//
++func pnTime(t time.Time) (pnt C.pn_timestamp_t) {
++	if !t.IsZero() {
++		pnt = C.pn_timestamp_t(t.Unix()*1000 + int64(t.Nanosecond())/int64(time.Millisecond))
++	}
++	return
 +}
 +
 +// goTime converts a pn_timestamp_t to a Go time.Time.
- func goTime(t C.pn_timestamp_t) time.Time {
- 	secs := int64(t) / 1000
- 	nsecs := (int64(t) % 1000) * int64(time.Millisecond)
- 	return time.Unix(secs, nsecs)
++//
++// Note: C.pn_timestamp_t(0) is converted to a zero time.Time and
++// vice-versa. These are used as "not set" sentinel values by the Go and Proton
++// APIs, so it is better to conserve the "zeroness" even though they don't
++// represent the same time instant.
++//
++func goTime(pnt C.pn_timestamp_t) (t time.Time) {
++	if pnt != 0 {
++		t = time.Unix(int64(pnt/1000), int64(pnt%1000)*int64(time.Millisecond))
++	}
++	return
 +}
 +
 +// Special treatment for Transport.Head, return value is unsafe.Pointer not string
 +func (t Transport) Head() unsafe.Pointer {
 +	return unsafe.Pointer(C.pn_transport_head(t.pn))
 +}
 +
++// Special treatment for Transport.Tail, return value is unsafe.Pointer not string
++func (t Transport) Tail() unsafe.Pointer {
++	return unsafe.Pointer(C.pn_transport_tail(t.pn))
++}
++
 +// Special treatment for Transport.Push, takes []byte instead of char*, size
 +func (t Transport) Push(bytes []byte) int {
 +	return int(C.pn_transport_push(t.pn, (*C.char)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes))))
 +}
++
++// Get the SASL object for the transport.
++func (t Transport) SASL() SASL {
++	return SASL{C.pn_sasl(t.pn)}
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/proton/wrappers_gen.go
----------------------------------------------------------------------
diff --cc proton/wrappers_gen.go
index 183d6ec,0000000..19bfde2
mode 100644,000000..100644
--- a/proton/wrappers_gen.go
+++ b/proton/wrappers_gen.go
@@@ -1,875 -1,0 +1,937 @@@
 +/*
 +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.
 +*/
 +
 +//
 +// NOTE: DO NOT EDIT. This file was generated by genwrap.go from the proton header files.
 +// Update the generator and re-run if you need to modify this code.
 +//
 +
 +package proton
 +
 +import (
 +	"time"
 +	"unsafe"
 +)
 +
 +// #include <proton/types.h>
 +// #include <proton/error.h>
 +// #include <proton/condition.h>
 +// #include <proton/event.h>
 +// #include <stdlib.h>
 +// #include <proton/session.h>
 +// #include <proton/link.h>
 +// #include <proton/delivery.h>
 +// #include <proton/disposition.h>
 +// #include <proton/condition.h>
 +// #include <proton/terminus.h>
 +// #include <proton/connection.h>
 +// #include <proton/transport.h>
++// #include <proton/sasl.h>
 +import "C"
 +
 +type EventType int
 +
 +const (
 +	EConnectionInit         EventType = C.PN_CONNECTION_INIT
 +	EConnectionBound        EventType = C.PN_CONNECTION_BOUND
 +	EConnectionUnbound      EventType = C.PN_CONNECTION_UNBOUND
 +	EConnectionLocalOpen    EventType = C.PN_CONNECTION_LOCAL_OPEN
 +	EConnectionRemoteOpen   EventType = C.PN_CONNECTION_REMOTE_OPEN
 +	EConnectionLocalClose   EventType = C.PN_CONNECTION_LOCAL_CLOSE
 +	EConnectionRemoteClose  EventType = C.PN_CONNECTION_REMOTE_CLOSE
 +	EConnectionFinal        EventType = C.PN_CONNECTION_FINAL
 +	ESessionInit            EventType = C.PN_SESSION_INIT
 +	ESessionLocalOpen       EventType = C.PN_SESSION_LOCAL_OPEN
 +	ESessionRemoteOpen      EventType = C.PN_SESSION_REMOTE_OPEN
 +	ESessionLocalClose      EventType = C.PN_SESSION_LOCAL_CLOSE
 +	ESessionRemoteClose     EventType = C.PN_SESSION_REMOTE_CLOSE
 +	ESessionFinal           EventType = C.PN_SESSION_FINAL
 +	ELinkInit               EventType = C.PN_LINK_INIT
 +	ELinkLocalOpen          EventType = C.PN_LINK_LOCAL_OPEN
 +	ELinkRemoteOpen         EventType = C.PN_LINK_REMOTE_OPEN
 +	ELinkLocalClose         EventType = C.PN_LINK_LOCAL_CLOSE
 +	ELinkRemoteClose        EventType = C.PN_LINK_REMOTE_CLOSE
 +	ELinkLocalDetach        EventType = C.PN_LINK_LOCAL_DETACH
 +	ELinkRemoteDetach       EventType = C.PN_LINK_REMOTE_DETACH
 +	ELinkFlow               EventType = C.PN_LINK_FLOW
 +	ELinkFinal              EventType = C.PN_LINK_FINAL
 +	EDelivery               EventType = C.PN_DELIVERY
 +	ETransport              EventType = C.PN_TRANSPORT
 +	ETransportAuthenticated EventType = C.PN_TRANSPORT_AUTHENTICATED
 +	ETransportError         EventType = C.PN_TRANSPORT_ERROR
 +	ETransportHeadClosed    EventType = C.PN_TRANSPORT_HEAD_CLOSED
 +	ETransportTailClosed    EventType = C.PN_TRANSPORT_TAIL_CLOSED
 +	ETransportClosed        EventType = C.PN_TRANSPORT_CLOSED
 +)
 +
 +func (e EventType) String() string {
 +	switch e {
 +
 +	case C.PN_CONNECTION_INIT:
 +		return "ConnectionInit"
 +	case C.PN_CONNECTION_BOUND:
 +		return "ConnectionBound"
 +	case C.PN_CONNECTION_UNBOUND:
 +		return "ConnectionUnbound"
 +	case C.PN_CONNECTION_LOCAL_OPEN:
 +		return "ConnectionLocalOpen"
 +	case C.PN_CONNECTION_REMOTE_OPEN:
 +		return "ConnectionRemoteOpen"
 +	case C.PN_CONNECTION_LOCAL_CLOSE:
 +		return "ConnectionLocalClose"
 +	case C.PN_CONNECTION_REMOTE_CLOSE:
 +		return "ConnectionRemoteClose"
 +	case C.PN_CONNECTION_FINAL:
 +		return "ConnectionFinal"
 +	case C.PN_SESSION_INIT:
 +		return "SessionInit"
 +	case C.PN_SESSION_LOCAL_OPEN:
 +		return "SessionLocalOpen"
 +	case C.PN_SESSION_REMOTE_OPEN:
 +		return "SessionRemoteOpen"
 +	case C.PN_SESSION_LOCAL_CLOSE:
 +		return "SessionLocalClose"
 +	case C.PN_SESSION_REMOTE_CLOSE:
 +		return "SessionRemoteClose"
 +	case C.PN_SESSION_FINAL:
 +		return "SessionFinal"
 +	case C.PN_LINK_INIT:
 +		return "LinkInit"
 +	case C.PN_LINK_LOCAL_OPEN:
 +		return "LinkLocalOpen"
 +	case C.PN_LINK_REMOTE_OPEN:
 +		return "LinkRemoteOpen"
 +	case C.PN_LINK_LOCAL_CLOSE:
 +		return "LinkLocalClose"
 +	case C.PN_LINK_REMOTE_CLOSE:
 +		return "LinkRemoteClose"
 +	case C.PN_LINK_LOCAL_DETACH:
 +		return "LinkLocalDetach"
 +	case C.PN_LINK_REMOTE_DETACH:
 +		return "LinkRemoteDetach"
 +	case C.PN_LINK_FLOW:
 +		return "LinkFlow"
 +	case C.PN_LINK_FINAL:
 +		return "LinkFinal"
 +	case C.PN_DELIVERY:
 +		return "Delivery"
 +	case C.PN_TRANSPORT:
 +		return "Transport"
 +	case C.PN_TRANSPORT_AUTHENTICATED:
 +		return "TransportAuthenticated"
 +	case C.PN_TRANSPORT_ERROR:
 +		return "TransportError"
 +	case C.PN_TRANSPORT_HEAD_CLOSED:
 +		return "TransportHeadClosed"
 +	case C.PN_TRANSPORT_TAIL_CLOSED:
 +		return "TransportTailClosed"
 +	case C.PN_TRANSPORT_CLOSED:
 +		return "TransportClosed"
 +	}
 +	return "Unknown"
 +}
 +
 +// Wrappers for declarations in session.h
 +
 +type Session struct{ pn *C.pn_session_t }
 +
 +func (s Session) IsNil() bool          { return s.pn == nil }
 +func (s Session) CPtr() unsafe.Pointer { return unsafe.Pointer(s.pn) }
 +func (s Session) Free() {
 +	C.pn_session_free(s.pn)
 +}
 +func (s Session) State() State {
 +	return State(C.pn_session_state(s.pn))
 +}
 +func (s Session) Error() error {
 +	return PnError(C.pn_session_error(s.pn))
 +}
 +func (s Session) Condition() Condition {
 +	return Condition{C.pn_session_condition(s.pn)}
 +}
 +func (s Session) RemoteCondition() Condition {
 +	return Condition{C.pn_session_remote_condition(s.pn)}
 +}
 +func (s Session) Connection() Connection {
 +	return Connection{C.pn_session_connection(s.pn)}
 +}
 +func (s Session) Open() {
 +	C.pn_session_open(s.pn)
 +}
 +func (s Session) Close() {
 +	C.pn_session_close(s.pn)
 +}
 +func (s Session) IncomingCapacity() uint {
 +	return uint(C.pn_session_get_incoming_capacity(s.pn))
 +}
 +func (s Session) SetIncomingCapacity(capacity uint) {
 +	C.pn_session_set_incoming_capacity(s.pn, C.size_t(capacity))
 +}
 +func (s Session) OutgoingWindow() uint {
 +	return uint(C.pn_session_get_outgoing_window(s.pn))
 +}
 +func (s Session) SetOutgoingWindow(window uint) {
 +	C.pn_session_set_outgoing_window(s.pn, C.size_t(window))
 +}
 +func (s Session) OutgoingBytes() uint {
 +	return uint(C.pn_session_outgoing_bytes(s.pn))
 +}
 +func (s Session) IncomingBytes() uint {
 +	return uint(C.pn_session_incoming_bytes(s.pn))
 +}
 +func (s Session) Next(state State) Session {
 +	return Session{C.pn_session_next(s.pn, C.pn_state_t(state))}
 +}
 +
 +// Wrappers for declarations in link.h
 +
 +type SndSettleMode C.pn_snd_settle_mode_t
 +
 +const (
 +	SndUnsettled SndSettleMode = C.PN_SND_UNSETTLED
 +	SndSettled   SndSettleMode = C.PN_SND_SETTLED
 +	SndMixed     SndSettleMode = C.PN_SND_MIXED
 +)
 +
 +func (e SndSettleMode) String() string {
 +	switch e {
 +
 +	case C.PN_SND_UNSETTLED:
 +		return "SndUnsettled"
 +	case C.PN_SND_SETTLED:
 +		return "SndSettled"
 +	case C.PN_SND_MIXED:
 +		return "SndMixed"
 +	}
 +	return "unknown"
 +}
 +
 +type RcvSettleMode C.pn_rcv_settle_mode_t
 +
 +const (
 +	RcvFirst  RcvSettleMode = C.PN_RCV_FIRST
 +	RcvSecond RcvSettleMode = C.PN_RCV_SECOND
 +)
 +
 +func (e RcvSettleMode) String() string {
 +	switch e {
 +
 +	case C.PN_RCV_FIRST:
 +		return "RcvFirst"
 +	case C.PN_RCV_SECOND:
 +		return "RcvSecond"
 +	}
 +	return "unknown"
 +}
 +
 +type Link struct{ pn *C.pn_link_t }
 +
 +func (l Link) IsNil() bool          { return l.pn == nil }
 +func (l Link) CPtr() unsafe.Pointer { return unsafe.Pointer(l.pn) }
 +func (l Link) Free() {
 +	C.pn_link_free(l.pn)
 +}
 +func (l Link) Name() string {
 +	return C.GoString(C.pn_link_name(l.pn))
 +}
 +func (l Link) IsSender() bool {
 +	return bool(C.pn_link_is_sender(l.pn))
 +}
 +func (l Link) IsReceiver() bool {
 +	return bool(C.pn_link_is_receiver(l.pn))
 +}
 +func (l Link) State() State {
 +	return State(C.pn_link_state(l.pn))
 +}
 +func (l Link) Error() error {
 +	return PnError(C.pn_link_error(l.pn))
 +}
 +func (l Link) Condition() Condition {
 +	return Condition{C.pn_link_condition(l.pn)}
 +}
 +func (l Link) RemoteCondition() Condition {
 +	return Condition{C.pn_link_remote_condition(l.pn)}
 +}
 +func (l Link) Session() Session {
 +	return Session{C.pn_link_session(l.pn)}
 +}
 +func (l Link) Next(state State) Link {
 +	return Link{C.pn_link_next(l.pn, C.pn_state_t(state))}
 +}
 +func (l Link) Open() {
 +	C.pn_link_open(l.pn)
 +}
 +func (l Link) Close() {
 +	C.pn_link_close(l.pn)
 +}
 +func (l Link) Detach() {
 +	C.pn_link_detach(l.pn)
 +}
 +func (l Link) Source() Terminus {
 +	return Terminus{C.pn_link_source(l.pn)}
 +}
 +func (l Link) Target() Terminus {
 +	return Terminus{C.pn_link_target(l.pn)}
 +}
 +func (l Link) RemoteSource() Terminus {
 +	return Terminus{C.pn_link_remote_source(l.pn)}
 +}
 +func (l Link) RemoteTarget() Terminus {
 +	return Terminus{C.pn_link_remote_target(l.pn)}
 +}
 +func (l Link) Current() Delivery {
 +	return Delivery{C.pn_link_current(l.pn)}
 +}
 +func (l Link) Advance() bool {
 +	return bool(C.pn_link_advance(l.pn))
 +}
 +func (l Link) Credit() int {
 +	return int(C.pn_link_credit(l.pn))
 +}
 +func (l Link) Queued() int {
 +	return int(C.pn_link_queued(l.pn))
 +}
 +func (l Link) RemoteCredit() int {
 +	return int(C.pn_link_remote_credit(l.pn))
 +}
- func (l Link) IsDrain() bool {
- 	return bool(C.pn_link_get_drain(l.pn))
- }
 +func (l Link) Drained() int {
 +	return int(C.pn_link_drained(l.pn))
 +}
 +func (l Link) Available() int {
 +	return int(C.pn_link_available(l.pn))
 +}
 +func (l Link) SndSettleMode() SndSettleMode {
 +	return SndSettleMode(C.pn_link_snd_settle_mode(l.pn))
 +}
 +func (l Link) RcvSettleMode() RcvSettleMode {
 +	return RcvSettleMode(C.pn_link_rcv_settle_mode(l.pn))
 +}
 +func (l Link) SetSndSettleMode(mode SndSettleMode) {
 +	C.pn_link_set_snd_settle_mode(l.pn, C.pn_snd_settle_mode_t(mode))
 +}
 +func (l Link) SetRcvSettleMode(mode RcvSettleMode) {
 +	C.pn_link_set_rcv_settle_mode(l.pn, C.pn_rcv_settle_mode_t(mode))
 +}
 +func (l Link) RemoteSndSettleMode() SndSettleMode {
 +	return SndSettleMode(C.pn_link_remote_snd_settle_mode(l.pn))
 +}
 +func (l Link) RemoteRcvSettleMode() RcvSettleMode {
 +	return RcvSettleMode(C.pn_link_remote_rcv_settle_mode(l.pn))
 +}
 +func (l Link) Unsettled() int {
 +	return int(C.pn_link_unsettled(l.pn))
 +}
 +func (l Link) Offered(credit int) {
 +	C.pn_link_offered(l.pn, C.int(credit))
 +}
 +func (l Link) Flow(credit int) {
 +	C.pn_link_flow(l.pn, C.int(credit))
 +}
 +func (l Link) Drain(credit int) {
 +	C.pn_link_drain(l.pn, C.int(credit))
 +}
 +func (l Link) SetDrain(drain bool) {
 +	C.pn_link_set_drain(l.pn, C.bool(drain))
 +}
 +func (l Link) Draining() bool {
 +	return bool(C.pn_link_draining(l.pn))
 +}
 +
 +// Wrappers for declarations in delivery.h
 +
 +type Delivery struct{ pn *C.pn_delivery_t }
 +
 +func (d Delivery) IsNil() bool          { return d.pn == nil }
 +func (d Delivery) CPtr() unsafe.Pointer { return unsafe.Pointer(d.pn) }
 +func (d Delivery) Tag() DeliveryTag {
 +	return DeliveryTag{C.pn_delivery_tag(d.pn)}
 +}
 +func (d Delivery) Link() Link {
 +	return Link{C.pn_delivery_link(d.pn)}
 +}
 +func (d Delivery) Local() Disposition {
 +	return Disposition{C.pn_delivery_local(d.pn)}
 +}
 +func (d Delivery) LocalState() uint64 {
 +	return uint64(C.pn_delivery_local_state(d.pn))
 +}
 +func (d Delivery) Remote() Disposition {
 +	return Disposition{C.pn_delivery_remote(d.pn)}
 +}
 +func (d Delivery) RemoteState() uint64 {
 +	return uint64(C.pn_delivery_remote_state(d.pn))
 +}
 +func (d Delivery) Settled() bool {
 +	return bool(C.pn_delivery_settled(d.pn))
 +}
 +func (d Delivery) Pending() uint {
 +	return uint(C.pn_delivery_pending(d.pn))
 +}
 +func (d Delivery) Partial() bool {
 +	return bool(C.pn_delivery_partial(d.pn))
 +}
 +func (d Delivery) Writable() bool {
 +	return bool(C.pn_delivery_writable(d.pn))
 +}
 +func (d Delivery) Readable() bool {
 +	return bool(C.pn_delivery_readable(d.pn))
 +}
 +func (d Delivery) Updated() bool {
 +	return bool(C.pn_delivery_updated(d.pn))
 +}
 +func (d Delivery) Update(state uint64) {
 +	C.pn_delivery_update(d.pn, C.uint64_t(state))
 +}
 +func (d Delivery) Clear() {
 +	C.pn_delivery_clear(d.pn)
 +}
 +func (d Delivery) Current() bool {
 +	return bool(C.pn_delivery_current(d.pn))
 +}
 +func (d Delivery) Settle() {
 +	C.pn_delivery_settle(d.pn)
 +}
 +func (d Delivery) Dump() {
 +	C.pn_delivery_dump(d.pn)
 +}
 +func (d Delivery) Buffered() bool {
 +	return bool(C.pn_delivery_buffered(d.pn))
 +}
 +
 +// Wrappers for declarations in disposition.h
 +
 +type Disposition struct{ pn *C.pn_disposition_t }
 +
 +func (d Disposition) IsNil() bool          { return d.pn == nil }
 +func (d Disposition) CPtr() unsafe.Pointer { return unsafe.Pointer(d.pn) }
 +func (d Disposition) Type() uint64 {
 +	return uint64(C.pn_disposition_type(d.pn))
 +}
 +func (d Disposition) Condition() Condition {
 +	return Condition{C.pn_disposition_condition(d.pn)}
 +}
 +func (d Disposition) Data() Data {
 +	return Data{C.pn_disposition_data(d.pn)}
 +}
 +func (d Disposition) SectionNumber() uint16 {
 +	return uint16(C.pn_disposition_get_section_number(d.pn))
 +}
 +func (d Disposition) SetSectionNumber(section_number uint16) {
 +	C.pn_disposition_set_section_number(d.pn, C.uint32_t(section_number))
 +}
 +func (d Disposition) SectionOffset() uint64 {
 +	return uint64(C.pn_disposition_get_section_offset(d.pn))
 +}
 +func (d Disposition) SetSectionOffset(section_offset uint64) {
 +	C.pn_disposition_set_section_offset(d.pn, C.uint64_t(section_offset))
 +}
 +func (d Disposition) IsFailed() bool {
 +	return bool(C.pn_disposition_is_failed(d.pn))
 +}
 +func (d Disposition) SetFailed(failed bool) {
 +	C.pn_disposition_set_failed(d.pn, C.bool(failed))
 +}
 +func (d Disposition) IsUndeliverable() bool {
 +	return bool(C.pn_disposition_is_undeliverable(d.pn))
 +}
 +func (d Disposition) SetUndeliverable(undeliverable bool) {
 +	C.pn_disposition_set_undeliverable(d.pn, C.bool(undeliverable))
 +}
 +func (d Disposition) Annotations() Data {
 +	return Data{C.pn_disposition_annotations(d.pn)}
 +}
 +
 +// Wrappers for declarations in condition.h
 +
 +type Condition struct{ pn *C.pn_condition_t }
 +
 +func (c Condition) IsNil() bool          { return c.pn == nil }
 +func (c Condition) CPtr() unsafe.Pointer { return unsafe.Pointer(c.pn) }
 +func (c Condition) IsSet() bool {
 +	return bool(C.pn_condition_is_set(c.pn))
 +}
 +func (c Condition) Clear() {
 +	C.pn_condition_clear(c.pn)
 +}
 +func (c Condition) Name() string {
 +	return C.GoString(C.pn_condition_get_name(c.pn))
 +}
 +func (c Condition) SetName(name string) int {
 +	nameC := C.CString(name)
 +	defer C.free(unsafe.Pointer(nameC))
 +
 +	return int(C.pn_condition_set_name(c.pn, nameC))
 +}
 +func (c Condition) Description() string {
 +	return C.GoString(C.pn_condition_get_description(c.pn))
 +}
 +func (c Condition) SetDescription(description string) int {
 +	descriptionC := C.CString(description)
 +	defer C.free(unsafe.Pointer(descriptionC))
 +
 +	return int(C.pn_condition_set_description(c.pn, descriptionC))
 +}
 +func (c Condition) Info() Data {
 +	return Data{C.pn_condition_info(c.pn)}
 +}
 +func (c Condition) IsRedirect() bool {
 +	return bool(C.pn_condition_is_redirect(c.pn))
 +}
 +func (c Condition) RedirectHost() string {
 +	return C.GoString(C.pn_condition_redirect_host(c.pn))
 +}
 +func (c Condition) RedirectPort() int {
 +	return int(C.pn_condition_redirect_port(c.pn))
 +}
 +
 +// Wrappers for declarations in terminus.h
 +
 +type TerminusType C.pn_terminus_type_t
 +
 +const (
 +	Unspecified TerminusType = C.PN_UNSPECIFIED
 +	Source      TerminusType = C.PN_SOURCE
 +	Target      TerminusType = C.PN_TARGET
 +	Coordinator TerminusType = C.PN_COORDINATOR
 +)
 +
 +func (e TerminusType) String() string {
 +	switch e {
 +
 +	case C.PN_UNSPECIFIED:
 +		return "Unspecified"
 +	case C.PN_SOURCE:
 +		return "Source"
 +	case C.PN_TARGET:
 +		return "Target"
 +	case C.PN_COORDINATOR:
 +		return "Coordinator"
 +	}
 +	return "unknown"
 +}
 +
 +type Durability C.pn_durability_t
 +
 +const (
 +	Nondurable    Durability = C.PN_NONDURABLE
 +	Configuration Durability = C.PN_CONFIGURATION
 +	Deliveries    Durability = C.PN_DELIVERIES
 +)
 +
 +func (e Durability) String() string {
 +	switch e {
 +
 +	case C.PN_NONDURABLE:
 +		return "Nondurable"
 +	case C.PN_CONFIGURATION:
 +		return "Configuration"
 +	case C.PN_DELIVERIES:
 +		return "Deliveries"
 +	}
 +	return "unknown"
 +}
 +
 +type ExpiryPolicy C.pn_expiry_policy_t
 +
 +const (
 +	ExpireWithLink       ExpiryPolicy = C.PN_EXPIRE_WITH_LINK
 +	ExpireWithSession    ExpiryPolicy = C.PN_EXPIRE_WITH_SESSION
 +	ExpireWithConnection ExpiryPolicy = C.PN_EXPIRE_WITH_CONNECTION
 +	ExpireNever          ExpiryPolicy = C.PN_EXPIRE_NEVER
 +)
 +
 +func (e ExpiryPolicy) String() string {
 +	switch e {
 +
 +	case C.PN_EXPIRE_WITH_LINK:
 +		return "ExpireWithLink"
 +	case C.PN_EXPIRE_WITH_SESSION:
 +		return "ExpireWithSession"
 +	case C.PN_EXPIRE_WITH_CONNECTION:
 +		return "ExpireWithConnection"
 +	case C.PN_EXPIRE_NEVER:
 +		return "ExpireNever"
 +	}
 +	return "unknown"
 +}
 +
 +type DistributionMode C.pn_distribution_mode_t
 +
 +const (
 +	DistModeUnspecified DistributionMode = C.PN_DIST_MODE_UNSPECIFIED
 +	DistModeCopy        DistributionMode = C.PN_DIST_MODE_COPY
 +	DistModeMove        DistributionMode = C.PN_DIST_MODE_MOVE
 +)
 +
 +func (e DistributionMode) String() string {
 +	switch e {
 +
 +	case C.PN_DIST_MODE_UNSPECIFIED:
 +		return "DistModeUnspecified"
 +	case C.PN_DIST_MODE_COPY:
 +		return "DistModeCopy"
 +	case C.PN_DIST_MODE_MOVE:
 +		return "DistModeMove"
 +	}
 +	return "unknown"
 +}
 +
 +type Terminus struct{ pn *C.pn_terminus_t }
 +
 +func (t Terminus) IsNil() bool          { return t.pn == nil }
 +func (t Terminus) CPtr() unsafe.Pointer { return unsafe.Pointer(t.pn) }
 +func (t Terminus) Type() TerminusType {
 +	return TerminusType(C.pn_terminus_get_type(t.pn))
 +}
 +func (t Terminus) SetType(type_ TerminusType) int {
 +	return int(C.pn_terminus_set_type(t.pn, C.pn_terminus_type_t(type_)))
 +}
 +func (t Terminus) Address() string {
 +	return C.GoString(C.pn_terminus_get_address(t.pn))
 +}
 +func (t Terminus) SetAddress(address string) int {
 +	addressC := C.CString(address)
 +	defer C.free(unsafe.Pointer(addressC))
 +
 +	return int(C.pn_terminus_set_address(t.pn, addressC))
 +}
 +func (t Terminus) SetDistributionMode(mode DistributionMode) int {
 +	return int(C.pn_terminus_set_distribution_mode(t.pn, C.pn_distribution_mode_t(mode)))
 +}
 +func (t Terminus) Durability() Durability {
 +	return Durability(C.pn_terminus_get_durability(t.pn))
 +}
 +func (t Terminus) SetDurability(durability Durability) int {
 +	return int(C.pn_terminus_set_durability(t.pn, C.pn_durability_t(durability)))
 +}
 +func (t Terminus) ExpiryPolicy() ExpiryPolicy {
 +	return ExpiryPolicy(C.pn_terminus_get_expiry_policy(t.pn))
 +}
 +func (t Terminus) SetExpiryPolicy(policy ExpiryPolicy) int {
 +	return int(C.pn_terminus_set_expiry_policy(t.pn, C.pn_expiry_policy_t(policy)))
 +}
 +func (t Terminus) Timeout() time.Duration {
 +	return (time.Duration(C.pn_terminus_get_timeout(t.pn)) * time.Second)
 +}
 +func (t Terminus) SetTimeout(timeout time.Duration) int {
 +	return int(C.pn_terminus_set_timeout(t.pn, C.pn_seconds_t(timeout)))
 +}
 +func (t Terminus) IsDynamic() bool {
 +	return bool(C.pn_terminus_is_dynamic(t.pn))
 +}
 +func (t Terminus) SetDynamic(dynamic bool) int {
 +	return int(C.pn_terminus_set_dynamic(t.pn, C.bool(dynamic)))
 +}
 +func (t Terminus) Properties() Data {
 +	return Data{C.pn_terminus_properties(t.pn)}
 +}
 +func (t Terminus) Capabilities() Data {
 +	return Data{C.pn_terminus_capabilities(t.pn)}
 +}
 +func (t Terminus) Outcomes() Data {
 +	return Data{C.pn_terminus_outcomes(t.pn)}
 +}
 +func (t Terminus) Filter() Data {
 +	return Data{C.pn_terminus_filter(t.pn)}
 +}
 +func (t Terminus) Copy(src Terminus) int {
 +	return int(C.pn_terminus_copy(t.pn, src.pn))
 +}
 +
 +// Wrappers for declarations in connection.h
 +
 +type Connection struct{ pn *C.pn_connection_t }
 +
 +func (c Connection) IsNil() bool          { return c.pn == nil }
 +func (c Connection) CPtr() unsafe.Pointer { return unsafe.Pointer(c.pn) }
 +func (c Connection) Free() {
 +	C.pn_connection_free(c.pn)
 +}
 +func (c Connection) Release() {
 +	C.pn_connection_release(c.pn)
 +}
 +func (c Connection) Error() error {
 +	return PnError(C.pn_connection_error(c.pn))
 +}
 +func (c Connection) State() State {
 +	return State(C.pn_connection_state(c.pn))
 +}
 +func (c Connection) Open() {
 +	C.pn_connection_open(c.pn)
 +}
 +func (c Connection) Close() {
 +	C.pn_connection_close(c.pn)
 +}
 +func (c Connection) Reset() {
 +	C.pn_connection_reset(c.pn)
 +}
 +func (c Connection) Condition() Condition {
 +	return Condition{C.pn_connection_condition(c.pn)}
 +}
 +func (c Connection) RemoteCondition() Condition {
 +	return Condition{C.pn_connection_remote_condition(c.pn)}
 +}
 +func (c Connection) Container() string {
 +	return C.GoString(C.pn_connection_get_container(c.pn))
 +}
 +func (c Connection) SetContainer(container string) {
 +	containerC := C.CString(container)
 +	defer C.free(unsafe.Pointer(containerC))
 +
 +	C.pn_connection_set_container(c.pn, containerC)
 +}
 +func (c Connection) SetUser(user string) {
 +	userC := C.CString(user)
 +	defer C.free(unsafe.Pointer(userC))
 +
 +	C.pn_connection_set_user(c.pn, userC)
 +}
- func (c Connection) SetPassword(password string) {
- 	passwordC := C.CString(password)
- 	defer C.free(unsafe.Pointer(passwordC))
- 
- 	C.pn_connection_set_password(c.pn, passwordC)
- }
 +func (c Connection) User() string {
 +	return C.GoString(C.pn_connection_get_user(c.pn))
 +}
 +func (c Connection) Hostname() string {
 +	return C.GoString(C.pn_connection_get_hostname(c.pn))
 +}
 +func (c Connection) SetHostname(hostname string) {
 +	hostnameC := C.CString(hostname)
 +	defer C.free(unsafe.Pointer(hostnameC))
 +
 +	C.pn_connection_set_hostname(c.pn, hostnameC)
 +}
 +func (c Connection) RemoteContainer() string {
 +	return C.GoString(C.pn_connection_remote_container(c.pn))
 +}
 +func (c Connection) RemoteHostname() string {
 +	return C.GoString(C.pn_connection_remote_hostname(c.pn))
 +}
 +func (c Connection) OfferedCapabilities() Data {
 +	return Data{C.pn_connection_offered_capabilities(c.pn)}
 +}
 +func (c Connection) DesiredCapabilities() Data {
 +	return Data{C.pn_connection_desired_capabilities(c.pn)}
 +}
 +func (c Connection) Properties() Data {
 +	return Data{C.pn_connection_properties(c.pn)}
 +}
 +func (c Connection) RemoteOfferedCapabilities() Data {
 +	return Data{C.pn_connection_remote_offered_capabilities(c.pn)}
 +}
 +func (c Connection) RemoteDesiredCapabilities() Data {
 +	return Data{C.pn_connection_remote_desired_capabilities(c.pn)}
 +}
 +func (c Connection) RemoteProperties() Data {
 +	return Data{C.pn_connection_remote_properties(c.pn)}
 +}
 +func (c Connection) Transport() Transport {
 +	return Transport{C.pn_connection_transport(c.pn)}
 +}
 +
 +// Wrappers for declarations in transport.h
 +
 +type Transport struct{ pn *C.pn_transport_t }
 +
 +func (t Transport) IsNil() bool          { return t.pn == nil }
 +func (t Transport) CPtr() unsafe.Pointer { return unsafe.Pointer(t.pn) }
 +func (t Transport) SetServer() {
 +	C.pn_transport_set_server(t.pn)
 +}
 +func (t Transport) Free() {
 +	C.pn_transport_free(t.pn)
 +}
 +func (t Transport) User() string {
 +	return C.GoString(C.pn_transport_get_user(t.pn))
 +}
 +func (t Transport) RequireAuth(required bool) {
 +	C.pn_transport_require_auth(t.pn, C.bool(required))
 +}
 +func (t Transport) IsAuthenticated() bool {
 +	return bool(C.pn_transport_is_authenticated(t.pn))
 +}
 +func (t Transport) RequireEncryption(required bool) {
 +	C.pn_transport_require_encryption(t.pn, C.bool(required))
 +}
 +func (t Transport) IsEncrypted() bool {
 +	return bool(C.pn_transport_is_encrypted(t.pn))
 +}
 +func (t Transport) Condition() Condition {
 +	return Condition{C.pn_transport_condition(t.pn)}
 +}
 +func (t Transport) Error() error {
 +	return PnError(C.pn_transport_error(t.pn))
 +}
 +func (t Transport) Bind(connection Connection) int {
 +	return int(C.pn_transport_bind(t.pn, connection.pn))
 +}
 +func (t Transport) Unbind() int {
 +	return int(C.pn_transport_unbind(t.pn))
 +}
 +func (t Transport) Log(message string) {
 +	messageC := C.CString(message)
 +	defer C.free(unsafe.Pointer(messageC))
 +
 +	C.pn_transport_log(t.pn, messageC)
 +}
 +func (t Transport) ChannelMax() uint32 {
 +	return uint32(C.pn_transport_get_channel_max(t.pn))
 +}
 +func (t Transport) SetChannelMax(channel_max uint32) int {
 +	return int(C.pn_transport_set_channel_max(t.pn, C.uint16_t(channel_max)))
 +}
 +func (t Transport) RemoteChannelMax() uint32 {
 +	return uint32(C.pn_transport_remote_channel_max(t.pn))
 +}
 +func (t Transport) MaxFrame() uint16 {
 +	return uint16(C.pn_transport_get_max_frame(t.pn))
 +}
 +func (t Transport) SetMaxFrame(size uint16) {
 +	C.pn_transport_set_max_frame(t.pn, C.uint32_t(size))
 +}
 +func (t Transport) RemoteMaxFrame() uint16 {
 +	return uint16(C.pn_transport_get_remote_max_frame(t.pn))
 +}
 +func (t Transport) IdleTimeout() time.Duration {
 +	return (time.Duration(C.pn_transport_get_idle_timeout(t.pn)) * time.Millisecond)
 +}
 +func (t Transport) SetIdleTimeout(timeout time.Duration) {
- 	C.pn_transport_set_idle_timeout(t.pn, C.pn_millis_t(timeout))
++	C.pn_transport_set_idle_timeout(t.pn, C.pn_millis_t(timeout/time.Millisecond))
 +}
 +func (t Transport) RemoteIdleTimeout() time.Duration {
 +	return (time.Duration(C.pn_transport_get_remote_idle_timeout(t.pn)) * time.Millisecond)
 +}
 +func (t Transport) Input(bytes string, available uint) int {
 +	bytesC := C.CString(bytes)
 +	defer C.free(unsafe.Pointer(bytesC))
 +
 +	return int(C.pn_transport_input(t.pn, bytesC, C.size_t(available)))
 +}
 +func (t Transport) Output(bytes string, size uint) int {
 +	bytesC := C.CString(bytes)
 +	defer C.free(unsafe.Pointer(bytesC))
 +
 +	return int(C.pn_transport_output(t.pn, bytesC, C.size_t(size)))
 +}
 +func (t Transport) Capacity() int {
 +	return int(C.pn_transport_capacity(t.pn))
 +}
- func (t Transport) Tail() string {
- 	return C.GoString(C.pn_transport_tail(t.pn))
- }
 +func (t Transport) Process(size uint) int {
 +	return int(C.pn_transport_process(t.pn, C.size_t(size)))
 +}
 +func (t Transport) CloseTail() int {
 +	return int(C.pn_transport_close_tail(t.pn))
 +}
 +func (t Transport) Pending() int {
 +	return int(C.pn_transport_pending(t.pn))
 +}
 +func (t Transport) Peek(dst string, size uint) int {
 +	dstC := C.CString(dst)
 +	defer C.free(unsafe.Pointer(dstC))
 +
 +	return int(C.pn_transport_peek(t.pn, dstC, C.size_t(size)))
 +}
 +func (t Transport) Pop(size uint) {
 +	C.pn_transport_pop(t.pn, C.size_t(size))
 +}
 +func (t Transport) CloseHead() int {
 +	return int(C.pn_transport_close_head(t.pn))
 +}
 +func (t Transport) Quiesced() bool {
 +	return bool(C.pn_transport_quiesced(t.pn))
 +}
 +func (t Transport) Closed() bool {
 +	return bool(C.pn_transport_closed(t.pn))
 +}
 +func (t Transport) Tick(now time.Time) time.Time {
 +	return goTime(C.pn_transport_tick(t.pn, pnTime(now)))
 +}
 +func (t Transport) Connection() Connection {
 +	return Connection{C.pn_transport_connection(t.pn)}
 +}
++
++// Wrappers for declarations in sasl.h
++
++type SASLOutcome C.pn_sasl_outcome_t
++
++const (
++	SASLNone SASLOutcome = C.PN_SASL_NONE
++	SASLOk   SASLOutcome = C.PN_SASL_OK
++	SASLAuth SASLOutcome = C.PN_SASL_AUTH
++	SASLSys  SASLOutcome = C.PN_SASL_SYS
++	SASLPerm SASLOutcome = C.PN_SASL_PERM
++	SASLTemp SASLOutcome = C.PN_SASL_TEMP
++)
++
++func (e SASLOutcome) String() string {
++	switch e {
++
++	case C.PN_SASL_NONE:
++		return "SASLNone"
++	case C.PN_SASL_OK:
++		return "SASLOk"
++	case C.PN_SASL_AUTH:
++		return "SASLAuth"
++	case C.PN_SASL_SYS:
++		return "SASLSys"
++	case C.PN_SASL_PERM:
++		return "SASLPerm"
++	case C.PN_SASL_TEMP:
++		return "SASLTemp"
++	}
++	return "unknown"
++}
++
++type SASL struct{ pn *C.pn_sasl_t }
++
++func (s SASL) IsNil() bool          { return s.pn == nil }
++func (s SASL) CPtr() unsafe.Pointer { return unsafe.Pointer(s.pn) }
++func (s SASL) Done(outcome SASLOutcome) {
++	C.pn_sasl_done(s.pn, C.pn_sasl_outcome_t(outcome))
++}
++func (s SASL) Outcome() SASLOutcome {
++	return SASLOutcome(C.pn_sasl_outcome(s.pn))
++}
++func (s SASL) User() string {
++	return C.GoString(C.pn_sasl_get_user(s.pn))
++}
++func (s SASL) Mech() string {
++	return C.GoString(C.pn_sasl_get_mech(s.pn))
++}
++func (s SASL) AllowedMechs(mechs string) {
++	mechsC := C.CString(mechs)
++	defer C.free(unsafe.Pointer(mechsC))
++
++	C.pn_sasl_allowed_mechs(s.pn, mechsC)
++}
++func (s SASL) SetAllowInsecureMechs(insecure bool) {
++	C.pn_sasl_set_allow_insecure_mechs(s.pn, C.bool(insecure))
++}
++func (s SASL) AllowInsecureMechs() bool {
++	return bool(C.pn_sasl_get_allow_insecure_mechs(s.pn))
++}
++func (s SASL) ConfigName(name string) {
++	nameC := C.CString(name)
++	defer C.free(unsafe.Pointer(nameC))
++
++	C.pn_sasl_config_name(s.pn, nameC)
++}
++func (s SASL) ConfigPath(path string) {
++	pathC := C.CString(path)
++	defer C.free(unsafe.Pointer(pathC))
++
++	C.pn_sasl_config_path(s.pn, pathC)
++}


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


[21/50] [abbrv] qpid-proton git commit: NO-JIRA: Oops - typo in previous commit

Posted by ac...@apache.org.
NO-JIRA: Oops - typo in previous commit


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

Branch: refs/heads/go1
Commit: 3dd69944fa3b55bb6daf5c0f104b4a02385a21d7
Parents: 0eafe3a
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Oct 14 14:15:50 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Oct 14 14:15:50 2016 -0400

----------------------------------------------------------------------
 appveyor.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3dd69944/appveyor.yml
----------------------------------------------------------------------
diff --git a/appveyor.yml b/appveyor.yml
index 368e9ad..fe87f0d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -8,7 +8,7 @@ cache:
 before_build:
 - mkdir BLD
 - cd BLD
-- cmake -G "Visual Studio 12" -DBUILD_PERL=no i-DBUILD_JAVA=no ..
+- cmake -G "Visual Studio 12" -DBUILD_PERL=no -DBUILD_JAVA=no ..
 - cd ..
 build:
   parallel: true


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


[23/50] [abbrv] qpid-proton git commit: NO-JIRA: go: fix parallel build from scratch

Posted by ac...@apache.org.
NO-JIRA: go: fix parallel build from scratch

Fixed example build dependencies to ensure the examples are not built
concurrently with the go packages they depend on. This was happening frequently
and causing errors in a parallel build from scratch.


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

Branch: refs/heads/go1
Commit: d91131a2b873260f0490b49895e7c1c868d40906
Parents: 05deba7
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Oct 18 13:25:27 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Oct 18 14:01:46 2016 -0400

----------------------------------------------------------------------
 examples/go/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d91131a2/examples/go/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/go/CMakeLists.txt b/examples/go/CMakeLists.txt
index 868b780..c9aba01 100644
--- a/examples/go/CMakeLists.txt
+++ b/examples/go/CMakeLists.txt
@@ -32,7 +32,7 @@ if(BUILD_GO)
     add_custom_target(${target} ALL
       COMMAND ${GO_BUILD} ${GO_EXAMPLE_FLAGS} -o ${output} ${CMAKE_CURRENT_SOURCE_DIR}/${example}.go
       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      DEPENDS qpid-proton)
+      DEPENDS go-build)
     list(APPEND example_targets ${target})
   endforeach()
 


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


[40/50] [abbrv] qpid-proton git commit: PROTON-1331: go: electron.Container.Dial returning (nil, nil)

Posted by ac...@apache.org.
PROTON-1331: go: electron.Container.Dial returning (nil, nil)

Scope error, creating new "err" variable instead of setting return variable.


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

Branch: refs/heads/go1
Commit: a17d30a2de5c68fd3ffa4d34da6cefa2e727bbdb
Parents: a1f0dd1
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Oct 24 20:22:25 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Oct 24 20:52:30 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/src/qpid.apache.org/electron/container.go | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a17d30a2/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
index 4cf5969..efb24ff 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
@@ -88,14 +88,16 @@ func (cont *container) Connection(conn net.Conn, opts ...ConnectionOption) (Conn
 }
 
 func (cont *container) Dial(network, address string, opts ...ConnectionOption) (c Connection, err error) {
-	if conn, err := net.Dial(network, address); err == nil {
+	conn, err := net.Dial(network, address)
+	if err == nil {
 		c, err = cont.Connection(conn, opts...)
 	}
 	return
 }
 
 func (cont *container) Accept(l net.Listener, opts ...ConnectionOption) (c Connection, err error) {
-	if conn, err := l.Accept(); err == nil {
+	conn, err := l.Accept()
+	if err == nil {
 		c, err = cont.Connection(conn, append(opts, Server())...)
 	}
 	return


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


[07/50] [abbrv] qpid-proton git commit: NO-JIRA: Fix delay in some python tests using the EchoServer.

Posted by ac...@apache.org.
NO-JIRA: Fix delay in some python tests using the EchoServer.

Server should close on transport_error as well as connection_closing.


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

Branch: refs/heads/go1
Commit: 4bd66a06e97d5b9f83afce5acb3ab590431b3ed8
Parents: ac06645
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Sep 27 14:50:06 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 27 14:50:06 2016 -0400

----------------------------------------------------------------------
 tests/python/proton_tests/utils.py | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4bd66a06/tests/python/proton_tests/utils.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/utils.py b/tests/python/proton_tests/utils.py
index c598251..0766eb9 100644
--- a/tests/python/proton_tests/utils.py
+++ b/tests/python/proton_tests/utils.py
@@ -70,6 +70,9 @@ class EchoServer(MessagingHandler, Thread):
     def on_connection_closing(self, event):
         self.acceptor.close()
 
+    def on_transport_error(self, event):
+        self.acceptor.close()
+
     def run(self):
         Container(self).run()
 


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


[17/50] [abbrv] qpid-proton git commit: PROTON-1323: update the .so major version to 10 for 0.16.0 on master

Posted by ac...@apache.org.
PROTON-1323: update the .so major version to 10 for 0.16.0 on master


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

Branch: refs/heads/go1
Commit: 1522100a8a0bd973593a7cda31938332e0d28963
Parents: c6d366c
Author: Robert Gemmell <ro...@apache.org>
Authored: Mon Oct 10 17:43:38 2016 +0100
Committer: Robert Gemmell <ro...@apache.org>
Committed: Mon Oct 10 17:43:38 2016 +0100

----------------------------------------------------------------------
 proton-c/soversion.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1522100a/proton-c/soversion.cmake
----------------------------------------------------------------------
diff --git a/proton-c/soversion.cmake b/proton-c/soversion.cmake
index 66686ec..58cc6f5 100644
--- a/proton-c/soversion.cmake
+++ b/proton-c/soversion.cmake
@@ -1,2 +1,2 @@
-set (PN_LIB_SOMAJOR 9)
+set (PN_LIB_SOMAJOR 10)
 set (PN_LIB_SOMINOR "0.0")


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


[39/50] [abbrv] qpid-proton git commit: PROTON-1332: go: electron client leaking links/sessions

Posted by ac...@apache.org.
PROTON-1332: go: electron client leaking links/sessions

Was not calling proton.Link/Session.Free() so links/sessions were never freed
till the connection was closed.


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

Branch: refs/heads/go1
Commit: f8c4c279126f2143c6f9e219cd0e1b6c27b6b7f0
Parents: a17d30a
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Oct 24 20:41:59 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Oct 24 20:52:30 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/src/qpid.apache.org/electron/handler.go | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f8c4c279/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
index 588ba79..af1efd6 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
@@ -159,6 +159,7 @@ func (h *handler) linkClosed(l proton.Link, err error) {
 	if link, ok := h.links[l]; ok {
 		_ = link.closed(err)
 		delete(h.links, l)
+		l.Free()
 	}
 }
 
@@ -171,6 +172,7 @@ func (h *handler) sessionClosed(ps proton.Session, err error) {
 				h.linkClosed(l, err)
 			}
 		}
+		ps.Free()
 	}
 }
 


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


[06/50] [abbrv] qpid-proton git commit: NO-JIRA: Made go_/cpp_ ctest target names consistent as go-/cpp-

Posted by ac...@apache.org.
NO-JIRA: Made go_/cpp_ ctest target names consistent as go-/cpp-


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

Branch: refs/heads/go1
Commit: ac06645c73cf4e89702ef68288f2909bd7d6066a
Parents: 6134e21
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Sep 27 14:40:02 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 27 14:40:02 2016 -0400

----------------------------------------------------------------------
 examples/cpp/CMakeLists.txt          | 4 ++--
 examples/go/CMakeLists.txt           | 4 ++--
 proton-c/bindings/cpp/CMakeLists.txt | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ac06645c/examples/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
index 017ef3f..4c094db 100644
--- a/examples/cpp/CMakeLists.txt
+++ b/examples/cpp/CMakeLists.txt
@@ -73,11 +73,11 @@ if(HAS_CPP11)
       add_executable(mt_${example} mt/${example}.cpp ${container_src})
       target_link_libraries(mt_${example} pthread)
     endforeach()
-    add_cpp_test(cpp_mt_example_test ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v MtBrokerTest)
+    add_cpp_test(cpp-example-mt ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v MtBrokerTest)
   endif()
 endif()
 
-add_cpp_test(cpp_container_example_test ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
+add_cpp_test(cpp-example-container ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
 
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ac06645c/examples/go/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/go/CMakeLists.txt b/examples/go/CMakeLists.txt
index eb69006..868b780 100644
--- a/examples/go/CMakeLists.txt
+++ b/examples/go/CMakeLists.txt
@@ -43,11 +43,11 @@ if(BUILD_GO)
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
 
   add_test(
-    NAME go_example_electron_test
+    NAME go-example-electron
     COMMAND ${GO_ENV} ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker broker)
 
   add_test(
-    NAME go_example_proton_test
+    NAME go-example-proton
     COMMAND ${GO_ENV} ${test_exe} -dir ${CMAKE_CURRENT_BINARY_DIR}/electron -broker ../proton/broker)
 
   list(APPEND ADDITIONAL_MAKE_CLEAN_FILES ${examples})

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ac06645c/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 1561134..7709bae 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -164,12 +164,12 @@ macro(add_cpp_test test)
   add_executable (${test} src/${test}.cpp)
   target_link_libraries (${test} qpid-proton qpid-proton-cpp)
   if (CMAKE_SYSTEM_NAME STREQUAL Windows)
-    add_test (NAME cpp_${test}
+    add_test (NAME cpp-${test}
       COMMAND ${env_py}
       "PATH=$<TARGET_FILE_DIR:qpid-proton>"
       $<TARGET_FILE:${test}> ${ARGN})
   else ()
-    add_test (NAME cpp_${test} COMMAND ${memcheck-cmd} ${CMAKE_CURRENT_BINARY_DIR}/${test} ${ARGN})
+    add_test (NAME cpp-${test} COMMAND ${memcheck-cmd} ${CMAKE_CURRENT_BINARY_DIR}/${test} ${ARGN})
   endif ()
 endmacro(add_cpp_test)
 


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


[14/50] [abbrv] qpid-proton git commit: PROTON-1323: update versions on master for 0.16.0-SNAPSHOT, inc python bundle version

Posted by ac...@apache.org.
PROTON-1323: update versions on master for 0.16.0-SNAPSHOT, inc python bundle version


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

Branch: refs/heads/go1
Commit: d5b1036c3c129657cd63ecbfbf489f674a17f5f4
Parents: 6d3aa78
Author: Robert Gemmell <ro...@apache.org>
Authored: Mon Oct 10 16:28:47 2016 +0100
Committer: Robert Gemmell <ro...@apache.org>
Committed: Mon Oct 10 16:28:47 2016 +0100

----------------------------------------------------------------------
 examples/engine/java/pom.xml                  | 2 +-
 examples/java/messenger/pom.xml               | 2 +-
 examples/java/reactor/pom.xml                 | 2 +-
 pom.xml                                       | 2 +-
 proton-c/bindings/python/setuputils/bundle.py | 4 ++--
 proton-j/pom.xml                              | 2 +-
 tests/pom.xml                                 | 2 +-
 version.txt                                   | 2 +-
 8 files changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/examples/engine/java/pom.xml
----------------------------------------------------------------------
diff --git a/examples/engine/java/pom.xml b/examples/engine/java/pom.xml
index cdc033e..5218f2b 100644
--- a/examples/engine/java/pom.xml
+++ b/examples/engine/java/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.apache.qpid</groupId>
     <artifactId>proton-project</artifactId>
-    <version>0.15.0-SNAPSHOT</version>
+    <version>0.16.0-SNAPSHOT</version>
     <relativePath>../../../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/examples/java/messenger/pom.xml
----------------------------------------------------------------------
diff --git a/examples/java/messenger/pom.xml b/examples/java/messenger/pom.xml
index 0274bb1..0d50bf8 100644
--- a/examples/java/messenger/pom.xml
+++ b/examples/java/messenger/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.apache.qpid</groupId>
     <artifactId>proton-project</artifactId>
-    <version>0.15.0-SNAPSHOT</version>
+    <version>0.16.0-SNAPSHOT</version>
     <relativePath>../../..</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/examples/java/reactor/pom.xml
----------------------------------------------------------------------
diff --git a/examples/java/reactor/pom.xml b/examples/java/reactor/pom.xml
index bd7448a..aa5c47f 100644
--- a/examples/java/reactor/pom.xml
+++ b/examples/java/reactor/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.apache.qpid</groupId>
     <artifactId>proton-project</artifactId>
-    <version>0.15.0-SNAPSHOT</version>
+    <version>0.16.0-SNAPSHOT</version>
     <relativePath>../../..</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ff83d50..1f2e8af 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,7 @@
 
   <groupId>org.apache.qpid</groupId>
   <artifactId>proton-project</artifactId>
-  <version>0.15.0-SNAPSHOT</version>
+  <version>0.16.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/proton-c/bindings/python/setuputils/bundle.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/setuputils/bundle.py b/proton-c/bindings/python/setuputils/bundle.py
index c85daf1..1bf3450 100644
--- a/proton-c/bindings/python/setuputils/bundle.py
+++ b/proton-c/bindings/python/setuputils/bundle.py
@@ -32,10 +32,10 @@ from . import log
 #-----------------------------------------------------------------------------
 # Constants
 #-----------------------------------------------------------------------------
-min_qpid_proton = (0, 15, 0)
+min_qpid_proton = (0, 16, 0)
 min_qpid_proton_str = "%i.%i.%i" % min_qpid_proton
 
-bundled_version = (0, 15, 0)
+bundled_version = (0, 16, 0)
 bundled_version_str = "%i.%i.%i" % bundled_version
 libqpid_proton = "qpid-proton-%s.tar.gz" % bundled_version_str
 libqpid_proton_url = ("http://www.apache.org/dist/qpid/proton/%s/%s" %

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/proton-j/pom.xml
----------------------------------------------------------------------
diff --git a/proton-j/pom.xml b/proton-j/pom.xml
index d9e4760..da7fb38 100644
--- a/proton-j/pom.xml
+++ b/proton-j/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.apache.qpid</groupId>
     <artifactId>proton-project</artifactId>
-    <version>0.15.0-SNAPSHOT</version>
+    <version>0.16.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/tests/pom.xml
----------------------------------------------------------------------
diff --git a/tests/pom.xml b/tests/pom.xml
index 0634197..eb9d717 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -27,7 +27,7 @@
   <parent>
     <groupId>org.apache.qpid</groupId>
     <artifactId>proton-project</artifactId>
-    <version>0.15.0-SNAPSHOT</version>
+    <version>0.16.0-SNAPSHOT</version>
   </parent>
 
   <description>The Proton python system tests execute against the Java or C implementation, using Maven (via this pom) and CMake/CTest respectively.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d5b1036c/version.txt
----------------------------------------------------------------------
diff --git a/version.txt b/version.txt
index 4f3da74..e466c4e 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.15.0-SNAPSHOT
+0.16.0-SNAPSHOT


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


[35/50] [abbrv] qpid-proton git commit: PROTON-1317: c++ SunStudio: Add template parameter

Posted by ac...@apache.org.
PROTON-1317: c++ SunStudio: Add template parameter

SunStudio 12.1 doesn't handle templated method signature detection when using an
"extern c" parameter

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: 1a20faa3910ecef380b47f560047eec576362ffa
Parents: dae0c55
Author: aboutros <ad...@murex.com>
Authored: Wed Oct 5 11:51:54 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/src/message.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a20faa3/proton-c/bindings/cpp/src/message.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/message.cpp b/proton-c/bindings/cpp/src/message.cpp
index 8524782..9a9634c 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -215,7 +215,7 @@ value& message::body() { pn_msg(); return body_; }
 // empty, the non-empty one is the authority.
 
 // Decode a map on demand
-template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
+template<class M, class F> M& get_map(pn_message_t* msg, F get, M& map) {
     codec::decoder d(make_wrapper(get(msg)));
     if (map.empty() && !d.empty()) {
         d.rewind();
@@ -226,7 +226,7 @@ template<class M> M& get_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*)
 }
 
 // Encode a map if necessary.
-template<class M> M& put_map(pn_message_t* msg, pn_data_t* (*get)(pn_message_t*), M& map) {
+template<class M, class F> M& put_map(pn_message_t* msg, F get, M& map) {
     codec::encoder e(make_wrapper(get(msg)));
     if (e.empty() && !map.empty()) {
         e << map;


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


[32/50] [abbrv] qpid-proton git commit: PROTON-1319: C++ SunStudo: Move internal header files of cpp bindings

Posted by ac...@apache.org.
PROTON-1319: C++ SunStudo: Move internal header files of cpp bindings

Sun compiler searches all include paths to build template-DB, creates problems
if from src files are in the path.

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: 8c3aa3a5155432b5a94ff830481f0663caddce89
Parents: 7952786
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 12:26:10 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/CMakeLists.txt            |   2 +-
 proton-c/bindings/cpp/src/acceptor.hpp          |  62 ----
 proton-c/bindings/cpp/src/connector.hpp         |  65 ----
 proton-c/bindings/cpp/src/container_impl.hpp    | 124 --------
 proton-c/bindings/cpp/src/contexts.hpp          | 137 ---------
 proton-c/bindings/cpp/src/include/acceptor.hpp  |  62 ++++
 proton-c/bindings/cpp/src/include/connector.hpp |  65 ++++
 .../bindings/cpp/src/include/container_impl.hpp | 124 ++++++++
 proton-c/bindings/cpp/src/include/contexts.hpp  | 137 +++++++++
 .../cpp/src/include/messaging_adapter.hpp       |  62 ++++
 proton-c/bindings/cpp/src/include/msg.hpp       |  58 ++++
 .../bindings/cpp/src/include/proton_bits.hpp    | 149 ++++++++++
 .../bindings/cpp/src/include/proton_event.hpp   | 293 +++++++++++++++++++
 .../bindings/cpp/src/include/proton_handler.hpp |  92 ++++++
 proton-c/bindings/cpp/src/include/reactor.hpp   | 106 +++++++
 .../bindings/cpp/src/include/scalar_test.hpp    | 209 +++++++++++++
 proton-c/bindings/cpp/src/include/test_bits.hpp | 136 +++++++++
 .../cpp/src/include/test_dummy_container.hpp    |  83 ++++++
 .../bindings/cpp/src/include/types_internal.hpp |  74 +++++
 proton-c/bindings/cpp/src/messaging_adapter.hpp |  62 ----
 proton-c/bindings/cpp/src/msg.hpp               |  58 ----
 proton-c/bindings/cpp/src/proton_bits.hpp       | 149 ----------
 proton-c/bindings/cpp/src/proton_event.hpp      | 293 -------------------
 proton-c/bindings/cpp/src/proton_handler.hpp    |  92 ------
 proton-c/bindings/cpp/src/reactor.hpp           | 106 -------
 proton-c/bindings/cpp/src/scalar_test.hpp       | 209 -------------
 proton-c/bindings/cpp/src/test_bits.hpp         | 136 ---------
 .../bindings/cpp/src/test_dummy_container.hpp   |  83 ------
 proton-c/bindings/cpp/src/types_internal.hpp    |  74 -----
 29 files changed, 1651 insertions(+), 1651 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 7709bae..ed969eb 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -22,7 +22,7 @@ include(cpp.cmake) # Compiler checks
 include_directories(
   "${CMAKE_SOURCE_DIR}/proton-c/include"
   "${CMAKE_CURRENT_SOURCE_DIR}/include"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src")
+  "${CMAKE_CURRENT_SOURCE_DIR}/src/include")
 
 add_definitions(${CXX_WARNING_FLAGS})
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/acceptor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/acceptor.hpp b/proton-c/bindings/cpp/src/acceptor.hpp
deleted file mode 100644
index 9a25592..0000000
--- a/proton-c/bindings/cpp/src/acceptor.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef PROTON_ACCEPTOR_HPP
-#define PROTON_ACCEPTOR_HPP
-
-/*
- *
- * 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/internal/export.hpp"
-#include "proton/internal/object.hpp"
-
-#include <proton/reactor.h>
-
-struct pn_acceptor_t;
-
-namespace proton {
-
-/// A context for accepting inbound connections.
-///
-/// @see container::listen
-class acceptor : public internal::object<pn_acceptor_t> {
-    /// @cond INTERNAL
-    acceptor(pn_acceptor_t* a) : internal::object<pn_acceptor_t>(a) {}
-    /// @endcond
-
-  public:
-    acceptor() : internal::object<pn_acceptor_t>(0) {}
-
-    /// Close the acceptor.
-    PN_CPP_EXTERN void close();
-
-    /// Return the current set of connection options applied to
-    /// inbound connectons by the acceptor.
-    ///
-    /// Note that changes made to the connection options only affect
-    /// connections accepted after this call returns.
-    PN_CPP_EXTERN class connection_options &connection_options();
-
-    /// @cond INTERNAL
-  friend class internal::factory<acceptor>;
-    /// @endcond
-};
-
-} // proton
-
-#endif // PROTON_ACCEPTOR_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/connector.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connector.hpp b/proton-c/bindings/cpp/src/connector.hpp
deleted file mode 100644
index 5b6707a..0000000
--- a/proton-c/bindings/cpp/src/connector.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef PROTON_CPP_CONNECTOR_HANDLER_H
-#define PROTON_CPP_CONNECTOR_HANDLER_H
-
-/*
- *
- * 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/connection.hpp"
-#include "proton/connection_options.hpp"
-#include <proton/event.h>
-#include <proton/reactor.h>
-#include "proton/url.hpp"
-
-#include "proton_handler.hpp"
-
-#include <string>
-
-
-namespace proton {
-
-class reconnect_timer;
-
-class connector : public proton_handler
-{
-  public:
-    connector(connection &c, const connection_options &options, const url&);
-    ~connector();
-    const url &address() const { return address_; }
-    void connect();
-    void reconnect_timer(const class reconnect_timer &);
-    virtual void on_connection_local_open(proton_event &e);
-    virtual void on_connection_remote_open(proton_event &e);
-    virtual void on_connection_init(proton_event &e);
-    virtual void on_transport_closed(proton_event &e);
-    virtual void on_transport_tail_closed(proton_event &e);
-    virtual void on_timer_task(proton_event &e);
-
-  private:
-    connection connection_;
-    const connection_options options_;
-    const url address_;
-    class reconnect_timer *reconnect_timer_;
-};
-
-
-}
-
-#endif  /*!PROTON_CPP_CONNECTOR_HANDLER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.hpp b/proton-c/bindings/cpp/src/container_impl.hpp
deleted file mode 100644
index 97f6be2..0000000
--- a/proton-c/bindings/cpp/src/container_impl.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef PROTON_CPP_CONTAINERIMPL_H
-#define PROTON_CPP_CONTAINERIMPL_H
-
-/*
- *
- * 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/io/link_namer.hpp"
-
-#include "proton/container.hpp"
-#include "proton/connection.hpp"
-#include "proton/connection_options.hpp"
-#include "proton/duration.hpp"
-#include "proton/sender.hpp"
-#include "proton/receiver.hpp"
-
-#include "messaging_adapter.hpp"
-#include "reactor.hpp"
-#include "proton_bits.hpp"
-#include "proton_handler.hpp"
-
-#include <list>
-#include <map>
-#include <string>
-
-namespace proton {
-
-class dispatch_helper;
-class connection;
-class connector;
-class acceptor;
-class container;
-class url;
-class task;
-class listen_handler;
-
-class container_impl : public standard_container {
-  public:
-    // Pull in base class functions here so that name search finds all the overloads
-    using standard_container::stop;
-    using standard_container::connect;
-    using standard_container::listen;
-    using standard_container::open_receiver;
-    using standard_container::open_sender;
-
-    container_impl(const std::string& id, messaging_handler* = 0);
-    ~container_impl();
-    std::string id() const PN_CPP_OVERRIDE { return id_; }
-    returned<connection> connect(const std::string&, const connection_options&) PN_CPP_OVERRIDE;
-    returned<sender> open_sender(
-        const std::string&, const proton::sender_options &, const connection_options &) PN_CPP_OVERRIDE;
-    returned<receiver> open_receiver(
-        const std::string&, const proton::receiver_options &, const connection_options &) PN_CPP_OVERRIDE;
-    listener listen(const std::string&, listen_handler& lh) PN_CPP_OVERRIDE;
-    void stop_listening(const std::string&) PN_CPP_OVERRIDE;
-    void client_connection_options(const connection_options &) PN_CPP_OVERRIDE;
-    connection_options client_connection_options() const PN_CPP_OVERRIDE { return client_connection_options_; }
-    void server_connection_options(const connection_options &) PN_CPP_OVERRIDE;
-    connection_options server_connection_options() const PN_CPP_OVERRIDE { return server_connection_options_; }
-    void sender_options(const proton::sender_options&) PN_CPP_OVERRIDE;
-    class sender_options sender_options() const PN_CPP_OVERRIDE { return sender_options_; }
-    void receiver_options(const proton::receiver_options&) PN_CPP_OVERRIDE;
-    class receiver_options receiver_options() const PN_CPP_OVERRIDE { return receiver_options_; }
-    void run() PN_CPP_OVERRIDE;
-    void stop(const error_condition& err) PN_CPP_OVERRIDE;
-    void auto_stop(bool set) PN_CPP_OVERRIDE;
-#if PN_CPP_HAS_STD_FUNCTION
-    void schedule(duration, std::function<void()>) PN_CPP_OVERRIDE;
-#endif
-    void schedule(duration, void_function0&) PN_CPP_OVERRIDE;
-
-    // non-interface functions
-    void configure_server_connection(connection &c);
-    static task schedule(container& c, int delay, proton_handler *h);
-    template <class T> static void set_handler(T s, messaging_handler* h);
-
-  private:
-    internal::pn_ptr<pn_handler_t> cpp_handler(proton_handler *h);
-
-    typedef std::map<std::string, acceptor> acceptors;
-
-    reactor reactor_;
-    // Keep a list of all the handlers used by the container so they last as long as the container
-    std::list<internal::pn_unique_ptr<proton_handler> > handlers_;
-    std::string id_;
-    connection_options client_connection_options_;
-    connection_options server_connection_options_;
-    proton::sender_options sender_options_;
-    proton::receiver_options receiver_options_;
-    bool auto_stop_;
-    acceptors acceptors_;
-
-  friend class messaging_adapter;
-};
-
-template <class T>
-void container_impl::set_handler(T s, messaging_handler* mh) {
-    pn_record_t *record = internal::get_attachments(unwrap(s));
-    proton_handler* h = new messaging_adapter(*mh);
-    container_impl& ci = static_cast<container_impl&>(s.container());
-    ci.handlers_.push_back(h);
-    pn_record_set_handler(record, ci.cpp_handler(h).get());
-}
-
-}
-
-#endif  /*!PROTON_CPP_CONTAINERIMPL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/contexts.hpp b/proton-c/bindings/cpp/src/contexts.hpp
deleted file mode 100644
index 74a763c..0000000
--- a/proton-c/bindings/cpp/src/contexts.hpp
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef PROTON_CPP_CONTEXTS_H
-#define PROTON_CPP_CONTEXTS_H
-
-/*
- *
- * 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/connection.hpp"
-#include "proton/container.hpp"
-#include "proton/io/connection_engine.hpp"
-#include "proton/event_loop.hpp"
-#include "proton/listen_handler.hpp"
-#include "proton/message.hpp"
-#include "proton/internal/pn_unique_ptr.hpp"
-
-#include "proton/io/link_namer.hpp"
-
-#include "proton_handler.hpp"
-
-struct pn_session_t;
-struct pn_event_t;
-struct pn_reactor_t;
-struct pn_record_t;
-struct pn_acceptor_t;
-
-namespace proton {
-
-class proton_handler;
-class reactor;
-
-// Base class for C++ classes that are used as proton contexts.
-// Contexts are pn_objects managed by pn reference counts, the C++ value is allocated in-place.
-class context {
-  public:
-    // identifies a context, contains a record pointer and a handle.
-    typedef std::pair<pn_record_t*, pn_handle_t> id;
-
-    virtual ~context();
-
-    // Allocate a default-constructed T as a proton object.
-    // T must be a subclass of context.
-    template <class T> static T *create() { return new(alloc(sizeof(T))) T(); }
-
-    // The pn_class for a context
-    static pn_class_t* pn_class();
-
-    // Get the context identified by id as a C++ T*, return null pointer if not present.
-    template <class T> static T* ptr(id id_) {
-        return reinterpret_cast<T*>(pn_record_get(id_.first, id_.second));
-    }
-
-    // If the context is not present, create it with value x.
-    template <class T> static T& ref(id id_) {
-        T* ctx = context::ptr<T>(id_);
-        if (!ctx) {
-            ctx = create<T>();
-            pn_record_def(id_.first, id_.second, pn_class());
-            pn_record_set(id_.first, id_.second, ctx);
-            pn_decref(ctx);
-        }
-        return *ctx;
-    }
-
-  private:
-    static void *alloc(size_t n);
-};
-
-// Connection context used by all connections.
-class connection_context : public context {
-  public:
-    connection_context() : container(0), default_session(0), link_gen(0), collector(0) {}
-
-    class container* container;
-    pn_session_t *default_session; // Owned by connection.
-    message event_message;      // re-used by messaging_adapter for performance.
-    io::link_namer* link_gen;      // Link name generator.
-    pn_collector_t* collector;
-
-    internal::pn_unique_ptr<proton_handler> handler;
-    internal::pn_unique_ptr<class event_loop> event_loop;
-
-    static connection_context& get(pn_connection_t *c) { return ref<connection_context>(id(c)); }
-    static connection_context& get(const connection& c) { return ref<connection_context>(id(c)); }
-
-  protected:
-    static context::id id(pn_connection_t*);
-    static context::id id(const connection& c);
-};
-
-void container_context(const reactor&, container&);
-
-class container_context {
-  public:
-    static void set(const reactor& r, container& c);
-    static container& get(pn_reactor_t*);
-};
-
-class listener_context : public context {
-  public:
-    static listener_context& get(pn_acceptor_t* c);
-    listener_context() : listen_handler_(0), ssl(false) {}
-    connection_options  get_options() { return listen_handler_->on_accept(); }
-    class listen_handler* listen_handler_;
-    bool ssl;
-};
-
-class link_context : public context {
-  public:
-    static link_context& get(pn_link_t* l);
-    link_context() : credit_window(10), auto_accept(true), auto_settle(true), draining(false), pending_credit(0) {}
-    int credit_window;
-    bool auto_accept;
-    bool auto_settle;
-    bool draining;
-    uint32_t pending_credit;
-};
-
-}
-
-#endif  /*!PROTON_CPP_CONTEXTS_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/acceptor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/acceptor.hpp b/proton-c/bindings/cpp/src/include/acceptor.hpp
new file mode 100644
index 0000000..9a25592
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/acceptor.hpp
@@ -0,0 +1,62 @@
+#ifndef PROTON_ACCEPTOR_HPP
+#define PROTON_ACCEPTOR_HPP
+
+/*
+ *
+ * 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/internal/export.hpp"
+#include "proton/internal/object.hpp"
+
+#include <proton/reactor.h>
+
+struct pn_acceptor_t;
+
+namespace proton {
+
+/// A context for accepting inbound connections.
+///
+/// @see container::listen
+class acceptor : public internal::object<pn_acceptor_t> {
+    /// @cond INTERNAL
+    acceptor(pn_acceptor_t* a) : internal::object<pn_acceptor_t>(a) {}
+    /// @endcond
+
+  public:
+    acceptor() : internal::object<pn_acceptor_t>(0) {}
+
+    /// Close the acceptor.
+    PN_CPP_EXTERN void close();
+
+    /// Return the current set of connection options applied to
+    /// inbound connectons by the acceptor.
+    ///
+    /// Note that changes made to the connection options only affect
+    /// connections accepted after this call returns.
+    PN_CPP_EXTERN class connection_options &connection_options();
+
+    /// @cond INTERNAL
+  friend class internal::factory<acceptor>;
+    /// @endcond
+};
+
+} // proton
+
+#endif // PROTON_ACCEPTOR_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/connector.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/connector.hpp b/proton-c/bindings/cpp/src/include/connector.hpp
new file mode 100644
index 0000000..5b6707a
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/connector.hpp
@@ -0,0 +1,65 @@
+#ifndef PROTON_CPP_CONNECTOR_HANDLER_H
+#define PROTON_CPP_CONNECTOR_HANDLER_H
+
+/*
+ *
+ * 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/connection.hpp"
+#include "proton/connection_options.hpp"
+#include <proton/event.h>
+#include <proton/reactor.h>
+#include "proton/url.hpp"
+
+#include "proton_handler.hpp"
+
+#include <string>
+
+
+namespace proton {
+
+class reconnect_timer;
+
+class connector : public proton_handler
+{
+  public:
+    connector(connection &c, const connection_options &options, const url&);
+    ~connector();
+    const url &address() const { return address_; }
+    void connect();
+    void reconnect_timer(const class reconnect_timer &);
+    virtual void on_connection_local_open(proton_event &e);
+    virtual void on_connection_remote_open(proton_event &e);
+    virtual void on_connection_init(proton_event &e);
+    virtual void on_transport_closed(proton_event &e);
+    virtual void on_transport_tail_closed(proton_event &e);
+    virtual void on_timer_task(proton_event &e);
+
+  private:
+    connection connection_;
+    const connection_options options_;
+    const url address_;
+    class reconnect_timer *reconnect_timer_;
+};
+
+
+}
+
+#endif  /*!PROTON_CPP_CONNECTOR_HANDLER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/container_impl.hpp b/proton-c/bindings/cpp/src/include/container_impl.hpp
new file mode 100644
index 0000000..97f6be2
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/container_impl.hpp
@@ -0,0 +1,124 @@
+#ifndef PROTON_CPP_CONTAINERIMPL_H
+#define PROTON_CPP_CONTAINERIMPL_H
+
+/*
+ *
+ * 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/io/link_namer.hpp"
+
+#include "proton/container.hpp"
+#include "proton/connection.hpp"
+#include "proton/connection_options.hpp"
+#include "proton/duration.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
+
+#include "messaging_adapter.hpp"
+#include "reactor.hpp"
+#include "proton_bits.hpp"
+#include "proton_handler.hpp"
+
+#include <list>
+#include <map>
+#include <string>
+
+namespace proton {
+
+class dispatch_helper;
+class connection;
+class connector;
+class acceptor;
+class container;
+class url;
+class task;
+class listen_handler;
+
+class container_impl : public standard_container {
+  public:
+    // Pull in base class functions here so that name search finds all the overloads
+    using standard_container::stop;
+    using standard_container::connect;
+    using standard_container::listen;
+    using standard_container::open_receiver;
+    using standard_container::open_sender;
+
+    container_impl(const std::string& id, messaging_handler* = 0);
+    ~container_impl();
+    std::string id() const PN_CPP_OVERRIDE { return id_; }
+    returned<connection> connect(const std::string&, const connection_options&) PN_CPP_OVERRIDE;
+    returned<sender> open_sender(
+        const std::string&, const proton::sender_options &, const connection_options &) PN_CPP_OVERRIDE;
+    returned<receiver> open_receiver(
+        const std::string&, const proton::receiver_options &, const connection_options &) PN_CPP_OVERRIDE;
+    listener listen(const std::string&, listen_handler& lh) PN_CPP_OVERRIDE;
+    void stop_listening(const std::string&) PN_CPP_OVERRIDE;
+    void client_connection_options(const connection_options &) PN_CPP_OVERRIDE;
+    connection_options client_connection_options() const PN_CPP_OVERRIDE { return client_connection_options_; }
+    void server_connection_options(const connection_options &) PN_CPP_OVERRIDE;
+    connection_options server_connection_options() const PN_CPP_OVERRIDE { return server_connection_options_; }
+    void sender_options(const proton::sender_options&) PN_CPP_OVERRIDE;
+    class sender_options sender_options() const PN_CPP_OVERRIDE { return sender_options_; }
+    void receiver_options(const proton::receiver_options&) PN_CPP_OVERRIDE;
+    class receiver_options receiver_options() const PN_CPP_OVERRIDE { return receiver_options_; }
+    void run() PN_CPP_OVERRIDE;
+    void stop(const error_condition& err) PN_CPP_OVERRIDE;
+    void auto_stop(bool set) PN_CPP_OVERRIDE;
+#if PN_CPP_HAS_STD_FUNCTION
+    void schedule(duration, std::function<void()>) PN_CPP_OVERRIDE;
+#endif
+    void schedule(duration, void_function0&) PN_CPP_OVERRIDE;
+
+    // non-interface functions
+    void configure_server_connection(connection &c);
+    static task schedule(container& c, int delay, proton_handler *h);
+    template <class T> static void set_handler(T s, messaging_handler* h);
+
+  private:
+    internal::pn_ptr<pn_handler_t> cpp_handler(proton_handler *h);
+
+    typedef std::map<std::string, acceptor> acceptors;
+
+    reactor reactor_;
+    // Keep a list of all the handlers used by the container so they last as long as the container
+    std::list<internal::pn_unique_ptr<proton_handler> > handlers_;
+    std::string id_;
+    connection_options client_connection_options_;
+    connection_options server_connection_options_;
+    proton::sender_options sender_options_;
+    proton::receiver_options receiver_options_;
+    bool auto_stop_;
+    acceptors acceptors_;
+
+  friend class messaging_adapter;
+};
+
+template <class T>
+void container_impl::set_handler(T s, messaging_handler* mh) {
+    pn_record_t *record = internal::get_attachments(unwrap(s));
+    proton_handler* h = new messaging_adapter(*mh);
+    container_impl& ci = static_cast<container_impl&>(s.container());
+    ci.handlers_.push_back(h);
+    pn_record_set_handler(record, ci.cpp_handler(h).get());
+}
+
+}
+
+#endif  /*!PROTON_CPP_CONTAINERIMPL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
new file mode 100644
index 0000000..74a763c
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -0,0 +1,137 @@
+#ifndef PROTON_CPP_CONTEXTS_H
+#define PROTON_CPP_CONTEXTS_H
+
+/*
+ *
+ * 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/connection.hpp"
+#include "proton/container.hpp"
+#include "proton/io/connection_engine.hpp"
+#include "proton/event_loop.hpp"
+#include "proton/listen_handler.hpp"
+#include "proton/message.hpp"
+#include "proton/internal/pn_unique_ptr.hpp"
+
+#include "proton/io/link_namer.hpp"
+
+#include "proton_handler.hpp"
+
+struct pn_session_t;
+struct pn_event_t;
+struct pn_reactor_t;
+struct pn_record_t;
+struct pn_acceptor_t;
+
+namespace proton {
+
+class proton_handler;
+class reactor;
+
+// Base class for C++ classes that are used as proton contexts.
+// Contexts are pn_objects managed by pn reference counts, the C++ value is allocated in-place.
+class context {
+  public:
+    // identifies a context, contains a record pointer and a handle.
+    typedef std::pair<pn_record_t*, pn_handle_t> id;
+
+    virtual ~context();
+
+    // Allocate a default-constructed T as a proton object.
+    // T must be a subclass of context.
+    template <class T> static T *create() { return new(alloc(sizeof(T))) T(); }
+
+    // The pn_class for a context
+    static pn_class_t* pn_class();
+
+    // Get the context identified by id as a C++ T*, return null pointer if not present.
+    template <class T> static T* ptr(id id_) {
+        return reinterpret_cast<T*>(pn_record_get(id_.first, id_.second));
+    }
+
+    // If the context is not present, create it with value x.
+    template <class T> static T& ref(id id_) {
+        T* ctx = context::ptr<T>(id_);
+        if (!ctx) {
+            ctx = create<T>();
+            pn_record_def(id_.first, id_.second, pn_class());
+            pn_record_set(id_.first, id_.second, ctx);
+            pn_decref(ctx);
+        }
+        return *ctx;
+    }
+
+  private:
+    static void *alloc(size_t n);
+};
+
+// Connection context used by all connections.
+class connection_context : public context {
+  public:
+    connection_context() : container(0), default_session(0), link_gen(0), collector(0) {}
+
+    class container* container;
+    pn_session_t *default_session; // Owned by connection.
+    message event_message;      // re-used by messaging_adapter for performance.
+    io::link_namer* link_gen;      // Link name generator.
+    pn_collector_t* collector;
+
+    internal::pn_unique_ptr<proton_handler> handler;
+    internal::pn_unique_ptr<class event_loop> event_loop;
+
+    static connection_context& get(pn_connection_t *c) { return ref<connection_context>(id(c)); }
+    static connection_context& get(const connection& c) { return ref<connection_context>(id(c)); }
+
+  protected:
+    static context::id id(pn_connection_t*);
+    static context::id id(const connection& c);
+};
+
+void container_context(const reactor&, container&);
+
+class container_context {
+  public:
+    static void set(const reactor& r, container& c);
+    static container& get(pn_reactor_t*);
+};
+
+class listener_context : public context {
+  public:
+    static listener_context& get(pn_acceptor_t* c);
+    listener_context() : listen_handler_(0), ssl(false) {}
+    connection_options  get_options() { return listen_handler_->on_accept(); }
+    class listen_handler* listen_handler_;
+    bool ssl;
+};
+
+class link_context : public context {
+  public:
+    static link_context& get(pn_link_t* l);
+    link_context() : credit_window(10), auto_accept(true), auto_settle(true), draining(false), pending_credit(0) {}
+    int credit_window;
+    bool auto_accept;
+    bool auto_settle;
+    bool draining;
+    uint32_t pending_credit;
+};
+
+}
+
+#endif  /*!PROTON_CPP_CONTEXTS_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/messaging_adapter.hpp b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
new file mode 100644
index 0000000..5371eec
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
@@ -0,0 +1,62 @@
+#ifndef PROTON_CPP_MESSAGING_ADAPTER_H
+#define PROTON_CPP_MESSAGING_ADAPTER_H
+
+/*
+ *
+ * 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/messaging_handler.hpp"
+
+#include "proton_handler.hpp"
+
+#include <proton/event.h>
+#include <proton/reactor.h>
+
+///@cond INTERNAL
+
+namespace proton {
+
+/// Convert the low level proton-c events to the higher level proton::messaging_handler calls
+class messaging_adapter : public proton_handler
+{
+  public:
+    messaging_adapter(messaging_handler &delegate) : delegate_(delegate) {}
+
+    void on_reactor_init(proton_event &e);
+    void on_reactor_final(proton_event & e);
+    void on_link_flow(proton_event &e);
+    void on_delivery(proton_event &e);
+    void on_connection_remote_open(proton_event &e);
+    void on_connection_remote_close(proton_event &e);
+    void on_session_remote_open(proton_event &e);
+    void on_session_remote_close(proton_event &e);
+    void on_link_local_open(proton_event &e);
+    void on_link_remote_open(proton_event &e);
+    void on_link_remote_detach(proton_event & e);
+    void on_link_remote_close(proton_event &e);
+    void on_transport_closed(proton_event &e);
+
+  private:
+    messaging_handler &delegate_;  // The handler for generated messaging_event's
+};
+
+}
+///@endcond INTERNAL
+#endif  /*!PROTON_CPP_MESSAGING_ADAPTER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/msg.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/msg.hpp b/proton-c/bindings/cpp/src/include/msg.hpp
new file mode 100644
index 0000000..b24b25c
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/msg.hpp
@@ -0,0 +1,58 @@
+#ifndef PROTON_MSG_H
+#define PROTON_MSG_H
+
+/*
+ *
+ * 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 <sstream>
+#include <iostream>
+
+namespace proton {
+
+/** A simple facade for std::ostringstream that allows
+ * in place construction of a message and automatic conversion
+ * to string.
+ * E.g.
+ *@code
+ * void foo(const std::string&);
+ * foo(msg() << "hello " << 32);
+ *@endcode
+ * Will construct the string "hello 32" and pass it to foo()
+ */
+struct msg {
+    std::ostringstream os;
+    msg() {}
+    msg(const msg& m) : os(m.str()) {}
+    std::string str() const { return os.str(); }
+    operator std::string() const { return str(); }
+    template <class T> msg& operator<<(const T& t) { os << t; return *this; }
+};
+
+inline std::ostream& operator<<(std::ostream& o, const msg& m) { return o << m.str(); }
+
+/** Construct a message using operator << and append (file:line) */
+#define QUOTe_(x) #x
+#define QUOTE(x) QUOTe_(x)
+#define MSG(message) (::proton::msg() << message)
+
+}
+
+#endif  /*!PROTON_MSG_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/proton_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_bits.hpp b/proton-c/bindings/cpp/src/include/proton_bits.hpp
new file mode 100644
index 0000000..97d4bee
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proton_bits.hpp
@@ -0,0 +1,149 @@
+#ifndef PROTON_BITS_HPP
+#define PROTON_BITS_HPP
+/*
+ * 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/link.h>
+#include <proton/session.h>
+
+#include <string>
+#include <iosfwd>
+
+/**@file
+ *
+ * Assorted internal proton utilities.
+ */
+
+struct pn_error_t;
+
+struct pn_data_t;
+struct pn_transport_t;
+struct pn_sasl_t;
+struct pn_ssl_t;
+struct pn_connection_t;
+struct pn_session_t;
+struct pn_link_t;
+struct pn_delivery_t;
+struct pn_condition_t;
+struct pn_acceptor_t;
+struct pn_terminus_t;
+struct pn_reactor_t;
+struct pn_record_t;
+
+namespace proton {
+
+namespace internal { class data; }
+class transport;
+class sasl;
+class ssl;
+class connection;
+class session;
+class link;
+class sender;
+class receiver;
+class transfer;
+class tracker;
+class delivery;
+class error_condition;
+class acceptor;
+class terminus;
+class source;
+class target;
+class reactor;
+
+std::string error_str(long code);
+
+/** Print the error string from pn_error_t, or from code if pn_error_t has no error. */
+std::string error_str(pn_error_t*, long code=0);
+
+/** Make a void* inspectable via operator <<. */
+struct inspectable { void* value; inspectable(void* o) : value(o) {} };
+
+/** Stream a proton object via pn_inspect. */
+std::ostream& operator<<(std::ostream& o, const inspectable& object);
+
+void set_error_condition(const error_condition&, pn_condition_t*);
+
+/// Convert a const char* to std::string, convert NULL to the empty string.
+inline std::string str(const char* s) { return s ? s : std::string(); }
+
+namespace internal {
+
+// These traits relate the wrapped and wrapper classes for the templated factories below
+template <class T> struct wrapped {};
+template <> struct wrapped<internal::data> { typedef pn_data_t type; };
+template <> struct wrapped<transport> { typedef pn_transport_t type; };
+template <> struct wrapped<sasl> { typedef pn_sasl_t type; };
+template <> struct wrapped<ssl> { typedef pn_ssl_t type; };
+template <> struct wrapped<connection> { typedef pn_connection_t type; };
+template <> struct wrapped<session> { typedef pn_session_t type; };
+template <> struct wrapped<link> { typedef pn_link_t type; };
+template <> struct wrapped<sender> { typedef pn_link_t type; };
+template <> struct wrapped<receiver> { typedef pn_link_t type; };
+template <> struct wrapped<transfer> { typedef pn_delivery_t type; };
+template <> struct wrapped<tracker> { typedef pn_delivery_t type; };
+template <> struct wrapped<delivery> { typedef pn_delivery_t type; };
+template <> struct wrapped<error_condition> { typedef pn_condition_t type; };
+template <> struct wrapped<acceptor> { typedef pn_acceptor_t type; }; // TODO aconway 2016-05-13: reactor only
+template <> struct wrapped<terminus> { typedef pn_terminus_t type; };
+template <> struct wrapped<source> { typedef pn_terminus_t type; };
+template <> struct wrapped<target> { typedef pn_terminus_t type; };
+template <> struct wrapped<reactor> { typedef pn_reactor_t type; };
+
+template <class T> struct wrapper {};
+template <> struct wrapper<pn_data_t> { typedef internal::data type; };
+template <> struct wrapper<pn_transport_t> { typedef transport type; };
+template <> struct wrapper<pn_sasl_t> { typedef sasl type; };
+template <> struct wrapper<pn_ssl_t> { typedef ssl type; };
+template <> struct wrapper<pn_connection_t> { typedef connection type; };
+template <> struct wrapper<pn_session_t> { typedef session type; };
+template <> struct wrapper<pn_link_t> { typedef link type; };
+template <> struct wrapper<pn_delivery_t> { typedef transfer type; };
+template <> struct wrapper<pn_condition_t> { typedef error_condition type; };
+template <> struct wrapper<pn_acceptor_t> { typedef acceptor type; };
+template <> struct wrapper<pn_terminus_t> { typedef terminus type; };
+template <> struct wrapper<pn_reactor_t> { typedef reactor type; };
+
+// Factory for wrapper types
+template <class T>
+class factory {
+public:
+    static T wrap(typename wrapped<T>::type* t) { return t; }
+    static typename wrapped<T>::type* unwrap(T t) { return t.pn_object(); }
+};
+
+// Get attachments for various proton-c types
+template <class T>
+inline pn_record_t* get_attachments(T*);
+
+template <> inline pn_record_t* get_attachments(pn_session_t* s) { return pn_session_attachments(s); }
+template <> inline pn_record_t* get_attachments(pn_link_t* l) { return pn_link_attachments(l); }
+}
+
+template <class T>
+typename internal::wrapper<T>::type make_wrapper(T* t) { return internal::factory<typename internal::wrapper<T>::type>::wrap(t); }
+
+template <class U>
+U make_wrapper(typename internal::wrapped<U>::type* t) { return internal::factory<U>::wrap(t); }
+
+template <class T>
+typename internal::wrapped<T>::type* unwrap(T t) {return internal::factory<T>::unwrap(t); }
+
+}
+
+#endif // PROTON_BITS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/proton_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_event.hpp b/proton-c/bindings/cpp/src/include/proton_event.hpp
new file mode 100644
index 0000000..9b33701
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proton_event.hpp
@@ -0,0 +1,293 @@
+#ifndef PROTON_CPP_PROTONEVENT_H
+#define PROTON_CPP_PROTONEVENT_H
+
+/*
+ *
+ * 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/error.hpp"
+
+#include <proton/event.h>
+
+namespace proton {
+
+class proton_handler;
+class container;
+
+/** Event information for a proton::proton_handler */
+class proton_event
+{
+  public:
+    /// The type of an event
+    enum event_type {
+    ///@name Event types
+    ///@{
+
+      /**
+      * Defined as a programming convenience. No event of this type will
+      * ever be generated.
+      */
+      EVENT_NONE=PN_EVENT_NONE,
+
+      /**
+      * A reactor has been started. Events of this type point to the reactor.
+      */
+      REACTOR_INIT=PN_REACTOR_INIT,
+
+      /**
+      * A reactor has no more events to process. Events of this type
+      * point to the reactor.
+      */
+      REACTOR_QUIESCED=PN_REACTOR_QUIESCED,
+
+      /**
+      * A reactor has been stopped. Events of this type point to the reactor.
+      */
+      REACTOR_FINAL=PN_REACTOR_FINAL,
+
+      /**
+      * A timer event has occurred.
+      */
+      TIMER_TASK=PN_TIMER_TASK,
+
+      /**
+      * The connection has been created. This is the first event that
+      * will ever be issued for a connection. Events of this type point
+      * to the relevant connection.
+      */
+      CONNECTION_INIT=PN_CONNECTION_INIT,
+
+      /**
+      * The connection has been bound to a transport. This event is
+      * issued when the transport::bind() is called.
+      */
+      CONNECTION_BOUND=PN_CONNECTION_BOUND,
+
+      /**
+      * The connection has been unbound from its transport. This event is
+      * issued when transport::unbind() is called.
+      */
+      CONNECTION_UNBOUND=PN_CONNECTION_UNBOUND,
+
+      /**
+      * The local connection endpoint has been closed. Events of this
+      * type point to the relevant connection.
+      */
+      CONNECTION_LOCAL_OPEN=PN_CONNECTION_LOCAL_OPEN,
+
+      /**
+      * The remote endpoint has opened the connection. Events of this
+      * type point to the relevant connection.
+      */
+      CONNECTION_REMOTE_OPEN=PN_CONNECTION_REMOTE_OPEN,
+
+      /**
+      * The local connection endpoint has been closed. Events of this
+      * type point to the relevant connection.
+      */
+      CONNECTION_LOCAL_CLOSE=PN_CONNECTION_LOCAL_CLOSE,
+
+      /**
+      *  The remote endpoint has closed the connection. Events of this
+      *  type point to the relevant connection.
+      */
+      CONNECTION_REMOTE_CLOSE=PN_CONNECTION_REMOTE_CLOSE,
+
+      /**
+      * The connection has been freed and any outstanding processing has
+      * been completed. This is the final event that will ever be issued
+      * for a connection.
+      */
+      CONNECTION_FINAL=PN_CONNECTION_FINAL,
+
+      /**
+      * The session has been created. This is the first event that will
+      * ever be issued for a session.
+      */
+      SESSION_INIT=PN_SESSION_INIT,
+
+      /**
+      * The local session endpoint has been opened. Events of this type
+      * point to the relevant session.
+      */
+      SESSION_LOCAL_OPEN=PN_SESSION_LOCAL_OPEN,
+
+      /**
+      * The remote endpoint has opened the session. Events of this type
+      * point to the relevant session.
+      */
+      SESSION_REMOTE_OPEN=PN_SESSION_REMOTE_OPEN,
+
+      /**
+      * The local session endpoint has been closed. Events of this type
+      * point ot the relevant session.
+      */
+      SESSION_LOCAL_CLOSE=PN_SESSION_LOCAL_CLOSE,
+
+      /**
+      * The remote endpoint has closed the session. Events of this type
+      * point to the relevant session.
+      */
+      SESSION_REMOTE_CLOSE=PN_SESSION_REMOTE_CLOSE,
+
+      /**
+      * The session has been freed and any outstanding processing has
+      * been completed. This is the final event that will ever be issued
+      * for a session.
+      */
+      SESSION_FINAL=PN_SESSION_FINAL,
+
+      /**
+      * The link has been created. This is the first event that will ever
+      * be issued for a link.
+      */
+      LINK_INIT=PN_LINK_INIT,
+
+      /**
+      * The local link endpoint has been opened. Events of this type
+      * point ot the relevant link.
+      */
+      LINK_LOCAL_OPEN=PN_LINK_LOCAL_OPEN,
+
+      /**
+      * The remote endpoint has opened the link. Events of this type
+      * point to the relevant link.
+      */
+      LINK_REMOTE_OPEN=PN_LINK_REMOTE_OPEN,
+
+      /**
+      * The local link endpoint has been closed. Events of this type
+      * point ot the relevant link.
+      */
+      LINK_LOCAL_CLOSE=PN_LINK_LOCAL_CLOSE,
+
+      /**
+      * The remote endpoint has closed the link. Events of this type
+      * point to the relevant link.
+      */
+      LINK_REMOTE_CLOSE=PN_LINK_REMOTE_CLOSE,
+
+      /**
+      * The local link endpoint has been detached. Events of this type
+      * point to the relevant link.
+      */
+      LINK_LOCAL_DETACH=PN_LINK_LOCAL_DETACH,
+
+      /**
+      * The remote endpoint has detached the link. Events of this type
+      * point to the relevant link.
+      */
+      LINK_REMOTE_DETACH=PN_LINK_REMOTE_DETACH,
+
+      /**
+      * The flow control state for a link has changed. Events of this
+      * type point to the relevant link.
+      */
+      LINK_FLOW=PN_LINK_FLOW,
+
+      /**
+      * The link has been freed and any outstanding processing has been
+      * completed. This is the final event that will ever be issued for a
+      * link. Events of this type point to the relevant link.
+      */
+      LINK_FINAL=PN_LINK_FINAL,
+
+      /**
+      * A delivery has been created or updated. Events of this type point
+      * to the relevant delivery.
+      */
+      DELIVERY=PN_DELIVERY,
+
+      /**
+      * The transport has new data to read and/or write. Events of this
+      * type point to the relevant transport.
+      */
+      TRANSPORT=PN_TRANSPORT,
+
+      /**
+      * The transport has authenticated, if this is received by a server
+      * the associated transport has authenticated an incoming connection
+      * and transport::user() can be used to obtain the authenticated
+      * user.
+      */
+      TRANSPORT_AUTHENTICATED=PN_TRANSPORT_AUTHENTICATED,
+
+      /**
+      * Indicates that a transport error has occurred. Use
+      * transport::condition() to access the details of the error
+      * from the associated transport.
+      */
+      TRANSPORT_ERROR=PN_TRANSPORT_ERROR,
+
+      /**
+      * Indicates that the head of the transport has been closed. This
+      * means the transport will never produce more bytes for output to
+      * the network. Events of this type point to the relevant transport.
+      */
+      TRANSPORT_HEAD_CLOSED=PN_TRANSPORT_HEAD_CLOSED,
+
+      /**
+      * Indicates that the tail of the transport has been closed. This
+      * means the transport will never be able to process more bytes from
+      * the network. Events of this type point to the relevant transport.
+      */
+      TRANSPORT_TAIL_CLOSED=PN_TRANSPORT_TAIL_CLOSED,
+
+      /**
+      * Indicates that the both the head and tail of the transport are
+      * closed. Events of this type point to the relevant transport.
+      */
+      TRANSPORT_CLOSED=PN_TRANSPORT_CLOSED,
+
+      SELECTABLE_INIT=PN_SELECTABLE_INIT,
+      SELECTABLE_UPDATED=PN_SELECTABLE_UPDATED,
+      SELECTABLE_READABLE=PN_SELECTABLE_READABLE,
+      SELECTABLE_WRITABLE=PN_SELECTABLE_WRITABLE,
+      SELECTABLE_ERROR=PN_SELECTABLE_ERROR,
+      SELECTABLE_EXPIRED=PN_SELECTABLE_EXPIRED,
+      SELECTABLE_FINAL=PN_SELECTABLE_FINAL
+    };
+    ///@}
+
+    proton_event(pn_event_t *ce, class container* cont) :
+      pn_event_(ce),
+      container_(cont)
+    {}
+
+    pn_event_t* pn_event() const { return pn_event_; }
+    class container& container() const {
+        if (!container_)
+            throw proton::error("event does not have a container");
+        return *container_;
+    }
+
+    /// Get type of event
+    event_type type() const { return event_type(pn_event_type(pn_event_)); }
+
+    void dispatch(proton_handler& h);
+
+  private:
+    pn_event_t *pn_event_;
+    class container* container_;
+};
+
+}
+
+#endif  /*!PROTON_CPP_PROTONEVENT_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/proton_handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_handler.hpp b/proton-c/bindings/cpp/src/include/proton_handler.hpp
new file mode 100644
index 0000000..9941396
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proton_handler.hpp
@@ -0,0 +1,92 @@
+#ifndef PROTON_CPP_PROTONHANDLER_H
+#define PROTON_CPP_PROTONHANDLER_H
+
+/*
+ *
+ * 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/internal/object.hpp"
+
+#include <vector>
+
+struct pn_handler_t;
+
+namespace proton {
+
+class event;
+class proton_event;
+
+/// Handler base class, subclass and over-ride event handling member functions.
+/// @see proton::proton_event for meaning of events.
+class proton_handler
+{
+  public:
+    proton_handler();
+    virtual ~proton_handler();
+
+    ///@name Over-ride these member functions to handle events
+    ///@{
+    virtual void on_reactor_init(proton_event &e);
+    virtual void on_reactor_quiesced(proton_event &e);
+    virtual void on_reactor_final(proton_event &e);
+    virtual void on_timer_task(proton_event &e);
+    virtual void on_connection_init(proton_event &e);
+    virtual void on_connection_bound(proton_event &e);
+    virtual void on_connection_unbound(proton_event &e);
+    virtual void on_connection_local_open(proton_event &e);
+    virtual void on_connection_local_close(proton_event &e);
+    virtual void on_connection_remote_open(proton_event &e);
+    virtual void on_connection_remote_close(proton_event &e);
+    virtual void on_connection_final(proton_event &e);
+    virtual void on_session_init(proton_event &e);
+    virtual void on_session_local_open(proton_event &e);
+    virtual void on_session_local_close(proton_event &e);
+    virtual void on_session_remote_open(proton_event &e);
+    virtual void on_session_remote_close(proton_event &e);
+    virtual void on_session_final(proton_event &e);
+    virtual void on_link_init(proton_event &e);
+    virtual void on_link_local_open(proton_event &e);
+    virtual void on_link_local_close(proton_event &e);
+    virtual void on_link_local_detach(proton_event &e);
+    virtual void on_link_remote_open(proton_event &e);
+    virtual void on_link_remote_close(proton_event &e);
+    virtual void on_link_remote_detach(proton_event &e);
+    virtual void on_link_flow(proton_event &e);
+    virtual void on_link_final(proton_event &e);
+    virtual void on_delivery(proton_event &e);
+    virtual void on_transport(proton_event &e);
+    virtual void on_transport_error(proton_event &e);
+    virtual void on_transport_head_closed(proton_event &e);
+    virtual void on_transport_tail_closed(proton_event &e);
+    virtual void on_transport_closed(proton_event &e);
+    virtual void on_selectable_init(proton_event &e);
+    virtual void on_selectable_updated(proton_event &e);
+    virtual void on_selectable_readable(proton_event &e);
+    virtual void on_selectable_writable(proton_event &e);
+    virtual void on_selectable_expired(proton_event &e);
+    virtual void on_selectable_error(proton_event &e);
+    virtual void on_selectable_final(proton_event &e);
+    virtual void on_unhandled(proton_event &e);
+    ///@}
+};
+
+}
+
+#endif  /*!PROTON_CPP_PROTONHANDLER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/reactor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/reactor.hpp b/proton-c/bindings/cpp/src/include/reactor.hpp
new file mode 100644
index 0000000..c7ab915
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/reactor.hpp
@@ -0,0 +1,106 @@
+#ifndef REACTOR_HPP
+#define REACTOR_HPP
+
+/*
+ * 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.
+ */
+
+/// @cond INTERNAL
+/// XXX remove
+
+#include "proton/internal/object.hpp"
+#include "proton/duration.hpp"
+#include "proton/timestamp.hpp"
+
+struct pn_reactor_t;
+struct pn_handler_t;
+struct pn_io_t;
+
+namespace proton {
+
+class connection;
+class container;
+class acceptor;
+class url;
+class messaging_handler;
+class task;
+
+class reactor : public internal::object<pn_reactor_t> {
+  public:
+    reactor(pn_reactor_t* r = 0) : internal::object<pn_reactor_t>(r) {}
+
+    /** Create a new reactor. */
+    static reactor create();
+
+    /** Open a connection to url and create a receiver with source=url.path() */
+    acceptor listen(const proton::url &);
+
+    /** Run the event loop, return when all connections and acceptors are closed. */
+    void run();
+
+    /** Start the reactor, you must call process() to process events */
+    void start();
+
+    /** Process events, return true if there are more events to process. */
+    bool process();
+
+    /** Stop the reactor, causes run() to return and process() to return false. */
+    void stop();
+
+    /// Identifier for the container
+    std::string id() const;
+
+    /// Get timeout, process() will return if there is no activity within the timeout.
+    duration timeout();
+
+    /// Set timeout, process() will return if there is no activity within the timeout.
+    void timeout(duration timeout);
+
+    timestamp mark();
+    timestamp now();
+
+    task schedule(int, pn_handler_t*);
+
+    class connection connection(pn_handler_t*) const;
+
+    class connection connection_to_host(const std::string &host, const std::string &port, pn_handler_t*) const;
+
+    pn_handler_t* pn_handler() const;
+
+    void pn_handler(pn_handler_t* );
+
+    pn_handler_t* pn_global_handler() const;
+
+    void pn_global_handler(pn_handler_t* );
+
+    pn_io_t* pn_io() const;
+
+    void wakeup();
+    bool quiesced();
+    void yield();
+
+  friend class container_impl;
+  friend class container_context;
+  friend class internal::factory<reactor>;
+};
+
+}
+
+/// @endcond
+
+#endif // REACTOR_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/scalar_test.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/scalar_test.hpp b/proton-c/bindings/cpp/src/include/scalar_test.hpp
new file mode 100644
index 0000000..b075c98
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/scalar_test.hpp
@@ -0,0 +1,209 @@
+#ifndef SCALAR_TEST_HPP
+#define SCALAR_TEST_HPP
+
+/*
+ * 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.
+ */
+
+// Template tests used by both scalar_test.cpp and value_test.hpp to test conversion
+// of scalar values via a proton::scalar or a proton::value.
+
+#include "test_bits.hpp"
+
+#include "proton/types.hpp"
+#include "proton/error.hpp"
+
+#include <sstream>
+
+
+namespace test {
+
+using namespace proton;
+
+// Inserting and extracting simple C++ values using same-type get<T> and coerce<T>
+template <class V, class T> void simple_type_test(T x, type_id tid, const std::string& s, T y) {
+    V vx(x);                    // Construct from C++ value
+    ASSERT_EQUAL(tid, vx.type());
+    ASSERT(!vx.empty());
+    ASSERT_EQUAL(x, get<T>(vx));
+    ASSERT_EQUAL(x, coerce<T>(vx));
+
+    V vxa = x;                  // Assign from C++ value
+    ASSERT_EQUAL(tid, vxa.type());
+    ASSERT(!vx.empty());
+    ASSERT_EQUAL(vx, vxa);
+    ASSERT_EQUAL(x, get<T>(vxa));
+    ASSERT_EQUAL(x, coerce<T>(vxa));
+
+    V v2;                       // Default construct
+    ASSERT(v2.type() == NULL_TYPE);
+    ASSERT(v2.empty());
+    v2 = x;                     // Assign from C++ value
+    ASSERT_EQUAL(tid, v2.type());
+    ASSERT_EQUAL(vx, v2);
+    ASSERT_EQUAL(x, get<T>(v2));
+    ASSERT_EQUAL(x, coerce<T>(v2));
+
+    V v3(vx);                   // Copy construct
+    ASSERT_EQUAL(tid, v3.type());
+    ASSERT_EQUAL(vx, v3);
+    ASSERT_EQUAL(x, get<T>(v3));
+    ASSERT_EQUAL(x, coerce<T>(v3));
+
+    V v4 = vx;                  // Copy assign
+    ASSERT_EQUAL(tid, v4.type());
+    ASSERT_EQUAL(x, get<T>(v4));
+    ASSERT_EQUAL(x, coerce<T>(v4));
+
+    ASSERT_EQUAL(s, to_string(vx));   // Stringify
+    V vy(y);
+    ASSERT(vx != vy);           // Compare
+    ASSERT(vx < vy);
+    ASSERT(vy > vx);
+}
+
+// Test native C/C++ integer types via their mapped integer type ([u]int_x_t)
+template <class V, class T> void simple_integral_test() {
+    typedef typename internal::integer_type<sizeof(T), internal::is_signed<T>::value>::type int_type;
+    simple_type_test<V>(T(3), internal::type_id_of<int_type>::value, "3", T(4));
+}
+
+// Test invalid gets, valid same-type get<T> is tested by simple_type_test
+// Templated to test both scalar and value.
+template<class V>  void bad_get_test() {
+    try { get<bool>(V(int8_t(1))); FAIL("byte as bool"); } catch (conversion_error) {}
+    try { get<uint8_t>(V(true)); FAIL("bool as uint8_t"); } catch (conversion_error) {}
+    try { get<uint8_t>(V(int8_t(1))); FAIL("int8 as uint8"); } catch (conversion_error) {}
+    try { get<int16_t>(V(uint16_t(1))); FAIL("uint16 as int16"); } catch (conversion_error) {}
+    try { get<int16_t>(V(int32_t(1))); FAIL("int32 as int16"); } catch (conversion_error) {}
+    try { get<symbol>(V(std::string())); FAIL("string as symbol"); } catch (conversion_error) {}
+    try { get<std::string>(V(binary())); FAIL("binary as string"); } catch (conversion_error) {}
+    try { get<binary>(V(symbol())); FAIL("symbol as binary"); } catch (conversion_error) {}
+    try { get<binary>(V(timestamp())); FAIL("timestamp as binary"); } catch (conversion_error) {}
+    try { get<int>(V(timestamp())); FAIL("timestamp as int"); } catch (conversion_error) {}
+    try { get<timestamp>(V(0)); FAIL("int as timestamp"); } catch (conversion_error) {}
+    try { get<timestamp>(V(std::string())); FAIL("string as timestamp"); } catch (conversion_error) {}
+}
+
+// Test some valid coercions and some bad ones with mixed types.
+// Templated to test both scalar and value.
+template<class V> void coerce_test() {
+    // Valid C++ conversions should work with coerce.
+    ASSERT_EQUAL(false, coerce<bool>(V(0)));
+    ASSERT_EQUAL(true, coerce<bool>(V(-1)));
+    ASSERT_EQUAL(true, coerce<bool>(V(int64_t(0xFFFF0000))));
+
+    ASSERT_EQUAL(1, coerce<uint8_t>(V(uint64_t(1)))); // In range.
+    ASSERT_EQUAL(1, coerce<uint8_t>(V(uint32_t(0xFF01)))); // int truncate.
+    ASSERT_EQUAL(0xFFFF, coerce<uint16_t>(V(int8_t(-1)))); // Sign extend.
+    ASSERT_EQUAL(-1, coerce<int32_t>(V(uint64_t(0xFFFFFFFFul)))); // 2s complement
+
+    ASSERT_EQUALISH(1.2f, coerce<float>(V(double(1.2))), 0.001f);
+    ASSERT_EQUALISH(3.4, coerce<double>(V(float(3.4))), 0.001);
+    ASSERT_EQUALISH(23.0, coerce<double>(V(uint64_t(23))), 0.001); // int to double.
+    ASSERT_EQUAL(-1945, coerce<int>(V(float(-1945.123))));    // round to int.
+
+    // String-like conversions.
+    ASSERT_EQUAL(std::string("foo"), coerce<std::string>(V(symbol("foo"))));
+    ASSERT_EQUAL(std::string("foo"), coerce<std::string>(V(binary("foo"))));
+
+    // Bad coercions, types are not `is_convertible`
+    V s("foo");
+    try { coerce<bool>(s); FAIL("string as bool"); } catch (conversion_error) {}
+    try { coerce<int>(s); FAIL("string as int"); } catch (conversion_error) {}
+    try { coerce<double>(s); FAIL("string as double"); } catch (conversion_error) {}
+
+    try { coerce<std::string>(V(0)); FAIL("int as string"); } catch (conversion_error) {}
+    try { coerce<symbol>(V(true)); FAIL("bool as symbol"); } catch (conversion_error) {}
+    try { coerce<binary>(V(0.0)); FAIL("double as binary"); } catch (conversion_error) {}
+    try { coerce<symbol>(V(binary())); FAIL("binary as symbol"); } catch (conversion_error) {}
+    try { coerce<binary>(V(symbol())); FAIL("symbol as binary"); } catch (conversion_error) {}
+    try { coerce<binary>(s); } catch (conversion_error) {}
+    try { coerce<symbol>(s); } catch (conversion_error) {}
+}
+
+template <class V> void null_test() {
+    V v;
+    ASSERT(v.empty());
+    ASSERT_EQUAL(NULL_TYPE, v.type());
+    get<null>(v);
+    null n;
+    get(v, n);
+    V v2(n);
+    ASSERT(v.empty());
+    ASSERT_EQUAL(NULL_TYPE, v.type());
+    v = "foo";
+    ASSERT_EQUAL(STRING, v.type());
+    try { get<null>(v); FAIL("Expected conversion_error"); } catch (conversion_error) {}
+    v = null();
+    get<null>(v);
+}
+
+// Nasty hack for uninterpreted decimal<> types.
+template <class T> T make(const char c) { T x; std::fill(x.begin(), x.end(), c); return x; }
+
+template <class V> void scalar_test_group(int& failed) {
+    // Direct AMQP-mapped types.
+    RUN_TEST(failed, simple_type_test<V>(false, BOOLEAN, "false", true));
+    RUN_TEST(failed, simple_type_test<V>(uint8_t(42), UBYTE, "42", uint8_t(50)));
+    RUN_TEST(failed, simple_type_test<V>(int8_t(-42), BYTE, "-42", int8_t(-40)));
+    RUN_TEST(failed, simple_type_test<V>(uint16_t(4242), USHORT, "4242", uint16_t(5252)));
+    RUN_TEST(failed, simple_type_test<V>(int16_t(-4242), SHORT, "-4242", int16_t(3)));
+    RUN_TEST(failed, simple_type_test<V>(uint32_t(4242), UINT, "4242", uint32_t(5252)));
+    RUN_TEST(failed, simple_type_test<V>(int32_t(-4242), INT, "-4242", int32_t(3)));
+    RUN_TEST(failed, simple_type_test<V>(uint64_t(4242), ULONG, "4242", uint64_t(5252)));
+    RUN_TEST(failed, simple_type_test<V>(int64_t(-4242), LONG, "-4242", int64_t(3)));
+    RUN_TEST(failed, simple_type_test<V>(wchar_t('X'), CHAR, "88", wchar_t('Y')));
+    RUN_TEST(failed, simple_type_test<V>(float(1.234), FLOAT, "1.234", float(2.345)));
+    RUN_TEST(failed, simple_type_test<V>(double(11.2233), DOUBLE, "11.2233", double(12)));
+    RUN_TEST(failed, simple_type_test<V>(timestamp(1234), TIMESTAMP, "1234", timestamp(12345)));
+    RUN_TEST(failed, simple_type_test<V>(make<decimal32>(1), DECIMAL32, "decimal32(0x01010101)", make<decimal32>(2)));
+    RUN_TEST(failed, simple_type_test<V>(make<decimal64>(3), DECIMAL64, "decimal64(0x0303030303030303)", make<decimal64>(4)));
+    RUN_TEST(failed, simple_type_test<V>(make<decimal128>(5), DECIMAL128, "decimal128(0x05050505050505050505050505050505)", make<decimal128>(6)));
+    RUN_TEST(failed, simple_type_test<V>(
+                 uuid::copy("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"),
+                 UUID, "00112233-4455-6677-8899-aabbccddeeff",
+                 uuid::copy("\xff\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")));
+    RUN_TEST(failed, simple_type_test<V>(std::string("xxx"), STRING, "xxx", std::string("yyy")));
+    RUN_TEST(failed, simple_type_test<V>(symbol("aaa"), SYMBOL, "aaa", symbol("aaaa")));
+    RUN_TEST(failed, simple_type_test<V>(binary("\010aaa"), BINARY, "b\"\\x08aaa\"", binary("aaaa")));
+
+    // Test native C++ integral types.
+    RUN_TEST(failed, (simple_integral_test<V, char>()));
+    RUN_TEST(failed, (simple_integral_test<V, signed char>()));
+    RUN_TEST(failed, (simple_integral_test<V, unsigned char>()));
+    RUN_TEST(failed, (simple_integral_test<V, short>()));
+    RUN_TEST(failed, (simple_integral_test<V, int>()));
+    RUN_TEST(failed, (simple_integral_test<V, long>()));
+    RUN_TEST(failed, (simple_integral_test<V, unsigned short>()));
+    RUN_TEST(failed, (simple_integral_test<V, unsigned int>()));
+    RUN_TEST(failed, (simple_integral_test<V, unsigned long>()));
+#if PN_CPP_HAS_LONG_LONG
+    RUN_TEST(failed, (simple_integral_test<V, long long>()));
+    RUN_TEST(failed, (simple_integral_test<V, unsigned long long>()));
+#endif
+
+
+    RUN_TEST(failed, (coerce_test<V>()));
+    RUN_TEST(failed, (null_test<V>()));
+    RUN_TEST(failed, (bad_get_test<V>()));
+}
+
+}
+
+#endif // SCALAR_TEST_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/test_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/test_bits.hpp b/proton-c/bindings/cpp/src/include/test_bits.hpp
new file mode 100644
index 0000000..0cfbe1f
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/test_bits.hpp
@@ -0,0 +1,136 @@
+#ifndef TEST_BITS_HPP
+#define TEST_BITS_HPP
+/*
+ * 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 "msg.hpp"
+#include "proton/types.hpp"
+
+#include <stdexcept>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <math.h>
+
+namespace test {
+
+struct fail : public std::logic_error {
+    fail(const std::string& what) : logic_error(what) {}
+};
+
+template <class T, class U>
+void assert_equal(const T& want, const U& got, const std::string& what) {
+    if (!(want == got))
+        throw fail(MSG(what << " " << want << " != " << got));
+}
+
+template <class T>
+inline void assert_equalish(T want, T got, T delta, const std::string& what)
+{
+    if (!(fabs(want-got) <= delta))
+        throw fail(MSG(what << " " << want << " !=~ " << got));
+}
+
+#define FAIL_MSG(WHAT) (MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT).str())
+#define FAIL(WHAT) throw test::fail(FAIL_MSG(WHAT))
+#define ASSERT(TEST) do { if (!(TEST)) FAIL("failed ASSERT(" #TEST ")"); } while(false)
+#define ASSERT_EQUAL(WANT, GOT) \
+    test::assert_equal((WANT), (GOT), FAIL_MSG("failed ASSERT_EQUAL(" #WANT ", " #GOT ")"))
+#define ASSERT_EQUALISH(WANT, GOT, DELTA) \
+    test::assert_equalish((WANT), (GOT), (DELTA), FAIL_MSG("failed ASSERT_EQUALISH(" #WANT ", " #GOT ")"))
+
+#define RUN_TEST(BAD_COUNT, TEST)                                       \
+    do {                                                                \
+        try {                                                           \
+            TEST;                                                       \
+            break;                                                      \
+        } catch(const test::fail& e) {                                        \
+            std::cout << "FAIL " << #TEST << std::endl << e.what() << std::endl; \
+        } catch(const std::exception& e) {                              \
+            std::cout << "ERROR " << #TEST << std::endl << __FILE__ << ":" << __LINE__ << ": " << e.what() << std::endl; \
+        }                                                               \
+            ++BAD_COUNT;                                                \
+    } while(0)
+
+template<class T> std::string str(const T& x) {
+    std::ostringstream s; s << std::boolalpha << x; return s.str();
+}
+
+// A way to easily create literal collections that can be compared to std:: collections
+// and to print std collections
+// e.g.
+//     std::vector<string> v = ...;
+//     ASSERT_EQUAL(many<string>() + "a" + "b" + "c", v);
+template <class T> struct many : public std::vector<T> {
+    many() {}
+    template<class S> explicit many(const S& s) : std::vector<T>(s.begin(), s.end()) {}
+    many& operator+=(const T& t) { this->push_back(t); return *this; }
+    many& operator<<(const T& t) { return *this += t; }
+    many operator+(const T& t) { many<T> l(*this); return l += t; }
+};
+
+template <class T, class S> bool operator==(const many<T>& m, const S& s) {
+    return m.size() == s.size() && S(m.begin(), m.end()) == s;
+}
+
+template <class T, class S> bool operator==(const S& s, const many<T>& m) {
+    return m.size() == s.size() && S(m.begin(), m.end()) == s;
+}
+
+template <class T> std::ostream& operator<<(std::ostream& o, const many<T>& m) {
+    std::ostream_iterator<T> oi(o, " ");
+    std::copy(m.begin(), m.end(), oi);
+    return o;
+}
+
+}
+
+namespace std {
+template <class T> std::ostream& operator<<(std::ostream& o, const std::vector<T>& s) {
+    return o << test::many<T>(s);
+}
+
+template <class T> std::ostream& operator<<(std::ostream& o, const std::deque<T>& s) {
+    return o << test::many<T>(s);
+}
+
+template <class T> std::ostream& operator<<(std::ostream& o, const std::list<T>& s) {
+    return o << test::many<T>(s);
+}
+
+template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::map<K, T>& x) {
+    return o << test::many<std::pair<K, T> >(x);
+}
+
+template <class U, class V> std::ostream& operator<<(std::ostream& o, const std::pair<U, V>& p) {
+    return o << "( " << p.first << " , " << p.second << " )";
+}
+
+#if PN_CPP_HAS_CPP11
+template <class K, class T> std::ostream& operator<<(std::ostream& o, const std::unordered_map<K, T>& x) {
+    return o << test::many<std::pair<const K, T> >(x);
+}
+
+template <class T> std::ostream& operator<<(std::ostream& o, const std::forward_list<T>& s) {
+    return o << test::many<T>(s);
+}
+#endif
+}
+
+#endif // TEST_BITS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/test_dummy_container.hpp b/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
new file mode 100644
index 0000000..4af432a
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
@@ -0,0 +1,83 @@
+#ifndef TEST_DUMMY_CONTAINER_HPP
+#define TEST_DUMMY_CONTAINER_HPP
+
+/*
+ * 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/container.hpp"
+#include "proton/event_loop.hpp"
+#include "proton/thread_safe.hpp"
+
+namespace test {
+
+using namespace proton;
+
+
+class dummy_container : public standard_container {
+  public:
+    dummy_container(const std::string cid="") :
+        id_(cid), fail("not implemented for dummy_container") {}
+
+    // Pull in base class functions here so that name search finds all the overloads
+    using standard_container::stop;
+    using standard_container::connect;
+    using standard_container::listen;
+    using standard_container::open_receiver;
+    using standard_container::open_sender;
+
+    returned<connection> connect(const std::string&, const connection_options&) { throw fail; }
+    listener listen(const std::string& , listen_handler& ) { throw fail; }
+    void stop_listening(const std::string&) { throw fail; }
+    void run() { throw fail; }
+    void auto_stop(bool) { throw fail; }
+    void stop(const proton::error_condition& ) { throw fail; }
+    returned<sender> open_sender(const std::string &, const proton::sender_options &, const connection_options&) { throw fail; }
+    returned<receiver> open_receiver( const std::string &, const proton::receiver_options &, const connection_options &) { throw fail; }
+    std::string id() const { return id_; }
+    void client_connection_options(const connection_options &o) { ccopts_ = o; }
+    connection_options client_connection_options() const { return ccopts_; }
+    void server_connection_options(const connection_options &o) { scopts_ = o; }
+    connection_options server_connection_options() const { return scopts_; }
+    void sender_options(const class sender_options &o) { sopts_ = o; }
+    class sender_options sender_options() const { return sopts_; }
+    void receiver_options(const class receiver_options &o) { ropts_ = o; }
+    class receiver_options receiver_options() const { return ropts_; }
+#if PN_CPP_HAS_STD_FUNCTION
+    void schedule(duration, std::function<void()>) { throw fail; }
+#endif
+    void schedule(duration, void_function0&) { throw fail; }
+
+  private:
+    std::string id_;
+    connection_options ccopts_, scopts_;
+    class sender_options sopts_;
+    class receiver_options ropts_;
+    std::runtime_error fail;
+};
+
+class dummy_event_loop : public event_loop {
+#if PN_CPP_HAS_CPP11
+    bool inject(std::function<void()> f) PN_CPP_OVERRIDE { f(); return true; }
+#endif
+    bool inject(proton::void_function0& h) PN_CPP_OVERRIDE { h(); return true; }
+};
+
+}
+
+#endif // TEST_DUMMY_CONTAINER_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/include/types_internal.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/types_internal.hpp b/proton-c/bindings/cpp/src/include/types_internal.hpp
new file mode 100644
index 0000000..bff93a0
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/types_internal.hpp
@@ -0,0 +1,74 @@
+#ifndef TYPES_INTERNAL_HPP
+#define TYPES_INTERNAL_HPP
+/*
+ * 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/internal/type_traits.hpp"
+#include "proton/error.hpp"
+#include "proton/binary.hpp"
+#include <sstream>
+
+///@file
+/// Inline helpers for encode/decode/type conversion/ostream operators.
+
+namespace proton {
+
+/// Byte copy between two objects, only enabled if their sizes are equal.
+template <class T, class U>
+typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) {
+    const char *p = reinterpret_cast<const char*>(&from);
+    std::copy(p, p + sizeof(T), reinterpret_cast<char*>(&to));
+}
+
+inline conversion_error
+make_conversion_error(type_id want, type_id got, const std::string& msg=std::string()) {
+    std::ostringstream s;
+    s << "unexpected type, want: " << want << " got: " << got;
+    if (!msg.empty()) s << ": " << msg;
+    return conversion_error(s.str());
+}
+
+/// Convert std::string to pn_bytes_t
+inline pn_bytes_t pn_bytes(const std::string& s) {
+    pn_bytes_t b = { s.size(), s.empty() ? 0 : const_cast<char*>(&s[0]) };
+    return b;
+}
+
+inline pn_bytes_t pn_bytes(const binary& s) {
+    pn_bytes_t b = { s.size(), s.empty() ? 0 : reinterpret_cast<const char*>(&s[0]) };
+    return b;
+}
+
+inline std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); }
+inline binary bin(const pn_bytes_t& b) { return binary(b.start, b.start+b.size); }
+
+// Save all stream format state, restore in destructor.
+struct ios_guard {
+    std::ios &guarded;
+    std::ios old;
+    ios_guard(std::ios& x) : guarded(x), old(0) { old.copyfmt(guarded); }
+    ~ios_guard() { guarded.copyfmt(old); }
+};
+
+// Convert a char (signed or unsigned) into an unsigned 1 byte integer that will ostream
+// as a numeric byte value, not a character and will not get sign-extended.
+inline unsigned int printable_byte(uint8_t byte) { return byte; }
+
+}
+#endif // TYPES_INTERNAL_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/messaging_adapter.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.hpp b/proton-c/bindings/cpp/src/messaging_adapter.hpp
deleted file mode 100644
index 5371eec..0000000
--- a/proton-c/bindings/cpp/src/messaging_adapter.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef PROTON_CPP_MESSAGING_ADAPTER_H
-#define PROTON_CPP_MESSAGING_ADAPTER_H
-
-/*
- *
- * 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/messaging_handler.hpp"
-
-#include "proton_handler.hpp"
-
-#include <proton/event.h>
-#include <proton/reactor.h>
-
-///@cond INTERNAL
-
-namespace proton {
-
-/// Convert the low level proton-c events to the higher level proton::messaging_handler calls
-class messaging_adapter : public proton_handler
-{
-  public:
-    messaging_adapter(messaging_handler &delegate) : delegate_(delegate) {}
-
-    void on_reactor_init(proton_event &e);
-    void on_reactor_final(proton_event & e);
-    void on_link_flow(proton_event &e);
-    void on_delivery(proton_event &e);
-    void on_connection_remote_open(proton_event &e);
-    void on_connection_remote_close(proton_event &e);
-    void on_session_remote_open(proton_event &e);
-    void on_session_remote_close(proton_event &e);
-    void on_link_local_open(proton_event &e);
-    void on_link_remote_open(proton_event &e);
-    void on_link_remote_detach(proton_event & e);
-    void on_link_remote_close(proton_event &e);
-    void on_transport_closed(proton_event &e);
-
-  private:
-    messaging_handler &delegate_;  // The handler for generated messaging_event's
-};
-
-}
-///@endcond INTERNAL
-#endif  /*!PROTON_CPP_MESSAGING_ADAPTER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8c3aa3a5/proton-c/bindings/cpp/src/msg.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/msg.hpp b/proton-c/bindings/cpp/src/msg.hpp
deleted file mode 100644
index b24b25c..0000000
--- a/proton-c/bindings/cpp/src/msg.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef PROTON_MSG_H
-#define PROTON_MSG_H
-
-/*
- *
- * 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 <sstream>
-#include <iostream>
-
-namespace proton {
-
-/** A simple facade for std::ostringstream that allows
- * in place construction of a message and automatic conversion
- * to string.
- * E.g.
- *@code
- * void foo(const std::string&);
- * foo(msg() << "hello " << 32);
- *@endcode
- * Will construct the string "hello 32" and pass it to foo()
- */
-struct msg {
-    std::ostringstream os;
-    msg() {}
-    msg(const msg& m) : os(m.str()) {}
-    std::string str() const { return os.str(); }
-    operator std::string() const { return str(); }
-    template <class T> msg& operator<<(const T& t) { os << t; return *this; }
-};
-
-inline std::ostream& operator<<(std::ostream& o, const msg& m) { return o << m.str(); }
-
-/** Construct a message using operator << and append (file:line) */
-#define QUOTe_(x) #x
-#define QUOTE(x) QUOTe_(x)
-#define MSG(message) (::proton::msg() << message)
-
-}
-
-#endif  /*!PROTON_MSG_H*/


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


[49/50] [abbrv] qpid-proton git commit: PROTON-1338: Go: update `go get`

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/electron_test.go
----------------------------------------------------------------------
diff --cc electron/electron_test.go
index 0000000,0000000..294e952
new file mode 100644
--- /dev/null
+++ b/electron/electron_test.go
@@@ -1,0 -1,0 +1,546 @@@
++/*
++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 electron
++
++import (
++	"fmt"
++	"net"
++	"path"
++	"qpid.apache.org/amqp"
++	"reflect"
++	"runtime"
++	"testing"
++	"time"
++)
++
++func fatalIf(t *testing.T, err error) {
++	if err != nil {
++		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
++		if ok {
++			_, file = path.Split(file)
++		}
++		t.Fatalf("(from %s:%d) %v", file, line, err)
++	}
++}
++
++func errorIf(t *testing.T, err error) {
++	if err != nil {
++		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
++		if ok {
++			_, file = path.Split(file)
++		}
++		t.Errorf("(from %s:%d) %v", file, line, err)
++	}
++}
++
++func checkEqual(want interface{}, got interface{}) error {
++	if !reflect.DeepEqual(want, got) {
++		return fmt.Errorf("%#v != %#v", want, got)
++	}
++	return nil
++}
++
++// Start a server, return listening addr and channel for incoming Connections.
++func newServer(t *testing.T, cont Container, opts ...ConnectionOption) (net.Addr, <-chan Connection) {
++	listener, err := net.Listen("tcp", "")
++	fatalIf(t, err)
++	addr := listener.Addr()
++	ch := make(chan Connection)
++	go func() {
++		conn, err := listener.Accept()
++		c, err := cont.Connection(conn, append([]ConnectionOption{Server()}, opts...)...)
++		fatalIf(t, err)
++		ch <- c
++	}()
++	return addr, ch
++}
++
++// Open a client connection and session, return the session.
++func newClient(t *testing.T, cont Container, addr net.Addr, opts ...ConnectionOption) Session {
++	conn, err := net.Dial(addr.Network(), addr.String())
++	fatalIf(t, err)
++	c, err := cont.Connection(conn, opts...)
++	fatalIf(t, err)
++	sn, err := c.Session()
++	fatalIf(t, err)
++	return sn
++}
++
++// Return client and server ends of the same connection.
++func newClientServerOpts(t *testing.T, copts []ConnectionOption, sopts []ConnectionOption) (client Session, server Connection) {
++	addr, ch := newServer(t, NewContainer("test-server"), sopts...)
++	client = newClient(t, NewContainer("test-client"), addr, copts...)
++	return client, <-ch
++}
++
++// Return client and server ends of the same connection.
++func newClientServer(t *testing.T) (client Session, server Connection) {
++	return newClientServerOpts(t, nil, nil)
++}
++
++// Close client and server
++func closeClientServer(client Session, server Connection) {
++	client.Connection().Close(nil)
++	server.Close(nil)
++}
++
++// Send a message one way with a client sender and server receiver, verify ack.
++func TestClientSendServerReceive(t *testing.T) {
++	nLinks := 3
++	nMessages := 3
++
++	rchan := make(chan Receiver, nLinks)
++	client, server := newClientServer(t)
++	go func() {
++		for in := range server.Incoming() {
++			switch in := in.(type) {
++			case *IncomingReceiver:
++				in.SetCapacity(1)
++				in.SetPrefetch(false)
++				rchan <- in.Accept().(Receiver)
++			default:
++				in.Accept()
++			}
++		}
++	}()
++
++	defer func() { closeClientServer(client, server) }()
++
++	s := make([]Sender, nLinks)
++	for i := 0; i < nLinks; i++ {
++		var err error
++		s[i], err = client.Sender(Target(fmt.Sprintf("foo%d", i)))
++		if err != nil {
++			t.Fatal(err)
++		}
++	}
++	r := make([]Receiver, nLinks)
++	for i := 0; i < nLinks; i++ {
++		r[i] = <-rchan
++	}
++
++	for i := 0; i < nLinks; i++ {
++		for j := 0; j < nMessages; j++ {
++			// Client send
++			ack := make(chan Outcome, 1)
++			sendDone := make(chan struct{})
++			go func() {
++				defer close(sendDone)
++				m := amqp.NewMessageWith(fmt.Sprintf("foobar%v-%v", i, j))
++				var err error
++				s[i].SendAsync(m, ack, "testing")
++				if err != nil {
++					t.Fatal(err)
++				}
++			}()
++
++			// Server recieve
++			rm, err := r[i].Receive()
++			if err != nil {
++				t.Fatal(err)
++			}
++			if want, got := interface{}(fmt.Sprintf("foobar%v-%v", i, j)), rm.Message.Body(); want != got {
++				t.Errorf("%#v != %#v", want, got)
++			}
++
++			// Should not be acknowledged on client yet
++			<-sendDone
++			select {
++			case <-ack:
++				t.Errorf("unexpected ack")
++			default:
++			}
++
++			// Server send ack
++			if err := rm.Reject(); err != nil {
++				t.Error(err)
++			}
++			// Client get ack.
++			if a := <-ack; a.Value != "testing" || a.Error != nil || a.Status != Rejected {
++				t.Error("unexpected ack: ", a.Status, a.Error, a.Value)
++			}
++		}
++	}
++}
++
++func TestClientReceiver(t *testing.T) {
++	nMessages := 3
++	client, server := newClientServer(t)
++	go func() {
++		for in := range server.Incoming() {
++			switch in := in.(type) {
++			case *IncomingSender:
++				s := in.Accept().(Sender)
++				go func() {
++					for i := int32(0); i < int32(nMessages); i++ {
++						out := s.SendSync(amqp.NewMessageWith(i))
++						if out.Error != nil {
++							t.Error(out.Error)
++							return
++						}
++					}
++					s.Close(nil)
++				}()
++			default:
++				in.Accept()
++			}
++		}
++	}()
++
++	r, err := client.Receiver(Source("foo"))
++	if err != nil {
++		t.Fatal(err)
++	}
++	for i := int32(0); i < int32(nMessages); i++ {
++		rm, err := r.Receive()
++		if err != nil {
++			if err != Closed {
++				t.Error(err)
++			}
++			break
++		}
++		if err := rm.Accept(); err != nil {
++			t.Error(err)
++		}
++		if b, ok := rm.Message.Body().(int32); !ok || b != i {
++			t.Errorf("want %v, true got %v, %v", i, b, ok)
++		}
++	}
++	server.Close(nil)
++	client.Connection().Close(nil)
++}
++
++// Test timeout versions of waiting functions.
++func TestTimeouts(t *testing.T) {
++	var err error
++	rchan := make(chan Receiver, 1)
++	client, server := newClientServer(t)
++	go func() {
++		for i := range server.Incoming() {
++			switch i := i.(type) {
++			case *IncomingReceiver:
++				i.SetCapacity(1)
++				i.SetPrefetch(false)
++				rchan <- i.Accept().(Receiver) // Issue credit only on receive
++			default:
++				i.Accept()
++			}
++		}
++	}()
++	defer func() { closeClientServer(client, server) }()
++
++	// Open client sender
++	snd, err := client.Sender(Target("test"))
++	if err != nil {
++		t.Fatal(err)
++	}
++	rcv := <-rchan
++
++	// Test send with timeout
++	short := time.Millisecond
++	long := time.Second
++	m := amqp.NewMessage()
++	if err := snd.SendSyncTimeout(m, 0).Error; err != Timeout { // No credit, expect timeout.
++		t.Error("want Timeout got", err)
++	}
++	if err := snd.SendSyncTimeout(m, short).Error; err != Timeout { // No credit, expect timeout.
++		t.Error("want Timeout got", err)
++	}
++	// Test receive with timeout
++	if _, err = rcv.ReceiveTimeout(0); err != Timeout { // No credit, expect timeout.
++		t.Error("want Timeout got", err)
++	}
++	// Test receive with timeout
++	if _, err = rcv.ReceiveTimeout(short); err != Timeout { // No credit, expect timeout.
++		t.Error("want Timeout got", err)
++	}
++	// There is now a credit on the link due to receive
++	ack := make(chan Outcome)
++	snd.SendAsyncTimeout(m, ack, nil, short)
++	// Disposition should timeout
++	select {
++	case <-ack:
++		t.Errorf("want Timeout got %#v", ack)
++	case <-time.After(short):
++	}
++
++	// Receive and accept
++	rm, err := rcv.ReceiveTimeout(long)
++	if err != nil {
++		t.Fatal(err)
++	}
++	if err := rm.Accept(); err != nil {
++		t.Fatal(err)
++	}
++	// Sender get ack
++	if a := <-ack; a.Status != Accepted || a.Error != nil {
++		t.Errorf("want (accepted, nil) got %#v", a)
++	}
++}
++
++// A server that returns the opposite end of each client link via channels.
++type pairs struct {
++	t        *testing.T
++	client   Session
++	server   Connection
++	rchan    chan Receiver
++	schan    chan Sender
++	capacity int
++	prefetch bool
++}
++
++func newPairs(t *testing.T, capacity int, prefetch bool) *pairs {
++	p := &pairs{t: t, rchan: make(chan Receiver, 1), schan: make(chan Sender, 1)}
++	p.client, p.server = newClientServer(t)
++	go func() {
++		for i := range p.server.Incoming() {
++			switch i := i.(type) {
++			case *IncomingReceiver:
++				i.SetCapacity(capacity)
++				i.SetPrefetch(prefetch)
++				p.rchan <- i.Accept().(Receiver)
++			case *IncomingSender:
++				p.schan <- i.Accept().(Sender)
++			default:
++				i.Accept()
++			}
++		}
++	}()
++	return p
++}
++
++func (p *pairs) close() {
++	closeClientServer(p.client, p.server)
++}
++
++// Return a client sender and server receiver
++func (p *pairs) senderReceiver() (Sender, Receiver) {
++	snd, err := p.client.Sender()
++	fatalIf(p.t, err)
++	rcv := <-p.rchan
++	return snd, rcv
++}
++
++// Return a client receiver and server sender
++func (p *pairs) receiverSender() (Receiver, Sender) {
++	rcv, err := p.client.Receiver()
++	fatalIf(p.t, err)
++	snd := <-p.schan
++	return rcv, snd
++}
++
++type result struct {
++	label string
++	err   error
++	value interface{}
++}
++
++func (r result) String() string { return fmt.Sprintf("%v(%v)", r.err, r.label) }
++
++func doSend(snd Sender, results chan result) {
++	err := snd.SendSync(amqp.NewMessage()).Error
++	results <- result{"send", err, nil}
++}
++
++func doReceive(rcv Receiver, results chan result) {
++	msg, err := rcv.Receive()
++	results <- result{"receive", err, msg}
++}
++
++func doDisposition(ack <-chan Outcome, results chan result) {
++	results <- result{"disposition", (<-ack).Error, nil}
++}
++
++// Senders get credit immediately if receivers have prefetch set
++func TestSendReceivePrefetch(t *testing.T) {
++	pairs := newPairs(t, 1, true)
++	s, r := pairs.senderReceiver()
++	s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should not block for credit.
++	if _, err := r.Receive(); err != nil {
++		t.Error(err)
++	}
++}
++
++// Senders do not get credit till Receive() if receivers don't have prefetch
++func TestSendReceiveNoPrefetch(t *testing.T) {
++	pairs := newPairs(t, 1, false)
++	s, r := pairs.senderReceiver()
++	done := make(chan struct{}, 1)
++	go func() {
++		s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should block for credit.
++		close(done)
++	}()
++	select {
++	case <-done:
++		t.Errorf("send should be blocked on credit")
++	default:
++		if _, err := r.Receive(); err != nil {
++			t.Error(err)
++		} else {
++			<-done
++		} // Should be unblocked now
++	}
++}
++
++// Test that closing Links interrupts blocked link functions.
++func TestLinkCloseInterrupt(t *testing.T) {
++	want := amqp.Error{Name: "x", Description: "all bad"}
++	pairs := newPairs(t, 1, false)
++	results := make(chan result) // Collect expected errors
++
++	// Note closing the link does not interrupt Send() calls, the AMQP spec says
++	// that deliveries can be settled after the link is closed.
++
++	// Receiver.Close() interrupts Receive()
++	snd, rcv := pairs.senderReceiver()
++	go doReceive(rcv, results)
++	rcv.Close(want)
++	if r := <-results; want != r.err {
++		t.Errorf("want %#v got %#v", want, r)
++	}
++
++	// Remote Sender.Close() interrupts Receive()
++	snd, rcv = pairs.senderReceiver()
++	go doReceive(rcv, results)
++	snd.Close(want)
++	if r := <-results; want != r.err {
++		t.Errorf("want %#v got %#v", want, r)
++	}
++}
++
++// Test closing the server end of a connection.
++func TestConnectionCloseInterrupt1(t *testing.T) {
++	want := amqp.Error{Name: "x", Description: "bad"}
++	pairs := newPairs(t, 1, true)
++	results := make(chan result) // Collect expected errors
++
++	// Connection.Close() interrupts Send, Receive, Disposition.
++	snd, rcv := pairs.senderReceiver()
++	go doSend(snd, results)
++
++	if _, err := rcv.Receive(); err != nil {
++		t.Error("receive", err)
++	}
++	rcv, snd = pairs.receiverSender()
++	go doReceive(rcv, results)
++
++	snd, rcv = pairs.senderReceiver()
++	ack := snd.SendWaitable(amqp.NewMessage())
++	if _, err := rcv.Receive(); err != nil {
++		t.Error("receive", err)
++	}
++	go doDisposition(ack, results)
++
++	pairs.server.Close(want)
++	for i := 0; i < 3; i++ {
++		if r := <-results; want != r.err {
++			t.Errorf("want %v got %v", want, r)
++		}
++	}
++}
++
++// Test closing the client end of the connection.
++func TestConnectionCloseInterrupt2(t *testing.T) {
++	want := amqp.Error{Name: "x", Description: "bad"}
++	pairs := newPairs(t, 1, true)
++	results := make(chan result) // Collect expected errors
++
++	// Connection.Close() interrupts Send, Receive, Disposition.
++	snd, rcv := pairs.senderReceiver()
++	go doSend(snd, results)
++	if _, err := rcv.Receive(); err != nil {
++		t.Error("receive", err)
++	}
++
++	rcv, snd = pairs.receiverSender()
++	go doReceive(rcv, results)
++
++	snd, rcv = pairs.senderReceiver()
++	ack := snd.SendWaitable(amqp.NewMessage())
++	go doDisposition(ack, results)
++
++	pairs.client.Connection().Close(want)
++	for i := 0; i < 3; i++ {
++		if r := <-results; want != r.err {
++			t.Errorf("want %v got %v", want, r.err)
++		}
++	}
++}
++
++func heartbeat(c Connection) time.Duration {
++	return c.(*connection).engine.Transport().RemoteIdleTimeout()
++}
++
++func TestHeartbeat(t *testing.T) {
++	client, server := newClientServerOpts(t,
++		[]ConnectionOption{Heartbeat(102 * time.Millisecond)},
++		nil)
++	defer closeClientServer(client, server)
++
++	var serverHeartbeat time.Duration
++
++	go func() {
++		for in := range server.Incoming() {
++			switch in := in.(type) {
++			case *IncomingConnection:
++				serverHeartbeat = in.Heartbeat()
++				in.AcceptConnection(Heartbeat(101 * time.Millisecond))
++			default:
++				in.Accept()
++			}
++		}
++	}()
++
++	// Freeze the server to stop it sending heartbeats.
++	unfreeze := make(chan bool)
++	defer close(unfreeze)
++	freeze := func() error { return server.(*connection).engine.Inject(func() { <-unfreeze }) }
++
++	fatalIf(t, client.Sync())
++	errorIf(t, checkEqual(101*time.Millisecond, heartbeat(client.Connection())))
++	errorIf(t, checkEqual(102*time.Millisecond, serverHeartbeat))
++	errorIf(t, client.Connection().Error())
++
++	// Freeze the server for less than a heartbeat
++	fatalIf(t, freeze())
++	time.Sleep(50 * time.Millisecond)
++	unfreeze <- true
++	// Make sure server is still responding.
++	s, err := client.Sender()
++	errorIf(t, err)
++	errorIf(t, s.Sync())
++
++	// Freeze the server till the client times out the connection
++	fatalIf(t, freeze())
++	select {
++	case <-client.Done():
++		if amqp.ResourceLimitExceeded != client.Error().(amqp.Error).Name {
++			t.Error("bad timeout error:", client.Error())
++		}
++	case <-time.After(400 * time.Millisecond):
++		t.Error("connection failed to time out")
++	}
++
++	unfreeze <- true // Unfreeze the server
++	<-server.Done()
++	if amqp.ResourceLimitExceeded != server.Error().(amqp.Error).Name {
++		t.Error("bad timeout error:", server.Error())
++	}
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/endpoint.go
----------------------------------------------------------------------
diff --cc electron/endpoint.go
index fc701c6,0000000..ca93e5b
mode 100644,000000..100644
--- a/electron/endpoint.go
+++ b/electron/endpoint.go
@@@ -1,102 -1,0 +1,182 @@@
 +/*
 +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 electron
 +
 +import (
++	"fmt"
 +	"io"
 +	"qpid.apache.org/proton"
 +)
 +
 +// Closed is an alias for io.EOF. It is returned as an error when an endpoint
 +// was closed cleanly.
 +var Closed = io.EOF
 +
- // Endpoint is the common interface for Connection, Session, Link, Sender and Receiver.
++// Endpoint is the local end of a communications channel to the remote peer
++// process.  The following interface implement Endpoint: Connection, Session,
++// Sender and Receiver.
 +//
- // Endpoints can be created locally or by the remote peer. You must Open() an
- // endpoint before you can use it. Some endpoints have additional Set*() methods
- // that must be called before Open() to take effect, see Connection, Session,
- // Link, Sender and Receiver for details.
++// You can create an endpoint with functions on Container, Connection and
++// Session. You can accept incoming endpoints from the remote peer using
++// Connection.Incoming()
 +//
 +type Endpoint interface {
 +	// Close an endpoint and signal an error to the remote end if error != nil.
 +	Close(error)
 +
 +	// String is a human readable identifier, useful for debugging and logging.
 +	String() string
 +
 +	// Error returns nil if the endpoint is open, otherwise returns an error.
 +	// Error() == Closed means the endpoint was closed without error.
 +	Error() error
 +
- 	// Connection containing the endpoint
++	// Connection is the connection associated with this endpoint.
 +	Connection() Connection
 +
 +	// Done returns a channel that will close when the endpoint closes.
- 	// Error() will contain the reason.
++	// After Done() has closed, Error() will return the reason for closing.
 +	Done() <-chan struct{}
 +
++	// Sync() waits for the remote peer to confirm the endpoint is active or
++	// reject it with an error. You can call it immediately on new endpoints
++	// for more predictable error handling.
++	//
++	// AMQP is an asynchronous protocol. It is legal to create an endpoint and
++	// start using it without waiting for confirmation. This avoids a needless
++	// delay in the non-error case and throughput by "assuming the best".
++	//
++	// However if there *is* an error, these "optimistic" actions will fail. The
++	// endpoint and its children will be closed with an error. The error will only
++	// be detected when you try to use one of these endpoints or call Sync()
++	Sync() error
++
 +	// Called in handler goroutine when endpoint is remotely closed.
 +	closed(err error) error
++	wakeSync()
 +}
 +
- // DEVELOPER NOTES
- //
- // An electron.Endpoint corresponds to a proton.Endpoint, which can be invalidated
- //
++// Base implementation for Endpoint
 +type endpoint struct {
- 	err  proton.ErrorHolder
- 	str  string // Must be set by the value that embeds endpoint.
- 	done chan struct{}
++	err    proton.ErrorHolder
++	str    string // String() return value.
++	done   chan struct{}
++	active chan struct{}
 +}
 +
- func (e *endpoint) init(s string) { e.str = s; e.done = make(chan struct{}) }
++func (e *endpoint) init(s string) {
++	e.str = s
++	e.done = make(chan struct{})
++	e.active = make(chan struct{})
++}
++
++// Called in proton goroutine on remote open.
++func (e *endpoint) wakeSync() {
++	select { // Close active channel if not already closed.
++	case <-e.active:
++	default:
++		close(e.active)
++	}
++}
 +
- // Called in handler on a Closed event. Marks the endpoint as closed and the corresponding
- // proton.Endpoint pointer as invalid. Injected functions should check Error() to ensure
- // the pointer has not been invalidated.
++// Called in proton goroutine (from handler) on a Closed or Disconnected event.
 +//
- // Returns the error stored on the endpoint, which may not be different to err if there was
- // already a n error
++// Set err if there is not already an error on the endpoint.
++// Return Error()
 +func (e *endpoint) closed(err error) error {
 +	select {
 +	case <-e.done:
 +		// Already closed
 +	default:
 +		e.err.Set(err)
 +		e.err.Set(Closed)
++		e.wakeSync() // Make sure we wake up Sync()
 +		close(e.done)
 +	}
- 	return e.err.Get()
++	return e.Error()
 +}
 +
 +func (e *endpoint) String() string { return e.str }
 +
 +func (e *endpoint) Error() error { return e.err.Get() }
 +
 +func (e *endpoint) Done() <-chan struct{} { return e.done }
 +
++func (e *endpoint) Sync() error {
++	<-e.active
++	return e.Error()
++}
++
 +// Call in proton goroutine to initiate closing an endpoint locally
 +// handler will complete the close when remote end closes.
 +func localClose(ep proton.Endpoint, err error) {
 +	if ep.State().LocalActive() {
 +		proton.CloseError(ep, err)
 +	}
 +}
++
++// Incoming is the interface for incoming endpoints, see Connection.Incoming()
++//
++// Call Incoming.Accept() to open the endpoint or Incoming.Reject() to close it
++// with optional error
++//
++// Implementing types are *IncomingConnection, *IncomingSession, *IncomingSender
++// and *IncomingReceiver. Each type provides methods to examine the incoming
++// endpoint request and set configuration options for the local endpoint
++// before calling Accept() or Reject()
++type Incoming interface {
++	// Accept and open the endpoint.
++	Accept() Endpoint
++
++	// Reject the endpoint with an error
++	Reject(error)
++
++	// wait for and call the accept function, call in proton goroutine.
++	wait() error
++	pEndpoint() proton.Endpoint
++}
++
++type incoming struct {
++	pep      proton.Endpoint
++	acceptCh chan func() error
++}
++
++func makeIncoming(e proton.Endpoint) incoming {
++	return incoming{pep: e, acceptCh: make(chan func() error)}
++}
++
++func (in *incoming) String() string   { return fmt.Sprintf("%s: %s", in.pep.Type(), in.pep) }
++func (in *incoming) Reject(err error) { in.acceptCh <- func() error { return err } }
++
++// Call in proton goroutine, wait for and call the accept function.
++func (in *incoming) wait() error { return (<-in.acceptCh)() }
++
++func (in *incoming) pEndpoint() proton.Endpoint { return in.pep }
++
++// Called in app goroutine to send an accept function to proton and return the resulting endpoint.
++func (in *incoming) accept(f func() Endpoint) Endpoint {
++	done := make(chan Endpoint)
++	in.acceptCh <- func() error {
++		ep := f()
++		done <- ep
++		return nil
++	}
++	return <-done
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/ex_client_server_test.go
----------------------------------------------------------------------
diff --cc electron/ex_client_server_test.go
index 0000000,0000000..93f275b
new file mode 100644
--- /dev/null
+++ b/electron/ex_client_server_test.go
@@@ -1,0 -1,0 +1,81 @@@
++package electron_test
++
++import (
++	"fmt"
++	"net"
++	"qpid.apache.org/amqp"
++	"qpid.apache.org/electron"
++)
++
++//  Print errors
++func check(msg string, err error) bool {
++	if err != nil {
++		fmt.Printf("%s: %s\n", msg, err)
++	}
++	return err == nil
++}
++
++func runServer(cont electron.Container, l net.Listener) {
++	for c, err := cont.Accept(l); check("accept connection", err); c, err = cont.Accept(l) {
++		go func() { // Process connections concurrently, accepting AMQP endpoints
++			for in := range c.Incoming() {
++				ep := in.Accept() // Accept all endpoints
++				go func() {       // Process endpoints concurrently
++					switch ep := ep.(type) {
++					case electron.Sender:
++						m := amqp.NewMessageWith("hello yourself")
++						fmt.Printf("server %q sending %q\n", ep.Source(), m.Body())
++						ep.SendForget(m) // One-way send, client does not need to Accept.
++					case electron.Receiver:
++						if rm, err := ep.Receive(); check("server receive", err) {
++							fmt.Printf("server %q received %q\n", ep.Target(), rm.Message.Body())
++							err := rm.Accept() // Client is waiting for Accept.
++							check("accept message", err)
++						}
++					}
++				}()
++			}
++		}()
++	}
++}
++
++func startServer() (addr net.Addr) {
++	cont := electron.NewContainer("server")
++	if l, err := net.Listen("tcp", ""); check("listen", err) {
++		addr = l.Addr()
++		go runServer(cont, l)
++	}
++	return addr
++}
++
++// Connect to addr and send/receive a message.
++func client(addr net.Addr) {
++	if c, err := electron.Dial(addr.Network(), addr.String()); check("dial", err) {
++		defer c.Close(nil)
++		if s, err := c.Sender(electron.Target("target")); check("sender", err) {
++			fmt.Printf("client sending\n")
++			s.SendSync(amqp.NewMessageWith("hello")) // Send and wait for server to Accept()
++		}
++		if r, err := c.Receiver(electron.Source("source")); check("receiver", err) {
++			if rm, err := r.Receive(); err == nil {
++				fmt.Printf("client received %q\n", rm.Message.Body())
++			}
++		}
++	}
++}
++
++// Example client and server communicating via AMQP over a TCP/IP connection.
++//
++// Normally client and server would be separate processes.
++// For more realistic examples:
++//     https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
++//
++func Example_clientServer() {
++	addr := startServer()
++	client(addr)
++	// Output:
++	// client sending
++	// server "target" received "hello"
++	// server "source" sending "hello yourself"
++	// client received "hello yourself"
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/handler.go
----------------------------------------------------------------------
diff --cc electron/handler.go
index eb53df3,0000000..af1efd6
mode 100644,000000..100644
--- a/electron/handler.go
+++ b/electron/handler.go
@@@ -1,187 -1,0 +1,201 @@@
 +/*
 +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 electron
 +
 +import (
 +	"qpid.apache.org/amqp"
 +	"qpid.apache.org/proton"
 +)
 +
 +// NOTE: methods in this file are called only in the proton goroutine unless otherwise indicated.
 +
 +type handler struct {
 +	delegator    *proton.MessagingAdapter
 +	connection   *connection
 +	links        map[proton.Link]Endpoint
 +	sentMessages map[proton.Delivery]sentMessage
 +	sessions     map[proton.Session]*session
 +}
 +
 +func newHandler(c *connection) *handler {
 +	h := &handler{
 +		connection:   c,
 +		links:        make(map[proton.Link]Endpoint),
 +		sentMessages: make(map[proton.Delivery]sentMessage),
 +		sessions:     make(map[proton.Session]*session),
 +	}
 +	h.delegator = proton.NewMessagingAdapter(h)
 +	// Disable auto features of MessagingAdapter, we do these ourselves.
 +	h.delegator.Prefetch = 0
 +	h.delegator.AutoAccept = false
 +	h.delegator.AutoSettle = false
 +	h.delegator.AutoOpen = false
 +	return h
 +}
 +
 +func (h *handler) linkError(l proton.Link, msg string) {
 +	proton.CloseError(l, amqp.Errorf(amqp.InternalError, "%s for %s %s", msg, l.Type(), l))
 +}
 +
 +func (h *handler) HandleMessagingEvent(t proton.MessagingEvent, e proton.Event) {
 +	switch t {
 +
 +	case proton.MMessage:
 +		if r, ok := h.links[e.Link()].(*receiver); ok {
 +			r.message(e.Delivery())
 +		} else {
 +			h.linkError(e.Link(), "no receiver")
 +		}
 +
 +	case proton.MSettled:
 +		if sm, ok := h.sentMessages[e.Delivery()]; ok {
 +			d := e.Delivery().Remote()
 +			sm.ack <- Outcome{sentStatus(d.Type()), d.Condition().Error(), sm.value}
 +			delete(h.sentMessages, e.Delivery())
 +		}
 +
 +	case proton.MSendable:
 +		if s, ok := h.links[e.Link()].(*sender); ok {
 +			s.sendable()
 +		} else {
 +			h.linkError(e.Link(), "no sender")
 +		}
 +
++	case proton.MConnectionOpening:
++		h.connection.heartbeat = e.Transport().RemoteIdleTimeout()
++		if e.Connection().State().LocalUninit() { // Remotely opened
++			h.incoming(newIncomingConnection(h.connection))
++		}
++		h.connection.wakeSync()
++
 +	case proton.MSessionOpening:
 +		if e.Session().State().LocalUninit() { // Remotely opened
 +			h.incoming(newIncomingSession(h, e.Session()))
 +		}
++		h.sessions[e.Session()].wakeSync()
 +
 +	case proton.MSessionClosed:
 +		h.sessionClosed(e.Session(), proton.EndpointError(e.Session()))
 +
 +	case proton.MLinkOpening:
 +		l := e.Link()
- 		if l.State().LocalActive() { // Already opened locally.
- 			break
- 		}
- 		ss := h.sessions[l.Session()]
- 		if ss == nil {
- 			h.linkError(e.Link(), "no session")
- 			break
- 		}
- 		if l.IsReceiver() {
- 			h.incoming(&IncomingReceiver{makeIncomingLink(ss, l)})
++		if ss := h.sessions[l.Session()]; ss != nil {
++			if l.State().LocalUninit() { // Remotely opened.
++				if l.IsReceiver() {
++					h.incoming(newIncomingReceiver(ss, l))
++				} else {
++					h.incoming(newIncomingSender(ss, l))
++				}
++			}
++			if ep, ok := h.links[l]; ok {
++				ep.wakeSync()
++			} else {
++				h.linkError(l, "no link")
++			}
 +		} else {
- 			h.incoming(&IncomingSender{makeIncomingLink(ss, l)})
++			h.linkError(l, "no session")
 +		}
 +
 +	case proton.MLinkClosing:
 +		e.Link().Close()
 +
 +	case proton.MLinkClosed:
 +		h.linkClosed(e.Link(), proton.EndpointError(e.Link()))
 +
 +	case proton.MConnectionClosing:
 +		h.connection.err.Set(e.Connection().RemoteCondition().Error())
 +
 +	case proton.MConnectionClosed:
- 		h.connectionClosed(proton.EndpointError(e.Connection()))
++		h.shutdown(proton.EndpointError(e.Connection()))
 +
 +	case proton.MDisconnected:
- 		h.connection.err.Set(e.Transport().Condition().Error())
- 		// If err not set at this point (e.g. to Closed) then this is unexpected.
- 		h.connection.err.Set(amqp.Errorf(amqp.IllegalState, "unexpected disconnect on %s", h.connection))
- 
- 		err := h.connection.Error()
- 
- 		for l, _ := range h.links {
- 			h.linkClosed(l, err)
- 		}
- 		h.links = nil
- 		for _, s := range h.sessions {
- 			s.closed(err)
- 		}
- 		h.sessions = nil
- 		for _, sm := range h.sentMessages {
- 			sm.ack <- Outcome{Unacknowledged, err, sm.value}
++		err := e.Transport().Condition().Error()
++		if err == nil {
++			err = amqp.Errorf(amqp.IllegalState, "unexpected disconnect on %s", h.connection)
 +		}
- 		h.sentMessages = nil
++		h.shutdown(err)
 +	}
 +}
 +
 +func (h *handler) incoming(in Incoming) {
 +	var err error
 +	if h.connection.incoming != nil {
 +		h.connection.incoming <- in
++		// Must block until accept/reject, subsequent events may use the incoming endpoint.
 +		err = in.wait()
 +	} else {
 +		err = amqp.Errorf(amqp.NotAllowed, "rejected incoming %s %s",
 +			in.pEndpoint().Type(), in.pEndpoint().String())
 +	}
 +	if err == nil {
 +		in.pEndpoint().Open()
 +	} else {
 +		proton.CloseError(in.pEndpoint(), err)
 +	}
 +}
 +
 +func (h *handler) addLink(pl proton.Link, el Endpoint) {
 +	h.links[pl] = el
 +}
 +
 +func (h *handler) linkClosed(l proton.Link, err error) {
 +	if link, ok := h.links[l]; ok {
- 		link.closed(err)
++		_ = link.closed(err)
 +		delete(h.links, l)
++		l.Free()
 +	}
 +}
 +
 +func (h *handler) sessionClosed(ps proton.Session, err error) {
 +	if s, ok := h.sessions[ps]; ok {
 +		delete(h.sessions, ps)
 +		err = s.closed(err)
 +		for l, _ := range h.links {
 +			if l.Session() == ps {
 +				h.linkClosed(l, err)
 +			}
 +		}
++		ps.Free()
 +	}
 +}
 +
- func (h *handler) connectionClosed(err error) {
++func (h *handler) shutdown(err error) {
 +	err = h.connection.closed(err)
- 	// Close links first to avoid repeated scans of the link list by sessions.
- 	for l, _ := range h.links {
- 		h.linkClosed(l, err)
++	for _, sm := range h.sentMessages {
++		// Don't block but ensure outcome is sent eventually.
++		if sm.ack != nil {
++			o := Outcome{Unacknowledged, err, sm.value}
++			select {
++			case sm.ack <- o:
++			default:
++				go func(ack chan<- Outcome) { ack <- o }(sm.ack) // Deliver it eventually
++			}
++		}
++	}
++	h.sentMessages = nil
++	for _, l := range h.links {
++		_ = l.closed(err)
 +	}
- 	for s, _ := range h.sessions {
- 		h.sessionClosed(s, err)
++	h.links = nil
++	for _, s := range h.sessions {
++		_ = s.closed(err)
 +	}
++	h.sessions = nil
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/link.go
----------------------------------------------------------------------
diff --cc electron/link.go
index 80b4d5c,0000000..1d17894
mode 100644,000000..100644
--- a/electron/link.go
+++ b/electron/link.go
@@@ -1,233 -1,0 +1,221 @@@
 +/*
 +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 electron
 +
 +import (
 +	"fmt"
 +	"qpid.apache.org/proton"
 +)
 +
 +// Settings associated with a link
 +type LinkSettings interface {
 +	// Source address that messages are coming from.
 +	Source() string
 +
 +	// Target address that messages are going to.
 +	Target() string
 +
 +	// Name is a unique name for the link among links between the same
 +	// containers in the same direction. By default generated automatically.
 +	LinkName() string
 +
 +	// IsSender is true if this is the sending end of the link.
 +	IsSender() bool
 +
 +	// IsReceiver is true if this is the receiving end of the link.
 +	IsReceiver() bool
 +
 +	// SndSettle defines when the sending end of the link settles message delivery.
 +	SndSettle() SndSettleMode
 +
 +	// RcvSettle defines when the sending end of the link settles message delivery.
 +	RcvSettle() RcvSettleMode
 +
 +	// Session containing the Link
 +	Session() Session
 +}
 +
 +// LinkOption can be passed when creating a sender or receiver link to set optional configuration.
 +type LinkOption func(*linkSettings)
 +
 +// Source returns a LinkOption that sets address that messages are coming from.
 +func Source(s string) LinkOption { return func(l *linkSettings) { l.source = s } }
 +
 +// Target returns a LinkOption that sets address that messages are going to.
 +func Target(s string) LinkOption { return func(l *linkSettings) { l.target = s } }
 +
 +// LinkName returns a LinkOption that sets the link name.
 +func LinkName(s string) LinkOption { return func(l *linkSettings) { l.target = s } }
 +
 +// SndSettle returns a LinkOption that sets the send settle mode
 +func SndSettle(m SndSettleMode) LinkOption { return func(l *linkSettings) { l.sndSettle = m } }
 +
 +// RcvSettle returns a LinkOption that sets the send settle mode
 +func RcvSettle(m RcvSettleMode) LinkOption { return func(l *linkSettings) { l.rcvSettle = m } }
 +
 +// SndSettleMode returns a LinkOption that defines when the sending end of the
 +// link settles message delivery.
 +type SndSettleMode proton.SndSettleMode
 +
 +// Capacity returns a LinkOption that sets the link capacity
 +func Capacity(n int) LinkOption { return func(l *linkSettings) { l.capacity = n } }
 +
 +// Prefetch returns a LinkOption that sets a receivers pre-fetch flag. Not relevant for a sender.
 +func Prefetch(p bool) LinkOption { return func(l *linkSettings) { l.prefetch = p } }
 +
 +// AtMostOnce returns a LinkOption that sets "fire and forget" mode, messages
 +// are sent but no acknowledgment is received, messages can be lost if there is
 +// a network failure. Sets SndSettleMode=SendSettled and RcvSettleMode=RcvFirst
 +func AtMostOnce() LinkOption {
 +	return func(l *linkSettings) {
 +		SndSettle(SndSettled)(l)
 +		RcvSettle(RcvFirst)(l)
 +	}
 +}
 +
 +// AtLeastOnce returns a LinkOption that requests acknowledgment for every
 +// message, acknowledgment indicates the message was definitely received. In the
 +// event of a failure, unacknowledged messages can be re-sent but there is a
 +// chance that the message will be received twice in this case.  Sets
 +// SndSettleMode=SndUnsettled and RcvSettleMode=RcvFirst
 +func AtLeastOnce() LinkOption {
 +	return func(l *linkSettings) {
 +		SndSettle(SndUnsettled)(l)
 +		RcvSettle(RcvFirst)(l)
 +	}
 +}
 +
 +const (
 +	// Messages are sent unsettled
 +	SndUnsettled = SndSettleMode(proton.SndUnsettled)
 +	// Messages are sent already settled
 +	SndSettled = SndSettleMode(proton.SndSettled)
 +	// Sender can send either unsettled or settled messages.
 +	SendMixed = SndSettleMode(proton.SndMixed)
 +)
 +
 +// RcvSettleMode defines when the receiving end of the link settles message delivery.
 +type RcvSettleMode proton.RcvSettleMode
 +
 +const (
 +	// Receiver settles first.
 +	RcvFirst = RcvSettleMode(proton.RcvFirst)
 +	// Receiver waits for sender to settle before settling.
 +	RcvSecond = RcvSettleMode(proton.RcvSecond)
 +)
 +
 +type linkSettings struct {
 +	source    string
 +	target    string
 +	linkName  string
 +	isSender  bool
 +	sndSettle SndSettleMode
 +	rcvSettle RcvSettleMode
 +	capacity  int
 +	prefetch  bool
 +	session   *session
- 	eLink     proton.Link
++	pLink     proton.Link
 +}
 +
 +type link struct {
 +	endpoint
 +	linkSettings
 +}
 +
 +func (l *linkSettings) Source() string           { return l.source }
 +func (l *linkSettings) Target() string           { return l.target }
 +func (l *linkSettings) LinkName() string         { return l.linkName }
 +func (l *linkSettings) IsSender() bool           { return l.isSender }
 +func (l *linkSettings) IsReceiver() bool         { return !l.isSender }
 +func (l *linkSettings) SndSettle() SndSettleMode { return l.sndSettle }
 +func (l *linkSettings) RcvSettle() RcvSettleMode { return l.rcvSettle }
 +
 +func (l *link) Session() Session       { return l.session }
 +func (l *link) Connection() Connection { return l.session.Connection() }
 +func (l *link) engine() *proton.Engine { return l.session.connection.engine }
 +func (l *link) handler() *handler      { return l.session.connection.handler }
 +
 +// Open a link and return the linkSettings.
 +func makeLocalLink(sn *session, isSender bool, setting ...LinkOption) (linkSettings, error) {
 +	l := linkSettings{
 +		isSender: isSender,
 +		capacity: 1,
 +		prefetch: false,
 +		session:  sn,
 +	}
 +	for _, set := range setting {
 +		set(&l)
 +	}
 +	if l.linkName == "" {
 +		l.linkName = l.session.connection.container.nextLinkName()
 +	}
 +	if l.IsSender() {
- 		l.eLink = l.session.eSession.Sender(l.linkName)
++		l.pLink = l.session.pSession.Sender(l.linkName)
 +	} else {
- 		l.eLink = l.session.eSession.Receiver(l.linkName)
++		l.pLink = l.session.pSession.Receiver(l.linkName)
 +	}
- 	if l.eLink.IsNil() {
- 		return l, fmt.Errorf("cannot create link %s", l.eLink)
++	if l.pLink.IsNil() {
++		return l, fmt.Errorf("cannot create link %s", l.pLink)
 +	}
- 	l.eLink.Source().SetAddress(l.source)
- 	l.eLink.Target().SetAddress(l.target)
- 	l.eLink.SetSndSettleMode(proton.SndSettleMode(l.sndSettle))
- 	l.eLink.SetRcvSettleMode(proton.RcvSettleMode(l.rcvSettle))
- 	l.eLink.Open()
++	l.pLink.Source().SetAddress(l.source)
++	l.pLink.Target().SetAddress(l.target)
++	l.pLink.SetSndSettleMode(proton.SndSettleMode(l.sndSettle))
++	l.pLink.SetRcvSettleMode(proton.RcvSettleMode(l.rcvSettle))
++	l.pLink.Open()
 +	return l, nil
 +}
 +
- type incomingLink struct {
- 	incoming
- 	linkSettings
- 	eLink proton.Link
- 	sn    *session
- }
- 
- // Set up a link from an incoming proton.Link.
- func makeIncomingLink(sn *session, eLink proton.Link) incomingLink {
- 	l := incomingLink{
- 		incoming: makeIncoming(eLink),
- 		linkSettings: linkSettings{
- 			isSender:  eLink.IsSender(),
- 			source:    eLink.RemoteSource().Address(),
- 			target:    eLink.RemoteTarget().Address(),
- 			linkName:  eLink.Name(),
- 			sndSettle: SndSettleMode(eLink.RemoteSndSettleMode()),
- 			rcvSettle: RcvSettleMode(eLink.RemoteRcvSettleMode()),
- 			capacity:  1,
- 			prefetch:  false,
- 			eLink:     eLink,
- 			session:   sn,
- 		},
++func makeIncomingLinkSettings(pLink proton.Link, sn *session) linkSettings {
++	return linkSettings{
++		isSender:  pLink.IsSender(),
++		source:    pLink.RemoteSource().Address(),
++		target:    pLink.RemoteTarget().Address(),
++		linkName:  pLink.Name(),
++		sndSettle: SndSettleMode(pLink.RemoteSndSettleMode()),
++		rcvSettle: RcvSettleMode(pLink.RemoteRcvSettleMode()),
++		capacity:  1,
++		prefetch:  false,
++		pLink:     pLink,
++		session:   sn,
 +	}
- 	return l
 +}
 +
 +// Not part of Link interface but use by Sender and Receiver.
 +func (l *link) Credit() (credit int, err error) {
 +	err = l.engine().InjectWait(func() error {
 +		if l.Error() != nil {
 +			return l.Error()
 +		}
- 		credit = l.eLink.Credit()
++		credit = l.pLink.Credit()
 +		return nil
 +	})
 +	return
 +}
 +
 +// Not part of Link interface but use by Sender and Receiver.
 +func (l *link) Capacity() int { return l.capacity }
 +
 +func (l *link) Close(err error) {
- 	l.engine().Inject(func() {
++	_ = l.engine().Inject(func() {
 +		if l.Error() == nil {
- 			localClose(l.eLink, err)
++			localClose(l.pLink, err)
 +		}
 +	})
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/receiver.go
----------------------------------------------------------------------
diff --cc electron/receiver.go
index f2b7a52,0000000..781fd7c
mode 100644,000000..100644
--- a/electron/receiver.go
+++ b/electron/receiver.go
@@@ -1,225 -1,0 +1,236 @@@
 +/*
 +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 electron
 +
 +import (
 +	"fmt"
 +	"qpid.apache.org/amqp"
 +	"qpid.apache.org/proton"
 +	"time"
 +)
 +
 +// Receiver is a Link that receives messages.
 +//
 +type Receiver interface {
 +	Endpoint
 +	LinkSettings
 +
 +	// Receive blocks until a message is available or until the Receiver is closed
 +	// and has no more buffered messages.
 +	Receive() (ReceivedMessage, error)
 +
 +	// ReceiveTimeout is like Receive but gives up after timeout, see Timeout.
 +	//
 +	// Note that that if Prefetch is false, after a Timeout the credit issued by
 +	// Receive remains on the link. It will be used by the next call to Receive.
 +	ReceiveTimeout(timeout time.Duration) (ReceivedMessage, error)
 +
 +	// Prefetch==true means the Receiver will automatically issue credit to the
 +	// remote sender to keep its buffer as full as possible, i.e. it will
 +	// "pre-fetch" messages independently of the application calling
 +	// Receive(). This gives good throughput for applications that handle a
 +	// continuous stream of messages. Larger capacity may improve throughput, the
 +	// optimal value depends on the characteristics of your application.
 +	//
 +	// Prefetch==false means the Receiver will issue only issue credit when you
 +	// call Receive(), and will only issue enough credit to satisfy the calls
 +	// actually made. This gives lower throughput but will not fetch any messages
 +	// in advance. It is good for synchronous applications that need to evaluate
 +	// each message before deciding whether to receive another. The
 +	// request-response pattern is a typical example.  If you make concurrent
 +	// calls to Receive with pre-fetch disabled, you can improve performance by
 +	// setting the capacity close to the expected number of concurrent calls.
 +	//
 +	Prefetch() bool
 +
 +	// Capacity is the size (number of messages) of the local message buffer
 +	// These are messages received but not yet returned to the application by a call to Receive()
 +	Capacity() int
 +}
 +
 +// Receiver implementation
 +type receiver struct {
 +	link
 +	buffer  chan ReceivedMessage
 +	callers int
 +}
 +
 +func (r *receiver) Capacity() int  { return cap(r.buffer) }
 +func (r *receiver) Prefetch() bool { return r.prefetch }
 +
 +// Call in proton goroutine
 +func newReceiver(ls linkSettings) *receiver {
 +	r := &receiver{link: link{linkSettings: ls}}
- 	r.endpoint.init(r.link.eLink.String())
++	r.endpoint.init(r.link.pLink.String())
 +	if r.capacity < 1 {
 +		r.capacity = 1
 +	}
 +	r.buffer = make(chan ReceivedMessage, r.capacity)
- 	r.handler().addLink(r.eLink, r)
- 	r.link.eLink.Open()
++	r.handler().addLink(r.pLink, r)
++	r.link.pLink.Open()
 +	if r.prefetch {
 +		r.flow(r.maxFlow())
 +	}
 +	return r
 +}
 +
 +// Call in proton gorotine. Max additional credit we can request.
- func (r *receiver) maxFlow() int { return cap(r.buffer) - len(r.buffer) - r.eLink.Credit() }
++func (r *receiver) maxFlow() int { return cap(r.buffer) - len(r.buffer) - r.pLink.Credit() }
 +
 +func (r *receiver) flow(credit int) {
 +	if credit > 0 {
- 		r.eLink.Flow(credit)
++		r.pLink.Flow(credit)
 +	}
 +}
 +
 +// Inject flow check per-caller call when prefetch is off.
 +// Called with inc=1 at start of call, inc = -1 at end
 +func (r *receiver) caller(inc int) {
- 	r.engine().Inject(func() {
++	_ = r.engine().Inject(func() {
 +		r.callers += inc
- 		need := r.callers - (len(r.buffer) + r.eLink.Credit())
++		need := r.callers - (len(r.buffer) + r.pLink.Credit())
 +		max := r.maxFlow()
 +		if need > max {
 +			need = max
 +		}
 +		r.flow(need)
 +	})
 +}
 +
 +// Inject flow top-up if prefetch is enabled
 +func (r *receiver) flowTopUp() {
 +	if r.prefetch {
- 		r.engine().Inject(func() { r.flow(r.maxFlow()) })
++		_ = r.engine().Inject(func() { r.flow(r.maxFlow()) })
 +	}
 +}
 +
- // Not claled
 +func (r *receiver) Receive() (rm ReceivedMessage, err error) {
 +	return r.ReceiveTimeout(Forever)
 +}
 +
- func (r *receiver) ReceiveTimeout(timeout time.Duration) (ReceivedMessage, error) {
++func (r *receiver) ReceiveTimeout(timeout time.Duration) (rm ReceivedMessage, err error) {
 +	assert(r.buffer != nil, "Receiver is not open: %s", r)
- 	select { // Check for immediate availability
- 	case rm := <-r.buffer:
- 		r.flowTopUp()
- 		return rm, nil
- 	default:
- 	}
 +	if !r.prefetch { // Per-caller flow control
- 		r.caller(+1)
- 		defer r.caller(-1)
++		select { // Check for immediate availability, avoid caller() inject
++		case rm2, ok := <-r.buffer:
++			if ok {
++				rm = rm2
++			} else {
++				err = r.Error()
++			}
++			return
++		default: // Not immediately available, inject caller() counts
++			r.caller(+1)
++			defer r.caller(-1)
++		}
 +	}
 +	rmi, err := timedReceive(r.buffer, timeout)
 +	switch err {
 +	case nil:
 +		r.flowTopUp()
- 		return rmi.(ReceivedMessage), err
++		rm = rmi.(ReceivedMessage)
 +	case Closed:
- 		return ReceivedMessage{}, r.Error()
- 	default:
- 		return ReceivedMessage{}, err
++		err = r.Error()
 +	}
++	return
 +}
 +
 +// Called in proton goroutine on MMessage event.
 +func (r *receiver) message(delivery proton.Delivery) {
- 	if r.eLink.State().RemoteClosed() {
- 		localClose(r.eLink, r.eLink.RemoteCondition().Error())
++	if r.pLink.State().RemoteClosed() {
++		localClose(r.pLink, r.pLink.RemoteCondition().Error())
 +		return
 +	}
 +	if delivery.HasMessage() {
 +		m, err := delivery.Message()
 +		if err != nil {
- 			localClose(r.eLink, err)
++			localClose(r.pLink, err)
 +			return
 +		}
 +		assert(m != nil)
- 		r.eLink.Advance()
- 		if r.eLink.Credit() < 0 {
- 			localClose(r.eLink, fmt.Errorf("received message in excess of credit limit"))
++		r.pLink.Advance()
++		if r.pLink.Credit() < 0 {
++			localClose(r.pLink, fmt.Errorf("received message in excess of credit limit"))
 +		} else {
 +			// We never issue more credit than cap(buffer) so this will not block.
 +			r.buffer <- ReceivedMessage{m, delivery, r}
 +		}
 +	}
 +}
 +
 +func (r *receiver) closed(err error) error {
++	e := r.link.closed(err)
 +	if r.buffer != nil {
 +		close(r.buffer)
 +	}
- 	return r.link.closed(err)
++	return e
 +}
 +
 +// ReceivedMessage contains an amqp.Message and allows the message to be acknowledged.
 +type ReceivedMessage struct {
 +	// Message is the received message.
 +	Message amqp.Message
 +
- 	eDelivery proton.Delivery
++	pDelivery proton.Delivery
 +	receiver  Receiver
 +}
 +
 +// Acknowledge a ReceivedMessage with the given delivery status.
 +func (rm *ReceivedMessage) acknowledge(status uint64) error {
 +	return rm.receiver.(*receiver).engine().Inject(func() {
 +		// Deliveries are valid as long as the connection is, unless settled.
- 		rm.eDelivery.SettleAs(uint64(status))
++		rm.pDelivery.SettleAs(uint64(status))
 +	})
 +}
 +
 +// Accept tells the sender that we take responsibility for processing the message.
 +func (rm *ReceivedMessage) Accept() error { return rm.acknowledge(proton.Accepted) }
 +
 +// Reject tells the sender we consider the message invalid and unusable.
 +func (rm *ReceivedMessage) Reject() error { return rm.acknowledge(proton.Rejected) }
 +
 +// Release tells the sender we will not process the message but some other
 +// receiver might.
 +func (rm *ReceivedMessage) Release() error { return rm.acknowledge(proton.Released) }
 +
 +// IncomingReceiver is sent on the Connection.Incoming() channel when there is
 +// an incoming request to open a receiver link.
 +type IncomingReceiver struct {
- 	incomingLink
++	incoming
++	linkSettings
++}
++
++func newIncomingReceiver(sn *session, pLink proton.Link) *IncomingReceiver {
++	return &IncomingReceiver{
++		incoming:     makeIncoming(pLink),
++		linkSettings: makeIncomingLinkSettings(pLink, sn),
++	}
 +}
 +
 +// SetCapacity sets the capacity of the incoming receiver, call before Accept()
 +func (in *IncomingReceiver) SetCapacity(capacity int) { in.capacity = capacity }
 +
 +// SetPrefetch sets the pre-fetch mode of the incoming receiver, call before Accept()
 +func (in *IncomingReceiver) SetPrefetch(prefetch bool) { in.prefetch = prefetch }
 +
 +// Accept accepts an incoming receiver endpoint
 +func (in *IncomingReceiver) Accept() Endpoint {
 +	return in.accept(func() Endpoint { return newReceiver(in.linkSettings) })
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/sender.go
----------------------------------------------------------------------
diff --cc electron/sender.go
index 2f0e965,0000000..f46fdc4
mode 100644,000000..100644
--- a/electron/sender.go
+++ b/electron/sender.go
@@@ -1,274 -1,0 +1,288 @@@
 +/*
 +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 electron
 +
 +// #include <proton/disposition.h>
 +import "C"
 +
 +import (
 +	"fmt"
 +	"qpid.apache.org/amqp"
 +	"qpid.apache.org/proton"
 +	"time"
 +)
 +
 +// Sender is a Link that sends messages.
 +//
 +// The result of sending a message is provided by an Outcome value.
 +//
 +// A sender can buffer messages up to the credit limit provided by the remote receiver.
- // Send* methods will block if the buffer is full until there is space.
++// All the Send* methods will block if the buffer is full until there is space.
 +// Send*Timeout methods will give up after the timeout and set Timeout as Outcome.Error.
 +//
 +type Sender interface {
 +	Endpoint
 +	LinkSettings
 +
 +	// SendSync sends a message and blocks until the message is acknowledged by the remote receiver.
 +	// Returns an Outcome, which may contain an error if the message could not be sent.
 +	SendSync(m amqp.Message) Outcome
 +
 +	// SendWaitable puts a message in the send buffer and returns a channel that
 +	// you can use to wait for the Outcome of just that message. The channel is
- 	// buffered so you can receive from it whenever you want without blocking anything.
++	// buffered so you can receive from it whenever you want without blocking.
++	//
++	// Note: can block if there is no space to buffer the message.
 +	SendWaitable(m amqp.Message) <-chan Outcome
 +
 +	// SendForget buffers a message for sending and returns, with no notification of the outcome.
++	//
++	// Note: can block if there is no space to buffer the message.
 +	SendForget(m amqp.Message)
 +
 +	// SendAsync puts a message in the send buffer and returns immediately.  An
 +	// Outcome with Value = value will be sent to the ack channel when the remote
 +	// receiver has acknowledged the message or if there is an error.
 +	//
 +	// You can use the same ack channel for many calls to SendAsync(), possibly on
 +	// many Senders. The channel will receive the outcomes in the order they
 +	// become available. The channel should be buffered and/or served by dedicated
 +	// goroutines to avoid blocking the connection.
 +	//
 +	// If ack == nil no Outcome is sent.
++	//
++	// Note: can block if there is no space to buffer the message.
 +	SendAsync(m amqp.Message, ack chan<- Outcome, value interface{})
 +
 +	SendAsyncTimeout(m amqp.Message, ack chan<- Outcome, value interface{}, timeout time.Duration)
 +
 +	SendWaitableTimeout(m amqp.Message, timeout time.Duration) <-chan Outcome
 +
 +	SendForgetTimeout(m amqp.Message, timeout time.Duration)
 +
 +	SendSyncTimeout(m amqp.Message, timeout time.Duration) Outcome
 +}
 +
 +// Outcome provides information about the outcome of sending a message.
 +type Outcome struct {
 +	// Status of the message: was it sent, how was it acknowledged.
 +	Status SentStatus
 +	// Error is a local error if Status is Unsent or Unacknowledged, a remote error otherwise.
 +	Error error
 +	// Value provided by the application in SendAsync()
 +	Value interface{}
 +}
 +
 +func (o Outcome) send(ack chan<- Outcome) {
 +	if ack != nil {
 +		ack <- o
 +	}
 +}
 +
 +// SentStatus indicates the status of a sent message.
 +type SentStatus int
 +
 +const (
 +	// Message was never sent
 +	Unsent SentStatus = iota
 +	// Message was sent but never acknowledged. It may or may not have been received.
 +	Unacknowledged
 +	// Message was accepted by the receiver (or was sent pre-settled, accept is assumed)
 +	Accepted
 +	// Message was rejected as invalid by the receiver
 +	Rejected
 +	// Message was not processed by the receiver but may be valid for a different receiver
 +	Released
 +	// Receiver responded with an unrecognized status.
 +	Unknown
 +)
 +
 +// String human readable name for SentStatus.
 +func (s SentStatus) String() string {
 +	switch s {
 +	case Unsent:
 +		return "unsent"
 +	case Unacknowledged:
 +		return "unacknowledged"
 +	case Accepted:
 +		return "accepted"
 +	case Rejected:
 +		return "rejected"
 +	case Released:
 +		return "released"
 +	case Unknown:
 +		return "unknown"
 +	default:
 +		return fmt.Sprintf("invalid(%d)", s)
 +	}
 +}
 +
 +// Convert proton delivery state code to SentStatus value
 +func sentStatus(d uint64) SentStatus {
 +	switch d {
 +	case proton.Accepted:
 +		return Accepted
 +	case proton.Rejected:
 +		return Rejected
 +	case proton.Released, proton.Modified:
 +		return Released
 +	default:
 +		return Unknown
 +	}
 +}
 +
 +// Sender implementation, held by handler.
 +type sender struct {
 +	link
 +	credit chan struct{} // Signal available credit.
 +}
 +
 +func (s *sender) SendAsyncTimeout(m amqp.Message, ack chan<- Outcome, v interface{}, t time.Duration) {
 +	// wait for credit
 +	if _, err := timedReceive(s.credit, t); err != nil {
 +		if err == Closed && s.Error() != nil {
 +			err = s.Error()
 +		}
 +		Outcome{Unsent, err, v}.send(ack)
 +		return
 +	}
 +	// Send a message in handler goroutine
 +	err := s.engine().Inject(func() {
 +		if s.Error() != nil {
 +			Outcome{Unsent, s.Error(), v}.send(ack)
 +			return
 +		}
 +
- 		delivery, err2 := s.eLink.Send(m)
++		delivery, err2 := s.pLink.Send(m)
 +		switch {
 +		case err2 != nil:
 +			Outcome{Unsent, err2, v}.send(ack)
 +		case ack == nil || s.SndSettle() == SndSettled: // Pre-settled
 +			if s.SndSettle() != SndUnsettled { // Not forced to send unsettled by link policy
 +				delivery.Settle()
 +			}
 +			Outcome{Accepted, nil, v}.send(ack) // Assume accepted
 +		default:
 +			s.handler().sentMessages[delivery] = sentMessage{ack, v} // Register with handler
 +		}
- 		if s.eLink.Credit() > 0 { // Signal there is still credit
++		if s.pLink.Credit() > 0 { // Signal there is still credit
 +			s.sendable()
 +		}
 +	})
 +	if err != nil {
 +		Outcome{Unsent, err, v}.send(ack)
 +	}
 +}
 +
 +// Set credit flag if not already set. Non-blocking, any goroutine
 +func (s *sender) sendable() {
 +	select { // Non-blocking
 +	case s.credit <- struct{}{}:
 +	default:
 +	}
 +}
 +
 +func (s *sender) SendWaitableTimeout(m amqp.Message, t time.Duration) <-chan Outcome {
 +	out := make(chan Outcome, 1)
 +	s.SendAsyncTimeout(m, out, nil, t)
 +	return out
 +}
 +
 +func (s *sender) SendForgetTimeout(m amqp.Message, t time.Duration) {
 +	s.SendAsyncTimeout(m, nil, nil, t)
 +}
 +
 +func (s *sender) SendSyncTimeout(m amqp.Message, t time.Duration) Outcome {
 +	deadline := time.Now().Add(t)
 +	ack := s.SendWaitableTimeout(m, t)
 +	t = deadline.Sub(time.Now()) // Adjust for time already spent.
 +	if t < 0 {
 +		t = 0
 +	}
 +	if out, err := timedReceive(ack, t); err == nil {
 +		return out.(Outcome)
 +	} else {
 +		if err == Closed && s.Error() != nil {
 +			err = s.Error()
 +		}
 +		return Outcome{Unacknowledged, err, nil}
 +	}
 +}
 +
 +func (s *sender) SendAsync(m amqp.Message, ack chan<- Outcome, v interface{}) {
 +	s.SendAsyncTimeout(m, ack, v, Forever)
 +}
 +
 +func (s *sender) SendWaitable(m amqp.Message) <-chan Outcome {
 +	return s.SendWaitableTimeout(m, Forever)
 +}
 +
 +func (s *sender) SendForget(m amqp.Message) {
 +	s.SendForgetTimeout(m, Forever)
 +}
 +
 +func (s *sender) SendSync(m amqp.Message) Outcome {
 +	return <-s.SendWaitable(m)
 +}
 +
 +// handler goroutine
 +func (s *sender) closed(err error) error {
 +	close(s.credit)
 +	return s.link.closed(err)
 +}
 +
 +func newSender(ls linkSettings) *sender {
 +	s := &sender{link: link{linkSettings: ls}, credit: make(chan struct{}, 1)}
- 	s.endpoint.init(s.link.eLink.String())
- 	s.handler().addLink(s.eLink, s)
- 	s.link.eLink.Open()
++	s.endpoint.init(s.link.pLink.String())
++	s.handler().addLink(s.pLink, s)
++	s.link.pLink.Open()
 +	return s
 +}
 +
 +// sentMessage records a sent message on the handler.
 +type sentMessage struct {
 +	ack   chan<- Outcome
 +	value interface{}
 +}
 +
 +// IncomingSender is sent on the Connection.Incoming() channel when there is
 +// an incoming request to open a sender link.
 +type IncomingSender struct {
- 	incomingLink
++	incoming
++	linkSettings
++}
++
++func newIncomingSender(sn *session, pLink proton.Link) *IncomingSender {
++	return &IncomingSender{
++		incoming:     makeIncoming(pLink),
++		linkSettings: makeIncomingLinkSettings(pLink, sn),
++	}
 +}
 +
 +// Accept accepts an incoming sender endpoint
 +func (in *IncomingSender) Accept() Endpoint {
 +	return in.accept(func() Endpoint { return newSender(in.linkSettings) })
 +}
 +
 +// Call in injected functions to check if the sender is valid.
 +func (s *sender) valid() bool {
- 	s2, ok := s.handler().links[s.eLink].(*sender)
++	s2, ok := s.handler().links[s.pLink].(*sender)
 +	return ok && s2 == s
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/session.go
----------------------------------------------------------------------
diff --cc electron/session.go
index 1bbc52c,0000000..6dae354
mode 100644,000000..100644
--- a/electron/session.go
+++ b/electron/session.go
@@@ -1,128 -1,0 +1,139 @@@
 +/*
 +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 electron
 +
 +import (
 +	"qpid.apache.org/proton"
 +)
 +
 +// Session is an AMQP session, it contains Senders and Receivers.
 +type Session interface {
 +	Endpoint
 +
 +	// Sender opens a new sender.
 +	Sender(...LinkOption) (Sender, error)
 +
 +	// Receiver opens a new Receiver.
 +	Receiver(...LinkOption) (Receiver, error)
 +}
 +
 +type session struct {
 +	endpoint
- 	eSession   proton.Session
- 	connection *connection
- 	capacity   uint
++	pSession                         proton.Session
++	connection                       *connection
++	incomingCapacity, outgoingWindow uint
 +}
 +
 +// SessionOption can be passed when creating a Session
 +type SessionOption func(*session)
 +
 +// IncomingCapacity returns a Session Option that sets the size (in bytes) of
- // the sessions incoming data buffer..
- func IncomingCapacity(cap uint) SessionOption { return func(s *session) { s.capacity = cap } }
++// the session's incoming data buffer.
++func IncomingCapacity(bytes uint) SessionOption {
++	return func(s *session) { s.incomingCapacity = bytes }
++}
++
++// OutgoingWindow returns a Session Option that sets the outgoing window size (in frames).
++func OutgoingWindow(frames uint) SessionOption {
++	return func(s *session) { s.outgoingWindow = frames }
++}
 +
 +// in proton goroutine
 +func newSession(c *connection, es proton.Session, setting ...SessionOption) *session {
 +	s := &session{
 +		connection: c,
- 		eSession:   es,
++		pSession:   es,
 +	}
 +	s.endpoint.init(es.String())
 +	for _, set := range setting {
 +		set(s)
 +	}
- 	c.handler.sessions[s.eSession] = s
- 	s.eSession.SetIncomingCapacity(s.capacity)
- 	s.eSession.Open()
++	c.handler.sessions[s.pSession] = s
++	s.pSession.SetIncomingCapacity(s.incomingCapacity)
++	s.pSession.SetOutgoingWindow(s.outgoingWindow)
++	s.pSession.Open()
 +	return s
 +}
 +
 +func (s *session) Connection() Connection     { return s.connection }
- func (s *session) eEndpoint() proton.Endpoint { return s.eSession }
++func (s *session) pEndpoint() proton.Endpoint { return s.pSession }
 +func (s *session) engine() *proton.Engine     { return s.connection.engine }
 +
 +func (s *session) Close(err error) {
- 	s.engine().Inject(func() {
++	_ = s.engine().Inject(func() {
 +		if s.Error() == nil {
- 			localClose(s.eSession, err)
++			localClose(s.pSession, err)
 +		}
 +	})
 +}
 +
 +func (s *session) Sender(setting ...LinkOption) (snd Sender, err error) {
 +	err = s.engine().InjectWait(func() error {
 +		if s.Error() != nil {
 +			return s.Error()
 +		}
 +		l, err := makeLocalLink(s, true, setting...)
 +		if err == nil {
 +			snd = newSender(l)
 +		}
 +		return err
 +	})
 +	return
 +}
 +
 +func (s *session) Receiver(setting ...LinkOption) (rcv Receiver, err error) {
 +	err = s.engine().InjectWait(func() error {
 +		if s.Error() != nil {
 +			return s.Error()
 +		}
 +		l, err := makeLocalLink(s, false, setting...)
 +		if err == nil {
 +			rcv = newReceiver(l)
 +		}
 +		return err
 +	})
 +	return
 +}
 +
 +// IncomingSender is sent on the Connection.Incoming() channel when there is an
 +// incoming request to open a session.
 +type IncomingSession struct {
 +	incoming
- 	h        *handler
- 	pSession proton.Session
- 	capacity uint
++	h                                *handler
++	pSession                         proton.Session
++	incomingCapacity, outgoingWindow uint
 +}
 +
 +func newIncomingSession(h *handler, ps proton.Session) *IncomingSession {
 +	return &IncomingSession{incoming: makeIncoming(ps), h: h, pSession: ps}
 +}
 +
- // SetCapacity sets the session buffer capacity of an incoming session in bytes.
- func (in *IncomingSession) SetCapacity(bytes uint) { in.capacity = bytes }
++// SetIncomingCapacity sets the session buffer capacity of an incoming session in bytes.
++func (in *IncomingSession) SetIncomingCapacity(bytes uint) { in.incomingCapacity = bytes }
++
++// SetOutgoingWindow sets the session outgoing window of an incoming session in frames.
++func (in *IncomingSession) SetOutgoingWindow(frames uint) { in.outgoingWindow = frames }
 +
 +// Accept an incoming session endpoint.
 +func (in *IncomingSession) Accept() Endpoint {
 +	return in.accept(func() Endpoint {
- 		return newSession(in.h.connection, in.pSession, IncomingCapacity(in.capacity))
++		return newSession(in.h.connection, in.pSession, IncomingCapacity(in.incomingCapacity), OutgoingWindow(in.outgoingWindow))
 +	})
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/proton/engine.go
----------------------------------------------------------------------
diff --cc proton/engine.go
index eecda7a,0000000..c0f0093
mode 100644,000000..100644
--- a/proton/engine.go
+++ b/proton/engine.go
@@@ -1,409 -1,0 +1,422 @@@
 +/*
 +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 proton
 +
- // #include <proton/connection.h>
- // #include <proton/event.h>
- // #include <proton/error.h>
- // #include <proton/handlers.h>
- // #include <proton/session.h>
- // #include <proton/transport.h>
- // #include <memory.h>
- // #include <stdlib.h>
- //
- // PN_HANDLE(REMOTE_ADDR)
- import "C"
- 
 +import (
 +	"fmt"
 +	"net"
++	"os"
++	"strings"
 +	"sync"
 +	"time"
 +	"unsafe"
 +)
 +
++/*
++#include <proton/connection.h>
++#include <proton/event.h>
++#include <proton/error.h>
++#include <proton/handlers.h>
++#include <proton/session.h>
++#include <proton/transport.h>
++#include <memory.h>
++#include <stdlib.h>
++*/
++import "C"
++
 +// Injecter allows functions to be "injected" into the event-processing loop, to
 +// be called in the same goroutine as event handlers.
 +type Injecter interface {
 +	// Inject a function into the engine goroutine.
 +	//
 +	// f() will be called in the same goroutine as event handlers, so it can safely
 +	// use values belonging to event handlers without synchronization. f() should
 +	// not block, no further events or injected functions can be processed until
 +	// f() returns.
 +	//
 +	// Returns a non-nil error if the function could not be injected and will
 +	// never be called. Otherwise the function will eventually be called.
 +	//
 +	// Note that proton values (Link, Session, Connection etc.) that existed when
 +	// Inject(f) was called may have become invalid by the time f() is executed.
 +	// Handlers should handle keep track of Closed events to ensure proton values
 +	// are not used after they become invalid. One technique is to have map from
 +	// proton values to application values. Check that the map has the correct
 +	// proton/application value pair at the start of the injected function and
 +	// delete the value from the map when handling a Closed event.
 +	Inject(f func()) error
 +
 +	// InjectWait is like Inject but does not return till f() has completed.
 +	// If f() cannot be injected it returns the error from Inject(), otherwise
 +	// it returns the error from f()
 +	InjectWait(f func() error) error
 +}
 +
- // bufferChan manages a pair of ping-pong buffers to pass bytes through a channel.
- type bufferChan struct {
- 	buffers    chan []byte
- 	buf1, buf2 []byte
- }
- 
- func newBufferChan(size int) *bufferChan {
- 	return &bufferChan{make(chan []byte), make([]byte, size), make([]byte, size)}
- }
- 
- func (b *bufferChan) buffer() []byte {
- 	b.buf1, b.buf2 = b.buf2, b.buf1 // Alternate buffers.
- 	return b.buf1[:cap(b.buf1)]
- }
- 
 +// Engine reads from a net.Conn, decodes AMQP events and calls the appropriate
 +// Handler functions sequentially in a single goroutine. Actions taken by
 +// Handler functions (such as sending messages) are encoded and written to the
 +// net.Conn. You can create multiple Engines to handle multiple connections
 +// concurrently.
 +//
 +// You implement the EventHandler and/or MessagingHandler interfaces and provide
 +// those values to NewEngine(). Their HandleEvent method will be called in the
 +// event-handling goroutine.
 +//
 +// Handlers can pass values from an event (Connections, Links, Deliveries etc.) to
 +// other goroutines, store them, or use them as map indexes. Effectively they are
 +// just pointers.  Other goroutines cannot call their methods directly but they can
 +// can create a function closure to call such methods and pass it to Engine.Inject()
 +// to have it evaluated in the engine goroutine.
 +//
 +// You are responsible for ensuring you don't use an event value after it is
 +// invalid. The handler methods will tell you when a value is no longer valid. For
 +// example after a LinkClosed event, that link is no longer valid. If you do
 +// Link.Close() yourself (in a handler or injected function) the link remains valid
 +// until the corresponing LinkClosed event is received by the handler.
 +//
 +// Engine.Close() will take care of cleaning up any remaining values when you are
 +// done with the Engine. All values associated with a engine become invalid when you
 +// call Engine.Close()
 +//
 +// The qpid.apache.org/proton/concurrent package will do all this for you, so it
 +// may be a better choice for some applications.
 +//
 +type Engine struct {
 +	// Error is set on exit from Run() if there was an error.
 +	err    ErrorHolder
 +	inject chan func()
 +
 +	conn       net.Conn
 +	connection Connection
 +	transport  Transport
 +	collector  *C.pn_collector_t
- 	read       *bufferChan    // Read buffers channel.
- 	write      *bufferChan    // Write buffers channel.
 +	handlers   []EventHandler // Handlers for proton events.
 +	running    chan struct{}  // This channel will be closed when the goroutines are done.
 +	closeOnce  sync.Once
++	timer      *time.Timer
++	traceEvent bool
 +}
 +
 +const bufferSize = 4096
 +
- // NewEngine initializes a engine with a connection and handlers. To start it running:
- //    eng := NewEngine(...)
- //    go run eng.Run()
- // The goroutine will exit when the engine is closed or disconnected.
- // You can check for errors on Engine.Error.
- //
++func envBool(name string) bool {
++	v := strings.ToLower(os.Getenv(name))
++	return v == "true" || v == "1" || v == "yes" || v == "on"
++}
++
++// Create a new Engine and call Initialize() with conn and handlers
 +func NewEngine(conn net.Conn, handlers ...EventHandler) (*Engine, error) {
- 	// Save the connection ID for Connection.String()
- 	eng := &Engine{
- 		inject:     make(chan func()),
- 		conn:       conn,
- 		transport:  Transport{C.pn_transport()},
- 		connection: Connection{C.pn_connection()},
- 		collector:  C.pn_collector(),
- 		handlers:   handlers,
- 		read:       newBufferChan(bufferSize),
- 		write:      newBufferChan(bufferSize),
- 		running:    make(chan struct{}),
- 	}
++	eng := &Engine{}
++	return eng, eng.Initialize(conn, handlers...)
++}
++
++// Initialize an Engine with a connection and handlers. Start it with Run()
++func (eng *Engine) Initialize(conn net.Conn, handlers ...EventHandler) error {
++	eng.inject = make(chan func())
++	eng.conn = conn
++	eng.connection = Connection{C.pn_connection()}
++	eng.transport = Transport{C.pn_transport()}
++	eng.collector = C.pn_collector()
++	eng.handlers = handlers
++	eng.running = make(chan struct{})
++	eng.timer = time.NewTimer(0)
++	eng.traceEvent = envBool("PN_TRACE_EVT")
 +	if eng.transport.IsNil() || eng.connection.IsNil() || eng.collector == nil {
- 		return nil, fmt.Errorf("failed to allocate engine")
++		eng.free()
++		return fmt.Errorf("proton.NewEngine cannot allocate")
 +	}
++	C.pn_connection_collect(eng.connection.pn, eng.collector)
++	return nil
++}
 +
- 	// TODO aconway 2015-06-25: connection settings for user, password, container etc.
- 	// before transport.Bind() Set up connection before Engine, allow Engine or Reactor
- 	// to run connection.
- 
- 	// Unique container-id by default.
- 	eng.connection.SetContainer(UUID4().String())
- 	pnErr := eng.transport.Bind(eng.connection)
- 	if pnErr != 0 {
- 		return nil, fmt.Errorf("cannot setup engine: %s", PnErrorCode(pnErr))
++// Create a byte slice backed by C memory.
++// Empty or error (size <= 0) returns a nil byte slice.
++func cByteSlice(start unsafe.Pointer, size int) []byte {
++	if start == nil || size <= 0 {
++		return nil
++	} else {
++		// Slice from very large imaginary array in C memory
++		return (*[1 << 30]byte)(start)[:size:size]
 +	}
- 	C.pn_connection_collect(eng.connection.pn, eng.collector)
- 	eng.connection.Open()
- 	return eng, nil
++}
++
++func (eng *Engine) Connection() Connection {
++	return eng.connection
++}
++
++func (eng *Engine) Transport() Transport {
++	return eng.transport
 +}
 +
 +func (eng *Engine) String() string {
- 	return fmt.Sprintf("%s-%s", eng.conn.LocalAddr(), eng.conn.RemoteAddr())
++	return fmt.Sprintf("[%s]%s-%s", eng.Id(), eng.conn.LocalAddr(), eng.conn.RemoteAddr())
 +}
 +
 +func (eng *Engine) Id() string {
- 	return fmt.Sprintf("%p", eng)
++	// Use transport address to match default PN_TRACE_FRM=1 output.
++	return fmt.Sprintf("%p", eng.Transport().CPtr())
 +}
 +
 +func (eng *Engine) Error() error {
 +	return eng.err.Get()
 +}
 +
 +// Inject a function into the Engine's event loop.
 +//
 +// f() will be called in the same event-processing goroutine that calls Handler
 +// methods. f() can safely call methods on values that belong to this engine
 +// (Sessions, Links etc)
 +//
 +// The injected function has no parameters or return values. It is normally a
 +// closure and can use channels to communicate with the injecting goroutine if
 +// necessary.
 +//
 +// Returns a non-nil error if the engine is closed before the function could be
 +// injected.
 +func (eng *Engine) Inject(f func()) error {
 +	select {
 +	case eng.inject <- f:
 +		return nil
 +	case <-eng.running:
 +		return eng.Error()
 +	}
 +}
 +
 +// InjectWait is like Inject but does not return till f() has completed or the
 +// engine is closed, and returns an error value from f()
 +func (eng *Engine) InjectWait(f func() error) error {
 +	done := make(chan error)
 +	defer close(done)
 +	err := eng.Inject(func() { done <- f() })
 +	if err != nil {
 +		return err
 +	}
 +	select {
 +	case <-eng.running:
 +		return eng.Error()
 +	case err := <-done:
 +		return err
 +	}
 +}
 +
 +// Server puts the Engine in server mode, meaning it will auto-detect security settings on
 +// the incoming connnection such as use of SASL and SSL.
 +// Must be called before Run()
 +//
- func (eng *Engine) Server() { eng.transport.SetServer() }
++func (eng *Engine) Server() { eng.Transport().SetServer() }
 +
- func (eng *Engine) disconnect() {
- 	eng.transport.CloseHead()
++func (eng *Engine) disconnect(err error) {
++	cond := eng.Transport().Condition()
++	cond.SetError(err)              // Set the provided error.
++	cond.SetError(eng.conn.Close()) // Use connection error if cond is not already set.
 +	eng.transport.CloseTail()
- 	eng.conn.Close()
- 	eng.dispatch()
++	eng.transport.CloseHead()
 +}
 +
 +// Close the engine's connection.
 +// If err != nil pass it to the remote end as the close condition.
 +// Returns when the remote end closes or disconnects.
 +func (eng *Engine) Close(err error) {
- 	eng.Inject(func() { CloseError(eng.connection, err) })
++	_ = eng.Inject(func() { CloseError(eng.Connection(), err) })
 +	<-eng.running
 +}
 +
 +// CloseTimeout like Close but disconnect if the remote end doesn't close within timeout.
 +func (eng *Engine) CloseTimeout(err error, timeout time.Duration) {
- 	eng.Inject(func() { CloseError(eng.connection, err) })
++	_ = eng.Inject(func() { CloseError(eng.Connection(), err) })
 +	select {
 +	case <-eng.running:
 +	case <-time.After(timeout):
 +		eng.Disconnect(err)
 +	}
 +}
 +
 +// Disconnect the engine's connection immediately without an AMQP close.
 +// Process any termination events before returning.
 +func (eng *Engine) Disconnect(err error) {
- 	eng.Inject(func() { eng.transport.Condition().SetError(err); eng.disconnect() })
++	_ = eng.Inject(func() { eng.disconnect(err) })
 +	<-eng.running
 +}
 +
++// Let proton run timed activity and set up the next tick
++func (eng *Engine) tick() {
++	now := time.Now()
++	next := eng.Transport().Tick(now)
++	if !next.IsZero() {
++		eng.timer.Reset(next.Sub(now))
++	}
++}
++
++func (eng *Engine) dispatch() bool {
++	for ce := C.pn_collector_peek(eng.collector); ce != nil; ce = C.pn_collector_peek(eng.collector) {
++		e := makeEvent(ce, eng)
++		if eng.traceEvent {
++			eng.transport.Log(e.String())
++		}
++		for _, h := range eng.handlers {
++			h.HandleEvent(e)
++		}
++		if e.Type() == EConnectionRemoteOpen {
++			eng.tick() // Update the tick if changed by remote.
++		}
++		C.pn_collector_pop(eng.collector)
++	}
++	return !eng.transport.Closed() || C.pn_collector_peek(eng.collector) != nil
++}
++
++func (eng *Engine) writeBuffer() []byte {
++	size := eng.Transport().Pending() // Evaluate before Head(), may change buffer.
++	start := eng.Transport().Head()
++	return cByteSlice(start, size)
++}
++
++func (eng *Engine) readBuffer() []byte {
++	size := eng.Transport().Capacity()
++	start := eng.Transport().Tail()
++	return cByteSlice(start, size)
++}
++
++func (eng *Engine) free() {
++	if !eng.transport.IsNil() {
++		eng.transport.Unbind()
++		eng.transport.Free()
++		eng.transport = Transport{}
++	}
++	if !eng.connection.IsNil() {
++		eng.connection.Free()
++		eng.connection = Connection{}
++	}
++	if eng.collector != nil {
++		C.pn_collector_release(eng.collector)
++		C.pn_collector_free(eng.collector)
++		eng.collector = nil
++	}
++}
++
 +// Run the engine. Engine.Run() will exit when the engine is closed or
 +// disconnected.  You can check for errors after exit with Engine.Error().
 +//
 +func (eng *Engine) Run() error {
++	defer eng.free()
++	eng.transport.Bind(eng.connection)
++	eng.tick() // Start ticking if needed
++
++	// Channels for read and write buffers going in and out of the read/write goroutines.
++	// The channels are unbuffered: we want to exchange buffers in seuquence.
++	readsIn, writesIn := make(chan []byte), make(chan []byte)
++	readsOut, writesOut := make(chan []byte), make(chan []byte)
++
 +	wait := sync.WaitGroup{}
 +	wait.Add(2) // Read and write goroutines
 +
- 	readErr := make(chan error, 1) // Don't block
- 	go func() {                    // Read goroutine
++	go func() { // Read goroutine
 +		defer wait.Done()
 +		for {
- 			rbuf := eng.read.buffer()
++			rbuf, ok := <-readsIn
++			if !ok {
++				return
++			}
 +			n, err := eng.conn.Read(rbuf)
 +			if n > 0 {
- 				eng.read.buffers <- rbuf[:n]
- 			}
- 			if err != nil {
- 				readErr <- err
- 				close(readErr)
- 				close(eng.read.buffers)
++				readsOut <- rbuf[:n]
++			} else if err != nil {
++				_ = eng.Inject(func() {
++					eng.Transport().Condition().SetError(err)
++					eng.Transport().CloseTail()
++				})
 +				return
 +			}
 +		}
 +	}()
 +
- 	writeErr := make(chan error, 1) // Don't block
- 	go func() {                     // Write goroutine
++	go func() { // Write goroutine
 +		defer wait.Done()
 +		for {
- 			wbuf, ok := <-eng.write.buffers
++			wbuf, ok := <-writesIn
 +			if !ok {
 +				return
 +			}
- 			_, err := eng.conn.Write(wbuf)
- 			if err != nil {
- 				writeErr <- err
- 				close(writeErr)
++			n, err := eng.conn.Write(wbuf)
++			if n > 0 {
++				writesOut <- wbuf[:n]
++			} else if err != nil {
++				_ = eng.Inject(func() {
++					eng.Transport().Condition().SetError(err)
++					eng.Transport().CloseHead()
++				})
 +				return
 +			}
 +		}
 +	}()
 +
- 	wbuf := eng.write.buffer()[:0]
++	for eng.dispatch() {
++		readBuf := eng.readBuffer()
++		writeBuf := eng.writeBuffer()
++		// Note that getting the buffers can generate events (eg. SASL events) that
++		// might close the transport. Check if we are already finished before
++		// blocking for IO.
++		if !eng.dispatch() {
++			break
++		}
 +
- 	for !eng.transport.Closed() {
- 		if len(wbuf) == 0 {
- 			eng.pop(&wbuf)
++		// sendReads/sendWrites are nil (not sendable in select) unless we have a
++		// buffer to read/write
++		var sendReads, sendWrites chan []byte
++		if readBuf != nil {
++			sendReads = readsIn
 +		}
- 		// Don't set wchan unless there is something to write.
- 		var wchan chan []byte
- 		if len(wbuf) > 0 {
- 			wchan = eng.write.buffers
++		if writeBuf != nil {
++			sendWrites = writesIn
 +		}
 +
++		// Send buffers to the read/write goroutines if we have them.
++		// Get buffers from the read/write goroutines and process them
++		// Check for injected functions
 +		select {
- 		case buf, ok := <-eng.read.buffers: // Read a buffer
- 			if ok {
- 				eng.push(buf)
- 			}
- 		case wchan <- wbuf: // Write a buffer
- 			wbuf = eng.write.buffer()[:0]
- 		case f, ok := <-eng.inject: // Function injected from another goroutine
- 			if ok {
- 				f()
- 			}
- 		case err := <-readErr:
- 			eng.transport.Condition().SetError(err)
- 			eng.transport.CloseTail()
- 		case err := <-writeErr:
- 			eng.transport.Condition().SetError(err)
- 			eng.transport.CloseHead()
- 		}
- 		eng.dispatch()
- 		if eng.connection.State().RemoteClosed() && eng.connection.State().LocalClosed() {
- 			eng.disconnect()
- 		}
- 	}
- 	eng.err.Set(EndpointError(eng.connection))
- 	eng.err.Set(eng.transport.Condition().Error())
- 	close(eng.write.buffers)
- 	eng.conn.Close() // Make sure connection is closed
- 	wait.Wait()
- 	close(eng.running) // Signal goroutines have exited and Error is set.
 +
- 	if !eng.connection.IsNil() {
- 		eng.connection.Free()
- 	}
- 	if !eng.transport.IsNil() {
- 		eng.transport.Free()
- 	}
- 	if eng.collector != nil {
- 		C.pn_collector_free(eng.collector)
- 	}
- 	for _, h := range eng.handlers {
- 		switch h := h.(type) {
- 		case cHandler:
- 			C.pn_handler_free(h.pn)
- 		}
- 	}
- 	return eng.err.Get()
- }
++		case sendReads <- readBuf:
 +
- func minInt(a, b int) int {
- 	if a < b {
- 		return a
- 	} else {
- 		return b
- 	}
- }
++		case sendWrites <- writeBuf:
 +
- func (eng *Engine) pop(buf *[]byte) {
- 	pending := int(eng.transport.Pending())
- 	switch {
- 	case pending == int(C.PN_EOS):
- 		*buf = (*buf)[:]
- 		return
- 	case pending < 0:
- 		panic(fmt.Errorf("%s", PnErrorCode(pending)))
- 	}
- 	size := minInt(pending, cap(*buf))
- 	*buf = (*buf)[:size]
- 	if size == 0 {
- 		return
- 	}
- 	C.memcpy(unsafe.Pointer(&(*buf)[0]), eng.transport.Head(), C.size_t(size))
- 	assert(size > 0)
- 	eng.transport.Pop(uint(size))
- }
++		case buf := <-readsOut:
++			eng.transport.Process(uint(len(buf)))
 +
- func (eng *Engine) push(buf []byte) {
- 	buf2 := buf
- 	for len(buf2) > 0 {
- 		n := eng.transport.Push(buf2)
- 		if n <= 0 {
- 			panic(fmt.Errorf("error in transport: %s", PnErrorCode(n)))
- 		}
- 		buf2 = buf2[n:]
- 	}
- }
++		case buf := <-writesOut:
++			eng.transport.Pop(uint(len(buf)))
 +
- func (eng *Engine) peek() *C.pn_event_t { return C.pn_collector_peek(eng.collector) }
++		case f, ok := <-eng.inject: // Function injected from another goroutine
++			if ok {
++				f()
++			}
 +
- func (eng *Engine) dispatch() {
- 	for ce := eng.peek(); ce != nil; ce = eng.peek() {
- 		for _, h := range eng.handlers {
- 			h.HandleEvent(makeEvent(ce, eng))
++		case <-eng.timer.C:
++			eng.tick()
 +		}
- 		C.pn_collector_pop(eng.collector)
 +	}
- }
 +
- func (eng *Engine) Connection() Connection { return eng.connection }
++	eng.err.Set(EndpointError(eng.Connection()))
++	eng.err.Set(eng.Transport().Condition().Error())
++	close(readsIn)
++	close(writesIn)
++	close(eng.running)   // Signal goroutines have exited and Error is set, disable Inject()
++	_ = eng.conn.Close() // Close conn, force read/write goroutines to exit (they will Inject)
++	wait.Wait()          // Wait for goroutines
++	return eng.err.Get()
++}


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


[30/50] [abbrv] qpid-proton git commit: PROTON-1316 Set visibility of exportable symbols on Solaris

Posted by ac...@apache.org.
PROTON-1316 Set visibility of exportable symbols on Solaris

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: dae0c55acffc77f23c548f4d23b6dc166c388ac1
Parents: 68f64e0
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 09:47:38 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:49 2016 -0400

----------------------------------------------------------------------
 proton-c/CMakeLists.txt                                  | 5 +++++
 proton-c/bindings/cpp/include/proton/internal/export.hpp | 5 +++++
 2 files changed, 10 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/dae0c55a/proton-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index c634113..0b4f7e1 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -250,6 +250,11 @@ if (CMAKE_COMPILER_IS_GNUCC)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
   endif (ENABLE_HIDE_UNEXPORTED_SYMBOLS)
+elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "SunPro")
+  if (ENABLE_HIDE_UNEXPORTED_SYMBOLS)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -xldscope=hidden")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xldscope=hidden")
+  endif (ENABLE_HIDE_UNEXPORTED_SYMBOLS)
 endif (CMAKE_COMPILER_IS_GNUCC)
 
 if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/dae0c55a/proton-c/bindings/cpp/include/proton/internal/export.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/export.hpp b/proton-c/bindings/cpp/include/proton/internal/export.hpp
index c38ed95..4c95956 100644
--- a/proton-c/bindings/cpp/include/proton/internal/export.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/export.hpp
@@ -33,6 +33,11 @@
 #  define PN_CPP_IMPORT __declspec(dllimport)
 #  define PN_CPP_CLASS_EXPORT
 #  define PN_CPP_CLASS_IMPORT
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#  define PN_CPP_EXPORT __global
+#  define PN_CPP_IMPORT
+#  define PN_CPP_CLASS_EXPORT __global
+#  define PN_CPP_CLASS_IMPORT
 #else
   //
   // Non-Windows (Linux, etc.) definitions:


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


[20/50] [abbrv] qpid-proton git commit: NO-JIRA: Don't build Java on appveyor to avoid CI failure - Appveyor Windows CI never previously build/tested Proton-J. Its configuration has changed and it tries to test Proton-J but fails, so turning off Java

Posted by ac...@apache.org.
NO-JIRA: Don't build Java on appveyor to avoid CI failure
- Appveyor Windows CI never previously build/tested Proton-J.
  Its configuration has changed and it tries to test Proton-J
  but fails, so turning off Java is no problem as we never had this
  working before in any case.


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

Branch: refs/heads/go1
Commit: 0eafe3af73e6d8e45d4ee2125aaba3bbd36046b9
Parents: cd011b6
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Oct 14 13:48:12 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Oct 14 13:48:12 2016 -0400

----------------------------------------------------------------------
 appveyor.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0eafe3af/appveyor.yml
----------------------------------------------------------------------
diff --git a/appveyor.yml b/appveyor.yml
index 8c61be0..368e9ad 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -8,7 +8,7 @@ cache:
 before_build:
 - mkdir BLD
 - cd BLD
-- cmake -G "Visual Studio 12" -DBUILD_PERL=no ..
+- cmake -G "Visual Studio 12" -DBUILD_PERL=no i-DBUILD_JAVA=no ..
 - cd ..
 build:
   parallel: true


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


[04/50] [abbrv] qpid-proton git commit: PROTON-1305: Go sporadic test failure in electron_test

Posted by ac...@apache.org.
PROTON-1305: Go sporadic test failure in electron_test

Reliably reproduced by:
    . config.sh && go test qpid.apache.org/electron -run TestLinkCloseInterrupt -count 100

Fixed missing error check in receiver.ReceiveTimeout()


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

Branch: refs/heads/go1
Commit: b4d0912b0d8fa7c2ff2115635dece381f5d48868
Parents: 158ad91
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Sep 8 19:37:25 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 20 17:39:15 2016 -0400

----------------------------------------------------------------------
 .../qpid.apache.org/electron/messaging_test.go  |  9 +++---
 .../go/src/qpid.apache.org/electron/receiver.go | 29 +++++++++++---------
 2 files changed, 21 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b4d0912b/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
index 4a9e652..c5c351a 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
@@ -324,22 +324,23 @@ func (p *pairs) receiverSender() (Receiver, Sender) {
 type result struct {
 	label string
 	err   error
+	value interface{}
 }
 
 func (r result) String() string { return fmt.Sprintf("%v(%v)", r.err, r.label) }
 
 func doSend(snd Sender, results chan result) {
 	err := snd.SendSync(amqp.NewMessage()).Error
-	results <- result{"send", err}
+	results <- result{"send", err, nil}
 }
 
 func doReceive(rcv Receiver, results chan result) {
-	_, err := rcv.Receive()
-	results <- result{"receive", err}
+	msg, err := rcv.Receive()
+	results <- result{"receive", err, msg}
 }
 
 func doDisposition(ack <-chan Outcome, results chan result) {
-	results <- result{"disposition", (<-ack).Error}
+	results <- result{"disposition", (<-ack).Error, nil}
 }
 
 // Senders get credit immediately if receivers have prefetch set

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b4d0912b/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go b/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
index 026a385..606e4d6 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
@@ -125,28 +125,31 @@ func (r *receiver) Receive() (rm ReceivedMessage, err error) {
 	return r.ReceiveTimeout(Forever)
 }
 
-func (r *receiver) ReceiveTimeout(timeout time.Duration) (ReceivedMessage, error) {
+func (r *receiver) ReceiveTimeout(timeout time.Duration) (rm ReceivedMessage, err error) {
 	assert(r.buffer != nil, "Receiver is not open: %s", r)
-	select { // Check for immediate availability, avoid caller() inject.
-	case rm := <-r.buffer:
-		r.flowTopUp()
-		return rm, nil
-	default:
-	}
 	if !r.prefetch { // Per-caller flow control
-		r.caller(+1)
-		defer r.caller(-1)
+		select { // Check for immediate availability, avoid caller() inject
+		case rm2, ok := <-r.buffer:
+			if ok {
+				rm = rm2
+			} else {
+				err = r.Error()
+			}
+			return
+		default: // Not immediately available, inject caller() counts
+			r.caller(+1)
+			defer r.caller(-1)
+		}
 	}
 	rmi, err := timedReceive(r.buffer, timeout)
 	switch err {
 	case nil:
 		r.flowTopUp()
-		return rmi.(ReceivedMessage), err
+		rm = rmi.(ReceivedMessage)
 	case Closed:
-		return ReceivedMessage{}, r.Error()
-	default:
-		return ReceivedMessage{}, err
+		err = r.Error()
 	}
+	return
 }
 
 // Called in proton goroutine on MMessage event.


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


[43/50] [abbrv] qpid-proton git commit: PROTON-1255: Remove pn_connection_engine_start

Posted by ac...@apache.org.
PROTON-1255: Remove pn_connection_engine_start

Bind the connection automatically in pn_connection_engine_dispatch after the
user has processed the PN_CONNECTION_INIT event. This removes the need to
manually call start and allows user handlers to set security settings
in their handler on PN_CONNECTION_INIT, before the bind.


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

Branch: refs/heads/go1
Commit: 507c9356692858a81916a4a8802fbc6b2302bc5f
Parents: 79e4848
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Oct 25 10:45:46 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Oct 25 10:45:46 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/src/io/connection_engine.cpp     |  1 -
 .../bindings/go/src/qpid.apache.org/proton/engine.go   |  1 -
 proton-c/include/proton/connection_engine.h            |  6 ------
 proton-c/src/engine/connection_engine.c                | 13 ++++---------
 4 files changed, 4 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/507c9356/proton-c/bindings/cpp/src/io/connection_engine.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_engine.cpp b/proton-c/bindings/cpp/src/io/connection_engine.cpp
index d3f2667..4712b3e 100644
--- a/proton-c/bindings/cpp/src/io/connection_engine.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_engine.cpp
@@ -65,7 +65,6 @@ void connection_engine::configure(const connection_options& opts) {
     opts.apply_bound(c);
     handler_ =  opts.handler();
     connection_context::get(connection()).collector = c_engine_.collector;
-    pn_connection_engine_start(&c_engine_);
 }
 
 connection_engine::~connection_engine() {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/507c9356/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index a0b8888..5680010 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -283,7 +283,6 @@ func (eng *Engine) readBuffer() []byte {
 // disconnected.  You can check for errors after exit with Engine.Error().
 //
 func (eng *Engine) Run() error {
-	C.pn_connection_engine_start(&eng.engine)
 	// Channels for read and write buffers going in and out of the read/write goroutines.
 	// The channels are unbuffered: we want to exchange buffers in seuquence.
 	readsIn, writesIn := make(chan []byte), make(chan []byte)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/507c9356/proton-c/include/proton/connection_engine.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/connection_engine.h b/proton-c/include/proton/connection_engine.h
index b1476c7..d9df77b 100644
--- a/proton-c/include/proton/connection_engine.h
+++ b/proton-c/include/proton/connection_engine.h
@@ -87,18 +87,12 @@ typedef struct pn_connection_engine_t {
 /// Initialize a pn_connection_engine_t struct with a new connection and
 /// transport.
 ///
-/// Configure connection properties and call connection_engine_start() before
-/// using the engine.
-///
 /// Call pn_connection_engine_final to free resources when you are done.
 ///
 ///@return 0 on success, a proton error code on failure (@see error.h)
 ///
 PN_EXTERN int pn_connection_engine_init(pn_connection_engine_t* engine);
 
-/// Start the engine, call after setting security and host properties.
-PN_EXTERN void pn_connection_engine_start(pn_connection_engine_t* engine);
-
 /// Free resources used by the engine, set the connection and transport pointers
 /// to NULL.
 PN_EXTERN void pn_connection_engine_final(pn_connection_engine_t* engine);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/507c9356/proton-c/src/engine/connection_engine.c
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/connection_engine.c b/proton-c/src/engine/connection_engine.c
index adfb145..5d184a1 100644
--- a/proton-c/src/engine/connection_engine.c
+++ b/proton-c/src/engine/connection_engine.c
@@ -36,14 +36,6 @@ int pn_connection_engine_init(pn_connection_engine_t* e) {
     return PN_OK;
 }
 
-void pn_connection_engine_start(pn_connection_engine_t* e) {
-    /*
-      Ignore bind errors. PN_STATE_ERR means we are already bound, any
-      other error will be delivered as an event.
-    */
-    pn_transport_bind(e->transport, e->connection);
-}
-
 void pn_connection_engine_final(pn_connection_engine_t* e) {
     if (e->transport && e->connection) {
         pn_transport_unbind(e->transport);
@@ -105,8 +97,11 @@ static void log_event(pn_connection_engine_t *engine, pn_event_t* event) {
 }
 
 pn_event_t* pn_connection_engine_dispatch(pn_connection_engine_t* e) {
-    if (e->event)
+    if (e->event) {             /* Already returned */
+        if (pn_event_type(e->event) == PN_CONNECTION_INIT)
+            pn_transport_bind(e->transport, e->connection);
         pn_collector_pop(e->collector);
+    }
     e->event = pn_collector_peek(e->collector);
     log_event(e, e->event);
     return e->event;


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


[11/50] [abbrv] qpid-proton git commit: NO-JIRA: Add missing dependencies to INSTALL.md for ruby binding.

Posted by ac...@apache.org.
NO-JIRA: Add missing dependencies to INSTALL.md for ruby binding.


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

Branch: refs/heads/go1
Commit: b7e44c42081eb9ad7adda33630d3561e41e20086
Parents: ce80f9d
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Sep 29 09:19:53 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Sep 29 09:19:53 2016 -0400

----------------------------------------------------------------------
 INSTALL.md | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b7e44c42/INSTALL.md
----------------------------------------------------------------------
diff --git a/INSTALL.md b/INSTALL.md
index 704237c..422b606 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -23,7 +23,11 @@ package for that language:
     $ yum install cyrus-sasl-devel
 
     # dependencies needed for bindings
-    $ yum install swig python-devel ruby-devel php-devel perl-devel
+    $ yum install swig          # Required for all bindings
+    $ yum install python-devel                               # Python
+    $ yum install ruby-devel rubygem-rspec rubygem-simplecov # Ruby
+    $ yum install pphp-devel                                 # PHP
+    $ yum install perl-devel                                 # Perl
 
     # dependencies needed for java (note that any non-ancient jvm will
     # work, 1.8.0 is just what is current for fedora 23)


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


[12/50] [abbrv] qpid-proton git commit: NO-JIRA: go: minor cleanup in dispatch loop code.

Posted by ac...@apache.org.
NO-JIRA: go: minor cleanup in dispatch loop code.

needTick check did not need to be in inner loop.


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

Branch: refs/heads/go1
Commit: 64abf0616817531fca0fbd4dfb2cce5cf8a89a2f
Parents: b7e44c4
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Oct 6 11:08:38 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 6 11:08:38 2016 -0400

----------------------------------------------------------------------
 .../go/src/qpid.apache.org/proton/engine.go      | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/64abf061/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index 7ba6827..7f1368e 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -251,18 +251,17 @@ func (eng *Engine) tick() {
 func (eng *Engine) dispatch() bool {
 	var needTick bool // Set if we need to tick the transport.
 	for {
-		if cevent := C.pn_connection_engine_dispatch(&eng.engine); cevent != nil {
-			event := makeEvent(cevent, eng)
-			for _, h := range eng.handlers {
-				switch event.Type() {
-				case ETransport:
-					needTick = true
-				}
-				h.HandleEvent(event)
-			}
-		} else {
+		cevent := C.pn_connection_engine_dispatch(&eng.engine)
+		if cevent == nil {
 			break
 		}
+		event := makeEvent(cevent, eng)
+		if event.Type() == ETransport {
+			needTick = true
+		}
+		for _, h := range eng.handlers {
+			h.HandleEvent(event)
+		}
 	}
 	if needTick {
 		eng.tick()


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


[27/50] [abbrv] qpid-proton git commit: PROTON-1325: Python mapping for 'buffer' and/or 'memoryview'

Posted by ac...@apache.org.
PROTON-1325: Python mapping for 'buffer' and/or 'memoryview'

Use whichever is available, memoryview is 3.x and some later 2.x, buffer is
older 2.x. Some have 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/6dabb379
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/6dabb379
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/6dabb379

Branch: refs/heads/go1
Commit: 6dabb379bf029950ce96966a305cf6b0bc344448
Parents: 9568275
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Oct 19 13:20:48 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Oct 19 15:23:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/python/proton/__init__.py |  8 +++++--
 tests/python/proton_tests/codec.py          | 27 +++++++++++++++++-------
 2 files changed, 25 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6dabb379/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
index 1478d38..516daf1 100644
--- a/proton-c/bindings/python/proton/__init__.py
+++ b/proton-c/bindings/python/proton/__init__.py
@@ -2229,14 +2229,18 @@ class Data:
     list: put_sequence,
     tuple: put_sequence,
     dict: put_dict,
-    buffer: put_binary,
     Described: put_py_described,
     Array: put_py_array
     }
   # for python 3.x, long is merely an alias for int, but for python 2.x
   # we need to add an explicit int since it is a different type
   if int not in put_mappings:
-      put_mappings[int] = put_int
+    put_mappings[int] = put_int
+  # For python 3.x use 'memoryview', for <=2.5 use 'buffer'. Python >=2.6 has both.
+  if getattr(__builtins__, 'memoryview', None):
+    put_mappings[memoryview] = put_binary
+  if getattr(__builtins__, 'buffer', None):
+    put_mappings[buffer] = put_binary
 
   get_mappings = {
     NULL: lambda s: None,

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6dabb379/tests/python/proton_tests/codec.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/codec.py b/tests/python/proton_tests/codec.py
index b7bb04d..4d3d906 100644
--- a/tests/python/proton_tests/codec.py
+++ b/tests/python/proton_tests/codec.py
@@ -357,14 +357,25 @@ class DataTest(Test):
     copy = data.get_object()
     assert copy == obj, (copy, obj)
 
-  def testBuffer(self):
-    self.data.put_object(buffer("foo"))
-    data = Data()
-    data.decode(self.data.encode())
-    data.rewind()
-    assert data.next()
-    assert data.type() == Data.BINARY
-    assert data.get_object() == "foo"
+  if getattr(__builtins__, 'buffer', None):
+    def testBuffer(self):
+      self.data.put_object(buffer("foo"))
+      data = Data()
+      data.decode(self.data.encode())
+      data.rewind()
+      assert data.next()
+      assert data.type() == Data.BINARY
+      assert data.get_object() == "foo"
+
+  if getattr(__builtins__, 'memoryview', None):
+    def testBuffer(self):
+      self.data.put_object(memoryview("foo"))
+      data = Data()
+      data.decode(self.data.encode())
+      data.rewind()
+      assert data.next()
+      assert data.type() == Data.BINARY
+      assert data.get_object() == "foo"
 
   def testLookup(self):
     obj = {symbol("key"): str2unicode("value"),


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


[38/50] [abbrv] qpid-proton git commit: PROTON-1324: c++ correct implementation of proton::is_signed

Posted by ac...@apache.org.
PROTON-1324: c++ correct implementation of proton::is_signed<char>

This uses std::numeric_limits<char> to get the platform setting, which works on
C++03 and should be portable.


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

Branch: refs/heads/go1
Commit: a1f0dd167563bd9643c7d06419da11244d119752
Parents: d280f8f
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Oct 20 11:52:05 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 11:52:05 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/include/proton/internal/type_traits.hpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a1f0dd16/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp b/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
index ee49a15..3d66f94 100644
--- a/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
@@ -30,6 +30,7 @@
 #include "./config.hpp"
 #include "../types_fwd.hpp"
 #include "../type_id.hpp"
+#include <limits>
 
 namespace proton {
 namespace internal {
@@ -47,7 +48,7 @@ template <class T> struct is_integral : public false_type {};
 template <class T> struct is_signed : public false_type {};
 
 template <> struct is_integral<char> : public true_type {};
-template <> struct is_signed<char> : public false_type {};
+template <> struct is_signed<char> { static const bool value = std::numeric_limits<char>::is_signed; };
 
 template <> struct is_integral<unsigned char> : public true_type {};
 template <> struct is_integral<unsigned short> : public true_type {};


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


[42/50] [abbrv] qpid-proton git commit: NO-JIRA: Remove incorrect memory_management.md article.

Posted by ac...@apache.org.
NO-JIRA: Remove incorrect memory_management.md article.

The discussion in that article about the use of pn_incref/pn_decref was incorrect.
The article has been removed, and a comment added to proton/object.h with this
correct statement:

   pn_incref, pn_decref and pn_refcount are for internal use by the proton
   library, the should not be called by application code. Application code
   should use the appropriate pn_*_free function (pn_link_free, pn_session_free
   etc.) when it is finished with a proton value. Proton values should only be
   used when handling a pn_event_t that refers to them.


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

Branch: refs/heads/go1
Commit: 79e48484db1e3a7b283597d50c65d05589a9bb30
Parents: f83c70c
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Oct 24 21:04:08 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Oct 24 21:21:17 2016 -0400

----------------------------------------------------------------------
 docs/markdown/memory_management.md | 135 --------------------------------
 proton-c/include/proton/object.h   |   9 +++
 2 files changed, 9 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/79e48484/docs/markdown/memory_management.md
----------------------------------------------------------------------
diff --git a/docs/markdown/memory_management.md b/docs/markdown/memory_management.md
deleted file mode 100644
index 1792b1f..0000000
--- a/docs/markdown/memory_management.md
+++ /dev/null
@@ -1,135 +0,0 @@
-Proton memory mangement
-=======================
-
-Proton is a collection of libraries in different programming langauges. Some of
-the libraries (e.g. C and Java) are written directly in those langauges. Some
-(e.g. python and ruby) are "bindings", native libraries that that internally use
-the C library. All the libraries provide a "native" memory management
-experience, you don't need to know anything about C or the proton C library to
-use them.
-
-If you only program in java, python, ruby or a similar garbage-collected
-language then you may be wondering "what is *memory management*?"  Don't worry,
-the proton library takes care of it. However, as usual, you are responsible for
-some non-memory *resource* management. For example if you fail to `close()` a
-proton connection there won't be memory leaks but the remote end will get a rude
-"connection failed" error instead of an orderly connection close.
-
-If you are a C programmer, you are probably rolling your eyes and wondering why
-the kids these days expect their memory to be managed for them. Don't worry, the
-C API offers the standard C experience: you must call `pn_X_free` on a `pn_X_t*`
-when the time is right and you must know when a `pn_X_t*` can become invalid as
-a side effect of some other call. Read the doc, learn the rules and get it
-right. You are a C programmer!
-
-If you are a modern C++11 programmer and always use `shared_ptr` and
-`unique_ptr` to write leak-safe code, then the C++ binding is leak-safe. If you
-are stuck on C++03, the binding supports `boost::shared_ptr` and
-`boost::intrusive_ptr`. If you cannot even use boost, the binding provides a
-simple (type safe, intrusive) smart pointer of its own which can help you.
-
-If you are a Go programmer, you know that Go takes care of *Go-allocated* memory
-but you are responsible other resource cleanup, e.g. closing connections.  Go
-does not have object-scoped cleanup (or indeed objects) but as a crafty Go
-programmer you know that function-scoped cleanup is all you really need, and
-`defer` is your friend. The Go binding internally starts goroutines and
-allocates memory that is not tracked by Go, so proper cleanup is important (but
-you knew that.)
-
-The role of reference counts
-----------------------------
-
-Internally, the proton C library uses reference counting, and you can
-*optionally* use it in your code. You should choose *either* reference counting
-*or* `pn_X_free` in your code, *not both*. It might work, but it is the sort of
-Bad Idea that might break your code in the future and will hurt your head in the
-present. `pn_X_free` is all you really need to write an AMQP application in
-straight C.
-
-However, proton is designed to be embedded and integrated. If you are
-integrating proton with a new programming language, or some other kind of
-framework, reference counts may be useful. If your integration target has some
-form of automatic clean-up that you can hook into (reference-counted pointers,
-finalizers, destructors or the like) then reference counts may help
-(e.g. python, ruby and C++ bindings all use them).
-
-As a counter-example the Go language is garbage collected, and has finalizers,
-but does not use reference counts. Go garbage collection is scheduled around
-memory use, so the timing may not be suitable for other resources. The Go
-binding does not use proton reference counts, it simply calls `pn_X_free` as
-part of resource cleanup (e.g. during Connection.Close()) or via finalizers as a
-fail-safe if resources are not cleaned up properly by the application.
-
-If you are mixing your own C code with code using a reference-counted proton
-binding (e.g. C++ or python) then you may need to at least be aware of reference
-counting.
-
-You can even use reference counts in plain C code if you find that helpful. I
-don't see how it would be but you never know.
-
-The reference counting rules
-----------------------------
-
-The proton C API has standard reference counting rules (but see [1] below)
-
-- A pointer *returned* by a `pn_` function is either *borrowed* by the caller,
-  or the caller *owns* a reference (the API doc should say which)
-- The owner of a reference must call `pn_decref()` exactly once to
-  release it.
-- To keep a borrowed pointer, call `pn_incref()`. This adds a new
-  reference, which you now own.
-- A pointer *passed* to a `pn_` function has no change of ownership. If you
-  owned a reference you still do, if you didn't you still don't.
-- An object is never freed while there are still references to it.
-- An object is freed when all references to it are released.
-
-A *borrowed* pointer is valid within some scope (typically the scope of an event
-handling function) but beyond that scope you cannot assume it is valid unless
-you make a new reference with `pn_incref`. The API documentation for the
-function that returned the pointer should tell you what the scope is.
-
-There are "container" relationships in proton: e.g. a connection contains
-sessions, a session contains links. Containers hold a reference to their
-contents. Freeing a container *releases* that reference. For example freeing a
-connection releases its sessions.
-
-If you don't use reference counts, then freeing a container *frees* the contents
-in traditional C style. However if you add a reference to a contained object it
-will *not* be freed till you release your reference, even if all references to
-container are released [1]. This is useful for bindings to langauges with
-"finalizers" or "destructors". You can use reference counts to "pin" proton C
-objects in memory for as long as any binding object needs them.
-
-For example: if you call `pn_message()` then you *own* a reference to the
-newly-created `pn_message_t` and you must call `pn_decref` when you are
-done [2]. If you call `pn_event_link()` in an event handler then you get a
-*borrowed* reference to the link. You can use it in the scope of the event
-handler, but if you want to save it for later you must call `pn_incref`
-to add a reference and of course call `pn_decref` when you are done with
-that reference.
-
-You should treat `pn_decref` *exactly* like freeing the object: the pointer is
-dead to you, you must never even look at it again. *Never* write code that
-assumes that "something else" still has a reference after you have released your
-own. *Never* write code that checks the value of the reference count (except for
-debugging purposes.) If you own a reference you can use the pointer. Once you
-release your reference, the pointer is dead to you. That's the whole story.
-
-The point of reference counts is to break ownership dependencies between
-different parts of the code so that everything will Just Work provided each part
-of the code independently obeys the simple rules. If your code makes assumptions
-about distant refcounts or "peeks" to vary its behavior based on what others are
-doing, you defeat the purpose of reference counting [1].
-
-[1] *Internally* the proton library plays tricks with reference counts to
-implement 'weak' pointers and manage circular containment relationships. You do
-*not* need to understand this to use proton, even if you are writing bindings or
-doing funky mixed-language development. However if you are working on the
-implementation of the proton C library itself you may need to learn more, ask on
-proton@qpid.apache.org.
-
-[2] Actually if you call `pn_message()` then you must *either* call
-`pn_decref()` *or* `pn_message_free()`, definitely not both. It is
-possible to mix reference couting and 'free' style memory management in the same
-codebase (`free` is sort-of an alias for `decref`) but it is probably not a good
-idea.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/79e48484/proton-c/include/proton/object.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/object.h b/proton-c/include/proton/object.h
index 827aa77..bafdcf4 100644
--- a/proton-c/include/proton/object.h
+++ b/proton-c/include/proton/object.h
@@ -162,10 +162,19 @@ PREFIX ## _t *PREFIX ## _new(void) {                                      \
 PN_EXTERN pn_cid_t pn_class_id(const pn_class_t *clazz);
 PN_EXTERN const char *pn_class_name(const pn_class_t *clazz);
 PN_EXTERN void *pn_class_new(const pn_class_t *clazz, size_t size);
+
+/* pn_incref, pn_decref and pn_refcount are for internal use by the proton
+   library, the should not be called by application code. Application code
+   should use the appropriate pn_*_free function (pn_link_free, pn_session_free
+   etc.) when it is finished with a proton value. Proton values should only be
+   used when handling a pn_event_t that refers to them.
+*/
 PN_EXTERN void *pn_class_incref(const pn_class_t *clazz, void *object);
 PN_EXTERN int pn_class_refcount(const pn_class_t *clazz, void *object);
 PN_EXTERN int pn_class_decref(const pn_class_t *clazz, void *object);
+
 PN_EXTERN void pn_class_free(const pn_class_t *clazz, void *object);
+
 PN_EXTERN const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object);
 PN_EXTERN uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object);
 PN_EXTERN intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b);


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


[28/50] [abbrv] qpid-proton git commit: PROTON-1314: Fixing SIGPIPE ignore on Solaris OS

Posted by ac...@apache.org.
PROTON-1314: Fixing SIGPIPE ignore on Solaris OS

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: 3dd7be374d0eb69dc9cf70e793de11bd765050a3
Parents: 6dabb37
Author: aboutros <ad...@murex.com>
Authored: Wed Oct 5 10:38:34 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Oct 19 17:14:47 2016 -0400

----------------------------------------------------------------------
 proton-c/src/posix/io.c | 48 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3dd7be37/proton-c/src/posix/io.c
----------------------------------------------------------------------
diff --git a/proton-c/src/posix/io.c b/proton-c/src/posix/io.c
index c0dc425..27d1a35 100644
--- a/proton-c/src/posix/io.c
+++ b/proton-c/src/posix/io.c
@@ -257,7 +257,53 @@ static inline int pn_create_socket(int af, int protocol) {
   return sock;
 }
 #else
-#error "Don't know how to turn off SIGPIPE on this platform"
+
+#include <signal.h>
+
+static inline int pn_create_socket(int af, int protocol) {
+  return socket(af, SOCK_STREAM, protocol);
+}
+
+static ssize_t nosigpipe_send(int fd, const void *buffer, size_t size) {
+  sigset_t pendingSignals, oldSignals, newSignals;
+  ssize_t count;
+  int sendErrno, sigmaskErr;
+
+  sigpending(&pendingSignals);
+  int sigpipeIsPending = sigismember(&pendingSignals, SIGPIPE);
+  if (!sigpipeIsPending) {
+    sigemptyset(&newSignals);
+    sigaddset(&newSignals, SIGPIPE);
+    if (sigmaskErr = pthread_sigmask(SIG_BLOCK, (const sigset_t *)&newSignals, (sigset_t *)&oldSignals))
+    {
+      errno = sigmaskErr;
+      return -1;
+    }
+  }
+
+  count = send(fd, buffer, size, 0);
+  if (!sigpipeIsPending) {
+    sendErrno = errno;
+    if (count == -1 && errno == EPIPE) {
+      while (-1 == sigtimedwait(&newSignals, NULL, &(struct timespec){ 0, 0 }) && errno == EINTR)
+        ; //do nothing
+    }
+    if (sigmaskErr = pthread_sigmask(SIG_SETMASK, (const sigset_t *)&oldSignals, (sigset_t *)NULL))
+    {
+      errno = sigmaskErr;
+      return -1;
+    }
+    errno = sendErrno;
+  }
+  return count;
+}
+
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size) {
+  ssize_t count = nosigpipe_send(socket, buf, size);
+  io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
+  if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
+  return count;
+}
 #endif
 
 ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size)


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


[34/50] [abbrv] qpid-proton git commit: PROTON-1312: c++ Sunstudio does not compile "++vector.begin()"

Posted by ac...@apache.org.
PROTON-1312: c++ Sunstudio does not compile "++vector.begin()"

Error message:"Operand for operator "++" must be an lvalue.". We used a local
variable to bypass that.

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: af17dead2e31364d6741833c2884f83ae78663f8
Parents: cca892e
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 15:03:59 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/src/value_test.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/af17dead/proton-c/bindings/cpp/src/value_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/value_test.cpp b/proton-c/bindings/cpp/src/value_test.cpp
index 596cc6b..d9f0f4a 100644
--- a/proton-c/bindings/cpp/src/value_test.cpp
+++ b/proton-c/bindings/cpp/src/value_test.cpp
@@ -55,7 +55,8 @@ template <class T> void sequence_test(
     ASSERT_EQUAL(vx, v2);
 
     T y(x);
-    *y.begin() = *(++y.begin()); // Second element is bigger so y is lexicographically bigger than x
+    typename T::iterator it = y.begin();
+    *y.begin() = *(++it); // Second element is bigger so y is lexicographically bigger than x
     value vy(y);
     ASSERT(vx != vy);
     ASSERT(vx < vy);


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


[08/50] [abbrv] qpid-proton git commit: PROTON-1307: go binding amqp.message does not honor Inferred flag

Posted by ac...@apache.org.
PROTON-1307: go binding amqp.message does not honor Inferred flag

Applied fix provided by Richard Laos for typo in the SetInferred method.


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

Branch: refs/heads/go1
Commit: 2c438a8554daf4526b9a7f1444fb5389a55bc1bb
Parents: 4bd66a0
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Sep 27 15:03:57 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 27 15:05:56 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/src/qpid.apache.org/amqp/message.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2c438a85/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
index 4ae36f4..48a209a 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
@@ -261,7 +261,7 @@ func dataString(data *C.pn_data_t) string {
 	return C.GoString(C.pn_string_get(str))
 }
 
-func (m *message) SetInferred(b bool)  { C.pn_message_set_inferred(m.pn, C.bool(m.Inferred())) }
+func (m *message) SetInferred(b bool)  { C.pn_message_set_inferred(m.pn, C.bool(b)) }
 func (m *message) SetDurable(b bool)   { C.pn_message_set_durable(m.pn, C.bool(b)) }
 func (m *message) SetPriority(b uint8) { C.pn_message_set_priority(m.pn, C.uint8_t(b)) }
 func (m *message) SetTTL(d time.Duration) {


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


[05/50] [abbrv] qpid-proton git commit: PROTON-1306: Go container improvements and client-server example.

Posted by ac...@apache.org.
PROTON-1306: Go container improvements and client-server example.

Added convenience ops to Container: Dial and Accept.
Added client-server documentation example.
Added Container.String(), improve other proton String() funcs.


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

Branch: refs/heads/go1
Commit: 6134e216caf952aa031a49ab09d3e59ba71b1965
Parents: 77b907b
Author: Alan Conway <ac...@redhat.com>
Authored: Fri Sep 9 12:37:01 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 20 17:43:35 2016 -0400

----------------------------------------------------------------------
 examples/go/README.md                           | 104 +++++++++++--------
 examples/go/electron/broker.go                  |   9 +-
 examples/go/electron/receive.go                 |   8 +-
 examples/go/electron/send.go                    |   9 +-
 .../bindings/go/src/qpid.apache.org/README.md   |   5 +-
 .../go/src/qpid.apache.org/amqp/message.go      |   2 +
 .../src/qpid.apache.org/electron/connection.go  |  35 ++++++-
 .../src/qpid.apache.org/electron/container.go   |  52 +++++++---
 .../go/src/qpid.apache.org/electron/doc.go      |  10 ++
 .../electron/ex_client_server_test.go           |  81 +++++++++++++++
 .../go/src/qpid.apache.org/electron/sender.go   |  10 +-
 .../go/src/qpid.apache.org/proton/wrappers.go   |   4 +-
 12 files changed, 237 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/examples/go/README.md
----------------------------------------------------------------------
diff --git a/examples/go/README.md b/examples/go/README.md
index 9ba497b..24f4d2a 100644
--- a/examples/go/README.md
+++ b/examples/go/README.md
@@ -1,36 +1,34 @@
-# Go examples for proton
+# Go examples
 
-There are 3 Go packages for proton:
+## Electron examples
 
-- qpid.apache.org/electron: Concurrent, procedural API for messaging clients and servers.
-- qpid.apache.org/proton: Direct access to the event-driven, concurrent-unsafe proton library.
-- qpid.apache.org/amqp: Convert AMQP messages and data to and from Go data types.
+[qpid.apache.org/electron](http://godoc.org/qpid.apache.org/electron) is a
+simple API for writing concurrent AMQP clients and servers.
 
-`proton` and `electron` are alternative APIs for sending messages. `proton` is a
-direct wrapping of the concurrent-unsafe, event-driven C proton API. `electron`
-is a procedural, concurrent-safe interface that may be more convenient and
-familiar for Go programmers. The examples `proton/broker.go` and
-`electron/broker.go` give an illustration of how the APIs differ.
-
-## Example programs
-
-electron
 - [receive.go](electron/receive.go) receive from many connections concurrently.
 - [send.go](electron/send.go) send to many connections concurrently.
 - [broker.go](electron/broker.go) a simple broker using the electron API
+n
+## Proton examples
+
+[qpid.apache.org/proton](http://godoc.org/qpid.apache.org/proton) is an
+event-driven, concurrent-unsafe Go wrapper for the proton-C library. The
+[electron](http://godoc.org/qpid.apache.org/electron) package provides a more
+Go-friendly concurrent API built on top of proton.
 
-proton
 - [broker.go](proton/broker.go) a simple broker using the proton API
 
+See [A Tale of Two Brokers](#a-tale-of-two-brokers) for a comparison of the two APIs.
+
 ## Using the Go packages
 
-If you have the proton C library and headers installed you can get the latest go
+If you have the proton-C library and headers installed you can get the latest go
 packages with
 
     go get qpid.apache.org/electron
 
-If proton is installed in a non-standard place (other than /usr or /usr/local) you
-can set these environment variables before `go get`, for example:
+If Proton-C is installed in a non-standard place (other than /usr or /usr/local)
+you should set these environment variables before `go get`:
 
     export CGO_LDFLAGS="-L/<my-proton>/lib[64]"
     export CGO_CFLAGS="-I/<my-proton>/include"
@@ -77,43 +75,57 @@ Receive messages concurrently from "foo" and "bar". Note -count 20 for 10 messag
 The broker and clients use the standard AMQP port (5672) on the local host by
 default, to use a different address use the `-addr host:port` flag.
 
-If you have the full proton repository checked out you can try try using the
-python broker with Go clients:
+If you have other Proton examples available you can try communicating between
+programs in in different languages. For example use the python broker with Go
+clients:
 
     python ../python/broker.py
+    go run send.go -count 10 localhost:/foo localhost:/bar
 
 Or use the Go broker and the python clients:
 
+    go run broker.go -debug
     python ../python/simple_send.py
     python ../python/simple_recv.py
 
 
 ## A tale of two brokers.
 
-The `proton` and `electron` packages provide two alternate APIs for AMQP applications.
-See [the proton Go README](https://github.com/apache/qpid-proton/blob/master/proton-c/bindings/go/src/qpid.apache.org/README.md) for a discussion
-of why there are two APIs.
-
-The examples `proton/broker.go` and `electron/broker.go` both implement the same
-simple broker-like functionality using each of the two APIs. They both handle
-multiple connections concurrently and store messages on bounded queues
-implemented by Go channels.
-
-However the `electron/broker` is less than half as long as the `proton/broker`
-illustrating why it is better suited for most Go applications.
-
-`proton/broker` must explicitly handle proton events, which are processed in a
-single goroutine per connection since proton is not concurrent safe. Each
-connection uses channels to exchange messages between the event-handling
-goroutine and the shared queues that are accessible to all connections. Sending
-messages is particularly tricky since we must monitor the queue for available
-messages and the sending link for available credit in order to send messages.
-
-
-`electron/broker` takes advantage of the `electron` package, which hides all the
-event handling and passing of messages between goroutines beind behind
-straightforward interfaces for sending and receiving messages. The electron
-broker can implement links as simple goroutines that loop popping messages from
-a queue and sending them or receiving messages and pushing them to a queue.
-
+The [proton](http://godoc.org/qpid.apache.org/proton) and
+[electron](http://godoc.org/qpid.apache.org/electron) packages provide two
+different APIs for building AMQP applications. For most applications,
+[electron](http://godoc.org/qpid.apache.org/electron) is easier to use.
+[The proton Go README](https://github.com/apache/qpid-proton/blob/master/proton-c/bindings/go/src/qpid.apache.org/README.md)
+has some discussion about why there are two APIs.
+
+The examples [proton/broker.go](proton/broker.go) and
+[electron/broker.go](electron/broker.go) implement the same simple broker
+functionality using each of the two APIs. They both handle multiple connections
+concurrently and store messages on bounded queues implemented by Go channels.
+
+However the [electron/broker.go](electron/broker.go) is less than half as long as the
+[proton/broker.go](proton/broker.go) illustrating why it is better suited for most Go
+applications.
+
+[proton/broker.go](proton/broker.go) implements an event-driven loop per connection that reacts
+to events like 'incoming link', 'incoming message' and 'sender has credit'.  It
+uses channels to exchange data between the event-loop goroutine for each
+connection and shared queues that are accessible to all connections. Sending
+messages is particularly tricky, the broker must monitor the queue for available
+messages and the sender link for available credit.
+
+
+[electron/broker.go](electron/broker.go) does not need any "upside-down"
+event-driven code, it is implemented as straightforward loops. The broker is a
+loop listening for connections. Each connection is a loop accepting for incoming
+sender or recdiver links. Each receiving link is a loop that receives a message
+and pushes it to a queue.  Each sending link is a loop that pops a message from
+a queue and sends it.
+
+Queue bounds and credit manage themselves: popping from a queue blocks till
+there is a message, sending blocks until there is credit, receiving blocks till
+something is received and pushing onto a queue blocks until there is
+space. There's no need for code that monitors the state of multiple queues and
+links. Each loop has one simple job to do, and the Go run-time schedules them
+efficiently.
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/examples/go/electron/broker.go
----------------------------------------------------------------------
diff --git a/examples/go/electron/broker.go b/examples/go/electron/broker.go
index d7aedcc..d698838 100644
--- a/examples/go/electron/broker.go
+++ b/examples/go/electron/broker.go
@@ -55,7 +55,7 @@ func main() {
 	flag.Parse()
 	b := &broker{
 		queues:    util.MakeQueues(*qsize),
-		container: electron.NewContainer(""),
+		container: electron.NewContainer(fmt.Sprintf("broker[%s]", os.Getpid())),
 		acks:      make(chan electron.Outcome),
 		sent:      make(chan sentMessage),
 	}
@@ -92,16 +92,11 @@ func (b *broker) run() error {
 
 	// Start a goroutine for each new connections
 	for {
-		conn, err := listener.Accept()
+		c, err := b.container.Accept(listener)
 		if err != nil {
 			util.Debugf("Accept error: %v", err)
 			continue
 		}
-		c, err := b.container.Connection(conn, electron.Server(), electron.AllowIncoming())
-		if err != nil {
-			util.Debugf("Connection error: %v", err)
-			continue
-		}
 		cc := &connection{b, c}
 		go cc.run() // Handle the connection
 		util.Debugf("Accepted %v", c)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/examples/go/electron/receive.go
----------------------------------------------------------------------
diff --git a/examples/go/electron/receive.go b/examples/go/electron/receive.go
index 94ee509..7a505d8 100644
--- a/examples/go/electron/receive.go
+++ b/examples/go/electron/receive.go
@@ -24,9 +24,7 @@ import (
 	"flag"
 	"fmt"
 	"log"
-	"net"
 	"os"
-	"path"
 	"qpid.apache.org/amqp"
 	"qpid.apache.org/electron"
 	"sync"
@@ -59,8 +57,7 @@ func main() {
 	var wait sync.WaitGroup // Used by main() to wait for all goroutines to end.
 	wait.Add(len(urls))     // Wait for one goroutine per URL.
 
-	_, prog := path.Split(os.Args[0])
-	container := electron.NewContainer(fmt.Sprintf("%v:%v", prog, os.Getpid()))
+	container := electron.NewContainer(fmt.Sprintf("receive[%s]", os.Getpid()))
 	connections := make(chan electron.Connection, len(urls)) // Connections to close on exit
 
 	// Start a goroutine to for each URL to receive messages and send them to the messages channel.
@@ -74,9 +71,8 @@ func main() {
 			util.ExitIf(err)
 
 			// Open a new connection
-			conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
+			c, err := container.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
 			util.ExitIf(err)
-			c, err := container.Connection(conn)
 			connections <- c // Save connection so we can Close() when main() ends
 
 			// Create a Receiver using the path of the URL as the source address

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/examples/go/electron/send.go
----------------------------------------------------------------------
diff --git a/examples/go/electron/send.go b/examples/go/electron/send.go
index 04ec2ef..4ea93ec 100644
--- a/examples/go/electron/send.go
+++ b/examples/go/electron/send.go
@@ -24,9 +24,7 @@ import (
 	"flag"
 	"fmt"
 	"log"
-	"net"
 	"os"
-	"path"
 	"qpid.apache.org/amqp"
 	"qpid.apache.org/electron"
 	"sync"
@@ -58,8 +56,7 @@ func main() {
 	var wait sync.WaitGroup
 	wait.Add(len(urls)) // Wait for one goroutine per URL.
 
-	_, prog := path.Split(os.Args[0])
-	container := electron.NewContainer(fmt.Sprintf("%v:%v", prog, os.Getpid()))
+	container := electron.NewContainer(fmt.Sprintf("send[%s]", os.Getpid()))
 	connections := make(chan electron.Connection, len(urls)) // Connctions to close on exit
 
 	// Start a goroutine for each URL to send messages.
@@ -72,9 +69,7 @@ func main() {
 			util.ExitIf(err)
 
 			// Open a new connection
-			conn, err := net.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
-			util.ExitIf(err)
-			c, err := container.Connection(conn)
+			c, err := container.Dial("tcp", url.Host) // Note net.URL.Host is actually "host:port"
 			util.ExitIf(err)
 			connections <- c // Save connection so we can Close() when main() ends
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/README.md
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/README.md b/proton-c/bindings/go/src/qpid.apache.org/README.md
index 4b2da12..ffd67f8 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/README.md
+++ b/proton-c/bindings/go/src/qpid.apache.org/README.md
@@ -16,9 +16,10 @@ with goroutines and channels to build concurrent AMQP clients and servers.
 
 [qpid.apache.org/proton](http://godoc.org/qpid.apache.org/proton) is an
 event-driven, concurrent-unsafe package that closely follows the proton C
-API. Most Go programmers will find the electron package easier to use.
+API. Most Go programmers will find the
+[electron](http://godoc.org/qpid.apache.org/electron) package easier to use.
 
-There are [examples](https://github.com/apache/qpid-proton/blob/master/examples/go/README.md)
+See the [examples](https://github.com/apache/qpid-proton/blob/master/examples/go/README.md)
 to help you get started.
 
 Feedback is encouraged at:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
index 1d1287f..4ae36f4 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/message.go
@@ -344,3 +344,5 @@ func (m *message) Encode(buffer []byte) ([]byte, error) {
 }
 
 // TODO aconway 2015-09-14: Multi-section messages.
+
+// TODO aconway 2016-09-09: Message.String() use inspect.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
index d0733f2..00c08ad 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
@@ -141,6 +141,12 @@ func AllowIncoming() ConnectionOption {
 	return func(c *connection) { c.incoming = make(chan Incoming) }
 }
 
+// Parent returns a ConnectionOption that associates the Connection with it's Container
+// If not set a connection will create its own default container.
+func Parent(cont Container) ConnectionOption {
+	return func(c *connection) { c.container = cont.(*container) }
+}
+
 type connection struct {
 	endpoint
 	connectionSettings
@@ -158,10 +164,10 @@ type connection struct {
 	defaultSession Session
 }
 
-func newConnection(conn net.Conn, cont *container, setting ...ConnectionOption) (*connection, error) {
+// NewConnection creates a connection with the given options.
+func NewConnection(conn net.Conn, setting ...ConnectionOption) (*connection, error) {
 	c := &connection{
-		container: cont,
-		conn:      conn,
+		conn: conn,
 	}
 	c.handler = newHandler(c)
 	var err error
@@ -170,10 +176,13 @@ func newConnection(conn net.Conn, cont *container, setting ...ConnectionOption)
 		return nil, err
 	}
 	c.pConnection = c.engine.Connection()
-	c.pConnection.SetContainer(cont.Id())
 	for _, set := range setting {
 		set(c)
 	}
+	if c.container == nil {
+		c.container = NewContainer("").(*container)
+	}
+	c.pConnection.SetContainer(c.container.Id())
 	globalSASLInit(c.engine)
 
 	c.endpoint.init(c.engine.String())
@@ -351,3 +360,21 @@ func globalSASLInit(eng *proton.Engine) {
 		sasl.ConfigPath(globalSASLConfigDir)
 	}
 }
+
+// Dial is shorthand for using net.Dial() then NewConnection()
+func Dial(network, addr string, opts ...ConnectionOption) (c Connection, err error) {
+	conn, err := net.Dial(network, addr)
+	if err == nil {
+		c, err = NewConnection(conn, opts...)
+	}
+	return
+}
+
+// DialWithDialer is shorthand for using dialer.Dial() then NewConnection()
+func DialWithDialer(dialer *net.Dialer, network, addr string, opts ...ConnectionOption) (c Connection, err error) {
+	conn, err := dialer.Dial(network, addr)
+	if err == nil {
+		c, err = NewConnection(conn, opts...)
+	}
+	return
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
index 1ab4df2..4cf5969 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
@@ -26,8 +26,11 @@ import (
 	"sync/atomic"
 )
 
-// Container is an AMQP container, it represents a single AMQP "application".It
-// provides functions to create new Connections to remote containers.
+// Container is an AMQP container, it represents a single AMQP "application"
+// which can have multiple client or server connections.
+//
+// Each Container in a distributed AMQP application must have a unique
+// container-id which is applied to its connections.
 //
 // Create with NewContainer()
 //
@@ -35,18 +38,19 @@ type Container interface {
 	// Id is a unique identifier for the container in your distributed application.
 	Id() string
 
-	// Enable AMQP over the supplied net.Conn. Returns a Connection endpoint.
-	//
-	// For client connections (e.g. established with net.Dial()), you can start
-	// using the connection immediately. Connection.Incoming() is disabled by
-	// default for clients, pass an AllowIncoming() option to enable incoming
-	// sessions and links.
-	//
-	// For server connection (e.g. established with net.Listener.Accept()) you
-	// must pass the Server() option and receive from the Connection.Incoming()
-	// channel. The first Incoming value will be an *IncomingConnection that lets
-	// you examine the connection properties before Accept() or Reject()
-	Connection(net.Conn, ...ConnectionOption) (Connection, error)
+	// Connection creates a connection associated with this container.
+	Connection(conn net.Conn, opts ...ConnectionOption) (Connection, error)
+
+	// Dial is shorthand for
+	//     conn, err := net.Dial(); c, err := Connection(conn, opts...)
+	Dial(network string, addr string, opts ...ConnectionOption) (Connection, error)
+
+	// Accept is shorthand for:
+	//     conn, err := l.Accept(); c, err := Connection(conn, append(opts, Server()...)
+	Accept(l net.Listener, opts ...ConnectionOption) (Connection, error)
+
+	// String returns Id()
+	String() string
 }
 
 type container struct {
@@ -73,10 +77,26 @@ func NewContainer(id string) Container {
 
 func (cont *container) Id() string { return cont.id }
 
+func (cont *container) String() string { return cont.Id() }
+
 func (cont *container) nextLinkName() string {
 	return cont.id + "@" + cont.nextTag()
 }
 
-func (cont *container) Connection(conn net.Conn, setting ...ConnectionOption) (Connection, error) {
-	return newConnection(conn, cont, setting...)
+func (cont *container) Connection(conn net.Conn, opts ...ConnectionOption) (Connection, error) {
+	return NewConnection(conn, append(opts, Parent(cont))...)
+}
+
+func (cont *container) Dial(network, address string, opts ...ConnectionOption) (c Connection, err error) {
+	if conn, err := net.Dial(network, address); err == nil {
+		c, err = cont.Connection(conn, opts...)
+	}
+	return
+}
+
+func (cont *container) Accept(l net.Listener, opts ...ConnectionOption) (c Connection, err error) {
+	if conn, err := l.Accept(); err == nil {
+		c, err = cont.Connection(conn, append(opts, Server())...)
+	}
+	return
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go b/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
index 207d8ba..436e5df 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
@@ -36,6 +36,16 @@ links to Send() and Receive() messages. Connection.Incoming() lets you accept
 incoming links opened by the remote peer. You can open and accept multiple links
 in both directions on a single Connection.
 
+Some of the documentation examples show client and server side by side in a
+single program, in separate goroutines. This is only for example purposes, real
+AMQP applications would run in separate processes on the network.
+More realistic examples: https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
+
+Some of the documentation examples show client and server side by side in a
+single program, in separate goroutines. This is only for example purposes, real
+AMQP applications would run in separate processes on the network.
+More realistic examples: https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
+
 */
 package electron
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/electron/ex_client_server_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/ex_client_server_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/ex_client_server_test.go
new file mode 100644
index 0000000..93f275b
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/ex_client_server_test.go
@@ -0,0 +1,81 @@
+package electron_test
+
+import (
+	"fmt"
+	"net"
+	"qpid.apache.org/amqp"
+	"qpid.apache.org/electron"
+)
+
+//  Print errors
+func check(msg string, err error) bool {
+	if err != nil {
+		fmt.Printf("%s: %s\n", msg, err)
+	}
+	return err == nil
+}
+
+func runServer(cont electron.Container, l net.Listener) {
+	for c, err := cont.Accept(l); check("accept connection", err); c, err = cont.Accept(l) {
+		go func() { // Process connections concurrently, accepting AMQP endpoints
+			for in := range c.Incoming() {
+				ep := in.Accept() // Accept all endpoints
+				go func() {       // Process endpoints concurrently
+					switch ep := ep.(type) {
+					case electron.Sender:
+						m := amqp.NewMessageWith("hello yourself")
+						fmt.Printf("server %q sending %q\n", ep.Source(), m.Body())
+						ep.SendForget(m) // One-way send, client does not need to Accept.
+					case electron.Receiver:
+						if rm, err := ep.Receive(); check("server receive", err) {
+							fmt.Printf("server %q received %q\n", ep.Target(), rm.Message.Body())
+							err := rm.Accept() // Client is waiting for Accept.
+							check("accept message", err)
+						}
+					}
+				}()
+			}
+		}()
+	}
+}
+
+func startServer() (addr net.Addr) {
+	cont := electron.NewContainer("server")
+	if l, err := net.Listen("tcp", ""); check("listen", err) {
+		addr = l.Addr()
+		go runServer(cont, l)
+	}
+	return addr
+}
+
+// Connect to addr and send/receive a message.
+func client(addr net.Addr) {
+	if c, err := electron.Dial(addr.Network(), addr.String()); check("dial", err) {
+		defer c.Close(nil)
+		if s, err := c.Sender(electron.Target("target")); check("sender", err) {
+			fmt.Printf("client sending\n")
+			s.SendSync(amqp.NewMessageWith("hello")) // Send and wait for server to Accept()
+		}
+		if r, err := c.Receiver(electron.Source("source")); check("receiver", err) {
+			if rm, err := r.Receive(); err == nil {
+				fmt.Printf("client received %q\n", rm.Message.Body())
+			}
+		}
+	}
+}
+
+// Example client and server communicating via AMQP over a TCP/IP connection.
+//
+// Normally client and server would be separate processes.
+// For more realistic examples:
+//     https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
+//
+func Example_clientServer() {
+	addr := startServer()
+	client(addr)
+	// Output:
+	// client sending
+	// server "target" received "hello"
+	// server "source" sending "hello yourself"
+	// client received "hello yourself"
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go b/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
index 8badf35..f46fdc4 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
@@ -34,7 +34,7 @@ import (
 // The result of sending a message is provided by an Outcome value.
 //
 // A sender can buffer messages up to the credit limit provided by the remote receiver.
-// Send* methods will block if the buffer is full until there is space.
+// All the Send* methods will block if the buffer is full until there is space.
 // Send*Timeout methods will give up after the timeout and set Timeout as Outcome.Error.
 //
 type Sender interface {
@@ -47,10 +47,14 @@ type Sender interface {
 
 	// SendWaitable puts a message in the send buffer and returns a channel that
 	// you can use to wait for the Outcome of just that message. The channel is
-	// buffered so you can receive from it whenever you want without blocking anything.
+	// buffered so you can receive from it whenever you want without blocking.
+	//
+	// Note: can block if there is no space to buffer the message.
 	SendWaitable(m amqp.Message) <-chan Outcome
 
 	// SendForget buffers a message for sending and returns, with no notification of the outcome.
+	//
+	// Note: can block if there is no space to buffer the message.
 	SendForget(m amqp.Message)
 
 	// SendAsync puts a message in the send buffer and returns immediately.  An
@@ -63,6 +67,8 @@ type Sender interface {
 	// goroutines to avoid blocking the connection.
 	//
 	// If ack == nil no Outcome is sent.
+	//
+	// Note: can block if there is no space to buffer the message.
 	SendAsync(m amqp.Message, ack chan<- Outcome, value interface{})
 
 	SendAsyncTimeout(m amqp.Message, ack chan<- Outcome, value interface{}, timeout time.Duration)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6134e216/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
index 3303f0a..fa3e850 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
@@ -294,7 +294,7 @@ func (s Session) Receiver(name string) Link {
 // Unique (per process) string identifier for a connection, useful for debugging.
 func (c Connection) String() string {
 	// Use the transport address to match the default transport logs from PN_TRACE.
-	return fmt.Sprintf("%p", c.Transport().CPtr())
+	return fmt.Sprintf("(Connection)(%p)", c.Transport().CPtr())
 }
 
 func (c Connection) Type() string {
@@ -338,7 +338,7 @@ func (c Connection) SetPassword(password []byte) {
 }
 
 func (s Session) String() string {
-	return fmt.Sprintf("%s/%p", s.Connection(), s.pn)
+	return fmt.Sprintf("(Session)(%p)", s.pn) // TODO aconway 2016-09-12: should print channel number.
 }
 
 func (s Session) Type() string { return "session" }


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


[24/50] [abbrv] qpid-proton git commit: PROTON-1309: go: set outgoing message window via electron interface.

Posted by ac...@apache.org.
PROTON-1309: go: set outgoing message window via electron interface.

Added a session option and IncomingSession setter for outgoing window.


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

Branch: refs/heads/go1
Commit: 3569e03b28b0f82c5a4e1004be6684f628c15aa8
Parents: d91131a
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Oct 18 14:00:35 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Oct 18 14:01:52 2016 -0400

----------------------------------------------------------------------
 .../go/src/qpid.apache.org/electron/session.go  | 35 +++++++++++++-------
 1 file changed, 23 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3569e03b/proton-c/bindings/go/src/qpid.apache.org/electron/session.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/session.go b/proton-c/bindings/go/src/qpid.apache.org/electron/session.go
index 66a8995..6dae354 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/session.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/session.go
@@ -36,17 +36,24 @@ type Session interface {
 
 type session struct {
 	endpoint
-	pSession   proton.Session
-	connection *connection
-	capacity   uint
+	pSession                         proton.Session
+	connection                       *connection
+	incomingCapacity, outgoingWindow uint
 }
 
 // SessionOption can be passed when creating a Session
 type SessionOption func(*session)
 
 // IncomingCapacity returns a Session Option that sets the size (in bytes) of
-// the sessions incoming data buffer..
-func IncomingCapacity(cap uint) SessionOption { return func(s *session) { s.capacity = cap } }
+// the session's incoming data buffer.
+func IncomingCapacity(bytes uint) SessionOption {
+	return func(s *session) { s.incomingCapacity = bytes }
+}
+
+// OutgoingWindow returns a Session Option that sets the outgoing window size (in frames).
+func OutgoingWindow(frames uint) SessionOption {
+	return func(s *session) { s.outgoingWindow = frames }
+}
 
 // in proton goroutine
 func newSession(c *connection, es proton.Session, setting ...SessionOption) *session {
@@ -59,7 +66,8 @@ func newSession(c *connection, es proton.Session, setting ...SessionOption) *ses
 		set(s)
 	}
 	c.handler.sessions[s.pSession] = s
-	s.pSession.SetIncomingCapacity(s.capacity)
+	s.pSession.SetIncomingCapacity(s.incomingCapacity)
+	s.pSession.SetOutgoingWindow(s.outgoingWindow)
 	s.pSession.Open()
 	return s
 }
@@ -108,21 +116,24 @@ func (s *session) Receiver(setting ...LinkOption) (rcv Receiver, err error) {
 // incoming request to open a session.
 type IncomingSession struct {
 	incoming
-	h        *handler
-	pSession proton.Session
-	capacity uint
+	h                                *handler
+	pSession                         proton.Session
+	incomingCapacity, outgoingWindow uint
 }
 
 func newIncomingSession(h *handler, ps proton.Session) *IncomingSession {
 	return &IncomingSession{incoming: makeIncoming(ps), h: h, pSession: ps}
 }
 
-// SetCapacity sets the session buffer capacity of an incoming session in bytes.
-func (in *IncomingSession) SetCapacity(bytes uint) { in.capacity = bytes }
+// SetIncomingCapacity sets the session buffer capacity of an incoming session in bytes.
+func (in *IncomingSession) SetIncomingCapacity(bytes uint) { in.incomingCapacity = bytes }
+
+// SetOutgoingWindow sets the session outgoing window of an incoming session in frames.
+func (in *IncomingSession) SetOutgoingWindow(frames uint) { in.outgoingWindow = frames }
 
 // Accept an incoming session endpoint.
 func (in *IncomingSession) Accept() Endpoint {
 	return in.accept(func() Endpoint {
-		return newSession(in.h.connection, in.pSession, IncomingCapacity(in.capacity))
+		return newSession(in.h.connection, in.pSession, IncomingCapacity(in.incomingCapacity), OutgoingWindow(in.outgoingWindow))
 	})
 }


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


[26/50] [abbrv] qpid-proton git commit: NO-JIRA: Only try to run java tests if we are building java

Posted by ac...@apache.org.
NO-JIRA: Only try to run java tests if we are building java


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

Branch: refs/heads/go1
Commit: 956827559a3270f67ce6d1436ef309940ad9d05d
Parents: 1bbe435
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Oct 19 12:00:21 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Oct 19 12:00:21 2016 -0400

----------------------------------------------------------------------
 CMakeLists.txt          | 11 -----------
 proton-j/CMakeLists.txt | 11 +++++++++++
 2 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/95682755/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64311ea..df18cfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -188,17 +188,6 @@ install (DIRECTORY examples
          REGEX "/examples/CMakeLists.txt$" EXCLUDE
          PATTERN "*Config.cmake" EXCLUDE)
 
-# add relevant CTest support
-find_program (MAVEN_EXE mvn DOC "Location of the maven program")
-mark_as_advanced (MAVEN_EXE)
-if (CMAKE_BUILD_TYPE MATCHES "Coverage")
-  message (STATUS "Building for coverage analysis: testing disabled for Proton-J")
-elseif (JAVA_FOUND AND MAVEN_EXE)
-  add_test (proton-java ${MAVEN_EXE} clean test --file ${Proton_SOURCE_DIR}/pom.xml)
-else ()
-  message (STATUS "Cannot find both Java and Maven: testing disabled for Proton-J")
-endif ()
-
 # Generate test environment settings
 configure_file(${CMAKE_SOURCE_DIR}/config.sh.in
                ${CMAKE_BINARY_DIR}/config.sh @ONLY)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/95682755/proton-j/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-j/CMakeLists.txt b/proton-j/CMakeLists.txt
index b675464..788c08f 100644
--- a/proton-j/CMakeLists.txt
+++ b/proton-j/CMakeLists.txt
@@ -26,3 +26,14 @@ rebuild_jar(proton-j proton-j-${PN_VERSION}.jar)
 set (JAVA_INSTALL_DIR ${SHARE_INSTALL_DIR}/java CACHE PATH "Installation directory for all JARs except those using JNI")
 mark_as_advanced (JAVA_INSTALL_DIR)
 install_jar(proton-j ${JAVA_INSTALL_DIR})
+
+# add relevant CTest support
+find_program (MAVEN_EXE mvn DOC "Location of the maven program")
+mark_as_advanced (MAVEN_EXE)
+if (CMAKE_BUILD_TYPE MATCHES "Coverage")
+  message (STATUS "Building for coverage analysis: testing disabled for Proton-J")
+elseif (MAVEN_EXE)
+  add_test (proton-java ${MAVEN_EXE} clean test --file ${Proton_SOURCE_DIR}/pom.xml)
+else ()
+  message (STATUS "Cannot find Maven: testing disabled for Proton-J")
+endif ()


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


[15/50] [abbrv] qpid-proton git commit: PROTON-1323: bump python docs version metadata on master for 0.16.0

Posted by ac...@apache.org.
PROTON-1323: bump python docs version metadata on master for 0.16.0


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

Branch: refs/heads/go1
Commit: 3eb1785a5e5b9d5b74ebb94c1d20d5f7d335b5ee
Parents: d5b1036
Author: Robert Gemmell <ro...@apache.org>
Authored: Mon Oct 10 16:56:22 2016 +0100
Committer: Robert Gemmell <ro...@apache.org>
Committed: Mon Oct 10 16:56:22 2016 +0100

----------------------------------------------------------------------
 proton-c/bindings/python/docs/conf.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3eb1785a/proton-c/bindings/python/docs/conf.py
----------------------------------------------------------------------
diff --git a/proton-c/bindings/python/docs/conf.py b/proton-c/bindings/python/docs/conf.py
index a37a39f..9e51595 100644
--- a/proton-c/bindings/python/docs/conf.py
+++ b/proton-c/bindings/python/docs/conf.py
@@ -48,9 +48,9 @@ copyright = u'2015, Apache Qpid'
 # built documents.
 #
 # The short X.Y version.
-version = '0.15.0'
+version = '0.16.0'
 # The full version, including alpha/beta/rc tags.
-release = '0.15.0-SNAPSHOT'
+release = '0.16.0-SNAPSHOT'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.


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


[33/50] [abbrv] qpid-proton git commit: PROTON-1320: c++ Add std:: namespace prefix to srand and rand

Posted by ac...@apache.org.
PROTON-1320: c++ Add std:: namespace prefix to srand and rand

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: cca892e6c7b88d0cd65aa3c1074fd4570f28d881
Parents: 8c3aa3a
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 14:43:45 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/src/container_test.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cca892e6/proton-c/bindings/cpp/src/container_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_test.cpp b/proton-c/bindings/cpp/src/container_test.cpp
index 1a3e2c4..062bb94 100644
--- a/proton-c/bindings/cpp/src/container_test.cpp
+++ b/proton-c/bindings/cpp/src/container_test.cpp
@@ -43,9 +43,9 @@ static std::string int2string(int n) {
 int listen_on_random_port(proton::container& c, proton::listener& l) {
     int port;
     // I'm going to hell for this:
-    srand((unsigned int)time(0));
+    std::srand((unsigned int)time(0));
     while (true) {
-        port = 20000 + (rand() % 30000);
+        port = 20000 + (std::rand() % 30000);
         try {
             l = c.listen("0.0.0.0:" + int2string(port));
             break;


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


[13/50] [abbrv] qpid-proton git commit: PROTON-1313: c++: missing #include in some headers

Posted by ac...@apache.org.
PROTON-1313: c++: missing #include <string> in some headers

Several header files that use std::string were missing #include <string>:

binary.hpp
symbol.hpp
url.hpp


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

Branch: refs/heads/go1
Commit: 6d3aa78420febe314b9bf43a06a966fe13742380
Parents: 64abf06
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Oct 6 11:26:16 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 6 11:26:16 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/include/proton/binary.hpp | 1 +
 proton-c/bindings/cpp/include/proton/symbol.hpp | 2 ++
 proton-c/bindings/cpp/include/proton/url.hpp    | 1 +
 3 files changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6d3aa784/proton-c/bindings/cpp/include/proton/binary.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/binary.hpp b/proton-c/bindings/cpp/include/proton/binary.hpp
index b7b7ac1..d2f5b97 100644
--- a/proton-c/bindings/cpp/include/proton/binary.hpp
+++ b/proton-c/bindings/cpp/include/proton/binary.hpp
@@ -26,6 +26,7 @@
 #include "./types_fwd.hpp"
 
 #include <iosfwd>
+#include <string>
 #include <vector>
 
 namespace proton {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6d3aa784/proton-c/bindings/cpp/include/proton/symbol.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/symbol.hpp b/proton-c/bindings/cpp/include/proton/symbol.hpp
index 026154f..303f350 100644
--- a/proton-c/bindings/cpp/include/proton/symbol.hpp
+++ b/proton-c/bindings/cpp/include/proton/symbol.hpp
@@ -22,6 +22,8 @@
  *
  */
 
+#include <string>
+
 namespace proton {
 
 /// A std::string that represents the AMQP symbol type.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6d3aa784/proton-c/bindings/cpp/include/proton/url.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/url.hpp b/proton-c/bindings/cpp/include/proton/url.hpp
index 1ff0bba..57ef586 100644
--- a/proton-c/bindings/cpp/include/proton/url.hpp
+++ b/proton-c/bindings/cpp/include/proton/url.hpp
@@ -26,6 +26,7 @@
 #include "./error.hpp"
 
 #include <iosfwd>
+#include <string>
 
 struct pn_url_t;
 


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


[18/50] [abbrv] qpid-proton git commit: NO-JIRA: ensure requests are sent as strings with python 2

Posted by ac...@apache.org.
NO-JIRA: ensure requests are sent as strings with python 2


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

Branch: refs/heads/go1
Commit: 5639656cf817e8f0f656ee22a31655a50a3fcc39
Parents: 1522100
Author: Gordon Sim <gs...@redhat.com>
Authored: Tue Oct 11 14:01:53 2016 +0100
Committer: Gordon Sim <gs...@redhat.com>
Committed: Tue Oct 11 14:02:08 2016 +0100

----------------------------------------------------------------------
 examples/python/sync_client.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5639656c/examples/python/sync_client.py
----------------------------------------------------------------------
diff --git a/examples/python/sync_client.py b/examples/python/sync_client.py
index 95a5650..0b7b045 100755
--- a/examples/python/sync_client.py
+++ b/examples/python/sync_client.py
@@ -23,7 +23,7 @@ Demonstrates the client side of the synchronous request-response pattern
 (also known as RPC or Remote Procecure Call) using proton.
 
 """
-from __future__ import print_function
+from __future__ import print_function, unicode_literals
 
 import optparse
 from proton import Message, Url, ConnectionException, Timeout


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


[03/50] [abbrv] qpid-proton git commit: PROTON-1255: connection_engine separate bind from _init

Posted by ac...@apache.org.
PROTON-1255: connection_engine separate bind from _init

SASL/SSL properties must be set on connection and transport *before* the
pn_transport_bind() call, move it out of pn_connection_engine_init() and add
pn_connection_engine_start() that must be called before using the engine but
after security (and other) properties are set.

Updated the Go and C++ engines accordingly.


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

Branch: refs/heads/go1
Commit: 3d9fe620758bd55afae6af76b50a2bd5d6839232
Parents: b4d0912
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Sep 6 12:39:36 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 20 17:39:15 2016 -0400

----------------------------------------------------------------------
 .../bindings/cpp/src/io/connection_engine.cpp   |  1 +
 .../go/src/qpid.apache.org/proton/engine.go     |  2 +
 proton-c/include/proton/connection_engine.h     | 40 ++++++++++++++------
 proton-c/src/engine/connection_engine.c         | 17 +++++----
 4 files changed, 40 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3d9fe620/proton-c/bindings/cpp/src/io/connection_engine.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_engine.cpp b/proton-c/bindings/cpp/src/io/connection_engine.cpp
index 4712b3e..d3f2667 100644
--- a/proton-c/bindings/cpp/src/io/connection_engine.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_engine.cpp
@@ -65,6 +65,7 @@ void connection_engine::configure(const connection_options& opts) {
     opts.apply_bound(c);
     handler_ =  opts.handler();
     connection_context::get(connection()).collector = c_engine_.collector;
+    pn_connection_engine_start(&c_engine_);
 }
 
 connection_engine::~connection_engine() {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3d9fe620/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index 3cc6524..bfcb41c 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -248,6 +248,8 @@ func (eng *Engine) Disconnect(err error) {
 // disconnected.  You can check for errors after exit with Engine.Error().
 //
 func (eng *Engine) Run() error {
+	C.pn_connection_engine_start(&eng.engine)
+
 	// Channels for read and write buffers going in and out of the read/write goroutines.
 	// The channels are unbuffered: we want to exchange buffers in seuquence.
 	readsIn, writesIn := make(chan []byte), make(chan []byte)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3d9fe620/proton-c/include/proton/connection_engine.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/connection_engine.h b/proton-c/include/proton/connection_engine.h
index cf5006b..b1476c7 100644
--- a/proton-c/include/proton/connection_engine.h
+++ b/proton-c/include/proton/connection_engine.h
@@ -43,16 +43,21 @@
 /// Summary of use:
 ///
 /// - while !pn_connection_engine_finished()
+///   - Call pn_connection_engine_dispatch() to dispatch events until it returns NULL.
 ///   - Read data from your source into pn_connection_engine_read_buffer()
 ///   - Call pn_connection_engine_read_done() when complete.
 ///   - Write data from pn_connection_engine_write_buffer() to your destination.
 ///   - Call pn_connection_engine_write_done() to indicate how much was written.
-///   - Call pn_connection_engine_dispatch() to dispatch events until it returns NULL.
 ///
-/// Note on error handling: most of the pn_connection_engine_*() functions do
-/// not return an error code. If a fatal error occurs, the transport error
-/// condition will be set and the next call to pn_connection_engine_dispatch()
-/// report it to the handler as a  PN_TRANSPORT_ERROR event and return false.
+/// Note on blocking: the _read/write_buffer and _read/write_done functions can
+/// all generate events that may cause the engine to finish. Before you wait for
+/// IO, always drain pn_connection_engine_dispatch() till it returns NULL and
+/// check pn_connection_engine_finished() in case there is nothing more to do..
+///
+/// Note on error handling: the pn_connection_engine_*() functions do not return
+/// an error code. If an error occurs it will be reported as a
+/// PN_TRANSPORT_ERROR event and pn_connection_engine_finished() will return
+/// true once all final events have been processed.
 ///
 /// @defgroup connection_engine The Connection Engine
 /// @{
@@ -79,16 +84,27 @@ typedef struct pn_connection_engine_t {
     pn_event_t* event;
 } pn_connection_engine_t;
 
-/// Initialize a pn_connection_engine_t struct with a new connection, transport
-/// and collector. Return 0 on success, a proton error code on failure.
+/// Initialize a pn_connection_engine_t struct with a new connection and
+/// transport.
+///
+/// Configure connection properties and call connection_engine_start() before
+/// using the engine.
+///
+/// Call pn_connection_engine_final to free resources when you are done.
+///
+///@return 0 on success, a proton error code on failure (@see error.h)
+///
 PN_EXTERN int pn_connection_engine_init(pn_connection_engine_t* engine);
 
-/// Release the connection, transport and collector associated with engine, set all the pointers
-/// to NULL. Only call on an engine that was initialized with pn_connection_engine_init
+/// Start the engine, call after setting security and host properties.
+PN_EXTERN void pn_connection_engine_start(pn_connection_engine_t* engine);
+
+/// Free resources used by the engine, set the connection and transport pointers
+/// to NULL.
 PN_EXTERN void pn_connection_engine_final(pn_connection_engine_t* engine);
 
-/// The engine's read buffer. Read data from your IO source to buf.start, up to
-/// a max of buf.size. Then call pn_connection_engine_read_done().
+/// Get the engine's read buffer. Read data from your IO source to buf.start, up
+/// to a max of buf.size. Then call pn_connection_engine_read_done().
 ///
 /// buf.size==0 means the engine cannot read presently, calling
 /// pn_connection_engine_dispatch() may create more buffer space.
@@ -104,7 +120,7 @@ PN_EXTERN void pn_connection_engine_read_done(pn_connection_engine_t*, size_t n)
 /// in pn_connection_engine_write_buffer()
 PN_EXTERN void pn_connection_engine_read_close(pn_connection_engine_t*);
 
-/// The engine's write buffer. Write data from buf.start to your IO destination,
+/// Get the engine's write buffer. Write data from buf.start to your IO destination,
 /// up to a max of buf.size. Then call pn_connection_engine_write_done().
 ///
 /// buf.size==0 means the engine has nothing to write presently.  Calling

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3d9fe620/proton-c/src/engine/connection_engine.c
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/connection_engine.c b/proton-c/src/engine/connection_engine.c
index 41a1bdc..adfb145 100644
--- a/proton-c/src/engine/connection_engine.c
+++ b/proton-c/src/engine/connection_engine.c
@@ -30,19 +30,20 @@ int pn_connection_engine_init(pn_connection_engine_t* e) {
     e->collector = pn_collector();
     if (!e->connection || !e->transport || !e->collector) {
         pn_connection_engine_final(e);
-        return PN_ERR;
-    }
-    int err;
-    // Bind before collect: don't expose the connection until it has a transport.
-    err = pn_transport_bind(e->transport, e->connection);
-    if (err) {
-        pn_connection_engine_final(e);
-        return err;
+        return PN_OUT_OF_MEMORY;
     }
     pn_connection_collect(e->connection, e->collector);
     return PN_OK;
 }
 
+void pn_connection_engine_start(pn_connection_engine_t* e) {
+    /*
+      Ignore bind errors. PN_STATE_ERR means we are already bound, any
+      other error will be delivered as an event.
+    */
+    pn_transport_bind(e->transport, e->connection);
+}
+
 void pn_connection_engine_final(pn_connection_engine_t* e) {
     if (e->transport && e->connection) {
         pn_transport_unbind(e->transport);


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


[41/50] [abbrv] qpid-proton git commit: PROTON-1333: CMake error if no C++ compiler avaliable

Posted by ac...@apache.org.
PROTON-1333: CMake error if no C++ compiler avaliable

Change if() statement to use variable name not quoted ${variable}.


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

Branch: refs/heads/go1
Commit: f83c70cc5b929161ead83567a048d3f6cb9a0dd4
Parents: f8c4c27
Author: Alan Conway <ac...@redhat.com>
Authored: Mon Oct 24 21:15:55 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Oct 24 21:20:11 2016 -0400

----------------------------------------------------------------------
 proton-c/CMakeLists.txt | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f83c70cc/proton-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index 0b4f7e1..cba043a 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -110,13 +110,13 @@ elseif (SASL_IMPL STREQUAL none)
 endif ()
 
 # Set Compiler extra flags for Solaris when using SunStudio
-IF( ${CMAKE_CXX_COMPILER_ID} STREQUAL "SunPro" )
-    SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mt" )
-ENDIF()
+if(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro" )
+    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mt" )
+endif()
 
-IF( ${CMAKE_C_COMPILER_ID} STREQUAL "SunPro" )
-    SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mt" )
-ENDIF()
+if(CMAKE_C_COMPILER_ID STREQUAL "SunPro" )
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mt")
+endif()
 
 # Link in openssl if present
 if (SSL_IMPL STREQUAL openssl)
@@ -250,7 +250,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
   endif (ENABLE_HIDE_UNEXPORTED_SYMBOLS)
-elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "SunPro")
+elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
   if (ENABLE_HIDE_UNEXPORTED_SYMBOLS)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -xldscope=hidden")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -xldscope=hidden")


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


[50/50] [abbrv] qpid-proton git commit: PROTON-1338: Go: update `go get`

Posted by ac...@apache.org.
PROTON-1338: Go: update `go get`

Merge branch 'master' into go1 to update the published `go get` version of the
Go packages. The new packages are tested with C library versions 0.10 - 0.15.0


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

Branch: refs/heads/go1
Commit: 287eeacafbfc166529108b9f6d1bf8e839c9f9be
Parents: 5e6024b 7b6b8de
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Nov 1 22:48:55 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Nov 1 22:48:55 2016 -0400

----------------------------------------------------------------------
 README.md                         |   5 +-
 amqp/error.go                     |  28 +-
 amqp/interop_test.go              |  32 +-
 amqp/marshal.go                   |   2 +-
 amqp/message.go                   |   4 +-
 amqp/url.go                       | 118 +++----
 amqp/url_test.go                  |  14 +-
 amqp/version.go                   |  29 ++
 electron/auth_test.go             | 124 ++++++++
 electron/connection.go            | 287 +++++++++++++----
 electron/container.go             |  49 ++-
 electron/doc.go                   |  43 ++-
 electron/electron_test.go         | 546 +++++++++++++++++++++++++++++++++
 electron/endpoint.go              | 122 ++++++--
 electron/ex_client_server_test.go |  81 +++++
 electron/handler.go               |  86 +++---
 electron/link.go                  |  62 ++--
 electron/messaging_test.go        | 454 ---------------------------
 electron/receiver.go              |  75 +++--
 electron/sender.go                |  32 +-
 electron/session.go               |  47 +--
 proton/engine.go                  | 377 ++++++++++++-----------
 proton/handlers.go                |  41 ++-
 proton/proton_test.go             |  73 ++++-
 proton/wrappers.go                |  69 ++++-
 proton/wrappers_gen.go            |  88 +++++-
 26 files changed, 1873 insertions(+), 1015 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/README.md
----------------------------------------------------------------------
diff --cc README.md
index 4b2da12,9f95939..ffd67f8
--- a/README.md
+++ b/README.md
@@@ -1,96 -1,44 +1,97 @@@
 -Qpid Proton - AMQP messaging toolkit
 -====================================
 -
 -Linux Build | Windows Build
 -------------|--------------
 -[![Linux Build Status](https://travis-ci.org/apache/qpid-proton.svg?branch=master)](https://travis-ci.org/apache/qpid-proton) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/apache/qpid-proton?branch=master&svg=true)](https://ci.appveyor.com/project/ke4qqq/qpid-proton/branch/master)
 -
 -Qpid Proton is a high-performance, lightweight messaging library. It can be
 -used in the widest range of messaging applications, including brokers, client
 -libraries, routers, bridges, proxies, and more. Proton makes it trivial to
 -integrate with the AMQP 1.0 ecosystem from any platform, environment, or
 -language
 -
 -Features
 ---------
 -
 -  + A flexible and capable reactive messaging API
 -  + Full control of AMQP 1.0 protocol semantics
 -  + Portable C implementation with bindings to popular languages
 -  + Pure-Java and pure-JavaScript implementations
 -  + Peer-to-peer and brokered messaging
 -  + Secure communication via SSL and SASL
 -
 -Universal - Proton is designed to scale both up and down. Equally suitable for
 -simple clients or high-powered servers, it can be deployed in simple
 -peer-to-peer configurations or as part of a global federated messaging network.
 -
 -Embeddable - Proton is carefully written to be portable and cross platform. It
 -has minimal dependencies, and it is architected to be usable with any threading
 -model, as well as with non-threaded applications. These features make it
 -uniquely suited for embedding messaging capabilities into existing software.
 -
 -Standard - Built around the AMQP 1.0 messaging standard, Proton is not only
 -ideal for building out your own messaging applications but also for connecting
 -them to the broader ecosystem of AMQP 1.0-based messaging applications.
 -
 -Getting Started
 ----------------
 -
 -See the included INSTALL file for build and install instructions and the
 -DEVELOPERS file for information on how to modify and test the library code
 -itself.
 -
 -Please see http://qpid.apache.org/proton for a more info.
 +# Qpid Go packages for AMQP
 +
 +These packages provide [Go](http://golang.org) support for sending and receiving
 +AMQP messages in client or server applications. Reference documentation is
 +available at: <http://godoc.org/?q=qpid.apache.org>
 +
 +There are 3 packages:
 +
 +[qpid.apache.org/amqp](http://godoc.org/qpid.apache.org/amqp) provides functions
 +to convert AMQP messages and data types to and from Go data types.  Used by both
 +the proton and electron packages to manage AMQP data.
 +
 +[qpid.apache.org/electron](http://godoc.org/qpid.apache.org/electron) is a
 +simple, concurrent-safe API for sending and receiving messages. It can be used
 +with goroutines and channels to build concurrent AMQP clients and servers.
 +
 +[qpid.apache.org/proton](http://godoc.org/qpid.apache.org/proton) is an
 +event-driven, concurrent-unsafe package that closely follows the proton C
- API. Most Go programmers will find the electron package easier to use.
++API. Most Go programmers will find the
++[electron](http://godoc.org/qpid.apache.org/electron) package easier to use.
 +
- There are [examples](https://github.com/apache/qpid-proton/blob/master/examples/go/README.md)
++See the [examples](https://github.com/apache/qpid-proton/blob/master/examples/go/README.md)
 +to help you get started.
 +
 +Feedback is encouraged at:
 +
 +- Email <pr...@qpid.apache.org>
 +- Create issues <https://issues.apache.org/jira/browse/PROTON>, attach patches to an issue.
 +
 +### Why two APIs?
 +
 +The `proton` API is a direct mapping of the proton C library into Go. It is
 +usable but not very natural for a Go programmer because it takes an
 +*event-driven* approach and has no built-in support for concurrent
 +use. `electron` uses `proton` internally but provides a more Go-like API that is
 +safe to use from multiple concurrent goroutines.
 +
 +Go encourages programs to be structured as concurrent *goroutines* that
 +communicate via *channels*. Go literature distinguishes between:
 +
 +- *concurrency*: "keeping track of things that could be done in parallel"
 +- *parallelism*: "actually doing things in parallel on multiple CPUs or cores"
 +
 +A Go program expresses concurrency by starting goroutines for potentially
 +concurrent tasks. The Go runtime schedules the activity of goroutines onto a
 +small number (possibly one) of actual parallel executions.
 +
 +Even with no hardware parallelism, goroutine concurrency lets the Go runtime
 +order unpredictable events like file descriptors being readable/writable,
 +channels having data, timers firing etc. Go automatically takes care of
 +switching out goroutines that block or sleep so it is normal to write code in
 +terms of blocking calls.
 +
 +By contrast, event-driven programming is based on polling mechanisms like
 +`select`, `poll` or `epoll`. These also dispatch unpredictably ordered events to
 +a single thread or a small thread pool. However this requires a different style
 +of programming: "event-driven" or "reactive" programming. Go developers call it
 +"inside-out" programming.  In an event-driven program blocking is a big problem
 +as it consumes a scarce thread of execution, so actions that take time to
 +complete have to be re-structured in terms of multiple events.
 +
 +The promise of Go is that you can express your program in concurrent, sequential
 +terms and the Go runtime will turn it inside-out for you. You can start
 +goroutines for all concurrent activities. They can loop forever or block for as
 +long as they need waiting for timers, IO or any unpredictable event. Go will
 +interleave and schedule them efficiently onto the available parallel hardware.
 +
 +For example: in the `electron` API, you can send a message and wait for it to be
 +acknowledged in a single function. All the information about the message, why
 +you sent it, and what to do when it is acknowledged can be held in local
 +variables, all the code is in a simple sequence. Other goroutines in your
 +program can be sending and receiving messages concurrently, they are not
 +blocked.
 +
 +In the `proton` API, an event handler that sends a message must return
 +*immediately*, it cannot block the event loop to wait for
 +acknowledgement. Acknowledgement is a separate event, so the code for handling
 +it is in a different event handler. Context information about the message has to
 +be stored in some non-local variable that both functions can find. This makes
 +the code harder to follow.
 +
 +The `proton` API is important because it is the foundation for the `electron`
 +API, and may be useful for programs that need to be close to the original C
 +library for some reason. However the `electron` API hides the event-driven
 +details behind simple, sequential, concurrent-safe methods that can be called
 +from arbitrary goroutines. Under the covers, data is passed through channels to
 +dedicated `proton` goroutines so user goroutines can work concurrently with the
 +proton event-loop.
 +
 +## New to Go?
 +
 +If you are new to Go then these are a good place to start:
 +
 +- [A Tour of Go](http://tour.golang.org)
 +- [Effective Go](http://golang.org/doc/effective_go.html)
 +
 +Then look at the tools and docs at <http://golang.org> as you need them.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/error.go
----------------------------------------------------------------------
diff --cc amqp/error.go
index 349fc41,0000000..3a178b2
mode 100644,000000..100644
--- a/amqp/error.go
+++ b/amqp/error.go
@@@ -1,103 -1,0 +1,103 @@@
 +/*
 +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 amqp
 +
 +// #include <proton/error.h>
 +import "C"
 +
 +import (
 +	"fmt"
 +	"reflect"
 +)
 +
 +// Error is an AMQP error condition. It has a name and a description.
 +// It implements the Go error interface so can be returned as an error value.
 +//
- // You can pass amqp.Error to methods that pass an error to a remote endpoint,
++// You can pass amqp.Error to methods that send an error to a remote endpoint,
 +// this gives you full control over what the remote endpoint will see.
 +//
 +// You can also pass any Go error to such functions, the remote peer
 +// will see the equivalent of MakeError(error)
 +//
 +type Error struct{ Name, Description string }
 +
 +// Error implements the Go error interface for AMQP error errors.
 +func (c Error) Error() string { return fmt.Sprintf("%s: %s", c.Name, c.Description) }
 +
 +// Errorf makes a Error with name and formatted description as per fmt.Sprintf
 +func Errorf(name, format string, arg ...interface{}) Error {
 +	return Error{name, fmt.Sprintf(format, arg...)}
 +}
 +
 +// MakeError makes an AMQP error from a go error using the Go error type as the name
 +// and the err.Error() string as the description.
 +func MakeError(err error) Error {
 +	return Error{reflect.TypeOf(err).Name(), err.Error()}
 +}
 +
 +var (
- 	InternalError      = "amqp:internal-error"
- 	NotFound           = "amqp:not-found"
- 	UnauthorizedAccess = "amqp:unauthorized-access"
- 	DecodeError        = "amqp:decode-error"
- 	ResourceLimit      = "amqp:resource-limit"
- 	NotAllowed         = "amqp:not-allowed"
- 	InvalidField       = "amqp:invalid-field"
- 	NotImplemented     = "amqp:not-implemented"
- 	ResourceLocked     = "amqp:resource-locked"
- 	PreerrorFailed     = "amqp:preerror-failed"
- 	ResourceDeleted    = "amqp:resource-deleted"
- 	IllegalState       = "amqp:illegal-state"
- 	FrameSizeTooSmall  = "amqp:frame-size-too-small"
++	InternalError         = "amqp:internal-error"
++	NotFound              = "amqp:not-found"
++	UnauthorizedAccess    = "amqp:unauthorized-access"
++	DecodeError           = "amqp:decode-error"
++	ResourceLimitExceeded = "amqp:resource-limit-exceeded"
++	NotAllowed            = "amqp:not-allowed"
++	InvalidField          = "amqp:invalid-field"
++	NotImplemented        = "amqp:not-implemented"
++	ResourceLocked        = "amqp:resource-locked"
++	PreconditionFailed    = "amqp:precondition-failed"
++	ResourceDeleted       = "amqp:resource-deleted"
++	IllegalState          = "amqp:illegal-state"
++	FrameSizeTooSmall     = "amqp:frame-size-too-small"
 +)
 +
 +type PnErrorCode int
 +
 +func (e PnErrorCode) String() string {
 +	switch e {
 +	case C.PN_EOS:
 +		return "end-of-data"
 +	case C.PN_ERR:
 +		return "error"
 +	case C.PN_OVERFLOW:
 +		return "overflow"
 +	case C.PN_UNDERFLOW:
 +		return "underflow"
 +	case C.PN_STATE_ERR:
 +		return "bad-state"
 +	case C.PN_ARG_ERR:
 +		return "invalid-argument"
 +	case C.PN_TIMEOUT:
 +		return "timeout"
 +	case C.PN_INTR:
 +		return "interrupted"
 +	case C.PN_INPROGRESS:
 +		return "in-progress"
 +	default:
 +		return fmt.Sprintf("unknown-error(%d)", e)
 +	}
 +}
 +
 +func PnError(e *C.pn_error_t) error {
 +	if e == nil || C.pn_error_code(e) == 0 {
 +		return nil
 +	}
 +	return fmt.Errorf("%s: %s", PnErrorCode(C.pn_error_code(e)), C.GoString(C.pn_error_text(e)))
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/interop_test.go
----------------------------------------------------------------------
diff --cc amqp/interop_test.go
index b36ef64,0000000..b3e27bc
mode 100644,000000..100644
--- a/amqp/interop_test.go
+++ b/amqp/interop_test.go
@@@ -1,381 -1,0 +1,385 @@@
 +/*
 +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.
 +*/
 +
 +// Test that conversion of Go type to/from AMQP is compatible with other
 +// bindings.
 +//
 +package amqp
 +
 +import (
 +	"bytes"
 +	"fmt"
 +	"io"
 +	"io/ioutil"
 +	"os"
 +	"reflect"
 +	"strings"
 +	"testing"
 +)
 +
 +func checkEqual(want interface{}, got interface{}) error {
 +	if !reflect.DeepEqual(want, got) {
 +		return fmt.Errorf("%#v != %#v", want, got)
 +	}
 +	return nil
 +}
 +
- func getReader(name string) (r io.Reader) {
- 	r, err := os.Open("interop/" + name + ".amqp")
++func getReader(t *testing.T, name string) (r io.Reader) {
++	dir := os.Getenv("PN_INTEROP_DIR")
++	if dir == "" {
++		t.Skip("no PN_INTEROP_DIR in environment")
++	}
++	r, err := os.Open(dir + "/" + name + ".amqp")
 +	if err != nil {
- 		panic(fmt.Errorf("Can't open %#v: %v", name, err))
++		t.Fatalf("can't open %#v: %v", name, err)
 +	}
 +	return
 +}
 +
 +func remaining(d *Decoder) string {
 +	remainder, _ := ioutil.ReadAll(io.MultiReader(d.Buffered(), d.reader))
 +	return string(remainder)
 +}
 +
 +// checkDecode: want is the expected value, gotPtr is a pointer to a
 +// instance of the same type for Decode.
 +func checkDecode(d *Decoder, want interface{}, gotPtr interface{}, t *testing.T) {
 +
 +	if err := d.Decode(gotPtr); err != nil {
 +		t.Error("Decode failed", err)
 +		return
 +	}
 +	got := reflect.ValueOf(gotPtr).Elem().Interface()
 +	if err := checkEqual(want, got); err != nil {
 +		t.Error("Decode bad value:", err)
 +		return
 +	}
 +
 +	// Try round trip encoding
 +	bytes, err := Marshal(want, nil)
 +	if err != nil {
 +		t.Error("Marshal failed", err)
 +		return
 +	}
 +	n, err := Unmarshal(bytes, gotPtr)
 +	if err != nil {
 +		t.Error("Unmarshal failed", err)
 +		return
 +	}
 +	if err := checkEqual(n, len(bytes)); err != nil {
 +		t.Error("Bad unmarshal length", err)
 +		return
 +	}
 +	got = reflect.ValueOf(gotPtr).Elem().Interface()
 +	if err = checkEqual(want, got); err != nil {
 +		t.Error("Bad unmarshal value", err)
 +		return
 +	}
 +}
 +
 +func TestUnmarshal(t *testing.T) {
- 	bytes, err := ioutil.ReadAll(getReader("strings"))
++	bytes, err := ioutil.ReadAll(getReader(t, "strings"))
 +	if err != nil {
 +		t.Error(err)
 +	}
 +	for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
 +		var got string
 +		n, err := Unmarshal(bytes, &got)
 +		if err != nil {
 +			t.Error(err)
 +		}
 +		if want != got {
 +			t.Errorf("%#v != %#v", want, got)
 +		}
 +		bytes = bytes[n:]
 +	}
 +}
 +
 +func TestPrimitivesExact(t *testing.T) {
- 	d := NewDecoder(getReader("primitives"))
++	d := NewDecoder(getReader(t, "primitives"))
 +	// Decoding into exact types
 +	var b bool
 +	checkDecode(d, true, &b, t)
 +	checkDecode(d, false, &b, t)
 +	var u8 uint8
 +	checkDecode(d, uint8(42), &u8, t)
 +	var u16 uint16
 +	checkDecode(d, uint16(42), &u16, t)
 +	var i16 int16
 +	checkDecode(d, int16(-42), &i16, t)
 +	var u32 uint32
 +	checkDecode(d, uint32(12345), &u32, t)
 +	var i32 int32
 +	checkDecode(d, int32(-12345), &i32, t)
 +	var u64 uint64
 +	checkDecode(d, uint64(12345), &u64, t)
 +	var i64 int64
 +	checkDecode(d, int64(-12345), &i64, t)
 +	var f32 float32
 +	checkDecode(d, float32(0.125), &f32, t)
 +	var f64 float64
 +	checkDecode(d, float64(0.125), &f64, t)
 +}
 +
 +func TestPrimitivesCompatible(t *testing.T) {
- 	d := NewDecoder(getReader("primitives"))
++	d := NewDecoder(getReader(t, "primitives"))
 +	// Decoding into compatible types
 +	var b bool
 +	var i int
 +	var u uint
 +	var f float64
 +	checkDecode(d, true, &b, t)
 +	checkDecode(d, false, &b, t)
 +	checkDecode(d, uint(42), &u, t)
 +	checkDecode(d, uint(42), &u, t)
 +	checkDecode(d, -42, &i, t)
 +	checkDecode(d, uint(12345), &u, t)
 +	checkDecode(d, -12345, &i, t)
 +	checkDecode(d, uint(12345), &u, t)
 +	checkDecode(d, -12345, &i, t)
 +	checkDecode(d, 0.125, &f, t)
 +	checkDecode(d, 0.125, &f, t)
 +}
 +
 +// checkDecodeValue: want is the expected value, decode into a reflect.Value
 +func checkDecodeInterface(d *Decoder, want interface{}, t *testing.T) {
 +
 +	var got, got2 interface{}
 +	if err := d.Decode(&got); err != nil {
 +		t.Error("Decode failed", err)
 +		return
 +	}
 +	if err := checkEqual(want, got); err != nil {
 +		t.Error(err)
 +		return
 +	}
 +	// Try round trip encoding
 +	bytes, err := Marshal(got, nil)
 +	if err != nil {
 +		t.Error(err)
 +		return
 +	}
 +	n, err := Unmarshal(bytes, &got2)
 +	if err != nil {
 +		t.Error(err)
 +		return
 +	}
 +	if err := checkEqual(n, len(bytes)); err != nil {
 +		t.Error(err)
 +		return
 +	}
 +	if err := checkEqual(want, got2); err != nil {
 +		t.Error(err)
 +		return
 +	}
 +}
 +
 +func TestPrimitivesInterface(t *testing.T) {
- 	d := NewDecoder(getReader("primitives"))
++	d := NewDecoder(getReader(t, "primitives"))
 +	checkDecodeInterface(d, true, t)
 +	checkDecodeInterface(d, false, t)
 +	checkDecodeInterface(d, uint8(42), t)
 +	checkDecodeInterface(d, uint16(42), t)
 +	checkDecodeInterface(d, int16(-42), t)
 +	checkDecodeInterface(d, uint32(12345), t)
 +	checkDecodeInterface(d, int32(-12345), t)
 +	checkDecodeInterface(d, uint64(12345), t)
 +	checkDecodeInterface(d, int64(-12345), t)
 +	checkDecodeInterface(d, float32(0.125), t)
 +	checkDecodeInterface(d, float64(0.125), t)
 +}
 +
 +func TestStrings(t *testing.T) {
- 	d := NewDecoder(getReader("strings"))
++	d := NewDecoder(getReader(t, "strings"))
 +	// Test decoding as plain Go strings
 +	for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
 +		var got string
 +		checkDecode(d, want, &got, t)
 +	}
 +	remains := remaining(d)
 +	if remains != "" {
 +		t.Errorf("leftover: %s", remains)
 +	}
 +
 +	// Test decoding as specific string types
- 	d = NewDecoder(getReader("strings"))
++	d = NewDecoder(getReader(t, "strings"))
 +	var bytes []byte
 +	var str, sym string
 +	checkDecode(d, []byte("abc\000defg"), &bytes, t)
 +	checkDecode(d, "abcdefg", &str, t)
 +	checkDecode(d, "abcdefg", &sym, t)
 +	checkDecode(d, make([]byte, 0), &bytes, t)
 +	checkDecode(d, "", &str, t)
 +	checkDecode(d, "", &sym, t)
 +	remains = remaining(d)
 +	if remains != "" {
 +		t.Fatalf("leftover: %s", remains)
 +	}
 +
 +	// Test some error handling
- 	d = NewDecoder(getReader("strings"))
++	d = NewDecoder(getReader(t, "strings"))
 +	var s string
 +	err := d.Decode(s)
 +	if err == nil {
 +		t.Fatal("Expected error")
 +	}
 +	if !strings.Contains(err.Error(), "not a pointer") {
 +		t.Error(err)
 +	}
 +	var i int
 +	err = d.Decode(&i)
 +	if !strings.Contains(err.Error(), "cannot unmarshal") {
 +		t.Error(err)
 +	}
 +	_, err = Unmarshal([]byte{}, nil)
 +	if !strings.Contains(err.Error(), "not enough data") {
 +		t.Error(err)
 +	}
 +	_, err = Unmarshal([]byte("foobar"), nil)
 +	if !strings.Contains(err.Error(), "invalid-argument") {
 +		t.Error(err)
 +	}
 +}
 +
 +func TestEncodeDecode(t *testing.T) {
 +	type data struct {
 +		s  string
 +		i  int
 +		u8 uint8
 +		b  bool
 +		f  float32
 +		v  interface{}
 +	}
 +
 +	in := data{"foo", 42, 9, true, 1.234, "thing"}
 +
 +	buf := bytes.Buffer{}
 +	e := NewEncoder(&buf)
 +	if err := e.Encode(in.s); err != nil {
 +		t.Error(err)
 +	}
 +	if err := e.Encode(in.i); err != nil {
 +		t.Error(err)
 +	}
 +	if err := e.Encode(in.u8); err != nil {
 +		t.Error(err)
 +	}
 +	if err := e.Encode(in.b); err != nil {
 +		t.Error(err)
 +	}
 +	if err := e.Encode(in.f); err != nil {
 +		t.Error(err)
 +	}
 +	if err := e.Encode(in.v); err != nil {
 +		t.Error(err)
 +	}
 +
 +	var out data
 +	d := NewDecoder(&buf)
 +	if err := d.Decode(&out.s); err != nil {
 +		t.Error(err)
 +	}
 +	if err := d.Decode(&out.i); err != nil {
 +		t.Error(err)
 +	}
 +	if err := d.Decode(&out.u8); err != nil {
 +		t.Error(err)
 +	}
 +	if err := d.Decode(&out.b); err != nil {
 +		t.Error(err)
 +	}
 +	if err := d.Decode(&out.f); err != nil {
 +		t.Error(err)
 +	}
 +	if err := d.Decode(&out.v); err != nil {
 +		t.Error(err)
 +	}
 +
 +	if err := checkEqual(in, out); err != nil {
 +		t.Error(err)
 +	}
 +}
 +
 +func TestMap(t *testing.T) {
- 	d := NewDecoder(getReader("maps"))
++	d := NewDecoder(getReader(t, "maps"))
 +
 +	// Generic map
 +	var m Map
 +	checkDecode(d, Map{"one": int32(1), "two": int32(2), "three": int32(3)}, &m, t)
 +
 +	// Interface as map
 +	var i interface{}
 +	checkDecode(d, Map{int32(1): "one", int32(2): "two", int32(3): "three"}, &i, t)
 +
- 	d = NewDecoder(getReader("maps"))
++	d = NewDecoder(getReader(t, "maps"))
 +	// Specific typed map
 +	var m2 map[string]int
 +	checkDecode(d, map[string]int{"one": 1, "two": 2, "three": 3}, &m2, t)
 +
 +	// Nested map
 +	m = Map{int64(1): "one", "two": int32(2), true: Map{uint8(1): true, uint8(2): false}}
 +	bytes, err := Marshal(m, nil)
 +	if err != nil {
 +		t.Fatal(err)
 +	}
 +	_, err = Unmarshal(bytes, &i)
 +	if err != nil {
 +		t.Fatal(err)
 +	}
 +	if err = checkEqual(m, i); err != nil {
 +		t.Fatal(err)
 +	}
 +}
 +
 +func TestList(t *testing.T) {
- 	d := NewDecoder(getReader("lists"))
++	d := NewDecoder(getReader(t, "lists"))
 +	var l List
 +	checkDecode(d, List{int32(32), "foo", true}, &l, t)
 +	checkDecode(d, List{}, &l, t)
 +}
 +
 +// TODO aconway 2015-09-08: the message.amqp file seems to be incorrectly coded as
 +// as an AMQP string *inside* an AMQP binary?? Skip the test for now.
 +func TODO_TestMessage(t *testing.T) {
- 	bytes, err := ioutil.ReadAll(getReader("message"))
++	bytes, err := ioutil.ReadAll(getReader(t, "message"))
 +	if err != nil {
 +		t.Fatal(err)
 +	}
 +
 +	m, err := DecodeMessage(bytes)
 +	if err != nil {
 +		t.Fatal(err)
 +	} else {
 +		if err := checkEqual(m.Body(), "hello"); err != nil {
 +			t.Error(err)
 +		}
 +	}
 +
 +	m2 := NewMessageWith("hello")
 +	bytes2, err := m2.Encode(nil)
 +	if err != nil {
 +		t.Error(err)
 +	} else {
 +		if err = checkEqual(bytes, bytes2); err != nil {
 +			t.Error(err)
 +		}
 +	}
 +}
 +
 +// TODO aconway 2015-03-13: finish the full interop test

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/marshal.go
----------------------------------------------------------------------
diff --cc amqp/marshal.go
index 66e14d8,0000000..3b4a59e
mode 100644,000000..100644
--- a/amqp/marshal.go
+++ b/amqp/marshal.go
@@@ -1,250 -1,0 +1,250 @@@
 +/*
 +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 amqp
 +
 +//#include "codec_shim.h"
 +import "C"
 +
 +import (
 +	"fmt"
 +	"io"
 +	"reflect"
 +	"unsafe"
 +)
 +
 +func dataError(prefix string, data *C.pn_data_t) error {
 +	err := PnError(C.pn_data_error(data))
 +	if err != nil {
 +		err = fmt.Errorf("%s: %s", prefix, err.Error())
 +	}
 +	return err
 +}
 +
 +/*
 +Marshal encodes a Go value as AMQP data in buffer.
 +If buffer is nil, or is not large enough, a new buffer  is created.
 +
 +Returns the buffer used for encoding with len() adjusted to the actual size of data.
 +
 +Go types are encoded as follows
 +
 + +-------------------------------------+--------------------------------------------+
 + |Go type                              |AMQP type                                   |
 + +-------------------------------------+--------------------------------------------+
 + |bool                                 |bool                                        |
 + +-------------------------------------+--------------------------------------------+
 + |int8, int16, int32, int64 (int)      |byte, short, int, long (int or long)        |
 + +-------------------------------------+--------------------------------------------+
 + |uint8, uint16, uint32, uint64 (uint) |ubyte, ushort, uint, ulong (uint or ulong)  |
 + +-------------------------------------+--------------------------------------------+
 + |float32, float64                     |float, double.                              |
 + +-------------------------------------+--------------------------------------------+
 + |string                               |string                                      |
 + +-------------------------------------+--------------------------------------------+
 + |[]byte, Binary                       |binary                                      |
 + +-------------------------------------+--------------------------------------------+
 + |Symbol                               |symbol                                      |
 + +-------------------------------------+--------------------------------------------+
 + |interface{}                          |the contained type                          |
 + +-------------------------------------+--------------------------------------------+
 + |nil                                  |null                                        |
 + +-------------------------------------+--------------------------------------------+
 + |map[K]T                              |map with K and T converted as above         |
 + +-------------------------------------+--------------------------------------------+
 + |Map                                  |map, may have mixed types for keys, values  |
 + +-------------------------------------+--------------------------------------------+
 + |[]T                                  |list with T converted as above              |
 + +-------------------------------------+--------------------------------------------+
 + |List                                 |list, may have mixed types  values          |
 + +-------------------------------------+--------------------------------------------+
 +
 +The following Go types cannot be marshaled: uintptr, function, interface, channel
 +
 +TODO
 +
 +Go types: array, slice, struct, complex64/128.
 +
 +AMQP types: decimal32/64/128, char, timestamp, uuid, array, multi-section message bodies.
 +
 +Described types.
 +
 +*/
 +func Marshal(v interface{}, buffer []byte) (outbuf []byte, err error) {
 +	defer doRecover(&err)
 +	data := C.pn_data(0)
 +	defer C.pn_data_free(data)
 +	marshal(v, data)
 +	encode := func(buf []byte) ([]byte, error) {
 +		n := int(C.pn_data_encode(data, cPtr(buf), cLen(buf)))
 +		switch {
 +		case n == int(C.PN_OVERFLOW):
 +			return buf, overflow
 +		case n < 0:
 +			return buf, dataError("marshal error", data)
 +		default:
 +			return buf[:n], nil
 +		}
 +	}
 +	return encodeGrow(buffer, encode)
 +}
 +
 +const minEncode = 256
 +
 +// overflow is returned when an encoding function can't fit data in the buffer.
 +var overflow = fmt.Errorf("buffer too small")
 +
 +// encodeFn encodes into buffer[0:len(buffer)].
 +// Returns buffer with length adjusted for data encoded.
 +// If buffer too small, returns overflow as error.
 +type encodeFn func(buffer []byte) ([]byte, error)
 +
 +// encodeGrow calls encode() into buffer, if it returns overflow grows the buffer.
 +// Returns the final buffer.
 +func encodeGrow(buffer []byte, encode encodeFn) ([]byte, error) {
 +	if buffer == nil || len(buffer) == 0 {
 +		buffer = make([]byte, minEncode)
 +	}
 +	var err error
 +	for buffer, err = encode(buffer); err == overflow; buffer, err = encode(buffer) {
 +		buffer = make([]byte, 2*len(buffer))
 +	}
 +	return buffer, err
 +}
 +
 +func marshal(v interface{}, data *C.pn_data_t) {
 +	switch v := v.(type) {
 +	case nil:
 +		C.pn_data_put_null(data)
 +	case bool:
 +		C.pn_data_put_bool(data, C.bool(v))
 +	case int8:
 +		C.pn_data_put_byte(data, C.int8_t(v))
 +	case int16:
 +		C.pn_data_put_short(data, C.int16_t(v))
 +	case int32:
 +		C.pn_data_put_int(data, C.int32_t(v))
 +	case int64:
 +		C.pn_data_put_long(data, C.int64_t(v))
 +	case int:
 +		if unsafe.Sizeof(0) == 8 {
 +			C.pn_data_put_long(data, C.int64_t(v))
 +		} else {
 +			C.pn_data_put_int(data, C.int32_t(v))
 +		}
 +	case uint8:
 +		C.pn_data_put_ubyte(data, C.uint8_t(v))
 +	case uint16:
 +		C.pn_data_put_ushort(data, C.uint16_t(v))
 +	case uint32:
 +		C.pn_data_put_uint(data, C.uint32_t(v))
 +	case uint64:
 +		C.pn_data_put_ulong(data, C.uint64_t(v))
 +	case uint:
 +		if unsafe.Sizeof(0) == 8 {
 +			C.pn_data_put_ulong(data, C.uint64_t(v))
 +		} else {
 +			C.pn_data_put_uint(data, C.uint32_t(v))
 +		}
 +	case float32:
 +		C.pn_data_put_float(data, C.float(v))
 +	case float64:
 +		C.pn_data_put_double(data, C.double(v))
 +	case string:
 +		C.pn_data_put_string(data, pnBytes([]byte(v)))
 +	case []byte:
 +		C.pn_data_put_binary(data, pnBytes(v))
 +	case Binary:
 +		C.pn_data_put_binary(data, pnBytes([]byte(v)))
 +	case Symbol:
 +		C.pn_data_put_symbol(data, pnBytes([]byte(v)))
 +	case Map: // Special map type
 +		C.pn_data_put_map(data)
 +		C.pn_data_enter(data)
 +		for key, val := range v {
 +			marshal(key, data)
 +			marshal(val, data)
 +		}
 +		C.pn_data_exit(data)
 +	default:
 +		switch reflect.TypeOf(v).Kind() {
 +		case reflect.Map:
 +			putMap(data, v)
 +		case reflect.Slice:
 +			putList(data, v)
 +		default:
 +			panic(fmt.Errorf("cannot marshal %s to AMQP", reflect.TypeOf(v)))
 +		}
 +	}
 +	err := dataError("marshal", data)
 +	if err != nil {
 +		panic(err)
 +	}
 +	return
 +}
 +
 +func clearMarshal(v interface{}, data *C.pn_data_t) {
 +	C.pn_data_clear(data)
 +	marshal(v, data)
 +}
 +
 +func putMap(data *C.pn_data_t, v interface{}) {
 +	mapValue := reflect.ValueOf(v)
 +	C.pn_data_put_map(data)
 +	C.pn_data_enter(data)
 +	for _, key := range mapValue.MapKeys() {
 +		marshal(key.Interface(), data)
 +		marshal(mapValue.MapIndex(key).Interface(), data)
 +	}
 +	C.pn_data_exit(data)
 +}
 +
 +func putList(data *C.pn_data_t, v interface{}) {
 +	listValue := reflect.ValueOf(v)
 +	C.pn_data_put_list(data)
 +	C.pn_data_enter(data)
 +	for i := 0; i < listValue.Len(); i++ {
 +		marshal(listValue.Index(i).Interface(), data)
 +	}
 +	C.pn_data_exit(data)
 +}
 +
 +// Encoder encodes AMQP values to an io.Writer
 +type Encoder struct {
 +	writer io.Writer
 +	buffer []byte
 +}
 +
 +// New encoder returns a new encoder that writes to w.
 +func NewEncoder(w io.Writer) *Encoder {
 +	return &Encoder{w, make([]byte, minEncode)}
 +}
 +
 +func (e *Encoder) Encode(v interface{}) (err error) {
 +	e.buffer, err = Marshal(v, e.buffer)
 +	if err == nil {
- 		e.writer.Write(e.buffer)
++		_, err = e.writer.Write(e.buffer)
 +	}
 +	return err
 +}
 +
 +func replace(data *C.pn_data_t, v interface{}) {
 +	C.pn_data_clear(data)
 +	marshal(v, data)
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/message.go
----------------------------------------------------------------------
diff --cc amqp/message.go
index 1d1287f,0000000..48a209a
mode 100644,000000..100644
--- a/amqp/message.go
+++ b/amqp/message.go
@@@ -1,346 -1,0 +1,348 @@@
 +/*
 +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 amqp
 +
 +// #include "codec_shim.h"
 +// #include <proton/types.h>
 +// #include <proton/message.h>
 +// #include <stdlib.h>
 +//
 +// /* Helper for setting message string fields */
 +// typedef int (*set_fn)(pn_message_t*, const char*);
 +// int msg_set_str(pn_message_t* m, char* s, set_fn set) {
 +//     int result = set(m, s);
 +//     free(s);
 +//     return result;
 +// }
 +//
 +import "C"
 +
 +import (
 +	"fmt"
 +	"runtime"
 +	"time"
 +	"unsafe"
 +)
 +
 +// Message is the interface to an AMQP message.
 +type Message interface {
 +	// Durable indicates that any parties taking responsibility
 +	// for the message must durably store the content.
 +	Durable() bool
 +	SetDurable(bool)
 +
 +	// Priority impacts ordering guarantees. Within a
 +	// given ordered context, higher priority messages may jump ahead of
 +	// lower priority messages.
 +	Priority() uint8
 +	SetPriority(uint8)
 +
 +	// TTL or Time To Live, a message it may be dropped after this duration
 +	TTL() time.Duration
 +	SetTTL(time.Duration)
 +
 +	// FirstAcquirer indicates
 +	// that the recipient of the message is the first recipient to acquire
 +	// the message, i.e. there have been no failed delivery attempts to
 +	// other acquirers. Note that this does not mean the message has not
 +	// been delivered to, but not acquired, by other recipients.
 +	FirstAcquirer() bool
 +	SetFirstAcquirer(bool)
 +
 +	// DeliveryCount tracks how many attempts have been made to
 +	// delivery a message.
 +	DeliveryCount() uint32
 +	SetDeliveryCount(uint32)
 +
 +	// MessageId provides a unique identifier for a message.
 +	// it can be an a string, an unsigned long, a uuid or a
 +	// binary value.
 +	MessageId() interface{}
 +	SetMessageId(interface{})
 +
 +	UserId() string
 +	SetUserId(string)
 +
 +	Address() string
 +	SetAddress(string)
 +
 +	Subject() string
 +	SetSubject(string)
 +
 +	ReplyTo() string
 +	SetReplyTo(string)
 +
 +	// CorrelationId is set on correlated request and response messages. It can be
 +	// an a string, an unsigned long, a uuid or a binary value.
 +	CorrelationId() interface{}
 +	SetCorrelationId(interface{})
 +
 +	ContentType() string
 +	SetContentType(string)
 +
 +	ContentEncoding() string
 +	SetContentEncoding(string)
 +
 +	// ExpiryTime indicates an absoulte time when the message may be dropped.
 +	// A Zero time (i.e. t.isZero() == true) indicates a message never expires.
 +	ExpiryTime() time.Time
 +	SetExpiryTime(time.Time)
 +
 +	CreationTime() time.Time
 +	SetCreationTime(time.Time)
 +
 +	GroupId() string
 +	SetGroupId(string)
 +
 +	GroupSequence() int32
 +	SetGroupSequence(int32)
 +
 +	ReplyToGroupId() string
 +	SetReplyToGroupId(string)
 +
 +	// Instructions - AMQP delivery instructions.
 +	Instructions() map[string]interface{}
 +	SetInstructions(v map[string]interface{})
 +
 +	// Annotations - AMQP annotations.
 +	Annotations() map[string]interface{}
 +	SetAnnotations(v map[string]interface{})
 +
 +	// Properties - Application properties.
 +	Properties() map[string]interface{}
 +	SetProperties(v map[string]interface{})
 +
 +	// Inferred 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.
 +	Inferred() bool
 +	SetInferred(bool)
 +
 +	// Marshal a Go value into the message body. See amqp.Marshal() for details.
 +	Marshal(interface{})
 +
 +	// Unmarshal the message body into the value pointed to by v. See amqp.Unmarshal() for details.
 +	Unmarshal(interface{})
 +
 +	// Body value resulting from the default unmarshalling of message body as interface{}
 +	Body() interface{}
 +
 +	// Encode encodes the message as AMQP data. If buffer is non-nil and is large enough
 +	// the message is encoded into it, otherwise a new buffer is created.
 +	// Returns the buffer containing the message.
 +	Encode(buffer []byte) ([]byte, error)
 +
 +	// Decode data into this message. Overwrites an existing message content.
 +	Decode(buffer []byte) error
 +
 +	// Clear the message contents.
 +	Clear()
 +
 +	// Copy the contents of another message to this one.
 +	Copy(m Message) error
 +}
 +
 +type message struct{ pn *C.pn_message_t }
 +
 +func freeMessage(m *message) {
 +	C.pn_message_free(m.pn)
 +	m.pn = nil
 +}
 +
 +// NewMessage creates a new message instance.
 +func NewMessage() Message {
 +	m := &message{C.pn_message()}
 +	runtime.SetFinalizer(m, freeMessage)
 +	return m
 +}
 +
 +// NewMessageWith creates a message with value as the body. Equivalent to
 +//     m := NewMessage(); m.Marshal(body)
 +func NewMessageWith(value interface{}) Message {
 +	m := NewMessage()
 +	m.Marshal(value)
 +	return m
 +}
 +
 +func (m *message) Clear() { C.pn_message_clear(m.pn) }
 +
 +func (m *message) Copy(x Message) error {
 +	if data, err := x.Encode(nil); err == nil {
 +		return m.Decode(data)
 +	} else {
 +		return err
 +	}
 +}
 +
 +// ==== message get functions
 +
 +func rewindGet(data *C.pn_data_t) (v interface{}) {
 +	C.pn_data_rewind(data)
 +	C.pn_data_next(data)
 +	unmarshal(&v, data)
 +	return v
 +}
 +
 +func rewindMap(data *C.pn_data_t) (v map[string]interface{}) {
 +	C.pn_data_rewind(data)
 +	C.pn_data_next(data)
 +	unmarshal(&v, data)
 +	return v
 +}
 +
 +func (m *message) Inferred() bool  { return bool(C.pn_message_is_inferred(m.pn)) }
 +func (m *message) Durable() bool   { return bool(C.pn_message_is_durable(m.pn)) }
 +func (m *message) Priority() uint8 { return uint8(C.pn_message_get_priority(m.pn)) }
 +func (m *message) TTL() time.Duration {
 +	return time.Duration(C.pn_message_get_ttl(m.pn)) * time.Millisecond
 +}
 +func (m *message) FirstAcquirer() bool        { return bool(C.pn_message_is_first_acquirer(m.pn)) }
 +func (m *message) DeliveryCount() uint32      { return uint32(C.pn_message_get_delivery_count(m.pn)) }
 +func (m *message) MessageId() interface{}     { return rewindGet(C.pn_message_id(m.pn)) }
 +func (m *message) UserId() string             { return goString(C.pn_message_get_user_id(m.pn)) }
 +func (m *message) Address() string            { return C.GoString(C.pn_message_get_address(m.pn)) }
 +func (m *message) Subject() string            { return C.GoString(C.pn_message_get_subject(m.pn)) }
 +func (m *message) ReplyTo() string            { return C.GoString(C.pn_message_get_reply_to(m.pn)) }
 +func (m *message) CorrelationId() interface{} { return rewindGet(C.pn_message_correlation_id(m.pn)) }
 +func (m *message) ContentType() string        { return C.GoString(C.pn_message_get_content_type(m.pn)) }
 +func (m *message) ContentEncoding() string    { return C.GoString(C.pn_message_get_content_encoding(m.pn)) }
 +
 +func (m *message) ExpiryTime() time.Time {
 +	return time.Unix(0, int64(time.Millisecond*time.Duration(C.pn_message_get_expiry_time(m.pn))))
 +}
 +func (m *message) CreationTime() time.Time {
 +	return time.Unix(0, int64(time.Millisecond)*int64(C.pn_message_get_creation_time(m.pn)))
 +}
 +func (m *message) GroupId() string        { return C.GoString(C.pn_message_get_group_id(m.pn)) }
 +func (m *message) GroupSequence() int32   { return int32(C.pn_message_get_group_sequence(m.pn)) }
 +func (m *message) ReplyToGroupId() string { return C.GoString(C.pn_message_get_reply_to_group_id(m.pn)) }
 +
 +func (m *message) Instructions() map[string]interface{} {
 +	return rewindMap(C.pn_message_instructions(m.pn))
 +}
 +func (m *message) Annotations() map[string]interface{} {
 +	return rewindMap(C.pn_message_annotations(m.pn))
 +}
 +func (m *message) Properties() map[string]interface{} {
 +	return rewindMap(C.pn_message_properties(m.pn))
 +}
 +
 +// ==== message set methods
 +
 +func setData(v interface{}, data *C.pn_data_t) {
 +	C.pn_data_clear(data)
 +	marshal(v, data)
 +}
 +
 +func dataString(data *C.pn_data_t) string {
 +	str := C.pn_string(C.CString(""))
 +	defer C.pn_free(unsafe.Pointer(str))
 +	C.pn_inspect(unsafe.Pointer(data), str)
 +	return C.GoString(C.pn_string_get(str))
 +}
 +
- func (m *message) SetInferred(b bool)  { C.pn_message_set_inferred(m.pn, C.bool(m.Inferred())) }
++func (m *message) SetInferred(b bool)  { C.pn_message_set_inferred(m.pn, C.bool(b)) }
 +func (m *message) SetDurable(b bool)   { C.pn_message_set_durable(m.pn, C.bool(b)) }
 +func (m *message) SetPriority(b uint8) { C.pn_message_set_priority(m.pn, C.uint8_t(b)) }
 +func (m *message) SetTTL(d time.Duration) {
 +	C.pn_message_set_ttl(m.pn, C.pn_millis_t(d/time.Millisecond))
 +}
 +func (m *message) SetFirstAcquirer(b bool)     { C.pn_message_set_first_acquirer(m.pn, C.bool(b)) }
 +func (m *message) SetDeliveryCount(c uint32)   { C.pn_message_set_delivery_count(m.pn, C.uint32_t(c)) }
 +func (m *message) SetMessageId(id interface{}) { setData(id, C.pn_message_id(m.pn)) }
 +func (m *message) SetUserId(s string)          { C.pn_message_set_user_id(m.pn, pnBytes(([]byte)(s))) }
 +func (m *message) SetAddress(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_address))
 +}
 +func (m *message) SetSubject(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_subject))
 +}
 +func (m *message) SetReplyTo(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_reply_to))
 +}
 +func (m *message) SetCorrelationId(c interface{}) { setData(c, C.pn_message_correlation_id(m.pn)) }
 +func (m *message) SetContentType(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_content_type))
 +}
 +func (m *message) SetContentEncoding(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_content_encoding))
 +}
 +func (m *message) SetExpiryTime(t time.Time)   { C.pn_message_set_expiry_time(m.pn, pnTime(t)) }
 +func (m *message) SetCreationTime(t time.Time) { C.pn_message_set_creation_time(m.pn, pnTime(t)) }
 +func (m *message) SetGroupId(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_group_id))
 +}
 +func (m *message) SetGroupSequence(s int32) {
 +	C.pn_message_set_group_sequence(m.pn, C.pn_sequence_t(s))
 +}
 +func (m *message) SetReplyToGroupId(s string) {
 +	C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_reply_to_group_id))
 +}
 +
 +func (m *message) SetInstructions(v map[string]interface{}) {
 +	setData(v, C.pn_message_instructions(m.pn))
 +}
 +func (m *message) SetAnnotations(v map[string]interface{}) { setData(v, C.pn_message_annotations(m.pn)) }
 +func (m *message) SetProperties(v map[string]interface{})  { setData(v, C.pn_message_properties(m.pn)) }
 +
 +// Marshal/Unmarshal body
 +func (m *message) Marshal(v interface{})   { clearMarshal(v, C.pn_message_body(m.pn)) }
 +func (m *message) Unmarshal(v interface{}) { rewindUnmarshal(v, C.pn_message_body(m.pn)) }
 +func (m *message) Body() (v interface{})   { m.Unmarshal(&v); return }
 +
 +func (m *message) Decode(data []byte) error {
 +	m.Clear()
 +	if len(data) == 0 {
 +		return fmt.Errorf("empty buffer for decode")
 +	}
 +	if C.pn_message_decode(m.pn, cPtr(data), cLen(data)) < 0 {
 +		return fmt.Errorf("decoding message: %s", PnError(C.pn_message_error(m.pn)))
 +	}
 +	return nil
 +}
 +
 +func DecodeMessage(data []byte) (m Message, err error) {
 +	m = NewMessage()
 +	err = m.Decode(data)
 +	return
 +}
 +
 +func (m *message) Encode(buffer []byte) ([]byte, error) {
 +	encode := func(buf []byte) ([]byte, error) {
 +		len := cLen(buf)
 +		result := C.pn_message_encode(m.pn, cPtr(buf), &len)
 +		switch {
 +		case result == C.PN_OVERFLOW:
 +			return buf, overflow
 +		case result < 0:
 +			return buf, fmt.Errorf("cannot encode message: %s", PnErrorCode(result))
 +		default:
 +			return buf[:len], nil
 +		}
 +	}
 +	return encodeGrow(buffer, encode)
 +}
 +
 +// TODO aconway 2015-09-14: Multi-section messages.
++
++// TODO aconway 2016-09-09: Message.String() use inspect.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/url.go
----------------------------------------------------------------------
diff --cc amqp/url.go
index 70545d2,0000000..fd6c8dc
mode 100644,000000..100644
--- a/amqp/url.go
+++ b/amqp/url.go
@@@ -1,96 -1,0 +1,104 @@@
 +/*
 +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 amqp
 +
- /*
- #include <stdlib.h>
- #include <string.h>
- #include <proton/url.h>
- 
- // Helper function for setting URL fields.
- typedef void (*setter_fn)(pn_url_t* url, const char* value);
- inline void	set(pn_url_t *url, setter_fn s, const char* value) {
-   s(url, value);
- }
- */
- import "C"
- 
 +import (
- 	"fmt"
++	"errors"
 +	"net"
 +	"net/url"
- 	"unsafe"
++	"strings"
 +)
 +
 +const (
 +	amqp  string = "amqp"
 +	amqps        = "amqps"
++	defaulthost  = "localhost"
 +)
 +
- // ParseUrl parses an AMQP URL string and returns a net/url.Url.
- //
- // It is more forgiving than net/url.Parse and allows most of the parts of the
- // URL to be missing, assuming AMQP defaults.
- //
- func ParseURL(s string) (u *url.URL, err error) {
- 	cstr := C.CString(s)
- 	defer C.free(unsafe.Pointer(cstr))
- 	pnUrl := C.pn_url_parse(cstr)
- 	if pnUrl == nil {
- 		return nil, fmt.Errorf("bad URL %#v", s)
++// The way this is used it can only get a hostport already validated by
++// the URL parser, so this means we can skip some error checks
++func splitHostPort(hostport string) (string, string, error) {
++	if hostport == "" {
++		return "", "", nil
 +	}
- 	defer C.pn_url_free(pnUrl)
- 
- 	scheme := C.GoString(C.pn_url_get_scheme(pnUrl))
- 	username := C.GoString(C.pn_url_get_username(pnUrl))
- 	password := C.GoString(C.pn_url_get_password(pnUrl))
- 	host := C.GoString(C.pn_url_get_host(pnUrl))
- 	port := C.GoString(C.pn_url_get_port(pnUrl))
- 	path := C.GoString(C.pn_url_get_path(pnUrl))
++	if hostport[0] == '[' {
++		// There must be a matching ']' as already validated
++		if l := strings.LastIndex(hostport, "]"); len(hostport) == l+1 {
++			// trim off '[' and ']'
++			return hostport[1:l], "", nil
++		}
++	} else if strings.IndexByte(hostport, ':') < 0 {
++		return hostport, "", nil
++	}
++	return net.SplitHostPort(hostport)
++}
 +
++func UpdateURL(in *url.URL) (err error) {
++	// Detect form without "amqp://" and stick it on front
++	// to make it match the usual proton defaults
++	u := new (url.URL)
++	*u = *in
++	if (u.Scheme != "" && u.Opaque != "") ||
++	   (u.Scheme == "" && u.Host == "") {
++		input := u.String()
++		input = "amqp://" + input
++		u, err = url.Parse(input)
++		if err != nil {
++			return
++		}
++	}
++	// If Scheme is still "" then default to amqp
++	if u.Scheme == "" {
++		u.Scheme = amqp
++	}
++	// Error if the scheme is not an amqp scheme
++	if u.Scheme != amqp && u.Scheme != amqps {
++		return errors.New("invalid amqp scheme")
++	}
++	// Decompose Host into host and port
++	host, port, err := splitHostPort(u.Host)
 +	if err != nil {
- 		return nil, fmt.Errorf("bad URL %#v: %s", s, err)
++		return
 +	}
- 	if scheme == "" {
- 		scheme = amqp
++	if host == "" {
++		host = defaulthost
 +	}
 +	if port == "" {
- 		if scheme == amqps {
- 			port = amqps
- 		} else {
- 			port = amqp
- 		}
- 	}
- 	var user *url.Userinfo
- 	if password != "" {
- 		user = url.UserPassword(username, password)
- 	} else if username != "" {
- 		user = url.User(username)
++		port = u.Scheme
 +	}
++	u.Host = net.JoinHostPort(host, port)
++	*in = *u
++	return nil
++}
 +
- 	u = &url.URL{
- 		Scheme: scheme,
- 		User:   user,
- 		Host:   net.JoinHostPort(host, port),
- 		Path:   path,
++// ParseUrl parses an AMQP URL string and returns a net/url.Url.
++//
++// It is more forgiving than net/url.Parse and allows most of the parts of the
++// URL to be missing, assuming AMQP defaults.
++//
++func ParseURL(s string) (u *url.URL, err error) {
++	if u, err = url.Parse(s); err != nil {
++		return
 +	}
- 
- 	return u, nil
++	if err = UpdateURL(u); err != nil {
++		u = nil
++	}
++	return u, err
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/url_test.go
----------------------------------------------------------------------
diff --cc amqp/url_test.go
index 99b656d,0000000..f52d4bf
mode 100644,000000..100644
--- a/amqp/url_test.go
+++ b/amqp/url_test.go
@@@ -1,51 -1,0 +1,59 @@@
 +/*
 +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 amqp
 +
 +import (
 +	"fmt"
 +)
 +
 +func ExampleParseURL() {
 +	for _, s := range []string{
 +		"amqp://username:password@host:1234/path",
 +		"host:1234",
 +		"host",
- 		":1234",
 +		"host/path",
 +		"amqps://host",
++		"/path",
 +		"",
++		":1234",
++                // Taken out becasue the go 1.4 URL parser isn't the same as later
++		//"[::1]",
++		//"[::1",
++		// Output would be:
++		// amqp://[::1]:amqp
++		// parse amqp://[::1: missing ']' in host
 +	} {
 +		u, err := ParseURL(s)
 +		if err != nil {
 +			fmt.Println(err)
 +		} else {
 +			fmt.Println(u)
 +		}
 +	}
 +	// Output:
 +	// amqp://username:password@host:1234/path
 +	// amqp://host:1234
 +	// amqp://host:amqp
- 	// amqp://:1234
 +	// amqp://host:amqp/path
 +	// amqps://host:amqps
- 	// bad URL ""
++	// amqp://localhost:amqp/path
++	// amqp://localhost:amqp
++	// parse :1234: missing protocol scheme
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/amqp/version.go
----------------------------------------------------------------------
diff --cc amqp/version.go
index 0000000,0000000..cefa904
new file mode 100644
--- /dev/null
+++ b/amqp/version.go
@@@ -1,0 -1,0 +1,29 @@@
++/*
++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 amqp
++
++// Version check for proton library.
++// Done here because this is the lowest-level dependency for all the proton Go packages.
++
++// #include <proton/version.h>
++// #if PN_VERSION_MINOR < 10
++// #error packages qpid.apache.org/... require Proton-C library version 0.10 or greater
++// #endif
++import "C"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/auth_test.go
----------------------------------------------------------------------
diff --cc electron/auth_test.go
index 0000000,0000000..73a9299
new file mode 100644
--- /dev/null
+++ b/electron/auth_test.go
@@@ -1,0 -1,0 +1,124 @@@
++/*
++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 electron
++
++import (
++	"fmt"
++	"io/ioutil"
++	"os"
++	"os/exec"
++	"path/filepath"
++	"strings"
++	"testing"
++)
++
++func testAuthClientServer(t *testing.T, copts []ConnectionOption, sopts []ConnectionOption) (got connectionSettings, err error) {
++	client, server := newClientServerOpts(t, copts, sopts)
++	defer closeClientServer(client, server)
++
++	go func() {
++		for in := range server.Incoming() {
++			switch in := in.(type) {
++			case *IncomingConnection:
++				got = connectionSettings{user: in.User(), virtualHost: in.VirtualHost()}
++			}
++			in.Accept()
++		}
++	}()
++
++	err = client.Sync()
++	return
++}
++
++func TestAuthAnonymous(t *testing.T) {
++	fatalIf(t, configureSASL())
++	got, err := testAuthClientServer(t,
++		[]ConnectionOption{User("fred"), VirtualHost("vhost"), SASLAllowInsecure(true)},
++		[]ConnectionOption{SASLAllowedMechs("ANONYMOUS"), SASLAllowInsecure(true)})
++	fatalIf(t, err)
++	errorIf(t, checkEqual(connectionSettings{user: "anonymous", virtualHost: "vhost"}, got))
++}
++
++func TestAuthPlain(t *testing.T) {
++	fatalIf(t, configureSASL())
++	got, err := testAuthClientServer(t,
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("xxx"))},
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
++	fatalIf(t, err)
++	errorIf(t, checkEqual(connectionSettings{user: "fred@proton"}, got))
++}
++
++func TestAuthBadPass(t *testing.T) {
++	fatalIf(t, configureSASL())
++	_, err := testAuthClientServer(t,
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("yyy"))},
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
++	if err == nil {
++		t.Error("Expected auth failure for bad pass")
++	}
++}
++
++func TestAuthBadUser(t *testing.T) {
++	fatalIf(t, configureSASL())
++	_, err := testAuthClientServer(t,
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("foo@bar"), Password([]byte("yyy"))},
++		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
++	if err == nil {
++		t.Error("Expected auth failure for bad user")
++	}
++}
++
++var confDir string
++var confErr error
++
++func configureSASL() error {
++	if confDir != "" || confErr != nil {
++		return confErr
++	}
++	confDir, confErr = ioutil.TempDir("", "")
++	if confErr != nil {
++		return confErr
++	}
++
++	GlobalSASLConfigDir(confDir)
++	GlobalSASLConfigName("test")
++	conf := filepath.Join(confDir, "test.conf")
++
++	db := filepath.Join(confDir, "proton.sasldb")
++	cmd := exec.Command("saslpasswd2", "-c", "-p", "-f", db, "-u", "proton", "fred")
++	cmd.Stdin = strings.NewReader("xxx") // Password
++	if out, err := cmd.CombinedOutput(); err != nil {
++		confErr = fmt.Errorf("saslpasswd2 failed: %s\n%s", err, out)
++		return confErr
++	}
++	confStr := "sasldb_path: " + db + "\nmech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS\n"
++	if err := ioutil.WriteFile(conf, []byte(confStr), os.ModePerm); err != nil {
++		confErr = fmt.Errorf("write conf file %s failed: %s", conf, err)
++	}
++	return confErr
++}
++
++func TestMain(m *testing.M) {
++	status := m.Run()
++	if confDir != "" {
++		_ = os.RemoveAll(confDir)
++	}
++	os.Exit(status)
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/connection.go
----------------------------------------------------------------------
diff --cc electron/connection.go
index 1f8bd40,0000000..7f3050f
mode 100644,000000..100644
--- a/electron/connection.go
+++ b/electron/connection.go
@@@ -1,246 -1,0 +1,405 @@@
 +/*
 +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 electron
 +
 +// #include <proton/disposition.h>
 +import "C"
 +
 +import (
- 	"fmt"
 +	"net"
 +	"qpid.apache.org/proton"
 +	"sync"
 +	"time"
 +)
 +
++// Settings associated with a Connection.
++type ConnectionSettings interface {
++	// Authenticated user name associated with the connection.
++	User() string
++
++	// The AMQP virtual host name for the connection.
++	//
++	// Optional, useful when the server has multiple names and provides different
++	// service based on the name the client uses to connect.
++	//
++	// By default it is set to the DNS host name that the client uses to connect,
++	// but it can be set to something different at the client side with the
++	// VirtualHost() option.
++	//
++	// Returns error if the connection fails to authenticate.
++	VirtualHost() string
++
++	// Heartbeat is the maximum delay between sending frames that the remote peer
++	// has requested of us. If the interval expires an empty "heartbeat" frame
++	// will be sent automatically to keep the connection open.
++	Heartbeat() time.Duration
++}
++
 +// Connection is an AMQP connection, created by a Container.
 +type Connection interface {
 +	Endpoint
++	ConnectionSettings
 +
 +	// Sender opens a new sender on the DefaultSession.
 +	Sender(...LinkOption) (Sender, error)
 +
 +	// Receiver opens a new Receiver on the DefaultSession().
 +	Receiver(...LinkOption) (Receiver, error)
 +
 +	// DefaultSession() returns a default session for the connection. It is opened
 +	// on the first call to DefaultSession and returned on subsequent calls.
 +	DefaultSession() (Session, error)
 +
 +	// Session opens a new session.
 +	Session(...SessionOption) (Session, error)
 +
 +	// Container for the connection.
 +	Container() Container
 +
 +	// Disconnect the connection abruptly with an error.
 +	Disconnect(error)
 +
 +	// Wait waits for the connection to be disconnected.
 +	Wait() error
 +
 +	// WaitTimeout is like Wait but returns Timeout if the timeout expires.
 +	WaitTimeout(time.Duration) error
 +
- 	// Incoming returns a channel for incoming endpoints opened by the remote end.
- 	//
- 	// To enable, pass AllowIncoming() when creating the Connection. Otherwise all
- 	// incoming endpoint requests are automatically rejected and Incoming()
- 	// returns nil.
- 	//
- 	// An Incoming value can be an *IncomingSession, *IncomingSender or
- 	// *IncomingReceiver.  You must call Accept() to open the endpoint or Reject()
- 	// to close it with an error. The specific Incoming types have additional
- 	// methods to configure the endpoint.
- 	//
- 	// Not receiving from Incoming() or not calling Accept/Reject will block the
- 	// electron event loop. Normally you would have a dedicated goroutine receive
- 	// from Incoming() and start new goroutines to serve each incoming endpoint.
- 	// The channel is closed when the Connection closes.
++	// Incoming returns a channel for incoming endpoints opened by the remote peer.
++	// See the Incoming interface for more.
 +	//
++	// Not receiving from Incoming() and calling Accept/Reject will block the
++	// electron event loop. You should run a loop to handle the types that
++	// interest you in a switch{} and and Accept() all others.
 +	Incoming() <-chan Incoming
 +}
 +
++type connectionSettings struct {
++	user, virtualHost string
++	heartbeat         time.Duration
++}
++
++func (c connectionSettings) User() string             { return c.user }
++func (c connectionSettings) VirtualHost() string      { return c.virtualHost }
++func (c connectionSettings) Heartbeat() time.Duration { return c.heartbeat }
++
 +// ConnectionOption can be passed when creating a connection to configure various options
 +type ConnectionOption func(*connection)
 +
- // Server returns a ConnectionOption to put the connection in server mode.
++// User returns a ConnectionOption sets the user name for a connection
++func User(user string) ConnectionOption {
++	return func(c *connection) {
++		c.user = user
++		c.pConnection.SetUser(user)
++	}
++}
++
++// VirtualHost returns a ConnectionOption to set the AMQP virtual host for the connection.
++// Only applies to outbound client connection.
++func VirtualHost(virtualHost string) ConnectionOption {
++	return func(c *connection) {
++		c.virtualHost = virtualHost
++		c.pConnection.SetHostname(virtualHost)
++	}
++}
++
++// Password returns a ConnectionOption to set the password used to establish a
++// connection.  Only applies to outbound client connection.
++//
++// The connection will erase its copy of the password from memory as soon as it
++// has been used to authenticate. If you are concerned about paswords staying in
++// memory you should never store them as strings, and should overwrite your
++// copy as soon as you are done with it.
++//
++func Password(password []byte) ConnectionOption {
++	return func(c *connection) { c.pConnection.SetPassword(password) }
++}
++
++// Server returns a ConnectionOption to put the connection in server mode for incoming connections.
 +//
 +// A server connection will do protocol negotiation to accept a incoming AMQP
 +// connection. Normally you would call this for a connection created by
 +// net.Listener.Accept()
 +//
- func Server() ConnectionOption { return func(c *connection) { c.engine.Server() } }
++func Server() ConnectionOption {
++	return func(c *connection) { c.engine.Server(); c.server = true; AllowIncoming()(c) }
++}
 +
- // AllowIncoming returns a ConnectionOption to enable incoming endpoint open requests.
- // See Connection.Incoming()
++// AllowIncoming returns a ConnectionOption to enable incoming endpoints, see
++// Connection.Incoming() This is automatically set for Server() connections.
 +func AllowIncoming() ConnectionOption {
 +	return func(c *connection) { c.incoming = make(chan Incoming) }
 +}
 +
++// Parent returns a ConnectionOption that associates the Connection with it's Container
++// If not set a connection will create its own default container.
++func Parent(cont Container) ConnectionOption {
++	return func(c *connection) { c.container = cont.(*container) }
++}
++
 +type connection struct {
 +	endpoint
++	connectionSettings
++
 +	defaultSessionOnce, closeOnce sync.Once
 +
 +	container   *container
 +	conn        net.Conn
++	server      bool
 +	incoming    chan Incoming
 +	handler     *handler
 +	engine      *proton.Engine
- 	eConnection proton.Connection
++	pConnection proton.Connection
 +
 +	defaultSession Session
 +}
 +
- func newConnection(conn net.Conn, cont *container, setting ...ConnectionOption) (*connection, error) {
- 	c := &connection{container: cont, conn: conn}
++// NewConnection creates a connection with the given options.
++func NewConnection(conn net.Conn, opts ...ConnectionOption) (*connection, error) {
++	c := &connection{
++		conn: conn,
++	}
 +	c.handler = newHandler(c)
 +	var err error
 +	c.engine, err = proton.NewEngine(c.conn, c.handler.delegator)
 +	if err != nil {
 +		return nil, err
 +	}
- 	for _, set := range setting {
++	c.pConnection = c.engine.Connection()
++	for _, set := range opts {
 +		set(c)
 +	}
++	if c.container == nil {
++		c.container = NewContainer("").(*container)
++	}
++	c.pConnection.SetContainer(c.container.Id())
++	globalSASLInit(c.engine)
++
 +	c.endpoint.init(c.engine.String())
- 	c.eConnection = c.engine.Connection()
 +	go c.run()
 +	return c, nil
 +}
 +
 +func (c *connection) run() {
- 	c.engine.Run()
++	if !c.server {
++		c.pConnection.Open()
++	}
++	_ = c.engine.Run()
 +	if c.incoming != nil {
 +		close(c.incoming)
 +	}
- 	c.closed(Closed)
++	_ = c.closed(Closed)
 +}
 +
 +func (c *connection) Close(err error) {
 +	c.err.Set(err)
 +	c.engine.Close(err)
 +}
 +
 +func (c *connection) Disconnect(err error) {
 +	c.err.Set(err)
 +	c.engine.Disconnect(err)
 +}
 +
- func (c *connection) Session(setting ...SessionOption) (Session, error) {
++func (c *connection) Session(opts ...SessionOption) (Session, error) {
 +	var s Session
 +	err := c.engine.InjectWait(func() error {
 +		if c.Error() != nil {
 +			return c.Error()
 +		}
- 		eSession, err := c.engine.Connection().Session()
++		pSession, err := c.engine.Connection().Session()
 +		if err == nil {
- 			eSession.Open()
++			pSession.Open()
 +			if err == nil {
- 				s = newSession(c, eSession, setting...)
++				s = newSession(c, pSession, opts...)
 +			}
 +		}
 +		return err
 +	})
 +	return s, err
 +}
 +
 +func (c *connection) Container() Container { return c.container }
 +
 +func (c *connection) DefaultSession() (s Session, err error) {
 +	c.defaultSessionOnce.Do(func() {
 +		c.defaultSession, err = c.Session()
 +	})
 +	if err == nil {
 +		err = c.Error()
 +	}
 +	return c.defaultSession, err
 +}
 +
- func (c *connection) Sender(setting ...LinkOption) (Sender, error) {
++func (c *connection) Sender(opts ...LinkOption) (Sender, error) {
 +	if s, err := c.DefaultSession(); err == nil {
- 		return s.Sender(setting...)
++		return s.Sender(opts...)
 +	} else {
 +		return nil, err
 +	}
 +}
 +
- func (c *connection) Receiver(setting ...LinkOption) (Receiver, error) {
++func (c *connection) Receiver(opts ...LinkOption) (Receiver, error) {
 +	if s, err := c.DefaultSession(); err == nil {
- 		return s.Receiver(setting...)
++		return s.Receiver(opts...)
 +	} else {
 +		return nil, err
 +	}
 +}
 +
 +func (c *connection) Connection() Connection { return c }
 +
 +func (c *connection) Wait() error { return c.WaitTimeout(Forever) }
 +func (c *connection) WaitTimeout(timeout time.Duration) error {
 +	_, err := timedReceive(c.done, timeout)
 +	if err == Timeout {
 +		return Timeout
 +	}
 +	return c.Error()
 +}
 +
- func (c *connection) Incoming() <-chan Incoming { return c.incoming }
++func (c *connection) Incoming() <-chan Incoming {
++	assert(c.incoming != nil, "electron.Connection.Incoming() disabled for %s", c)
++	return c.incoming
++}
 +
- // Incoming is the interface for incoming requests to open an endpoint.
- // Implementing types are IncomingSession, IncomingSender and IncomingReceiver.
- type Incoming interface {
- 	// Accept and open the endpoint.
- 	Accept() Endpoint
++type IncomingConnection struct {
++	incoming
++	connectionSettings
++	c *connection
++}
 +
- 	// Reject the endpoint with an error
- 	Reject(error)
++func newIncomingConnection(c *connection) *IncomingConnection {
++	c.user = c.pConnection.Transport().User()
++	c.virtualHost = c.pConnection.RemoteHostname()
++	return &IncomingConnection{
++		incoming:           makeIncoming(c.pConnection),
++		connectionSettings: c.connectionSettings,
++		c:                  c}
++}
 +
- 	// wait for and call the accept function, call in proton goroutine.
- 	wait() error
- 	pEndpoint() proton.Endpoint
++// AcceptConnection is like Accept() but takes ConnectionOption s
++// For example you can set the Heartbeat() for the accepted connection.
++func (in *IncomingConnection) AcceptConnection(opts ...ConnectionOption) Connection {
++	return in.accept(func() Endpoint {
++		for _, opt := range opts {
++			opt(in.c)
++		}
++		in.c.pConnection.Open()
++		return in.c
++	}).(Connection)
 +}
 +
- type incoming struct {
- 	endpoint proton.Endpoint
- 	acceptCh chan func() error
++func (in *IncomingConnection) Accept() Endpoint {
++	return in.AcceptConnection()
 +}
 +
- func makeIncoming(e proton.Endpoint) incoming {
- 	return incoming{endpoint: e, acceptCh: make(chan func() error)}
++func sasl(c *connection) proton.SASL { return c.engine.Transport().SASL() }
++
++// SASLEnable returns a ConnectionOption that enables SASL authentication.
++// Only required if you don't set any other SASL options.
++func SASLEnable() ConnectionOption { return func(c *connection) { sasl(c) } }
++
++// SASLAllowedMechs returns a ConnectionOption to set the list of allowed SASL
++// mechanisms.
++//
++// Can be used on the client or the server to restrict the SASL for a connection.
++// mechs is a space-separated list of mechanism names.
++//
++func SASLAllowedMechs(mechs string) ConnectionOption {
++	return func(c *connection) { sasl(c).AllowedMechs(mechs) }
 +}
 +
- func (in *incoming) String() string   { return fmt.Sprintf("%s: %s", in.endpoint.Type(), in.endpoint) }
- func (in *incoming) Reject(err error) { in.acceptCh <- func() error { return err } }
++// SASLAllowInsecure returns a ConnectionOption that allows or disallows clear
++// text SASL authentication mechanisms
++//
++// By default the SASL layer is configured not to allow mechanisms that disclose
++// the clear text of the password over an unencrypted AMQP connection. This specifically
++// will disallow the use of the PLAIN mechanism without using SSL encryption.
++//
++// This default is to avoid disclosing password information accidentally over an
++// insecure network.
++//
++func SASLAllowInsecure(b bool) ConnectionOption {
++	return func(c *connection) { sasl(c).SetAllowInsecureMechs(b) }
++}
 +
- // Call in proton goroutine, wait for and call the accept function fr
- func (in *incoming) wait() error { return (<-in.acceptCh)() }
++// Heartbeat returns a ConnectionOption that requests the maximum delay
++// between sending frames for the remote peer. If we don't receive any frames
++// within 2*delay we will close the connection.
++//
++func Heartbeat(delay time.Duration) ConnectionOption {
++	// Proton-C divides the idle-timeout by 2 before sending, so compensate.
++	return func(c *connection) { c.engine.Transport().SetIdleTimeout(2 * delay) }
++}
 +
- func (in *incoming) pEndpoint() proton.Endpoint { return in.endpoint }
++// GlobalSASLConfigDir sets the SASL configuration directory for every
++// Connection created in this process. If not called, the default is determined
++// by your SASL installation.
++//
++// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
++//
++func GlobalSASLConfigDir(dir string) { globalSASLConfigDir = dir }
 +
- // Called in app goroutine to send an accept function to proton and return the resulting endpoint.
- func (in *incoming) accept(f func() Endpoint) Endpoint {
- 	done := make(chan Endpoint)
- 	in.acceptCh <- func() error {
- 		ep := f()
- 		done <- ep
- 		return nil
++// GlobalSASLConfigName sets the SASL configuration name for every Connection
++// created in this process. If not called the default is "proton-server".
++//
++// The complete configuration file name is
++//     <sasl-config-dir>/<sasl-config-name>.conf
++//
++// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
++//
++func GlobalSASLConfigName(dir string) { globalSASLConfigName = dir }
++
++var (
++	globalSASLConfigName string
++	globalSASLConfigDir  string
++)
++
++// TODO aconway 2016-09-15: Current pn_sasl C impl config is broken, so all we
++// can realistically offer is global configuration. Later if/when the pn_sasl C
++// impl is fixed we can offer per connection over-rides.
++func globalSASLInit(eng *proton.Engine) {
++	sasl := eng.Transport().SASL()
++	if globalSASLConfigName != "" {
++		sasl.ConfigName(globalSASLConfigName)
++	}
++	if globalSASLConfigDir != "" {
++		sasl.ConfigPath(globalSASLConfigDir)
++	}
++}
++
++// Dial is shorthand for using net.Dial() then NewConnection()
++func Dial(network, addr string, opts ...ConnectionOption) (c Connection, err error) {
++	conn, err := net.Dial(network, addr)
++	if err == nil {
++		c, err = NewConnection(conn, opts...)
++	}
++	return
++}
++
++// DialWithDialer is shorthand for using dialer.Dial() then NewConnection()
++func DialWithDialer(dialer *net.Dialer, network, addr string, opts ...ConnectionOption) (c Connection, err error) {
++	conn, err := dialer.Dial(network, addr)
++	if err == nil {
++		c, err = NewConnection(conn, opts...)
 +	}
- 	return <-done
++	return
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/container.go
----------------------------------------------------------------------
diff --cc electron/container.go
index b5ce6c0,0000000..efb24ff
mode 100644,000000..100644
--- a/electron/container.go
+++ b/electron/container.go
@@@ -1,77 -1,0 +1,104 @@@
 +/*
 +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 electron
 +
 +import (
 +	"net"
 +	"qpid.apache.org/proton"
 +	"strconv"
 +	"sync/atomic"
 +)
 +
- // Container is an AMQP container, it represents a single AMQP "application".It
- // provides functions to create new Connections to remote containers.
++// Container is an AMQP container, it represents a single AMQP "application"
++// which can have multiple client or server connections.
++//
++// Each Container in a distributed AMQP application must have a unique
++// container-id which is applied to its connections.
 +//
 +// Create with NewContainer()
 +//
 +type Container interface {
 +	// Id is a unique identifier for the container in your distributed application.
 +	Id() string
 +
- 	// Create a new AMQP Connection over the supplied net.Conn connection.
- 	//
- 	// You must call Connection.Open() on the returned Connection, after
- 	// setting any Connection properties you need to set. Note the net.Conn
- 	// can be an outgoing connection (e.g. made with net.Dial) or an incoming
- 	// connection (e.g. made with net.Listener.Accept())
- 	Connection(net.Conn, ...ConnectionOption) (Connection, error)
++	// Connection creates a connection associated with this container.
++	Connection(conn net.Conn, opts ...ConnectionOption) (Connection, error)
++
++	// Dial is shorthand for
++	//     conn, err := net.Dial(); c, err := Connection(conn, opts...)
++	Dial(network string, addr string, opts ...ConnectionOption) (Connection, error)
++
++	// Accept is shorthand for:
++	//     conn, err := l.Accept(); c, err := Connection(conn, append(opts, Server()...)
++	Accept(l net.Listener, opts ...ConnectionOption) (Connection, error)
++
++	// String returns Id()
++	String() string
 +}
 +
 +type container struct {
 +	id         string
 +	tagCounter uint64
 +}
 +
 +func (cont *container) nextTag() string {
 +	return strconv.FormatUint(atomic.AddUint64(&cont.tagCounter, 1), 32)
 +}
 +
 +// NewContainer creates a new container. The id must be unique in your
 +// distributed application, all connections created by the container
 +// will have this container-id.
 +//
 +// If id == "" a random UUID will be generated for the id.
 +func NewContainer(id string) Container {
 +	if id == "" {
 +		id = proton.UUID4().String()
 +	}
 +	cont := &container{id: id}
 +	return cont
 +}
 +
 +func (cont *container) Id() string { return cont.id }
 +
++func (cont *container) String() string { return cont.Id() }
++
 +func (cont *container) nextLinkName() string {
 +	return cont.id + "@" + cont.nextTag()
 +}
 +
- func (cont *container) Connection(conn net.Conn, setting ...ConnectionOption) (Connection, error) {
- 	return newConnection(conn, cont, setting...)
++func (cont *container) Connection(conn net.Conn, opts ...ConnectionOption) (Connection, error) {
++	return NewConnection(conn, append(opts, Parent(cont))...)
++}
++
++func (cont *container) Dial(network, address string, opts ...ConnectionOption) (c Connection, err error) {
++	conn, err := net.Dial(network, address)
++	if err == nil {
++		c, err = cont.Connection(conn, opts...)
++	}
++	return
++}
++
++func (cont *container) Accept(l net.Listener, opts ...ConnectionOption) (c Connection, err error) {
++	conn, err := l.Accept()
++	if err == nil {
++		c, err = cont.Connection(conn, append(opts, Server())...)
++	}
++	return
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/287eeaca/electron/doc.go
----------------------------------------------------------------------
diff --cc electron/doc.go
index 46bde37,0000000..436e5df
mode 100644,000000..100644
--- a/electron/doc.go
+++ b/electron/doc.go
@@@ -1,63 -1,0 +1,72 @@@
 +/*
 +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 electron is a procedural, concurrent-safe Go library for AMQP messaging.
 +You can write clients and servers using this library.
 +
- Start by creating a Container with NewContainer. A Container represents a client
- or server application that can contain many incoming or outgoing connections.
++Start by creating a Container with NewContainer. An AMQP Container represents a
++single AMQP "application" and can contain client and server connections.
 +
- Create connections with the standard Go 'net' package using net.Dial or
- net.Listen. Create an AMQP connection over a net.Conn with
- Container.Connection() and open it with Connection.Open().
++You can enable AMQP over any connection that implements the standard net.Conn
++interface. Typically you can connect with net.Dial() or listen for server
++connections with net.Listen.  Enable AMQP by passing the net.Conn to
++Container.Connection().
 +
- AMQP sends messages over "links". Each link has a Sender end and a Receiver
- end. Connection.Sender() and Connection.Receiver() allow you to create links to
- Send() and Receive() messages.
++AMQP allows bi-direction peer-to-peer message exchange as well as
++client-to-broker. Messages are sent over "links". Each link is one-way and has a
++Sender and Receiver end. Connection.Sender() and Connection.Receiver() open
++links to Send() and Receive() messages. Connection.Incoming() lets you accept
++incoming links opened by the remote peer. You can open and accept multiple links
++in both directions on a single Connection.
 +
- You can create an AMQP server connection by calling Connection.Server() and
- Connection.Listen() before calling Connection.Open(). A server connection can
- negotiate protocol security details and can accept incoming links opened from
- the remote end of the connection.
++Some of the documentation examples show client and server side by side in a
++single program, in separate goroutines. This is only for example purposes, real
++AMQP applications would run in separate processes on the network.
++More realistic examples: https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
++
++Some of the documentation examples show client and server side by side in a
++single program, in separate goroutines. This is only for example purposes, real
++AMQP applications would run in separate processes on the network.
++More realistic examples: https://github.com/apache/qpid-proton/blob/master/examples/go/README.md
 +
 +*/
 +package electron
 +
 +//#cgo LDFLAGS: -lqpid-proton
 +import "C"
 +
 +// Just for package comment
 +
 +/* DEVELOPER NOTES
 +
 +There is a single proton.Engine per connection, each driving it's own event-loop goroutine,
 +and each with a 'handler'. Most state for a connection is maintained on the handler, and
 +only accessed in the event-loop goroutine, so no locks are required there.
 +
 +The handler sets up channels as needed to get or send data from user goroutines
 +using electron types like Sender or Receiver.
 +
- We also use Engine.Inject to inject actions into the event loop from user
- goroutines. It is important to check at the start of an injected function that
- required objects are still valid, for example a link may be remotely closed
- between the time a Sender function calls Inject and the time the injected
- function is execute by the handler goroutine. See comments in endpoint.go for more.
++Engine.Inject injects actions into the event loop from user goroutines. It is
++important to check at the start of an injected function that required objects
++are still valid, for example a link may be remotely closed between the time a
++Sender function calls Inject and the time the injected function is execute by
++the handler goroutine.
 +
 +*/


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


[37/50] [abbrv] qpid-proton git commit: PROTON-1322: c++ Sunstudio: unable to find templated method

Posted by ac...@apache.org.
PROTON-1322: c++ Sunstudio: unable to find templated method

Sunstudio can't find templated method when parameter can be constructed by an
intermediate class (proton::scalar --> proton::value)

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: d280f8fad07a8c38e05dc2009fd4ee7d1682a56b
Parents: af17dea
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 17:57:07 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/include/proton/value.hpp | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d280f8fa/proton-c/bindings/cpp/include/proton/value.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/value.hpp b/proton-c/bindings/cpp/include/proton/value.hpp
index 242ec68..b24f02e 100644
--- a/proton-c/bindings/cpp/include/proton/value.hpp
+++ b/proton-c/bindings/cpp/include/proton/value.hpp
@@ -160,6 +160,9 @@ template<class T> T get(const value& v) { T x; get(v, x); return x; }
 /// @related proton::value
 template<class T> void get(const value& v, T& x) { codec::decoder d(v, true); d >> x; }
 
+/// @related proton::value
+template<class T, class U> inline void get(const U& u, T& x) { const value v(u); get(v, x); }
+
 /// @copydoc scalar::coerce
 /// @related proton::value
 template<class T> T coerce(const value& v) { T x; coerce(v, x); return x; }


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


[45/50] [abbrv] qpid-proton git commit: PROTON-1337 Add missing file

Posted by ac...@apache.org.
PROTON-1337 Add missing file

Missed on last commit.  

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

Branch: refs/heads/go1
Commit: 3661f90f79d24d8dee5649f4302b5a1a486a47ec
Parents: acf1f6e
Author: Timothy Bish <ta...@gmail.com>
Authored: Fri Oct 28 15:37:24 2016 -0400
Committer: Timothy Bish <ta...@gmail.com>
Committed: Fri Oct 28 15:37:24 2016 -0400

----------------------------------------------------------------------
 .../qpid/proton/codec/ReadableBuffer.java       | 191 +++++++++++++++++++
 1 file changed, 191 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/3661f90f/proton-j/src/main/java/org/apache/qpid/proton/codec/ReadableBuffer.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/ReadableBuffer.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/ReadableBuffer.java
new file mode 100644
index 0000000..1360d76
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/ReadableBuffer.java
@@ -0,0 +1,191 @@
+/*
+ * 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;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * Interface to abstract a buffer, similar to {@link WritableBuffer}
+ */
+public interface ReadableBuffer {
+
+    void put(ReadableBuffer other);
+
+    byte get();
+
+    int getInt();
+
+    long getLong();
+
+    short getShort();
+
+    float getFloat();
+
+    double getDouble();
+
+    ReadableBuffer get(final byte[] data, final int offset, final int length);
+
+    ReadableBuffer get(final byte[] data);
+
+    ReadableBuffer position(int position);
+
+    ReadableBuffer slice();
+
+    ReadableBuffer flip();
+
+    ReadableBuffer limit(int limit);
+
+    int limit();
+
+    int remaining();
+
+    int position();
+
+    boolean hasRemaining();
+
+    ReadableBuffer duplicate();
+
+    ByteBuffer byteBuffer();
+
+    String readUTF8();
+
+    final class ByteBufferReader implements ReadableBuffer {
+
+        private static final Charset Charset_UTF8 = Charset.forName("UTF-8");
+
+        private ByteBuffer buffer;
+
+        public static ByteBufferReader allocate(int size) {
+            ByteBuffer allocated = ByteBuffer.allocate(size);
+            return new ByteBufferReader(allocated);
+        }
+
+        public ByteBufferReader(ByteBuffer buffer) {
+            this.buffer = buffer;
+        }
+
+        @Override
+        public byte get() {
+            return buffer.get();
+        }
+
+        @Override
+        public int getInt() {
+            return buffer.getInt();
+        }
+
+        @Override
+        public long getLong() {
+            return buffer.getLong();
+        }
+
+        @Override
+        public short getShort() {
+            return buffer.getShort();
+        }
+
+        @Override
+        public float getFloat() {
+            return buffer.getFloat();
+        }
+
+        @Override
+        public double getDouble() {
+            return buffer.getDouble();
+        }
+
+        @Override
+        public int limit() {
+            return buffer.limit();
+        }
+
+        @Override
+        public ReadableBuffer get(byte[] data, int offset, int length) {
+            buffer.get(data, offset, length);
+            return this;
+        }
+
+        @Override
+        public ReadableBuffer get(byte[] data) {
+            buffer.get(data);
+            return this;
+        }
+
+        @Override
+        public ReadableBuffer flip() {
+            buffer.flip();
+            return this;
+        }
+
+        @Override
+        public ReadableBuffer position(int position) {
+            buffer.position(position);
+            return this;
+        }
+
+        @Override
+        public ReadableBuffer slice() {
+            return new ByteBufferReader(buffer.slice());
+        }
+
+        @Override
+        public ReadableBuffer limit(int limit) {
+            buffer.limit(limit);
+            return this;
+        }
+
+        @Override
+        public int remaining() {
+            return buffer.remaining();
+        }
+
+        @Override
+        public int position() {
+            return buffer.position();
+        }
+
+        @Override
+        public boolean hasRemaining() {
+            return buffer.hasRemaining();
+        }
+
+        @Override
+        public ReadableBuffer duplicate() {
+            return new ByteBufferReader(buffer.duplicate());
+        }
+
+        @Override
+        public ByteBuffer byteBuffer() {
+            return buffer;
+        }
+
+        @Override
+        public String readUTF8() {
+            CharBuffer charBuf = Charset_UTF8.decode(buffer);
+            return charBuf.toString();
+        }
+
+        @Override
+        public void put(ReadableBuffer other) {
+            this.buffer.put(other.byteBuffer());
+        }
+    }
+}
\ No newline at end of file


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


[47/50] [abbrv] qpid-proton git commit: PROTON-1338: Go: make binding compatible with older C libraries

Posted by ac...@apache.org.
PROTON-1338: Go: make binding compatible with older C libraries

The Go binding is now compatible with all releases since 0.10, tested up to 0.15
Absent C library source or binary incompatible changes, it should remain so.


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

Branch: refs/heads/go1
Commit: 7b6b8dec76f1345647de90201130f7d8bff903f1
Parents: 9a4cdf0
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Nov 1 22:47:35 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Nov 1 22:47:35 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/genwrap.go                 |   9 +-
 .../go/src/qpid.apache.org/amqp/interop_test.go |  29 ++--
 .../go/src/qpid.apache.org/amqp/version.go      |  29 ++++
 .../go/src/qpid.apache.org/proton/engine.go     | 143 ++++++++++++-------
 .../go/src/qpid.apache.org/proton/handlers.go   |   6 +-
 .../src/qpid.apache.org/proton/proton_test.go   |  73 +++++++++-
 .../go/src/qpid.apache.org/proton/wrappers.go   |  10 ++
 .../src/qpid.apache.org/proton/wrappers_gen.go  |   6 -
 8 files changed, 219 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/genwrap.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/genwrap.go b/proton-c/bindings/go/genwrap.go
index 8a9af03..7782b0b 100644
--- a/proton-c/bindings/go/genwrap.go
+++ b/proton-c/bindings/go/genwrap.go
@@ -212,7 +212,7 @@ var (
 	enumDefRe   = regexp.MustCompile("typedef enum {([^}]*)} pn_([a-z_]+)_t;")
 	enumValRe   = regexp.MustCompile("PN_[A-Z_]+")
 	skipEventRe = regexp.MustCompile("EVENT_NONE|REACTOR|SELECTABLE|TIMER")
-	skipFnRe    = regexp.MustCompile("attach|context|class|collect|link_recv|link_send|transport_.*logf$|transport_.*trace|transport_head|transport_push|connection_set_password")
+	skipFnRe    = regexp.MustCompile("attach|context|class|collect|link_recv|link_send|transport_.*logf$|transport_.*trace|transport_head|transport_tail|transport_push|connection_set_password|link_get_drain")
 )
 
 // Generate event wrappers.
@@ -410,12 +410,7 @@ func goFnName(api, fname string) string {
 	if skipFnRe.FindStringSubmatch(api+"_"+fname) != nil {
 		return ""
 	}
-	switch api + "." + fname {
-	case "link.get_drain":
-		return "IsDrain"
-	default:
-		return mixedCaseTrim(fname, "get_")
-	}
+	return mixedCaseTrim(fname, "get_")
 }
 
 func apiWrapFns(api, header string, out io.Writer) {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/amqp/interop_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/interop_test.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/interop_test.go
index d118523..b3e27bc 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/interop_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/interop_test.go
@@ -40,11 +40,14 @@ func checkEqual(want interface{}, got interface{}) error {
 	return nil
 }
 
-func getReader(name string) (r io.Reader) {
+func getReader(t *testing.T, name string) (r io.Reader) {
 	dir := os.Getenv("PN_INTEROP_DIR")
+	if dir == "" {
+		t.Skip("no PN_INTEROP_DIR in environment")
+	}
 	r, err := os.Open(dir + "/" + name + ".amqp")
 	if err != nil {
-		panic(fmt.Errorf("Can't open %#v: %v", name, err))
+		t.Fatalf("can't open %#v: %v", name, err)
 	}
 	return
 }
@@ -91,7 +94,7 @@ func checkDecode(d *Decoder, want interface{}, gotPtr interface{}, t *testing.T)
 }
 
 func TestUnmarshal(t *testing.T) {
-	bytes, err := ioutil.ReadAll(getReader("strings"))
+	bytes, err := ioutil.ReadAll(getReader(t, "strings"))
 	if err != nil {
 		t.Error(err)
 	}
@@ -109,7 +112,7 @@ func TestUnmarshal(t *testing.T) {
 }
 
 func TestPrimitivesExact(t *testing.T) {
-	d := NewDecoder(getReader("primitives"))
+	d := NewDecoder(getReader(t, "primitives"))
 	// Decoding into exact types
 	var b bool
 	checkDecode(d, true, &b, t)
@@ -135,7 +138,7 @@ func TestPrimitivesExact(t *testing.T) {
 }
 
 func TestPrimitivesCompatible(t *testing.T) {
-	d := NewDecoder(getReader("primitives"))
+	d := NewDecoder(getReader(t, "primitives"))
 	// Decoding into compatible types
 	var b bool
 	var i int
@@ -188,7 +191,7 @@ func checkDecodeInterface(d *Decoder, want interface{}, t *testing.T) {
 }
 
 func TestPrimitivesInterface(t *testing.T) {
-	d := NewDecoder(getReader("primitives"))
+	d := NewDecoder(getReader(t, "primitives"))
 	checkDecodeInterface(d, true, t)
 	checkDecodeInterface(d, false, t)
 	checkDecodeInterface(d, uint8(42), t)
@@ -203,7 +206,7 @@ func TestPrimitivesInterface(t *testing.T) {
 }
 
 func TestStrings(t *testing.T) {
-	d := NewDecoder(getReader("strings"))
+	d := NewDecoder(getReader(t, "strings"))
 	// Test decoding as plain Go strings
 	for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
 		var got string
@@ -215,7 +218,7 @@ func TestStrings(t *testing.T) {
 	}
 
 	// Test decoding as specific string types
-	d = NewDecoder(getReader("strings"))
+	d = NewDecoder(getReader(t, "strings"))
 	var bytes []byte
 	var str, sym string
 	checkDecode(d, []byte("abc\000defg"), &bytes, t)
@@ -230,7 +233,7 @@ func TestStrings(t *testing.T) {
 	}
 
 	// Test some error handling
-	d = NewDecoder(getReader("strings"))
+	d = NewDecoder(getReader(t, "strings"))
 	var s string
 	err := d.Decode(s)
 	if err == nil {
@@ -314,7 +317,7 @@ func TestEncodeDecode(t *testing.T) {
 }
 
 func TestMap(t *testing.T) {
-	d := NewDecoder(getReader("maps"))
+	d := NewDecoder(getReader(t, "maps"))
 
 	// Generic map
 	var m Map
@@ -324,7 +327,7 @@ func TestMap(t *testing.T) {
 	var i interface{}
 	checkDecode(d, Map{int32(1): "one", int32(2): "two", int32(3): "three"}, &i, t)
 
-	d = NewDecoder(getReader("maps"))
+	d = NewDecoder(getReader(t, "maps"))
 	// Specific typed map
 	var m2 map[string]int
 	checkDecode(d, map[string]int{"one": 1, "two": 2, "three": 3}, &m2, t)
@@ -345,7 +348,7 @@ func TestMap(t *testing.T) {
 }
 
 func TestList(t *testing.T) {
-	d := NewDecoder(getReader("lists"))
+	d := NewDecoder(getReader(t, "lists"))
 	var l List
 	checkDecode(d, List{int32(32), "foo", true}, &l, t)
 	checkDecode(d, List{}, &l, t)
@@ -354,7 +357,7 @@ func TestList(t *testing.T) {
 // TODO aconway 2015-09-08: the message.amqp file seems to be incorrectly coded as
 // as an AMQP string *inside* an AMQP binary?? Skip the test for now.
 func TODO_TestMessage(t *testing.T) {
-	bytes, err := ioutil.ReadAll(getReader("message"))
+	bytes, err := ioutil.ReadAll(getReader(t, "message"))
 	if err != nil {
 		t.Fatal(err)
 	}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/amqp/version.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/version.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/version.go
new file mode 100644
index 0000000..cefa904
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/version.go
@@ -0,0 +1,29 @@
+/*
+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 amqp
+
+// Version check for proton library.
+// Done here because this is the lowest-level dependency for all the proton Go packages.
+
+// #include <proton/version.h>
+// #if PN_VERSION_MINOR < 10
+// #error packages qpid.apache.org/... require Proton-C library version 0.10 or greater
+// #endif
+import "C"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index 5680010..c0f0093 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -22,6 +22,8 @@ package proton
 import (
 	"fmt"
 	"net"
+	"os"
+	"strings"
 	"sync"
 	"time"
 	"unsafe"
@@ -29,7 +31,6 @@ import (
 
 /*
 #include <proton/connection.h>
-#include <proton/connection_engine.h>
 #include <proton/event.h>
 #include <proton/error.h>
 #include <proton/handlers.h>
@@ -102,52 +103,66 @@ type Engine struct {
 	err    ErrorHolder
 	inject chan func()
 
-	conn      net.Conn
-	engine    C.pn_connection_engine_t
-	handlers  []EventHandler // Handlers for proton events.
-	running   chan struct{}  // This channel will be closed when the goroutines are done.
-	closeOnce sync.Once
-	timer     *time.Timer
+	conn       net.Conn
+	connection Connection
+	transport  Transport
+	collector  *C.pn_collector_t
+	handlers   []EventHandler // Handlers for proton events.
+	running    chan struct{}  // This channel will be closed when the goroutines are done.
+	closeOnce  sync.Once
+	timer      *time.Timer
+	traceEvent bool
 }
 
 const bufferSize = 4096
 
-// NewEngine initializes a engine with a connection and handlers. To start it running:
-//    eng := NewEngine(...)
-//    go run eng.Run()
-// The goroutine will exit when the engine is closed or disconnected.
-// You can check for errors on Engine.Error.
-//
+func envBool(name string) bool {
+	v := strings.ToLower(os.Getenv(name))
+	return v == "true" || v == "1" || v == "yes" || v == "on"
+}
+
+// Create a new Engine and call Initialize() with conn and handlers
 func NewEngine(conn net.Conn, handlers ...EventHandler) (*Engine, error) {
-	eng := &Engine{
-		inject:   make(chan func()),
-		conn:     conn,
-		handlers: handlers,
-		running:  make(chan struct{}),
-		timer:    time.NewTimer(0),
-	}
-	if pnErr := C.pn_connection_engine_init(&eng.engine); pnErr != 0 {
-		return nil, fmt.Errorf("cannot setup engine: %s", PnErrorCode(pnErr))
+	eng := &Engine{}
+	return eng, eng.Initialize(conn, handlers...)
+}
+
+// Initialize an Engine with a connection and handlers. Start it with Run()
+func (eng *Engine) Initialize(conn net.Conn, handlers ...EventHandler) error {
+	eng.inject = make(chan func())
+	eng.conn = conn
+	eng.connection = Connection{C.pn_connection()}
+	eng.transport = Transport{C.pn_transport()}
+	eng.collector = C.pn_collector()
+	eng.handlers = handlers
+	eng.running = make(chan struct{})
+	eng.timer = time.NewTimer(0)
+	eng.traceEvent = envBool("PN_TRACE_EVT")
+	if eng.transport.IsNil() || eng.connection.IsNil() || eng.collector == nil {
+		eng.free()
+		return fmt.Errorf("proton.NewEngine cannot allocate")
 	}
-	return eng, nil
+	C.pn_connection_collect(eng.connection.pn, eng.collector)
+	return nil
 }
 
-// Create a byte slice backed by the memory of a pn_rwbytes_t, no copy.
-// Empty buffer {0,0} returns a nil byte slice.
-func byteSlice(data unsafe.Pointer, size C.size_t) []byte {
-	if data == nil || size == 0 {
+// Create a byte slice backed by C memory.
+// Empty or error (size <= 0) returns a nil byte slice.
+func cByteSlice(start unsafe.Pointer, size int) []byte {
+	if start == nil || size <= 0 {
 		return nil
 	} else {
-		return (*[1 << 30]byte)(data)[:size:size]
+		// Slice from very large imaginary array in C memory
+		return (*[1 << 30]byte)(start)[:size:size]
 	}
 }
 
 func (eng *Engine) Connection() Connection {
-	return Connection{C.pn_connection_engine_connection(&eng.engine)}
+	return eng.connection
 }
 
 func (eng *Engine) Transport() Transport {
-	return Transport{C.pn_connection_engine_transport(&eng.engine)}
+	return eng.transport
 }
 
 func (eng *Engine) String() string {
@@ -211,7 +226,8 @@ func (eng *Engine) disconnect(err error) {
 	cond := eng.Transport().Condition()
 	cond.SetError(err)              // Set the provided error.
 	cond.SetError(eng.conn.Close()) // Use connection error if cond is not already set.
-	C.pn_connection_engine_disconnected(&eng.engine)
+	eng.transport.CloseTail()
+	eng.transport.CloseHead()
 }
 
 // Close the engine's connection.
@@ -249,40 +265,59 @@ func (eng *Engine) tick() {
 }
 
 func (eng *Engine) dispatch() bool {
-	var needTick bool // Set if we need to tick the transport.
-	for {
-		cevent := C.pn_connection_engine_dispatch(&eng.engine)
-		if cevent == nil {
-			break
-		}
-		event := makeEvent(cevent, eng)
-		if event.Type() == ETransport {
-			needTick = true
+	for ce := C.pn_collector_peek(eng.collector); ce != nil; ce = C.pn_collector_peek(eng.collector) {
+		e := makeEvent(ce, eng)
+		if eng.traceEvent {
+			eng.transport.Log(e.String())
 		}
 		for _, h := range eng.handlers {
-			h.HandleEvent(event)
+			h.HandleEvent(e)
 		}
+		if e.Type() == EConnectionRemoteOpen {
+			eng.tick() // Update the tick if changed by remote.
+		}
+		C.pn_collector_pop(eng.collector)
 	}
-	if needTick {
-		eng.tick()
-	}
-	return !bool(C.pn_connection_engine_finished(&eng.engine))
+	return !eng.transport.Closed() || C.pn_collector_peek(eng.collector) != nil
 }
 
 func (eng *Engine) writeBuffer() []byte {
-	w := C.pn_connection_engine_write_buffer(&eng.engine)
-	return byteSlice(unsafe.Pointer(w.start), w.size)
+	size := eng.Transport().Pending() // Evaluate before Head(), may change buffer.
+	start := eng.Transport().Head()
+	return cByteSlice(start, size)
 }
 
 func (eng *Engine) readBuffer() []byte {
-	r := C.pn_connection_engine_read_buffer(&eng.engine)
-	return byteSlice(unsafe.Pointer(r.start), r.size)
+	size := eng.Transport().Capacity()
+	start := eng.Transport().Tail()
+	return cByteSlice(start, size)
+}
+
+func (eng *Engine) free() {
+	if !eng.transport.IsNil() {
+		eng.transport.Unbind()
+		eng.transport.Free()
+		eng.transport = Transport{}
+	}
+	if !eng.connection.IsNil() {
+		eng.connection.Free()
+		eng.connection = Connection{}
+	}
+	if eng.collector != nil {
+		C.pn_collector_release(eng.collector)
+		C.pn_collector_free(eng.collector)
+		eng.collector = nil
+	}
 }
 
 // Run the engine. Engine.Run() will exit when the engine is closed or
 // disconnected.  You can check for errors after exit with Engine.Error().
 //
 func (eng *Engine) Run() error {
+	defer eng.free()
+	eng.transport.Bind(eng.connection)
+	eng.tick() // Start ticking if needed
+
 	// Channels for read and write buffers going in and out of the read/write goroutines.
 	// The channels are unbuffered: we want to exchange buffers in seuquence.
 	readsIn, writesIn := make(chan []byte), make(chan []byte)
@@ -304,7 +339,7 @@ func (eng *Engine) Run() error {
 			} else if err != nil {
 				_ = eng.Inject(func() {
 					eng.Transport().Condition().SetError(err)
-					C.pn_connection_engine_read_close(&eng.engine)
+					eng.Transport().CloseTail()
 				})
 				return
 			}
@@ -324,7 +359,7 @@ func (eng *Engine) Run() error {
 			} else if err != nil {
 				_ = eng.Inject(func() {
 					eng.Transport().Condition().SetError(err)
-					C.pn_connection_engine_write_close(&eng.engine)
+					eng.Transport().CloseHead()
 				})
 				return
 			}
@@ -361,10 +396,10 @@ func (eng *Engine) Run() error {
 		case sendWrites <- writeBuf:
 
 		case buf := <-readsOut:
-			C.pn_connection_engine_read_done(&eng.engine, C.size_t(len(buf)))
+			eng.transport.Process(uint(len(buf)))
 
 		case buf := <-writesOut:
-			C.pn_connection_engine_write_done(&eng.engine, C.size_t(len(buf)))
+			eng.transport.Pop(uint(len(buf)))
 
 		case f, ok := <-eng.inject: // Function injected from another goroutine
 			if ok {
@@ -383,7 +418,5 @@ func (eng *Engine) Run() error {
 	close(eng.running)   // Signal goroutines have exited and Error is set, disable Inject()
 	_ = eng.conn.Close() // Close conn, force read/write goroutines to exit (they will Inject)
 	wait.Wait()          // Wait for goroutines
-
-	C.pn_connection_engine_final(&eng.engine)
 	return eng.err.Get()
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
index 8213b65..961136e 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
@@ -231,14 +231,14 @@ type flowcontroller struct {
 }
 
 func (d flowcontroller) HandleEvent(e Event) {
-	link := e.Link();
+	link := e.Link()
 
 	switch e.Type() {
 	case ELinkLocalOpen, ELinkRemoteOpen, ELinkFlow, EDelivery:
 		if link.IsReceiver() {
 			d.drained += link.Drained()
 			if d.drained != 0 {
-				link.Flow(d.window-link.Credit())
+				link.Flow(d.window - link.Credit())
 			}
 		}
 	}
@@ -313,7 +313,7 @@ func (d *MessagingAdapter) HandleEvent(e Event) {
 			d,
 		}
 		if d.Prefetch > 0 {
-			d.flowcontroller = flowcontroller{ window:d.Prefetch, drained:0 }
+			d.flowcontroller = flowcontroller{window: d.Prefetch, drained: 0}
 		}
 		d.mhandler.HandleMessagingEvent(MStart, e)
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/proton/proton_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/proton_test.go b/proton-c/bindings/go/src/qpid.apache.org/proton/proton_test.go
index bb3f21c..aad93eb 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/proton_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/proton_test.go
@@ -20,8 +20,77 @@ under the License.
 package proton
 
 import (
+	"fmt"
+	"net"
+	"path"
+	"runtime"
 	"testing"
+	"time"
 )
 
-// TODO aconway 2015-10-14: placeholder, add unit tests.
-func Test(*testing.T) {}
+func errorIf(t *testing.T, err error) {
+	if err != nil {
+		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
+		if ok {
+			_, file = path.Split(file)
+		}
+		t.Errorf("(from %s:%d) %v", file, line, err)
+	}
+}
+
+func fatalIf(t *testing.T, err error) {
+	if err != nil {
+		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
+		if ok {
+			_, file = path.Split(file)
+		}
+		t.Fatalf("(from %s:%d) %v", file, line, err)
+	}
+}
+
+type events []EventType
+
+type testEngine struct {
+	Engine
+	events chan EventType
+}
+
+func newTestEngine(conn net.Conn) (*testEngine, error) {
+	testEng := &testEngine{events: make(chan EventType, 1000)}
+	return testEng, testEng.Initialize(conn, testEng)
+}
+
+func (eng *testEngine) HandleEvent(e Event) {
+	eng.events <- e.Type()
+}
+
+func (eng *testEngine) expect(events []EventType) error {
+	timer := time.After(5 * time.Second)
+	for _, want := range events {
+		select {
+		case got := <-eng.events:
+			if want != got {
+				return fmt.Errorf("want %s, got %s", want, got)
+			}
+		case <-timer:
+			return fmt.Errorf("expect timeout")
+		}
+	}
+	return nil
+}
+
+func Test(t *testing.T) {
+	cConn, sConn := net.Pipe()
+	client, err := newTestEngine(cConn)
+	fatalIf(t, err)
+	server, err := newTestEngine(sConn)
+	fatalIf(t, err)
+	server.Server()
+	go client.Run()
+	go server.Run()
+	fatalIf(t, server.expect(events{EConnectionInit, EConnectionBound}))
+	fatalIf(t, client.expect(events{EConnectionInit, EConnectionBound}))
+	fatalIf(t, client.InjectWait(func() error { client.Connection().Open(); return nil }))
+	fatalIf(t, client.expect(events{EConnectionLocalOpen}))
+	fatalIf(t, server.expect(events{EConnectionRemoteOpen}))
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
index 1dee743..4d55e4f 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
@@ -268,6 +268,11 @@ func (l Link) Type() string {
 	}
 }
 
+// IsDrain calls pn_link_get_drain(), it conflicts with pn_link_drain() under the normal mapping.
+func (l Link) IsDrain() bool {
+	return bool(C.pn_link_get_drain(l.pn))
+}
+
 func cPtr(b []byte) *C.char {
 	if len(b) == 0 {
 		return nil
@@ -410,6 +415,11 @@ func (t Transport) Head() unsafe.Pointer {
 	return unsafe.Pointer(C.pn_transport_head(t.pn))
 }
 
+// Special treatment for Transport.Tail, return value is unsafe.Pointer not string
+func (t Transport) Tail() unsafe.Pointer {
+	return unsafe.Pointer(C.pn_transport_tail(t.pn))
+}
+
 // Special treatment for Transport.Push, takes []byte instead of char*, size
 func (t Transport) Push(bytes []byte) int {
 	return int(C.pn_transport_push(t.pn, (*C.char)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes))))

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/7b6b8dec/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
index 629caa6..19bfde2 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
@@ -310,9 +310,6 @@ func (l Link) Queued() int {
 func (l Link) RemoteCredit() int {
 	return int(C.pn_link_remote_credit(l.pn))
 }
-func (l Link) IsDrain() bool {
-	return bool(C.pn_link_get_drain(l.pn))
-}
 func (l Link) Drained() int {
 	return int(C.pn_link_drained(l.pn))
 }
@@ -832,9 +829,6 @@ func (t Transport) Output(bytes string, size uint) int {
 func (t Transport) Capacity() int {
 	return int(C.pn_transport_capacity(t.pn))
 }
-func (t Transport) Tail() string {
-	return C.GoString(C.pn_transport_tail(t.pn))
-}
 func (t Transport) Process(size uint) int {
 	return int(C.pn_transport_process(t.pn, C.size_t(size)))
 }


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


[02/50] [abbrv] qpid-proton git commit: PROTON-1293: Go binding SASL support.

Posted by ac...@apache.org.
PROTON-1293: Go binding SASL support.

proton package
- added sasl.h to the Go proton wrapper generator.
- capitalized as "SASL" *not* "Sasl", consistent with Go conventions (e.g. URL)
- added SASL() accessor to proton.Transport.
- Engine.Run() extra dispatch and check as pn_connection_engine_read/write_buffer()
  can generate events that close the transport in an auth failure.
- Engine.Id()/String() use transport address to match PN_TRACE_ logs.
- Drop auto-open of engine: let user set security first.

electron package:
- new ConnectionOption: User, Password, VirtualHost, SASLAllowInsecure, SASLAllowedMechs
- global settings with GlobalSASLConfigDir, GobalSASLConfName
- IncomingConnection allows user to accept/reject authenticated incoming connections
- updated & improved documentation
- Endpoint.Sync() synchronous check of endpoint open, to verify authenticated.

Note: Password option takes []byte not string. There is no way to securely erase
a string from memory, an array can be over-written.


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

Branch: refs/heads/go1
Commit: 0e37353d7410841ebb291b14e05b7dc9943cd1ce
Parents: 3d9fe62
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Sep 6 13:11:09 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Sep 20 17:39:15 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/genwrap.go                 |  42 +-
 .../src/qpid.apache.org/electron/auth_test.go   | 124 +++++
 .../src/qpid.apache.org/electron/connection.go  | 209 ++++++--
 .../src/qpid.apache.org/electron/container.go   |  15 +-
 .../go/src/qpid.apache.org/electron/doc.go      |  35 +-
 .../qpid.apache.org/electron/electron_test.go   | 477 +++++++++++++++++++
 .../go/src/qpid.apache.org/electron/endpoint.go | 122 ++++-
 .../go/src/qpid.apache.org/electron/handler.go  |  80 ++--
 .../go/src/qpid.apache.org/electron/link.go     |  36 +-
 .../qpid.apache.org/electron/messaging_test.go  | 454 ------------------
 .../go/src/qpid.apache.org/electron/receiver.go |  10 +-
 .../go/src/qpid.apache.org/electron/sender.go   |  10 +-
 .../go/src/qpid.apache.org/proton/engine.go     |  83 ++--
 .../go/src/qpid.apache.org/proton/handlers.go   |   2 +-
 .../go/src/qpid.apache.org/proton/wrappers.go   |  21 +-
 .../src/qpid.apache.org/proton/wrappers_gen.go  |  80 +++-
 proton-c/src/engine/engine.c                    |   4 +
 17 files changed, 1126 insertions(+), 678 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/genwrap.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/genwrap.go b/proton-c/bindings/go/genwrap.go
index c904638..f295a32 100644
--- a/proton-c/bindings/go/genwrap.go
+++ b/proton-c/bindings/go/genwrap.go
@@ -19,7 +19,9 @@ under the License.
 
 // Code generator to generate a thin Go wrapper API around the C proton API.
 //
-
+// Not run automatically, generated sources are checked in. To update the
+// generated sources run `go run genwrap.go` in this directory.
+//
 package main
 
 import (
@@ -44,7 +46,7 @@ func main() {
 	panicIf(err)
 	defer out.Close()
 
-	apis := []string{"session", "link", "delivery", "disposition", "condition", "terminus", "connection", "transport"}
+	apis := []string{"session", "link", "delivery", "disposition", "condition", "terminus", "connection", "transport", "sasl"}
 	fmt.Fprintln(out, copyright)
 	fmt.Fprint(out, `
 package proton
@@ -89,12 +91,18 @@ import (
 	}
 }
 
+// Identify acronyms that should be uppercase not Mixedcase
+var acronym = regexp.MustCompile("(?i)SASL|AMQP")
+
 func mixedCase(s string) string {
 	result := ""
 	for _, w := range strings.Split(s, "_") {
-		if w != "" {
-			result = result + strings.ToUpper(w[0:1]) + strings.ToLower(w[1:])
+		if acronym.MatchString(w) {
+			w = strings.ToUpper(w)
+		} else {
+			w = strings.ToUpper(w[0:1]) + strings.ToLower(w[1:])
 		}
+		result = result + w
 	}
 	return result
 }
@@ -122,7 +130,13 @@ func findEnums(header string) (enums []enumType) {
 	return enums
 }
 
+// Types that are integral, not wrappers. Enums are added automatically.
+var simpleType = map[string]bool{
+	"State": true, // integral typedef
+}
+
 func genEnum(out io.Writer, name string, values []string) {
+	simpleType[mixedCase(name)] = true
 	doTemplate(out, []interface{}{name, values}, `
 {{$enumName := index . 0}}{{$values := index . 1}}
 type {{mixedCase $enumName}} C.pn_{{$enumName}}_t
@@ -140,10 +154,6 @@ func (e {{mixedCase $enumName}}) String() string {
 `)
 }
 
-var (
-	reSpace = regexp.MustCompile("\\s+")
-)
-
 func panicIf(err error) {
 	if err != nil {
 		panic(err)
@@ -202,7 +212,7 @@ var (
 	enumDefRe   = regexp.MustCompile("typedef enum {([^}]*)} pn_([a-z_]+)_t;")
 	enumValRe   = regexp.MustCompile("PN_[A-Z_]+")
 	skipEventRe = regexp.MustCompile("EVENT_NONE|REACTOR|SELECTABLE|TIMER")
-	skipFnRe    = regexp.MustCompile("attach|context|class|collect|link_recv|link_send|transport_.*logf$|transport_.*trace|transport_head|transport_push")
+	skipFnRe    = regexp.MustCompile("attach|context|class|collect|link_recv|link_send|transport_.*logf$|transport_.*trace|transport_head|transport_push|connection_set_password")
 )
 
 // Generate event wrappers.
@@ -268,20 +278,10 @@ func (g genType) goConvert(value string) string {
 	}
 }
 
-var notStruct = map[string]bool{
-	"EventType":        true,
-	"SndSettleMode":    true,
-	"RcvSettleMode":    true,
-	"TerminusType":     true,
-	"State":            true,
-	"Durability":       true,
-	"ExpiryPolicy":     true,
-	"DistributionMode": true,
-}
-
 func mapType(ctype string) (g genType) {
 	g.Ctype = "C." + strings.Trim(ctype, " \n")
 
+	// Special-case mappings for C types, default: is the general wrapper type case.
 	switch g.Ctype {
 	case "C.void":
 		g.Gotype = ""
@@ -331,7 +331,7 @@ func mapType(ctype string) (g genType) {
 			panic(fmt.Errorf("unknown C type %#v", g.Ctype))
 		}
 		g.Gotype = mixedCase(match[1])
-		if !notStruct[g.Gotype] {
+		if !simpleType[g.Gotype] {
 			g.ToGo = g.goLiteral
 			g.ToC = func(v string) string { return v + ".pn" }
 		}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
new file mode 100644
index 0000000..a090b78
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
@@ -0,0 +1,124 @@
+/*
+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 electron
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+func testAuthClientServer(t *testing.T, copts []ConnectionOption, sopts []ConnectionOption) (got connectionSettings, err error) {
+	client, server := newClientServerOpts(t, copts, sopts)
+	defer closeClientServer(client, server)
+
+	go func() {
+		for in := range server.Incoming() {
+			switch in := in.(type) {
+			case *IncomingConnection:
+				got = connectionSettings{user: in.User(), virtualHost: in.VirtualHost()}
+			}
+			in.Accept()
+		}
+	}()
+
+	err = client.Sync()
+	return
+}
+
+func TestAuthAnonymous(t *testing.T) {
+	fatalIf(t, configureSASL())
+	got, err := testAuthClientServer(t,
+		[]ConnectionOption{User("fred"), VirtualHost("vhost"), SASLAllowInsecure(true)},
+		[]ConnectionOption{SASLAllowedMechs("ANONYMOUS"), SASLAllowInsecure(true)})
+	fatalIf(t, err)
+	errorIf(t, checkEqual(connectionSettings{"anonymous", "vhost"}, got))
+}
+
+func TestAuthPlain(t *testing.T) {
+	fatalIf(t, configureSASL())
+	got, err := testAuthClientServer(t,
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("xxx"))},
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
+	fatalIf(t, err)
+	errorIf(t, checkEqual(connectionSettings{"fred@proton", ""}, got))
+}
+
+func TestAuthBadPass(t *testing.T) {
+	fatalIf(t, configureSASL())
+	_, err := testAuthClientServer(t,
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("yyy"))},
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
+	if err == nil {
+		t.Error("Expected auth failure for bad pass")
+	}
+}
+
+func TestAuthBadUser(t *testing.T) {
+	fatalIf(t, configureSASL())
+	_, err := testAuthClientServer(t,
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("foo@bar"), Password([]byte("yyy"))},
+		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
+	if err == nil {
+		t.Error("Expected auth failure for bad user")
+	}
+}
+
+var confDir string
+var confErr error
+
+func configureSASL() error {
+	if confDir != "" || confErr != nil {
+		return confErr
+	}
+	confDir, confErr = ioutil.TempDir("", "")
+	if confErr != nil {
+		return confErr
+	}
+
+	GlobalSASLConfigDir(confDir)
+	GlobalSASLConfigName("test")
+	conf := filepath.Join(confDir, "test.conf")
+
+	db := filepath.Join(confDir, "proton.sasldb")
+	cmd := exec.Command("saslpasswd2", "-c", "-p", "-f", db, "-u", "proton", "fred")
+	cmd.Stdin = strings.NewReader("xxx") // Password
+	if out, err := cmd.CombinedOutput(); err != nil {
+		confErr = fmt.Errorf("saslpasswd2 failed: %s\n%s", err, out)
+		return confErr
+	}
+	confStr := "sasldb_path: " + db + "\nmech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS\n"
+	if err := ioutil.WriteFile(conf, []byte(confStr), os.ModePerm); err != nil {
+		confErr = fmt.Errorf("write conf file %s failed: %s", conf, err)
+	}
+	return confErr
+}
+
+func TestMain(m *testing.M) {
+	status := m.Run()
+	if confDir != "" {
+		os.RemoveAll(confDir)
+	}
+	os.Exit(status)
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
index 96feb1f..3bc5dcf 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
@@ -23,16 +23,34 @@ package electron
 import "C"
 
 import (
-	"fmt"
 	"net"
 	"qpid.apache.org/proton"
 	"sync"
 	"time"
 )
 
+// Settings associated with a Connection.
+type ConnectionSettings interface {
+	// Authenticated user name associated with the connection.
+	User() string
+
+	// The AMQP virtual host name for the connection.
+	//
+	// Optional, useful when the server has multiple names and provides different
+	// service based on the name the client uses to connect.
+	//
+	// By default it is set to the DNS host name that the client uses to connect,
+	// but it can be set to something different at the client side with the
+	// VirtualHost() option.
+	//
+	// Returns error if the connection fails to authenticate.
+	VirtualHost() string
+}
+
 // Connection is an AMQP connection, created by a Container.
 type Connection interface {
 	Endpoint
+	ConnectionSettings
 
 	// Sender opens a new sender on the DefaultSession.
 	Sender(...LinkOption) (Sender, error)
@@ -59,48 +77,79 @@ type Connection interface {
 	// WaitTimeout is like Wait but returns Timeout if the timeout expires.
 	WaitTimeout(time.Duration) error
 
-	// Incoming returns a channel for incoming endpoints opened by the remote end.
-	//
-	// To enable, pass AllowIncoming() when creating the Connection. Otherwise all
-	// incoming endpoint requests are automatically rejected and Incoming()
-	// returns nil.
-	//
-	// An Incoming value can be an *IncomingSession, *IncomingSender or
-	// *IncomingReceiver.  You must call Accept() to open the endpoint or Reject()
-	// to close it with an error. The specific Incoming types have additional
-	// methods to configure the endpoint.
-	//
-	// Not receiving from Incoming() or not calling Accept/Reject will block the
-	// electron event loop. Normally you would have a dedicated goroutine receive
-	// from Incoming() and start new goroutines to serve each incoming endpoint.
-	// The channel is closed when the Connection closes.
+	// Incoming returns a channel for incoming endpoints opened by the remote peer.
+	// See the Incoming interface for more.
 	//
+	// Not receiving from Incoming() and calling Accept/Reject will block the
+	// electron event loop. You should run a loop to handle the types that
+	// interest you in a switch{} and and Accept() all others.
 	Incoming() <-chan Incoming
 }
 
+type connectionSettings struct {
+	user, virtualHost string
+}
+
+func (c connectionSettings) User() string        { return c.user }
+func (c connectionSettings) VirtualHost() string { return c.virtualHost }
+
 // ConnectionOption can be passed when creating a connection to configure various options
 type ConnectionOption func(*connection)
 
-// Server returns a ConnectionOption to put the connection in server mode.
+// User returns a ConnectionOption sets the user name for a connection
+func User(user string) ConnectionOption {
+	return func(c *connection) {
+		c.user = user
+		c.pConnection.SetUser(user)
+	}
+}
+
+// VirtualHost returns a ConnectionOption to set the AMQP virtual host for the connection.
+// Only applies to outbound client connection.
+func VirtualHost(virtualHost string) ConnectionOption {
+	return func(c *connection) {
+		c.virtualHost = virtualHost
+		c.pConnection.SetHostname(virtualHost)
+	}
+}
+
+// Password returns a ConnectionOption to set the password used to establish a
+// connection.  Only applies to outbound client connection.
+//
+// The connection will erase its copy of the password from memory as soon as it
+// has been used to authenticate. If you are concerned about paswords staying in
+// memory you should never store them as strings, and should overwrite your
+// copy as soon as you are done with it.
+//
+func Password(password []byte) ConnectionOption {
+	return func(c *connection) { c.pConnection.SetPassword(password) }
+}
+
+// Server returns a ConnectionOption to put the connection in server mode for incoming connections.
 //
 // A server connection will do protocol negotiation to accept a incoming AMQP
 // connection. Normally you would call this for a connection created by
 // net.Listener.Accept()
 //
-func Server() ConnectionOption { return func(c *connection) { c.engine.Server() } }
+func Server() ConnectionOption {
+	return func(c *connection) { c.engine.Server(); c.server = true; AllowIncoming()(c) }
+}
 
-// AllowIncoming returns a ConnectionOption to enable incoming endpoint open requests.
-// See Connection.Incoming()
+// AllowIncoming returns a ConnectionOption to enable incoming endpoints, see
+// Connection.Incoming() This is automatically set for Server() connections.
 func AllowIncoming() ConnectionOption {
 	return func(c *connection) { c.incoming = make(chan Incoming) }
 }
 
 type connection struct {
 	endpoint
+	connectionSettings
+
 	defaultSessionOnce, closeOnce sync.Once
 
 	container   *container
 	conn        net.Conn
+	server      bool
 	incoming    chan Incoming
 	handler     *handler
 	engine      *proton.Engine
@@ -110,23 +159,32 @@ type connection struct {
 }
 
 func newConnection(conn net.Conn, cont *container, setting ...ConnectionOption) (*connection, error) {
-	c := &connection{container: cont, conn: conn}
+	c := &connection{
+		container: cont,
+		conn:      conn,
+	}
 	c.handler = newHandler(c)
 	var err error
 	c.engine, err = proton.NewEngine(c.conn, c.handler.delegator)
 	if err != nil {
 		return nil, err
 	}
+	c.pConnection = c.engine.Connection()
+	c.pConnection.SetContainer(cont.Id())
 	for _, set := range setting {
 		set(c)
 	}
+	globalSASLInit(c.engine)
+
 	c.endpoint.init(c.engine.String())
-	c.pConnection = c.engine.Connection()
 	go c.run()
 	return c, nil
 }
 
 func (c *connection) run() {
+	if !c.server {
+		c.pConnection.Open()
+	}
 	c.engine.Run()
 	if c.incoming != nil {
 		close(c.incoming)
@@ -201,46 +259,95 @@ func (c *connection) WaitTimeout(timeout time.Duration) error {
 	return c.Error()
 }
 
-func (c *connection) Incoming() <-chan Incoming { return c.incoming }
+func (c *connection) Incoming() <-chan Incoming {
+	assert(c.incoming != nil, "electron.Connection.Incoming() disabled for %s", c)
+	return c.incoming
+}
 
-// Incoming is the interface for incoming requests to open an endpoint.
-// Implementing types are IncomingSession, IncomingSender and IncomingReceiver.
-type Incoming interface {
-	// Accept and open the endpoint.
-	Accept() Endpoint
+type IncomingConnection struct {
+	incoming
+	connectionSettings
+	c *connection
+}
 
-	// Reject the endpoint with an error
-	Reject(error)
+func newIncomingConnection(c *connection) *IncomingConnection {
+	c.user = c.pConnection.Transport().User()
+	c.virtualHost = c.pConnection.RemoteHostname()
+	return &IncomingConnection{
+		incoming:           makeIncoming(c.pConnection),
+		connectionSettings: c.connectionSettings,
+		c:                  c}
+}
 
-	// wait for and call the accept function, call in proton goroutine.
-	wait() error
-	pEndpoint() proton.Endpoint
+func (in *IncomingConnection) Accept() Endpoint {
+	return in.accept(func() Endpoint {
+		in.c.pConnection.Open()
+		return in.c
+	})
 }
 
-type incoming struct {
-	pep      proton.Endpoint
-	acceptCh chan func() error
+func sasl(c *connection) proton.SASL { return c.engine.Transport().SASL() }
+
+// SASLEnable returns a ConnectionOption that enables SASL authentication.
+// Only required if you don't set any other SASL options.
+func SASLEnable() ConnectionOption { return func(c *connection) { sasl(c) } }
+
+// SASLAllowedMechs returns a ConnectionOption to set the list of allowed SASL
+// mechanisms.
+//
+// Can be used on the client or the server to restrict the SASL for a connection.
+// mechs is a space-separated list of mechanism names.
+//
+func SASLAllowedMechs(mechs string) ConnectionOption {
+	return func(c *connection) { sasl(c).AllowedMechs(mechs) }
 }
 
-func makeIncoming(e proton.Endpoint) incoming {
-	return incoming{pep: e, acceptCh: make(chan func() error)}
+// SASLAllowInsecure returns a ConnectionOption that allows or disallows clear
+// text SASL authentication mechanisms
+//
+// By default the SASL layer is configured not to allow mechanisms that disclose
+// the clear text of the password over an unencrypted AMQP connection. This specifically
+// will disallow the use of the PLAIN mechanism without using SSL encryption.
+//
+// This default is to avoid disclosing password information accidentally over an
+// insecure network.
+//
+func SASLAllowInsecure(b bool) ConnectionOption {
+	return func(c *connection) { sasl(c).SetAllowInsecureMechs(b) }
 }
 
-func (in *incoming) String() string   { return fmt.Sprintf("%s: %s", in.pep.Type(), in.pep) }
-func (in *incoming) Reject(err error) { in.acceptCh <- func() error { return err } }
+// GlobalSASLConfigDir sets the SASL configuration directory for every
+// Connection created in this process. If not called, the default is determined
+// by your SASL installation.
+//
+// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
+//
+func GlobalSASLConfigDir(dir string) { globalSASLConfigDir = dir }
 
-// Call in proton goroutine, wait for and call the accept function fr
-func (in *incoming) wait() error { return (<-in.acceptCh)() }
+// GlobalSASLConfigName sets the SASL configuration name for every Connection
+// created in this process. If not called the default is "proton-server".
+//
+// The complete configuration file name is
+//     <sasl-config-dir>/<sasl-config-name>.conf
+//
+// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
+//
+func GlobalSASLConfigName(dir string) { globalSASLConfigName = dir }
 
-func (in *incoming) pEndpoint() proton.Endpoint { return in.pep }
+var (
+	globalSASLConfigName string
+	globalSASLConfigDir  string
+)
 
-// Called in app goroutine to send an accept function to proton and return the resulting endpoint.
-func (in *incoming) accept(f func() Endpoint) Endpoint {
-	done := make(chan Endpoint)
-	in.acceptCh <- func() error {
-		ep := f()
-		done <- ep
-		return nil
+// TODO aconway 2016-09-15: Current pn_sasl C impl config is broken, so all we
+// can realistically offer is global configuration. Later if/when the pn_sasl C
+// impl is fixed we can offer per connection over-rides.
+func globalSASLInit(eng *proton.Engine) {
+	sasl := eng.Transport().SASL()
+	if globalSASLConfigName != "" {
+		sasl.ConfigName(globalSASLConfigName)
+	}
+	if globalSASLConfigDir != "" {
+		sasl.ConfigPath(globalSASLConfigDir)
 	}
-	return <-done
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
index b5ce6c0..1ab4df2 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/container.go
@@ -35,12 +35,17 @@ type Container interface {
 	// Id is a unique identifier for the container in your distributed application.
 	Id() string
 
-	// Create a new AMQP Connection over the supplied net.Conn connection.
+	// Enable AMQP over the supplied net.Conn. Returns a Connection endpoint.
 	//
-	// You must call Connection.Open() on the returned Connection, after
-	// setting any Connection properties you need to set. Note the net.Conn
-	// can be an outgoing connection (e.g. made with net.Dial) or an incoming
-	// connection (e.g. made with net.Listener.Accept())
+	// For client connections (e.g. established with net.Dial()), you can start
+	// using the connection immediately. Connection.Incoming() is disabled by
+	// default for clients, pass an AllowIncoming() option to enable incoming
+	// sessions and links.
+	//
+	// For server connection (e.g. established with net.Listener.Accept()) you
+	// must pass the Server() option and receive from the Connection.Incoming()
+	// channel. The first Incoming value will be an *IncomingConnection that lets
+	// you examine the connection properties before Accept() or Reject()
 	Connection(net.Conn, ...ConnectionOption) (Connection, error)
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go b/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
index 46bde37..207d8ba 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/doc.go
@@ -21,21 +21,20 @@ under the License.
 Package electron is a procedural, concurrent-safe Go library for AMQP messaging.
 You can write clients and servers using this library.
 
-Start by creating a Container with NewContainer. A Container represents a client
-or server application that can contain many incoming or outgoing connections.
+Start by creating a Container with NewContainer. An AMQP Container represents a
+single AMQP "application" and can contain client and server connections.
 
-Create connections with the standard Go 'net' package using net.Dial or
-net.Listen. Create an AMQP connection over a net.Conn with
-Container.Connection() and open it with Connection.Open().
+You can enable AMQP over any connection that implements the standard net.Conn
+interface. Typically you can connect with net.Dial() or listen for server
+connections with net.Listen.  Enable AMQP by passing the net.Conn to
+Container.Connection().
 
-AMQP sends messages over "links". Each link has a Sender end and a Receiver
-end. Connection.Sender() and Connection.Receiver() allow you to create links to
-Send() and Receive() messages.
-
-You can create an AMQP server connection by calling Connection.Server() and
-Connection.Listen() before calling Connection.Open(). A server connection can
-negotiate protocol security details and can accept incoming links opened from
-the remote end of the connection.
+AMQP allows bi-direction peer-to-peer message exchange as well as
+client-to-broker. Messages are sent over "links". Each link is one-way and has a
+Sender and Receiver end. Connection.Sender() and Connection.Receiver() open
+links to Send() and Receive() messages. Connection.Incoming() lets you accept
+incoming links opened by the remote peer. You can open and accept multiple links
+in both directions on a single Connection.
 
 */
 package electron
@@ -54,10 +53,10 @@ only accessed in the event-loop goroutine, so no locks are required there.
 The handler sets up channels as needed to get or send data from user goroutines
 using electron types like Sender or Receiver.
 
-We also use Engine.Inject to inject actions into the event loop from user
-goroutines. It is important to check at the start of an injected function that
-required objects are still valid, for example a link may be remotely closed
-between the time a Sender function calls Inject and the time the injected
-function is execute by the handler goroutine. See comments in endpoint.go for more.
+Engine.Inject injects actions into the event loop from user goroutines. It is
+important to check at the start of an injected function that required objects
+are still valid, for example a link may be remotely closed between the time a
+Sender function calls Inject and the time the injected function is execute by
+the handler goroutine.
 
 */

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
new file mode 100644
index 0000000..56b91bf
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
@@ -0,0 +1,477 @@
+/*
+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 electron
+
+import (
+	"fmt"
+	"net"
+	"path"
+	"qpid.apache.org/amqp"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func fatalIf(t *testing.T, err error) {
+	if err != nil {
+		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
+		if ok {
+			_, file = path.Split(file)
+		}
+		t.Fatalf("(from %s:%d) %v", file, line, err)
+	}
+}
+
+func errorIf(t *testing.T, err error) {
+	if err != nil {
+		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
+		if ok {
+			_, file = path.Split(file)
+		}
+		t.Errorf("(from %s:%d) %v", file, line, err)
+	}
+}
+
+func checkEqual(want interface{}, got interface{}) error {
+	if !reflect.DeepEqual(want, got) {
+		return fmt.Errorf("%#v != %#v", want, got)
+	}
+	return nil
+}
+
+// Start a server, return listening addr and channel for incoming Connections.
+func newServer(t *testing.T, cont Container, opts ...ConnectionOption) (net.Addr, <-chan Connection) {
+	listener, err := net.Listen("tcp", "")
+	fatalIf(t, err)
+	addr := listener.Addr()
+	ch := make(chan Connection)
+	go func() {
+		conn, err := listener.Accept()
+		c, err := cont.Connection(conn, append([]ConnectionOption{Server()}, opts...)...)
+		fatalIf(t, err)
+		ch <- c
+	}()
+	return addr, ch
+}
+
+// Open a client connection and session, return the session.
+func newClient(t *testing.T, cont Container, addr net.Addr, opts ...ConnectionOption) Session {
+	conn, err := net.Dial(addr.Network(), addr.String())
+	fatalIf(t, err)
+	c, err := cont.Connection(conn, opts...)
+	fatalIf(t, err)
+	sn, err := c.Session()
+	fatalIf(t, err)
+	return sn
+}
+
+// Return client and server ends of the same connection.
+func newClientServerOpts(t *testing.T, copts []ConnectionOption, sopts []ConnectionOption) (client Session, server Connection) {
+	addr, ch := newServer(t, NewContainer("test-server"), sopts...)
+	client = newClient(t, NewContainer("test-client"), addr, copts...)
+	return client, <-ch
+}
+
+// Return client and server ends of the same connection.
+func newClientServer(t *testing.T) (client Session, server Connection) {
+	return newClientServerOpts(t, nil, nil)
+}
+
+// Close client and server
+func closeClientServer(client Session, server Connection) {
+	client.Connection().Close(nil)
+	server.Close(nil)
+}
+
+// Send a message one way with a client sender and server receiver, verify ack.
+func TestClientSendServerReceive(t *testing.T) {
+	nLinks := 3
+	nMessages := 3
+
+	rchan := make(chan Receiver, nLinks)
+	client, server := newClientServer(t)
+	go func() {
+		for in := range server.Incoming() {
+			switch in := in.(type) {
+			case *IncomingReceiver:
+				in.SetCapacity(1)
+				in.SetPrefetch(false)
+				rchan <- in.Accept().(Receiver)
+			default:
+				in.Accept()
+			}
+		}
+	}()
+
+	defer func() { closeClientServer(client, server) }()
+
+	s := make([]Sender, nLinks)
+	for i := 0; i < nLinks; i++ {
+		var err error
+		s[i], err = client.Sender(Target(fmt.Sprintf("foo%d", i)))
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+	r := make([]Receiver, nLinks)
+	for i := 0; i < nLinks; i++ {
+		r[i] = <-rchan
+	}
+
+	for i := 0; i < nLinks; i++ {
+		for j := 0; j < nMessages; j++ {
+			// Client send
+			ack := make(chan Outcome, 1)
+			sendDone := make(chan struct{})
+			go func() {
+				defer close(sendDone)
+				m := amqp.NewMessageWith(fmt.Sprintf("foobar%v-%v", i, j))
+				var err error
+				s[i].SendAsync(m, ack, "testing")
+				if err != nil {
+					t.Fatal(err)
+				}
+			}()
+
+			// Server recieve
+			rm, err := r[i].Receive()
+			if err != nil {
+				t.Fatal(err)
+			}
+			if want, got := interface{}(fmt.Sprintf("foobar%v-%v", i, j)), rm.Message.Body(); want != got {
+				t.Errorf("%#v != %#v", want, got)
+			}
+
+			// Should not be acknowledged on client yet
+			<-sendDone
+			select {
+			case <-ack:
+				t.Errorf("unexpected ack")
+			default:
+			}
+
+			// Server send ack
+			if err := rm.Reject(); err != nil {
+				t.Error(err)
+			}
+			// Client get ack.
+			if a := <-ack; a.Value != "testing" || a.Error != nil || a.Status != Rejected {
+				t.Error("unexpected ack: ", a.Status, a.Error, a.Value)
+			}
+		}
+	}
+}
+
+func TestClientReceiver(t *testing.T) {
+	nMessages := 3
+	client, server := newClientServer(t)
+	go func() {
+		for in := range server.Incoming() {
+			switch in := in.(type) {
+			case *IncomingSender:
+				s := in.Accept().(Sender)
+				go func() {
+					for i := int32(0); i < int32(nMessages); i++ {
+						out := s.SendSync(amqp.NewMessageWith(i))
+						if out.Error != nil {
+							t.Error(out.Error)
+							return
+						}
+					}
+					s.Close(nil)
+				}()
+			default:
+				in.Accept()
+			}
+		}
+	}()
+
+	r, err := client.Receiver(Source("foo"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	for i := int32(0); i < int32(nMessages); i++ {
+		rm, err := r.Receive()
+		if err != nil {
+			if err != Closed {
+				t.Error(err)
+			}
+			break
+		}
+		if err := rm.Accept(); err != nil {
+			t.Error(err)
+		}
+		if b, ok := rm.Message.Body().(int32); !ok || b != i {
+			t.Errorf("want %v, true got %v, %v", i, b, ok)
+		}
+	}
+	server.Close(nil)
+	client.Connection().Close(nil)
+}
+
+// Test timeout versions of waiting functions.
+func TestTimeouts(t *testing.T) {
+	var err error
+	rchan := make(chan Receiver, 1)
+	client, server := newClientServer(t)
+	go func() {
+		for i := range server.Incoming() {
+			switch i := i.(type) {
+			case *IncomingReceiver:
+				i.SetCapacity(1)
+				i.SetPrefetch(false)
+				rchan <- i.Accept().(Receiver) // Issue credit only on receive
+			default:
+				i.Accept()
+			}
+		}
+	}()
+	defer func() { closeClientServer(client, server) }()
+
+	// Open client sender
+	snd, err := client.Sender(Target("test"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	rcv := <-rchan
+
+	// Test send with timeout
+	short := time.Millisecond
+	long := time.Second
+	m := amqp.NewMessage()
+	if err := snd.SendSyncTimeout(m, 0).Error; err != Timeout { // No credit, expect timeout.
+		t.Error("want Timeout got", err)
+	}
+	if err := snd.SendSyncTimeout(m, short).Error; err != Timeout { // No credit, expect timeout.
+		t.Error("want Timeout got", err)
+	}
+	// Test receive with timeout
+	if _, err = rcv.ReceiveTimeout(0); err != Timeout { // No credit, expect timeout.
+		t.Error("want Timeout got", err)
+	}
+	// Test receive with timeout
+	if _, err = rcv.ReceiveTimeout(short); err != Timeout { // No credit, expect timeout.
+		t.Error("want Timeout got", err)
+	}
+	// There is now a credit on the link due to receive
+	ack := make(chan Outcome)
+	snd.SendAsyncTimeout(m, ack, nil, short)
+	// Disposition should timeout
+	select {
+	case <-ack:
+		t.Errorf("want Timeout got %#v", ack)
+	case <-time.After(short):
+	}
+
+	// Receive and accept
+	rm, err := rcv.ReceiveTimeout(long)
+	if err != nil {
+		t.Fatal(err)
+	}
+	rm.Accept()
+	// Sender get ack
+	if a := <-ack; a.Status != Accepted || a.Error != nil {
+		t.Errorf("want (accepted, nil) got %#v", a)
+	}
+}
+
+// A server that returns the opposite end of each client link via channels.
+type pairs struct {
+	t        *testing.T
+	client   Session
+	server   Connection
+	rchan    chan Receiver
+	schan    chan Sender
+	capacity int
+	prefetch bool
+}
+
+func newPairs(t *testing.T, capacity int, prefetch bool) *pairs {
+	p := &pairs{t: t, rchan: make(chan Receiver, 1), schan: make(chan Sender, 1)}
+	p.client, p.server = newClientServer(t)
+	go func() {
+		for i := range p.server.Incoming() {
+			switch i := i.(type) {
+			case *IncomingReceiver:
+				i.SetCapacity(capacity)
+				i.SetPrefetch(prefetch)
+				p.rchan <- i.Accept().(Receiver)
+			case *IncomingSender:
+				p.schan <- i.Accept().(Sender)
+			default:
+				i.Accept()
+			}
+		}
+	}()
+	return p
+}
+
+func (p *pairs) close() {
+	closeClientServer(p.client, p.server)
+}
+
+// Return a client sender and server receiver
+func (p *pairs) senderReceiver() (Sender, Receiver) {
+	snd, err := p.client.Sender()
+	fatalIf(p.t, err)
+	rcv := <-p.rchan
+	return snd, rcv
+}
+
+// Return a client receiver and server sender
+func (p *pairs) receiverSender() (Receiver, Sender) {
+	rcv, err := p.client.Receiver()
+	fatalIf(p.t, err)
+	snd := <-p.schan
+	return rcv, snd
+}
+
+type result struct {
+	label string
+	err   error
+	value interface{}
+}
+
+func (r result) String() string { return fmt.Sprintf("%v(%v)", r.err, r.label) }
+
+func doSend(snd Sender, results chan result) {
+	err := snd.SendSync(amqp.NewMessage()).Error
+	results <- result{"send", err, nil}
+}
+
+func doReceive(rcv Receiver, results chan result) {
+	msg, err := rcv.Receive()
+	results <- result{"receive", err, msg}
+}
+
+func doDisposition(ack <-chan Outcome, results chan result) {
+	results <- result{"disposition", (<-ack).Error, nil}
+}
+
+// Senders get credit immediately if receivers have prefetch set
+func TestSendReceivePrefetch(t *testing.T) {
+	pairs := newPairs(t, 1, true)
+	s, r := pairs.senderReceiver()
+	s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should not block for credit.
+	if _, err := r.Receive(); err != nil {
+		t.Error(err)
+	}
+}
+
+// Senders do not get credit till Receive() if receivers don't have prefetch
+func TestSendReceiveNoPrefetch(t *testing.T) {
+	pairs := newPairs(t, 1, false)
+	s, r := pairs.senderReceiver()
+	done := make(chan struct{}, 1)
+	go func() {
+		s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should block for credit.
+		close(done)
+	}()
+	select {
+	case <-done:
+		t.Errorf("send should be blocked on credit")
+	default:
+		if _, err := r.Receive(); err != nil {
+			t.Error(err)
+		} else {
+			<-done
+		} // Should be unblocked now
+	}
+}
+
+// Test that closing Links interrupts blocked link functions.
+func TestLinkCloseInterrupt(t *testing.T) {
+	want := amqp.Error{Name: "x", Description: "all bad"}
+	pairs := newPairs(t, 1, false)
+	results := make(chan result) // Collect expected errors
+
+	// Note closing the link does not interrupt Send() calls, the AMQP spec says
+	// that deliveries can be settled after the link is closed.
+
+	// Receiver.Close() interrupts Receive()
+	snd, rcv := pairs.senderReceiver()
+	go doReceive(rcv, results)
+	rcv.Close(want)
+	if r := <-results; want != r.err {
+		t.Errorf("want %#v got %#v", want, r)
+	}
+
+	// Remote Sender.Close() interrupts Receive()
+	snd, rcv = pairs.senderReceiver()
+	go doReceive(rcv, results)
+	snd.Close(want)
+	if r := <-results; want != r.err {
+		t.Errorf("want %#v got %#v", want, r)
+	}
+}
+
+// Test closing the server end of a connection.
+func TestConnectionCloseInterrupt1(t *testing.T) {
+	want := amqp.Error{Name: "x", Description: "bad"}
+	pairs := newPairs(t, 1, true)
+	results := make(chan result) // Collect expected errors
+
+	// Connection.Close() interrupts Send, Receive, Disposition.
+	snd, rcv := pairs.senderReceiver()
+	go doSend(snd, results)
+
+	rcv.Receive()
+	rcv, snd = pairs.receiverSender()
+	go doReceive(rcv, results)
+
+	snd, rcv = pairs.senderReceiver()
+	ack := snd.SendWaitable(amqp.NewMessage())
+	rcv.Receive()
+	go doDisposition(ack, results)
+
+	pairs.server.Close(want)
+	for i := 0; i < 3; i++ {
+		if r := <-results; want != r.err {
+			t.Errorf("want %v got %v", want, r)
+		}
+	}
+}
+
+// Test closing the client end of the connection.
+func TestConnectionCloseInterrupt2(t *testing.T) {
+	want := amqp.Error{Name: "x", Description: "bad"}
+	pairs := newPairs(t, 1, true)
+	results := make(chan result) // Collect expected errors
+
+	// Connection.Close() interrupts Send, Receive, Disposition.
+	snd, rcv := pairs.senderReceiver()
+	go doSend(snd, results)
+	rcv.Receive()
+
+	rcv, snd = pairs.receiverSender()
+	go doReceive(rcv, results)
+
+	snd, rcv = pairs.senderReceiver()
+	ack := snd.SendWaitable(amqp.NewMessage())
+	go doDisposition(ack, results)
+
+	pairs.client.Connection().Close(want)
+	for i := 0; i < 3; i++ {
+		if r := <-results; want != r.err {
+			t.Errorf("want %v got %v", want, r.err)
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/endpoint.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/endpoint.go b/proton-c/bindings/go/src/qpid.apache.org/electron/endpoint.go
index fc701c6..ca93e5b 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/endpoint.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/endpoint.go
@@ -20,6 +20,7 @@ under the License.
 package electron
 
 import (
+	"fmt"
 	"io"
 	"qpid.apache.org/proton"
 )
@@ -28,12 +29,13 @@ import (
 // was closed cleanly.
 var Closed = io.EOF
 
-// Endpoint is the common interface for Connection, Session, Link, Sender and Receiver.
+// Endpoint is the local end of a communications channel to the remote peer
+// process.  The following interface implement Endpoint: Connection, Session,
+// Sender and Receiver.
 //
-// Endpoints can be created locally or by the remote peer. You must Open() an
-// endpoint before you can use it. Some endpoints have additional Set*() methods
-// that must be called before Open() to take effect, see Connection, Session,
-// Link, Sender and Receiver for details.
+// You can create an endpoint with functions on Container, Connection and
+// Session. You can accept incoming endpoints from the remote peer using
+// Connection.Incoming()
 //
 type Endpoint interface {
 	// Close an endpoint and signal an error to the remote end if error != nil.
@@ -46,35 +48,58 @@ type Endpoint interface {
 	// Error() == Closed means the endpoint was closed without error.
 	Error() error
 
-	// Connection containing the endpoint
+	// Connection is the connection associated with this endpoint.
 	Connection() Connection
 
 	// Done returns a channel that will close when the endpoint closes.
-	// Error() will contain the reason.
+	// After Done() has closed, Error() will return the reason for closing.
 	Done() <-chan struct{}
 
+	// Sync() waits for the remote peer to confirm the endpoint is active or
+	// reject it with an error. You can call it immediately on new endpoints
+	// for more predictable error handling.
+	//
+	// AMQP is an asynchronous protocol. It is legal to create an endpoint and
+	// start using it without waiting for confirmation. This avoids a needless
+	// delay in the non-error case and throughput by "assuming the best".
+	//
+	// However if there *is* an error, these "optimistic" actions will fail. The
+	// endpoint and its children will be closed with an error. The error will only
+	// be detected when you try to use one of these endpoints or call Sync()
+	Sync() error
+
 	// Called in handler goroutine when endpoint is remotely closed.
 	closed(err error) error
+	wakeSync()
 }
 
-// DEVELOPER NOTES
-//
-// An electron.Endpoint corresponds to a proton.Endpoint, which can be invalidated
-//
+// Base implementation for Endpoint
 type endpoint struct {
-	err  proton.ErrorHolder
-	str  string // Must be set by the value that embeds endpoint.
-	done chan struct{}
+	err    proton.ErrorHolder
+	str    string // String() return value.
+	done   chan struct{}
+	active chan struct{}
 }
 
-func (e *endpoint) init(s string) { e.str = s; e.done = make(chan struct{}) }
+func (e *endpoint) init(s string) {
+	e.str = s
+	e.done = make(chan struct{})
+	e.active = make(chan struct{})
+}
+
+// Called in proton goroutine on remote open.
+func (e *endpoint) wakeSync() {
+	select { // Close active channel if not already closed.
+	case <-e.active:
+	default:
+		close(e.active)
+	}
+}
 
-// Called in handler on a Closed event. Marks the endpoint as closed and the corresponding
-// proton.Endpoint pointer as invalid. Injected functions should check Error() to ensure
-// the pointer has not been invalidated.
+// Called in proton goroutine (from handler) on a Closed or Disconnected event.
 //
-// Returns the error stored on the endpoint, which may not be different to err if there was
-// already a n error
+// Set err if there is not already an error on the endpoint.
+// Return Error()
 func (e *endpoint) closed(err error) error {
 	select {
 	case <-e.done:
@@ -82,9 +107,10 @@ func (e *endpoint) closed(err error) error {
 	default:
 		e.err.Set(err)
 		e.err.Set(Closed)
+		e.wakeSync() // Make sure we wake up Sync()
 		close(e.done)
 	}
-	return e.err.Get()
+	return e.Error()
 }
 
 func (e *endpoint) String() string { return e.str }
@@ -93,6 +119,11 @@ func (e *endpoint) Error() error { return e.err.Get() }
 
 func (e *endpoint) Done() <-chan struct{} { return e.done }
 
+func (e *endpoint) Sync() error {
+	<-e.active
+	return e.Error()
+}
+
 // Call in proton goroutine to initiate closing an endpoint locally
 // handler will complete the close when remote end closes.
 func localClose(ep proton.Endpoint, err error) {
@@ -100,3 +131,52 @@ func localClose(ep proton.Endpoint, err error) {
 		proton.CloseError(ep, err)
 	}
 }
+
+// Incoming is the interface for incoming endpoints, see Connection.Incoming()
+//
+// Call Incoming.Accept() to open the endpoint or Incoming.Reject() to close it
+// with optional error
+//
+// Implementing types are *IncomingConnection, *IncomingSession, *IncomingSender
+// and *IncomingReceiver. Each type provides methods to examine the incoming
+// endpoint request and set configuration options for the local endpoint
+// before calling Accept() or Reject()
+type Incoming interface {
+	// Accept and open the endpoint.
+	Accept() Endpoint
+
+	// Reject the endpoint with an error
+	Reject(error)
+
+	// wait for and call the accept function, call in proton goroutine.
+	wait() error
+	pEndpoint() proton.Endpoint
+}
+
+type incoming struct {
+	pep      proton.Endpoint
+	acceptCh chan func() error
+}
+
+func makeIncoming(e proton.Endpoint) incoming {
+	return incoming{pep: e, acceptCh: make(chan func() error)}
+}
+
+func (in *incoming) String() string   { return fmt.Sprintf("%s: %s", in.pep.Type(), in.pep) }
+func (in *incoming) Reject(err error) { in.acceptCh <- func() error { return err } }
+
+// Call in proton goroutine, wait for and call the accept function.
+func (in *incoming) wait() error { return (<-in.acceptCh)() }
+
+func (in *incoming) pEndpoint() proton.Endpoint { return in.pep }
+
+// Called in app goroutine to send an accept function to proton and return the resulting endpoint.
+func (in *incoming) accept(f func() Endpoint) Endpoint {
+	done := make(chan Endpoint)
+	in.acceptCh <- func() error {
+		ep := f()
+		done <- ep
+		return nil
+	}
+	return <-done
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
index eb53df3..ede7b6c 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
@@ -78,28 +78,38 @@ func (h *handler) HandleMessagingEvent(t proton.MessagingEvent, e proton.Event)
 			h.linkError(e.Link(), "no sender")
 		}
 
+	case proton.MConnectionOpening:
+		if e.Connection().State().LocalUninit() { // Remotely opened
+			h.incoming(newIncomingConnection(h.connection))
+		}
+		h.connection.wakeSync()
+
 	case proton.MSessionOpening:
 		if e.Session().State().LocalUninit() { // Remotely opened
 			h.incoming(newIncomingSession(h, e.Session()))
 		}
+		h.sessions[e.Session()].wakeSync()
 
 	case proton.MSessionClosed:
 		h.sessionClosed(e.Session(), proton.EndpointError(e.Session()))
 
 	case proton.MLinkOpening:
 		l := e.Link()
-		if l.State().LocalActive() { // Already opened locally.
-			break
-		}
-		ss := h.sessions[l.Session()]
-		if ss == nil {
-			h.linkError(e.Link(), "no session")
-			break
-		}
-		if l.IsReceiver() {
-			h.incoming(&IncomingReceiver{makeIncomingLink(ss, l)})
+		if ss := h.sessions[l.Session()]; ss != nil {
+			if l.State().LocalUninit() { // Remotely opened.
+				if l.IsReceiver() {
+					h.incoming(newIncomingReceiver(ss, l))
+				} else {
+					h.incoming(newIncomingSender(ss, l))
+				}
+			}
+			if ep, ok := h.links[l]; ok {
+				ep.wakeSync()
+			} else {
+				h.linkError(l, "no link")
+			}
 		} else {
-			h.incoming(&IncomingSender{makeIncomingLink(ss, l)})
+			h.linkError(l, "no session")
 		}
 
 	case proton.MLinkClosing:
@@ -112,27 +122,14 @@ func (h *handler) HandleMessagingEvent(t proton.MessagingEvent, e proton.Event)
 		h.connection.err.Set(e.Connection().RemoteCondition().Error())
 
 	case proton.MConnectionClosed:
-		h.connectionClosed(proton.EndpointError(e.Connection()))
+		h.shutdown(proton.EndpointError(e.Connection()))
 
 	case proton.MDisconnected:
-		h.connection.err.Set(e.Transport().Condition().Error())
-		// If err not set at this point (e.g. to Closed) then this is unexpected.
-		h.connection.err.Set(amqp.Errorf(amqp.IllegalState, "unexpected disconnect on %s", h.connection))
-
-		err := h.connection.Error()
-
-		for l, _ := range h.links {
-			h.linkClosed(l, err)
-		}
-		h.links = nil
-		for _, s := range h.sessions {
-			s.closed(err)
-		}
-		h.sessions = nil
-		for _, sm := range h.sentMessages {
-			sm.ack <- Outcome{Unacknowledged, err, sm.value}
+		err := e.Transport().Condition().Error()
+		if err == nil {
+			err = amqp.Errorf(amqp.IllegalState, "unexpected disconnect on %s", h.connection)
 		}
-		h.sentMessages = nil
+		h.shutdown(err)
 	}
 }
 
@@ -175,13 +172,26 @@ func (h *handler) sessionClosed(ps proton.Session, err error) {
 	}
 }
 
-func (h *handler) connectionClosed(err error) {
+func (h *handler) shutdown(err error) {
 	err = h.connection.closed(err)
-	// Close links first to avoid repeated scans of the link list by sessions.
-	for l, _ := range h.links {
-		h.linkClosed(l, err)
+	for _, sm := range h.sentMessages {
+		// Don't block but ensure outcome is sent eventually.
+		if sm.ack != nil {
+			o := Outcome{Unacknowledged, err, sm.value}
+			select {
+			case sm.ack <- o:
+			default:
+				go func(ack chan<- Outcome) { ack <- o }(sm.ack) // Deliver it eventually
+			}
+		}
+	}
+	h.sentMessages = nil
+	for _, l := range h.links {
+		l.closed(err)
 	}
-	for s, _ := range h.sessions {
-		h.sessionClosed(s, err)
+	h.links = nil
+	for _, s := range h.sessions {
+		s.closed(err)
 	}
+	h.sessions = nil
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/link.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/link.go b/proton-c/bindings/go/src/qpid.apache.org/electron/link.go
index 5d78a14..e0f6cb4 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/link.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/link.go
@@ -182,31 +182,19 @@ func makeLocalLink(sn *session, isSender bool, setting ...LinkOption) (linkSetti
 	return l, nil
 }
 
-type incomingLink struct {
-	incoming
-	linkSettings
-	pLink proton.Link
-	sn    *session
-}
-
-// Set up a link from an incoming proton.Link.
-func makeIncomingLink(sn *session, pLink proton.Link) incomingLink {
-	l := incomingLink{
-		incoming: makeIncoming(pLink),
-		linkSettings: linkSettings{
-			isSender:  pLink.IsSender(),
-			source:    pLink.RemoteSource().Address(),
-			target:    pLink.RemoteTarget().Address(),
-			linkName:  pLink.Name(),
-			sndSettle: SndSettleMode(pLink.RemoteSndSettleMode()),
-			rcvSettle: RcvSettleMode(pLink.RemoteRcvSettleMode()),
-			capacity:  1,
-			prefetch:  false,
-			pLink:     pLink,
-			session:   sn,
-		},
+func makeIncomingLinkSettings(pLink proton.Link, sn *session) linkSettings {
+	return linkSettings{
+		isSender:  pLink.IsSender(),
+		source:    pLink.RemoteSource().Address(),
+		target:    pLink.RemoteTarget().Address(),
+		linkName:  pLink.Name(),
+		sndSettle: SndSettleMode(pLink.RemoteSndSettleMode()),
+		rcvSettle: RcvSettleMode(pLink.RemoteRcvSettleMode()),
+		capacity:  1,
+		prefetch:  false,
+		pLink:     pLink,
+		session:   sn,
 	}
-	return l
 }
 
 // Not part of Link interface but use by Sender and Receiver.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
deleted file mode 100644
index c5c351a..0000000
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/messaging_test.go
+++ /dev/null
@@ -1,454 +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.
-*/
-
-package electron
-
-import (
-	"fmt"
-	"net"
-	"path"
-	"qpid.apache.org/amqp"
-	"runtime"
-	"testing"
-	"time"
-)
-
-func fatalIf(t *testing.T, err error) {
-	if err != nil {
-		_, file, line, ok := runtime.Caller(1) // annotate with location of caller.
-		if ok {
-			_, file = path.Split(file)
-		}
-		t.Fatalf("(from %s:%d) %v", file, line, err)
-	}
-}
-
-// Start a server, return listening addr and channel for incoming Connections.
-func newServer(t *testing.T, cont Container) (net.Addr, <-chan Connection) {
-	listener, err := net.Listen("tcp", "")
-	fatalIf(t, err)
-	addr := listener.Addr()
-	ch := make(chan Connection)
-	go func() {
-		conn, err := listener.Accept()
-		c, err := cont.Connection(conn, Server(), AllowIncoming())
-		fatalIf(t, err)
-		ch <- c
-	}()
-	return addr, ch
-}
-
-// Open a client connection and session, return the session.
-func newClient(t *testing.T, cont Container, addr net.Addr) Session {
-	conn, err := net.Dial(addr.Network(), addr.String())
-	fatalIf(t, err)
-	c, err := cont.Connection(conn)
-	fatalIf(t, err)
-	sn, err := c.Session()
-	fatalIf(t, err)
-	return sn
-}
-
-// Return client and server ends of the same connection.
-func newClientServer(t *testing.T) (client Session, server Connection) {
-	addr, ch := newServer(t, NewContainer("test-server"))
-	client = newClient(t, NewContainer("test-client"), addr)
-	return client, <-ch
-}
-
-// Close client and server
-func closeClientServer(client Session, server Connection) {
-	client.Connection().Close(nil)
-	server.Close(nil)
-}
-
-// Send a message one way with a client sender and server receiver, verify ack.
-func TestClientSendServerReceive(t *testing.T) {
-	nLinks := 3
-	nMessages := 3
-
-	rchan := make(chan Receiver, nLinks)
-	client, server := newClientServer(t)
-	go func() {
-		for in := range server.Incoming() {
-			switch in := in.(type) {
-			case *IncomingReceiver:
-				in.SetCapacity(1)
-				in.SetPrefetch(false)
-				rchan <- in.Accept().(Receiver)
-			default:
-				in.Accept()
-			}
-		}
-	}()
-
-	defer func() { closeClientServer(client, server) }()
-
-	s := make([]Sender, nLinks)
-	for i := 0; i < nLinks; i++ {
-		var err error
-		s[i], err = client.Sender(Target(fmt.Sprintf("foo%d", i)))
-		if err != nil {
-			t.Fatal(err)
-		}
-	}
-	r := make([]Receiver, nLinks)
-	for i := 0; i < nLinks; i++ {
-		r[i] = <-rchan
-	}
-
-	for i := 0; i < nLinks; i++ {
-		for j := 0; j < nMessages; j++ {
-			// Client send
-			ack := make(chan Outcome, 1)
-			sendDone := make(chan struct{})
-			go func() {
-				defer close(sendDone)
-				m := amqp.NewMessageWith(fmt.Sprintf("foobar%v-%v", i, j))
-				var err error
-				s[i].SendAsync(m, ack, "testing")
-				if err != nil {
-					t.Fatal(err)
-				}
-			}()
-
-			// Server recieve
-			rm, err := r[i].Receive()
-			if err != nil {
-				t.Fatal(err)
-			}
-			if want, got := interface{}(fmt.Sprintf("foobar%v-%v", i, j)), rm.Message.Body(); want != got {
-				t.Errorf("%#v != %#v", want, got)
-			}
-
-			// Should not be acknowledged on client yet
-			<-sendDone
-			select {
-			case <-ack:
-				t.Errorf("unexpected ack")
-			default:
-			}
-
-			// Server send ack
-			if err := rm.Reject(); err != nil {
-				t.Error(err)
-			}
-			// Client get ack.
-			if a := <-ack; a.Value != "testing" || a.Error != nil || a.Status != Rejected {
-				t.Error("unexpected ack: ", a.Status, a.Error, a.Value)
-			}
-		}
-	}
-}
-
-func TestClientReceiver(t *testing.T) {
-	nMessages := 3
-	client, server := newClientServer(t)
-	go func() {
-		for in := range server.Incoming() {
-			switch in := in.(type) {
-			case *IncomingSender:
-				s := in.Accept().(Sender)
-				go func() {
-					for i := int32(0); i < int32(nMessages); i++ {
-						out := s.SendSync(amqp.NewMessageWith(i))
-						if out.Error != nil {
-							t.Error(out.Error)
-							return
-						}
-					}
-					s.Close(nil)
-				}()
-			default:
-				in.Accept()
-			}
-		}
-	}()
-
-	r, err := client.Receiver(Source("foo"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i := int32(0); i < int32(nMessages); i++ {
-		rm, err := r.Receive()
-		if err != nil {
-			if err != Closed {
-				t.Error(err)
-			}
-			break
-		}
-		if err := rm.Accept(); err != nil {
-			t.Error(err)
-		}
-		if b, ok := rm.Message.Body().(int32); !ok || b != i {
-			t.Errorf("want %v, true got %v, %v", i, b, ok)
-		}
-	}
-	server.Close(nil)
-	client.Connection().Close(nil)
-}
-
-// Test timeout versions of waiting functions.
-func TestTimeouts(t *testing.T) {
-	var err error
-	rchan := make(chan Receiver, 1)
-	client, server := newClientServer(t)
-	go func() {
-		for i := range server.Incoming() {
-			switch i := i.(type) {
-			case *IncomingReceiver:
-				i.SetCapacity(1)
-				i.SetPrefetch(false)
-				rchan <- i.Accept().(Receiver) // Issue credit only on receive
-			default:
-				i.Accept()
-			}
-		}
-	}()
-	defer func() { closeClientServer(client, server) }()
-
-	// Open client sender
-	snd, err := client.Sender(Target("test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	rcv := <-rchan
-
-	// Test send with timeout
-	short := time.Millisecond
-	long := time.Second
-	m := amqp.NewMessage()
-	if err := snd.SendSyncTimeout(m, 0).Error; err != Timeout { // No credit, expect timeout.
-		t.Error("want Timeout got", err)
-	}
-	if err := snd.SendSyncTimeout(m, short).Error; err != Timeout { // No credit, expect timeout.
-		t.Error("want Timeout got", err)
-	}
-	// Test receive with timeout
-	if _, err = rcv.ReceiveTimeout(0); err != Timeout { // No credit, expect timeout.
-		t.Error("want Timeout got", err)
-	}
-	// Test receive with timeout
-	if _, err = rcv.ReceiveTimeout(short); err != Timeout { // No credit, expect timeout.
-		t.Error("want Timeout got", err)
-	}
-	// There is now a credit on the link due to receive
-	ack := make(chan Outcome)
-	snd.SendAsyncTimeout(m, ack, nil, short)
-	// Disposition should timeout
-	select {
-	case <-ack:
-		t.Errorf("want Timeout got %#v", ack)
-	case <-time.After(short):
-	}
-
-	// Receive and accept
-	rm, err := rcv.ReceiveTimeout(long)
-	if err != nil {
-		t.Fatal(err)
-	}
-	rm.Accept()
-	// Sender get ack
-	if a := <-ack; a.Status != Accepted || a.Error != nil {
-		t.Errorf("want (accepted, nil) got %#v", a)
-	}
-}
-
-// A server that returns the opposite end of each client link via channels.
-type pairs struct {
-	t        *testing.T
-	client   Session
-	server   Connection
-	rchan    chan Receiver
-	schan    chan Sender
-	capacity int
-	prefetch bool
-}
-
-func newPairs(t *testing.T, capacity int, prefetch bool) *pairs {
-	p := &pairs{t: t, rchan: make(chan Receiver, 1), schan: make(chan Sender, 1)}
-	p.client, p.server = newClientServer(t)
-	go func() {
-		for i := range p.server.Incoming() {
-			switch i := i.(type) {
-			case *IncomingReceiver:
-				i.SetCapacity(capacity)
-				i.SetPrefetch(prefetch)
-				p.rchan <- i.Accept().(Receiver)
-			case *IncomingSender:
-				p.schan <- i.Accept().(Sender)
-			default:
-				i.Accept()
-			}
-		}
-	}()
-	return p
-}
-
-func (p *pairs) close() {
-	closeClientServer(p.client, p.server)
-}
-
-// Return a client sender and server receiver
-func (p *pairs) senderReceiver() (Sender, Receiver) {
-	snd, err := p.client.Sender()
-	fatalIf(p.t, err)
-	rcv := <-p.rchan
-	return snd, rcv
-}
-
-// Return a client receiver and server sender
-func (p *pairs) receiverSender() (Receiver, Sender) {
-	rcv, err := p.client.Receiver()
-	fatalIf(p.t, err)
-	snd := <-p.schan
-	return rcv, snd
-}
-
-type result struct {
-	label string
-	err   error
-	value interface{}
-}
-
-func (r result) String() string { return fmt.Sprintf("%v(%v)", r.err, r.label) }
-
-func doSend(snd Sender, results chan result) {
-	err := snd.SendSync(amqp.NewMessage()).Error
-	results <- result{"send", err, nil}
-}
-
-func doReceive(rcv Receiver, results chan result) {
-	msg, err := rcv.Receive()
-	results <- result{"receive", err, msg}
-}
-
-func doDisposition(ack <-chan Outcome, results chan result) {
-	results <- result{"disposition", (<-ack).Error, nil}
-}
-
-// Senders get credit immediately if receivers have prefetch set
-func TestSendReceivePrefetch(t *testing.T) {
-	pairs := newPairs(t, 1, true)
-	s, r := pairs.senderReceiver()
-	s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should not block for credit.
-	if _, err := r.Receive(); err != nil {
-		t.Error(err)
-	}
-}
-
-// Senders do not get credit till Receive() if receivers don't have prefetch
-func TestSendReceiveNoPrefetch(t *testing.T) {
-	pairs := newPairs(t, 1, false)
-	s, r := pairs.senderReceiver()
-	done := make(chan struct{}, 1)
-	go func() {
-		s.SendAsyncTimeout(amqp.NewMessage(), nil, nil, time.Second) // Should block for credit.
-		close(done)
-	}()
-	select {
-	case <-done:
-		t.Errorf("send should be blocked on credit")
-	default:
-		if _, err := r.Receive(); err != nil {
-			t.Error(err)
-		} else {
-			<-done
-		} // Should be unblocked now
-	}
-}
-
-// Test that closing Links interrupts blocked link functions.
-func TestLinkCloseInterrupt(t *testing.T) {
-	want := amqp.Error{Name: "x", Description: "all bad"}
-	pairs := newPairs(t, 1, false)
-	results := make(chan result) // Collect expected errors
-
-	// Note closing the link does not interrupt Send() calls, the AMQP spec says
-	// that deliveries can be settled after the link is closed.
-
-	// Receiver.Close() interrupts Receive()
-	snd, rcv := pairs.senderReceiver()
-	go doReceive(rcv, results)
-	rcv.Close(want)
-	if r := <-results; want != r.err {
-		t.Errorf("want %#v got %#v", want, r)
-	}
-
-	// Remote Sender.Close() interrupts Receive()
-	snd, rcv = pairs.senderReceiver()
-	go doReceive(rcv, results)
-	snd.Close(want)
-	if r := <-results; want != r.err {
-		t.Errorf("want %#v got %#v", want, r)
-	}
-}
-
-// Test closing the server end of a connection.
-func TestConnectionCloseInterrupt1(t *testing.T) {
-	want := amqp.Error{Name: "x", Description: "bad"}
-	pairs := newPairs(t, 1, true)
-	results := make(chan result) // Collect expected errors
-
-	// Connection.Close() interrupts Send, Receive, Disposition.
-	snd, rcv := pairs.senderReceiver()
-	go doSend(snd, results)
-
-	rcv.Receive()
-	rcv, snd = pairs.receiverSender()
-	go doReceive(rcv, results)
-
-	snd, rcv = pairs.senderReceiver()
-	ack := snd.SendWaitable(amqp.NewMessage())
-	rcv.Receive()
-	go doDisposition(ack, results)
-
-	pairs.server.Close(want)
-	for i := 0; i < 3; i++ {
-		if r := <-results; want != r.err {
-			t.Errorf("want %v got %v", want, r)
-		}
-	}
-}
-
-// Test closing the client end of the connection.
-func TestConnectionCloseInterrupt2(t *testing.T) {
-	want := amqp.Error{Name: "x", Description: "bad"}
-	pairs := newPairs(t, 1, true)
-	results := make(chan result) // Collect expected errors
-
-	// Connection.Close() interrupts Send, Receive, Disposition.
-	snd, rcv := pairs.senderReceiver()
-	go doSend(snd, results)
-	rcv.Receive()
-
-	rcv, snd = pairs.receiverSender()
-	go doReceive(rcv, results)
-
-	snd, rcv = pairs.senderReceiver()
-	ack := snd.SendWaitable(amqp.NewMessage())
-	go doDisposition(ack, results)
-
-	pairs.client.Connection().Close(want)
-	for i := 0; i < 3; i++ {
-		if r := <-results; want != r.err {
-			t.Errorf("want %v got %v", want, r.err)
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go b/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
index 606e4d6..fb234e2 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/receiver.go
@@ -213,7 +213,15 @@ func (rm *ReceivedMessage) Release() error { return rm.acknowledge(proton.Releas
 // IncomingReceiver is sent on the Connection.Incoming() channel when there is
 // an incoming request to open a receiver link.
 type IncomingReceiver struct {
-	incomingLink
+	incoming
+	linkSettings
+}
+
+func newIncomingReceiver(sn *session, pLink proton.Link) *IncomingReceiver {
+	return &IncomingReceiver{
+		incoming:     makeIncoming(pLink),
+		linkSettings: makeIncomingLinkSettings(pLink, sn),
+	}
 }
 
 // SetCapacity sets the capacity of the incoming receiver, call before Accept()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go b/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
index 1d0fc60..8badf35 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/sender.go
@@ -259,7 +259,15 @@ type sentMessage struct {
 // IncomingSender is sent on the Connection.Incoming() channel when there is
 // an incoming request to open a sender link.
 type IncomingSender struct {
-	incomingLink
+	incoming
+	linkSettings
+}
+
+func newIncomingSender(sn *session, pLink proton.Link) *IncomingSender {
+	return &IncomingSender{
+		incoming:     makeIncoming(pLink),
+		linkSettings: makeIncomingLinkSettings(pLink, sn),
+	}
 }
 
 // Accept accepts an incoming sender endpoint

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index bfcb41c..d9dcefd 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -127,9 +127,6 @@ func NewEngine(conn net.Conn, handlers ...EventHandler) (*Engine, error) {
 	if pnErr := C.pn_connection_engine_init(&eng.engine); pnErr != 0 {
 		return nil, fmt.Errorf("cannot setup engine: %s", PnErrorCode(pnErr))
 	}
-	// Unique container-id by default.
-	eng.Connection().SetContainer(UUID4().String()) // FIXME aconway 2016-06-21:
-	eng.Connection().Open()
 	return eng, nil
 }
 
@@ -143,12 +140,6 @@ func byteSlice(data unsafe.Pointer, size C.size_t) []byte {
 	}
 }
 
-func (eng *Engine) buffers() ([]byte, []byte) {
-	r := C.pn_connection_engine_read_buffer(&eng.engine)
-	w := C.pn_connection_engine_write_buffer(&eng.engine)
-	return byteSlice(unsafe.Pointer(r.start), r.size), byteSlice(unsafe.Pointer(w.start), w.size)
-}
-
 func (eng *Engine) Connection() Connection {
 	return Connection{C.pn_connection_engine_connection(&eng.engine)}
 }
@@ -158,11 +149,12 @@ func (eng *Engine) Transport() Transport {
 }
 
 func (eng *Engine) String() string {
-	return fmt.Sprintf("%s-%s", eng.conn.LocalAddr(), eng.conn.RemoteAddr())
+	return fmt.Sprintf("[%s]%s-%s", eng.Id(), eng.conn.LocalAddr(), eng.conn.RemoteAddr())
 }
 
 func (eng *Engine) Id() string {
-	return fmt.Sprintf("%p", eng)
+	// Use transport address to match default PN_TRACE_FRM=1 output.
+	return fmt.Sprintf("%p", eng.Transport().CPtr())
 }
 
 func (eng *Engine) Error() error {
@@ -213,8 +205,7 @@ func (eng *Engine) InjectWait(f func() error) error {
 //
 func (eng *Engine) Server() { eng.Transport().SetServer() }
 
-// FIXME aconway 2016-06-21: rename
-func (eng *Engine) disconnect() { // FIXME aconway 2016-06-21: disconnected
+func (eng *Engine) disconnect() {
 	eng.conn.Close()
 	C.pn_connection_engine_disconnected(&eng.engine)
 }
@@ -244,12 +235,35 @@ func (eng *Engine) Disconnect(err error) {
 	<-eng.running
 }
 
+func (eng *Engine) dispatch() bool {
+	for {
+		if cevent := C.pn_connection_engine_dispatch(&eng.engine); cevent != nil {
+			event := makeEvent(cevent, eng)
+			for _, h := range eng.handlers {
+				h.HandleEvent(event)
+			}
+		} else {
+			break
+		}
+	}
+	return !bool(C.pn_connection_engine_finished(&eng.engine))
+}
+
+func (eng *Engine) writeBuffer() []byte {
+	w := C.pn_connection_engine_write_buffer(&eng.engine)
+	return byteSlice(unsafe.Pointer(w.start), w.size)
+}
+
+func (eng *Engine) readBuffer() []byte {
+	r := C.pn_connection_engine_read_buffer(&eng.engine)
+	return byteSlice(unsafe.Pointer(r.start), r.size)
+}
+
 // Run the engine. Engine.Run() will exit when the engine is closed or
 // disconnected.  You can check for errors after exit with Engine.Error().
 //
 func (eng *Engine) Run() error {
 	C.pn_connection_engine_start(&eng.engine)
-
 	// Channels for read and write buffers going in and out of the read/write goroutines.
 	// The channels are unbuffered: we want to exchange buffers in seuquence.
 	readsIn, writesIn := make(chan []byte), make(chan []byte)
@@ -298,9 +312,18 @@ func (eng *Engine) Run() error {
 		}
 	}()
 
-	for !C.pn_connection_engine_finished(&eng.engine) {
-		// Enable readIn/writeIn channles only if we have a buffer.
-		readBuf, writeBuf := eng.buffers()
+	for eng.dispatch() {
+		readBuf := eng.readBuffer()
+		writeBuf := eng.writeBuffer()
+		// Note that getting the buffers can generate events (eg. SASL events) that
+		// might close the transport. Check if we are already finished before
+		// blocking for IO.
+		if !eng.dispatch() {
+			break
+		}
+
+		// sendReads/sendWrites are nil (not sendable in select) unless we have a
+		// buffer to read/write
 		var sendReads, sendWrites chan []byte
 		if readBuf != nil {
 			sendReads = readsIn
@@ -311,6 +334,7 @@ func (eng *Engine) Run() error {
 
 		// Send buffers to the read/write goroutines if we have them.
 		// Get buffers from the read/write goroutines and process them
+		// Check for injected functions
 		select {
 
 		case sendReads <- readBuf:
@@ -318,36 +342,18 @@ func (eng *Engine) Run() error {
 		case sendWrites <- writeBuf:
 
 		case buf := <-readsOut:
-			if len(buf) > 0 {
-				C.pn_connection_engine_read_done(&eng.engine, C.size_t(len(buf)))
-			} else {
-				panic(fmt.Sprintf("read buf %v", buf))
-			}
+			C.pn_connection_engine_read_done(&eng.engine, C.size_t(len(buf)))
 
 		case buf := <-writesOut:
-			if len(buf) > 0 {
-				C.pn_connection_engine_write_done(&eng.engine, C.size_t(len(buf)))
-			} else {
-				panic(fmt.Sprintf("write buf %v", buf))
-			}
+			C.pn_connection_engine_write_done(&eng.engine, C.size_t(len(buf)))
 
 		case f, ok := <-eng.inject: // Function injected from another goroutine
 			if ok {
 				f()
 			}
 		}
-
-		for {
-			cevent := C.pn_connection_engine_dispatch(&eng.engine)
-			if cevent == nil {
-				break
-			}
-			event := makeEvent(cevent, eng)
-			for _, h := range eng.handlers {
-				h.HandleEvent(event)
-			}
-		}
 	}
+
 	eng.err.Set(EndpointError(eng.Connection()))
 	eng.err.Set(eng.Transport().Condition().Error())
 	close(readsIn)
@@ -365,6 +371,5 @@ func (eng *Engine) Run() error {
 			C.pn_handler_free(h.pn)
 		}
 	}
-	// FIXME aconway 2016-06-21: consistent error handling
 	return eng.err.Get()
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
index 2a96d81..0fd652c 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
@@ -206,11 +206,11 @@ func (d endpointDelegator) HandleEvent(e Event) {
 		}
 
 	case d.remoteOpen:
+		d.delegator.mhandler.HandleMessagingEvent(d.opening, e)
 		switch {
 		case state.LocalActive():
 			d.delegator.mhandler.HandleMessagingEvent(d.opened, e)
 		case state.LocalUninit():
-			d.delegator.mhandler.HandleMessagingEvent(d.opening, e)
 			if d.delegator.AutoOpen {
 				endpoint.Open()
 			}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
index 70611d3..3303f0a 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
@@ -29,6 +29,7 @@ package proton
 //#include <proton/link.h>
 //#include <proton/link.h>
 //#include <proton/object.h>
+//#include <proton/sasl.h>
 //#include <proton/session.h>
 //#include <proton/transport.h>
 //#include <stdlib.h>
@@ -292,7 +293,8 @@ func (s Session) Receiver(name string) Link {
 
 // Unique (per process) string identifier for a connection, useful for debugging.
 func (c Connection) String() string {
-	return fmt.Sprintf("%x", c.pn)
+	// Use the transport address to match the default transport logs from PN_TRACE.
+	return fmt.Sprintf("%p", c.Transport().CPtr())
 }
 
 func (c Connection) Type() string {
@@ -323,6 +325,18 @@ func (c Connection) Sessions(state State) (sessions []Session) {
 	return
 }
 
+// SetPassword takes []byte not string because it is impossible to erase a string
+// from memory reliably. Proton will not keep the password in memory longer than
+// needed, the caller should overwrite their copy on return.
+//
+// The password must not contain embedded nul characters, a trailing nul is ignored.
+func (c Connection) SetPassword(password []byte) {
+	if len(password) == 0 || password[len(password)-1] != 0 {
+		password = append(password, 0) // Proton requires a terminating null.
+	}
+	C.pn_connection_set_password(c.pn, (*C.char)(unsafe.Pointer(&password[0])))
+}
+
 func (s Session) String() string {
 	return fmt.Sprintf("%s/%p", s.Connection(), s.pn)
 }
@@ -384,3 +398,8 @@ func (t Transport) Head() unsafe.Pointer {
 func (t Transport) Push(bytes []byte) int {
 	return int(C.pn_transport_push(t.pn, (*C.char)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes))))
 }
+
+// Get the SASL object for the transport.
+func (t Transport) SASL() SASL {
+	return SASL{C.pn_sasl(t.pn)}
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
index 183d6ec..38c76cc 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
@@ -42,6 +42,7 @@ import (
 // #include <proton/terminus.h>
 // #include <proton/connection.h>
 // #include <proton/transport.h>
+// #include <proton/sasl.h>
 import "C"
 
 type EventType int
@@ -704,12 +705,6 @@ func (c Connection) SetUser(user string) {
 
 	C.pn_connection_set_user(c.pn, userC)
 }
-func (c Connection) SetPassword(password string) {
-	passwordC := C.CString(password)
-	defer C.free(unsafe.Pointer(passwordC))
-
-	C.pn_connection_set_password(c.pn, passwordC)
-}
 func (c Connection) User() string {
 	return C.GoString(C.pn_connection_get_user(c.pn))
 }
@@ -873,3 +868,76 @@ func (t Transport) Tick(now time.Time) time.Time {
 func (t Transport) Connection() Connection {
 	return Connection{C.pn_transport_connection(t.pn)}
 }
+
+// Wrappers for declarations in sasl.h
+
+type SASLOutcome C.pn_sasl_outcome_t
+
+const (
+	SASLNone SASLOutcome = C.PN_SASL_NONE
+	SASLOk   SASLOutcome = C.PN_SASL_OK
+	SASLAuth SASLOutcome = C.PN_SASL_AUTH
+	SASLSys  SASLOutcome = C.PN_SASL_SYS
+	SASLPerm SASLOutcome = C.PN_SASL_PERM
+	SASLTemp SASLOutcome = C.PN_SASL_TEMP
+)
+
+func (e SASLOutcome) String() string {
+	switch e {
+
+	case C.PN_SASL_NONE:
+		return "SASLNone"
+	case C.PN_SASL_OK:
+		return "SASLOk"
+	case C.PN_SASL_AUTH:
+		return "SASLAuth"
+	case C.PN_SASL_SYS:
+		return "SASLSys"
+	case C.PN_SASL_PERM:
+		return "SASLPerm"
+	case C.PN_SASL_TEMP:
+		return "SASLTemp"
+	}
+	return "unknown"
+}
+
+type SASL struct{ pn *C.pn_sasl_t }
+
+func (s SASL) IsNil() bool          { return s.pn == nil }
+func (s SASL) CPtr() unsafe.Pointer { return unsafe.Pointer(s.pn) }
+func (s SASL) Done(outcome SASLOutcome) {
+	C.pn_sasl_done(s.pn, C.pn_sasl_outcome_t(outcome))
+}
+func (s SASL) Outcome() SASLOutcome {
+	return SASLOutcome(C.pn_sasl_outcome(s.pn))
+}
+func (s SASL) User() string {
+	return C.GoString(C.pn_sasl_get_user(s.pn))
+}
+func (s SASL) Mech() string {
+	return C.GoString(C.pn_sasl_get_mech(s.pn))
+}
+func (s SASL) AllowedMechs(mechs string) {
+	mechsC := C.CString(mechs)
+	defer C.free(unsafe.Pointer(mechsC))
+
+	C.pn_sasl_allowed_mechs(s.pn, mechsC)
+}
+func (s SASL) SetAllowInsecureMechs(insecure bool) {
+	C.pn_sasl_set_allow_insecure_mechs(s.pn, C.bool(insecure))
+}
+func (s SASL) AllowInsecureMechs() bool {
+	return bool(C.pn_sasl_get_allow_insecure_mechs(s.pn))
+}
+func (s SASL) ConfigName(name string) {
+	nameC := C.CString(name)
+	defer C.free(unsafe.Pointer(nameC))
+
+	C.pn_sasl_config_name(s.pn, nameC)
+}
+func (s SASL) ConfigPath(path string) {
+	pathC := C.CString(path)
+	defer C.free(unsafe.Pointer(pathC))
+
+	C.pn_sasl_config_path(s.pn, pathC)
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0e37353d/proton-c/src/engine/engine.c
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine.c b/proton-c/src/engine/engine.c
index ca7e4d8..cb1f479 100644
--- a/proton-c/src/engine/engine.c
+++ b/proton-c/src/engine/engine.c
@@ -594,6 +594,10 @@ void pn_connection_set_user(pn_connection_t *connection, const char *user)
 void pn_connection_set_password(pn_connection_t *connection, const char *password)
 {
     assert(connection);
+    // Make sure the previous password is erased, if there was one.
+    size_t n = pn_string_size(connection->auth_password);
+    const char* s = pn_string_get(connection->auth_password);
+    if (n > 0 && s) memset((void*)s, 0, n);
     pn_string_set(connection->auth_password, password);
 }
 


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


[09/50] [abbrv] qpid-proton git commit: PROTON-1308: Go: fix typos in some AMQP condition names

Posted by ac...@apache.org.
PROTON-1308: Go: fix typos in some AMQP condition names


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

Branch: refs/heads/go1
Commit: e7b70d8048098190827e12b3415c51d766ee4448
Parents: 2c438a8
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Sep 28 11:56:14 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Sep 28 16:38:51 2016 -0400

----------------------------------------------------------------------
 .../go/src/qpid.apache.org/amqp/error.go        | 28 ++++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e7b70d80/proton-c/bindings/go/src/qpid.apache.org/amqp/error.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/error.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/error.go
index 349fc41..3a178b2 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/error.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/error.go
@@ -30,7 +30,7 @@ import (
 // Error is an AMQP error condition. It has a name and a description.
 // It implements the Go error interface so can be returned as an error value.
 //
-// You can pass amqp.Error to methods that pass an error to a remote endpoint,
+// You can pass amqp.Error to methods that send an error to a remote endpoint,
 // this gives you full control over what the remote endpoint will see.
 //
 // You can also pass any Go error to such functions, the remote peer
@@ -53,19 +53,19 @@ func MakeError(err error) Error {
 }
 
 var (
-	InternalError      = "amqp:internal-error"
-	NotFound           = "amqp:not-found"
-	UnauthorizedAccess = "amqp:unauthorized-access"
-	DecodeError        = "amqp:decode-error"
-	ResourceLimit      = "amqp:resource-limit"
-	NotAllowed         = "amqp:not-allowed"
-	InvalidField       = "amqp:invalid-field"
-	NotImplemented     = "amqp:not-implemented"
-	ResourceLocked     = "amqp:resource-locked"
-	PreerrorFailed     = "amqp:preerror-failed"
-	ResourceDeleted    = "amqp:resource-deleted"
-	IllegalState       = "amqp:illegal-state"
-	FrameSizeTooSmall  = "amqp:frame-size-too-small"
+	InternalError         = "amqp:internal-error"
+	NotFound              = "amqp:not-found"
+	UnauthorizedAccess    = "amqp:unauthorized-access"
+	DecodeError           = "amqp:decode-error"
+	ResourceLimitExceeded = "amqp:resource-limit-exceeded"
+	NotAllowed            = "amqp:not-allowed"
+	InvalidField          = "amqp:invalid-field"
+	NotImplemented        = "amqp:not-implemented"
+	ResourceLocked        = "amqp:resource-locked"
+	PreconditionFailed    = "amqp:precondition-failed"
+	ResourceDeleted       = "amqp:resource-deleted"
+	IllegalState          = "amqp:illegal-state"
+	FrameSizeTooSmall     = "amqp:frame-size-too-small"
 )
 
 type PnErrorCode int


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


[44/50] [abbrv] qpid-proton git commit: PROTON-1337 Add alternate send and recv methods that use generic buffers

Posted by ac...@apache.org.
PROTON-1337 Add alternate send and recv methods that use generic buffers

Add support for clients that use other buffering types to interact with
the Sender and Receiver using a ReadableBuffer and WritableBuffer
abstraction.  

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

Branch: refs/heads/go1
Commit: acf1f6eb182a62ce047270c0c6483bcd0b2eb083
Parents: 507c935
Author: Timothy Bish <ta...@gmail.com>
Authored: Fri Oct 28 15:35:45 2016 -0400
Committer: Timothy Bish <ta...@gmail.com>
Committed: Fri Oct 28 15:35:45 2016 -0400

----------------------------------------------------------------------
 .../qpid/proton/codec/WritableBuffer.java       | 21 +++++-
 .../org/apache/qpid/proton/engine/Receiver.java | 10 +++
 .../org/apache/qpid/proton/engine/Sender.java   | 15 ++++
 .../qpid/proton/engine/impl/DeliveryImpl.java   | 78 ++++++++++++++++++--
 .../qpid/proton/engine/impl/ReceiverImpl.java   | 23 +++++-
 .../qpid/proton/engine/impl/SenderImpl.java     | 27 ++++++-
 6 files changed, 162 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/codec/WritableBuffer.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/WritableBuffer.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/WritableBuffer.java
index 4bcf793..79676b3 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/WritableBuffer.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/WritableBuffer.java
@@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
 
 public interface WritableBuffer
 {
-    public void put(byte b);
+    void put(byte b);
 
     void putFloat(float f);
 
@@ -60,66 +60,79 @@ public interface WritableBuffer
             _buf = buf;
         }
 
+        @Override
         public void put(byte b)
         {
             _buf.put(b);
         }
 
+        @Override
         public void putFloat(float f)
         {
             _buf.putFloat(f);
         }
 
+        @Override
         public void putDouble(double d)
         {
             _buf.putDouble(d);
         }
 
+        @Override
         public void put(byte[] src, int offset, int length)
         {
             _buf.put(src, offset, length);
         }
 
+        @Override
         public void putShort(short s)
         {
             _buf.putShort(s);
         }
 
+        @Override
         public void putInt(int i)
         {
             _buf.putInt(i);
         }
 
+        @Override
         public void putLong(long l)
         {
             _buf.putLong(l);
         }
 
+        @Override
         public boolean hasRemaining()
         {
             return _buf.hasRemaining();
         }
 
+        @Override
         public int remaining()
         {
             return _buf.remaining();
         }
 
+        @Override
         public int position()
         {
             return _buf.position();
         }
 
+        @Override
         public void position(int position)
         {
             _buf.position(position);
         }
 
+        @Override
         public void put(ByteBuffer src)
         {
             _buf.put(src);
         }
 
+        @Override
         public int limit()
         {
             return _buf.limit();
@@ -130,5 +143,11 @@ public interface WritableBuffer
         {
             return String.format("[pos: %d, limit: %d, remaining:%d]", _buf.position(), _buf.limit(), _buf.remaining());
         }
+
+        public static ByteBufferWrapper allocate(int size)
+        {
+            ByteBuffer allocated = ByteBuffer.allocate(size);
+            return new ByteBufferWrapper(allocated);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java
index eec64da..f9d718f 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.engine;
 
+import org.apache.qpid.proton.codec.WritableBuffer;
 
 /**
  * Receiver
@@ -59,6 +60,15 @@ public interface Receiver extends Link
      */
     public int recv(byte[] bytes, int offset, int size);
 
+    /**
+     * Receive message data for the current delivery.
+     *
+     * @param buffer the buffer to write the message data.
+     *
+     * @return number of bytes written. -1 if there are no more bytes for the current delivery.
+     */
+    public int recv(WritableBuffer buffer);
+
     public void drain(int credit);
 
     /**

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java
index b4a61c6..159d5c3 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.engine;
 
+import org.apache.qpid.proton.codec.ReadableBuffer;
 
 /**
  * Sender
@@ -40,6 +41,10 @@ public interface Sender extends Link
      * Sends some data for the current delivery.  The application may call this method multiple
      * times for the same delivery.
      *
+     * @param bytes the byte array containing the data to be sent.
+     * @param offset the offset into the given array to start reading.
+     * @param length the number of bytes to read from the given byte array.
+     *
      * @return the number of bytes accepted
      *
      * TODO Proton-j current copies all the bytes it has been given so the return value will always be
@@ -49,6 +54,16 @@ public interface Sender extends Link
     public int send(byte[] bytes, int offset, int length);
 
     /**
+     * Sends some data for the current delivery. The application may call this method multiple
+     * times for the same delivery.
+     *
+     * @param buffer the buffer to read the data from.
+     *
+     * @return the number of bytes read from the provided buffer.
+     */
+    public int send(ReadableBuffer buffer);
+
+    /**
      * Abort the current delivery.
      *
      * Note "pn_link_abort" is commented out in the .h

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
index 20fe4fe..0bdb163 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
@@ -22,10 +22,12 @@ package org.apache.qpid.proton.engine.impl;
 
 import java.util.Arrays;
 
+import org.apache.qpid.proton.amqp.transport.DeliveryState;
+import org.apache.qpid.proton.codec.ReadableBuffer;
+import org.apache.qpid.proton.codec.WritableBuffer;
 import org.apache.qpid.proton.engine.Delivery;
 import org.apache.qpid.proton.engine.Record;
 import org.apache.qpid.proton.engine.Transport;
-import org.apache.qpid.proton.amqp.transport.DeliveryState;
 
 public class DeliveryImpl implements Delivery
 {
@@ -80,26 +82,31 @@ public class DeliveryImpl implements Delivery
         }
     }
 
+    @Override
     public byte[] getTag()
     {
         return _tag;
     }
 
+    @Override
     public LinkImpl getLink()
     {
         return _link;
     }
 
+    @Override
     public DeliveryState getLocalState()
     {
         return _deliveryState;
     }
 
+    @Override
     public DeliveryState getRemoteState()
     {
         return _remoteDeliveryState;
     }
 
+    @Override
     public boolean remotelySettled()
     {
         return _remoteSettled;
@@ -117,6 +124,7 @@ public class DeliveryImpl implements Delivery
         return _messageFormat;
     }
 
+    @Override
     public void disposition(final DeliveryState state)
     {
         _deliveryState = state;
@@ -126,6 +134,7 @@ public class DeliveryImpl implements Delivery
         }
     }
 
+    @Override
     public void settle()
     {
         if (_settled) {
@@ -164,11 +173,13 @@ public class DeliveryImpl implements Delivery
         return _linkNext;
     }
 
+    @Override
     public DeliveryImpl next()
     {
         return getLinkNext();
     }
 
+    @Override
     public void free()
     {
         settle();
@@ -179,6 +190,7 @@ public class DeliveryImpl implements Delivery
         return _linkPrevious;
     }
 
+    @Override
     public DeliveryImpl getWorkNext()
     {
         if (_workNext != null)
@@ -205,11 +217,10 @@ public class DeliveryImpl implements Delivery
         _workPrev = workPrev;
     }
 
-    int recv(byte[] bytes, int offset, int size)
+    int recv(final byte[] bytes, int offset, int size)
     {
-
         final int consumed;
-        if(_data != null)
+        if (_data != null)
         {
             //TODO - should only be if no bytes left
             consumed = Math.min(size, _dataSize);
@@ -220,11 +231,30 @@ public class DeliveryImpl implements Delivery
         }
         else
         {
-            _dataSize =  consumed = 0;
+            _dataSize = consumed = 0;
         }
+
         return (_complete && consumed == 0) ? Transport.END_OF_STREAM : consumed;  //TODO - Implement
     }
 
+    int recv(final WritableBuffer buffer) {
+        final int consumed;
+        if (_data != null)
+        {
+            consumed = Math.min(buffer.remaining(), _dataSize);
+
+            buffer.put(_data, _offset, consumed);
+            _offset += consumed;
+            _dataSize -= consumed;
+        }
+        else
+        {
+            _dataSize = consumed = 0;
+        }
+
+        return (_complete && consumed == 0) ? Transport.END_OF_STREAM : consumed;
+    }
+
     void updateWork()
     {
         getLink().getConnectionImpl().workUpdate(this);
@@ -274,6 +304,7 @@ public class DeliveryImpl implements Delivery
         _transportDelivery = transportDelivery;
     }
 
+    @Override
     public boolean isSettled()
     {
         return _settled;
@@ -289,15 +320,36 @@ public class DeliveryImpl implements Delivery
         {
             byte[] oldData = _data;
             _data = new byte[oldData.length + _dataSize];
-            System.arraycopy(oldData,_offset,_data,0,_dataSize);
+            System.arraycopy(oldData, _offset, _data, 0, _dataSize);
             _offset = 0;
         }
-        System.arraycopy(bytes,offset,_data,_dataSize+_offset,length);
-        _dataSize+=length;
+        System.arraycopy(bytes, offset, _data, _dataSize + _offset, length);
+        _dataSize += length;
         addToTransportWorkList();
         return length;  //TODO - Implement.
     }
 
+    int send(final ReadableBuffer buffer)
+    {
+        int length = buffer.remaining();
+
+        if(_data == null)
+        {
+            _data = new byte[length];
+        }
+        else if(_data.length - _dataSize < length)
+        {
+            byte[] oldData = _data;
+            _data = new byte[oldData.length + _dataSize];
+            System.arraycopy(oldData, _offset, _data, 0, _dataSize);
+            _offset = 0;
+        }
+        buffer.get(_data, _offset, length);
+        _dataSize+=length;
+        addToTransportWorkList();
+        return length;
+    }
+
     byte[] getData()
     {
         return _data;
@@ -328,6 +380,7 @@ public class DeliveryImpl implements Delivery
         _offset = arrayOffset;
     }
 
+    @Override
     public boolean isWritable()
     {
         return getLink() instanceof SenderImpl
@@ -335,6 +388,7 @@ public class DeliveryImpl implements Delivery
                 && ((SenderImpl) getLink()).hasCredit();
     }
 
+    @Override
     public boolean isReadable()
     {
         return getLink() instanceof ReceiverImpl
@@ -346,6 +400,7 @@ public class DeliveryImpl implements Delivery
         _complete = true;
     }
 
+    @Override
     public boolean isPartial()
     {
         return !_complete;
@@ -357,11 +412,13 @@ public class DeliveryImpl implements Delivery
         _updated = true;
     }
 
+    @Override
     public boolean isUpdated()
     {
         return _updated;
     }
 
+    @Override
     public void clear()
     {
         _updated = false;
@@ -385,6 +442,7 @@ public class DeliveryImpl implements Delivery
         _updated = true;
     }
 
+    @Override
     public boolean isBuffered()
     {
         if (_remoteSettled) return false;
@@ -399,16 +457,19 @@ public class DeliveryImpl implements Delivery
         }
     }
 
+    @Override
     public Object getContext()
     {
         return _context;
     }
 
+    @Override
     public void setContext(Object context)
     {
         _context = context;
     }
 
+    @Override
     public Record attachments()
     {
         if(_attachments == null)
@@ -440,6 +501,7 @@ public class DeliveryImpl implements Delivery
         return builder.toString();
     }
 
+    @Override
     public int pending()
     {
         return _dataSize;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java
index a3a01f7..6f86700 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java
@@ -21,6 +21,7 @@
 package org.apache.qpid.proton.engine.impl;
 
 import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.codec.WritableBuffer;
 import org.apache.qpid.proton.engine.Receiver;
 
 public class ReceiverImpl extends LinkImpl implements Receiver
@@ -58,6 +59,7 @@ public class ReceiverImpl extends LinkImpl implements Receiver
         super(session, name);
     }
 
+    @Override
     public void flow(final int credits)
     {
         addCredit(credits);
@@ -77,7 +79,7 @@ public class ReceiverImpl extends LinkImpl implements Receiver
         return credits;
     }
 
-
+    @Override
     public int recv(final byte[] bytes, int offset, int size)
     {
         if (_current == null) {
@@ -95,6 +97,23 @@ public class ReceiverImpl extends LinkImpl implements Receiver
     }
 
     @Override
+    public int recv(final WritableBuffer buffer)
+    {
+        if (_current == null) {
+            throw new IllegalStateException("no current delivery");
+        }
+
+        int consumed = _current.recv(buffer);
+        if (consumed > 0) {
+            getSession().incrementIncomingBytes(-consumed);
+            if (getSession().getTransportSession().getIncomingWindowSize().equals(UnsignedInteger.ZERO)) {
+                modified();
+            }
+        }
+        return consumed;
+    }
+
+    @Override
     void doFree()
     {
         getSession().freeReceiver(this);
@@ -117,6 +136,7 @@ public class ReceiverImpl extends LinkImpl implements Receiver
         return _transportReceiver;
     }
 
+    @Override
     public void drain(int credit)
     {
         setDrain(true);
@@ -124,6 +144,7 @@ public class ReceiverImpl extends LinkImpl implements Receiver
         _drainFlagMode = false;
     }
 
+    @Override
     public boolean draining()
     {
         return getDrain() && (getCredit() > getQueued());

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/acf1f6eb/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java
index 7cf605f..f418655 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.engine.impl;
 
+import org.apache.qpid.proton.codec.ReadableBuffer;
 import org.apache.qpid.proton.engine.EndpointState;
 import org.apache.qpid.proton.engine.Sender;
 
@@ -33,19 +34,21 @@ public class SenderImpl  extends LinkImpl implements Sender
         super(session, name);
     }
 
+    @Override
     public void offer(final int credits)
     {
         _offered = credits;
     }
 
+    @Override
     public int send(final byte[] bytes, int offset, int length)
     {
-        if( getLocalState() == EndpointState.CLOSED ) 
+        if (getLocalState() == EndpointState.CLOSED)
         {
             throw new IllegalStateException("send not allowed after the sender is closed.");
         }
         DeliveryImpl current = current();
-        if(current == null || current.getLink() != this)
+        if (current == null || current.getLink() != this)
         {
             throw new IllegalArgumentException();//TODO.
         }
@@ -56,6 +59,26 @@ public class SenderImpl  extends LinkImpl implements Sender
         return sent;
     }
 
+    @Override
+    public int send(final ReadableBuffer buffer)
+    {
+        if (getLocalState() == EndpointState.CLOSED)
+        {
+            throw new IllegalStateException("send not allowed after the sender is closed.");
+        }
+        DeliveryImpl current = current();
+        if (current == null || current.getLink() != this)
+        {
+            throw new IllegalArgumentException();
+        }
+        int sent = current.send(buffer);
+        if (sent > 0) {
+            getSession().incrementOutgoingBytes(sent);
+        }
+        return sent;
+    }
+
+    @Override
     public void abort()
     {
         //TODO.


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


[46/50] [abbrv] qpid-proton git commit: NO-JIRA: Removed uneeded #includes

Posted by ac...@apache.org.
NO-JIRA: Removed uneeded #includes


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

Branch: refs/heads/go1
Commit: 9a4cdf0f4bdd1347bef9d40656a44d21ea5f5742
Parents: 3661f90
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Oct 28 17:08:15 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Mon Oct 31 11:13:39 2016 -0400

----------------------------------------------------------------------
 proton-c/include/proton/messenger.h | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9a4cdf0f/proton-c/include/proton/messenger.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/messenger.h b/proton-c/include/proton/messenger.h
index 87cb35c..6d0f58b 100644
--- a/proton-c/include/proton/messenger.h
+++ b/proton-c/include/proton/messenger.h
@@ -25,8 +25,6 @@
 #include <proton/import_export.h>
 #include <proton/message.h>
 #include <proton/selectable.h>
-#include <proton/condition.h>
-#include <proton/terminus.h>
 #include <proton/link.h>
 #include <proton/transport.h>
 #include <proton/ssl.h>


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


[10/50] [abbrv] qpid-proton git commit: PROTON-1308: Go: Support Idle Timeout setting in electron Transport

Posted by ac...@apache.org.
PROTON-1308: Go: Support Idle Timeout setting in electron Transport

electron.Heartbeat(time.Duration) returns a ConnectionOption that will set the
required heartbeat interval for the remote peer. See electron.Heartbeat
and electron.ConnectionSettings.Heartbeat

NOTE: The term "Heartbeat" was chosen to avoid the ambiguous term
"idle-timeout". Heartbeat *always* refers to the max allowed duration
between *sending* frames. The frame receiver waits for 2*remote-heartbeat before
closing a connection.


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

Branch: refs/heads/go1
Commit: ce80f9d7250400cbe47bb5bf0ced3937ed829d92
Parents: e7b70d8
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Sep 28 13:00:22 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Sep 28 16:39:05 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/go/genwrap.go                 |  1 +
 .../src/qpid.apache.org/electron/auth_test.go   |  6 +-
 .../src/qpid.apache.org/electron/connection.go  | 49 ++++++++++++----
 .../qpid.apache.org/electron/electron_test.go   | 61 ++++++++++++++++++++
 .../go/src/qpid.apache.org/electron/handler.go  |  2 +
 .../go/src/qpid.apache.org/proton/engine.go     | 38 +++++++++---
 .../go/src/qpid.apache.org/proton/wrappers.go   | 36 ++++++++----
 .../src/qpid.apache.org/proton/wrappers_gen.go  |  2 +-
 8 files changed, 160 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/genwrap.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/genwrap.go b/proton-c/bindings/go/genwrap.go
index f295a32..8a9af03 100644
--- a/proton-c/bindings/go/genwrap.go
+++ b/proton-c/bindings/go/genwrap.go
@@ -317,6 +317,7 @@ func mapType(ctype string) (g genType) {
 	case "C.pn_millis_t":
 		g.Gotype = "time.Duration"
 		g.ToGo = func(v string) string { return fmt.Sprintf("(time.Duration(%s) * time.Millisecond)", v) }
+		g.ToC = func(v string) string { return fmt.Sprintf("C.pn_millis_t(%s/time.Millisecond)", v) }
 	case "C.pn_timestamp_t":
 		g.Gotype = "time.Time"
 		g.ToC = func(v string) string { return fmt.Sprintf("pnTime(%s)", v) }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
index a090b78..73a9299 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
@@ -53,7 +53,7 @@ func TestAuthAnonymous(t *testing.T) {
 		[]ConnectionOption{User("fred"), VirtualHost("vhost"), SASLAllowInsecure(true)},
 		[]ConnectionOption{SASLAllowedMechs("ANONYMOUS"), SASLAllowInsecure(true)})
 	fatalIf(t, err)
-	errorIf(t, checkEqual(connectionSettings{"anonymous", "vhost"}, got))
+	errorIf(t, checkEqual(connectionSettings{user: "anonymous", virtualHost: "vhost"}, got))
 }
 
 func TestAuthPlain(t *testing.T) {
@@ -62,7 +62,7 @@ func TestAuthPlain(t *testing.T) {
 		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("xxx"))},
 		[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
 	fatalIf(t, err)
-	errorIf(t, checkEqual(connectionSettings{"fred@proton", ""}, got))
+	errorIf(t, checkEqual(connectionSettings{user: "fred@proton"}, got))
 }
 
 func TestAuthBadPass(t *testing.T) {
@@ -118,7 +118,7 @@ func configureSASL() error {
 func TestMain(m *testing.M) {
 	status := m.Run()
 	if confDir != "" {
-		os.RemoveAll(confDir)
+		_ = os.RemoveAll(confDir)
 	}
 	os.Exit(status)
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
index 00c08ad..7f3050f 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
@@ -45,6 +45,11 @@ type ConnectionSettings interface {
 	//
 	// Returns error if the connection fails to authenticate.
 	VirtualHost() string
+
+	// Heartbeat is the maximum delay between sending frames that the remote peer
+	// has requested of us. If the interval expires an empty "heartbeat" frame
+	// will be sent automatically to keep the connection open.
+	Heartbeat() time.Duration
 }
 
 // Connection is an AMQP connection, created by a Container.
@@ -88,10 +93,12 @@ type Connection interface {
 
 type connectionSettings struct {
 	user, virtualHost string
+	heartbeat         time.Duration
 }
 
-func (c connectionSettings) User() string        { return c.user }
-func (c connectionSettings) VirtualHost() string { return c.virtualHost }
+func (c connectionSettings) User() string             { return c.user }
+func (c connectionSettings) VirtualHost() string      { return c.virtualHost }
+func (c connectionSettings) Heartbeat() time.Duration { return c.heartbeat }
 
 // ConnectionOption can be passed when creating a connection to configure various options
 type ConnectionOption func(*connection)
@@ -165,7 +172,7 @@ type connection struct {
 }
 
 // NewConnection creates a connection with the given options.
-func NewConnection(conn net.Conn, setting ...ConnectionOption) (*connection, error) {
+func NewConnection(conn net.Conn, opts ...ConnectionOption) (*connection, error) {
 	c := &connection{
 		conn: conn,
 	}
@@ -176,7 +183,7 @@ func NewConnection(conn net.Conn, setting ...ConnectionOption) (*connection, err
 		return nil, err
 	}
 	c.pConnection = c.engine.Connection()
-	for _, set := range setting {
+	for _, set := range opts {
 		set(c)
 	}
 	if c.container == nil {
@@ -211,7 +218,7 @@ func (c *connection) Disconnect(err error) {
 	c.engine.Disconnect(err)
 }
 
-func (c *connection) Session(setting ...SessionOption) (Session, error) {
+func (c *connection) Session(opts ...SessionOption) (Session, error) {
 	var s Session
 	err := c.engine.InjectWait(func() error {
 		if c.Error() != nil {
@@ -221,7 +228,7 @@ func (c *connection) Session(setting ...SessionOption) (Session, error) {
 		if err == nil {
 			pSession.Open()
 			if err == nil {
-				s = newSession(c, pSession, setting...)
+				s = newSession(c, pSession, opts...)
 			}
 		}
 		return err
@@ -241,17 +248,17 @@ func (c *connection) DefaultSession() (s Session, err error) {
 	return c.defaultSession, err
 }
 
-func (c *connection) Sender(setting ...LinkOption) (Sender, error) {
+func (c *connection) Sender(opts ...LinkOption) (Sender, error) {
 	if s, err := c.DefaultSession(); err == nil {
-		return s.Sender(setting...)
+		return s.Sender(opts...)
 	} else {
 		return nil, err
 	}
 }
 
-func (c *connection) Receiver(setting ...LinkOption) (Receiver, error) {
+func (c *connection) Receiver(opts ...LinkOption) (Receiver, error) {
 	if s, err := c.DefaultSession(); err == nil {
-		return s.Receiver(setting...)
+		return s.Receiver(opts...)
 	} else {
 		return nil, err
 	}
@@ -288,11 +295,20 @@ func newIncomingConnection(c *connection) *IncomingConnection {
 		c:                  c}
 }
 
-func (in *IncomingConnection) Accept() Endpoint {
+// AcceptConnection is like Accept() but takes ConnectionOption s
+// For example you can set the Heartbeat() for the accepted connection.
+func (in *IncomingConnection) AcceptConnection(opts ...ConnectionOption) Connection {
 	return in.accept(func() Endpoint {
+		for _, opt := range opts {
+			opt(in.c)
+		}
 		in.c.pConnection.Open()
 		return in.c
-	})
+	}).(Connection)
+}
+
+func (in *IncomingConnection) Accept() Endpoint {
+	return in.AcceptConnection()
 }
 
 func sasl(c *connection) proton.SASL { return c.engine.Transport().SASL() }
@@ -325,6 +341,15 @@ func SASLAllowInsecure(b bool) ConnectionOption {
 	return func(c *connection) { sasl(c).SetAllowInsecureMechs(b) }
 }
 
+// Heartbeat returns a ConnectionOption that requests the maximum delay
+// between sending frames for the remote peer. If we don't receive any frames
+// within 2*delay we will close the connection.
+//
+func Heartbeat(delay time.Duration) ConnectionOption {
+	// Proton-C divides the idle-timeout by 2 before sending, so compensate.
+	return func(c *connection) { c.engine.Transport().SetIdleTimeout(2 * delay) }
+}
+
 // GlobalSASLConfigDir sets the SASL configuration directory for every
 // Connection created in this process. If not called, the default is determined
 // by your SASL installation.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
index aa37d57..294e952 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/electron_test.go
@@ -483,3 +483,64 @@ func TestConnectionCloseInterrupt2(t *testing.T) {
 		}
 	}
 }
+
+func heartbeat(c Connection) time.Duration {
+	return c.(*connection).engine.Transport().RemoteIdleTimeout()
+}
+
+func TestHeartbeat(t *testing.T) {
+	client, server := newClientServerOpts(t,
+		[]ConnectionOption{Heartbeat(102 * time.Millisecond)},
+		nil)
+	defer closeClientServer(client, server)
+
+	var serverHeartbeat time.Duration
+
+	go func() {
+		for in := range server.Incoming() {
+			switch in := in.(type) {
+			case *IncomingConnection:
+				serverHeartbeat = in.Heartbeat()
+				in.AcceptConnection(Heartbeat(101 * time.Millisecond))
+			default:
+				in.Accept()
+			}
+		}
+	}()
+
+	// Freeze the server to stop it sending heartbeats.
+	unfreeze := make(chan bool)
+	defer close(unfreeze)
+	freeze := func() error { return server.(*connection).engine.Inject(func() { <-unfreeze }) }
+
+	fatalIf(t, client.Sync())
+	errorIf(t, checkEqual(101*time.Millisecond, heartbeat(client.Connection())))
+	errorIf(t, checkEqual(102*time.Millisecond, serverHeartbeat))
+	errorIf(t, client.Connection().Error())
+
+	// Freeze the server for less than a heartbeat
+	fatalIf(t, freeze())
+	time.Sleep(50 * time.Millisecond)
+	unfreeze <- true
+	// Make sure server is still responding.
+	s, err := client.Sender()
+	errorIf(t, err)
+	errorIf(t, s.Sync())
+
+	// Freeze the server till the client times out the connection
+	fatalIf(t, freeze())
+	select {
+	case <-client.Done():
+		if amqp.ResourceLimitExceeded != client.Error().(amqp.Error).Name {
+			t.Error("bad timeout error:", client.Error())
+		}
+	case <-time.After(400 * time.Millisecond):
+		t.Error("connection failed to time out")
+	}
+
+	unfreeze <- true // Unfreeze the server
+	<-server.Done()
+	if amqp.ResourceLimitExceeded != server.Error().(amqp.Error).Name {
+		t.Error("bad timeout error:", server.Error())
+	}
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
index 2a426aa..588ba79 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/handler.go
@@ -79,6 +79,7 @@ func (h *handler) HandleMessagingEvent(t proton.MessagingEvent, e proton.Event)
 		}
 
 	case proton.MConnectionOpening:
+		h.connection.heartbeat = e.Transport().RemoteIdleTimeout()
 		if e.Connection().State().LocalUninit() { // Remotely opened
 			h.incoming(newIncomingConnection(h.connection))
 		}
@@ -137,6 +138,7 @@ func (h *handler) incoming(in Incoming) {
 	var err error
 	if h.connection.incoming != nil {
 		h.connection.incoming <- in
+		// Must block until accept/reject, subsequent events may use the incoming endpoint.
 		err = in.wait()
 	} else {
 		err = amqp.Errorf(amqp.NotAllowed, "rejected incoming %s %s",

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index 6439fc1..7ba6827 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -107,6 +107,7 @@ type Engine struct {
 	handlers  []EventHandler // Handlers for proton events.
 	running   chan struct{}  // This channel will be closed when the goroutines are done.
 	closeOnce sync.Once
+	timer     *time.Timer
 }
 
 const bufferSize = 4096
@@ -123,6 +124,7 @@ func NewEngine(conn net.Conn, handlers ...EventHandler) (*Engine, error) {
 		conn:     conn,
 		handlers: handlers,
 		running:  make(chan struct{}),
+		timer:    time.NewTimer(0),
 	}
 	if pnErr := C.pn_connection_engine_init(&eng.engine); pnErr != 0 {
 		return nil, fmt.Errorf("cannot setup engine: %s", PnErrorCode(pnErr))
@@ -237,17 +239,34 @@ func (eng *Engine) Disconnect(err error) {
 	<-eng.running
 }
 
+// Let proton run timed activity and set up the next tick
+func (eng *Engine) tick() {
+	now := time.Now()
+	next := eng.Transport().Tick(now)
+	if !next.IsZero() {
+		eng.timer.Reset(next.Sub(now))
+	}
+}
+
 func (eng *Engine) dispatch() bool {
+	var needTick bool // Set if we need to tick the transport.
 	for {
 		if cevent := C.pn_connection_engine_dispatch(&eng.engine); cevent != nil {
 			event := makeEvent(cevent, eng)
 			for _, h := range eng.handlers {
+				switch event.Type() {
+				case ETransport:
+					needTick = true
+				}
 				h.HandleEvent(event)
 			}
 		} else {
 			break
 		}
 	}
+	if needTick {
+		eng.tick()
+	}
 	return !bool(C.pn_connection_engine_finished(&eng.engine))
 }
 
@@ -285,10 +304,10 @@ func (eng *Engine) Run() error {
 			if n > 0 {
 				readsOut <- rbuf[:n]
 			} else if err != nil {
-				eng.inject <- func() {
+				_ = eng.Inject(func() {
 					eng.Transport().Condition().SetError(err)
 					C.pn_connection_engine_read_close(&eng.engine)
-				}
+				})
 				return
 			}
 		}
@@ -305,10 +324,10 @@ func (eng *Engine) Run() error {
 			if n > 0 {
 				writesOut <- wbuf[:n]
 			} else if err != nil {
-				eng.inject <- func() {
+				_ = eng.Inject(func() {
 					eng.Transport().Condition().SetError(err)
 					C.pn_connection_engine_write_close(&eng.engine)
-				}
+				})
 				return
 			}
 		}
@@ -353,6 +372,9 @@ func (eng *Engine) Run() error {
 			if ok {
 				f()
 			}
+
+		case <-eng.timer.C:
+			eng.tick()
 		}
 	}
 
@@ -360,18 +382,16 @@ func (eng *Engine) Run() error {
 	eng.err.Set(eng.Transport().Condition().Error())
 	close(readsIn)
 	close(writesIn)
-	_ = eng.conn.Close() // Make sure connection is closed
+	close(eng.running)   // Signal goroutines have exited and Error is set, disable Inject()
+	_ = eng.conn.Close() // Close conn, force read/write goroutines to exit (they will Inject)
 	wait.Wait()          // Wait for goroutines
 
-	close(eng.running) // Signal goroutines have exited and Error is set.
-
-	C.pn_connection_engine_final(&eng.engine)
-
 	for _, h := range eng.handlers {
 		switch h := h.(type) {
 		case cHandler:
 			C.pn_handler_free(h.pn)
 		}
 	}
+	C.pn_connection_engine_final(&eng.engine)
 	return eng.err.Get()
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
index fa3e850..1dee743 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers.go
@@ -291,6 +291,10 @@ func (s Session) Receiver(name string) Link {
 	return Link{C.pn_receiver(s.pn, cname)}
 }
 
+func (t Transport) String() string {
+	return fmt.Sprintf("(Transport)(%p)", t.CPtr())
+}
+
 // Unique (per process) string identifier for a connection, useful for debugging.
 func (c Connection) String() string {
 	// Use the transport address to match the default transport logs from PN_TRACE.
@@ -374,19 +378,31 @@ func (c Connection) Session() (Session, error) {
 }
 
 // pnTime converts Go time.Time to Proton millisecond Unix time.
-func pnTime(t time.Time) C.pn_timestamp_t {
-	secs := t.Unix()
-	// Note: sub-second accuracy is not guaraunteed if the Unix time in
-	// nanoseconds cannot be represented by an int64 (sometime around year 2260)
-	msecs := (t.UnixNano() % int64(time.Second)) / int64(time.Millisecond)
-	return C.pn_timestamp_t(secs*1000 + msecs)
+//
+// Note: t.isZero() is converted to C.pn_timestamp_t(0) and vice-versa. These
+// are used as "not set" sentinel values by the Go and Proton APIs, so it is
+// better to conserve the "zeroness" even though they don't represent the same
+// time instant.
+//
+func pnTime(t time.Time) (pnt C.pn_timestamp_t) {
+	if !t.IsZero() {
+		pnt = C.pn_timestamp_t(t.Unix()*1000 + int64(t.Nanosecond())/int64(time.Millisecond))
+	}
+	return
 }
 
 // goTime converts a pn_timestamp_t to a Go time.Time.
-func goTime(t C.pn_timestamp_t) time.Time {
-	secs := int64(t) / 1000
-	nsecs := (int64(t) % 1000) * int64(time.Millisecond)
-	return time.Unix(secs, nsecs)
+//
+// Note: C.pn_timestamp_t(0) is converted to a zero time.Time and
+// vice-versa. These are used as "not set" sentinel values by the Go and Proton
+// APIs, so it is better to conserve the "zeroness" even though they don't
+// represent the same time instant.
+//
+func goTime(pnt C.pn_timestamp_t) (t time.Time) {
+	if pnt != 0 {
+		t = time.Unix(int64(pnt/1000), int64(pnt%1000)*int64(time.Millisecond))
+	}
+	return
 }
 
 // Special treatment for Transport.Head, return value is unsafe.Pointer not string

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ce80f9d7/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
index 38c76cc..629caa6 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/wrappers_gen.go
@@ -812,7 +812,7 @@ func (t Transport) IdleTimeout() time.Duration {
 	return (time.Duration(C.pn_transport_get_idle_timeout(t.pn)) * time.Millisecond)
 }
 func (t Transport) SetIdleTimeout(timeout time.Duration) {
-	C.pn_transport_set_idle_timeout(t.pn, C.pn_millis_t(timeout))
+	C.pn_transport_set_idle_timeout(t.pn, C.pn_millis_t(timeout/time.Millisecond))
 }
 func (t Transport) RemoteIdleTimeout() time.Duration {
 	return (time.Duration(C.pn_transport_get_remote_idle_timeout(t.pn)) * time.Millisecond)


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


[19/50] [abbrv] qpid-proton git commit: PROTON-1327: [Go binding] Replaced c handler based flowcontroller with native go - The go binding now has no dependency on the proton-c reactor code

Posted by ac...@apache.org.
PROTON-1327: [Go binding] Replaced c handler based flowcontroller with native go
- The go binding now has no dependency on the proton-c reactor 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/cd011b6b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/cd011b6b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/cd011b6b

Branch: refs/heads/go1
Commit: cd011b6b2927f9a62b63884db723a496d54fe604
Parents: 5639656
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon Oct 10 15:31:25 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Oct 14 13:39:08 2016 -0400

----------------------------------------------------------------------
 .../go/src/qpid.apache.org/proton/engine.go     |  6 ----
 .../go/src/qpid.apache.org/proton/handlers.go   | 33 +++++++++++---------
 2 files changed, 19 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cd011b6b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
index 7f1368e..a0b8888 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/engine.go
@@ -385,12 +385,6 @@ func (eng *Engine) Run() error {
 	_ = eng.conn.Close() // Close conn, force read/write goroutines to exit (they will Inject)
 	wait.Wait()          // Wait for goroutines
 
-	for _, h := range eng.handlers {
-		switch h := h.(type) {
-		case cHandler:
-			C.pn_handler_free(h.pn)
-		}
-	}
 	C.pn_connection_engine_final(&eng.engine)
 	return eng.err.Get()
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cd011b6b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
index 24e5eb3..8213b65 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/handlers.go
@@ -19,8 +19,6 @@ under the License.
 
 package proton
 
-// #include <proton/handlers.h>
-import "C"
 import "fmt"
 
 // EventHandler handles core proton events.
@@ -31,17 +29,6 @@ type EventHandler interface {
 	HandleEvent(e Event)
 }
 
-// FIXME aconway 2016-06-21: get rid of C handlers?
-
-// cHandler wraps a C pn_handler_t
-type cHandler struct {
-	pn *C.pn_handler_t
-}
-
-func (h cHandler) HandleEvent(e Event) {
-	C.pn_handler_dispatch(h.pn, e.pn, C.pn_event_type(e.pn))
-}
-
 // MessagingHandler provides an alternative interface to EventHandler.
 // it is easier to use for most applications that send and receive messages.
 //
@@ -239,6 +226,24 @@ func (d endpointDelegator) HandleEvent(e Event) {
 	}
 }
 
+type flowcontroller struct {
+	window, drained int
+}
+
+func (d flowcontroller) HandleEvent(e Event) {
+	link := e.Link();
+
+	switch e.Type() {
+	case ELinkLocalOpen, ELinkRemoteOpen, ELinkFlow, EDelivery:
+		if link.IsReceiver() {
+			d.drained += link.Drained()
+			if d.drained != 0 {
+				link.Flow(d.window-link.Credit())
+			}
+		}
+	}
+}
+
 // MessagingAdapter implments a EventHandler and delegates to a MessagingHandler.
 // You can modify the exported fields before you pass the MessagingAdapter to
 // a Engine.
@@ -308,7 +313,7 @@ func (d *MessagingAdapter) HandleEvent(e Event) {
 			d,
 		}
 		if d.Prefetch > 0 {
-			d.flowcontroller = cHandler{C.pn_flowcontroller(C.int(d.Prefetch))}
+			d.flowcontroller = flowcontroller{ window:d.Prefetch, drained:0 }
 		}
 		d.mhandler.HandleMessagingEvent(MStart, e)
 


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


[22/50] [abbrv] qpid-proton git commit: PROTON-1325: Python "buffer" type should map to AMQP "binary"

Posted by ac...@apache.org.
PROTON-1325: Python "buffer" type should map to AMQP "binary"

Add an automatic mapping from a python buffer object to the AMQP binary type.

In the other direction, AMQP "binary" maps to the python "bytes" or "str" type, as before.


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

Branch: refs/heads/go1
Commit: 05deba72edebd0cf1e7bf148ba7e99ab2fb62bfe
Parents: 3dd6994
Author: Alan Conway <ac...@redhat.com>
Authored: Fri Oct 14 14:24:06 2016 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Fri Oct 14 14:37:17 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/python/proton/__init__.py | 3 ++-
 tests/python/proton_tests/codec.py          | 9 +++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/05deba72/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
index 25afa44..1478d38 100644
--- a/proton-c/bindings/python/proton/__init__.py
+++ b/proton-c/bindings/python/proton/__init__.py
@@ -1840,7 +1840,7 @@ class Data:
     @type b: binary
     @param b: a binary value
     """
-    self._check(pn_data_put_binary(self._data, b))
+    self._check(pn_data_put_binary(self._data, bytes(b)))
 
   def put_string(self, s):
     """
@@ -2229,6 +2229,7 @@ class Data:
     list: put_sequence,
     tuple: put_sequence,
     dict: put_dict,
+    buffer: put_binary,
     Described: put_py_described,
     Array: put_py_array
     }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/05deba72/tests/python/proton_tests/codec.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/codec.py b/tests/python/proton_tests/codec.py
index 9f246bf..b7bb04d 100644
--- a/tests/python/proton_tests/codec.py
+++ b/tests/python/proton_tests/codec.py
@@ -357,6 +357,15 @@ class DataTest(Test):
     copy = data.get_object()
     assert copy == obj, (copy, obj)
 
+  def testBuffer(self):
+    self.data.put_object(buffer("foo"))
+    data = Data()
+    data.decode(self.data.encode())
+    data.rewind()
+    assert data.next()
+    assert data.type() == Data.BINARY
+    assert data.get_object() == "foo"
+
   def testLookup(self):
     obj = {symbol("key"): str2unicode("value"),
            symbol("pi"): 3.14159,


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


[36/50] [abbrv] qpid-proton git commit: PROTON-1318: c++ SunStudio: Replace variadic constructor

Posted by ac...@apache.org.
PROTON-1318: c++ SunStudio: Replace variadic constructor

Variadic constructor of "sfinae::wildcard" not supported on SunStudio.

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: 795278665fc90b96ec1091e878972b9112f91569
Parents: 1a20faa
Author: aboutros <ad...@murex.com>
Authored: Fri Oct 7 12:11:58 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Oct 20 08:13:52 2016 -0400

----------------------------------------------------------------------
 proton-c/bindings/cpp/include/proton/codec/encoder.hpp       | 8 ++++----
 .../bindings/cpp/include/proton/internal/type_traits.hpp     | 4 +++-
 2 files changed, 7 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/79527866/proton-c/bindings/cpp/include/proton/codec/encoder.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/codec/encoder.hpp b/proton-c/bindings/cpp/include/proton/codec/encoder.hpp
index b1aff89..9183c07 100644
--- a/proton-c/bindings/cpp/include/proton/codec/encoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/codec/encoder.hpp
@@ -170,15 +170,15 @@ operator<<(encoder& e, T i)  {
 }
 
 /// @cond INTERNAL
-    
-namespace is_encodable_impl {   // Protected the world from wildcard operator<<
+
+namespace is_encodable_impl {   // Protect the world from fallback operator<<
 
 using namespace internal;
 
-sfinae::no operator<<(sfinae::wildcard, sfinae::wildcard); // Fallback
+sfinae::no operator<<(encoder const&, const sfinae::any_t &); // Fallback
 
 template<typename T> struct is_encodable : public sfinae {
-    static yes test(encoder);
+    static yes test(encoder&);
     static no test(...);         // Failed test, no match.
     static encoder* e;
     static const T* t;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/79527866/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp b/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
index 3119804..ee49a15 100644
--- a/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/type_traits.hpp
@@ -152,7 +152,9 @@ struct known_integer : public integer_type<sizeof(T), is_signed<T>::value> {};
 struct sfinae {
     typedef char yes;
     typedef double no;
-    struct wildcard { wildcard(...); };
+    struct any_t {
+        template < typename T > any_t(T const&);
+    };
 };
 
 template <class From, class To> struct is_convertible : public sfinae {


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


[29/50] [abbrv] qpid-proton git commit: PROTON-1315: Force compilation in multi-threading mode for Solaris SunStudio

Posted by ac...@apache.org.
PROTON-1315: Force compilation in multi-threading mode for Solaris SunStudio

Signed-off-by: aboutros <ad...@murex.com>


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

Branch: refs/heads/go1
Commit: 68f64e0fbcec30b05324d46550591b0a5846f280
Parents: 3dd7be3
Author: aboutros <ad...@murex.com>
Authored: Wed Oct 5 10:52:18 2016 +0200
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Oct 19 17:14:47 2016 -0400

----------------------------------------------------------------------
 proton-c/CMakeLists.txt | 9 +++++++++
 1 file changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/68f64e0f/proton-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index f2a5b76..c634113 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -109,6 +109,15 @@ elseif (SASL_IMPL STREQUAL none)
   set(pn_sasl_impl src/sasl/sasl.c src/sasl/none_sasl.c)
 endif ()
 
+# Set Compiler extra flags for Solaris when using SunStudio
+IF( ${CMAKE_CXX_COMPILER_ID} STREQUAL "SunPro" )
+    SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mt" )
+ENDIF()
+
+IF( ${CMAKE_C_COMPILER_ID} STREQUAL "SunPro" )
+    SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mt" )
+ENDIF()
+
 # Link in openssl if present
 if (SSL_IMPL STREQUAL openssl)
   set (pn_ssl_impl src/ssl/openssl.c)


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