This is an automated email from the ASF dual-hosted git repository.

tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton-dotnet.git


The following commit(s) were added to refs/heads/main by this push:
     new e389299  PROTON-2766 Build up more client usage docs
e389299 is described below

commit e389299dc26fa7be8b2ed0ee442e7c192da74371
Author: Timothy Bish <tabish...@gmail.com>
AuthorDate: Thu Sep 28 11:49:50 2023 -0400

    PROTON-2766 Build up more client usage docs
    
    Adds more client usage docs and clean up the overal documentation structure
---
 README.md                                     |   8 +-
 src/Proton.Client/README.md                   |  98 ++-----------------
 src/Proton.Client/{ => docs}/Configuration.md |  26 +++--
 src/Proton.Client/docs/GettingStarted.md      | 121 ++++++++++++++++++++++++
 src/Proton.Client/docs/LargeMessages.md       | 131 ++++++++++++++++++++++++++
 src/Proton.Client/docs/README.md              |  16 ++++
 src/Proton.Client/docs/Reconnection.md        |  88 +++++++++++++++++
 src/Proton/README.md                          |  21 ++++-
 8 files changed, 403 insertions(+), 106 deletions(-)

diff --git a/README.md b/README.md
index 0d9ee0d..1e82eb1 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,7 @@
-# Apache Qpid Proton DotNet
-===========================
+# Apache Qpid proton-dotnet
 
-Qpid Proton DotNet is a high-performance, lightweight AMQP protocol library. 
It can be
-used in the widest range of messaging applications, including brokers, client
-libraries, routers, bridges, proxies, and more.
+Qpid proton-dotnet is a high-performance, lightweight AMQP protocol library. 
It can be used in the widest range of messaging applications, including 
brokers, client libraries, routers, bridges, proxies, and more. This project 
provides an AMQP [protocol engine](src/Proton/README.md) for building your own 
AMQP clients and servers as well as a full featured imperative API 
[client](src/Proton.Client/README.md).
 
 Please see http://qpid.apache.org/proton for more information.
 
+
diff --git a/src/Proton.Client/README.md b/src/Proton.Client/README.md
index b05db6c..7182583 100644
--- a/src/Proton.Client/README.md
+++ b/src/Proton.Client/README.md
@@ -1,106 +1,22 @@
-# Apache Qpid Proton DotNet Client
+# Apache Qpid proton-dotnet Client
 
-Qpid Proton DotNet is a high-performance, lightweight AMQP Client that 
provides an
-imperative API which can be used in the widest range of messaging applications.
+Qpid Proton DotNet is a high-performance, lightweight AMQP Client that 
provides an imperative API which can be used in the widest range of messaging 
applications.
 
 ## Adding the client to your .NET application
 
-Using the `dotnet` CLI you can add a reference to the Qpid proton-dotnet 
client to your application
-which will also download release binaries from the Nuget gallery. The 
following command
-should be run (with the appropriate version updated) in the location where you 
project
-file is saved.
+Using the `dotnet` CLI you can add a reference to the Qpid proton-dotnet 
client to your application which will also download release binaries from the 
Nuget gallery. The following command should be run (with the appropriate 
version updated) in the location where you project file is saved.
 
     dotnet add package Apache.Qpid.Proton.Client --version 1.0.0-M9
 
-Following this command your 'csproj' file should be updated to contain a 
reference to
-to the proton-dotnet client library and should look similar to the following 
example:
+Following this command your 'csproj' file should be updated to contain a 
reference to to the proton-dotnet client library and should look similar to the 
following example:
 
     <ItemGroup>
       <PackageReference Include="Apache.Qpid.Proton.Client" Version="1.0.0-M9" 
/>
     </ItemGroup>
 
-Users can manually add this reference as well and use the `dotnet restore` 
command to
-fetch the artifacts from the Nuget gallery.
+Users can manually add this reference as well and use the `dotnet restore` 
command to fetch the artifacts from the Nuget gallery.
 
-## Creating a connection
+## Client Documentation
 
-The entry point for creating new connections with the proton-dotnet client is 
the IClient
-type which provides a simple static factory method to create new instances.
+The full client documentation is located in the Qpid proton-dotnet client 
[here](docs/README.md).
 
