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 2017/02/23 22:51:45 UTC

[38/38] qpid-proton git commit: PROTON-1415: Merge branch 'master' into go1

PROTON-1415: Merge branch 'master' into go1

Merge DurableSubscription changes.
Also merge restored compatibility back to proton-c 0.10


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

Branch: refs/heads/go1
Commit: 569b4fca1ecf733bee925cd1abf33541456cf630
Parents: ed8e879 9ec97b5
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Feb 23 17:50:40 2017 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Feb 23 17:50:40 2017 -0500

----------------------------------------------------------------------
 amqp/version.go        |   8 ++-
 electron/connection.go |   2 +-
 electron/link.go       | 128 +++++++++++++++++++++++++++++++++-----------
 electron/link_test.go  |  64 ++++++++++++++++++++++
 proton/wrappers_gen.go |   8 +--
 readme-go-get.md       |   1 +
 6 files changed, 174 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/569b4fca/amqp/version.go
----------------------------------------------------------------------
diff --cc amqp/version.go
index cefa904,0000000..bf33d2b
mode 100644,000000..100644
--- a/amqp/version.go
+++ b/amqp/version.go
@@@ -1,29 -1,0 +1,35 @@@
 +/*
 +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 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
++// #if PN_VERSION_MAJOR == 0 && 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/569b4fca/electron/connection.go
----------------------------------------------------------------------
diff --cc electron/connection.go
index 7f3050f,0000000..8f62491
mode 100644,000000..100644
--- a/electron/connection.go
+++ b/electron/connection.go
@@@ -1,405 -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 (
 +	"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 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)
 +
 +// 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(); c.server = true; AllowIncoming()(c) }
 +}
 +
 +// 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
 +	pConnection proton.Connection
 +
 +	defaultSession Session
 +}
 +
 +// 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
 +	}
 +	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())
 +	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)
 +	}
 +	_ = 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(opts ...SessionOption) (Session, error) {
 +	var s Session
 +	err := c.engine.InjectWait(func() error {
 +		if c.Error() != nil {
 +			return c.Error()
 +		}
 +		pSession, err := c.engine.Connection().Session()
 +		if err == nil {
 +			pSession.Open()
 +			if err == nil {
 +				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(opts ...LinkOption) (Sender, error) {
 +	if s, err := c.DefaultSession(); err == nil {
 +		return s.Sender(opts...)
 +	} else {
 +		return nil, err
 +	}
 +}
 +
 +func (c *connection) Receiver(opts ...LinkOption) (Receiver, error) {
 +	if s, err := c.DefaultSession(); err == nil {
 +		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 {
- 	assert(c.incoming != nil, "electron.Connection.Incoming() disabled for %s", c)
++	assert(c.incoming != nil, "Incoming() is only allowed for a Connection created with the Server() option: %s", c)
 +	return c.incoming
 +}
 +
 +type IncomingConnection struct {
 +	incoming
 +	connectionSettings
 +	c *connection
 +}
 +
 +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}
 +}
 +
 +// 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() }
 +
 +// 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) }
 +}
 +
 +// 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) }
 +}
 +
 +// 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.
 +//
 +// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
 +//
 +func GlobalSASLConfigDir(dir string) { globalSASLConfigDir = dir }
 +
 +// 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
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/569b4fca/electron/link.go
----------------------------------------------------------------------
diff --cc electron/link.go
index 1d17894,0000000..4f927c1
mode 100644,000000..100644
--- a/electron/link.go
+++ b/electron/link.go
@@@ -1,221 -1,0 +1,285 @@@
 +/*
 +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"
++	"time"
 +)
 +
 +// 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
++
++	// Advanced settings for the source
++	SourceSettings() TerminusSettings
++
++	// Advanced settings for the target
++	TargetSettings() TerminusSettings
 +}
 +
 +// 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 } }
++func LinkName(s string) LinkOption { return func(l *linkSettings) { l.linkName = 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 } }
 +
++// DurableSubscription returns a LinkOption that configures a Receiver as a named durable
++// subscription.  The name overrides (and is overridden by) LinkName() so you should normally
++// only use one of these options.
++func DurableSubscription(name string) LinkOption {
++	return func(l *linkSettings) {
++		l.linkName = name
++		l.sourceSettings.Durability = proton.Deliveries
++		l.sourceSettings.Expiry = proton.ExpireNever
++	}
++}
++
 +// 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)
 +	}
 +}
 +
++// SourceSettings returns a LinkOption that sets all the SourceSettings.
++// Note: it will override the source address set by a Source() option
++func SourceSettings(ts TerminusSettings) LinkOption {
++	return func(l *linkSettings) { l.sourceSettings = ts }
++}
++
++// TargetSettings returns a LinkOption that sets all the TargetSettings.
++// Note: it will override the target address set by a Target() option
++func TargetSettings(ts TerminusSettings) LinkOption {
++	return func(l *linkSettings) { l.targetSettings = ts }
++}
++
++// SndSettleMode defines when the sending end of the link settles message delivery.
++type SndSettleMode proton.SndSettleMode
++
 +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
- 	pLink     proton.Link
++	source         string
++	sourceSettings TerminusSettings
++	target         string
++	targetSettings TerminusSettings
++	linkName       string
++	isSender       bool
++	sndSettle      SndSettleMode
++	rcvSettle      RcvSettleMode
++	capacity       int
++	prefetch       bool
++	session        *session
++	pLink          proton.Link
++}
++
++// Advanced AMQP settings for the source or target of a link.
++// Usually these can be set via a more descriptive LinkOption, e.g. DurableSubscription()
++// and do not need to be set/examined directly.
++type TerminusSettings struct {
++	Durability proton.Durability
++	Expiry     proton.ExpiryPolicy
++	Timeout    time.Duration
++	Dynamic    bool
++}
++
++func makeTerminusSettings(t proton.Terminus) TerminusSettings {
++	return TerminusSettings{
++		Durability: t.Durability(),
++		Expiry:     t.ExpiryPolicy(),
++		Timeout:    t.Timeout(),
++		Dynamic:    t.IsDynamic(),
++	}
 +}
 +
 +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 *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 *linkSettings) SourceSettings() TerminusSettings { return l.sourceSettings }
++func (l *linkSettings) TargetSettings() TerminusSettings { return l.targetSettings }
 +
 +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.pLink = l.session.pSession.Sender(l.linkName)
 +	} else {
 +		l.pLink = l.session.pSession.Receiver(l.linkName)
 +	}
 +	if l.pLink.IsNil() {
 +		return l, fmt.Errorf("cannot create link %s", l.pLink)
 +	}
 +	l.pLink.Source().SetAddress(l.source)
++	l.pLink.Source().SetDurability(l.sourceSettings.Durability)
++	l.pLink.Source().SetExpiryPolicy(l.sourceSettings.Expiry)
++	l.pLink.Source().SetTimeout(l.sourceSettings.Timeout)
++	l.pLink.Source().SetDynamic(l.sourceSettings.Dynamic)
++
 +	l.pLink.Target().SetAddress(l.target)
++	l.pLink.Target().SetDurability(l.targetSettings.Durability)
++	l.pLink.Target().SetExpiryPolicy(l.targetSettings.Expiry)
++	l.pLink.Target().SetTimeout(l.targetSettings.Timeout)
++	l.pLink.Target().SetDynamic(l.targetSettings.Dynamic)
++
 +	l.pLink.SetSndSettleMode(proton.SndSettleMode(l.sndSettle))
 +	l.pLink.SetRcvSettleMode(proton.RcvSettleMode(l.rcvSettle))
 +	l.pLink.Open()
 +	return l, nil
 +}
 +
 +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,
++		isSender:       pLink.IsSender(),
++		source:         pLink.RemoteSource().Address(),
++		sourceSettings: makeTerminusSettings(pLink.RemoteSource()),
++		target:         pLink.RemoteTarget().Address(),
++		targetSettings: makeTerminusSettings(pLink.RemoteTarget()),
++		linkName:       pLink.Name(),
++		sndSettle:      SndSettleMode(pLink.RemoteSndSettleMode()),
++		rcvSettle:      RcvSettleMode(pLink.RemoteRcvSettleMode()),
++		capacity:       1,
++		prefetch:       false,
++		pLink:          pLink,
++		session:        sn,
 +	}
 +}
 +
 +// 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.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() {
 +		if l.Error() == nil {
 +			localClose(l.pLink, err)
 +		}
 +	})
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/569b4fca/electron/link_test.go
----------------------------------------------------------------------
diff --cc electron/link_test.go
index 0000000,0000000..133faad
new file mode 100644
--- /dev/null
+++ b/electron/link_test.go
@@@ -1,0 -1,0 +1,64 @@@
++/*
++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 link settings are propagated correctly
++package electron
++
++import (
++	"net"
++	"qpid.apache.org/proton"
++	"testing"
++	"time"
++)
++
++func TestLinkSettings(t *testing.T) {
++	cConn, sConn := net.Pipe()
++	done := make(chan error)
++	// FIXME aconway 2017-02-23: bug in timeout conversion (pn_second_t)
++	settings := TerminusSettings{Durability: 1, Expiry: 2, Timeout: 42 * time.Second, Dynamic: true}
++	go func() { // Server
++		close(done)
++		defer sConn.Close()
++		c, err := NewConnection(sConn, Server())
++		fatalIf(t, err)
++		for in := range c.Incoming() {
++			ep := in.Accept()
++			switch ep := ep.(type) {
++			case Receiver:
++				errorIf(t, checkEqual("one.source", ep.Source()))
++				errorIf(t, checkEqual(TerminusSettings{}, ep.SourceSettings()))
++				errorIf(t, checkEqual("one.target", ep.Target()))
++				errorIf(t, checkEqual(settings, ep.TargetSettings()))
++			case Sender:
++				errorIf(t, checkEqual("two", ep.LinkName()))
++				errorIf(t, checkEqual("two.source", ep.Source()))
++				errorIf(t, checkEqual(TerminusSettings{Durability: proton.Deliveries, Expiry: proton.ExpireNever}, ep.SourceSettings()))
++			}
++		}
++	}()
++
++	// Client
++	c, err := NewConnection(cConn)
++	fatalIf(t, err)
++	c.Sender(Source("one.source"), Target("one.target"), TargetSettings(settings))
++
++	c.Receiver(Source("two.source"), DurableSubscription("two"))
++	c.Close(nil)
++	<-done
++}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/569b4fca/proton/wrappers_gen.go
----------------------------------------------------------------------
diff --cc proton/wrappers_gen.go
index 19bfde2,0000000..0db04c8
mode 100644,000000..100644
--- a/proton/wrappers_gen.go
+++ b/proton/wrappers_gen.go
@@@ -1,937 -1,0 +1,939 @@@
 +/*
 +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/error.h>
 +// #include <proton/event.h>
++// #include <proton/types.h>
 +// #include <stdlib.h>
++import "C"
++
 +// #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) 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)))
++	return int(C.pn_terminus_set_timeout(t.pn, C.pn_seconds_t(timeout/time.Second)))
 +}
 +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) 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/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) 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)
 +}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/569b4fca/readme-go-get.md
----------------------------------------------------------------------
diff --cc readme-go-get.md
index 6eb1e2b,0000000..c59561f
mode 100644,000000..100644
--- a/readme-go-get.md
+++ b/readme-go-get.md
@@@ -1,18 -1,0 +1,19 @@@
 +The go-only subtree of proton is maintained on the branch `go1` for the `go get`
 +command.  `go1` is special to the `go get` command, it will use that branch
 +rather than `master` when it is present.
 +
 +Created with:
 +
 +    git subtree split --prefix=proton-c/bindings/go/src/qpid.apache.org -b go1
 +
 +Update with:
 +
 +    git checkout go1
++    git pull
 +    git merge -s recursive -Xsubtree=proton-c/bindings/go/src/qpid.apache.org master
 +
 +To see the branch description: `git config branch.go1.description`
 +
 +NOTE: when updating the branch, you should also visit the doc pages at
 +https://godoc.org/?q=qpid.apache.org and click "Refresh now" at the bottom of
 +the page


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