-    IClient container = IClient.Create();
-
-The IClient instance serves as a container for connections created by your 
application and
-can be used to close all active connections and provides the option of adding 
configuration
-to set the AMQP container Id that will be set on connections created from a 
given client
-instance.
-
-Once you have created a IClient instance you can use that to create new 
connections which
-will be of type IConnection. The IClient instance provides API for creating a 
connection
-to a given host and port as well as providing connection options object that 
carry a large
-set of connection specific configuration elements to customize the behavior of 
your connection.
-The basic create API looks as follows:
-
-    IConnection connection = container.Connect(remoteAddress, remotePort, new 
ConnectionOptions());
-
-From you connection instance you can then proceed to create sessions, senders 
and receivers that
-you can use in your application.
-
-### Sending a message
-
-Once you have a connection you can create senders that can be used to send 
messages to a remote
-peer on a specified address. The connection instance provides methods for 
creating senders and
-is used as follows:
-
-    ISender sender = connection.OpenSender("address");
-
-A message instance must be created before you can send it and the IMessage 
interface provides
-simple static factory methods for common message types you might want to send, 
for this example
-we will create a message that carries text in an AmqpValue body section:
-
-    IMessage<string> message = IMessage<string>.Create("Hello World");
-
-Once you have the message that you want to send the previously created sender 
can be used as
-follows:
-
-    ITracker tracker = sender.Send(message);
-
-The Send method of a sender will attempt to send the specified message and if 
the connection
-is open and the send can be performed it will return a ITracker instance to 
provides API for
-checking if the remote has accepted the message or applied other AMQP outcomes 
to the sent
-message.
-
-### Receiving a message
-
-To receive a message sent to the remote peer a Receiver instance must be 
created that listens
-on a given address for new messages to arrive. The connection instance 
provides methods for
-creating receivers and is used as follows:
-
-    IReceiver receiver = connection.OpenReceiver("address");
-
-After creating the receiver the application needs to provide credit to the 
remote which allows
-for control of how many messages a remote can send to the receiver. We will 
add a single credit
-here indicating to the remote that one message can be sent to this receiver:
-
-    receiver.AddCredit(1);
-
-After having granted credit to the above created receiver the application can 
then call one of
-the available receive APIs to await the arrival of a message from a remote 
sender.
-
-    IDelivery delivery = receiver.Receive();
-
-Once a delivery arrives an IDelivery instance is returned which provides API 
to both access
-the delivered message and to provide a disposition to the remote indicating if 
the delivered
-message is accepted or was rejected for some reason etc. The message is 
obtained by calling
-the message API as follows:
-
-    IMessage<object> received = delivery.Message();
-
-Once the message is examined and processed the application can accept delivery 
by calling
-the accept method from the delivery object as follows:
-
-    delivery.Accept();
-
-Other settlement options exist in the delivery API which provide the 
application wil full
-access to the AMQP specification delivery outcomes for the received message.
-
-Please see http://qpid.apache.org/proton for more information.
diff --git a/src/Proton.Client/Configuration.md 
b/src/Proton.Client/docs/Configuration.md
similarity index 96%
rename from src/Proton.Client/Configuration.md
rename to src/Proton.Client/docs/Configuration.md
index 0b7dfbe..f42c4eb 100644
--- a/src/Proton.Client/Configuration.md
+++ b/src/Proton.Client/docs/Configuration.md
@@ -20,10 +20,12 @@ The following options are available for configuration when 
creating a new **Clie
 
 The ConnectionOptions object can be provided to a Client instance when 
creating a new connection and allows configuration of several different aspects 
of the resulting Connection instance.
 
+```
      ConnectionOptions connectionOptions = new();
      connectionOptions.Username = "user";
      connectionOptions.Password = "pass";
-     IConnection connection = client.connect(serverHost, serverPort, 
connectionOptions);
+     IConnection connection = client.Connect(serverHost, serverPort, 
connectionOptions);
+```
 
 The following options are available for configuration when creating a new 
**Connection**.
 
@@ -42,11 +44,13 @@ The following options are available for configuration when 
creating a new **Conn
 
 The ConnectionOptions object exposes a set of configuration options for the 
underlying I/O transport layer known as the TransportOptions which allows for 
fine grained configuration of network level options.
 
+```
      ConnectionOptions connectionOptions = new();
      connectionOptions.TransportOptions.TcpNoDelay = false;
      connectionOptions.Username = "user";
      connectionOptions.Password = "pass";
-     IConnection connection = client.connect(serverHost, serverPort, 
connectionOptions);
+     IConnection connection = client.Connect(serverHost, serverPort, 
connectionOptions);
+```
 
 The following transport layer options are available for configuration when 
creating a new **Connection**.
 
@@ -59,17 +63,19 @@ The following transport layer options are available for 
configuration when creat
 
 If an secure connection is desired the ConnectionOptions exposes another 
options type for configuring the client for that, the SslOptions.
 
+```
      ConnectionOptions connectionOptions = new();
      connectionOptions.Username = "user";
      connectionOptions.Password = "pass";
      connectionOptions.SslOptions.SslEnabled = true;
      connectionOptions.SslOptions.VerifyHost = true;
-     IConnection connection = client.connect(serverHost, serverPort, 
connectionOptions);
+     IConnection connection = client.Connect(serverHost, serverPort, 
connectionOptions);
+```
 
 The following SSL layer options are available for configuration when creating 
a new **Connection**.
 
 + **SslOptions.SslEnabled** Enables or disables the use of the SSL transport 
layer, default is false.
-+ **SslOptions.EnableCertificateRevocationChecks**  Should Cerfiticate 
revocation checks be enabled (defaults to false).
++ **SslOptions.EnableCertificateRevocationChecks**  Should Certificate 
revocation checks be enabled (defaults to false).
 + **SslOptions.VerifyHost** Whether to verify that the hostname being 
connected to matches with the provided server certificate. Defaults to true.
 + **SslOptions.ServerNameOverride** Value used to validate the common name 
(server name) provided in the server certificate, the default is to use the 
host name used on connect.
 
@@ -77,13 +83,15 @@ The following SSL layer options are available for 
configuration when creating a
 
 When creating a new connection it is possible to configure that connection to 
perform automatic connection recovery.
 
+```
      ConnectionOptions connectionOptions = new();
      connectionOptions.Username = "user";
      connectionOptions.Password = "pass";
      connectionOptions.ReconnectionOptions.ReconnectEnabled = true;
      connectionOptions.ReconnectionOptions.ReconnectDelay = 30_000;
      connectionOptions.ReconnectionOptions.AddReconnectLocation(hostname, 
port);
-     IConnection connection = client.connect(serverHost, serverPort, 
connectionOptions);
+     IConnection connection = client.Connect(serverHost, serverPort, 
connectionOptions);
+```
 
 The following connection automatic reconnect options are available for 
configuration when creating a new **Connection**.
 
@@ -101,8 +109,10 @@ The following connection automatic reconnect options are 
available for configura
 
 When creating a new Session the **SessionOptions** object can be provided 
which allows some control over various behaviors of the session.
 
+```
      SessionOptions sessionOptions = new();
      ISession session = connection.OpenSession(sessionOptions);
+```
 
 The following options are available for configuration when creating a new 
**Session**.
 
@@ -145,8 +155,10 @@ The following options are available for configuration when 
creating a new **Rece
 
 When creating a new Sender the **SenderOptions** object can be provided which 
allows some control over various behaviors of the sender.
 
+```
      StreamSenderOptions streamSenderOptions = new();
      IStreamSender streamSender = connection.OpenStreamSender("address", 
streamSenderOptions);
+```
 
 The following options are available for configuration when creating a new 
**StreamSender**.
 
@@ -159,8 +171,10 @@ The following options are available for configuration when 
creating a new **Stre
 
 When creating a new Receiver the **ReceiverOptions** object can be provided 
which allows some control over various behaviors of the receiver.
 
+```
      StreamReceiverOptions streamReceiverOptions = new();
-     IStreamReceiver streamReceiver = connection.openStreamReceiver("address", 
streamReceiverOptions);
+     IStreamReceiver streamReceiver = connection.OpenStreamReceiver("address", 
streamReceiverOptions);
+```
 
 The following options are available for configuration when creating a new 
**StreamReceiver**.
 
diff --git a/src/Proton.Client/docs/GettingStarted.md 
b/src/Proton.Client/docs/GettingStarted.md
new file mode 100644
index 0000000..46c696a
--- /dev/null
+++ b/src/Proton.Client/docs/GettingStarted.md
@@ -0,0 +1,121 @@
+# Getting started with the Qpid proton-dotnet Client Library
+
+This client provides an imperative API for AMQP messaging applications
+
+Below are some quick pointers you might find useful.
+
+## Adding the client to your .NET application
+
+Using the `dotnet` CLI you can add a reference to the Qpid proton-dotnet 
client to your application which will also download release binaries from the 
Nuget gallery. The following command should be run (with the appropriate 
version updated) in the location where you project file is saved.
+
+    dotnet add package Apache.Qpid.Proton.Client --version 1.0.0-M9
+
+Following this command your 'csproj' file should be updated to contain a 
reference to to the proton-dotnet client library and should look similar to the 
following example:
+
+    <ItemGroup>
+      <PackageReference Include="Apache.Qpid.Proton.Client" Version="1.0.0-M9" 
/>
+    </ItemGroup>
+
+Users can manually add this reference as well and use the `dotnet restore` 
command to fetch the artifacts from the Nuget gallery.
+
+## Creating a connection
+
+The entry point for creating new connections with the proton-dotnet client is 
the Client type which provides a simple static factory method to create new 
instances.
+
+```
+    IClient container = IClient.Create();
+```
+
+The ``IClient`` instance serves as a container for connections created by your 
application and can be used to close all active connections and provides the 
option of adding configuration to set the AMQP container Id that will be set on 
connections created from a given client instance.
+
+Once you have created a Client instance you can use that to create new 
connections which will be of type ``IConnection``. The Client instance provides 
API for creating a connection to a given host and port as well as providing 
connection options that carry a large set of connection specific configuration 
elements to customize the behavior of your connection. The basic create API 
looks as follows:
+
+```
+    IConnection connection = container.Connect(remoteAddress, remotePort, new 
ConnectionOptions());
+```
+
+The above code provides host, port and connection options however you may omit 
the options and proceed using client defaults which will be suitable for many 
applications. From your connection instance you can then proceed to create 
sessions, senders and receivers that you can use in your application.
+
+### Sending a message
+
+Once you have a connection you can create senders that can be used to send 
messages to a remote peer on a specified address. The connection instance 
provides methods for creating senders and
+is used as follows:
+
+```
+    ISender sender = connection.OpenSender("address");
+```
+
+A message instance must be created before you can send it and the Message 
interface provides simple static factory methods for comon message types you 
might want to send, for this example
+we will create a message that carries text in an AmqpValue body section:
+
+```
+   IMessage<string> message = IMessage<string>.Create("Hello World");
+```
+
+Once you have the message that you want to send the previously created sender 
can be used as follows:
+
+```
+    ITracker tracker = sender.Send(message);
+```
+
+The Send method of a sender will attempt to send the specified message and if 
the connection is open and the send can be performed it will return a 
``ITracker`` instance to provides API for
+checking if the remote has accepted the message or applied other AMQP outcomes 
to the sent message. The send method can block if the sender lacks credit to 
send at the time it is called, it will await credit from the remote and send 
the message once credit is granted.
+
+#### Creating a message
+
+The application code can create a message to be sent by using static factory 
methods in the ``IMessage`` type that can later be sent using the ``ISender`` 
type. These factory methods accept a few types that map nicely into the 
standard AMQP message format body sections. A typical message creation example 
is shown below.
+
+```
+   IMessage<string> message = IMessage<string>.Create("Hello World");
+```
+
+The above code creates a new message object that carries a string value in the 
body of an AMQP message and it is carried inside an ``AmqpValue`` section. 
Other methods exist that wrap other types in the appropriate section types, a 
list of those is given below:
+
++ **IDictionary** The factory method creates a message with the Map value 
wrapped in an ``AmqpValue`` section.
++ **IList** The factory method creates a message with the List value wrapped 
in an ``AmqpSequence`` section.
++ **byte[]** The factory method creates a message with the byte array wrapped 
in an ``Data`` section.
++ **Object** All other objects are assumed to be types that should be wrapped 
in an ``AmqpValue`` section.
+
+It is also possible to create an empty message and set a body and it will be 
wrapped in AMQP section types following the same rules as listed above. 
Advanced users should spend time reading the API documentation of the 
``IMessage`` type to learn more.
+
+### Receiving a message
+
+To receive a message sent to the remote peer a ``IReceiver`` instance must be 
created that listens on a given address for new messages to arrive. The 
connection instance provides methods for
+creating receivers and is used as follows:
+
+```
+    IReceiver receiver = connection.OpenReceiver("address");
+```
+
+After creating the receiver the application can then call one of the available 
receive APIs to await the arrival of a message from a remote sender.
+
+```
+    IDelivery delivery = receiver.Receive();
+```
+
+By default receivers created from the client API have a credit window 
configured and will manage the outstanding credit with the remote for your 
application however if you have
+configured the client not to manage a credit window for you then your 
application will need to provide receiver credit before invoking the receive 
APIs.
+
+```
+    receiver.AddCredit(1);
+```
+
+Once a delivery arrives an ``IDelivery`` instance is returned which provides 
API to both access the delivered message and to provide a disposition to the 
remote indicating if the delivered
+message is accepted or was rejected for some reason etc. The message is 
obtained by calling the message API as follows:
+
+```
+    IMessage<object> received = delivery.Message();
+```
+
+Once the message is examined and processed the application can accept delivery 
by calling the accept method from the delivery object as follows:
+
+```
+    delivery.Accept();
+```
+
+Other settlement options exist in the delivery API which provide the 
application wil full access to the AMQP specification delivery outcomes for the 
received message.
+
+## Examples
+
+First build and install all the modules as detailed above (if running against 
a source checkout/release, rather than against released binaries) and then 
consult the README in the Examples directory.
+
diff --git a/src/Proton.Client/docs/LargeMessages.md 
b/src/Proton.Client/docs/LargeMessages.md
new file mode 100644
index 0000000..b702a18
--- /dev/null
+++ b/src/Proton.Client/docs/LargeMessages.md
@@ -0,0 +1,131 @@
+# Sending and Receiving large messages with proton-dotnet
+
+When sending and receiving messages whose size exceeds what might otherwise be 
acceptable to having in memory all at once the proton-dotnet client has a 
flexible API to make this process simpler. The stream sender and stream 
receiver APIs in the proton-dotnet client offer the ability to read and write 
messages in manageable chunks that prevent application memory being exhausted 
trying to house the entire message. This API also provides a simple means of 
streaming files directly vs having [...]
+
+## Stream senders and receivers
+
+The API for handling large message is broken out into stream senders and 
stream receivers that behave a bit differently than the standard senders and 
receivers. Unlike the standard sender and receiver which operate on whole in 
memory messages the streaming API makes message content available through 
stream where bytes can be read or written in chunks without the need to have to 
entire contents in memory at once.  Also the underlying streaming 
implementation performs tight flow control to [...]
+
+## Using the stream sender
+
+To send a large message using the stream sender API you need to create a 
``IStreamSender`` type which operates similar to the normal Sender API but 
imposes some restrictions on usage compared to the normal Sender.  Creating the 
stream sender is shown below:
+
+```
+   IStreamSender sender = connection.OpenStreamSender(address)
+```
+
+This code opens a new stream sender for the given address and returns a 
``IStreamSender`` type which you can then use to obtain the streaming message 
type which you will use to write the outgoing bytes. Unlike the standard 
message type the streaming message is created from the sender and it tied 
directly to that sender instance, and only one streaming message can be active 
on a sender at any give time. To create an outbound stream message use the 
following code:
+
+```
+   IStreamSenderMessage message = sender.BeginMessage();
+```
+
+This requests that the sender initiate a new outbound streaming message and 
will throw an exception if another stream sender message is still active. The 
``IStreamSenderMessage`` is a specialized ``IMessage`` type whose body is an 
output stream type meaning that it behaves much like a normal message only the 
application must get a reference to the body output stream to write the 
outgoing bytes. The code below shows how this can be done in practice.
+
+```
+    message.Durable = true;
+    message.SetAnnotation("x-opt-annotation", "value");
+    message.SetProperty("application-property", "value");
+
+    // Creates an OutputStream that writes a single Data Section whose expected
+    // size is configured in the stream options.
+    OutputStreamOptions streamOptions = new()
+    {
+       BodyLength = buffer.Length
+    };
+    Stream output = message.GetBodyStream(streamOptions);
+
+    while (<has data to send>)
+    {
+        output.Write(buffer, i, chunkSize);
+    }
+
+    output.Close();  // This completes the message send.
+
+    message.Tracker().AwaitAccepted();
+```
+
+In the example above the application code has already obtained a stream sender 
message and uses it much like a normal message, setting application properties 
and annotations for the receiver to interpret and then begins writing from some 
data source a stream of bytes that will be encoded into an AMQP ``Data`` 
section as the body of the message, the sender will ensure that the writes 
occur in manageable chunks and will not retain the previously written bytes in 
memory. A write call the th [...]
+
+Once the application has written all the payload into the message it completes 
the operation by closing the ``Stream`` and then it can await settlement from 
the remote to indicate the message was received and processed successfully.
+
+### Sending a large file using the stream sender
+
+Sending a file using the ``IStreamSenderMessage`` is an ideal use case for the 
stream sender. The first thing the application would need to do is to validate 
a file exists and open it (this is omitted here). Once a file has been opened 
the following code can be used to stream to contents to the remote peer.
+
+```
+    using IConnection connection = client.Connect(serverHost, serverPort, 
options);
+    using IStreamSender sender = connection.OpenStreamSender(address);
+    using FileStream inputStream = File.OpenRead(fileName);
+
+    IStreamSenderMessage message = sender.BeginMessage();
+
+    // Application can inform the other side what the original file name was.
+    message.SetProperty(fileNameKey, filename);
+
+    try
+    {
+       using Stream output = message.Body;
+       inputStream.CopyTo(output);
+    }
+    catch (Exception)
+    {
+       message.Abort();
+    }
+```
+
+In the example above the code makes use the .NET API from the ``Stream`` class 
to transfer the contents of a file to the remote peer, the transfer API will 
read the contents of the file in small chunks and write those into the provided 
``Stream`` which in this case is the stream from our ``IStreamSenderMessage``.
+
+## Using the stream receiver
+
+To receive a large message using the stream receiver API you need to create a 
``IStreamReceiver`` type which operates similar to the normal Receiver API but 
imposes some restrictions on usage compared to the normal Sender.  Creating the 
stream receiver is shown below:
+
+```
+    IStreamReceiver receiver = connection.OpenStreamReceiver(address));
+```
+
+This code opens a new stream receiver for the given address and returns a 
``IStreamReceiver`` type which you can then use to obtain the streaming message 
type which you will use to read the incoming bytes. Just like the standard 
message type the streaming message is received from the receiver instance but 
and it is tied directly to that receiver as it read incoming bytes from the 
remote peer, therefore only one streaming message can be active on a receiver 
at any give time. To create an  [...]
+
+```
+    IStreamDelivery delivery = receiver.Receive();
+    IStreamReceiverMessage message = delivery.Message();
+```
+
+Once a new inbound streaming message has been received the application can 
read the bytes by requesting the ``Stream`` from the message body and reading 
from it as one would any other input stream scenario.
+
+```
+    Stream inputStream = message.Body;
+
+    byte[] chunk = new byte[10];
+    int readCount = 0;
+
+    while (inputStream.Read(chunk) != 0)
+    {
+       Console.WriteLine(string.Format("Read data chunk [{0:D2}]: size => 
{1}", ++readCount, chunk.Length));
+    }
+
+```
+
+In the example code above the application reads from the message body input 
stream and simply writes out small chunks of the body to the system console, 
the read calls might block while waiting for bytes to arrive from the remote 
but the application remains unaffected in this case.
+
+### Receiving a large file using the stream receiver
+
+Just as stream sending example from previously sent a large file using the 
``IStreamSenderMessage`` an application can receive and write a large message 
directly into a file with a few quick lines of code.  An example follows which 
shows how this can be done, the application is responsible for choosing a 
proper location for the file and verifying that it has write access.
+
+```
+     using IConnection connection = client.Connect(serverHost, serverPort, 
options);
+     using IStreamReceiver receiver = connection.OpenStreamReceiver(address);
+
+     IStreamDelivery delivery = receiver.Receive();
+     IStreamReceiverMessage message = delivery.Message();
+     Stream inputStream = message.Body;
+
+     // Application needs to define where the file should go
+     using FileStream outputStream = File.Create(outputLocation);
+
+     message.Body.CopyTo(outputStream);
+
+```
+
+Just as in the stream sender case the application can make use of the .NET 
transfer API for ``Stream`` instances to handle the bulk of the work reading 
small blocks of bytes and writing them into the target file, in most cases the 
application should add more error handling code not shown in the example. 
Reading from the incoming byte stream can block waiting for data from the 
remote which may need to be accounted for in some applications.
+
diff --git a/src/Proton.Client/docs/README.md b/src/Proton.Client/docs/README.md
new file mode 100644
index 0000000..b695e9a
--- /dev/null
+++ b/src/Proton.Client/docs/README.md
@@ -0,0 +1,16 @@
+# Qpid proton-dotnet client documentation
+
+The proton-dotnet client is a feature rich AMQP v1.0 client implementing an 
imperative API that offers users full access to the AMQP protocol while being 
easy to use even if you are just getting started with AMQP or Messaging.
+
+The documentation is split up into various sections to make finding help 
easier, if you are new then it is recommended that you read the getting started 
guide first to get a basic overview of the client API.
+
+If you are viewing this documentation from an archive the most current 
versions can be found in the project [source 
repository](https://github.com/apache/qpid-proton-dotnet).
+
+## Where to go next
+
++ [Getting Started Guide](GettingStarted.md)
++ [Configuration Guide](Configuration.md)
++ [Reconnection Support](Reconnection.md)
++ [Large Message Handling](LargeMessages.md)
+
+
diff --git a/src/Proton.Client/docs/Reconnection.md 
b/src/Proton.Client/docs/Reconnection.md
new file mode 100644
index 0000000..dbb84b2
--- /dev/null
+++ b/src/Proton.Client/docs/Reconnection.md
@@ -0,0 +1,88 @@
+# Client Fault Tolerance Configuration
+
+The proton-dotnet client supports configuration to enable a connection to be 
handle both reestablished after an interruption and handling not being able to 
initially connect to a remote peer.
+
+## Enabling Reconnection
+
+By default the client does not attempt to reconnect to the configured remote 
peer, this can be easily done though by toggling the appropriate configuration 
option as follows:
+
+```
+   ConnectionOptions connectionOpts = new();
+   connectionOpts.ReconnectEnabled = true;
+```
+
+Once enabled the client will try indefinitely to connect and if disconnected 
to reconnect to the remote peer that was specified in the connection call that 
created the connection instance.  Additional options exist to control how many 
attempts to connect or reconnect are performed before the client gives up and 
marks the connection as failed. An example of configuring reconnection attempt 
and delays is below, see the full [configuration](Configuration.md) document 
for all the available o [...]
+
+```
+    ConnectionOptions options = new();
+    options.ReconnectOptions.ReconnectEnabled = true;
+    options.ReconnectOptions.MaxReconnectAttempts = 5;
+    options.ReconnectOptions.MaxInitialConnectionAttempts = 5;
+    options.ReconnectOptions.ReconnectDelay = 10;
+```
+
+Additional remote locations can be added to the reconnection options to allow 
for reconnect to an alternative location should the host specified in the 
connect API be unavailable, these hosts will always be tried after the host 
specified in the connect API and will be tried in order until a new connection 
is established.
+
+```
+    ConnectionOptions options = new();
+    options.ReconnectOptions.ReconnectEnabled = true;
+    options.ReconnectOptions.AddReconnectLocation("host2", 5672);
+    options.ReconnectOptions.AddReconnectLocation("host3", 5672);
+    options.ReconnectOptions.AddReconnectLocation("host4", 5672);
+```
+
+## Reconnection and Client behavior
+
+The client reconnect handling is transparent in most cases and application 
code need not be adjusted to handle special case scenarios. In some very 
special cases the application nay need to make some configuration changes 
depending on how the client is used which mostly involves choosing timeouts for 
actions such as send timeouts.
+
+A few select client operations and their behaviors during connection 
interruption as documented below:
+
++ **In Flight Send** A message that was sent and a valid tracker instance was 
returned will throw exception from any of the tracker methods that operate or 
wait on send outcomes which indicate a failure as the client cannot be certain 
if the send completed or failed.
++ **Send blocked on credit** A send that is blocked waiting on credit will 
continue to wait during a connection interruption and only be failed if the 
client reaches configured reconnect limits, or the configured send timeout is 
reached.
++ **Active transactions** If the application begins a new transaction and the 
client connection is interrupted before the transaction is committed the 
transaction will be marked as invalid and any call to commit will throw an 
exception, a call to roll back will succeed.
++ **Handling received messages** If the application received a delivery and 
attempts to accept it (or apply any other outcome) the disposition operation 
will fail indicating the disposition could not be applied.
+
+## Reconnection event notifications
+
+An application can configure event handlers that will be notified for various 
events related to the reconnection handling of the proton-dotnet client. The 
events available for subscription consist of following types:
+
++ **Connected** The client succeeded in establishing an initial connection to 
a remote peer.
++ **Interrupted** The client connection to a remote peer was broken it will 
now attempt to reconnect.
++ **Reconnected** The client succeeded in establishing an new connection to 
remote peer after having been interrupted.
++ **Disconnected** The client failed to establish a new connection and the 
configured attempt limit was reached (if set).
+
+To subscribe to one of the above events the application must set an event 
handler in the connection options instance for the desired event.
+
+As an example the client can set a handler to called upon the first successful 
connection to a remote peer and the event would carry the host and port where 
the connection was established to in a ConnectionEvent object.
+
+```
+    ConnectionOptions options = new();
+
+    options.ConnectedHandler = (conn, location) => ... Your code here ... ;
+
+```
+
+Then to be notified when an active connection is interrupted a handler is set 
in the connection which will be called with an disconnection event that carries 
the host and port that the client was connected to and an exception that 
provides any available details on the reason for disconnection.
+
+```
+    ConnectionOptions options = new();
+
+    options.InterruptedHandler = (conn, location) => ... Your code here ... ;
+
+```
+
+To be notified when a connection that was previously interrupted is 
successfully able to reconnect to one of the configured remote peers the 
reconnection event can be used which will be notified on reconnect and provided 
a connection event object that carries the host and port that the client 
reconnected to:
+
+```
+    ConnectionOptions options = new();
+
+    options.ReconnectedHandler = (conn, location) => ... Your code here ... ;
+```
+
+To be notified when the client has given up on reconnection due to exceeding 
the configured reconnection attempt the application can set a handler on the 
disconnected event which will be given a disconnection event object that 
carries the host and port of the last location the client was successfully 
connected to and an exception object that provides any available details on the 
failure cause.
+
+```
+    ConnectionOptions options = new();
+
+    options.DisconnectedHandler = (conn, location) => ... Your code here ... ;
+```
diff --git a/src/Proton/README.md b/src/Proton/README.md
index e9c8043..c3609db 100644
--- a/src/Proton/README.md
+++ b/src/Proton/README.md
@@ -1,9 +1,22 @@
 # Apache Qpid Proton DotNet
-===========================
 
-Qpid Proton DotNet is a high-performance, lightweight AMQP protocol engine. 
-It can be used to create AMQP 1.0 nessaging clients and servers or in tooling
-that requires a fast AMQP 1.0 protocol codec.
+Qpid proton-dotnet is a high-performance, lightweight AMQP protocol engine. It 
can be used to create AMQP 1.0 nessaging clients and servers or in toolingthat 
requires a fast AMQP 1.0 protocol codec.
+
+## Adding the engine to your .NET application
+
+Using the `dotnet` CLI you can add a reference to the Qpid proton-dotnet 
engine to your application which will also download release binaries from the 
Nuget gallery. The following command
+should be run (with the appropriate version updated) in the location where you 
project file is saved.
+
+    dotnet add package Apache.Qpid.Proton --version 1.0.0-M9
+
+Following this command your 'csproj' file should be updated to contain a 
reference to to the proton-dotnet protocol engine library and should look 
similar to the following example:
+
+    <ItemGroup>
+      <PackageReference Include="Apache.Qpid.Proton" Version="1.0.0-M9" />
+    </ItemGroup>
+
+Users can manually add this reference as well and use the `dotnet restore` 
command to fetch the artifacts from the Nuget gallery.
 
 Please see http://qpid.apache.org/proton for more information.
 
+


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


Reply via email to