normalize eol
This commit is contained in:
Родитель
297f87ef04
Коммит
ed63e4a632
|
@ -0,0 +1,10 @@
|
|||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.exe binary
|
||||
*.dll binary
|
||||
*.pdb binary
|
||||
*.ico binary
|
||||
*.png binary
|
||||
*.jpg binary
|
|
@ -1,28 +1,28 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Navigation;
|
||||
using Device.Controller.Resources;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Navigation;
|
||||
using Device.Controller.Resources;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
|
||||
namespace Device.Controller
|
||||
{
|
||||
public partial class App : Application
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using Device.Controller.Resources;
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
using Device.Controller.Resources;
|
||||
|
||||
namespace Device.Controller
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.Phone.Controls;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Device.Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// The controller runs on Windows Phone 8. The app name is iHome.
|
||||
/// Ensure the broker is running and change the IP address below.
|
||||
/// If using "amqps", ensure the broker certificate can be validated
|
||||
/// on the Phone (e.g. self-generated certificate needs to be imported
|
||||
/// to the phone).
|
||||
/// The app works with the test broker. Start it as follows:
|
||||
/// TestAmqpBroker.exe amqp://localhost:5672 /creds:guest:guest
|
||||
/// Add "/trace:frame" to output frames for debugging if requried.
|
||||
/// An "X" displayed in the middle indicates a connection failure.
|
||||
/// <summary>
|
||||
/// The controller runs on Windows Phone 8. The app name is iHome.
|
||||
/// Ensure the broker is running and change the IP address below.
|
||||
/// If using "amqps", ensure the broker certificate can be validated
|
||||
/// on the Phone (e.g. self-generated certificate needs to be imported
|
||||
/// to the phone).
|
||||
/// The app works with the test broker. Start it as follows:
|
||||
/// TestAmqpBroker.exe amqp://localhost:5672 /creds:guest:guest
|
||||
/// Add "/trace:frame" to output frames for debugging if requried.
|
||||
/// An "X" displayed in the middle indicates a connection failure.
|
||||
/// </summary>
|
||||
public partial class MainPage : PhoneApplicationPage
|
||||
{
|
||||
|
@ -39,15 +39,15 @@ namespace Device.Controller
|
|||
// Constructor
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
try
|
||||
{
|
||||
this.controller = new Controller(this);
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.btnData.Content = "X";
|
||||
this.controller = null;
|
||||
InitializeComponent();
|
||||
try
|
||||
{
|
||||
this.controller = new Controller(this);
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.btnData.Content = "X";
|
||||
this.controller = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace Device.Controller
|
|||
|
||||
public Controller(MainPage parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.parent = parent;
|
||||
Address address = new Address("amqp://guest:guest@10.1.10.76:5672");
|
||||
this.connection = new Connection(address);
|
||||
this.session = new Session(connection);
|
||||
|
@ -86,18 +86,18 @@ namespace Device.Controller
|
|||
}
|
||||
|
||||
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
if (this.controller != null)
|
||||
{
|
||||
this.controller.Control(38);
|
||||
{
|
||||
if (this.controller != null)
|
||||
{
|
||||
this.controller.Control(38);
|
||||
}
|
||||
}
|
||||
|
||||
private void Button_Click_1(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
if (this.controller != null)
|
||||
{
|
||||
this.controller.Control(40);
|
||||
{
|
||||
if (this.controller != null)
|
||||
{
|
||||
this.controller.Control(40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ using System.Resources;
|
|||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Device.Controller")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Device.Controller")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
|
|
@ -1,108 +1,108 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Device.Controller.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class AppResources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal AppResources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Device.Controller.Resources.AppResources", typeof(AppResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to add.
|
||||
/// </summary>
|
||||
public static string AppBarButtonText {
|
||||
get {
|
||||
return ResourceManager.GetString("AppBarButtonText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Menu Item.
|
||||
/// </summary>
|
||||
public static string AppBarMenuItemText {
|
||||
get {
|
||||
return ResourceManager.GetString("AppBarMenuItemText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to MY APPLICATION.
|
||||
/// </summary>
|
||||
public static string ApplicationTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ApplicationTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to LeftToRight.
|
||||
/// </summary>
|
||||
public static string ResourceFlowDirection {
|
||||
get {
|
||||
return ResourceManager.GetString("ResourceFlowDirection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to en-US.
|
||||
/// </summary>
|
||||
public static string ResourceLanguage {
|
||||
get {
|
||||
return ResourceManager.GetString("ResourceLanguage", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Device.Controller.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class AppResources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal AppResources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Device.Controller.Resources.AppResources", typeof(AppResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to add.
|
||||
/// </summary>
|
||||
public static string AppBarButtonText {
|
||||
get {
|
||||
return ResourceManager.GetString("AppBarButtonText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Menu Item.
|
||||
/// </summary>
|
||||
public static string AppBarMenuItemText {
|
||||
get {
|
||||
return ResourceManager.GetString("AppBarMenuItemText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to MY APPLICATION.
|
||||
/// </summary>
|
||||
public static string ApplicationTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ApplicationTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to LeftToRight.
|
||||
/// </summary>
|
||||
public static string ResourceFlowDirection {
|
||||
get {
|
||||
return ResourceManager.GetString("ResourceFlowDirection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to en-US.
|
||||
/// </summary>
|
||||
public static string ResourceLanguage {
|
||||
get {
|
||||
return ResourceManager.GetString("ResourceLanguage", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ using System;
|
|||
using Microsoft.SPOT;
|
||||
using Microsoft.SPOT.Input;
|
||||
using Microsoft.SPOT.Hardware;
|
||||
using Microsoft.SPOT.Presentation;
|
||||
|
||||
using Microsoft.SPOT.Presentation;
|
||||
|
||||
namespace Device.Thermometer
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Microsoft.SPOT;
|
||||
using Microsoft.SPOT.Input;
|
||||
using Microsoft.SPOT.Presentation;
|
||||
using Microsoft.SPOT.Presentation.Controls;
|
||||
using AmqpTrace = Amqp.Trace;
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Microsoft.SPOT;
|
||||
using Microsoft.SPOT.Input;
|
||||
using Microsoft.SPOT.Presentation;
|
||||
using Microsoft.SPOT.Presentation.Controls;
|
||||
using AmqpTrace = Amqp.Trace;
|
||||
|
||||
namespace Device.Thermometer
|
||||
{
|
||||
/// The thermomeer runs on NETMF. It displays a number for the current
|
||||
/// temprature. Click up and down buttons to increase/decrease the number.
|
||||
/// Ensure the broker is running and change the host name below.
|
||||
/// If using "amqps", ensure SSL is working on the device.
|
||||
/// The app works with the test broker. Start it as follows:
|
||||
/// TestAmqpBroker.exe amqp://localhost:5672 /creds:guest:guest
|
||||
/// Add "/trace:frame" to output frames for debugging if requried.
|
||||
{
|
||||
/// The thermomeer runs on NETMF. It displays a number for the current
|
||||
/// temprature. Click up and down buttons to increase/decrease the number.
|
||||
/// Ensure the broker is running and change the host name below.
|
||||
/// If using "amqps", ensure SSL is working on the device.
|
||||
/// The app works with the test broker. Start it as follows:
|
||||
/// TestAmqpBroker.exe amqp://localhost:5672 /creds:guest:guest
|
||||
/// Add "/trace:frame" to output frames for debugging if requried.
|
||||
public class Program : Application
|
||||
{
|
||||
{
|
||||
string address = "amqp://guest:guest@localhost:5672";
|
||||
Text text;
|
||||
int temperature;
|
||||
|
@ -57,33 +57,33 @@ namespace Device.Thermometer
|
|||
}
|
||||
|
||||
private void Listen()
|
||||
{
|
||||
// real applicaiton needs to implement error handling and recovery
|
||||
Connection connection = new Connection(new Address(this.address));
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "send-link", "data");
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receive-link", "control");
|
||||
receiver.Start(100, this.OnMessage);
|
||||
{
|
||||
// real applicaiton needs to implement error handling and recovery
|
||||
Connection connection = new Connection(new Address(this.address));
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "send-link", "data");
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receive-link", "control");
|
||||
receiver.Start(100, this.OnMessage);
|
||||
|
||||
while (true)
|
||||
{
|
||||
this.changed.WaitOne();
|
||||
|
||||
Message message = new Message();
|
||||
message.ApplicationProperties = new Amqp.Framing.ApplicationProperties();
|
||||
message.ApplicationProperties["temperature"] = this.temperature;
|
||||
sender.Send(message, null, null);
|
||||
AmqpTrace.WriteLine(TraceLevel.Information, "sent data to monitor");
|
||||
{
|
||||
this.changed.WaitOne();
|
||||
|
||||
Message message = new Message();
|
||||
message.ApplicationProperties = new Amqp.Framing.ApplicationProperties();
|
||||
message.ApplicationProperties["temperature"] = this.temperature;
|
||||
sender.Send(message, null, null);
|
||||
AmqpTrace.WriteLine(TraceLevel.Information, "sent data to monitor");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMessage(ReceiverLink receiver, Message message)
|
||||
{
|
||||
AmqpTrace.WriteLine(TraceLevel.Information, "received command from controller");
|
||||
int button = (int)message.ApplicationProperties["button"];
|
||||
this.OnAction(button);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnMessage(ReceiverLink receiver, Message message)
|
||||
{
|
||||
AmqpTrace.WriteLine(TraceLevel.Information, "received command from controller");
|
||||
int button = (int)message.ApplicationProperties["button"];
|
||||
this.OnAction(button);
|
||||
}
|
||||
|
||||
private void OnAction(int button)
|
||||
{
|
||||
WriteTrace("receive action: {0}", button);
|
||||
|
@ -120,8 +120,8 @@ namespace Device.Thermometer
|
|||
// size of the display.
|
||||
Window window = new Window();
|
||||
window.Height = SystemMetrics.ScreenHeight;
|
||||
window.Width = SystemMetrics.ScreenWidth;
|
||||
|
||||
window.Width = SystemMetrics.ScreenWidth;
|
||||
|
||||
// Create a single text control.
|
||||
Text text = new Text();
|
||||
text.TextContent = this.temperature.ToString();
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Device.Thermometer
|
||||
{
|
||||
|
||||
internal partial class Resources
|
||||
{
|
||||
private static System.Resources.ResourceManager manager;
|
||||
internal static System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((Resources.manager == null))
|
||||
{
|
||||
Resources.manager = new System.Resources.ResourceManager("Device.Thermometer.Resources", typeof(Resources).Assembly);
|
||||
}
|
||||
return Resources.manager;
|
||||
}
|
||||
}
|
||||
internal static Microsoft.SPOT.Font GetFont(Resources.FontResources id)
|
||||
{
|
||||
return ((Microsoft.SPOT.Font)(Microsoft.SPOT.ResourceUtility.GetObject(ResourceManager, id)));
|
||||
}
|
||||
internal static string GetString(Resources.StringResources id)
|
||||
{
|
||||
return ((string)(Microsoft.SPOT.ResourceUtility.GetObject(ResourceManager, id)));
|
||||
}
|
||||
[System.SerializableAttribute()]
|
||||
internal enum StringResources : short
|
||||
{
|
||||
String1 = 1228,
|
||||
}
|
||||
[System.SerializableAttribute()]
|
||||
internal enum FontResources : short
|
||||
{
|
||||
small = 13070,
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Device.Thermometer
|
||||
{
|
||||
|
||||
internal partial class Resources
|
||||
{
|
||||
private static System.Resources.ResourceManager manager;
|
||||
internal static System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((Resources.manager == null))
|
||||
{
|
||||
Resources.manager = new System.Resources.ResourceManager("Device.Thermometer.Resources", typeof(Resources).Assembly);
|
||||
}
|
||||
return Resources.manager;
|
||||
}
|
||||
}
|
||||
internal static Microsoft.SPOT.Font GetFont(Resources.FontResources id)
|
||||
{
|
||||
return ((Microsoft.SPOT.Font)(Microsoft.SPOT.ResourceUtility.GetObject(ResourceManager, id)));
|
||||
}
|
||||
internal static string GetString(Resources.StringResources id)
|
||||
{
|
||||
return ((string)(Microsoft.SPOT.ResourceUtility.GetObject(ResourceManager, id)));
|
||||
}
|
||||
[System.SerializableAttribute()]
|
||||
internal enum StringResources : short
|
||||
{
|
||||
String1 = 1228,
|
||||
}
|
||||
[System.SerializableAttribute()]
|
||||
internal enum FontResources : short
|
||||
{
|
||||
small = 13070,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,134 +1,134 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Examples.Interop
|
||||
{
|
||||
class Client
|
||||
{
|
||||
//
|
||||
// Return message as string.
|
||||
//
|
||||
static String GetContent(Message msg)
|
||||
{
|
||||
object body = msg.Body;
|
||||
return body == null ? null : body.ToString();
|
||||
}
|
||||
|
||||
//
|
||||
// Sample invocation: Interop.Client amqp://guest:guest@localhost:5672 [loopcount]
|
||||
//
|
||||
static int Main(string[] args)
|
||||
{
|
||||
String url = "amqp://guest:guest@localhost:5672";
|
||||
String requestQueueName = "service_queue";
|
||||
int loopcount = 1;
|
||||
|
||||
if (args.Length > 0)
|
||||
url = args[0];
|
||||
if (args.Length > 1)
|
||||
loopcount = Convert.ToInt32(args[1]);
|
||||
|
||||
Connection.DisableServerCertValidation = true;
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Address address = new Address(url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
|
||||
// Sender attaches to fixed request queue name
|
||||
SenderLink sender = new SenderLink(session, "Interop.Client-sender", requestQueueName);
|
||||
|
||||
// Receiver attaches to dynamic address.
|
||||
// Discover its name when it attaches.
|
||||
String replyTo = "";
|
||||
ManualResetEvent receiverAttached = new ManualResetEvent(false);
|
||||
OnAttached onReceiverAttached = (l, a) =>
|
||||
{
|
||||
replyTo = ((Source)a.Source).Address;
|
||||
receiverAttached.Set();
|
||||
};
|
||||
|
||||
// Create receiver and wait for it to attach.
|
||||
ReceiverLink receiver = new ReceiverLink(
|
||||
session, "Interop.Client-receiver", new Source() { Dynamic = true }, onReceiverAttached);
|
||||
if (receiverAttached.WaitOne(10000))
|
||||
{
|
||||
// Receiver is attached.
|
||||
// Send a series of requests, gather and print responses.
|
||||
String[] requests = new String[] {
|
||||
"Twas brillig, and the slithy toves",
|
||||
"Did gire and gymble in the wabe.",
|
||||
"All mimsy were the borogoves,",
|
||||
"And the mome raths outgrabe."
|
||||
};
|
||||
|
||||
for (int j = 0; j < loopcount; j++)
|
||||
{
|
||||
Console.WriteLine("Pass {0}", j);
|
||||
for (int i = 0; i < requests.Length; i++)
|
||||
{
|
||||
Message request = new Message(requests[i]);
|
||||
request.Properties = new Properties() { MessageId = "request" + i, ReplyTo = replyTo };
|
||||
sender.Send(request);
|
||||
Message response = receiver.Receive(10000);
|
||||
if (null != response)
|
||||
{
|
||||
receiver.Accept(response);
|
||||
Console.WriteLine("Processed request: {0} -> {1}",
|
||||
GetContent(request), GetContent(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Receiver timeout receiving response {0}", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Receiver attach timeout");
|
||||
}
|
||||
receiver.Close();
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Examples.Interop
|
||||
{
|
||||
class Client
|
||||
{
|
||||
//
|
||||
// Return message as string.
|
||||
//
|
||||
static String GetContent(Message msg)
|
||||
{
|
||||
object body = msg.Body;
|
||||
return body == null ? null : body.ToString();
|
||||
}
|
||||
|
||||
//
|
||||
// Sample invocation: Interop.Client amqp://guest:guest@localhost:5672 [loopcount]
|
||||
//
|
||||
static int Main(string[] args)
|
||||
{
|
||||
String url = "amqp://guest:guest@localhost:5672";
|
||||
String requestQueueName = "service_queue";
|
||||
int loopcount = 1;
|
||||
|
||||
if (args.Length > 0)
|
||||
url = args[0];
|
||||
if (args.Length > 1)
|
||||
loopcount = Convert.ToInt32(args[1]);
|
||||
|
||||
Connection.DisableServerCertValidation = true;
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Address address = new Address(url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
|
||||
// Sender attaches to fixed request queue name
|
||||
SenderLink sender = new SenderLink(session, "Interop.Client-sender", requestQueueName);
|
||||
|
||||
// Receiver attaches to dynamic address.
|
||||
// Discover its name when it attaches.
|
||||
String replyTo = "";
|
||||
ManualResetEvent receiverAttached = new ManualResetEvent(false);
|
||||
OnAttached onReceiverAttached = (l, a) =>
|
||||
{
|
||||
replyTo = ((Source)a.Source).Address;
|
||||
receiverAttached.Set();
|
||||
};
|
||||
|
||||
// Create receiver and wait for it to attach.
|
||||
ReceiverLink receiver = new ReceiverLink(
|
||||
session, "Interop.Client-receiver", new Source() { Dynamic = true }, onReceiverAttached);
|
||||
if (receiverAttached.WaitOne(10000))
|
||||
{
|
||||
// Receiver is attached.
|
||||
// Send a series of requests, gather and print responses.
|
||||
String[] requests = new String[] {
|
||||
"Twas brillig, and the slithy toves",
|
||||
"Did gire and gymble in the wabe.",
|
||||
"All mimsy were the borogoves,",
|
||||
"And the mome raths outgrabe."
|
||||
};
|
||||
|
||||
for (int j = 0; j < loopcount; j++)
|
||||
{
|
||||
Console.WriteLine("Pass {0}", j);
|
||||
for (int i = 0; i < requests.Length; i++)
|
||||
{
|
||||
Message request = new Message(requests[i]);
|
||||
request.Properties = new Properties() { MessageId = "request" + i, ReplyTo = replyTo };
|
||||
sender.Send(request);
|
||||
Message response = receiver.Receive(10000);
|
||||
if (null != response)
|
||||
{
|
||||
receiver.Accept(response);
|
||||
Console.WriteLine("Processed request: {0} -> {1}",
|
||||
GetContent(request), GetContent(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Receiver timeout receiving response {0}", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Receiver attach timeout");
|
||||
}
|
||||
receiver.Close();
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Examples.Interop
|
||||
{
|
||||
|
|
|
@ -1,84 +1,84 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Examples.Interop {
|
||||
class Drain {
|
||||
//
|
||||
// Sample invocation: Interop.Drain.exe --broker localhost:5672 --timeout 30 --address my-queue
|
||||
//
|
||||
static int Main(string[] args) {
|
||||
const int ERROR_SUCCESS = 0;
|
||||
const int ERROR_NO_MESSAGE = 1;
|
||||
const int ERROR_OTHER = 2;
|
||||
|
||||
int exitCode = ERROR_SUCCESS;
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Options options = new Options(args);
|
||||
|
||||
Address address = new Address(options.Url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-drain", options.Address);
|
||||
int timeout = int.MaxValue;
|
||||
if (!options.Forever)
|
||||
timeout = 1000 * options.Timeout;
|
||||
Message message = new Message();
|
||||
int nReceived = 0;
|
||||
receiver.SetCredit(options.InitialCredit);
|
||||
while ((message = receiver.Receive(null, timeout)) != null)
|
||||
{
|
||||
nReceived++;
|
||||
if (!options.Quiet)
|
||||
{
|
||||
Console.WriteLine("Message(Properties={0}, ApplicationProperties={1}, Body={2}",
|
||||
message.Properties, message.ApplicationProperties, message.Body);
|
||||
}
|
||||
receiver.Accept(message);
|
||||
if (options.Count > 0 && nReceived == options.Count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (message == null)
|
||||
{
|
||||
exitCode = ERROR_NO_MESSAGE;
|
||||
}
|
||||
receiver.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
connection.Close();
|
||||
exitCode = ERROR_OTHER;
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Examples.Interop {
|
||||
class Drain {
|
||||
//
|
||||
// Sample invocation: Interop.Drain.exe --broker localhost:5672 --timeout 30 --address my-queue
|
||||
//
|
||||
static int Main(string[] args) {
|
||||
const int ERROR_SUCCESS = 0;
|
||||
const int ERROR_NO_MESSAGE = 1;
|
||||
const int ERROR_OTHER = 2;
|
||||
|
||||
int exitCode = ERROR_SUCCESS;
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Options options = new Options(args);
|
||||
|
||||
Address address = new Address(options.Url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-drain", options.Address);
|
||||
int timeout = int.MaxValue;
|
||||
if (!options.Forever)
|
||||
timeout = 1000 * options.Timeout;
|
||||
Message message = new Message();
|
||||
int nReceived = 0;
|
||||
receiver.SetCredit(options.InitialCredit);
|
||||
while ((message = receiver.Receive(null, timeout)) != null)
|
||||
{
|
||||
nReceived++;
|
||||
if (!options.Quiet)
|
||||
{
|
||||
Console.WriteLine("Message(Properties={0}, ApplicationProperties={1}, Body={2}",
|
||||
message.Properties, message.ApplicationProperties, message.Body);
|
||||
}
|
||||
receiver.Accept(message);
|
||||
if (options.Count > 0 && nReceived == options.Count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (message == null)
|
||||
{
|
||||
exitCode = ERROR_NO_MESSAGE;
|
||||
}
|
||||
receiver.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
connection.Close();
|
||||
exitCode = ERROR_OTHER;
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
|
@ -1,112 +1,112 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Interop.Server
|
||||
{
|
||||
class Server
|
||||
{
|
||||
//
|
||||
// Return message as string.
|
||||
//
|
||||
static String GetContent(Message msg)
|
||||
{
|
||||
object body = msg.Body;
|
||||
return body == null ? null : body.ToString();
|
||||
}
|
||||
|
||||
//
|
||||
// Sample invocation: Interop.Server amqp://guest:guest@localhost:5672
|
||||
//
|
||||
static int Main(string[] args)
|
||||
{
|
||||
String url = "amqp://guest:guest@127.0.0.1:5672";
|
||||
String requestQueueName = "service_queue";
|
||||
|
||||
if (args.Length > 0)
|
||||
url = args[0];
|
||||
|
||||
Connection.DisableServerCertValidation = true;
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Address address = new Address(url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
|
||||
// Create server receiver link
|
||||
// When messages arrive, reply to them
|
||||
ReceiverLink receiver = new ReceiverLink(session, "Interop.Server-receiver", requestQueueName);
|
||||
int linkId = 0;
|
||||
while (true)
|
||||
{
|
||||
Message request = receiver.Receive();
|
||||
if (null != request)
|
||||
{
|
||||
receiver.Accept(request);
|
||||
String replyTo = request.Properties.ReplyTo;
|
||||
SenderLink sender = new SenderLink(session, "Interop.Server-sender-" + (++linkId).ToString(), replyTo);
|
||||
|
||||
Message response = new Message(GetContent(request).ToUpper());
|
||||
response.Properties = new Properties() { CorrelationId = request.Properties.MessageId };
|
||||
|
||||
try
|
||||
{
|
||||
sender.Send(response, 10000);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine("Error waiting for response to be sent: {0} exception {1}",
|
||||
GetContent(response), exception.Message);
|
||||
break;
|
||||
}
|
||||
sender.Close();
|
||||
Console.WriteLine("Processed request: {0} -> {1}",
|
||||
GetContent(request), GetContent(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
// timed out waiting for request. This is normal.
|
||||
Console.WriteLine("Timeout waiting for request. Keep waiting...");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
namespace Interop.Server
|
||||
{
|
||||
class Server
|
||||
{
|
||||
//
|
||||
// Return message as string.
|
||||
//
|
||||
static String GetContent(Message msg)
|
||||
{
|
||||
object body = msg.Body;
|
||||
return body == null ? null : body.ToString();
|
||||
}
|
||||
|
||||
//
|
||||
// Sample invocation: Interop.Server amqp://guest:guest@localhost:5672
|
||||
//
|
||||
static int Main(string[] args)
|
||||
{
|
||||
String url = "amqp://guest:guest@127.0.0.1:5672";
|
||||
String requestQueueName = "service_queue";
|
||||
|
||||
if (args.Length > 0)
|
||||
url = args[0];
|
||||
|
||||
Connection.DisableServerCertValidation = true;
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
Address address = new Address(url);
|
||||
connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
|
||||
// Create server receiver link
|
||||
// When messages arrive, reply to them
|
||||
ReceiverLink receiver = new ReceiverLink(session, "Interop.Server-receiver", requestQueueName);
|
||||
int linkId = 0;
|
||||
while (true)
|
||||
{
|
||||
Message request = receiver.Receive();
|
||||
if (null != request)
|
||||
{
|
||||
receiver.Accept(request);
|
||||
String replyTo = request.Properties.ReplyTo;
|
||||
SenderLink sender = new SenderLink(session, "Interop.Server-sender-" + (++linkId).ToString(), replyTo);
|
||||
|
||||
Message response = new Message(GetContent(request).ToUpper());
|
||||
response.Properties = new Properties() { CorrelationId = request.Properties.MessageId };
|
||||
|
||||
try
|
||||
{
|
||||
sender.Send(response, 10000);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine("Error waiting for response to be sent: {0} exception {1}",
|
||||
GetContent(response), exception.Message);
|
||||
break;
|
||||
}
|
||||
sender.Close();
|
||||
Console.WriteLine("Processed request: {0} -> {1}",
|
||||
GetContent(request), GetContent(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
// timed out waiting for request. This is normal.
|
||||
Console.WriteLine("Timeout waiting for request. Keep waiting...");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception {0}.", e);
|
||||
if (null != connection)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Examples.Interop
|
||||
{
|
||||
using System;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,97 +1,97 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace PeerToPeer.Client
|
||||
{
|
||||
using System;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string address = "amqp://guest:guest@127.0.0.1:5672";
|
||||
if (args.Length > 0)
|
||||
{
|
||||
address = args[0];
|
||||
}
|
||||
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Console.WriteLine("Running message client...");
|
||||
RunMessageClient(address);
|
||||
|
||||
Console.WriteLine("Running request client...");
|
||||
RunRequestClient(address);
|
||||
}
|
||||
|
||||
static void RunMessageClient(string address)
|
||||
{
|
||||
const int nMsgs = 10;
|
||||
Connection connection = new Connection(new Address(address));
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "message-client", "message_processor");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message("hello");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
sender.Send(message);
|
||||
Console.WriteLine("Sent message {0} body {1}", message.Properties, message.Body);
|
||||
}
|
||||
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
static void RunRequestClient(string address)
|
||||
{
|
||||
Connection connection = new Connection(new Address(address));
|
||||
Session session = new Session(connection);
|
||||
|
||||
string replyTo = "client-reply-to";
|
||||
Attach recvAttach = new Attach()
|
||||
{
|
||||
Source = new Source() { Address = "request_processor" },
|
||||
Target = new Target() { Address = replyTo }
|
||||
};
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "request-client-receiver", recvAttach, null);
|
||||
SenderLink sender = new SenderLink(session, "request-client-sender", "request_processor");
|
||||
|
||||
Message request = new Message("hello");
|
||||
request.Properties = new Properties() { MessageId = "request1", ReplyTo = replyTo };
|
||||
sender.Send(request, null, null);
|
||||
Console.WriteLine("Sent request {0} body {1}", request.Properties, request.Body);
|
||||
|
||||
Message response = receiver.Receive();
|
||||
Console.WriteLine("Received response: {0} body {1}", response.Properties, response.Body);
|
||||
receiver.Accept(response);
|
||||
|
||||
receiver.Close();
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace PeerToPeer.Client
|
||||
{
|
||||
using System;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string address = "amqp://guest:guest@127.0.0.1:5672";
|
||||
if (args.Length > 0)
|
||||
{
|
||||
address = args[0];
|
||||
}
|
||||
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Console.WriteLine("Running message client...");
|
||||
RunMessageClient(address);
|
||||
|
||||
Console.WriteLine("Running request client...");
|
||||
RunRequestClient(address);
|
||||
}
|
||||
|
||||
static void RunMessageClient(string address)
|
||||
{
|
||||
const int nMsgs = 10;
|
||||
Connection connection = new Connection(new Address(address));
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "message-client", "message_processor");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message("hello");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
sender.Send(message);
|
||||
Console.WriteLine("Sent message {0} body {1}", message.Properties, message.Body);
|
||||
}
|
||||
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
static void RunRequestClient(string address)
|
||||
{
|
||||
Connection connection = new Connection(new Address(address));
|
||||
Session session = new Session(connection);
|
||||
|
||||
string replyTo = "client-reply-to";
|
||||
Attach recvAttach = new Attach()
|
||||
{
|
||||
Source = new Source() { Address = "request_processor" },
|
||||
Target = new Target() { Address = replyTo }
|
||||
};
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "request-client-receiver", recvAttach, null);
|
||||
SenderLink sender = new SenderLink(session, "request-client-sender", "request_processor");
|
||||
|
||||
Message request = new Message("hello");
|
||||
request.Properties = new Properties() { MessageId = "request1", ReplyTo = replyTo };
|
||||
sender.Send(request, null, null);
|
||||
Console.WriteLine("Sent request {0} body {1}", request.Properties, request.Body);
|
||||
|
||||
Message response = receiver.Receive();
|
||||
Console.WriteLine("Received response: {0} body {1}", response.Properties, response.Body);
|
||||
receiver.Accept(response);
|
||||
|
||||
receiver.Close();
|
||||
sender.Close();
|
||||
session.Close();
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PeerToPeer.Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PeerToPeer.Client")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("3f7eff2d-c9f0-4131-a5f2-09167b969c02")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PeerToPeer.Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PeerToPeer.Client")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("3f7eff2d-c9f0-4131-a5f2-09167b969c02")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,91 +1,91 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace PeerToPeer.Server
|
||||
{
|
||||
using System;
|
||||
using Amqp;
|
||||
using Amqp.Listener;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string address = "amqp://guest:guest@127.0.0.1:5672";
|
||||
if (args.Length > 0)
|
||||
{
|
||||
address = args[0];
|
||||
}
|
||||
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Uri addressUri = new Uri(address);
|
||||
ContainerHost host = new ContainerHost(new Uri[] { addressUri }, null, addressUri.UserInfo);
|
||||
host.Open();
|
||||
Console.WriteLine("Container host is listening on {0}:{1}", addressUri.Host, addressUri.Port);
|
||||
|
||||
string messageProcessor = "message_processor";
|
||||
host.RegisterMessageProcessor(messageProcessor, new MessageProcessor());
|
||||
Console.WriteLine("Message processor is registered on {0}", messageProcessor);
|
||||
|
||||
string requestProcessor = "request_processor";
|
||||
host.RegisterRequestProcessor(requestProcessor, new RequestProcessor());
|
||||
Console.WriteLine("Request processor is registered on {0}", requestProcessor);
|
||||
|
||||
Console.WriteLine("Press enter key to exist...");
|
||||
Console.ReadLine();
|
||||
|
||||
host.Close();
|
||||
}
|
||||
|
||||
static void PrintMessage(Message message)
|
||||
{
|
||||
if (message.Header != null) Console.WriteLine(message.Header.ToString());
|
||||
if (message.DeliveryAnnotations != null) Console.WriteLine(message.DeliveryAnnotations.ToString());
|
||||
if (message.MessageAnnotations != null) Console.WriteLine(message.MessageAnnotations.ToString());
|
||||
if (message.Properties != null) Console.WriteLine(message.Properties.ToString());
|
||||
if (message.ApplicationProperties != null) Console.WriteLine(message.ApplicationProperties.ToString());
|
||||
if (message.BodySection != null) Console.WriteLine("body:{0}", message.Body.ToString());
|
||||
if (message.Footer != null) Console.WriteLine(message.Footer.ToString());
|
||||
}
|
||||
|
||||
class MessageProcessor : IMessageProcessor
|
||||
{
|
||||
void IMessageProcessor.Process(MessageContext messageContext)
|
||||
{
|
||||
Console.WriteLine("Received a message.");
|
||||
PrintMessage(messageContext.Message);
|
||||
|
||||
messageContext.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
class RequestProcessor : IRequestProcessor
|
||||
{
|
||||
void IRequestProcessor.Process(RequestContext requestContext)
|
||||
{
|
||||
Console.WriteLine("Received a request.");
|
||||
PrintMessage(requestContext.Message);
|
||||
|
||||
Message response = new Message("welcome");
|
||||
requestContext.Complete(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace PeerToPeer.Server
|
||||
{
|
||||
using System;
|
||||
using Amqp;
|
||||
using Amqp.Listener;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string address = "amqp://guest:guest@127.0.0.1:5672";
|
||||
if (args.Length > 0)
|
||||
{
|
||||
address = args[0];
|
||||
}
|
||||
|
||||
// uncomment the following to write frame traces
|
||||
//Trace.TraceLevel = TraceLevel.Frame;
|
||||
//Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
Uri addressUri = new Uri(address);
|
||||
ContainerHost host = new ContainerHost(new Uri[] { addressUri }, null, addressUri.UserInfo);
|
||||
host.Open();
|
||||
Console.WriteLine("Container host is listening on {0}:{1}", addressUri.Host, addressUri.Port);
|
||||
|
||||
string messageProcessor = "message_processor";
|
||||
host.RegisterMessageProcessor(messageProcessor, new MessageProcessor());
|
||||
Console.WriteLine("Message processor is registered on {0}", messageProcessor);
|
||||
|
||||
string requestProcessor = "request_processor";
|
||||
host.RegisterRequestProcessor(requestProcessor, new RequestProcessor());
|
||||
Console.WriteLine("Request processor is registered on {0}", requestProcessor);
|
||||
|
||||
Console.WriteLine("Press enter key to exist...");
|
||||
Console.ReadLine();
|
||||
|
||||
host.Close();
|
||||
}
|
||||
|
||||
static void PrintMessage(Message message)
|
||||
{
|
||||
if (message.Header != null) Console.WriteLine(message.Header.ToString());
|
||||
if (message.DeliveryAnnotations != null) Console.WriteLine(message.DeliveryAnnotations.ToString());
|
||||
if (message.MessageAnnotations != null) Console.WriteLine(message.MessageAnnotations.ToString());
|
||||
if (message.Properties != null) Console.WriteLine(message.Properties.ToString());
|
||||
if (message.ApplicationProperties != null) Console.WriteLine(message.ApplicationProperties.ToString());
|
||||
if (message.BodySection != null) Console.WriteLine("body:{0}", message.Body.ToString());
|
||||
if (message.Footer != null) Console.WriteLine(message.Footer.ToString());
|
||||
}
|
||||
|
||||
class MessageProcessor : IMessageProcessor
|
||||
{
|
||||
void IMessageProcessor.Process(MessageContext messageContext)
|
||||
{
|
||||
Console.WriteLine("Received a message.");
|
||||
PrintMessage(messageContext.Message);
|
||||
|
||||
messageContext.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
class RequestProcessor : IRequestProcessor
|
||||
{
|
||||
void IRequestProcessor.Process(RequestContext requestContext)
|
||||
{
|
||||
Console.WriteLine("Received a request.");
|
||||
PrintMessage(requestContext.Message);
|
||||
|
||||
Message response = new Message("welcome");
|
||||
requestContext.Complete(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PeerToPeer.Server")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PeerToPeer.Server")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6f6acc29-cc77-42cd-8ed4-c3407b36f323")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PeerToPeer.Server")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PeerToPeer.Server")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6f6acc29-cc77-42cd-8ed4-c3407b36f323")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,155 +1,155 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace ServiceBus.Cbs
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
|
||||
class Program
|
||||
{
|
||||
// update the following with valid Service Bus namespace and SAS key info
|
||||
const string sbNamespace = "contoso.servicebus.windows.net";
|
||||
const string keyName = "key1";
|
||||
const string keyValue = "5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ=";
|
||||
const string entity = "q1";
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Trace.TraceLevel = TraceLevel.Information;
|
||||
Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
try
|
||||
{
|
||||
RunSampleAsync().Wait();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Trace.WriteLine(TraceLevel.Error, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
static async Task RunSampleAsync()
|
||||
{
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.SASL.Profile = SaslProfile.External;
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Establishing a connection...");
|
||||
Address address = new Address(sbNamespace, 5671, null, null, "/", "amqps");
|
||||
var connection = await factory.CreateAsync(address);
|
||||
|
||||
// before any operation can be performed, a token must be put to the $cbs node
|
||||
Trace.WriteLine(TraceLevel.Information, "Putting a token to the $cbs node...");
|
||||
await PutTokenAsync(connection);
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Sending a message...");
|
||||
var session = new Session(connection);
|
||||
var sender = new SenderLink(session, "ServiceBus.Cbs:sender-link", entity);
|
||||
await sender.SendAsync(new Message("test"));
|
||||
await sender.CloseAsync();
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Receiving the message back...");
|
||||
var receiver = new ReceiverLink(session, "ServiceBus.Cbs:receiver-link", entity);
|
||||
var message = await receiver.ReceiveAsync();
|
||||
receiver.Accept(message);
|
||||
await receiver.CloseAsync();
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Closing the connection...");
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
static async Task PutTokenAsync(Connection connection)
|
||||
{
|
||||
var session = new Session(connection);
|
||||
|
||||
string cbsClientAddress = "cbs-client-reply-to";
|
||||
var cbsSender = new SenderLink(session, "cbs-sender", "$cbs");
|
||||
var receiverAttach = new Attach()
|
||||
{
|
||||
Source = new Source() { Address = "$cbs" },
|
||||
Target = new Target() { Address = cbsClientAddress }
|
||||
};
|
||||
var cbsReceiver = new ReceiverLink(session, "cbs-receiver", receiverAttach, null);
|
||||
var sasToken = GetSASToken(keyName, keyValue, string.Format("http://{0}/{1}", sbNamespace, entity), TimeSpan.FromMinutes(20));
|
||||
Trace.WriteLine(TraceLevel.Information, " sas token: {0}", sasToken);
|
||||
|
||||
// construct the put-token message
|
||||
var request = new Message(sasToken);
|
||||
request.Properties = new Properties();
|
||||
request.Properties.MessageId = "1";
|
||||
request.Properties.ReplyTo = cbsClientAddress;
|
||||
request.ApplicationProperties = new ApplicationProperties();
|
||||
request.ApplicationProperties["operation"] = "put-token";
|
||||
request.ApplicationProperties["type"] = "servicebus.windows.net:sastoken";
|
||||
request.ApplicationProperties["name"] = string.Format("amqp://{0}/{1}", sbNamespace, entity);
|
||||
await cbsSender.SendAsync(request);
|
||||
Trace.WriteLine(TraceLevel.Information, " request: {0}", request.Properties);
|
||||
Trace.WriteLine(TraceLevel.Information, " request: {0}", request.ApplicationProperties);
|
||||
|
||||
// receive the response
|
||||
var response = await cbsReceiver.ReceiveAsync();
|
||||
if (response == null || response.Properties == null || response.ApplicationProperties == null)
|
||||
{
|
||||
throw new Exception("invalid response received");
|
||||
}
|
||||
|
||||
// validate message properties and status code.
|
||||
Trace.WriteLine(TraceLevel.Information, " response: {0}", response.Properties);
|
||||
Trace.WriteLine(TraceLevel.Information, " response: {0}", response.ApplicationProperties);
|
||||
int statusCode = (int)response.ApplicationProperties["status-code"];
|
||||
if (statusCode != (int)HttpStatusCode.Accepted && statusCode != (int)HttpStatusCode.OK)
|
||||
{
|
||||
throw new Exception("put-token message was not accepted. Error code: " + statusCode);
|
||||
}
|
||||
|
||||
// the sender/receiver may be kept open for refreshing tokens
|
||||
await cbsSender.CloseAsync();
|
||||
await cbsReceiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
}
|
||||
|
||||
static string GetSASToken(string keyName, string keyValue, string requestUri, TimeSpan ttl)
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/azure/dn170477.aspx
|
||||
// the canonical Uri scheme is http because the token is not amqp specific
|
||||
// signature is computed from joined encoded request Uri string and expiry string
|
||||
string expiry = ((long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)) + ttl).TotalSeconds).ToString();
|
||||
string encodedUri = HttpUtility.UrlEncode(requestUri);
|
||||
|
||||
string sig;
|
||||
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(keyValue)))
|
||||
{
|
||||
sig = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedUri + "\n" + expiry)));
|
||||
}
|
||||
|
||||
return string.Format(
|
||||
"SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}",
|
||||
HttpUtility.UrlEncode(sig),
|
||||
HttpUtility.UrlEncode(expiry),
|
||||
HttpUtility.UrlEncode(keyName),
|
||||
encodedUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace ServiceBus.Cbs
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
|
||||
class Program
|
||||
{
|
||||
// update the following with valid Service Bus namespace and SAS key info
|
||||
const string sbNamespace = "contoso.servicebus.windows.net";
|
||||
const string keyName = "key1";
|
||||
const string keyValue = "5znwNTZDYC39dqhFOTDtnaikd1hiuRa4XaAj3Y9kJhQ=";
|
||||
const string entity = "q1";
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Trace.TraceLevel = TraceLevel.Information;
|
||||
Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
|
||||
try
|
||||
{
|
||||
RunSampleAsync().Wait();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Trace.WriteLine(TraceLevel.Error, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
static async Task RunSampleAsync()
|
||||
{
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.SASL.Profile = SaslProfile.External;
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Establishing a connection...");
|
||||
Address address = new Address(sbNamespace, 5671, null, null, "/", "amqps");
|
||||
var connection = await factory.CreateAsync(address);
|
||||
|
||||
// before any operation can be performed, a token must be put to the $cbs node
|
||||
Trace.WriteLine(TraceLevel.Information, "Putting a token to the $cbs node...");
|
||||
await PutTokenAsync(connection);
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Sending a message...");
|
||||
var session = new Session(connection);
|
||||
var sender = new SenderLink(session, "ServiceBus.Cbs:sender-link", entity);
|
||||
await sender.SendAsync(new Message("test"));
|
||||
await sender.CloseAsync();
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Receiving the message back...");
|
||||
var receiver = new ReceiverLink(session, "ServiceBus.Cbs:receiver-link", entity);
|
||||
var message = await receiver.ReceiveAsync();
|
||||
receiver.Accept(message);
|
||||
await receiver.CloseAsync();
|
||||
|
||||
Trace.WriteLine(TraceLevel.Information, "Closing the connection...");
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
static async Task PutTokenAsync(Connection connection)
|
||||
{
|
||||
var session = new Session(connection);
|
||||
|
||||
string cbsClientAddress = "cbs-client-reply-to";
|
||||
var cbsSender = new SenderLink(session, "cbs-sender", "$cbs");
|
||||
var receiverAttach = new Attach()
|
||||
{
|
||||
Source = new Source() { Address = "$cbs" },
|
||||
Target = new Target() { Address = cbsClientAddress }
|
||||
};
|
||||
var cbsReceiver = new ReceiverLink(session, "cbs-receiver", receiverAttach, null);
|
||||
var sasToken = GetSASToken(keyName, keyValue, string.Format("http://{0}/{1}", sbNamespace, entity), TimeSpan.FromMinutes(20));
|
||||
Trace.WriteLine(TraceLevel.Information, " sas token: {0}", sasToken);
|
||||
|
||||
// construct the put-token message
|
||||
var request = new Message(sasToken);
|
||||
request.Properties = new Properties();
|
||||
request.Properties.MessageId = "1";
|
||||
request.Properties.ReplyTo = cbsClientAddress;
|
||||
request.ApplicationProperties = new ApplicationProperties();
|
||||
request.ApplicationProperties["operation"] = "put-token";
|
||||
request.ApplicationProperties["type"] = "servicebus.windows.net:sastoken";
|
||||
request.ApplicationProperties["name"] = string.Format("amqp://{0}/{1}", sbNamespace, entity);
|
||||
await cbsSender.SendAsync(request);
|
||||
Trace.WriteLine(TraceLevel.Information, " request: {0}", request.Properties);
|
||||
Trace.WriteLine(TraceLevel.Information, " request: {0}", request.ApplicationProperties);
|
||||
|
||||
// receive the response
|
||||
var response = await cbsReceiver.ReceiveAsync();
|
||||
if (response == null || response.Properties == null || response.ApplicationProperties == null)
|
||||
{
|
||||
throw new Exception("invalid response received");
|
||||
}
|
||||
|
||||
// validate message properties and status code.
|
||||
Trace.WriteLine(TraceLevel.Information, " response: {0}", response.Properties);
|
||||
Trace.WriteLine(TraceLevel.Information, " response: {0}", response.ApplicationProperties);
|
||||
int statusCode = (int)response.ApplicationProperties["status-code"];
|
||||
if (statusCode != (int)HttpStatusCode.Accepted && statusCode != (int)HttpStatusCode.OK)
|
||||
{
|
||||
throw new Exception("put-token message was not accepted. Error code: " + statusCode);
|
||||
}
|
||||
|
||||
// the sender/receiver may be kept open for refreshing tokens
|
||||
await cbsSender.CloseAsync();
|
||||
await cbsReceiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
}
|
||||
|
||||
static string GetSASToken(string keyName, string keyValue, string requestUri, TimeSpan ttl)
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/azure/dn170477.aspx
|
||||
// the canonical Uri scheme is http because the token is not amqp specific
|
||||
// signature is computed from joined encoded request Uri string and expiry string
|
||||
string expiry = ((long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)) + ttl).TotalSeconds).ToString();
|
||||
string encodedUri = HttpUtility.UrlEncode(requestUri);
|
||||
|
||||
string sig;
|
||||
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(keyValue)))
|
||||
{
|
||||
sig = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedUri + "\n" + expiry)));
|
||||
}
|
||||
|
||||
return string.Format(
|
||||
"SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}",
|
||||
HttpUtility.UrlEncode(sig),
|
||||
HttpUtility.UrlEncode(expiry),
|
||||
HttpUtility.UrlEncode(keyName),
|
||||
encodedUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ServiceBus.Cbs")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ServiceBus.Cbs")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("33911019-52fc-47ca-b8e0-2d34c1ac2c84")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ServiceBus.Cbs")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ServiceBus.Cbs")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("33911019-52fc-47ca-b8e0-2d34c1ac2c84")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
660
amqp.sln
660
amqp.sln
|
@ -1,330 +1,330 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF42", "src\Amqp.NetMF42.csproj", "{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.WP", "src\Amqp.WP.csproj", "{CD477EDC-5779-44CD-ABE9-330F1C6531D9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetMF42", "test\Test.Amqp.NetMF\Test.Amqp.NetMF42.csproj", "{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Store", "src\Amqp.Store.csproj", "{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.Net", "test\Test.Amqp.Net\Test.Amqp.Net.csproj", "{06CAA70A-20A7-4334-AF03-D6228039C178}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{679989B2-8717-4ECC-9CAD-B104CFA91C38}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Amqp.Net.nuspec = Amqp.Net.nuspec
|
||||
build.cmd = build.cmd
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net", "src\Amqp.Net.csproj", "{92153715-1D99-43B1-B291-470CF91A156D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetCF39", "src\Amqp.NetCF39.csproj", "{994D25B3-A2C4-4A27-A0E8-3203E954BF58}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetCF39", "test\Test.Amqp.NetCF39\Test.Amqp.NetCF39.csproj", "{187E608C-FBF4-4517-B61F-A85AFF5BCA75}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF43", "src\Amqp.NetMF43.csproj", "{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetMF43", "test\Test.Amqp.NetMF\Test.Amqp.NetMF43.csproj", "{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{8F701234-EC60-485C-BCDB-8EE233246832}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Drain", "Examples\Interop\Interop.Drain\Interop.Drain.csproj", "{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Spout", "Examples\Interop\Interop.Spout\Interop.Spout.csproj", "{68470436-2F0D-4A76-B1E6-9C8517844C3E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAmqpBroker", "test\TestAmqpBroker\TestAmqpBroker.csproj", "{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Server", "Examples\Interop\Interop.Server\Interop.Server.csproj", "{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Client", "Examples\Interop\Interop.Client\Interop.Client.csproj", "{C272B10E-36BE-4F36-A128-331F715514E6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceBus", "ServiceBus", "{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.Cbs", "Examples\ServiceBus\ServiceBus.Cbs\ServiceBus.Cbs.csproj", "{4681C268-36DB-4838-BD21-9EC9A8363269}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PeerToPeer", "PeerToPeer", "{7FF80B2D-4158-41D3-BC87-60C018028F53}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Server", "Examples\PeerToPeer\PeerToPeer.Server\PeerToPeer.Server.csproj", "{24C152B0-3813-43C6-82DD-8BB601642F6C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Client", "Examples\PeerToPeer\PeerToPeer.Client\PeerToPeer.Client.csproj", "{8FC90E46-024B-4089-9590-A7E8C2B092BE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net35", "src\Amqp.Net35.csproj", "{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Device", "Device", "{BF554E12-7096-465F-B1D0-9ACFF00877F2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Thermometer", "Examples\Device\Device.Thermometer\Device.Thermometer.csproj", "{43570F0D-DE6C-423E-A275-AC619A813B79}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Controller", "Examples\Device\Device.Controller\Device.Controller.csproj", "{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x86.Build.0 = Debug|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|ARM.Build.0 = Release|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x86.ActiveCfg = Release|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x86.Build.0 = Release|x86
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x64.Build.0 = Debug|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x86.Build.0 = Debug|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|ARM.Build.0 = Release|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x64.ActiveCfg = Release|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x64.Build.0 = Release|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x86.ActiveCfg = Release|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x86.Build.0 = Release|x86
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.Build.0 = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.Build.0 = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.ActiveCfg = Release|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.Build.0 = Release|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{7FF80B2D-4158-41D3-BC87-60C018028F53} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{BF554E12-7096-465F-B1D0-9ACFF00877F2} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF42", "src\Amqp.NetMF42.csproj", "{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.WP", "src\Amqp.WP.csproj", "{CD477EDC-5779-44CD-ABE9-330F1C6531D9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetMF42", "test\Test.Amqp.NetMF\Test.Amqp.NetMF42.csproj", "{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Store", "src\Amqp.Store.csproj", "{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.Net", "test\Test.Amqp.Net\Test.Amqp.Net.csproj", "{06CAA70A-20A7-4334-AF03-D6228039C178}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{679989B2-8717-4ECC-9CAD-B104CFA91C38}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Amqp.Net.nuspec = Amqp.Net.nuspec
|
||||
build.cmd = build.cmd
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net", "src\Amqp.Net.csproj", "{92153715-1D99-43B1-B291-470CF91A156D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetCF39", "src\Amqp.NetCF39.csproj", "{994D25B3-A2C4-4A27-A0E8-3203E954BF58}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetCF39", "test\Test.Amqp.NetCF39\Test.Amqp.NetCF39.csproj", "{187E608C-FBF4-4517-B61F-A85AFF5BCA75}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF43", "src\Amqp.NetMF43.csproj", "{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetMF43", "test\Test.Amqp.NetMF\Test.Amqp.NetMF43.csproj", "{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{8F701234-EC60-485C-BCDB-8EE233246832}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Drain", "Examples\Interop\Interop.Drain\Interop.Drain.csproj", "{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Spout", "Examples\Interop\Interop.Spout\Interop.Spout.csproj", "{68470436-2F0D-4A76-B1E6-9C8517844C3E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAmqpBroker", "test\TestAmqpBroker\TestAmqpBroker.csproj", "{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Server", "Examples\Interop\Interop.Server\Interop.Server.csproj", "{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Client", "Examples\Interop\Interop.Client\Interop.Client.csproj", "{C272B10E-36BE-4F36-A128-331F715514E6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceBus", "ServiceBus", "{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.Cbs", "Examples\ServiceBus\ServiceBus.Cbs\ServiceBus.Cbs.csproj", "{4681C268-36DB-4838-BD21-9EC9A8363269}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PeerToPeer", "PeerToPeer", "{7FF80B2D-4158-41D3-BC87-60C018028F53}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Server", "Examples\PeerToPeer\PeerToPeer.Server\PeerToPeer.Server.csproj", "{24C152B0-3813-43C6-82DD-8BB601642F6C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Client", "Examples\PeerToPeer\PeerToPeer.Client\PeerToPeer.Client.csproj", "{8FC90E46-024B-4089-9590-A7E8C2B092BE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net35", "src\Amqp.Net35.csproj", "{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Device", "Device", "{BF554E12-7096-465F-B1D0-9ACFF00877F2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Thermometer", "Examples\Device\Device.Thermometer\Device.Thermometer.csproj", "{43570F0D-DE6C-423E-A275-AC619A813B79}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Controller", "Examples\Device\Device.Controller\Device.Controller.csproj", "{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Debug|x86.Build.0 = Debug|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|ARM.Build.0 = Release|ARM
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x86.ActiveCfg = Release|x86
|
||||
{CD477EDC-5779-44CD-ABE9-330F1C6531D9}.Release|x86.Build.0 = Release|x86
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E0B13B0F-C739-4788-BC47-A6BEAF6FB5A6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x64.Build.0 = Debug|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Debug|x86.Build.0 = Debug|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|ARM.Build.0 = Release|ARM
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x64.ActiveCfg = Release|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x64.Build.0 = Release|x64
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x86.ActiveCfg = Release|x86
|
||||
{647AAC43-DC4A-47F0-8C07-E0DA2C312B30}.Release|x86.Build.0 = Release|x86
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{994D25B3-A2C4-4A27-A0E8-3203E954BF58}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{187E608C-FBF4-4517-B61F-A85AFF5BCA75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.Build.0 = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.Build.0 = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.ActiveCfg = Release|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.Build.0 = Release|x86
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{7FF80B2D-4158-41D3-BC87-60C018028F53} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{BF554E12-7096-465F-B1D0-9ACFF00877F2} = {8F701234-EC60-485C-BCDB-8EE233246832}
|
||||
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{68470436-2F0D-4A76-B1E6-9C8517844C3E} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{C272B10E-36BE-4F36-A128-331F715514E6} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
|
||||
{4681C268-36DB-4838-BD21-9EC9A8363269} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
|
||||
{24C152B0-3813-43C6-82DD-8BB601642F6C} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
|
||||
{8FC90E46-024B-4089-9590-A7E8C2B092BE} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
|
||||
{43570F0D-DE6C-423E-A275-AC619A813B79} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
|
||||
{23F5A590-C6D6-4FF7-A787-5AEE6A9522A7} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
500
src/Address.cs
500
src/Address.cs
|
@ -1,251 +1,251 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using Amqp.Types;
|
||||
|
||||
public sealed class Address
|
||||
{
|
||||
internal const string Amqp = "AMQP";
|
||||
internal const string Amqps = "AMQPS";
|
||||
const int AmqpPort = 5672;
|
||||
const int AmqpsPort = 5671;
|
||||
|
||||
public Address(string address)
|
||||
{
|
||||
this.Port = -1;
|
||||
this.Parse(address);
|
||||
this.SetDefault();
|
||||
}
|
||||
|
||||
public Address(string host, int port, string user = null, string password = null, string path = "/", string scheme = Amqps)
|
||||
{
|
||||
this.Host = host;
|
||||
this.Port = port;
|
||||
this.Path = path;
|
||||
this.Scheme = scheme;
|
||||
this.User = user;
|
||||
this.Password = password;
|
||||
this.SetDefault();
|
||||
}
|
||||
|
||||
public string Scheme
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool UseSsl
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Host
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string User
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
enum ParseState
|
||||
{
|
||||
Scheme,
|
||||
Slash1,
|
||||
Slash2,
|
||||
User,
|
||||
Password,
|
||||
Host,
|
||||
Port,
|
||||
Path
|
||||
}
|
||||
|
||||
void Parse(string address)
|
||||
{
|
||||
// amqp[s]://user:password@a.contoso.com:port/foo/bar
|
||||
ParseState state = ParseState.Scheme;
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < address.Length; ++i)
|
||||
{
|
||||
switch (address[i])
|
||||
{
|
||||
case ':':
|
||||
if (state == ParseState.Scheme)
|
||||
{
|
||||
this.Scheme = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Slash1;
|
||||
}
|
||||
else if (state == ParseState.User)
|
||||
{
|
||||
this.User = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Password;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else if (state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Port;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField,
|
||||
Fx.Format(SRAmqp.InvalidAddressFormat));
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
if (state == ParseState.Slash1)
|
||||
{
|
||||
state = ParseState.Slash2;
|
||||
}
|
||||
else if (state == ParseState.Slash2)
|
||||
{
|
||||
state = ParseState.User;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else if (state == ParseState.User || state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
else if (state == ParseState.Port)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
else if (state == ParseState.Password)
|
||||
{
|
||||
this.Host = this.User;
|
||||
this.User = null;
|
||||
this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (state == ParseState.Password)
|
||||
{
|
||||
this.Password = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Host;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField,
|
||||
Fx.Format(SRAmqp.InvalidAddressFormat));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == ParseState.Path)
|
||||
{
|
||||
this.Path = address.Substring(startIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check state in case of no trailing slash
|
||||
if (state == ParseState.User || state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex);
|
||||
}
|
||||
else if (state == ParseState.Password)
|
||||
{
|
||||
this.Host = this.User;
|
||||
this.User = null;
|
||||
if (startIndex < address.Length - 1)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex));
|
||||
}
|
||||
}
|
||||
else if (state == ParseState.Port)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex));
|
||||
}
|
||||
|
||||
if (this.Password != null && this.Password.Length > 0)
|
||||
{
|
||||
this.Password = Uri.UnescapeDataString(this.Password);
|
||||
}
|
||||
|
||||
if (this.User != null && this.User.Length > 0)
|
||||
{
|
||||
this.User = Uri.UnescapeDataString(this.User);
|
||||
}
|
||||
|
||||
if (this.Host != null)
|
||||
{
|
||||
this.Host = Uri.UnescapeDataString(this.Host);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefault()
|
||||
{
|
||||
string schemeUpper = this.Scheme.ToUpper();
|
||||
if (schemeUpper == Amqps)
|
||||
{
|
||||
this.UseSsl = true;
|
||||
}
|
||||
|
||||
if (this.Port == -1)
|
||||
{
|
||||
if (this.UseSsl)
|
||||
{
|
||||
this.Port = AmqpsPort;
|
||||
}
|
||||
else if (schemeUpper == Amqp)
|
||||
{
|
||||
this.Port = AmqpPort;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Path == null)
|
||||
{
|
||||
this.Path = "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using Amqp.Types;
|
||||
|
||||
public sealed class Address
|
||||
{
|
||||
internal const string Amqp = "AMQP";
|
||||
internal const string Amqps = "AMQPS";
|
||||
const int AmqpPort = 5672;
|
||||
const int AmqpsPort = 5671;
|
||||
|
||||
public Address(string address)
|
||||
{
|
||||
this.Port = -1;
|
||||
this.Parse(address);
|
||||
this.SetDefault();
|
||||
}
|
||||
|
||||
public Address(string host, int port, string user = null, string password = null, string path = "/", string scheme = Amqps)
|
||||
{
|
||||
this.Host = host;
|
||||
this.Port = port;
|
||||
this.Path = path;
|
||||
this.Scheme = scheme;
|
||||
this.User = user;
|
||||
this.Password = password;
|
||||
this.SetDefault();
|
||||
}
|
||||
|
||||
public string Scheme
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool UseSsl
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Host
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string User
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
enum ParseState
|
||||
{
|
||||
Scheme,
|
||||
Slash1,
|
||||
Slash2,
|
||||
User,
|
||||
Password,
|
||||
Host,
|
||||
Port,
|
||||
Path
|
||||
}
|
||||
|
||||
void Parse(string address)
|
||||
{
|
||||
// amqp[s]://user:password@a.contoso.com:port/foo/bar
|
||||
ParseState state = ParseState.Scheme;
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < address.Length; ++i)
|
||||
{
|
||||
switch (address[i])
|
||||
{
|
||||
case ':':
|
||||
if (state == ParseState.Scheme)
|
||||
{
|
||||
this.Scheme = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Slash1;
|
||||
}
|
||||
else if (state == ParseState.User)
|
||||
{
|
||||
this.User = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Password;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else if (state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Port;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField,
|
||||
Fx.Format(SRAmqp.InvalidAddressFormat));
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
if (state == ParseState.Slash1)
|
||||
{
|
||||
state = ParseState.Slash2;
|
||||
}
|
||||
else if (state == ParseState.Slash2)
|
||||
{
|
||||
state = ParseState.User;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else if (state == ParseState.User || state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
else if (state == ParseState.Port)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
else if (state == ParseState.Password)
|
||||
{
|
||||
this.Host = this.User;
|
||||
this.User = null;
|
||||
this.Port = int.Parse(address.Substring(startIndex, i - startIndex));
|
||||
state = ParseState.Path;
|
||||
startIndex = i;
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (state == ParseState.Password)
|
||||
{
|
||||
this.Password = address.Substring(startIndex, i - startIndex);
|
||||
state = ParseState.Host;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField,
|
||||
Fx.Format(SRAmqp.InvalidAddressFormat));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == ParseState.Path)
|
||||
{
|
||||
this.Path = address.Substring(startIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check state in case of no trailing slash
|
||||
if (state == ParseState.User || state == ParseState.Host)
|
||||
{
|
||||
this.Host = address.Substring(startIndex);
|
||||
}
|
||||
else if (state == ParseState.Password)
|
||||
{
|
||||
this.Host = this.User;
|
||||
this.User = null;
|
||||
if (startIndex < address.Length - 1)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex));
|
||||
}
|
||||
}
|
||||
else if (state == ParseState.Port)
|
||||
{
|
||||
this.Port = int.Parse(address.Substring(startIndex));
|
||||
}
|
||||
|
||||
if (this.Password != null && this.Password.Length > 0)
|
||||
{
|
||||
this.Password = Uri.UnescapeDataString(this.Password);
|
||||
}
|
||||
|
||||
if (this.User != null && this.User.Length > 0)
|
||||
{
|
||||
this.User = Uri.UnescapeDataString(this.User);
|
||||
}
|
||||
|
||||
if (this.Host != null)
|
||||
{
|
||||
this.Host = Uri.UnescapeDataString(this.Host);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefault()
|
||||
{
|
||||
string schemeUpper = this.Scheme.ToUpper();
|
||||
if (schemeUpper == Amqps)
|
||||
{
|
||||
this.UseSsl = true;
|
||||
}
|
||||
|
||||
if (this.Port == -1)
|
||||
{
|
||||
if (this.UseSsl)
|
||||
{
|
||||
this.Port = AmqpsPort;
|
||||
}
|
||||
else if (schemeUpper == Amqp)
|
||||
{
|
||||
this.Port = AmqpPort;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Path == null)
|
||||
{
|
||||
this.Path = "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +1,42 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
|
||||
public sealed class AmqpException : Exception
|
||||
{
|
||||
public AmqpException(Error error)
|
||||
: base(error.Description ?? error.Condition)
|
||||
{
|
||||
this.Error = error;
|
||||
}
|
||||
|
||||
public AmqpException(string condition, string description)
|
||||
: this(new Error() { Condition = condition, Description = description })
|
||||
{
|
||||
}
|
||||
|
||||
public Error Error
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
|
||||
public sealed class AmqpException : Exception
|
||||
{
|
||||
public AmqpException(Error error)
|
||||
: base(error.Description ?? error.Condition)
|
||||
{
|
||||
this.Error = error;
|
||||
}
|
||||
|
||||
public AmqpException(string condition, string description)
|
||||
: this(new Error() { Condition = condition, Description = description })
|
||||
{
|
||||
}
|
||||
|
||||
public Error Error
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,8 +31,8 @@ namespace Amqp
|
|||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void NotifyClosed(Error error)
|
||||
{
|
||||
ManualResetEvent temp = this.endEvent;
|
||||
|
@ -49,20 +49,20 @@ namespace Amqp
|
|||
}
|
||||
|
||||
public void Close(int waitUntilEnded = DefaultCloseTimeout, Error error = null)
|
||||
{
|
||||
// initialize event first to avoid the race with NotifyClosed
|
||||
this.endEvent = new ManualResetEvent(false);
|
||||
if (!this.OnClose(error))
|
||||
{
|
||||
if (waitUntilEnded > 0)
|
||||
{
|
||||
this.endEvent.WaitOne(waitUntilEnded, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.endEvent.Set();
|
||||
this.NotifyClosed(null);
|
||||
{
|
||||
// initialize event first to avoid the race with NotifyClosed
|
||||
this.endEvent = new ManualResetEvent(false);
|
||||
if (!this.OnClose(error))
|
||||
{
|
||||
if (waitUntilEnded > 0)
|
||||
{
|
||||
this.endEvent.WaitOne(waitUntilEnded, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.endEvent.Set();
|
||||
this.NotifyClosed(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Amqp
|
|||
int end;
|
||||
bool autoGrow;
|
||||
|
||||
public ByteBuffer(byte[] buffer, int offset, int count, int capacity)
|
||||
public ByteBuffer(byte[] buffer, int offset, int count, int capacity)
|
||||
: this(buffer, offset, count, capacity, false)
|
||||
{
|
||||
}
|
||||
|
@ -49,14 +49,14 @@ namespace Amqp
|
|||
public ByteBuffer(int size, bool autoGrow)
|
||||
: this(new byte[size], 0, 0, size, autoGrow)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ByteBuffer(byte[] buffer, int offset, int count, int capacity, bool autoGrow)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
this.start = offset;
|
||||
this.read = offset;
|
||||
this.write = offset + count;
|
||||
this.write = offset + count;
|
||||
this.end = offset + capacity;
|
||||
this.autoGrow = autoGrow;
|
||||
}
|
||||
|
|
1130
src/Connection.cs
1130
src/Connection.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -24,12 +24,12 @@ namespace Amqp.Framing
|
|||
public ApplicationProperties()
|
||||
: base(Codec.ApplicationProperties, typeof(string))
|
||||
{
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "app-properties:" + base.ToString();
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "app-properties:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -24,13 +24,13 @@ namespace Amqp.Framing
|
|||
public DeliveryAnnotations()
|
||||
: base(Codec.DeliveryAnnotations, typeof(Symbol))
|
||||
{
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "delivery-annotations:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "delivery-annotations:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,57 +1,57 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Framing
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
public sealed class Error : DescribedList
|
||||
{
|
||||
public Error()
|
||||
: base(Codec.Error, 3)
|
||||
{
|
||||
}
|
||||
|
||||
public Symbol Condition
|
||||
{
|
||||
get { return (Symbol)this.Fields[0]; }
|
||||
set { this.Fields[0] = value; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return (string)this.Fields[1]; }
|
||||
set { this.Fields[1] = value; }
|
||||
}
|
||||
|
||||
public Fields Info
|
||||
{
|
||||
get { return Amqp.Types.Fields.From(this.Fields, 2); }
|
||||
set { this.Fields[2] = value; }
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return this.GetDebugString(
|
||||
"error",
|
||||
new object[] { "condition", "description", "fields" },
|
||||
this.Fields);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Framing
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
public sealed class Error : DescribedList
|
||||
{
|
||||
public Error()
|
||||
: base(Codec.Error, 3)
|
||||
{
|
||||
}
|
||||
|
||||
public Symbol Condition
|
||||
{
|
||||
get { return (Symbol)this.Fields[0]; }
|
||||
set { this.Fields[0] = value; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return (string)this.Fields[1]; }
|
||||
set { this.Fields[1] = value; }
|
||||
}
|
||||
|
||||
public Fields Info
|
||||
{
|
||||
get { return Amqp.Types.Fields.From(this.Fields, 2); }
|
||||
set { this.Fields[2] = value; }
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return this.GetDebugString(
|
||||
"error",
|
||||
new object[] { "condition", "description", "fields" },
|
||||
this.Fields);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ namespace Amqp.Framing
|
|||
}
|
||||
|
||||
public Fields Properties
|
||||
{
|
||||
{
|
||||
get { return Amqp.Types.Fields.From(this.Fields, 10); }
|
||||
set { this.Fields[10] = value; }
|
||||
}
|
||||
|
|
|
@ -25,13 +25,13 @@ namespace Amqp.Framing
|
|||
public Footer()
|
||||
: base(Codec.Footer, typeof(Symbol))
|
||||
{
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "footer:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "footer:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,100 +1,100 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Framing
|
||||
{
|
||||
using System;
|
||||
using Amqp.Types;
|
||||
|
||||
enum FrameType : byte
|
||||
{
|
||||
Amqp = 0,
|
||||
Sasl = 1
|
||||
}
|
||||
|
||||
static class Frame
|
||||
{
|
||||
const byte DOF = 2;
|
||||
const int cmdBufferSize = 128;
|
||||
|
||||
public static ByteBuffer Encode(FrameType type, ushort channel, DescribedList command)
|
||||
{
|
||||
ByteBuffer buffer = new ByteBuffer(cmdBufferSize, true);
|
||||
EncodeFrame(buffer, type, channel, command);
|
||||
AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static ByteBuffer Encode(FrameType type, ushort channel, Transfer transfer,
|
||||
ByteBuffer payload, int maxFrameSize, out int payloadSize)
|
||||
{
|
||||
int bufferSize = cmdBufferSize + payload.Length;
|
||||
if (bufferSize > maxFrameSize)
|
||||
{
|
||||
bufferSize = maxFrameSize;
|
||||
}
|
||||
|
||||
bool more = false; // estimate it first
|
||||
if (payload.Length > bufferSize - 32)
|
||||
{
|
||||
transfer.More = more = true;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = new ByteBuffer(bufferSize, false);
|
||||
EncodeFrame(buffer, type, channel, transfer);
|
||||
|
||||
if (more && payload.Length <= buffer.Size)
|
||||
{
|
||||
// guessed it wrong. correct it
|
||||
transfer.More = false;
|
||||
buffer.Reset();
|
||||
EncodeFrame(buffer, type, channel, transfer);
|
||||
}
|
||||
|
||||
payloadSize = Math.Min(payload.Length, buffer.Size);
|
||||
AmqpBitConverter.WriteBytes(buffer, payload.Buffer, payload.Offset, payloadSize);
|
||||
payload.Complete(payloadSize);
|
||||
AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static void GetFrame(ByteBuffer buffer, out ushort channel, out DescribedList command)
|
||||
{
|
||||
AmqpBitConverter.ReadUInt(buffer);
|
||||
AmqpBitConverter.ReadUByte(buffer);
|
||||
AmqpBitConverter.ReadUByte(buffer);
|
||||
channel = AmqpBitConverter.ReadUShort(buffer);
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
command = (DescribedList)Codec.Decode(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
command = null;
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeFrame(ByteBuffer buffer, FrameType type, ushort channel, DescribedList command)
|
||||
{
|
||||
AmqpBitConverter.WriteUInt(buffer, 0u);
|
||||
AmqpBitConverter.WriteUByte(buffer, DOF);
|
||||
AmqpBitConverter.WriteUByte(buffer, (byte)type);
|
||||
AmqpBitConverter.WriteUShort(buffer, channel);
|
||||
Codec.Encode(command, buffer);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Framing
|
||||
{
|
||||
using System;
|
||||
using Amqp.Types;
|
||||
|
||||
enum FrameType : byte
|
||||
{
|
||||
Amqp = 0,
|
||||
Sasl = 1
|
||||
}
|
||||
|
||||
static class Frame
|
||||
{
|
||||
const byte DOF = 2;
|
||||
const int cmdBufferSize = 128;
|
||||
|
||||
public static ByteBuffer Encode(FrameType type, ushort channel, DescribedList command)
|
||||
{
|
||||
ByteBuffer buffer = new ByteBuffer(cmdBufferSize, true);
|
||||
EncodeFrame(buffer, type, channel, command);
|
||||
AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static ByteBuffer Encode(FrameType type, ushort channel, Transfer transfer,
|
||||
ByteBuffer payload, int maxFrameSize, out int payloadSize)
|
||||
{
|
||||
int bufferSize = cmdBufferSize + payload.Length;
|
||||
if (bufferSize > maxFrameSize)
|
||||
{
|
||||
bufferSize = maxFrameSize;
|
||||
}
|
||||
|
||||
bool more = false; // estimate it first
|
||||
if (payload.Length > bufferSize - 32)
|
||||
{
|
||||
transfer.More = more = true;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = new ByteBuffer(bufferSize, false);
|
||||
EncodeFrame(buffer, type, channel, transfer);
|
||||
|
||||
if (more && payload.Length <= buffer.Size)
|
||||
{
|
||||
// guessed it wrong. correct it
|
||||
transfer.More = false;
|
||||
buffer.Reset();
|
||||
EncodeFrame(buffer, type, channel, transfer);
|
||||
}
|
||||
|
||||
payloadSize = Math.Min(payload.Length, buffer.Size);
|
||||
AmqpBitConverter.WriteBytes(buffer, payload.Buffer, payload.Offset, payloadSize);
|
||||
payload.Complete(payloadSize);
|
||||
AmqpBitConverter.WriteInt(buffer.Buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static void GetFrame(ByteBuffer buffer, out ushort channel, out DescribedList command)
|
||||
{
|
||||
AmqpBitConverter.ReadUInt(buffer);
|
||||
AmqpBitConverter.ReadUByte(buffer);
|
||||
AmqpBitConverter.ReadUByte(buffer);
|
||||
channel = AmqpBitConverter.ReadUShort(buffer);
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
command = (DescribedList)Codec.Decode(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
command = null;
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeFrame(ByteBuffer buffer, FrameType type, ushort channel, DescribedList command)
|
||||
{
|
||||
AmqpBitConverter.WriteUInt(buffer, 0u);
|
||||
AmqpBitConverter.WriteUByte(buffer, DOF);
|
||||
AmqpBitConverter.WriteUByte(buffer, (byte)type);
|
||||
AmqpBitConverter.WriteUShort(buffer, channel);
|
||||
Codec.Encode(command, buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,13 +24,13 @@ namespace Amqp.Framing
|
|||
public MessageAnnotations()
|
||||
: base(Codec.MessageAnnotations, typeof(Symbol))
|
||||
{
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "msg-annotations:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return "msg-annotations:" + base.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -16,36 +16,36 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Framing
|
||||
{
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
struct ProtocolHeader
|
||||
{
|
||||
{
|
||||
public byte Id;
|
||||
|
||||
public byte Major;
|
||||
|
||||
public byte Minor;
|
||||
|
||||
public byte Revision;
|
||||
|
||||
public static ProtocolHeader Create(byte[] buffer, int offset)
|
||||
{
|
||||
if (buffer[offset + 0] != (byte)'A' ||
|
||||
buffer[offset + 1] != (byte)'M' ||
|
||||
buffer[offset + 2] != (byte)'Q' ||
|
||||
buffer[offset + 3] != (byte)'P')
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField, "ProtocolName");
|
||||
}
|
||||
|
||||
return new ProtocolHeader()
|
||||
{
|
||||
Id = buffer[offset + 4],
|
||||
Major = buffer[offset + 5],
|
||||
Minor = buffer[offset + 6],
|
||||
Revision = buffer[offset + 7]
|
||||
};
|
||||
public byte Revision;
|
||||
|
||||
public static ProtocolHeader Create(byte[] buffer, int offset)
|
||||
{
|
||||
if (buffer[offset + 0] != (byte)'A' ||
|
||||
buffer[offset + 1] != (byte)'M' ||
|
||||
buffer[offset + 2] != (byte)'Q' ||
|
||||
buffer[offset + 3] != (byte)'P')
|
||||
{
|
||||
throw new AmqpException(ErrorCode.InvalidField, "ProtocolName");
|
||||
}
|
||||
|
||||
return new ProtocolHeader()
|
||||
{
|
||||
Id = buffer[offset + 4],
|
||||
Major = buffer[offset + 5],
|
||||
Minor = buffer[offset + 6],
|
||||
Revision = buffer[offset + 7]
|
||||
};
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Amqp.Framing
|
|||
throw new ObjectDisposedException(transport.GetType().Name);
|
||||
}
|
||||
|
||||
return ProtocolHeader.Create(smallBuffer, 0);
|
||||
return ProtocolHeader.Create(smallBuffer, 0);
|
||||
}
|
||||
|
||||
public static ByteBuffer ReadFrameBuffer(ITransport transport, byte[] sizeBuffer, uint maxFrameSize)
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
|
||||
public interface ITransport
|
||||
{
|
||||
// if transport supports async write, it should perform async write with queued buffers
|
||||
void Send(ByteBuffer buffer);
|
||||
|
||||
// this is called from the pump thread, so blocking is fine
|
||||
int Receive(byte[] buffer, int offset, int count);
|
||||
|
||||
void Close();
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
|
||||
public interface ITransport
|
||||
{
|
||||
// if transport supports async write, it should perform async write with queued buffers
|
||||
void Send(ByteBuffer buffer);
|
||||
|
||||
// this is called from the pump thread, so blocking is fine
|
||||
int Receive(byte[] buffer, int offset, int count);
|
||||
|
||||
void Close();
|
||||
}
|
||||
}
|
432
src/Link.cs
432
src/Link.cs
|
@ -1,217 +1,217 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public delegate void OnAttached(Link link, Attach attach);
|
||||
|
||||
public abstract class Link : AmqpObject
|
||||
{
|
||||
enum State
|
||||
{
|
||||
Start,
|
||||
AttachSent,
|
||||
AttachReceived,
|
||||
Attached,
|
||||
DetachPipe,
|
||||
DetachSent,
|
||||
DetachReceived,
|
||||
End
|
||||
}
|
||||
|
||||
readonly Session session;
|
||||
readonly string name;
|
||||
readonly uint handle;
|
||||
readonly OnAttached onAttached;
|
||||
State state;
|
||||
|
||||
protected Link(Session session, string name, OnAttached onAttached)
|
||||
{
|
||||
this.session = session;
|
||||
this.name = name;
|
||||
this.onAttached = onAttached;
|
||||
this.handle = session.AddLink(this);
|
||||
this.state = State.Start;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return this.name; }
|
||||
}
|
||||
|
||||
public uint Handle
|
||||
{
|
||||
get { return this.handle; }
|
||||
}
|
||||
|
||||
internal Session Session
|
||||
{
|
||||
get { return this.session; }
|
||||
}
|
||||
|
||||
protected object ThisLock
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
protected bool IsDetaching
|
||||
{
|
||||
get { return this.state >= State.DetachPipe; }
|
||||
}
|
||||
|
||||
internal void Abort(Error error)
|
||||
{
|
||||
this.OnAbort(error);
|
||||
|
||||
if (this.state != State.End)
|
||||
{
|
||||
this.state = State.End;
|
||||
this.NotifyClosed(error);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.AttachSent)
|
||||
{
|
||||
this.state = State.Attached;
|
||||
}
|
||||
else if (this.state == State.DetachPipe)
|
||||
{
|
||||
this.state = State.DetachSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "OnAttach", this.state));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.onAttached != null && attach.Target != null && attach.Source != null)
|
||||
{
|
||||
this.onAttached(this, attach);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool OnDetach(Detach detach)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.DetachSent)
|
||||
{
|
||||
this.state = State.End;
|
||||
}
|
||||
else if (this.state == State.Attached)
|
||||
{
|
||||
this.SendDetach(null);
|
||||
this.state = State.End;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "OnDetach", this.state));
|
||||
}
|
||||
|
||||
this.OnClose(detach.Error);
|
||||
this.NotifyClosed(detach.Error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract void OnFlow(Flow flow);
|
||||
|
||||
internal abstract void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer);
|
||||
|
||||
internal abstract void OnDeliveryStateChanged(Delivery delivery);
|
||||
|
||||
protected abstract void OnAbort(Error error);
|
||||
|
||||
protected override bool OnClose(Error error)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.End)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.state == State.AttachSent)
|
||||
{
|
||||
this.state = State.DetachPipe;
|
||||
}
|
||||
else if (this.state == State.Attached)
|
||||
{
|
||||
this.state = State.DetachSent;
|
||||
}
|
||||
else if (this.state == State.DetachReceived)
|
||||
{
|
||||
this.state = State.End;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "Close", this.state));
|
||||
}
|
||||
|
||||
this.SendDetach(error);
|
||||
return this.state == State.End;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SendFlow(uint deliveryCount, uint credit)
|
||||
{
|
||||
Flow flow = new Flow() { Handle = this.handle, DeliveryCount = deliveryCount, LinkCredit = credit };
|
||||
this.session.SendFlow(flow);
|
||||
}
|
||||
|
||||
protected void SendAttach(bool role, uint initialDeliveryCount, Attach attach)
|
||||
{
|
||||
Fx.Assert(this.state == State.Start, "state must be Start");
|
||||
this.state = State.AttachSent;
|
||||
attach.LinkName = this.name;
|
||||
attach.Handle = this.handle;
|
||||
attach.Role = role;
|
||||
if (!role)
|
||||
{
|
||||
attach.InitialDeliveryCount = initialDeliveryCount;
|
||||
}
|
||||
|
||||
this.session.SendCommand(attach);
|
||||
}
|
||||
|
||||
protected void ThrowIfDetaching(string operation)
|
||||
{
|
||||
if (this.IsDetaching)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, operation, this.state));
|
||||
}
|
||||
}
|
||||
|
||||
void SendDetach(Error error)
|
||||
{
|
||||
Detach detach = new Detach() { Handle = this.handle, Error = error, Closed = true };
|
||||
this.session.SendCommand(detach);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public delegate void OnAttached(Link link, Attach attach);
|
||||
|
||||
public abstract class Link : AmqpObject
|
||||
{
|
||||
enum State
|
||||
{
|
||||
Start,
|
||||
AttachSent,
|
||||
AttachReceived,
|
||||
Attached,
|
||||
DetachPipe,
|
||||
DetachSent,
|
||||
DetachReceived,
|
||||
End
|
||||
}
|
||||
|
||||
readonly Session session;
|
||||
readonly string name;
|
||||
readonly uint handle;
|
||||
readonly OnAttached onAttached;
|
||||
State state;
|
||||
|
||||
protected Link(Session session, string name, OnAttached onAttached)
|
||||
{
|
||||
this.session = session;
|
||||
this.name = name;
|
||||
this.onAttached = onAttached;
|
||||
this.handle = session.AddLink(this);
|
||||
this.state = State.Start;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return this.name; }
|
||||
}
|
||||
|
||||
public uint Handle
|
||||
{
|
||||
get { return this.handle; }
|
||||
}
|
||||
|
||||
internal Session Session
|
||||
{
|
||||
get { return this.session; }
|
||||
}
|
||||
|
||||
protected object ThisLock
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
protected bool IsDetaching
|
||||
{
|
||||
get { return this.state >= State.DetachPipe; }
|
||||
}
|
||||
|
||||
internal void Abort(Error error)
|
||||
{
|
||||
this.OnAbort(error);
|
||||
|
||||
if (this.state != State.End)
|
||||
{
|
||||
this.state = State.End;
|
||||
this.NotifyClosed(error);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.AttachSent)
|
||||
{
|
||||
this.state = State.Attached;
|
||||
}
|
||||
else if (this.state == State.DetachPipe)
|
||||
{
|
||||
this.state = State.DetachSent;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "OnAttach", this.state));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.onAttached != null && attach.Target != null && attach.Source != null)
|
||||
{
|
||||
this.onAttached(this, attach);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool OnDetach(Detach detach)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.DetachSent)
|
||||
{
|
||||
this.state = State.End;
|
||||
}
|
||||
else if (this.state == State.Attached)
|
||||
{
|
||||
this.SendDetach(null);
|
||||
this.state = State.End;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "OnDetach", this.state));
|
||||
}
|
||||
|
||||
this.OnClose(detach.Error);
|
||||
this.NotifyClosed(detach.Error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract void OnFlow(Flow flow);
|
||||
|
||||
internal abstract void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer);
|
||||
|
||||
internal abstract void OnDeliveryStateChanged(Delivery delivery);
|
||||
|
||||
protected abstract void OnAbort(Error error);
|
||||
|
||||
protected override bool OnClose(Error error)
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.state == State.End)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.state == State.AttachSent)
|
||||
{
|
||||
this.state = State.DetachPipe;
|
||||
}
|
||||
else if (this.state == State.Attached)
|
||||
{
|
||||
this.state = State.DetachSent;
|
||||
}
|
||||
else if (this.state == State.DetachReceived)
|
||||
{
|
||||
this.state = State.End;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, "Close", this.state));
|
||||
}
|
||||
|
||||
this.SendDetach(error);
|
||||
return this.state == State.End;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SendFlow(uint deliveryCount, uint credit)
|
||||
{
|
||||
Flow flow = new Flow() { Handle = this.handle, DeliveryCount = deliveryCount, LinkCredit = credit };
|
||||
this.session.SendFlow(flow);
|
||||
}
|
||||
|
||||
protected void SendAttach(bool role, uint initialDeliveryCount, Attach attach)
|
||||
{
|
||||
Fx.Assert(this.state == State.Start, "state must be Start");
|
||||
this.state = State.AttachSent;
|
||||
attach.LinkName = this.name;
|
||||
attach.Handle = this.handle;
|
||||
attach.Role = role;
|
||||
if (!role)
|
||||
{
|
||||
attach.InitialDeliveryCount = initialDeliveryCount;
|
||||
}
|
||||
|
||||
this.session.SendCommand(attach);
|
||||
}
|
||||
|
||||
protected void ThrowIfDetaching(string operation)
|
||||
{
|
||||
if (this.IsDetaching)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.IllegalState,
|
||||
Fx.Format(SRAmqp.AmqpIllegalOperationState, operation, this.state));
|
||||
}
|
||||
}
|
||||
|
||||
void SendDetach(Error error)
|
||||
{
|
||||
Detach detach = new Detach() { Handle = this.handle, Error = error, Closed = true };
|
||||
this.session.SendCommand(detach);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,345 +1,345 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ContainerHost : IContainer
|
||||
{
|
||||
readonly X509Certificate2 certificate;
|
||||
readonly ConnectionListener[] listeners;
|
||||
readonly Dictionary<string, MessageProcessor> messageProcessors;
|
||||
readonly Dictionary<string, RequestProcessor> requestProcessors;
|
||||
|
||||
public ContainerHost(Uri addressUri)
|
||||
: this(new Uri[] { addressUri }, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ContainerHost(IList<Uri> addressUriList, X509Certificate2 certificate, string userInfo)
|
||||
{
|
||||
this.certificate = certificate;
|
||||
this.messageProcessors = new Dictionary<string, MessageProcessor>(StringComparer.OrdinalIgnoreCase);
|
||||
this.requestProcessors = new Dictionary<string, RequestProcessor>(StringComparer.OrdinalIgnoreCase);
|
||||
this.listeners = new ConnectionListener[addressUriList.Count];
|
||||
for (int i = 0; i < addressUriList.Count; i++)
|
||||
{
|
||||
this.listeners[i] = new ConnectionListener(addressUriList[i], userInfo, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
foreach (var listener in this.listeners)
|
||||
{
|
||||
listener.Open();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
foreach (var listener in this.listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Close();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Trace.WriteLine(TraceLevel.Error, exception.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterMessageProcessor(string address, IMessageProcessor messageProcessor)
|
||||
{
|
||||
AddProcessor(this.messageProcessors, address, new MessageProcessor(messageProcessor));
|
||||
}
|
||||
|
||||
public void RegisterRequestProcessor(string address, IRequestProcessor requestProcessor)
|
||||
{
|
||||
AddProcessor(this.requestProcessors, address, new RequestProcessor(requestProcessor));
|
||||
}
|
||||
|
||||
public void UnregisterMessageProcessor(string address)
|
||||
{
|
||||
RemoveProcessor(this.messageProcessors, address);
|
||||
}
|
||||
|
||||
public void UnregisterRequestProcessor(string address)
|
||||
{
|
||||
RemoveProcessor(this.requestProcessors, address);
|
||||
}
|
||||
|
||||
static void AddProcessor<T>(Dictionary<string, T> processors, string address, T processor)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
if (processors.ContainsKey(address))
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotAllowed, typeof(T).Name + " already registered");
|
||||
}
|
||||
|
||||
processors[address] = processor;
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveProcessor<T>(Dictionary<string, T> processors, string address)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
T processor;
|
||||
if (processors.TryGetValue(address, out processor))
|
||||
{
|
||||
processors.Remove(address);
|
||||
if (processor is IDisposable)
|
||||
{
|
||||
((IDisposable)processor).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryGetProcessor<T>(Dictionary<string, T> processors, string address, out T processor)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
return processors.TryGetValue(address, out processor);
|
||||
}
|
||||
}
|
||||
|
||||
X509Certificate2 IContainer.ServiceCertificate
|
||||
{
|
||||
get { return this.certificate; }
|
||||
}
|
||||
|
||||
Message IContainer.CreateMessage(ByteBuffer buffer)
|
||||
{
|
||||
return Message.Decode(buffer);
|
||||
}
|
||||
|
||||
Link IContainer.CreateLink(ListenerConnection connection, ListenerSession session, Attach attach)
|
||||
{
|
||||
return new ListenerLink(session, attach);
|
||||
}
|
||||
|
||||
bool IContainer.AttachLink(ListenerConnection connection, ListenerSession session, Link link, Attach attach)
|
||||
{
|
||||
string address = attach.Role ? ((Source)attach.Source).Address : ((Target)attach.Target).Address;
|
||||
var listenerLink = (ListenerLink)link;
|
||||
|
||||
MessageProcessor messageProcessor;
|
||||
if (TryGetProcessor(this.messageProcessors, address, out messageProcessor))
|
||||
{
|
||||
messageProcessor.AddLink(listenerLink, address);
|
||||
return true;
|
||||
}
|
||||
|
||||
RequestProcessor requestProcessor;
|
||||
if (TryGetProcessor(this.requestProcessors, address, out requestProcessor))
|
||||
{
|
||||
requestProcessor.AddLink(listenerLink, address, attach);
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AmqpException(ErrorCode.NotFound, "No processor was found at " + address);
|
||||
}
|
||||
|
||||
class MessageProcessor : IDisposable
|
||||
{
|
||||
static readonly Action<ListenerLink, Message, DeliveryState, object> dispatchMessage = DispatchMessage;
|
||||
readonly IMessageProcessor processor;
|
||||
readonly List<ListenerLink> links;
|
||||
|
||||
public MessageProcessor(IMessageProcessor processor)
|
||||
{
|
||||
this.processor = processor;
|
||||
this.links = new List<ListenerLink>();
|
||||
}
|
||||
|
||||
public void AddLink(ListenerLink link, string address)
|
||||
{
|
||||
if (!link.Role)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotAllowed, "Only sender link can be attached at " + address);
|
||||
}
|
||||
|
||||
link.InitializeReceiver(300, dispatchMessage, this);
|
||||
link.Closed += OnLinkClosed;
|
||||
lock (this.links)
|
||||
{
|
||||
this.links.Add(link);
|
||||
}
|
||||
}
|
||||
|
||||
static void DispatchMessage(ListenerLink link, Message message, DeliveryState deliveryState, object state)
|
||||
{
|
||||
MessageContext context = new MessageContext(link, message);
|
||||
((MessageProcessor)state).processor.Process(context);
|
||||
}
|
||||
|
||||
static void OnLinkClosed(AmqpObject sender, Error error)
|
||||
{
|
||||
ListenerLink link = (ListenerLink)sender;
|
||||
var thisPtr = (MessageProcessor)link.State;
|
||||
lock (thisPtr.links)
|
||||
{
|
||||
thisPtr.links.Remove(link);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
lock (this.links)
|
||||
{
|
||||
for (int i = 0; i < this.links.Count; i++)
|
||||
{
|
||||
this.links[i].Close(0, new Error() { Condition = ErrorCode.DetachForced, Description = "Processor was unregistered." });
|
||||
}
|
||||
|
||||
this.links.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RequestProcessor : IDisposable
|
||||
{
|
||||
static readonly Action<ListenerLink, Message, DeliveryState, object> dispatchRequest = DispatchRequest;
|
||||
readonly IRequestProcessor processor;
|
||||
readonly List<ListenerLink> requestLinks;
|
||||
readonly Dictionary<string, ListenerLink> responseLinks;
|
||||
|
||||
public RequestProcessor(IRequestProcessor processor)
|
||||
{
|
||||
this.processor = processor;
|
||||
this.requestLinks = new List<ListenerLink>();
|
||||
this.responseLinks = new Dictionary<string, ListenerLink>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public IRequestProcessor Processor
|
||||
{
|
||||
get { return this.processor; }
|
||||
}
|
||||
|
||||
public IList<ListenerLink> Links
|
||||
{
|
||||
get { return this.requestLinks; }
|
||||
}
|
||||
|
||||
public void AddLink(ListenerLink link, string address, Attach attach)
|
||||
{
|
||||
if (!link.Role)
|
||||
{
|
||||
string replyTo = ((Target)attach.Target).Address;
|
||||
AddProcessor(this.responseLinks, replyTo, link);
|
||||
link.SettleOnSend = true;
|
||||
link.InitializeSender((c, s) => { }, null, Tuple.Create(this, replyTo));
|
||||
link.Closed += OnLinkClosed;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.InitializeReceiver(300, dispatchRequest, this);
|
||||
link.Closed += OnLinkClosed;
|
||||
lock (this.requestLinks)
|
||||
{
|
||||
this.requestLinks.Add(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OnLinkClosed(AmqpObject sender, Error error)
|
||||
{
|
||||
ListenerLink link = (ListenerLink)sender;
|
||||
if (!link.Role)
|
||||
{
|
||||
var tuple = (Tuple<RequestProcessor, string>)link.State;
|
||||
RemoveProcessor(tuple.Item1.responseLinks, tuple.Item2);
|
||||
}
|
||||
else
|
||||
{
|
||||
var thisPtr = (RequestProcessor)link.State;
|
||||
lock (thisPtr.requestLinks)
|
||||
{
|
||||
thisPtr.requestLinks.Remove(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DispatchRequest(ListenerLink link, Message message, DeliveryState deliveryState, object state)
|
||||
{
|
||||
RequestProcessor thisPtr = (RequestProcessor)state;
|
||||
|
||||
ListenerLink responseLink = null;
|
||||
if (message.Properties != null || message.Properties.ReplyTo != null)
|
||||
{
|
||||
thisPtr.responseLinks.TryGetValue(message.Properties.ReplyTo, out responseLink);
|
||||
}
|
||||
|
||||
Outcome outcome;
|
||||
if (responseLink == null)
|
||||
{
|
||||
outcome = new Rejected()
|
||||
{
|
||||
Error = new Error()
|
||||
{
|
||||
Condition = ErrorCode.NotFound,
|
||||
Description = "Not response link was found. Ensure the link is attached or reply-to is set on the request."
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
outcome = new Accepted();
|
||||
}
|
||||
|
||||
link.DisposeMessage(message, outcome, true);
|
||||
|
||||
RequestContext context = new RequestContext(link, responseLink, message);
|
||||
thisPtr.processor.Process(context);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Error error = new Error() { Condition = ErrorCode.DetachForced, Description = "Processor was unregistered." };
|
||||
lock (this.requestLinks)
|
||||
{
|
||||
for (int i = 0; i < this.requestLinks.Count; i++)
|
||||
{
|
||||
this.requestLinks[i].Close(0, error);
|
||||
}
|
||||
|
||||
this.requestLinks.Clear();
|
||||
}
|
||||
|
||||
lock (this.responseLinks)
|
||||
{
|
||||
foreach (var link in this.responseLinks.Values)
|
||||
{
|
||||
link.Close(0, error);
|
||||
}
|
||||
|
||||
this.responseLinks.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ContainerHost : IContainer
|
||||
{
|
||||
readonly X509Certificate2 certificate;
|
||||
readonly ConnectionListener[] listeners;
|
||||
readonly Dictionary<string, MessageProcessor> messageProcessors;
|
||||
readonly Dictionary<string, RequestProcessor> requestProcessors;
|
||||
|
||||
public ContainerHost(Uri addressUri)
|
||||
: this(new Uri[] { addressUri }, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ContainerHost(IList<Uri> addressUriList, X509Certificate2 certificate, string userInfo)
|
||||
{
|
||||
this.certificate = certificate;
|
||||
this.messageProcessors = new Dictionary<string, MessageProcessor>(StringComparer.OrdinalIgnoreCase);
|
||||
this.requestProcessors = new Dictionary<string, RequestProcessor>(StringComparer.OrdinalIgnoreCase);
|
||||
this.listeners = new ConnectionListener[addressUriList.Count];
|
||||
for (int i = 0; i < addressUriList.Count; i++)
|
||||
{
|
||||
this.listeners[i] = new ConnectionListener(addressUriList[i], userInfo, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
foreach (var listener in this.listeners)
|
||||
{
|
||||
listener.Open();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
foreach (var listener in this.listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Close();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Trace.WriteLine(TraceLevel.Error, exception.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterMessageProcessor(string address, IMessageProcessor messageProcessor)
|
||||
{
|
||||
AddProcessor(this.messageProcessors, address, new MessageProcessor(messageProcessor));
|
||||
}
|
||||
|
||||
public void RegisterRequestProcessor(string address, IRequestProcessor requestProcessor)
|
||||
{
|
||||
AddProcessor(this.requestProcessors, address, new RequestProcessor(requestProcessor));
|
||||
}
|
||||
|
||||
public void UnregisterMessageProcessor(string address)
|
||||
{
|
||||
RemoveProcessor(this.messageProcessors, address);
|
||||
}
|
||||
|
||||
public void UnregisterRequestProcessor(string address)
|
||||
{
|
||||
RemoveProcessor(this.requestProcessors, address);
|
||||
}
|
||||
|
||||
static void AddProcessor<T>(Dictionary<string, T> processors, string address, T processor)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
if (processors.ContainsKey(address))
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotAllowed, typeof(T).Name + " already registered");
|
||||
}
|
||||
|
||||
processors[address] = processor;
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveProcessor<T>(Dictionary<string, T> processors, string address)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
T processor;
|
||||
if (processors.TryGetValue(address, out processor))
|
||||
{
|
||||
processors.Remove(address);
|
||||
if (processor is IDisposable)
|
||||
{
|
||||
((IDisposable)processor).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryGetProcessor<T>(Dictionary<string, T> processors, string address, out T processor)
|
||||
{
|
||||
lock (processors)
|
||||
{
|
||||
return processors.TryGetValue(address, out processor);
|
||||
}
|
||||
}
|
||||
|
||||
X509Certificate2 IContainer.ServiceCertificate
|
||||
{
|
||||
get { return this.certificate; }
|
||||
}
|
||||
|
||||
Message IContainer.CreateMessage(ByteBuffer buffer)
|
||||
{
|
||||
return Message.Decode(buffer);
|
||||
}
|
||||
|
||||
Link IContainer.CreateLink(ListenerConnection connection, ListenerSession session, Attach attach)
|
||||
{
|
||||
return new ListenerLink(session, attach);
|
||||
}
|
||||
|
||||
bool IContainer.AttachLink(ListenerConnection connection, ListenerSession session, Link link, Attach attach)
|
||||
{
|
||||
string address = attach.Role ? ((Source)attach.Source).Address : ((Target)attach.Target).Address;
|
||||
var listenerLink = (ListenerLink)link;
|
||||
|
||||
MessageProcessor messageProcessor;
|
||||
if (TryGetProcessor(this.messageProcessors, address, out messageProcessor))
|
||||
{
|
||||
messageProcessor.AddLink(listenerLink, address);
|
||||
return true;
|
||||
}
|
||||
|
||||
RequestProcessor requestProcessor;
|
||||
if (TryGetProcessor(this.requestProcessors, address, out requestProcessor))
|
||||
{
|
||||
requestProcessor.AddLink(listenerLink, address, attach);
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AmqpException(ErrorCode.NotFound, "No processor was found at " + address);
|
||||
}
|
||||
|
||||
class MessageProcessor : IDisposable
|
||||
{
|
||||
static readonly Action<ListenerLink, Message, DeliveryState, object> dispatchMessage = DispatchMessage;
|
||||
readonly IMessageProcessor processor;
|
||||
readonly List<ListenerLink> links;
|
||||
|
||||
public MessageProcessor(IMessageProcessor processor)
|
||||
{
|
||||
this.processor = processor;
|
||||
this.links = new List<ListenerLink>();
|
||||
}
|
||||
|
||||
public void AddLink(ListenerLink link, string address)
|
||||
{
|
||||
if (!link.Role)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotAllowed, "Only sender link can be attached at " + address);
|
||||
}
|
||||
|
||||
link.InitializeReceiver(300, dispatchMessage, this);
|
||||
link.Closed += OnLinkClosed;
|
||||
lock (this.links)
|
||||
{
|
||||
this.links.Add(link);
|
||||
}
|
||||
}
|
||||
|
||||
static void DispatchMessage(ListenerLink link, Message message, DeliveryState deliveryState, object state)
|
||||
{
|
||||
MessageContext context = new MessageContext(link, message);
|
||||
((MessageProcessor)state).processor.Process(context);
|
||||
}
|
||||
|
||||
static void OnLinkClosed(AmqpObject sender, Error error)
|
||||
{
|
||||
ListenerLink link = (ListenerLink)sender;
|
||||
var thisPtr = (MessageProcessor)link.State;
|
||||
lock (thisPtr.links)
|
||||
{
|
||||
thisPtr.links.Remove(link);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
lock (this.links)
|
||||
{
|
||||
for (int i = 0; i < this.links.Count; i++)
|
||||
{
|
||||
this.links[i].Close(0, new Error() { Condition = ErrorCode.DetachForced, Description = "Processor was unregistered." });
|
||||
}
|
||||
|
||||
this.links.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RequestProcessor : IDisposable
|
||||
{
|
||||
static readonly Action<ListenerLink, Message, DeliveryState, object> dispatchRequest = DispatchRequest;
|
||||
readonly IRequestProcessor processor;
|
||||
readonly List<ListenerLink> requestLinks;
|
||||
readonly Dictionary<string, ListenerLink> responseLinks;
|
||||
|
||||
public RequestProcessor(IRequestProcessor processor)
|
||||
{
|
||||
this.processor = processor;
|
||||
this.requestLinks = new List<ListenerLink>();
|
||||
this.responseLinks = new Dictionary<string, ListenerLink>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public IRequestProcessor Processor
|
||||
{
|
||||
get { return this.processor; }
|
||||
}
|
||||
|
||||
public IList<ListenerLink> Links
|
||||
{
|
||||
get { return this.requestLinks; }
|
||||
}
|
||||
|
||||
public void AddLink(ListenerLink link, string address, Attach attach)
|
||||
{
|
||||
if (!link.Role)
|
||||
{
|
||||
string replyTo = ((Target)attach.Target).Address;
|
||||
AddProcessor(this.responseLinks, replyTo, link);
|
||||
link.SettleOnSend = true;
|
||||
link.InitializeSender((c, s) => { }, null, Tuple.Create(this, replyTo));
|
||||
link.Closed += OnLinkClosed;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.InitializeReceiver(300, dispatchRequest, this);
|
||||
link.Closed += OnLinkClosed;
|
||||
lock (this.requestLinks)
|
||||
{
|
||||
this.requestLinks.Add(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OnLinkClosed(AmqpObject sender, Error error)
|
||||
{
|
||||
ListenerLink link = (ListenerLink)sender;
|
||||
if (!link.Role)
|
||||
{
|
||||
var tuple = (Tuple<RequestProcessor, string>)link.State;
|
||||
RemoveProcessor(tuple.Item1.responseLinks, tuple.Item2);
|
||||
}
|
||||
else
|
||||
{
|
||||
var thisPtr = (RequestProcessor)link.State;
|
||||
lock (thisPtr.requestLinks)
|
||||
{
|
||||
thisPtr.requestLinks.Remove(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DispatchRequest(ListenerLink link, Message message, DeliveryState deliveryState, object state)
|
||||
{
|
||||
RequestProcessor thisPtr = (RequestProcessor)state;
|
||||
|
||||
ListenerLink responseLink = null;
|
||||
if (message.Properties != null || message.Properties.ReplyTo != null)
|
||||
{
|
||||
thisPtr.responseLinks.TryGetValue(message.Properties.ReplyTo, out responseLink);
|
||||
}
|
||||
|
||||
Outcome outcome;
|
||||
if (responseLink == null)
|
||||
{
|
||||
outcome = new Rejected()
|
||||
{
|
||||
Error = new Error()
|
||||
{
|
||||
Condition = ErrorCode.NotFound,
|
||||
Description = "Not response link was found. Ensure the link is attached or reply-to is set on the request."
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
outcome = new Accepted();
|
||||
}
|
||||
|
||||
link.DisposeMessage(message, outcome, true);
|
||||
|
||||
RequestContext context = new RequestContext(link, responseLink, message);
|
||||
thisPtr.processor.Process(context);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Error error = new Error() { Condition = ErrorCode.DetachForced, Description = "Processor was unregistered." };
|
||||
lock (this.requestLinks)
|
||||
{
|
||||
for (int i = 0; i < this.requestLinks.Count; i++)
|
||||
{
|
||||
this.requestLinks[i].Close(0, error);
|
||||
}
|
||||
|
||||
this.requestLinks.Clear();
|
||||
}
|
||||
|
||||
lock (this.responseLinks)
|
||||
{
|
||||
foreach (var link in this.responseLinks.Values)
|
||||
{
|
||||
link.Close(0, error);
|
||||
}
|
||||
|
||||
this.responseLinks.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,99 +1,99 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using Amqp.Framing;
|
||||
|
||||
public interface IMessageProcessor
|
||||
{
|
||||
void Process(MessageContext messageContext);
|
||||
}
|
||||
|
||||
public interface IRequestProcessor
|
||||
{
|
||||
void Process(RequestContext requestContext);
|
||||
}
|
||||
|
||||
public abstract class Context
|
||||
{
|
||||
protected static Accepted Accepted = new Accepted();
|
||||
|
||||
protected Context(ListenerLink link, Message message)
|
||||
{
|
||||
this.Link = link;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
public ListenerLink Link
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Message Message
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
protected void Dispose(DeliveryState deliveryState)
|
||||
{
|
||||
this.Link.DisposeMessage(this.Message, deliveryState, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageContext : Context
|
||||
{
|
||||
internal MessageContext(ListenerLink link, Message message)
|
||||
: base(link, message)
|
||||
{
|
||||
}
|
||||
|
||||
public void Complete()
|
||||
{
|
||||
this.Dispose(Context.Accepted);
|
||||
}
|
||||
|
||||
public void Complete(Error error)
|
||||
{
|
||||
this.Dispose(new Rejected() { Error = error });
|
||||
}
|
||||
}
|
||||
|
||||
public class RequestContext : Context
|
||||
{
|
||||
readonly ListenerLink responseLink;
|
||||
|
||||
internal RequestContext(ListenerLink requestLink, ListenerLink responseLink, Message request)
|
||||
: base(requestLink, request)
|
||||
{
|
||||
this.responseLink = responseLink;
|
||||
}
|
||||
|
||||
public void Complete(Message response)
|
||||
{
|
||||
if (response.Properties == null)
|
||||
{
|
||||
response.Properties = new Properties();
|
||||
}
|
||||
|
||||
response.Properties.CorrelationId = this.Message.Properties.MessageId;
|
||||
this.responseLink.SendMessage(response, response.Encode());
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using Amqp.Framing;
|
||||
|
||||
public interface IMessageProcessor
|
||||
{
|
||||
void Process(MessageContext messageContext);
|
||||
}
|
||||
|
||||
public interface IRequestProcessor
|
||||
{
|
||||
void Process(RequestContext requestContext);
|
||||
}
|
||||
|
||||
public abstract class Context
|
||||
{
|
||||
protected static Accepted Accepted = new Accepted();
|
||||
|
||||
protected Context(ListenerLink link, Message message)
|
||||
{
|
||||
this.Link = link;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
public ListenerLink Link
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Message Message
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
protected void Dispose(DeliveryState deliveryState)
|
||||
{
|
||||
this.Link.DisposeMessage(this.Message, deliveryState, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageContext : Context
|
||||
{
|
||||
internal MessageContext(ListenerLink link, Message message)
|
||||
: base(link, message)
|
||||
{
|
||||
}
|
||||
|
||||
public void Complete()
|
||||
{
|
||||
this.Dispose(Context.Accepted);
|
||||
}
|
||||
|
||||
public void Complete(Error error)
|
||||
{
|
||||
this.Dispose(new Rejected() { Error = error });
|
||||
}
|
||||
}
|
||||
|
||||
public class RequestContext : Context
|
||||
{
|
||||
readonly ListenerLink responseLink;
|
||||
|
||||
internal RequestContext(ListenerLink requestLink, ListenerLink responseLink, Message request)
|
||||
: base(requestLink, request)
|
||||
{
|
||||
this.responseLink = responseLink;
|
||||
}
|
||||
|
||||
public void Complete(Message response)
|
||||
{
|
||||
if (response.Properties == null)
|
||||
{
|
||||
response.Properties = new Properties();
|
||||
}
|
||||
|
||||
response.Properties.CorrelationId = this.Message.Properties.MessageId;
|
||||
this.responseLink.SendMessage(response, response.Encode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Amqp.Framing;
|
||||
|
||||
public interface IContainer
|
||||
{
|
||||
X509Certificate2 ServiceCertificate { get; }
|
||||
|
||||
Message CreateMessage(ByteBuffer buffer);
|
||||
|
||||
Link CreateLink(ListenerConnection connection, ListenerSession session, Attach attach);
|
||||
|
||||
bool AttachLink(ListenerConnection connection, ListenerSession session, Link link, Attach attach);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Amqp.Framing;
|
||||
|
||||
public interface IContainer
|
||||
{
|
||||
X509Certificate2 ServiceCertificate { get; }
|
||||
|
||||
Message CreateMessage(ByteBuffer buffer);
|
||||
|
||||
Link CreateLink(ListenerConnection connection, ListenerSession session, Attach attach);
|
||||
|
||||
bool AttachLink(ListenerConnection connection, ListenerSession session, Link link, Attach attach);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Threading;
|
||||
using Amqp.Framing;
|
||||
|
||||
public class ListenerConnection : Connection
|
||||
{
|
||||
readonly ConnectionListener listener;
|
||||
|
||||
internal ListenerConnection(ConnectionListener listener, Address address, IAsyncTransport transport)
|
||||
: base(listener, address, transport, null, null)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
internal ConnectionListener Listener
|
||||
{
|
||||
get { return this.listener; }
|
||||
}
|
||||
|
||||
internal override void OnBegin(ushort remoteChannel, Begin begin)
|
||||
{
|
||||
// this sends a begin to the remote peer
|
||||
begin.RemoteChannel = remoteChannel;
|
||||
var session = new ListenerSession(this, begin);
|
||||
|
||||
// this updates the local session state
|
||||
begin.RemoteChannel = session.Channel;
|
||||
base.OnBegin(remoteChannel, begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Threading;
|
||||
using Amqp.Framing;
|
||||
|
||||
public class ListenerConnection : Connection
|
||||
{
|
||||
readonly ConnectionListener listener;
|
||||
|
||||
internal ListenerConnection(ConnectionListener listener, Address address, IAsyncTransport transport)
|
||||
: base(listener, address, transport, null, null)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
internal ConnectionListener Listener
|
||||
{
|
||||
get { return this.listener; }
|
||||
}
|
||||
|
||||
internal override void OnBegin(ushort remoteChannel, Begin begin)
|
||||
{
|
||||
// this sends a begin to the remote peer
|
||||
begin.RemoteChannel = remoteChannel;
|
||||
var session = new ListenerSession(this, begin);
|
||||
|
||||
// this updates the local session state
|
||||
begin.RemoteChannel = session.Channel;
|
||||
base.OnBegin(remoteChannel, begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,225 +1,225 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ListenerLink : Link
|
||||
{
|
||||
bool role;
|
||||
uint credit;
|
||||
object state;
|
||||
|
||||
// send
|
||||
Action<int, object> onCredit;
|
||||
Action<Message, DeliveryState, bool, object> onDispose;
|
||||
|
||||
// receive
|
||||
SequenceNumber deliveryCount;
|
||||
int delivered;
|
||||
Delivery deliveryCurrent;
|
||||
Action<ListenerLink, Message, DeliveryState, object> onMessage;
|
||||
|
||||
public ListenerLink(ListenerSession session, Attach attach)
|
||||
: base(session, attach.LinkName, null)
|
||||
{
|
||||
this.role = !attach.Role;
|
||||
this.SettleOnSend = attach.SndSettleMode == SenderSettleMode.Settled;
|
||||
}
|
||||
|
||||
public bool Role
|
||||
{
|
||||
get { return this.role; }
|
||||
}
|
||||
|
||||
public bool SettleOnSend
|
||||
{
|
||||
get; internal set;
|
||||
}
|
||||
|
||||
public object State
|
||||
{
|
||||
get { return this.state; }
|
||||
}
|
||||
|
||||
public void InitializeReceiver(uint credit, Action<ListenerLink, Message, DeliveryState, object> onMessage, object state)
|
||||
{
|
||||
this.credit = credit;
|
||||
this.onMessage = onMessage;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void InitializeSender(Action<int, object> onCredit, Action<Message, DeliveryState, bool, object> onDispose, object state)
|
||||
{
|
||||
this.onCredit = onCredit;
|
||||
this.onDispose = onDispose;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void SendMessage(Message message, ByteBuffer buffer)
|
||||
{
|
||||
Delivery delivery = new Delivery()
|
||||
{
|
||||
Handle = this.Handle,
|
||||
Message = message,
|
||||
Buffer = buffer,
|
||||
Link = this,
|
||||
Settled = this.SettleOnSend
|
||||
};
|
||||
|
||||
this.Session.SendDelivery(delivery);
|
||||
this.deliveryCount++;
|
||||
}
|
||||
|
||||
public void DisposeMessage(Message message, DeliveryState deliveryState, bool settled)
|
||||
{
|
||||
Delivery delivery = message.Delivery;
|
||||
if (delivery == null || delivery.Settled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Session.DisposeDelivery(this.role, delivery, deliveryState, settled);
|
||||
}
|
||||
|
||||
public void CompleteAttach(Attach attach, Error error)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
this.SendAttach(!attach.Role, attach.InitialDeliveryCount, new Attach() { Target = null, Source = null });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SendAttach(!attach.Role, attach.InitialDeliveryCount, new Attach() { Target = attach.Target, Source = attach.Source });
|
||||
}
|
||||
|
||||
base.OnAttach(attach.Handle, attach);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
this.Close(0, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.credit > 0)
|
||||
{
|
||||
this.SendFlow(this.deliveryCount, credit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
var container = ((ListenerConnection)this.Session.Connection).Listener.Container;
|
||||
|
||||
Error error = null;
|
||||
|
||||
try
|
||||
{
|
||||
bool done = container.AttachLink((ListenerConnection)this.Session.Connection, (ListenerSession)this.Session, this, attach);
|
||||
if (!done)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (AmqpException amqpException)
|
||||
{
|
||||
error = amqpException.Error;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
error = new Error() { Condition = ErrorCode.InternalError, Description = exception.Message };
|
||||
}
|
||||
|
||||
this.CompleteAttach(attach, error);
|
||||
}
|
||||
|
||||
internal override void OnFlow(Flow flow)
|
||||
{
|
||||
if (this.onCredit != null)
|
||||
{
|
||||
var theirLimit = (SequenceNumber)(flow.DeliveryCount + flow.LinkCredit);
|
||||
var myLimit = (SequenceNumber)((uint)this.deliveryCount + this.credit);
|
||||
int delta = theirLimit - myLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
this.onCredit(delta, this.state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnDeliveryStateChanged(Delivery delivery)
|
||||
{
|
||||
if (this.onDispose != null)
|
||||
{
|
||||
this.onDispose(delivery.Message, delivery.State, delivery.Settled, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
|
||||
{
|
||||
if (delivery != null)
|
||||
{
|
||||
this.deliveryCount++;
|
||||
if (!transfer.More)
|
||||
{
|
||||
// single transfer message - the most common case
|
||||
delivery.Buffer = buffer;
|
||||
this.DeliverMessage(delivery);
|
||||
}
|
||||
else
|
||||
{
|
||||
delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = delivery;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delivery = this.deliveryCurrent;
|
||||
if (!transfer.More)
|
||||
{
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = null;
|
||||
this.DeliverMessage(delivery);
|
||||
}
|
||||
else
|
||||
{
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAbort(Error error)
|
||||
{
|
||||
}
|
||||
|
||||
void DeliverMessage(Delivery delivery)
|
||||
{
|
||||
var container = ((ListenerConnection)this.Session.Connection).Listener.Container;
|
||||
delivery.Message = container.CreateMessage(delivery.Buffer);
|
||||
this.onMessage(this, delivery.Message, delivery.State, this.state);
|
||||
if (this.delivered++ >= this.credit / 2)
|
||||
{
|
||||
this.SendFlow(this.deliveryCount, this.credit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ListenerLink : Link
|
||||
{
|
||||
bool role;
|
||||
uint credit;
|
||||
object state;
|
||||
|
||||
// send
|
||||
Action<int, object> onCredit;
|
||||
Action<Message, DeliveryState, bool, object> onDispose;
|
||||
|
||||
// receive
|
||||
SequenceNumber deliveryCount;
|
||||
int delivered;
|
||||
Delivery deliveryCurrent;
|
||||
Action<ListenerLink, Message, DeliveryState, object> onMessage;
|
||||
|
||||
public ListenerLink(ListenerSession session, Attach attach)
|
||||
: base(session, attach.LinkName, null)
|
||||
{
|
||||
this.role = !attach.Role;
|
||||
this.SettleOnSend = attach.SndSettleMode == SenderSettleMode.Settled;
|
||||
}
|
||||
|
||||
public bool Role
|
||||
{
|
||||
get { return this.role; }
|
||||
}
|
||||
|
||||
public bool SettleOnSend
|
||||
{
|
||||
get; internal set;
|
||||
}
|
||||
|
||||
public object State
|
||||
{
|
||||
get { return this.state; }
|
||||
}
|
||||
|
||||
public void InitializeReceiver(uint credit, Action<ListenerLink, Message, DeliveryState, object> onMessage, object state)
|
||||
{
|
||||
this.credit = credit;
|
||||
this.onMessage = onMessage;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void InitializeSender(Action<int, object> onCredit, Action<Message, DeliveryState, bool, object> onDispose, object state)
|
||||
{
|
||||
this.onCredit = onCredit;
|
||||
this.onDispose = onDispose;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void SendMessage(Message message, ByteBuffer buffer)
|
||||
{
|
||||
Delivery delivery = new Delivery()
|
||||
{
|
||||
Handle = this.Handle,
|
||||
Message = message,
|
||||
Buffer = buffer,
|
||||
Link = this,
|
||||
Settled = this.SettleOnSend
|
||||
};
|
||||
|
||||
this.Session.SendDelivery(delivery);
|
||||
this.deliveryCount++;
|
||||
}
|
||||
|
||||
public void DisposeMessage(Message message, DeliveryState deliveryState, bool settled)
|
||||
{
|
||||
Delivery delivery = message.Delivery;
|
||||
if (delivery == null || delivery.Settled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Session.DisposeDelivery(this.role, delivery, deliveryState, settled);
|
||||
}
|
||||
|
||||
public void CompleteAttach(Attach attach, Error error)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
this.SendAttach(!attach.Role, attach.InitialDeliveryCount, new Attach() { Target = null, Source = null });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SendAttach(!attach.Role, attach.InitialDeliveryCount, new Attach() { Target = attach.Target, Source = attach.Source });
|
||||
}
|
||||
|
||||
base.OnAttach(attach.Handle, attach);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
this.Close(0, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.credit > 0)
|
||||
{
|
||||
this.SendFlow(this.deliveryCount, credit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
var container = ((ListenerConnection)this.Session.Connection).Listener.Container;
|
||||
|
||||
Error error = null;
|
||||
|
||||
try
|
||||
{
|
||||
bool done = container.AttachLink((ListenerConnection)this.Session.Connection, (ListenerSession)this.Session, this, attach);
|
||||
if (!done)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (AmqpException amqpException)
|
||||
{
|
||||
error = amqpException.Error;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
error = new Error() { Condition = ErrorCode.InternalError, Description = exception.Message };
|
||||
}
|
||||
|
||||
this.CompleteAttach(attach, error);
|
||||
}
|
||||
|
||||
internal override void OnFlow(Flow flow)
|
||||
{
|
||||
if (this.onCredit != null)
|
||||
{
|
||||
var theirLimit = (SequenceNumber)(flow.DeliveryCount + flow.LinkCredit);
|
||||
var myLimit = (SequenceNumber)((uint)this.deliveryCount + this.credit);
|
||||
int delta = theirLimit - myLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
this.onCredit(delta, this.state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnDeliveryStateChanged(Delivery delivery)
|
||||
{
|
||||
if (this.onDispose != null)
|
||||
{
|
||||
this.onDispose(delivery.Message, delivery.State, delivery.Settled, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
|
||||
{
|
||||
if (delivery != null)
|
||||
{
|
||||
this.deliveryCount++;
|
||||
if (!transfer.More)
|
||||
{
|
||||
// single transfer message - the most common case
|
||||
delivery.Buffer = buffer;
|
||||
this.DeliverMessage(delivery);
|
||||
}
|
||||
else
|
||||
{
|
||||
delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = delivery;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delivery = this.deliveryCurrent;
|
||||
if (!transfer.More)
|
||||
{
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = null;
|
||||
this.DeliverMessage(delivery);
|
||||
}
|
||||
else
|
||||
{
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAbort(Error error)
|
||||
{
|
||||
}
|
||||
|
||||
void DeliverMessage(Delivery delivery)
|
||||
{
|
||||
var container = ((ListenerConnection)this.Session.Connection).Listener.Container;
|
||||
delivery.Message = container.CreateMessage(delivery.Buffer);
|
||||
this.onMessage(this, delivery.Message, delivery.State, this.state);
|
||||
if (this.delivered++ >= this.credit / 2)
|
||||
{
|
||||
this.SendFlow(this.deliveryCount, this.credit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ListenerSession : Session
|
||||
{
|
||||
internal ListenerSession(ListenerConnection connection, Begin begin)
|
||||
: base(connection, begin)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void OnAttach(Attach attach)
|
||||
{
|
||||
var connection = (ListenerConnection)this.Connection;
|
||||
Link link = connection.Listener.Container.CreateLink(connection, this, attach);
|
||||
base.OnAttach(attach);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public class ListenerSession : Session
|
||||
{
|
||||
internal ListenerSession(ListenerConnection connection, Begin begin)
|
||||
: base(connection, begin)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void OnAttach(Attach attach)
|
||||
{
|
||||
var connection = (ListenerConnection)this.Connection;
|
||||
Link link = connection.Listener.Container.CreateLink(connection, this, attach);
|
||||
base.OnAttach(attach);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,99 +1,99 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
class AsyncPump
|
||||
{
|
||||
readonly IAsyncTransport transport;
|
||||
|
||||
public AsyncPump(IAsyncTransport transport)
|
||||
{
|
||||
this.transport = transport;
|
||||
}
|
||||
|
||||
public void Start(Connection connection)
|
||||
{
|
||||
Task task = this.StartAsync(connection);
|
||||
}
|
||||
|
||||
public async Task PumpAsync(Func<ProtocolHeader, bool> onHeader, Func<ByteBuffer, bool> onBuffer)
|
||||
{
|
||||
byte[] header = new byte[FixedWidth.ULong];
|
||||
|
||||
if (onHeader != null)
|
||||
{
|
||||
// header
|
||||
await this.ReceiveBufferAsync(header, 0, FixedWidth.ULong);
|
||||
if (!onHeader(ProtocolHeader.Create(header, 0)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// frames
|
||||
while (true)
|
||||
{
|
||||
await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt);
|
||||
int frameSize = AmqpBitConverter.ReadInt(header, 0);
|
||||
|
||||
byte[] buffer = new byte[frameSize];
|
||||
Buffer.BlockCopy(header, 0, buffer, 0, FixedWidth.UInt);
|
||||
|
||||
await this.ReceiveBufferAsync(buffer, FixedWidth.UInt, frameSize - FixedWidth.UInt);
|
||||
if (!onBuffer(new ByteBuffer(buffer, 0, frameSize, frameSize)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task StartAsync(Connection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.PumpAsync(connection.OnHeader, connection.OnFrame);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
connection.OnIoException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async Task ReceiveBufferAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
while (count > 0)
|
||||
{
|
||||
int received = await this.transport.ReceiveAsync(buffer, offset, count);
|
||||
if (received == 0)
|
||||
{
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
}
|
||||
|
||||
offset += received;
|
||||
count -= received;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
class AsyncPump
|
||||
{
|
||||
readonly IAsyncTransport transport;
|
||||
|
||||
public AsyncPump(IAsyncTransport transport)
|
||||
{
|
||||
this.transport = transport;
|
||||
}
|
||||
|
||||
public void Start(Connection connection)
|
||||
{
|
||||
Task task = this.StartAsync(connection);
|
||||
}
|
||||
|
||||
public async Task PumpAsync(Func<ProtocolHeader, bool> onHeader, Func<ByteBuffer, bool> onBuffer)
|
||||
{
|
||||
byte[] header = new byte[FixedWidth.ULong];
|
||||
|
||||
if (onHeader != null)
|
||||
{
|
||||
// header
|
||||
await this.ReceiveBufferAsync(header, 0, FixedWidth.ULong);
|
||||
if (!onHeader(ProtocolHeader.Create(header, 0)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// frames
|
||||
while (true)
|
||||
{
|
||||
await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt);
|
||||
int frameSize = AmqpBitConverter.ReadInt(header, 0);
|
||||
|
||||
byte[] buffer = new byte[frameSize];
|
||||
Buffer.BlockCopy(header, 0, buffer, 0, FixedWidth.UInt);
|
||||
|
||||
await this.ReceiveBufferAsync(buffer, FixedWidth.UInt, frameSize - FixedWidth.UInt);
|
||||
if (!onBuffer(new ByteBuffer(buffer, 0, frameSize, frameSize)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task StartAsync(Connection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.PumpAsync(connection.OnHeader, connection.OnFrame);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
connection.OnIoException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async Task ReceiveBufferAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
while (count > 0)
|
||||
{
|
||||
int received = await this.transport.ReceiveAsync(buffer, offset, count);
|
||||
if (received == 0)
|
||||
{
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
}
|
||||
|
||||
offset += received;
|
||||
count -= received;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,251 +1,251 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
|
||||
public class ConnectionFactory
|
||||
{
|
||||
internal TcpSettings tcpSettings;
|
||||
internal SslSettings sslSettings;
|
||||
internal SaslSettings saslSettings;
|
||||
internal AmqpSettings amqpSettings;
|
||||
|
||||
public ConnectionFactory()
|
||||
{
|
||||
this.amqpSettings = new AmqpSettings()
|
||||
{
|
||||
MaxFrameSize = (int)Connection.DefaultMaxFrameSize,
|
||||
ContainerId = Process.GetCurrentProcess().ProcessName,
|
||||
IdleTimeout = int.MaxValue,
|
||||
MaxSessionsPerConnection = 8
|
||||
};
|
||||
}
|
||||
|
||||
public TcpSettings TCP
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.tcpSettings ?? (this.tcpSettings = new TcpSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public SslSettings SSL
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.sslSettings ?? (this.sslSettings = new SslSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public SaslSettings SASL
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.saslSettings ?? (this.saslSettings = new SaslSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public AmqpSettings AMQP
|
||||
{
|
||||
get { return this.amqpSettings; }
|
||||
}
|
||||
|
||||
public Task<Connection> CreateAsync(Address address)
|
||||
{
|
||||
return this.CreateAsync(address, null, null);
|
||||
}
|
||||
|
||||
public Task<Connection> CreateAsync(Address address, OnOpened onOpened)
|
||||
{
|
||||
return this.CreateAsync(address, null, onOpened);
|
||||
}
|
||||
|
||||
public async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened)
|
||||
{
|
||||
IAsyncTransport transport;
|
||||
if (WebSocketTransport.MatchScheme(address.Scheme))
|
||||
{
|
||||
WebSocketTransport wsTransport = new WebSocketTransport();
|
||||
await wsTransport.ConnectAsync(address);
|
||||
transport = wsTransport;
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpTransport tcpTransport = new TcpTransport();
|
||||
await tcpTransport.ConnectAsync(address, this);
|
||||
transport = tcpTransport;
|
||||
}
|
||||
|
||||
if (address.User != null)
|
||||
{
|
||||
SaslPlainProfile profile = new SaslPlainProfile(address.User, address.Password);
|
||||
transport = await profile.OpenAsync(address.Host, transport);
|
||||
}
|
||||
else if (this.saslSettings != null && this.saslSettings.Profile != null)
|
||||
{
|
||||
transport = await this.saslSettings.Profile.OpenAsync(address.Host, transport);
|
||||
}
|
||||
|
||||
AsyncPump pump = new AsyncPump(transport);
|
||||
Connection connection = new Connection(this, address, transport, open, onOpened);
|
||||
pump.Start(connection);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
public class TcpSettings
|
||||
{
|
||||
const int DefaultBufferSize = 8192;
|
||||
bool? noDelay;
|
||||
int? receiveBufferSize;
|
||||
int? receiveTimeout;
|
||||
int? sendBufferSize;
|
||||
int? sendTimeout;
|
||||
|
||||
public LingerOption LingerOption
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool NoDelay
|
||||
{
|
||||
get { return this.noDelay ?? false; }
|
||||
set { this.noDelay = value; }
|
||||
}
|
||||
|
||||
public int ReceiveBufferSize
|
||||
{
|
||||
get { return this.receiveBufferSize ?? DefaultBufferSize; }
|
||||
set { this.receiveBufferSize = value; }
|
||||
}
|
||||
|
||||
public int ReceiveTimeout
|
||||
{
|
||||
get { return this.receiveTimeout ?? 0; }
|
||||
set { this.receiveTimeout = value; }
|
||||
}
|
||||
|
||||
public int SendBufferSize
|
||||
{
|
||||
get { return this.sendBufferSize ?? DefaultBufferSize; }
|
||||
set { this.sendBufferSize = value; }
|
||||
}
|
||||
|
||||
public int SendTimeout
|
||||
{
|
||||
get { return this.sendTimeout ?? 0; }
|
||||
set { this.sendTimeout = value; }
|
||||
}
|
||||
|
||||
internal void Configure(Socket socket)
|
||||
{
|
||||
if (this.noDelay != null) socket.NoDelay = this.noDelay.Value;
|
||||
if (this.receiveBufferSize != null) socket.ReceiveBufferSize = this.receiveBufferSize.Value;
|
||||
if (this.receiveTimeout != null) socket.ReceiveTimeout = this.receiveTimeout.Value;
|
||||
if (this.sendBufferSize != null) socket.SendBufferSize = this.sendBufferSize.Value;
|
||||
if (this.sendTimeout != null) socket.SendTimeout = this.sendTimeout.Value;
|
||||
if (this.LingerOption != null) socket.LingerState = this.LingerOption;
|
||||
}
|
||||
}
|
||||
|
||||
public class SslSettings
|
||||
{
|
||||
public SslSettings()
|
||||
{
|
||||
this.Protocols = SslProtocols.Default;
|
||||
this.ClientCertificates = new X509CertificateCollection();
|
||||
}
|
||||
|
||||
public X509CertificateCollection ClientCertificates
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public SslProtocols Protocols
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool CheckCertificateRevocation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RemoteCertificateValidationCallback RemoteCertificateValidationCallback
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class SaslSettings
|
||||
{
|
||||
public SaslProfile Profile
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class AmqpSettings
|
||||
{
|
||||
public int MaxFrameSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string ContainerId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string HostName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ushort MaxSessionsPerConnection
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int IdleTimeout
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
|
||||
public class ConnectionFactory
|
||||
{
|
||||
internal TcpSettings tcpSettings;
|
||||
internal SslSettings sslSettings;
|
||||
internal SaslSettings saslSettings;
|
||||
internal AmqpSettings amqpSettings;
|
||||
|
||||
public ConnectionFactory()
|
||||
{
|
||||
this.amqpSettings = new AmqpSettings()
|
||||
{
|
||||
MaxFrameSize = (int)Connection.DefaultMaxFrameSize,
|
||||
ContainerId = Process.GetCurrentProcess().ProcessName,
|
||||
IdleTimeout = int.MaxValue,
|
||||
MaxSessionsPerConnection = 8
|
||||
};
|
||||
}
|
||||
|
||||
public TcpSettings TCP
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.tcpSettings ?? (this.tcpSettings = new TcpSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public SslSettings SSL
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.sslSettings ?? (this.sslSettings = new SslSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public SaslSettings SASL
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.saslSettings ?? (this.saslSettings = new SaslSettings());
|
||||
}
|
||||
}
|
||||
|
||||
public AmqpSettings AMQP
|
||||
{
|
||||
get { return this.amqpSettings; }
|
||||
}
|
||||
|
||||
public Task<Connection> CreateAsync(Address address)
|
||||
{
|
||||
return this.CreateAsync(address, null, null);
|
||||
}
|
||||
|
||||
public Task<Connection> CreateAsync(Address address, OnOpened onOpened)
|
||||
{
|
||||
return this.CreateAsync(address, null, onOpened);
|
||||
}
|
||||
|
||||
public async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened)
|
||||
{
|
||||
IAsyncTransport transport;
|
||||
if (WebSocketTransport.MatchScheme(address.Scheme))
|
||||
{
|
||||
WebSocketTransport wsTransport = new WebSocketTransport();
|
||||
await wsTransport.ConnectAsync(address);
|
||||
transport = wsTransport;
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpTransport tcpTransport = new TcpTransport();
|
||||
await tcpTransport.ConnectAsync(address, this);
|
||||
transport = tcpTransport;
|
||||
}
|
||||
|
||||
if (address.User != null)
|
||||
{
|
||||
SaslPlainProfile profile = new SaslPlainProfile(address.User, address.Password);
|
||||
transport = await profile.OpenAsync(address.Host, transport);
|
||||
}
|
||||
else if (this.saslSettings != null && this.saslSettings.Profile != null)
|
||||
{
|
||||
transport = await this.saslSettings.Profile.OpenAsync(address.Host, transport);
|
||||
}
|
||||
|
||||
AsyncPump pump = new AsyncPump(transport);
|
||||
Connection connection = new Connection(this, address, transport, open, onOpened);
|
||||
pump.Start(connection);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
public class TcpSettings
|
||||
{
|
||||
const int DefaultBufferSize = 8192;
|
||||
bool? noDelay;
|
||||
int? receiveBufferSize;
|
||||
int? receiveTimeout;
|
||||
int? sendBufferSize;
|
||||
int? sendTimeout;
|
||||
|
||||
public LingerOption LingerOption
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool NoDelay
|
||||
{
|
||||
get { return this.noDelay ?? false; }
|
||||
set { this.noDelay = value; }
|
||||
}
|
||||
|
||||
public int ReceiveBufferSize
|
||||
{
|
||||
get { return this.receiveBufferSize ?? DefaultBufferSize; }
|
||||
set { this.receiveBufferSize = value; }
|
||||
}
|
||||
|
||||
public int ReceiveTimeout
|
||||
{
|
||||
get { return this.receiveTimeout ?? 0; }
|
||||
set { this.receiveTimeout = value; }
|
||||
}
|
||||
|
||||
public int SendBufferSize
|
||||
{
|
||||
get { return this.sendBufferSize ?? DefaultBufferSize; }
|
||||
set { this.sendBufferSize = value; }
|
||||
}
|
||||
|
||||
public int SendTimeout
|
||||
{
|
||||
get { return this.sendTimeout ?? 0; }
|
||||
set { this.sendTimeout = value; }
|
||||
}
|
||||
|
||||
internal void Configure(Socket socket)
|
||||
{
|
||||
if (this.noDelay != null) socket.NoDelay = this.noDelay.Value;
|
||||
if (this.receiveBufferSize != null) socket.ReceiveBufferSize = this.receiveBufferSize.Value;
|
||||
if (this.receiveTimeout != null) socket.ReceiveTimeout = this.receiveTimeout.Value;
|
||||
if (this.sendBufferSize != null) socket.SendBufferSize = this.sendBufferSize.Value;
|
||||
if (this.sendTimeout != null) socket.SendTimeout = this.sendTimeout.Value;
|
||||
if (this.LingerOption != null) socket.LingerState = this.LingerOption;
|
||||
}
|
||||
}
|
||||
|
||||
public class SslSettings
|
||||
{
|
||||
public SslSettings()
|
||||
{
|
||||
this.Protocols = SslProtocols.Default;
|
||||
this.ClientCertificates = new X509CertificateCollection();
|
||||
}
|
||||
|
||||
public X509CertificateCollection ClientCertificates
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public SslProtocols Protocols
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool CheckCertificateRevocation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RemoteCertificateValidationCallback RemoteCertificateValidationCallback
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class SaslSettings
|
||||
{
|
||||
public SaslProfile Profile
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class AmqpSettings
|
||||
{
|
||||
public int MaxFrameSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string ContainerId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string HostName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ushort MaxSessionsPerConnection
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int IdleTimeout
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IAsyncTransport : ITransport
|
||||
{
|
||||
void SetConnection(Connection connection);
|
||||
|
||||
// true: pending, false: completed
|
||||
bool SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize);
|
||||
|
||||
Task<int> ReceiveAsync(byte[] buffer, int offset, int count);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IAsyncTransport : ITransport
|
||||
{
|
||||
void SetConnection(Connection connection);
|
||||
|
||||
// true: pending, false: completed
|
||||
bool SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize);
|
||||
|
||||
Task<int> ReceiveAsync(byte[] buffer, int offset, int count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,143 +1,143 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
using Amqp.Transactions;
|
||||
using Amqp.Types;
|
||||
|
||||
public static class TaskExtensions
|
||||
{
|
||||
public static T GetBody<T>(this Message message)
|
||||
{
|
||||
if (message.BodySection != null &&
|
||||
message.BodySection.Descriptor.Code == Codec.AmqpValue.Code)
|
||||
{
|
||||
return ((AmqpValue)message.BodySection).GetValue<T>();
|
||||
}
|
||||
|
||||
return (T)message.Body;
|
||||
}
|
||||
|
||||
public static Task CloseAsync(this AmqpObject amqpObject, int timeout = 60000)
|
||||
{
|
||||
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
|
||||
try
|
||||
{
|
||||
amqpObject.Closed += (o, e) =>
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
tcs.SetException(new AmqpException(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
};
|
||||
|
||||
amqpObject.Close(0);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static async Task SendAsync(this SenderLink sender, Message message)
|
||||
{
|
||||
var txnState = await ResourceManager.GetTransactionalStateAsync(sender);
|
||||
|
||||
await sender.SendAsync(message, txnState);
|
||||
}
|
||||
|
||||
public static Task<Message> ReceiveAsync(this ReceiverLink receiver, int timeout = 60000)
|
||||
{
|
||||
TaskCompletionSource<Message> tcs = new TaskCompletionSource<Message>();
|
||||
try
|
||||
{
|
||||
var message = receiver.Receive(
|
||||
(l, m) => tcs.SetResult(m),
|
||||
timeout);
|
||||
if (message != null)
|
||||
{
|
||||
tcs.SetResult(message);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
internal static async Task<IAsyncTransport> OpenAsync(this SaslProfile saslProfile, string hostname, IAsyncTransport transport)
|
||||
{
|
||||
ProtocolHeader header = saslProfile.Start(hostname, transport);
|
||||
|
||||
AsyncPump pump = new AsyncPump(transport);
|
||||
|
||||
await pump.PumpAsync(
|
||||
h => { saslProfile.OnHeader(header, h); return true; },
|
||||
b => { SaslCode code; return saslProfile.OnFrame(transport, b, out code); });
|
||||
|
||||
return (IAsyncTransport)saslProfile.UpgradeTransportInternal(transport);
|
||||
}
|
||||
|
||||
static Task SendAsync(this SenderLink sender, Message message, DeliveryState deliveryState)
|
||||
{
|
||||
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
|
||||
try
|
||||
{
|
||||
sender.Send(
|
||||
message,
|
||||
deliveryState,
|
||||
false,
|
||||
(m, o, s) =>
|
||||
{
|
||||
var t = (TaskCompletionSource<object>)s;
|
||||
if (o.Descriptor.Code == Codec.Accepted.Code)
|
||||
{
|
||||
t.SetResult(null);
|
||||
}
|
||||
else if (o.Descriptor.Code == Codec.Rejected.Code)
|
||||
{
|
||||
t.SetException(new AmqpException(((Rejected)o).Error));
|
||||
}
|
||||
else
|
||||
{
|
||||
t.SetException(new AmqpException(ErrorCode.InternalError, o.Descriptor.Name));
|
||||
}
|
||||
},
|
||||
tcs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
using Amqp.Transactions;
|
||||
using Amqp.Types;
|
||||
|
||||
public static class TaskExtensions
|
||||
{
|
||||
public static T GetBody<T>(this Message message)
|
||||
{
|
||||
if (message.BodySection != null &&
|
||||
message.BodySection.Descriptor.Code == Codec.AmqpValue.Code)
|
||||
{
|
||||
return ((AmqpValue)message.BodySection).GetValue<T>();
|
||||
}
|
||||
|
||||
return (T)message.Body;
|
||||
}
|
||||
|
||||
public static Task CloseAsync(this AmqpObject amqpObject, int timeout = 60000)
|
||||
{
|
||||
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
|
||||
try
|
||||
{
|
||||
amqpObject.Closed += (o, e) =>
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
tcs.SetException(new AmqpException(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
};
|
||||
|
||||
amqpObject.Close(0);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static async Task SendAsync(this SenderLink sender, Message message)
|
||||
{
|
||||
var txnState = await ResourceManager.GetTransactionalStateAsync(sender);
|
||||
|
||||
await sender.SendAsync(message, txnState);
|
||||
}
|
||||
|
||||
public static Task<Message> ReceiveAsync(this ReceiverLink receiver, int timeout = 60000)
|
||||
{
|
||||
TaskCompletionSource<Message> tcs = new TaskCompletionSource<Message>();
|
||||
try
|
||||
{
|
||||
var message = receiver.Receive(
|
||||
(l, m) => tcs.SetResult(m),
|
||||
timeout);
|
||||
if (message != null)
|
||||
{
|
||||
tcs.SetResult(message);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
internal static async Task<IAsyncTransport> OpenAsync(this SaslProfile saslProfile, string hostname, IAsyncTransport transport)
|
||||
{
|
||||
ProtocolHeader header = saslProfile.Start(hostname, transport);
|
||||
|
||||
AsyncPump pump = new AsyncPump(transport);
|
||||
|
||||
await pump.PumpAsync(
|
||||
h => { saslProfile.OnHeader(header, h); return true; },
|
||||
b => { SaslCode code; return saslProfile.OnFrame(transport, b, out code); });
|
||||
|
||||
return (IAsyncTransport)saslProfile.UpgradeTransportInternal(transport);
|
||||
}
|
||||
|
||||
static Task SendAsync(this SenderLink sender, Message message, DeliveryState deliveryState)
|
||||
{
|
||||
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
|
||||
try
|
||||
{
|
||||
sender.Send(
|
||||
message,
|
||||
deliveryState,
|
||||
false,
|
||||
(m, o, s) =>
|
||||
{
|
||||
var t = (TaskCompletionSource<object>)s;
|
||||
if (o.Descriptor.Code == Codec.Accepted.Code)
|
||||
{
|
||||
t.SetResult(null);
|
||||
}
|
||||
else if (o.Descriptor.Code == Codec.Rejected.Code)
|
||||
{
|
||||
t.SetException(new AmqpException(((Rejected)o).Error));
|
||||
}
|
||||
else
|
||||
{
|
||||
t.SetException(new AmqpException(ErrorCode.InternalError, o.Descriptor.Name));
|
||||
}
|
||||
},
|
||||
tcs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
tcs.SetException(exception);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,381 +1,381 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class TcpTransport : IAsyncTransport
|
||||
{
|
||||
static readonly RemoteCertificateValidationCallback noneCertValidator = (a, b, c, d) => true;
|
||||
Connection connection;
|
||||
Writer writer;
|
||||
IAsyncTransport socketTransport;
|
||||
|
||||
public TcpTransport()
|
||||
{
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(Socket socket)
|
||||
{
|
||||
this.socketTransport = new TcpSocket(this, socket);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(SslStream sslStream)
|
||||
{
|
||||
this.socketTransport = new SslSocket(this, sslStream);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
this.ConnectAsync(address, new ConnectionFactory()).Wait();
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(Address address, ConnectionFactory factory)
|
||||
{
|
||||
Socket socket;
|
||||
IPAddress[] ipAddresses;
|
||||
IPAddress ipAddress;
|
||||
if (IPAddress.TryParse(address.Host, out ipAddress))
|
||||
{
|
||||
socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
ipAddresses = new IPAddress[] { ipAddress };
|
||||
}
|
||||
else
|
||||
{
|
||||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
ipAddresses = Dns.GetHostEntry(address.Host).AddressList;
|
||||
}
|
||||
|
||||
if (factory.tcpSettings != null)
|
||||
{
|
||||
factory.tcpSettings.Configure(socket);
|
||||
}
|
||||
|
||||
await Task.Factory.FromAsync(
|
||||
(c, s) => ((Socket)s).BeginConnect(ipAddresses, address.Port, c, s),
|
||||
(r) => ((Socket)r.AsyncState).EndConnect(r),
|
||||
socket);
|
||||
|
||||
IAsyncTransport transport;
|
||||
if (address.UseSsl)
|
||||
{
|
||||
SslStream sslStream;
|
||||
var ssl = factory.sslSettings;
|
||||
if (ssl == null)
|
||||
{
|
||||
sslStream = new SslStream(new NetworkStream(socket));
|
||||
await sslStream.AuthenticateAsClientAsync(address.Host);
|
||||
}
|
||||
else
|
||||
{
|
||||
sslStream = new SslStream(new NetworkStream(socket), false, ssl.RemoteCertificateValidationCallback);
|
||||
await sslStream.AuthenticateAsClientAsync(address.Host, ssl.ClientCertificates,
|
||||
ssl.Protocols, ssl.CheckCertificateRevocation);
|
||||
}
|
||||
|
||||
transport = new SslSocket(this, sslStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
transport = new TcpSocket(this, socket);
|
||||
}
|
||||
|
||||
this.socketTransport = transport;
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.ReceiveAsync(buffer, offset, count);
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.socketTransport.Close();
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
this.writer.Write(buffer);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.Receive(buffer, offset, count);
|
||||
}
|
||||
|
||||
class TcpSocket : IAsyncTransport
|
||||
{
|
||||
readonly static EventHandler<SocketAsyncEventArgs> onWriteComplete = OnWriteComplete;
|
||||
readonly TcpTransport transport;
|
||||
readonly Socket socket;
|
||||
readonly SocketAsyncEventArgs args;
|
||||
|
||||
public TcpSocket(TcpTransport transport, Socket socket)
|
||||
{
|
||||
this.transport = transport;
|
||||
this.socket = socket;
|
||||
this.args = new SocketAsyncEventArgs();
|
||||
this.args.Completed += onWriteComplete;
|
||||
this.args.UserToken = this;
|
||||
}
|
||||
|
||||
static void OnWriteComplete(object sender, SocketAsyncEventArgs eventArgs)
|
||||
{
|
||||
var thisPtr = (TcpSocket)eventArgs.UserToken;
|
||||
if (eventArgs.SocketError != SocketError.Success)
|
||||
{
|
||||
thisPtr.transport.connection.OnIoException(new SocketException((int)eventArgs.SocketError));
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPtr.transport.writer.ContinueWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
this.args.BufferList = null;
|
||||
this.args.SetBuffer(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.args.SetBuffer(null, 0, 0);
|
||||
this.args.BufferList = bufferList;
|
||||
}
|
||||
|
||||
return this.socket.SendAsync(this.args);
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(c, s) => ((TcpSocket)s).socket.BeginReceive(buffer, offset, count, SocketFlags.None, c, s),
|
||||
(r) => ((TcpSocket)r.AsyncState).socket.EndReceive(r),
|
||||
this);
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socket.Receive(buffer, offset, count, SocketFlags.None);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.socket.Close();
|
||||
this.args.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class SslSocket : IAsyncTransport
|
||||
{
|
||||
readonly TcpTransport transport;
|
||||
readonly SslStream sslStream;
|
||||
|
||||
public SslSocket(TcpTransport transport, SslStream sslStream)
|
||||
{
|
||||
this.transport = transport;
|
||||
this.sslStream = sslStream;
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
ArraySegment<byte> writeBuffer;
|
||||
if (buffer != null)
|
||||
{
|
||||
writeBuffer = new ArraySegment<byte>(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] temp = new byte[listSize];
|
||||
int offset = 0;
|
||||
for (int i = 0; i < bufferList.Count; i++)
|
||||
{
|
||||
ArraySegment<byte> segment = bufferList[i];
|
||||
Buffer.BlockCopy(segment.Array, segment.Offset, temp, offset, segment.Count);
|
||||
offset += segment.Count;
|
||||
}
|
||||
|
||||
writeBuffer = new ArraySegment<byte>(temp, 0, listSize);
|
||||
}
|
||||
|
||||
Task task = this.sslStream.WriteAsync(writeBuffer.Array, writeBuffer.Offset, writeBuffer.Count);
|
||||
bool pending = !task.IsCompleted;
|
||||
if (pending)
|
||||
{
|
||||
task.ContinueWith(
|
||||
(t, s) =>
|
||||
{
|
||||
var thisPtr = (SslSocket)s;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
thisPtr.transport.connection.OnIoException(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPtr.transport.writer.ContinueWrite();
|
||||
}
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.sslStream.ReadAsync(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.sslStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.sslStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Writer
|
||||
{
|
||||
readonly TcpTransport owner;
|
||||
readonly IAsyncTransport transport;
|
||||
Queue<ByteBuffer> bufferQueue;
|
||||
bool writing;
|
||||
|
||||
public Writer(TcpTransport owner, IAsyncTransport transport)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.transport = transport;
|
||||
this.bufferQueue = new Queue<ByteBuffer>();
|
||||
}
|
||||
|
||||
public void Write(ByteBuffer buffer)
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.writing)
|
||||
{
|
||||
this.bufferQueue.Enqueue(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writing = true;
|
||||
}
|
||||
|
||||
if (!this.transport.SendAsync(buffer, null, 0))
|
||||
{
|
||||
this.ContinueWrite();
|
||||
}
|
||||
}
|
||||
|
||||
public void ContinueWrite()
|
||||
{
|
||||
ByteBuffer buffer = null;
|
||||
IList<ArraySegment<byte>> buffers = null;
|
||||
int listSize = 0;
|
||||
do
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
int queueDepth = this.bufferQueue.Count;
|
||||
if (queueDepth == 0)
|
||||
{
|
||||
this.writing = false;
|
||||
return;
|
||||
}
|
||||
else if (queueDepth == 1)
|
||||
{
|
||||
buffer = this.bufferQueue.Dequeue();
|
||||
buffers = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = null;
|
||||
listSize = 0;
|
||||
buffers = new ArraySegment<byte>[queueDepth];
|
||||
for (int i = 0; i < queueDepth; i++)
|
||||
{
|
||||
ByteBuffer item = this.bufferQueue.Dequeue();
|
||||
buffers[i] = new ArraySegment<byte>(item.Buffer, item.Offset, item.Length);
|
||||
listSize += item.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (this.transport.SendAsync(buffer, buffers, listSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.owner.connection.OnIoException(exception);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class TcpTransport : IAsyncTransport
|
||||
{
|
||||
static readonly RemoteCertificateValidationCallback noneCertValidator = (a, b, c, d) => true;
|
||||
Connection connection;
|
||||
Writer writer;
|
||||
IAsyncTransport socketTransport;
|
||||
|
||||
public TcpTransport()
|
||||
{
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(Socket socket)
|
||||
{
|
||||
this.socketTransport = new TcpSocket(this, socket);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(SslStream sslStream)
|
||||
{
|
||||
this.socketTransport = new SslSocket(this, sslStream);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
this.ConnectAsync(address, new ConnectionFactory()).Wait();
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(Address address, ConnectionFactory factory)
|
||||
{
|
||||
Socket socket;
|
||||
IPAddress[] ipAddresses;
|
||||
IPAddress ipAddress;
|
||||
if (IPAddress.TryParse(address.Host, out ipAddress))
|
||||
{
|
||||
socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
ipAddresses = new IPAddress[] { ipAddress };
|
||||
}
|
||||
else
|
||||
{
|
||||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
ipAddresses = Dns.GetHostEntry(address.Host).AddressList;
|
||||
}
|
||||
|
||||
if (factory.tcpSettings != null)
|
||||
{
|
||||
factory.tcpSettings.Configure(socket);
|
||||
}
|
||||
|
||||
await Task.Factory.FromAsync(
|
||||
(c, s) => ((Socket)s).BeginConnect(ipAddresses, address.Port, c, s),
|
||||
(r) => ((Socket)r.AsyncState).EndConnect(r),
|
||||
socket);
|
||||
|
||||
IAsyncTransport transport;
|
||||
if (address.UseSsl)
|
||||
{
|
||||
SslStream sslStream;
|
||||
var ssl = factory.sslSettings;
|
||||
if (ssl == null)
|
||||
{
|
||||
sslStream = new SslStream(new NetworkStream(socket));
|
||||
await sslStream.AuthenticateAsClientAsync(address.Host);
|
||||
}
|
||||
else
|
||||
{
|
||||
sslStream = new SslStream(new NetworkStream(socket), false, ssl.RemoteCertificateValidationCallback);
|
||||
await sslStream.AuthenticateAsClientAsync(address.Host, ssl.ClientCertificates,
|
||||
ssl.Protocols, ssl.CheckCertificateRevocation);
|
||||
}
|
||||
|
||||
transport = new SslSocket(this, sslStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
transport = new TcpSocket(this, socket);
|
||||
}
|
||||
|
||||
this.socketTransport = transport;
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.ReceiveAsync(buffer, offset, count);
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.socketTransport.Close();
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
this.writer.Write(buffer);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.Receive(buffer, offset, count);
|
||||
}
|
||||
|
||||
class TcpSocket : IAsyncTransport
|
||||
{
|
||||
readonly static EventHandler<SocketAsyncEventArgs> onWriteComplete = OnWriteComplete;
|
||||
readonly TcpTransport transport;
|
||||
readonly Socket socket;
|
||||
readonly SocketAsyncEventArgs args;
|
||||
|
||||
public TcpSocket(TcpTransport transport, Socket socket)
|
||||
{
|
||||
this.transport = transport;
|
||||
this.socket = socket;
|
||||
this.args = new SocketAsyncEventArgs();
|
||||
this.args.Completed += onWriteComplete;
|
||||
this.args.UserToken = this;
|
||||
}
|
||||
|
||||
static void OnWriteComplete(object sender, SocketAsyncEventArgs eventArgs)
|
||||
{
|
||||
var thisPtr = (TcpSocket)eventArgs.UserToken;
|
||||
if (eventArgs.SocketError != SocketError.Success)
|
||||
{
|
||||
thisPtr.transport.connection.OnIoException(new SocketException((int)eventArgs.SocketError));
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPtr.transport.writer.ContinueWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
this.args.BufferList = null;
|
||||
this.args.SetBuffer(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.args.SetBuffer(null, 0, 0);
|
||||
this.args.BufferList = bufferList;
|
||||
}
|
||||
|
||||
return this.socket.SendAsync(this.args);
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(c, s) => ((TcpSocket)s).socket.BeginReceive(buffer, offset, count, SocketFlags.None, c, s),
|
||||
(r) => ((TcpSocket)r.AsyncState).socket.EndReceive(r),
|
||||
this);
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socket.Receive(buffer, offset, count, SocketFlags.None);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.socket.Close();
|
||||
this.args.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class SslSocket : IAsyncTransport
|
||||
{
|
||||
readonly TcpTransport transport;
|
||||
readonly SslStream sslStream;
|
||||
|
||||
public SslSocket(TcpTransport transport, SslStream sslStream)
|
||||
{
|
||||
this.transport = transport;
|
||||
this.sslStream = sslStream;
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
ArraySegment<byte> writeBuffer;
|
||||
if (buffer != null)
|
||||
{
|
||||
writeBuffer = new ArraySegment<byte>(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] temp = new byte[listSize];
|
||||
int offset = 0;
|
||||
for (int i = 0; i < bufferList.Count; i++)
|
||||
{
|
||||
ArraySegment<byte> segment = bufferList[i];
|
||||
Buffer.BlockCopy(segment.Array, segment.Offset, temp, offset, segment.Count);
|
||||
offset += segment.Count;
|
||||
}
|
||||
|
||||
writeBuffer = new ArraySegment<byte>(temp, 0, listSize);
|
||||
}
|
||||
|
||||
Task task = this.sslStream.WriteAsync(writeBuffer.Array, writeBuffer.Offset, writeBuffer.Count);
|
||||
bool pending = !task.IsCompleted;
|
||||
if (pending)
|
||||
{
|
||||
task.ContinueWith(
|
||||
(t, s) =>
|
||||
{
|
||||
var thisPtr = (SslSocket)s;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
thisPtr.transport.connection.OnIoException(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPtr.transport.writer.ContinueWrite();
|
||||
}
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.sslStream.ReadAsync(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.sslStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.sslStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Writer
|
||||
{
|
||||
readonly TcpTransport owner;
|
||||
readonly IAsyncTransport transport;
|
||||
Queue<ByteBuffer> bufferQueue;
|
||||
bool writing;
|
||||
|
||||
public Writer(TcpTransport owner, IAsyncTransport transport)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.transport = transport;
|
||||
this.bufferQueue = new Queue<ByteBuffer>();
|
||||
}
|
||||
|
||||
public void Write(ByteBuffer buffer)
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.writing)
|
||||
{
|
||||
this.bufferQueue.Enqueue(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writing = true;
|
||||
}
|
||||
|
||||
if (!this.transport.SendAsync(buffer, null, 0))
|
||||
{
|
||||
this.ContinueWrite();
|
||||
}
|
||||
}
|
||||
|
||||
public void ContinueWrite()
|
||||
{
|
||||
ByteBuffer buffer = null;
|
||||
IList<ArraySegment<byte>> buffers = null;
|
||||
int listSize = 0;
|
||||
do
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
int queueDepth = this.bufferQueue.Count;
|
||||
if (queueDepth == 0)
|
||||
{
|
||||
this.writing = false;
|
||||
return;
|
||||
}
|
||||
else if (queueDepth == 1)
|
||||
{
|
||||
buffer = this.bufferQueue.Dequeue();
|
||||
buffers = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = null;
|
||||
listSize = 0;
|
||||
buffers = new ArraySegment<byte>[queueDepth];
|
||||
for (int i = 0; i < queueDepth; i++)
|
||||
{
|
||||
ByteBuffer item = this.bufferQueue.Dequeue();
|
||||
buffers[i] = new ArraySegment<byte>(item.Buffer, item.Offset, item.Length);
|
||||
listSize += item.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (this.transport.SendAsync(buffer, buffers, listSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.owner.connection.OnIoException(exception);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,184 +1,184 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class WebSocketTransport : IAsyncTransport
|
||||
{
|
||||
public const string WebSocketSubProtocol = "AMQPWSB10";
|
||||
public const string WebSockets = "WS";
|
||||
public const string SecureWebSockets = "WSS";
|
||||
const int WebSocketsPort = 80;
|
||||
const int SecureWebSocketsPort = 443;
|
||||
WebSocket webSocket;
|
||||
Queue<ByteBuffer> bufferQueue;
|
||||
bool writing;
|
||||
Connection connection;
|
||||
|
||||
public WebSocketTransport()
|
||||
{
|
||||
this.bufferQueue = new Queue<ByteBuffer>();
|
||||
}
|
||||
|
||||
public WebSocketTransport(WebSocket webSocket)
|
||||
: this()
|
||||
{
|
||||
this.webSocket = webSocket;
|
||||
}
|
||||
|
||||
public static bool MatchScheme(string scheme)
|
||||
{
|
||||
return string.Equals(scheme, WebSockets, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(scheme, SecureWebSockets, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(Address address)
|
||||
{
|
||||
Uri uri = new UriBuilder()
|
||||
{
|
||||
Scheme = address.Scheme,
|
||||
Port = GetDefaultPort(address.Scheme, address.Port),
|
||||
Host = address.Host,
|
||||
Path = address.Path
|
||||
}.Uri;
|
||||
|
||||
ClientWebSocket cws = new ClientWebSocket();
|
||||
cws.Options.AddSubProtocol(WebSocketSubProtocol);
|
||||
await cws.ConnectAsync(uri, CancellationToken.None);
|
||||
if (cws.SubProtocol != WebSocketSubProtocol)
|
||||
{
|
||||
cws.Abort();
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"WebSocket SubProtocol used by the host is not the same that was requested: {0}",
|
||||
cws.SubProtocol ?? "<null>"));
|
||||
}
|
||||
|
||||
this.webSocket = cws;
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
async Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (this.webSocket.State != WebSocketState.Open)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var result = await this.webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count), CancellationToken.None);
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result.Count;
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "close", CancellationToken.None).Wait();
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.writing)
|
||||
{
|
||||
this.bufferQueue.Enqueue(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writing = true;
|
||||
}
|
||||
|
||||
Task task = this.WriteAsync(buffer);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
static int GetDefaultPort(string scheme, int port)
|
||||
{
|
||||
if (port < 0)
|
||||
{
|
||||
string temp = scheme.ToUpperInvariant();
|
||||
if (temp == WebSockets)
|
||||
{
|
||||
port = WebSocketsPort;
|
||||
}
|
||||
else if (temp == SecureWebSockets)
|
||||
{
|
||||
port = SecureWebSocketsPort;
|
||||
}
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
async Task WriteAsync(ByteBuffer buffer)
|
||||
{
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.webSocket.SendAsync(new ArraySegment<byte>(buffer.Buffer, buffer.Offset, buffer.Length),
|
||||
WebSocketMessageType.Binary, true, CancellationToken.None);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.connection.OnIoException(exception);
|
||||
break;
|
||||
}
|
||||
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.bufferQueue.Count > 0)
|
||||
{
|
||||
buffer = this.bufferQueue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.writing = false;
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (buffer != null);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class WebSocketTransport : IAsyncTransport
|
||||
{
|
||||
public const string WebSocketSubProtocol = "AMQPWSB10";
|
||||
public const string WebSockets = "WS";
|
||||
public const string SecureWebSockets = "WSS";
|
||||
const int WebSocketsPort = 80;
|
||||
const int SecureWebSocketsPort = 443;
|
||||
WebSocket webSocket;
|
||||
Queue<ByteBuffer> bufferQueue;
|
||||
bool writing;
|
||||
Connection connection;
|
||||
|
||||
public WebSocketTransport()
|
||||
{
|
||||
this.bufferQueue = new Queue<ByteBuffer>();
|
||||
}
|
||||
|
||||
public WebSocketTransport(WebSocket webSocket)
|
||||
: this()
|
||||
{
|
||||
this.webSocket = webSocket;
|
||||
}
|
||||
|
||||
public static bool MatchScheme(string scheme)
|
||||
{
|
||||
return string.Equals(scheme, WebSockets, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(scheme, SecureWebSockets, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public async Task ConnectAsync(Address address)
|
||||
{
|
||||
Uri uri = new UriBuilder()
|
||||
{
|
||||
Scheme = address.Scheme,
|
||||
Port = GetDefaultPort(address.Scheme, address.Port),
|
||||
Host = address.Host,
|
||||
Path = address.Path
|
||||
}.Uri;
|
||||
|
||||
ClientWebSocket cws = new ClientWebSocket();
|
||||
cws.Options.AddSubProtocol(WebSocketSubProtocol);
|
||||
await cws.ConnectAsync(uri, CancellationToken.None);
|
||||
if (cws.SubProtocol != WebSocketSubProtocol)
|
||||
{
|
||||
cws.Abort();
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"WebSocket SubProtocol used by the host is not the same that was requested: {0}",
|
||||
cws.SubProtocol ?? "<null>"));
|
||||
}
|
||||
|
||||
this.webSocket = cws;
|
||||
}
|
||||
|
||||
void IAsyncTransport.SetConnection(Connection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
async Task<int> IAsyncTransport.ReceiveAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (this.webSocket.State != WebSocketState.Open)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var result = await this.webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, count), CancellationToken.None);
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result.Count;
|
||||
}
|
||||
|
||||
bool IAsyncTransport.SendAsync(ByteBuffer buffer, IList<ArraySegment<byte>> bufferList, int listSize)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
this.webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "close", CancellationToken.None).Wait();
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.writing)
|
||||
{
|
||||
this.bufferQueue.Enqueue(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
this.writing = true;
|
||||
}
|
||||
|
||||
Task task = this.WriteAsync(buffer);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
static int GetDefaultPort(string scheme, int port)
|
||||
{
|
||||
if (port < 0)
|
||||
{
|
||||
string temp = scheme.ToUpperInvariant();
|
||||
if (temp == WebSockets)
|
||||
{
|
||||
port = WebSocketsPort;
|
||||
}
|
||||
else if (temp == SecureWebSockets)
|
||||
{
|
||||
port = SecureWebSocketsPort;
|
||||
}
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
async Task WriteAsync(ByteBuffer buffer)
|
||||
{
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.webSocket.SendAsync(new ArraySegment<byte>(buffer.Buffer, buffer.Offset, buffer.Length),
|
||||
WebSocketMessageType.Binary, true, CancellationToken.None);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.connection.OnIoException(exception);
|
||||
break;
|
||||
}
|
||||
|
||||
lock (this.bufferQueue)
|
||||
{
|
||||
if (this.bufferQueue.Count > 0)
|
||||
{
|
||||
buffer = this.bufferQueue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.writing = false;
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (buffer != null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,145 +1,145 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
|
||||
sealed class TcpTransport : ITransport
|
||||
{
|
||||
static RemoteCertificateValidationCallback NoVerifyCallback = (a, b, c, d) => true;
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
var ipHostEntry = Dns.GetHostEntry(address.Host);
|
||||
Exception exception = null;
|
||||
TcpSocket socket = null;
|
||||
|
||||
foreach (var ipAddress in ipHostEntry.AddressList)
|
||||
{
|
||||
if (ipAddress == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
socket = new TcpSocket();
|
||||
socket.Connect(new IPEndPoint(ipAddress, address.Port));
|
||||
exception = null;
|
||||
break;
|
||||
}
|
||||
catch (SocketException socketException)
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
socket.Close();
|
||||
socket = null;
|
||||
}
|
||||
|
||||
exception = socketException;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (address.UseSsl)
|
||||
{
|
||||
SslSocket sslSocket = new SslSocket(socket, noVerification);
|
||||
sslSocket.AuthenticateAsClient(address.Host);
|
||||
this.socketTransport = sslSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.socketTransport = socket;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
this.socketTransport.Close();
|
||||
}
|
||||
|
||||
public void Send(ByteBuffer buffer)
|
||||
{
|
||||
this.socketTransport.Send(buffer);
|
||||
}
|
||||
|
||||
public int Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.Receive(buffer, offset, count);
|
||||
}
|
||||
|
||||
class TcpSocket : Socket, ITransport
|
||||
{
|
||||
public TcpSocket()
|
||||
: base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
|
||||
{
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
base.Send(buffer.Buffer, buffer.Offset, buffer.Length, SocketFlags.None);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return base.Receive(buffer, offset, count, SocketFlags.None);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
|
||||
class SslSocket : SslStream, ITransport
|
||||
{
|
||||
Socket socket;
|
||||
|
||||
public SslSocket(Socket socket, bool noVerification)
|
||||
: base(new NetworkStream(socket), false, noVerification ? NoVerifyCallback : null)
|
||||
{
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
base.Write(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
//if (this.socket.Available <= 0) System.Threading.Thread.Sleep(20);
|
||||
//Trace.WriteLine(TraceLevel.Information, "Data Available: {0}", this.DataAvailable);
|
||||
return base.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
|
||||
sealed class TcpTransport : ITransport
|
||||
{
|
||||
static RemoteCertificateValidationCallback NoVerifyCallback = (a, b, c, d) => true;
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
var ipHostEntry = Dns.GetHostEntry(address.Host);
|
||||
Exception exception = null;
|
||||
TcpSocket socket = null;
|
||||
|
||||
foreach (var ipAddress in ipHostEntry.AddressList)
|
||||
{
|
||||
if (ipAddress == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
socket = new TcpSocket();
|
||||
socket.Connect(new IPEndPoint(ipAddress, address.Port));
|
||||
exception = null;
|
||||
break;
|
||||
}
|
||||
catch (SocketException socketException)
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
socket.Close();
|
||||
socket = null;
|
||||
}
|
||||
|
||||
exception = socketException;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (address.UseSsl)
|
||||
{
|
||||
SslSocket sslSocket = new SslSocket(socket, noVerification);
|
||||
sslSocket.AuthenticateAsClient(address.Host);
|
||||
this.socketTransport = sslSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.socketTransport = socket;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
this.socketTransport.Close();
|
||||
}
|
||||
|
||||
public void Send(ByteBuffer buffer)
|
||||
{
|
||||
this.socketTransport.Send(buffer);
|
||||
}
|
||||
|
||||
public int Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.socketTransport.Receive(buffer, offset, count);
|
||||
}
|
||||
|
||||
class TcpSocket : Socket, ITransport
|
||||
{
|
||||
public TcpSocket()
|
||||
: base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
|
||||
{
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
base.Send(buffer.Buffer, buffer.Offset, buffer.Length, SocketFlags.None);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return base.Receive(buffer, offset, count, SocketFlags.None);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
|
||||
class SslSocket : SslStream, ITransport
|
||||
{
|
||||
Socket socket;
|
||||
|
||||
public SslSocket(Socket socket, bool noVerification)
|
||||
: base(new NetworkStream(socket), false, noVerification ? NoVerifyCallback : null)
|
||||
{
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
void ITransport.Send(ByteBuffer buffer)
|
||||
{
|
||||
base.Write(buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
|
||||
int ITransport.Receive(byte[] buffer, int offset, int count)
|
||||
{
|
||||
//if (this.socket.Available <= 0) System.Threading.Thread.Sleep(20);
|
||||
//Trace.WriteLine(TraceLevel.Information, "Data Available: {0}", this.DataAvailable);
|
||||
return base.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
void ITransport.Close()
|
||||
{
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,9 +24,9 @@ namespace Amqp
|
|||
|
||||
sealed class TcpTransport : ITransport
|
||||
{
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
var ipHostEntry = Dns.GetHostEntry(address.Host);
|
||||
Exception exception = null;
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace Amqp
|
|||
|
||||
sealed class TcpTransport : ITransport
|
||||
{
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
ITransport socketTransport;
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
var ipHostEntry = Dns.GetHostEntry(address.Host);
|
||||
Exception exception = null;
|
||||
|
|
|
@ -1,441 +1,441 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
using System.Threading;
|
||||
|
||||
public delegate void MessageCallback(ReceiverLink receiver, Message message);
|
||||
|
||||
public class ReceiverLink : Link
|
||||
{
|
||||
#if DOTNET
|
||||
const int DefaultCredit = 200;
|
||||
#else
|
||||
const int DefaultCredit = 20;
|
||||
#endif
|
||||
// flow control
|
||||
SequenceNumber deliveryCount;
|
||||
int totalCredit;
|
||||
int credit;
|
||||
int restored;
|
||||
|
||||
// received messages queue
|
||||
LinkedList receivedMessages;
|
||||
Delivery deliveryCurrent;
|
||||
|
||||
// pending receivers
|
||||
LinkedList waiterList;
|
||||
MessageCallback onMessage;
|
||||
|
||||
public ReceiverLink(Session session, string name, string adderss)
|
||||
: this(session, name, new Source() { Address = adderss }, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ReceiverLink(Session session, string name, Source source, OnAttached onAttached)
|
||||
: this(session, name, new Attach() { Source = source, Target = new Target() }, onAttached)
|
||||
{
|
||||
}
|
||||
|
||||
public ReceiverLink(Session session, string name, Attach attach, OnAttached onAttached)
|
||||
: base(session, name, onAttached)
|
||||
{
|
||||
this.totalCredit = -1;
|
||||
this.receivedMessages = new LinkedList();
|
||||
this.waiterList = new LinkedList();
|
||||
this.SendAttach(true, 0, attach);
|
||||
}
|
||||
|
||||
public void Start(int credit, MessageCallback onMessage = null)
|
||||
{
|
||||
this.onMessage = onMessage;
|
||||
this.SetCredit(credit, true);
|
||||
}
|
||||
|
||||
public void SetCredit(int credit, bool autoRestore = true)
|
||||
{
|
||||
uint dc;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.IsDetaching)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.totalCredit = autoRestore ? credit : 0;
|
||||
this.credit = credit;
|
||||
this.restored = 0;
|
||||
dc = this.deliveryCount;
|
||||
}
|
||||
|
||||
this.SendFlow(dc, (uint)credit);
|
||||
}
|
||||
|
||||
public Message Receive(int timeout = 60000)
|
||||
{
|
||||
return this.ReceiveInternal(null, timeout);
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
public Message Receive(MessageCallback callback, int timeout = 60000)
|
||||
{
|
||||
return this.ReceiveInternal(callback, timeout);
|
||||
}
|
||||
|
||||
internal void SetInitialDeliveryCount(uint deliveryCount)
|
||||
{
|
||||
this.deliveryCount = deliveryCount;
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Accept(Message message)
|
||||
{
|
||||
this.ThrowIfDetaching("Accept");
|
||||
this.DisposeMessage(message, new Accepted());
|
||||
}
|
||||
|
||||
public void Release(Message message)
|
||||
{
|
||||
this.ThrowIfDetaching("Release");
|
||||
this.DisposeMessage(message, new Released());
|
||||
}
|
||||
|
||||
public void Reject(Message message, Error error = null)
|
||||
{
|
||||
this.ThrowIfDetaching("Reject");
|
||||
this.DisposeMessage(message, new Rejected() { Error = error });
|
||||
}
|
||||
|
||||
internal override void OnFlow(Flow flow)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
|
||||
{
|
||||
if (!transfer.More)
|
||||
{
|
||||
Waiter waiter;
|
||||
MessageCallback callback;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (delivery == null)
|
||||
{
|
||||
// multi-transfer delivery
|
||||
delivery = this.deliveryCurrent;
|
||||
this.deliveryCurrent = null;
|
||||
Fx.Assert(delivery != null, "Must have a delivery in the queue");
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
delivery.Message = Message.Decode(delivery.Buffer);
|
||||
delivery.Buffer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// single tranfer delivery
|
||||
this.OnDelivery(transfer.DeliveryId);
|
||||
delivery.Message = Message.Decode(buffer);
|
||||
}
|
||||
|
||||
callback = this.onMessage;
|
||||
waiter = (Waiter)this.waiterList.First;
|
||||
if (waiter != null)
|
||||
{
|
||||
this.waiterList.Remove(waiter);
|
||||
}
|
||||
|
||||
if (waiter == null && callback == null)
|
||||
{
|
||||
this.receivedMessages.Add(new MessageNode() { Message = delivery.Message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (waiter != null)
|
||||
{
|
||||
if (waiter.Signal(delivery.Message))
|
||||
{
|
||||
this.OnDeliverMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
waiter = (Waiter)this.waiterList.First;
|
||||
if (waiter != null)
|
||||
{
|
||||
this.waiterList.Remove(waiter);
|
||||
}
|
||||
else if (callback == null)
|
||||
{
|
||||
this.receivedMessages.Add(new MessageNode() { Message = delivery.Message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fx.Assert(waiter == null, "waiter must be null now");
|
||||
Fx.Assert(callback != null, "callback must not be null now");
|
||||
callback(this, delivery.Message);
|
||||
this.OnDeliverMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (delivery == null)
|
||||
{
|
||||
delivery = this.deliveryCurrent;
|
||||
Fx.Assert(delivery != null, "Must have a current delivery");
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.OnDelivery(transfer.DeliveryId);
|
||||
delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = delivery;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
base.OnAttach(remoteHandle, attach);
|
||||
this.deliveryCount = attach.InitialDeliveryCount;
|
||||
}
|
||||
|
||||
internal override void OnDeliveryStateChanged(Delivery delivery)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool OnClose(Error error)
|
||||
{
|
||||
this.OnAbort(error);
|
||||
|
||||
return base.OnClose(error);
|
||||
}
|
||||
|
||||
protected override void OnAbort(Error error)
|
||||
{
|
||||
Waiter waiter;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
waiter = (Waiter)this.waiterList.Clear();
|
||||
}
|
||||
|
||||
while (waiter != null)
|
||||
{
|
||||
waiter.Signal(null);
|
||||
waiter = (Waiter)waiter.Next;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDeliverMessage()
|
||||
{
|
||||
if (this.totalCredit > 0 &&
|
||||
Interlocked.Increment(ref this.restored) >= (this.totalCredit / 2))
|
||||
{
|
||||
this.SetCredit(this.totalCredit, true);
|
||||
}
|
||||
}
|
||||
|
||||
Message ReceiveInternal(MessageCallback callback, int timeout = 60000)
|
||||
{
|
||||
this.ThrowIfDetaching("Receive");
|
||||
if (this.totalCredit < 0)
|
||||
{
|
||||
this.SetCredit(DefaultCredit, true);
|
||||
}
|
||||
|
||||
Waiter waiter = null;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
MessageNode first = (MessageNode)this.receivedMessages.First;
|
||||
if (first != null)
|
||||
{
|
||||
this.receivedMessages.Remove(first);
|
||||
this.OnDeliverMessage();
|
||||
return first.Message;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
waiter = callback == null ? (Waiter)new SyncWaiter() : new AsyncWaiter(this, callback);
|
||||
#else
|
||||
waiter = new SyncWaiter();
|
||||
#endif
|
||||
this.waiterList.Add(waiter);
|
||||
}
|
||||
|
||||
return waiter.Wait(timeout);
|
||||
}
|
||||
|
||||
void DisposeMessage(Message message, Outcome outcome)
|
||||
{
|
||||
Delivery delivery = message.Delivery;
|
||||
if (delivery == null || delivery.Settled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeliveryState state = outcome;
|
||||
bool settled = true;
|
||||
#if DOTNET
|
||||
var txnState = Amqp.Transactions.ResourceManager.GetTransactionalStateAsync(this).Result;
|
||||
if (txnState != null)
|
||||
{
|
||||
txnState.Outcome = outcome;
|
||||
state = txnState;
|
||||
settled = false;
|
||||
}
|
||||
#endif
|
||||
this.Session.DisposeDelivery(true, delivery, state, settled);
|
||||
}
|
||||
|
||||
void OnDelivery(SequenceNumber deliveryId)
|
||||
{
|
||||
// called with lock held
|
||||
if (this.credit <= 0)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.TransferLimitExceeded,
|
||||
Fx.Format(SRAmqp.DeliveryLimitExceeded, deliveryId));
|
||||
}
|
||||
|
||||
this.deliveryCount++;
|
||||
this.credit--;
|
||||
}
|
||||
|
||||
sealed class MessageNode : INode
|
||||
{
|
||||
public Message Message { get; set; }
|
||||
|
||||
public INode Previous { get; set; }
|
||||
|
||||
public INode Next { get; set; }
|
||||
}
|
||||
|
||||
abstract class Waiter : INode
|
||||
{
|
||||
public INode Previous { get; set; }
|
||||
|
||||
public INode Next { get; set; }
|
||||
|
||||
public abstract Message Wait(int timeout);
|
||||
|
||||
public abstract bool Signal(Message message);
|
||||
}
|
||||
|
||||
sealed class SyncWaiter : Waiter
|
||||
{
|
||||
readonly ManualResetEvent signal;
|
||||
Message message;
|
||||
bool expired;
|
||||
|
||||
public SyncWaiter()
|
||||
{
|
||||
this.signal = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
public override Message Wait(int timeout)
|
||||
{
|
||||
this.signal.WaitOne(timeout, false);
|
||||
lock (this)
|
||||
{
|
||||
this.expired = this.message == null;
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Signal(Message message)
|
||||
{
|
||||
bool signaled = false;
|
||||
lock (this)
|
||||
{
|
||||
if (!this.expired)
|
||||
{
|
||||
this.message = message;
|
||||
signaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.signal.Set();
|
||||
return signaled;
|
||||
}
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
sealed class AsyncWaiter : Waiter
|
||||
{
|
||||
readonly static TimerCallback onTimer = OnTimer;
|
||||
readonly ReceiverLink link;
|
||||
readonly MessageCallback callback;
|
||||
Timer timer;
|
||||
int state; // 0: created, 1: waiting, 2: signaled
|
||||
|
||||
public AsyncWaiter(ReceiverLink link, MessageCallback callback)
|
||||
{
|
||||
this.link = link;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public override Message Wait(int timeout)
|
||||
{
|
||||
this.timer = new Timer(onTimer, this, timeout, -1);
|
||||
if (Interlocked.CompareExchange(ref this.state, 1, 0) != 0)
|
||||
{
|
||||
// already signaled
|
||||
this.timer.Dispose();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool Signal(Message message)
|
||||
{
|
||||
int old = Interlocked.Exchange(ref this.state, 2);
|
||||
if (old != 2)
|
||||
{
|
||||
if (old == 1)
|
||||
{
|
||||
this.timer.Dispose();
|
||||
}
|
||||
|
||||
this.callback(this.link, message);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void OnTimer(object state)
|
||||
{
|
||||
var thisPtr = (AsyncWaiter)state;
|
||||
thisPtr.Signal(null);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp
|
||||
{
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
using System.Threading;
|
||||
|
||||
public delegate void MessageCallback(ReceiverLink receiver, Message message);
|
||||
|
||||
public class ReceiverLink : Link
|
||||
{
|
||||
#if DOTNET
|
||||
const int DefaultCredit = 200;
|
||||
#else
|
||||
const int DefaultCredit = 20;
|
||||
#endif
|
||||
// flow control
|
||||
SequenceNumber deliveryCount;
|
||||
int totalCredit;
|
||||
int credit;
|
||||
int restored;
|
||||
|
||||
// received messages queue
|
||||
LinkedList receivedMessages;
|
||||
Delivery deliveryCurrent;
|
||||
|
||||
// pending receivers
|
||||
LinkedList waiterList;
|
||||
MessageCallback onMessage;
|
||||
|
||||
public ReceiverLink(Session session, string name, string adderss)
|
||||
: this(session, name, new Source() { Address = adderss }, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ReceiverLink(Session session, string name, Source source, OnAttached onAttached)
|
||||
: this(session, name, new Attach() { Source = source, Target = new Target() }, onAttached)
|
||||
{
|
||||
}
|
||||
|
||||
public ReceiverLink(Session session, string name, Attach attach, OnAttached onAttached)
|
||||
: base(session, name, onAttached)
|
||||
{
|
||||
this.totalCredit = -1;
|
||||
this.receivedMessages = new LinkedList();
|
||||
this.waiterList = new LinkedList();
|
||||
this.SendAttach(true, 0, attach);
|
||||
}
|
||||
|
||||
public void Start(int credit, MessageCallback onMessage = null)
|
||||
{
|
||||
this.onMessage = onMessage;
|
||||
this.SetCredit(credit, true);
|
||||
}
|
||||
|
||||
public void SetCredit(int credit, bool autoRestore = true)
|
||||
{
|
||||
uint dc;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (this.IsDetaching)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.totalCredit = autoRestore ? credit : 0;
|
||||
this.credit = credit;
|
||||
this.restored = 0;
|
||||
dc = this.deliveryCount;
|
||||
}
|
||||
|
||||
this.SendFlow(dc, (uint)credit);
|
||||
}
|
||||
|
||||
public Message Receive(int timeout = 60000)
|
||||
{
|
||||
return this.ReceiveInternal(null, timeout);
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
public Message Receive(MessageCallback callback, int timeout = 60000)
|
||||
{
|
||||
return this.ReceiveInternal(callback, timeout);
|
||||
}
|
||||
|
||||
internal void SetInitialDeliveryCount(uint deliveryCount)
|
||||
{
|
||||
this.deliveryCount = deliveryCount;
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Accept(Message message)
|
||||
{
|
||||
this.ThrowIfDetaching("Accept");
|
||||
this.DisposeMessage(message, new Accepted());
|
||||
}
|
||||
|
||||
public void Release(Message message)
|
||||
{
|
||||
this.ThrowIfDetaching("Release");
|
||||
this.DisposeMessage(message, new Released());
|
||||
}
|
||||
|
||||
public void Reject(Message message, Error error = null)
|
||||
{
|
||||
this.ThrowIfDetaching("Reject");
|
||||
this.DisposeMessage(message, new Rejected() { Error = error });
|
||||
}
|
||||
|
||||
internal override void OnFlow(Flow flow)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer)
|
||||
{
|
||||
if (!transfer.More)
|
||||
{
|
||||
Waiter waiter;
|
||||
MessageCallback callback;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (delivery == null)
|
||||
{
|
||||
// multi-transfer delivery
|
||||
delivery = this.deliveryCurrent;
|
||||
this.deliveryCurrent = null;
|
||||
Fx.Assert(delivery != null, "Must have a delivery in the queue");
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
delivery.Message = Message.Decode(delivery.Buffer);
|
||||
delivery.Buffer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// single tranfer delivery
|
||||
this.OnDelivery(transfer.DeliveryId);
|
||||
delivery.Message = Message.Decode(buffer);
|
||||
}
|
||||
|
||||
callback = this.onMessage;
|
||||
waiter = (Waiter)this.waiterList.First;
|
||||
if (waiter != null)
|
||||
{
|
||||
this.waiterList.Remove(waiter);
|
||||
}
|
||||
|
||||
if (waiter == null && callback == null)
|
||||
{
|
||||
this.receivedMessages.Add(new MessageNode() { Message = delivery.Message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (waiter != null)
|
||||
{
|
||||
if (waiter.Signal(delivery.Message))
|
||||
{
|
||||
this.OnDeliverMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
waiter = (Waiter)this.waiterList.First;
|
||||
if (waiter != null)
|
||||
{
|
||||
this.waiterList.Remove(waiter);
|
||||
}
|
||||
else if (callback == null)
|
||||
{
|
||||
this.receivedMessages.Add(new MessageNode() { Message = delivery.Message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fx.Assert(waiter == null, "waiter must be null now");
|
||||
Fx.Assert(callback != null, "callback must not be null now");
|
||||
callback(this, delivery.Message);
|
||||
this.OnDeliverMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
if (delivery == null)
|
||||
{
|
||||
delivery = this.deliveryCurrent;
|
||||
Fx.Assert(delivery != null, "Must have a current delivery");
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.OnDelivery(transfer.DeliveryId);
|
||||
delivery.Buffer = new ByteBuffer(buffer.Length * 2, true);
|
||||
AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length);
|
||||
this.deliveryCurrent = delivery;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnAttach(uint remoteHandle, Attach attach)
|
||||
{
|
||||
base.OnAttach(remoteHandle, attach);
|
||||
this.deliveryCount = attach.InitialDeliveryCount;
|
||||
}
|
||||
|
||||
internal override void OnDeliveryStateChanged(Delivery delivery)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool OnClose(Error error)
|
||||
{
|
||||
this.OnAbort(error);
|
||||
|
||||
return base.OnClose(error);
|
||||
}
|
||||
|
||||
protected override void OnAbort(Error error)
|
||||
{
|
||||
Waiter waiter;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
waiter = (Waiter)this.waiterList.Clear();
|
||||
}
|
||||
|
||||
while (waiter != null)
|
||||
{
|
||||
waiter.Signal(null);
|
||||
waiter = (Waiter)waiter.Next;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDeliverMessage()
|
||||
{
|
||||
if (this.totalCredit > 0 &&
|
||||
Interlocked.Increment(ref this.restored) >= (this.totalCredit / 2))
|
||||
{
|
||||
this.SetCredit(this.totalCredit, true);
|
||||
}
|
||||
}
|
||||
|
||||
Message ReceiveInternal(MessageCallback callback, int timeout = 60000)
|
||||
{
|
||||
this.ThrowIfDetaching("Receive");
|
||||
if (this.totalCredit < 0)
|
||||
{
|
||||
this.SetCredit(DefaultCredit, true);
|
||||
}
|
||||
|
||||
Waiter waiter = null;
|
||||
lock (this.ThisLock)
|
||||
{
|
||||
MessageNode first = (MessageNode)this.receivedMessages.First;
|
||||
if (first != null)
|
||||
{
|
||||
this.receivedMessages.Remove(first);
|
||||
this.OnDeliverMessage();
|
||||
return first.Message;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
waiter = callback == null ? (Waiter)new SyncWaiter() : new AsyncWaiter(this, callback);
|
||||
#else
|
||||
waiter = new SyncWaiter();
|
||||
#endif
|
||||
this.waiterList.Add(waiter);
|
||||
}
|
||||
|
||||
return waiter.Wait(timeout);
|
||||
}
|
||||
|
||||
void DisposeMessage(Message message, Outcome outcome)
|
||||
{
|
||||
Delivery delivery = message.Delivery;
|
||||
if (delivery == null || delivery.Settled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeliveryState state = outcome;
|
||||
bool settled = true;
|
||||
#if DOTNET
|
||||
var txnState = Amqp.Transactions.ResourceManager.GetTransactionalStateAsync(this).Result;
|
||||
if (txnState != null)
|
||||
{
|
||||
txnState.Outcome = outcome;
|
||||
state = txnState;
|
||||
settled = false;
|
||||
}
|
||||
#endif
|
||||
this.Session.DisposeDelivery(true, delivery, state, settled);
|
||||
}
|
||||
|
||||
void OnDelivery(SequenceNumber deliveryId)
|
||||
{
|
||||
// called with lock held
|
||||
if (this.credit <= 0)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.TransferLimitExceeded,
|
||||
Fx.Format(SRAmqp.DeliveryLimitExceeded, deliveryId));
|
||||
}
|
||||
|
||||
this.deliveryCount++;
|
||||
this.credit--;
|
||||
}
|
||||
|
||||
sealed class MessageNode : INode
|
||||
{
|
||||
public Message Message { get; set; }
|
||||
|
||||
public INode Previous { get; set; }
|
||||
|
||||
public INode Next { get; set; }
|
||||
}
|
||||
|
||||
abstract class Waiter : INode
|
||||
{
|
||||
public INode Previous { get; set; }
|
||||
|
||||
public INode Next { get; set; }
|
||||
|
||||
public abstract Message Wait(int timeout);
|
||||
|
||||
public abstract bool Signal(Message message);
|
||||
}
|
||||
|
||||
sealed class SyncWaiter : Waiter
|
||||
{
|
||||
readonly ManualResetEvent signal;
|
||||
Message message;
|
||||
bool expired;
|
||||
|
||||
public SyncWaiter()
|
||||
{
|
||||
this.signal = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
public override Message Wait(int timeout)
|
||||
{
|
||||
this.signal.WaitOne(timeout, false);
|
||||
lock (this)
|
||||
{
|
||||
this.expired = this.message == null;
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Signal(Message message)
|
||||
{
|
||||
bool signaled = false;
|
||||
lock (this)
|
||||
{
|
||||
if (!this.expired)
|
||||
{
|
||||
this.message = message;
|
||||
signaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.signal.Set();
|
||||
return signaled;
|
||||
}
|
||||
}
|
||||
|
||||
#if DOTNET
|
||||
sealed class AsyncWaiter : Waiter
|
||||
{
|
||||
readonly static TimerCallback onTimer = OnTimer;
|
||||
readonly ReceiverLink link;
|
||||
readonly MessageCallback callback;
|
||||
Timer timer;
|
||||
int state; // 0: created, 1: waiting, 2: signaled
|
||||
|
||||
public AsyncWaiter(ReceiverLink link, MessageCallback callback)
|
||||
{
|
||||
this.link = link;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public override Message Wait(int timeout)
|
||||
{
|
||||
this.timer = new Timer(onTimer, this, timeout, -1);
|
||||
if (Interlocked.CompareExchange(ref this.state, 1, 0) != 0)
|
||||
{
|
||||
// already signaled
|
||||
this.timer.Dispose();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool Signal(Message message)
|
||||
{
|
||||
int old = Interlocked.Exchange(ref this.state, 2);
|
||||
if (old != 2)
|
||||
{
|
||||
if (old == 1)
|
||||
{
|
||||
this.timer.Dispose();
|
||||
}
|
||||
|
||||
this.callback(this.link, message);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void OnTimer(object state)
|
||||
{
|
||||
var thisPtr = (AsyncWaiter)state;
|
||||
thisPtr.Signal(null);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,43 +1,43 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
sealed class SaslExternalProfile : SaslProfile
|
||||
{
|
||||
public SaslExternalProfile()
|
||||
{
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
return new SaslInit() { Mechanism = "EXTERNAL" };
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
sealed class SaslExternalProfile : SaslProfile
|
||||
{
|
||||
public SaslExternalProfile()
|
||||
{
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
return new SaslInit() { Mechanism = "EXTERNAL" };
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +1,26 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
abstract class SaslMechanism
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract SaslProfile CreateProfile();
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
abstract class SaslMechanism
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract SaslProfile CreateProfile();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
class SaslPlainMechanism : SaslMechanism
|
||||
{
|
||||
readonly string user;
|
||||
readonly string password;
|
||||
|
||||
public SaslPlainMechanism(string user, string password)
|
||||
{
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "PLAIN"; }
|
||||
}
|
||||
|
||||
public override SaslProfile CreateProfile()
|
||||
{
|
||||
return new SaslPlainProfile(this);
|
||||
}
|
||||
|
||||
class SaslPlainProfile : SaslProfile
|
||||
{
|
||||
readonly SaslPlainMechanism mechanism;
|
||||
|
||||
public SaslPlainProfile(SaslPlainMechanism mechanism)
|
||||
{
|
||||
this.mechanism = mechanism;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
if (command.Descriptor.Code == Codec.SaslInit.Code)
|
||||
{
|
||||
SaslInit init = (SaslInit)command;
|
||||
SaslCode code = this.ValidateCredentials(init);
|
||||
return new SaslOutcome() { Code = code };
|
||||
}
|
||||
|
||||
throw new AmqpException(ErrorCode.NotAllowed, command.ToString());
|
||||
}
|
||||
|
||||
SaslCode ValidateCredentials(SaslInit init)
|
||||
{
|
||||
byte[] response = init.InitialResponse;
|
||||
if (response.Length > 0)
|
||||
{
|
||||
string message = Encoding.UTF8.GetString(response, 0, response.Length);
|
||||
string[] items = message.Split('\0');
|
||||
if (items.Length == 3 &&
|
||||
string.Equals(this.mechanism.user, items[1], StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(this.mechanism.password, items[2], StringComparison.Ordinal))
|
||||
{
|
||||
return SaslCode.Ok;
|
||||
}
|
||||
}
|
||||
|
||||
return SaslCode.Auth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
class SaslPlainMechanism : SaslMechanism
|
||||
{
|
||||
readonly string user;
|
||||
readonly string password;
|
||||
|
||||
public SaslPlainMechanism(string user, string password)
|
||||
{
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "PLAIN"; }
|
||||
}
|
||||
|
||||
public override SaslProfile CreateProfile()
|
||||
{
|
||||
return new SaslPlainProfile(this);
|
||||
}
|
||||
|
||||
class SaslPlainProfile : SaslProfile
|
||||
{
|
||||
readonly SaslPlainMechanism mechanism;
|
||||
|
||||
public SaslPlainProfile(SaslPlainMechanism mechanism)
|
||||
{
|
||||
this.mechanism = mechanism;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
if (command.Descriptor.Code == Codec.SaslInit.Code)
|
||||
{
|
||||
SaslInit init = (SaslInit)command;
|
||||
SaslCode code = this.ValidateCredentials(init);
|
||||
return new SaslOutcome() { Code = code };
|
||||
}
|
||||
|
||||
throw new AmqpException(ErrorCode.NotAllowed, command.ToString());
|
||||
}
|
||||
|
||||
SaslCode ValidateCredentials(SaslInit init)
|
||||
{
|
||||
byte[] response = init.InitialResponse;
|
||||
if (response.Length > 0)
|
||||
{
|
||||
string message = Encoding.UTF8.GetString(response, 0, response.Length);
|
||||
string[] items = message.Split('\0');
|
||||
if (items.Length == 3 &&
|
||||
string.Equals(this.mechanism.user, items[1], StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(this.mechanism.password, items[2], StringComparison.Ordinal))
|
||||
{
|
||||
return SaslCode.Ok;
|
||||
}
|
||||
}
|
||||
|
||||
return SaslCode.Auth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using Amqp.Types;
|
||||
|
||||
sealed class SaslPlainProfile : SaslProfile
|
||||
{
|
||||
readonly string user;
|
||||
readonly string password;
|
||||
|
||||
public SaslPlainProfile(string user, string password)
|
||||
{
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
byte[] b1 = Encoding.UTF8.GetBytes(this.user);
|
||||
byte[] b2 = Encoding.UTF8.GetBytes(this.password);
|
||||
byte[] message = new byte[2 + b1.Length + b2.Length];
|
||||
Array.Copy(b1, 0, message, 1, b1.Length);
|
||||
Array.Copy(b2, 0, message, b1.Length + 2, b2.Length);
|
||||
|
||||
SaslInit init = new SaslInit()
|
||||
{
|
||||
Mechanism = "PLAIN",
|
||||
InitialResponse = message,
|
||||
HostName = hostname
|
||||
};
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using Amqp.Types;
|
||||
|
||||
sealed class SaslPlainProfile : SaslProfile
|
||||
{
|
||||
readonly string user;
|
||||
readonly string password;
|
||||
|
||||
public SaslPlainProfile(string user, string password)
|
||||
{
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
|
||||
protected override DescribedList GetStartCommand(string hostname)
|
||||
{
|
||||
byte[] b1 = Encoding.UTF8.GetBytes(this.user);
|
||||
byte[] b2 = Encoding.UTF8.GetBytes(this.password);
|
||||
byte[] message = new byte[2 + b1.Length + b2.Length];
|
||||
Array.Copy(b1, 0, message, 1, b1.Length);
|
||||
Array.Copy(b2, 0, message, b1.Length + 2, b2.Length);
|
||||
|
||||
SaslInit init = new SaslInit()
|
||||
{
|
||||
Mechanism = "PLAIN",
|
||||
InitialResponse = message,
|
||||
HostName = hostname
|
||||
};
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
protected override DescribedList OnCommand(DescribedList command)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,145 +1,145 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public abstract class SaslProfile
|
||||
{
|
||||
public static SaslProfile External
|
||||
{
|
||||
get { return new SaslExternalProfile(); }
|
||||
}
|
||||
|
||||
internal ITransport Open(string hostname, ITransport transport)
|
||||
{
|
||||
ProtocolHeader myHeader = this.Start(hostname, transport);
|
||||
|
||||
ProtocolHeader theirHeader = Reader.ReadHeader(transport);
|
||||
Trace.WriteLine(TraceLevel.Frame, "RECV AMQP {0}", theirHeader);
|
||||
this.OnHeader(myHeader, theirHeader);
|
||||
|
||||
SaslCode code = SaslCode.SysTemp;
|
||||
while (true)
|
||||
{
|
||||
ByteBuffer buffer = Reader.ReadFrameBuffer(transport, new byte[4], uint.MaxValue);
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new ObjectDisposedException(transport.GetType().Name);
|
||||
}
|
||||
|
||||
if (!this.OnFrame(transport, buffer, out code))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code != SaslCode.Ok)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.UnauthorizedAccess,
|
||||
Fx.Format(SRAmqp.SaslNegoFailed, code));
|
||||
}
|
||||
|
||||
return this.UpgradeTransport(transport);
|
||||
}
|
||||
|
||||
internal ProtocolHeader Start(string hostname, ITransport transport)
|
||||
{
|
||||
ProtocolHeader myHeader = new ProtocolHeader() { Id = 3, Major = 1, Minor = 0, Revision = 0 };
|
||||
|
||||
ByteBuffer headerBuffer = new ByteBuffer(
|
||||
new byte[] { (byte)'A', (byte)'M', (byte)'Q', (byte)'P', myHeader.Id, myHeader.Major, myHeader.Minor, myHeader.Revision },
|
||||
0,
|
||||
8,
|
||||
8);
|
||||
transport.Send(headerBuffer);
|
||||
Trace.WriteLine(TraceLevel.Frame, "SEND AMQP {0}", myHeader);
|
||||
|
||||
DescribedList command = this.GetStartCommand(hostname);
|
||||
if (command != null)
|
||||
{
|
||||
this.SendCommand(transport, command);
|
||||
}
|
||||
|
||||
return myHeader;
|
||||
}
|
||||
|
||||
internal void OnHeader(ProtocolHeader myHeader, ProtocolHeader theirHeader)
|
||||
{
|
||||
if (theirHeader.Id != myHeader.Id || theirHeader.Major != myHeader.Major ||
|
||||
theirHeader.Minor != myHeader.Minor || theirHeader.Revision != myHeader.Revision)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotImplemented, theirHeader.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
internal bool OnFrame(ITransport transport, ByteBuffer buffer, out SaslCode code)
|
||||
{
|
||||
ushort channel;
|
||||
DescribedList command;
|
||||
Frame.GetFrame(buffer, out channel, out command);
|
||||
Trace.WriteLine(TraceLevel.Frame, "RECV {0}", command);
|
||||
|
||||
bool shouldContinue = true;
|
||||
if (command.Descriptor.Code == Codec.SaslOutcome.Code)
|
||||
{
|
||||
code = ((SaslOutcome)command).Code;
|
||||
shouldContinue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = SaslCode.Ok;
|
||||
DescribedList response = this.OnCommand(command);
|
||||
if (response != null)
|
||||
{
|
||||
this.SendCommand(transport, response);
|
||||
shouldContinue = response.Descriptor.Code != Codec.SaslOutcome.Code;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldContinue;
|
||||
}
|
||||
|
||||
internal DescribedList OnCommandInternal(DescribedList command)
|
||||
{
|
||||
return this.OnCommand(command);
|
||||
}
|
||||
|
||||
internal ITransport UpgradeTransportInternal(ITransport transport)
|
||||
{
|
||||
return this.UpgradeTransport(transport);
|
||||
}
|
||||
|
||||
// if a profile handles signing and/or encryption, it should create
|
||||
// a new transport
|
||||
protected abstract ITransport UpgradeTransport(ITransport transport);
|
||||
|
||||
protected abstract DescribedList GetStartCommand(string hostname);
|
||||
|
||||
protected abstract DescribedList OnCommand(DescribedList command);
|
||||
|
||||
void SendCommand(ITransport transport, DescribedList command)
|
||||
{
|
||||
ByteBuffer buffer = Frame.Encode(FrameType.Sasl, 0, command);
|
||||
transport.Send(buffer);
|
||||
Trace.WriteLine(TraceLevel.Frame, "SEND {0}", command);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
{
|
||||
using System;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
|
||||
public abstract class SaslProfile
|
||||
{
|
||||
public static SaslProfile External
|
||||
{
|
||||
get { return new SaslExternalProfile(); }
|
||||
}
|
||||
|
||||
internal ITransport Open(string hostname, ITransport transport)
|
||||
{
|
||||
ProtocolHeader myHeader = this.Start(hostname, transport);
|
||||
|
||||
ProtocolHeader theirHeader = Reader.ReadHeader(transport);
|
||||
Trace.WriteLine(TraceLevel.Frame, "RECV AMQP {0}", theirHeader);
|
||||
this.OnHeader(myHeader, theirHeader);
|
||||
|
||||
SaslCode code = SaslCode.SysTemp;
|
||||
while (true)
|
||||
{
|
||||
ByteBuffer buffer = Reader.ReadFrameBuffer(transport, new byte[4], uint.MaxValue);
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new ObjectDisposedException(transport.GetType().Name);
|
||||
}
|
||||
|
||||
if (!this.OnFrame(transport, buffer, out code))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code != SaslCode.Ok)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.UnauthorizedAccess,
|
||||
Fx.Format(SRAmqp.SaslNegoFailed, code));
|
||||
}
|
||||
|
||||
return this.UpgradeTransport(transport);
|
||||
}
|
||||
|
||||
internal ProtocolHeader Start(string hostname, ITransport transport)
|
||||
{
|
||||
ProtocolHeader myHeader = new ProtocolHeader() { Id = 3, Major = 1, Minor = 0, Revision = 0 };
|
||||
|
||||
ByteBuffer headerBuffer = new ByteBuffer(
|
||||
new byte[] { (byte)'A', (byte)'M', (byte)'Q', (byte)'P', myHeader.Id, myHeader.Major, myHeader.Minor, myHeader.Revision },
|
||||
0,
|
||||
8,
|
||||
8);
|
||||
transport.Send(headerBuffer);
|
||||
Trace.WriteLine(TraceLevel.Frame, "SEND AMQP {0}", myHeader);
|
||||
|
||||
DescribedList command = this.GetStartCommand(hostname);
|
||||
if (command != null)
|
||||
{
|
||||
this.SendCommand(transport, command);
|
||||
}
|
||||
|
||||
return myHeader;
|
||||
}
|
||||
|
||||
internal void OnHeader(ProtocolHeader myHeader, ProtocolHeader theirHeader)
|
||||
{
|
||||
if (theirHeader.Id != myHeader.Id || theirHeader.Major != myHeader.Major ||
|
||||
theirHeader.Minor != myHeader.Minor || theirHeader.Revision != myHeader.Revision)
|
||||
{
|
||||
throw new AmqpException(ErrorCode.NotImplemented, theirHeader.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
internal bool OnFrame(ITransport transport, ByteBuffer buffer, out SaslCode code)
|
||||
{
|
||||
ushort channel;
|
||||
DescribedList command;
|
||||
Frame.GetFrame(buffer, out channel, out command);
|
||||
Trace.WriteLine(TraceLevel.Frame, "RECV {0}", command);
|
||||
|
||||
bool shouldContinue = true;
|
||||
if (command.Descriptor.Code == Codec.SaslOutcome.Code)
|
||||
{
|
||||
code = ((SaslOutcome)command).Code;
|
||||
shouldContinue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = SaslCode.Ok;
|
||||
DescribedList response = this.OnCommand(command);
|
||||
if (response != null)
|
||||
{
|
||||
this.SendCommand(transport, response);
|
||||
shouldContinue = response.Descriptor.Code != Codec.SaslOutcome.Code;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldContinue;
|
||||
}
|
||||
|
||||
internal DescribedList OnCommandInternal(DescribedList command)
|
||||
{
|
||||
return this.OnCommand(command);
|
||||
}
|
||||
|
||||
internal ITransport UpgradeTransportInternal(ITransport transport)
|
||||
{
|
||||
return this.UpgradeTransport(transport);
|
||||
}
|
||||
|
||||
// if a profile handles signing and/or encryption, it should create
|
||||
// a new transport
|
||||
protected abstract ITransport UpgradeTransport(ITransport transport);
|
||||
|
||||
protected abstract DescribedList GetStartCommand(string hostname);
|
||||
|
||||
protected abstract DescribedList OnCommand(DescribedList command);
|
||||
|
||||
void SendCommand(ITransport transport, DescribedList command)
|
||||
{
|
||||
ByteBuffer buffer = Frame.Encode(FrameType.Sasl, 0, command);
|
||||
transport.Send(buffer);
|
||||
Trace.WriteLine(TraceLevel.Frame, "SEND {0}", command);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +1,55 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
|
||||
AllowMultiple = false, Inherited = true)]
|
||||
public sealed class AmqpContractAttribute : Attribute
|
||||
{
|
||||
public AmqpContractAttribute()
|
||||
{
|
||||
this.Encoding = EncodingType.List;
|
||||
this.Code = -1;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public long Code
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public EncodingType Encoding
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
internal ulong? InternalCode
|
||||
{
|
||||
get { return this.Code >= 0 ? (ulong?)this.Code : null; }
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
|
||||
AllowMultiple = false, Inherited = true)]
|
||||
public sealed class AmqpContractAttribute : Attribute
|
||||
{
|
||||
public AmqpContractAttribute()
|
||||
{
|
||||
this.Encoding = EncodingType.List;
|
||||
this.Code = -1;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public long Code
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public EncodingType Encoding
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
internal ulong? InternalCode
|
||||
{
|
||||
get { return this.Code >= 0 ? (ulong?)this.Code : null; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +1,46 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,
|
||||
AllowMultiple = false, Inherited = true)]
|
||||
public sealed class AmqpMemberAttribute : Attribute
|
||||
{
|
||||
int? order;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get { return this.order.HasValue ? this.order.Value : 0; }
|
||||
|
||||
set { this.order = value; }
|
||||
}
|
||||
|
||||
internal int? InternalOrder
|
||||
{
|
||||
get { return this.order; }
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,
|
||||
AllowMultiple = false, Inherited = true)]
|
||||
public sealed class AmqpMemberAttribute : Attribute
|
||||
{
|
||||
int? order;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get { return this.order.HasValue ? this.order.Value : 0; }
|
||||
|
||||
set { this.order = value; }
|
||||
}
|
||||
|
||||
internal int? InternalOrder
|
||||
{
|
||||
get { return this.order; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
|
||||
Inherited = true, AllowMultiple = true)]
|
||||
public sealed class AmqpProvidesAttribute : Attribute
|
||||
{
|
||||
readonly Type type;
|
||||
|
||||
public AmqpProvidesAttribute(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
|
||||
Inherited = true, AllowMultiple = true)]
|
||||
public sealed class AmqpProvidesAttribute : Attribute
|
||||
{
|
||||
readonly Type type;
|
||||
|
||||
public AmqpProvidesAttribute(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
public enum EncodingType
|
||||
{
|
||||
List,
|
||||
Map
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
public enum EncodingType
|
||||
{
|
||||
List,
|
||||
Map
|
||||
}
|
||||
}
|
|
@ -1,31 +1,31 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
public interface IAmqpSerializable
|
||||
{
|
||||
int EncodeSize
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
void Encode(ByteBuffer buffer);
|
||||
|
||||
void Decode(ByteBuffer buffer);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
public interface IAmqpSerializable
|
||||
{
|
||||
int EncodeSize
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
void Encode(ByteBuffer buffer);
|
||||
|
||||
void Decode(ByteBuffer buffer);
|
||||
}
|
||||
}
|
|
@ -1,187 +1,187 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
abstract class MemberAccessor
|
||||
{
|
||||
readonly Type type;
|
||||
Func<object, object> getter;
|
||||
Action<object, object> setter;
|
||||
|
||||
protected MemberAccessor(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
|
||||
public static MemberAccessor Create(MemberInfo memberInfo, bool requiresSetter)
|
||||
{
|
||||
if (memberInfo.MemberType == MemberTypes.Field)
|
||||
{
|
||||
return new FieldMemberAccessor((FieldInfo)memberInfo);
|
||||
}
|
||||
else if (memberInfo.MemberType == MemberTypes.Property)
|
||||
{
|
||||
return new PropertyMemberAccessor((PropertyInfo)memberInfo, requiresSetter);
|
||||
}
|
||||
|
||||
throw new NotSupportedException(memberInfo.MemberType.ToString());
|
||||
}
|
||||
|
||||
public object Get(object container)
|
||||
{
|
||||
return this.getter(container);
|
||||
}
|
||||
|
||||
public void Set(object container, object value)
|
||||
{
|
||||
this.setter(container, value);
|
||||
}
|
||||
|
||||
static void EmitTypeConversion(ILGenerator generator, Type castType, bool isContainer)
|
||||
{
|
||||
if (castType == typeof(object))
|
||||
{
|
||||
}
|
||||
else if (castType.IsValueType)
|
||||
{
|
||||
generator.Emit(isContainer ? OpCodes.Unbox : OpCodes.Unbox_Any, castType);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, castType);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitCall(ILGenerator generator, MethodInfo method)
|
||||
{
|
||||
OpCode opcode = (method.IsStatic || method.DeclaringType.IsValueType) ? OpCodes.Call : OpCodes.Callvirt;
|
||||
generator.EmitCall(opcode, method, null);
|
||||
}
|
||||
|
||||
static string GetAccessorName(bool isGetter, string name)
|
||||
{
|
||||
return (isGetter ? "get_" : "set_") + name;
|
||||
}
|
||||
|
||||
sealed class FieldMemberAccessor : MemberAccessor
|
||||
{
|
||||
public FieldMemberAccessor(FieldInfo fieldInfo)
|
||||
: base(fieldInfo.FieldType)
|
||||
{
|
||||
this.InitializeGetter(fieldInfo);
|
||||
this.InitializeSetter(fieldInfo);
|
||||
}
|
||||
|
||||
void InitializeGetter(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(true, fieldInfo.Name), typeof(object), new[] { typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, fieldInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
if (fieldInfo.FieldType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, fieldInfo.FieldType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.getter = (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
||||
}
|
||||
|
||||
void InitializeSetter(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(false, fieldInfo.Name), typeof(void), new[] { typeof(object), typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, fieldInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
EmitTypeConversion(generator, fieldInfo.FieldType, false);
|
||||
generator.Emit(OpCodes.Stfld, fieldInfo);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.setter = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PropertyMemberAccessor : MemberAccessor
|
||||
{
|
||||
public PropertyMemberAccessor(PropertyInfo propertyInfo, bool requiresSetter)
|
||||
: base(propertyInfo.PropertyType)
|
||||
{
|
||||
this.InitializeGetter(propertyInfo);
|
||||
this.InitializeSetter(propertyInfo, requiresSetter);
|
||||
}
|
||||
|
||||
void InitializeGetter(PropertyInfo propertyInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(true, propertyInfo.Name), typeof(object), new[] { typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.DeclareLocal(typeof(object));
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, propertyInfo.DeclaringType, true);
|
||||
EmitCall(generator, propertyInfo.GetGetMethod(true));
|
||||
if (propertyInfo.PropertyType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, propertyInfo.PropertyType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.getter = (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
||||
}
|
||||
|
||||
void InitializeSetter(PropertyInfo propertyInfo, bool requiresSetter)
|
||||
{
|
||||
MethodInfo setMethod = propertyInfo.GetSetMethod(true);
|
||||
if (setMethod == null)
|
||||
{
|
||||
if (requiresSetter)
|
||||
{
|
||||
throw new SerializationException("Property annotated with AmqpMemberAttribute must have a setter.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(false, propertyInfo.Name), typeof(void), new[] { typeof(object), typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, propertyInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
EmitTypeConversion(generator, propertyInfo.PropertyType, false);
|
||||
EmitCall(generator, setMethod);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.setter = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
abstract class MemberAccessor
|
||||
{
|
||||
readonly Type type;
|
||||
Func<object, object> getter;
|
||||
Action<object, object> setter;
|
||||
|
||||
protected MemberAccessor(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
|
||||
public static MemberAccessor Create(MemberInfo memberInfo, bool requiresSetter)
|
||||
{
|
||||
if (memberInfo.MemberType == MemberTypes.Field)
|
||||
{
|
||||
return new FieldMemberAccessor((FieldInfo)memberInfo);
|
||||
}
|
||||
else if (memberInfo.MemberType == MemberTypes.Property)
|
||||
{
|
||||
return new PropertyMemberAccessor((PropertyInfo)memberInfo, requiresSetter);
|
||||
}
|
||||
|
||||
throw new NotSupportedException(memberInfo.MemberType.ToString());
|
||||
}
|
||||
|
||||
public object Get(object container)
|
||||
{
|
||||
return this.getter(container);
|
||||
}
|
||||
|
||||
public void Set(object container, object value)
|
||||
{
|
||||
this.setter(container, value);
|
||||
}
|
||||
|
||||
static void EmitTypeConversion(ILGenerator generator, Type castType, bool isContainer)
|
||||
{
|
||||
if (castType == typeof(object))
|
||||
{
|
||||
}
|
||||
else if (castType.IsValueType)
|
||||
{
|
||||
generator.Emit(isContainer ? OpCodes.Unbox : OpCodes.Unbox_Any, castType);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, castType);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitCall(ILGenerator generator, MethodInfo method)
|
||||
{
|
||||
OpCode opcode = (method.IsStatic || method.DeclaringType.IsValueType) ? OpCodes.Call : OpCodes.Callvirt;
|
||||
generator.EmitCall(opcode, method, null);
|
||||
}
|
||||
|
||||
static string GetAccessorName(bool isGetter, string name)
|
||||
{
|
||||
return (isGetter ? "get_" : "set_") + name;
|
||||
}
|
||||
|
||||
sealed class FieldMemberAccessor : MemberAccessor
|
||||
{
|
||||
public FieldMemberAccessor(FieldInfo fieldInfo)
|
||||
: base(fieldInfo.FieldType)
|
||||
{
|
||||
this.InitializeGetter(fieldInfo);
|
||||
this.InitializeSetter(fieldInfo);
|
||||
}
|
||||
|
||||
void InitializeGetter(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(true, fieldInfo.Name), typeof(object), new[] { typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, fieldInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
if (fieldInfo.FieldType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, fieldInfo.FieldType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.getter = (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
||||
}
|
||||
|
||||
void InitializeSetter(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(false, fieldInfo.Name), typeof(void), new[] { typeof(object), typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, fieldInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
EmitTypeConversion(generator, fieldInfo.FieldType, false);
|
||||
generator.Emit(OpCodes.Stfld, fieldInfo);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.setter = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PropertyMemberAccessor : MemberAccessor
|
||||
{
|
||||
public PropertyMemberAccessor(PropertyInfo propertyInfo, bool requiresSetter)
|
||||
: base(propertyInfo.PropertyType)
|
||||
{
|
||||
this.InitializeGetter(propertyInfo);
|
||||
this.InitializeSetter(propertyInfo, requiresSetter);
|
||||
}
|
||||
|
||||
void InitializeGetter(PropertyInfo propertyInfo)
|
||||
{
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(true, propertyInfo.Name), typeof(object), new[] { typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.DeclareLocal(typeof(object));
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, propertyInfo.DeclaringType, true);
|
||||
EmitCall(generator, propertyInfo.GetGetMethod(true));
|
||||
if (propertyInfo.PropertyType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, propertyInfo.PropertyType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.getter = (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
||||
}
|
||||
|
||||
void InitializeSetter(PropertyInfo propertyInfo, bool requiresSetter)
|
||||
{
|
||||
MethodInfo setMethod = propertyInfo.GetSetMethod(true);
|
||||
if (setMethod == null)
|
||||
{
|
||||
if (requiresSetter)
|
||||
{
|
||||
throw new SerializationException("Property annotated with AmqpMemberAttribute must have a setter.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DynamicMethod method = new DynamicMethod(GetAccessorName(false, propertyInfo.Name), typeof(void), new[] { typeof(object), typeof(object) }, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
EmitTypeConversion(generator, propertyInfo.DeclaringType, true);
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
EmitTypeConversion(generator, propertyInfo.PropertyType, false);
|
||||
EmitCall(generator, setMethod);
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.setter = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,167 +1,167 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
abstract class MethodAccessor
|
||||
{
|
||||
delegate object MethodDelegate(object container, object[] parameters);
|
||||
|
||||
static readonly Type[] delegateParamsType = { typeof(object), typeof(object[]) };
|
||||
bool isStatic;
|
||||
MethodDelegate methodDelegate;
|
||||
|
||||
public static MethodAccessor Create(MethodInfo methodInfo)
|
||||
{
|
||||
return new TypeMethodAccessor(methodInfo);
|
||||
}
|
||||
|
||||
public static MethodAccessor Create(ConstructorInfo constructorInfo)
|
||||
{
|
||||
return new ConstructorAccessor(constructorInfo);
|
||||
}
|
||||
|
||||
public object Invoke(object[] parameters)
|
||||
{
|
||||
if (!this.isStatic)
|
||||
{
|
||||
throw new InvalidOperationException("Instance required to call an instance method.");
|
||||
}
|
||||
|
||||
return this.Invoke(null, parameters);
|
||||
}
|
||||
|
||||
public object Invoke(object container, object[] parameters)
|
||||
{
|
||||
if (this.isStatic && container != null)
|
||||
{
|
||||
throw new InvalidOperationException("Static method must be called with null instance.");
|
||||
}
|
||||
|
||||
return this.methodDelegate(container, parameters);
|
||||
}
|
||||
|
||||
Type[] GetParametersType(ParameterInfo[] paramsInfo)
|
||||
{
|
||||
Type[] paramsType = new Type[paramsInfo.Length];
|
||||
for (int i = 0; i < paramsInfo.Length; i++)
|
||||
{
|
||||
paramsType[i] = paramsInfo[i].ParameterType.IsByRef ? paramsInfo[i].ParameterType.GetElementType() : paramsInfo[i].ParameterType;
|
||||
}
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
void LoadArguments(ILGenerator generator, Type[] paramsType)
|
||||
{
|
||||
for (int i = 0; i < paramsType.Length; i++)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
switch (i)
|
||||
{
|
||||
case 0: generator.Emit(OpCodes.Ldc_I4_0); break;
|
||||
case 1: generator.Emit(OpCodes.Ldc_I4_1); break;
|
||||
case 2: generator.Emit(OpCodes.Ldc_I4_2); break;
|
||||
case 3: generator.Emit(OpCodes.Ldc_I4_3); break;
|
||||
case 4: generator.Emit(OpCodes.Ldc_I4_4); break;
|
||||
case 5: generator.Emit(OpCodes.Ldc_I4_5); break;
|
||||
case 6: generator.Emit(OpCodes.Ldc_I4_6); break;
|
||||
case 7: generator.Emit(OpCodes.Ldc_I4_7); break;
|
||||
case 8: generator.Emit(OpCodes.Ldc_I4_8); break;
|
||||
default: generator.Emit(OpCodes.Ldc_I4, i); break;
|
||||
}
|
||||
generator.Emit(OpCodes.Ldelem_Ref);
|
||||
if (paramsType[i].IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox_Any, paramsType[i]);
|
||||
}
|
||||
else if (paramsType[i] != typeof(object))
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, paramsType[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ConstructorAccessor : MethodAccessor
|
||||
{
|
||||
public ConstructorAccessor(ConstructorInfo constructorInfo)
|
||||
{
|
||||
this.isStatic = true;
|
||||
DynamicMethod method = new DynamicMethod("ctor_" + constructorInfo.DeclaringType.Name, typeof(object), delegateParamsType, true);
|
||||
Type[] paramsType = this.GetParametersType(constructorInfo.GetParameters());
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
this.LoadArguments(generator, paramsType);
|
||||
generator.Emit(OpCodes.Newobj, constructorInfo);
|
||||
if (constructorInfo.DeclaringType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, constructorInfo.DeclaringType);
|
||||
}
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.methodDelegate = (MethodDelegate)method.CreateDelegate(typeof(MethodDelegate));
|
||||
}
|
||||
}
|
||||
|
||||
sealed class TypeMethodAccessor : MethodAccessor
|
||||
{
|
||||
public TypeMethodAccessor(MethodInfo methodInfo)
|
||||
{
|
||||
Type[] paramsType = this.GetParametersType(methodInfo.GetParameters());
|
||||
DynamicMethod method = new DynamicMethod("method_" + methodInfo.Name, typeof(object), delegateParamsType, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
if (!this.isStatic)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
if (methodInfo.DeclaringType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox_Any, methodInfo.DeclaringType);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, methodInfo.DeclaringType);
|
||||
}
|
||||
}
|
||||
this.LoadArguments(generator, paramsType);
|
||||
if (methodInfo.IsFinal)
|
||||
{
|
||||
generator.Emit(OpCodes.Call, methodInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Callvirt, methodInfo);
|
||||
}
|
||||
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
{
|
||||
generator.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
else if (methodInfo.ReturnType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, methodInfo.ReturnType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.methodDelegate = (MethodDelegate)method.CreateDelegate(typeof(MethodDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
abstract class MethodAccessor
|
||||
{
|
||||
delegate object MethodDelegate(object container, object[] parameters);
|
||||
|
||||
static readonly Type[] delegateParamsType = { typeof(object), typeof(object[]) };
|
||||
bool isStatic;
|
||||
MethodDelegate methodDelegate;
|
||||
|
||||
public static MethodAccessor Create(MethodInfo methodInfo)
|
||||
{
|
||||
return new TypeMethodAccessor(methodInfo);
|
||||
}
|
||||
|
||||
public static MethodAccessor Create(ConstructorInfo constructorInfo)
|
||||
{
|
||||
return new ConstructorAccessor(constructorInfo);
|
||||
}
|
||||
|
||||
public object Invoke(object[] parameters)
|
||||
{
|
||||
if (!this.isStatic)
|
||||
{
|
||||
throw new InvalidOperationException("Instance required to call an instance method.");
|
||||
}
|
||||
|
||||
return this.Invoke(null, parameters);
|
||||
}
|
||||
|
||||
public object Invoke(object container, object[] parameters)
|
||||
{
|
||||
if (this.isStatic && container != null)
|
||||
{
|
||||
throw new InvalidOperationException("Static method must be called with null instance.");
|
||||
}
|
||||
|
||||
return this.methodDelegate(container, parameters);
|
||||
}
|
||||
|
||||
Type[] GetParametersType(ParameterInfo[] paramsInfo)
|
||||
{
|
||||
Type[] paramsType = new Type[paramsInfo.Length];
|
||||
for (int i = 0; i < paramsInfo.Length; i++)
|
||||
{
|
||||
paramsType[i] = paramsInfo[i].ParameterType.IsByRef ? paramsInfo[i].ParameterType.GetElementType() : paramsInfo[i].ParameterType;
|
||||
}
|
||||
|
||||
return paramsType;
|
||||
}
|
||||
|
||||
void LoadArguments(ILGenerator generator, Type[] paramsType)
|
||||
{
|
||||
for (int i = 0; i < paramsType.Length; i++)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
switch (i)
|
||||
{
|
||||
case 0: generator.Emit(OpCodes.Ldc_I4_0); break;
|
||||
case 1: generator.Emit(OpCodes.Ldc_I4_1); break;
|
||||
case 2: generator.Emit(OpCodes.Ldc_I4_2); break;
|
||||
case 3: generator.Emit(OpCodes.Ldc_I4_3); break;
|
||||
case 4: generator.Emit(OpCodes.Ldc_I4_4); break;
|
||||
case 5: generator.Emit(OpCodes.Ldc_I4_5); break;
|
||||
case 6: generator.Emit(OpCodes.Ldc_I4_6); break;
|
||||
case 7: generator.Emit(OpCodes.Ldc_I4_7); break;
|
||||
case 8: generator.Emit(OpCodes.Ldc_I4_8); break;
|
||||
default: generator.Emit(OpCodes.Ldc_I4, i); break;
|
||||
}
|
||||
generator.Emit(OpCodes.Ldelem_Ref);
|
||||
if (paramsType[i].IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox_Any, paramsType[i]);
|
||||
}
|
||||
else if (paramsType[i] != typeof(object))
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, paramsType[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ConstructorAccessor : MethodAccessor
|
||||
{
|
||||
public ConstructorAccessor(ConstructorInfo constructorInfo)
|
||||
{
|
||||
this.isStatic = true;
|
||||
DynamicMethod method = new DynamicMethod("ctor_" + constructorInfo.DeclaringType.Name, typeof(object), delegateParamsType, true);
|
||||
Type[] paramsType = this.GetParametersType(constructorInfo.GetParameters());
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
this.LoadArguments(generator, paramsType);
|
||||
generator.Emit(OpCodes.Newobj, constructorInfo);
|
||||
if (constructorInfo.DeclaringType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, constructorInfo.DeclaringType);
|
||||
}
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.methodDelegate = (MethodDelegate)method.CreateDelegate(typeof(MethodDelegate));
|
||||
}
|
||||
}
|
||||
|
||||
sealed class TypeMethodAccessor : MethodAccessor
|
||||
{
|
||||
public TypeMethodAccessor(MethodInfo methodInfo)
|
||||
{
|
||||
Type[] paramsType = this.GetParametersType(methodInfo.GetParameters());
|
||||
DynamicMethod method = new DynamicMethod("method_" + methodInfo.Name, typeof(object), delegateParamsType, true);
|
||||
ILGenerator generator = method.GetILGenerator();
|
||||
if (!this.isStatic)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
if (methodInfo.DeclaringType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox_Any, methodInfo.DeclaringType);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, methodInfo.DeclaringType);
|
||||
}
|
||||
}
|
||||
this.LoadArguments(generator, paramsType);
|
||||
if (methodInfo.IsFinal)
|
||||
{
|
||||
generator.Emit(OpCodes.Call, methodInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Callvirt, methodInfo);
|
||||
}
|
||||
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
{
|
||||
generator.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
else if (methodInfo.ReturnType.IsValueType)
|
||||
{
|
||||
generator.Emit(OpCodes.Box, methodInfo.ReturnType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
this.methodDelegate = (MethodDelegate)method.CreateDelegate(typeof(MethodDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
sealed class SerialiableMember
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public MemberAccessor Accessor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public SerializableType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Serialization
|
||||
{
|
||||
sealed class SerialiableMember
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public MemberAccessor Accessor
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public SerializableType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1056
src/Session.cs
1056
src/Session.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,70 +1,70 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
sealed class Controller : SenderLink
|
||||
{
|
||||
public Controller(Session session)
|
||||
: base(session, GetName(), new Attach() { Target = new Coordinator(), Source = new Source() }, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<byte[]> DeclareAsync()
|
||||
{
|
||||
Message message = new Message(new Declare());
|
||||
TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
|
||||
this.Send(message, null, false, OnOutcome, tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task DischargeAsync(byte[] txnId, bool fail)
|
||||
{
|
||||
Message message = new Message(new Discharge() { TxnId = txnId, Fail = fail });
|
||||
TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
|
||||
this.Send(message, null, false, OnOutcome, tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
static string GetName()
|
||||
{
|
||||
return "controller-link-" + Guid.NewGuid().ToString("N").Substring(0, 5);
|
||||
}
|
||||
|
||||
static void OnOutcome(Message message, Outcome outcome, object state)
|
||||
{
|
||||
var tcs = (TaskCompletionSource<byte[]>)state;
|
||||
if (outcome.Descriptor.Code == Codec.Declared.Code)
|
||||
{
|
||||
tcs.SetResult(((Declared)outcome).TxnId);
|
||||
}
|
||||
else if (outcome.Descriptor.Code == Codec.Rejected.Code)
|
||||
{
|
||||
tcs.SetException(new AmqpException(((Rejected)outcome).Error));
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetCanceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
sealed class Controller : SenderLink
|
||||
{
|
||||
public Controller(Session session)
|
||||
: base(session, GetName(), new Attach() { Target = new Coordinator(), Source = new Source() }, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<byte[]> DeclareAsync()
|
||||
{
|
||||
Message message = new Message(new Declare());
|
||||
TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
|
||||
this.Send(message, null, false, OnOutcome, tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task DischargeAsync(byte[] txnId, bool fail)
|
||||
{
|
||||
Message message = new Message(new Discharge() { TxnId = txnId, Fail = fail });
|
||||
TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
|
||||
this.Send(message, null, false, OnOutcome, tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
static string GetName()
|
||||
{
|
||||
return "controller-link-" + Guid.NewGuid().ToString("N").Substring(0, 5);
|
||||
}
|
||||
|
||||
static void OnOutcome(Message message, Outcome outcome, object state)
|
||||
{
|
||||
var tcs = (TaskCompletionSource<byte[]>)state;
|
||||
if (outcome.Descriptor.Code == Codec.Declared.Code)
|
||||
{
|
||||
tcs.SetResult(((Declared)outcome).TxnId);
|
||||
}
|
||||
else if (outcome.Descriptor.Code == Codec.Rejected.Code)
|
||||
{
|
||||
tcs.SetException(new AmqpException(((Rejected)outcome).Error));
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.SetCanceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,213 +1,213 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
sealed class ResourceManager
|
||||
{
|
||||
static readonly ResourceManager instance = new ResourceManager();
|
||||
readonly Dictionary<Connection, Controller> controllers;
|
||||
readonly Dictionary<string, Enlistment> enlistments;
|
||||
|
||||
ResourceManager()
|
||||
{
|
||||
this.controllers = new Dictionary<Connection, Controller>();
|
||||
this.enlistments = new Dictionary<string, Enlistment>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
object SyncRoot { get { return this.enlistments; } }
|
||||
|
||||
public static async Task<TransactionalState> GetTransactionalStateAsync(Link link)
|
||||
{
|
||||
Transaction txn = Transaction.Current;
|
||||
if (txn != null)
|
||||
{
|
||||
byte[] txnId = await instance.EnlistAsync(link, txn);
|
||||
return new TransactionalState() { TxnId = txnId };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async Task<byte[]> EnlistAsync(Link link, Transaction txn)
|
||||
{
|
||||
string id = txn.TransactionInformation.LocalIdentifier;
|
||||
Enlistment enlistment;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
if (!this.enlistments.TryGetValue(id, out enlistment))
|
||||
{
|
||||
enlistment = new Enlistment(this, txn);
|
||||
this.enlistments.Add(id, enlistment);
|
||||
txn.TransactionCompleted += this.OnTransactionCompleted;
|
||||
|
||||
if (!txn.EnlistPromotableSinglePhase(enlistment))
|
||||
{
|
||||
this.enlistments.Remove(id);
|
||||
txn.TransactionCompleted -= this.OnTransactionCompleted;
|
||||
throw new InvalidOperationException("DTC not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await enlistment.EnlistAsync(link);
|
||||
}
|
||||
|
||||
void OnTransactionCompleted(object sender, TransactionEventArgs e)
|
||||
{
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
this.enlistments.Remove(e.Transaction.TransactionInformation.LocalIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
Controller GetOrCreateController(Link link)
|
||||
{
|
||||
Controller controller;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
if (!this.controllers.TryGetValue(link.Session.Connection, out controller))
|
||||
{
|
||||
Session session = new Session(link.Session.Connection);
|
||||
controller = new Controller(session);
|
||||
controller.Closed += this.OnControllerClosed;
|
||||
this.controllers.Add(link.Session.Connection, controller);
|
||||
}
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
void OnControllerClosed(AmqpObject obj, Error error)
|
||||
{
|
||||
var controller = (Controller)obj;
|
||||
bool removed;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
removed = this.controllers.Remove(controller.Session.Connection);
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
controller.Session.Close(0);
|
||||
}
|
||||
}
|
||||
|
||||
class Enlistment : IPromotableSinglePhaseNotification
|
||||
{
|
||||
static readonly TimeSpan rollbackTimeout = TimeSpan.FromMinutes(1);
|
||||
readonly ResourceManager owner;
|
||||
readonly Transaction transaction;
|
||||
readonly string transactionId;
|
||||
readonly object syncRoot;
|
||||
Controller controller;
|
||||
Task<byte[]> declareTask;
|
||||
byte[] txnid;
|
||||
|
||||
public Enlistment(ResourceManager owner, Transaction transaction)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.transaction = transaction;
|
||||
this.transactionId = this.transaction.TransactionInformation.LocalIdentifier;
|
||||
this.syncRoot = new object();
|
||||
}
|
||||
|
||||
public async Task<byte[]> EnlistAsync(Link link)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
return this.txnid;
|
||||
}
|
||||
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.declareTask == null)
|
||||
{
|
||||
this.controller = this.owner.GetOrCreateController(link);
|
||||
this.declareTask = this.controller.DeclareAsync();
|
||||
}
|
||||
}
|
||||
|
||||
return this.txnid = await this.declareTask;
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.Rollback(SinglePhaseEnlistment singlePhaseEnlistment)
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
this.controller.DischargeAsync(this.txnid, true).ContinueWith(
|
||||
(t, o) =>
|
||||
{
|
||||
var spe = (SinglePhaseEnlistment)o;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
spe.Aborted(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
spe.Done();
|
||||
}
|
||||
},
|
||||
singlePhaseEnlistment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
this.controller.DischargeAsync(this.txnid, false).ContinueWith(
|
||||
(t, o) =>
|
||||
{
|
||||
var spe = (SinglePhaseEnlistment)o;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
spe.Aborted(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
spe.Done();
|
||||
}
|
||||
},
|
||||
singlePhaseEnlistment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] ITransactionPromoter.Promote()
|
||||
{
|
||||
throw new TransactionPromotionException("DTC not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
|
||||
sealed class ResourceManager
|
||||
{
|
||||
static readonly ResourceManager instance = new ResourceManager();
|
||||
readonly Dictionary<Connection, Controller> controllers;
|
||||
readonly Dictionary<string, Enlistment> enlistments;
|
||||
|
||||
ResourceManager()
|
||||
{
|
||||
this.controllers = new Dictionary<Connection, Controller>();
|
||||
this.enlistments = new Dictionary<string, Enlistment>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
object SyncRoot { get { return this.enlistments; } }
|
||||
|
||||
public static async Task<TransactionalState> GetTransactionalStateAsync(Link link)
|
||||
{
|
||||
Transaction txn = Transaction.Current;
|
||||
if (txn != null)
|
||||
{
|
||||
byte[] txnId = await instance.EnlistAsync(link, txn);
|
||||
return new TransactionalState() { TxnId = txnId };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async Task<byte[]> EnlistAsync(Link link, Transaction txn)
|
||||
{
|
||||
string id = txn.TransactionInformation.LocalIdentifier;
|
||||
Enlistment enlistment;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
if (!this.enlistments.TryGetValue(id, out enlistment))
|
||||
{
|
||||
enlistment = new Enlistment(this, txn);
|
||||
this.enlistments.Add(id, enlistment);
|
||||
txn.TransactionCompleted += this.OnTransactionCompleted;
|
||||
|
||||
if (!txn.EnlistPromotableSinglePhase(enlistment))
|
||||
{
|
||||
this.enlistments.Remove(id);
|
||||
txn.TransactionCompleted -= this.OnTransactionCompleted;
|
||||
throw new InvalidOperationException("DTC not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await enlistment.EnlistAsync(link);
|
||||
}
|
||||
|
||||
void OnTransactionCompleted(object sender, TransactionEventArgs e)
|
||||
{
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
this.enlistments.Remove(e.Transaction.TransactionInformation.LocalIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
Controller GetOrCreateController(Link link)
|
||||
{
|
||||
Controller controller;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
if (!this.controllers.TryGetValue(link.Session.Connection, out controller))
|
||||
{
|
||||
Session session = new Session(link.Session.Connection);
|
||||
controller = new Controller(session);
|
||||
controller.Closed += this.OnControllerClosed;
|
||||
this.controllers.Add(link.Session.Connection, controller);
|
||||
}
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
void OnControllerClosed(AmqpObject obj, Error error)
|
||||
{
|
||||
var controller = (Controller)obj;
|
||||
bool removed;
|
||||
lock (this.SyncRoot)
|
||||
{
|
||||
removed = this.controllers.Remove(controller.Session.Connection);
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
controller.Session.Close(0);
|
||||
}
|
||||
}
|
||||
|
||||
class Enlistment : IPromotableSinglePhaseNotification
|
||||
{
|
||||
static readonly TimeSpan rollbackTimeout = TimeSpan.FromMinutes(1);
|
||||
readonly ResourceManager owner;
|
||||
readonly Transaction transaction;
|
||||
readonly string transactionId;
|
||||
readonly object syncRoot;
|
||||
Controller controller;
|
||||
Task<byte[]> declareTask;
|
||||
byte[] txnid;
|
||||
|
||||
public Enlistment(ResourceManager owner, Transaction transaction)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.transaction = transaction;
|
||||
this.transactionId = this.transaction.TransactionInformation.LocalIdentifier;
|
||||
this.syncRoot = new object();
|
||||
}
|
||||
|
||||
public async Task<byte[]> EnlistAsync(Link link)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
return this.txnid;
|
||||
}
|
||||
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.declareTask == null)
|
||||
{
|
||||
this.controller = this.owner.GetOrCreateController(link);
|
||||
this.declareTask = this.controller.DeclareAsync();
|
||||
}
|
||||
}
|
||||
|
||||
return this.txnid = await this.declareTask;
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.Rollback(SinglePhaseEnlistment singlePhaseEnlistment)
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
this.controller.DischargeAsync(this.txnid, true).ContinueWith(
|
||||
(t, o) =>
|
||||
{
|
||||
var spe = (SinglePhaseEnlistment)o;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
spe.Aborted(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
spe.Done();
|
||||
}
|
||||
},
|
||||
singlePhaseEnlistment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPromotableSinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.txnid != null)
|
||||
{
|
||||
this.controller.DischargeAsync(this.txnid, false).ContinueWith(
|
||||
(t, o) =>
|
||||
{
|
||||
var spe = (SinglePhaseEnlistment)o;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
spe.Aborted(t.Exception.InnerException);
|
||||
}
|
||||
else
|
||||
{
|
||||
spe.Done();
|
||||
}
|
||||
},
|
||||
singlePhaseEnlistment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] ITransactionPromoter.Promote()
|
||||
{
|
||||
throw new TransactionPromotionException("DTC not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
static class TxnCapabilities
|
||||
{
|
||||
public static readonly Symbol LocalTransactions = "amqp:local-transactions";
|
||||
public static readonly Symbol DistributedTxn = "amqp:distributed-transactions";
|
||||
public static readonly Symbol PrototableTransactions = "amqp:prototable-transactions";
|
||||
public static readonly Symbol MultiTxnsPerSsn = "amqp:multi-txns-per-ssn";
|
||||
public static readonly Symbol MultiSsnsPerTxn = "amqp:multi-ssns-per-txn";
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Transactions
|
||||
{
|
||||
using Amqp.Types;
|
||||
|
||||
static class TxnCapabilities
|
||||
{
|
||||
public static readonly Symbol LocalTransactions = "amqp:local-transactions";
|
||||
public static readonly Symbol DistributedTxn = "amqp:distributed-transactions";
|
||||
public static readonly Symbol PrototableTransactions = "amqp:prototable-transactions";
|
||||
public static readonly Symbol MultiTxnsPerSsn = "amqp:multi-txns-per-ssn";
|
||||
public static readonly Symbol MultiSsnsPerTxn = "amqp:multi-ssns-per-txn";
|
||||
}
|
||||
}
|
|
@ -21,24 +21,24 @@ namespace Amqp.Types
|
|||
{
|
||||
public void Encode(ByteBuffer buffer)
|
||||
{
|
||||
AmqpBitConverter.WriteUByte(buffer, FormatCode.Described);
|
||||
AmqpBitConverter.WriteUByte(buffer, FormatCode.Described);
|
||||
this.EncodeDescriptor(buffer);
|
||||
this.EncodeValue(buffer);
|
||||
}
|
||||
|
||||
public void Decode(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.ReadFormatCode(buffer);
|
||||
this.DecodeDescriptor(buffer);
|
||||
this.DecodeValue(buffer);
|
||||
}
|
||||
|
||||
internal abstract void EncodeDescriptor(ByteBuffer buffer);
|
||||
|
||||
internal abstract void EncodeValue(ByteBuffer buffer);
|
||||
|
||||
internal abstract void DecodeDescriptor(ByteBuffer buffer);
|
||||
|
||||
}
|
||||
|
||||
public void Decode(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.ReadFormatCode(buffer);
|
||||
this.DecodeDescriptor(buffer);
|
||||
this.DecodeValue(buffer);
|
||||
}
|
||||
|
||||
internal abstract void EncodeDescriptor(ByteBuffer buffer);
|
||||
|
||||
internal abstract void EncodeValue(ByteBuffer buffer);
|
||||
|
||||
internal abstract void DecodeDescriptor(ByteBuffer buffer);
|
||||
|
||||
internal abstract void DecodeValue(ByteBuffer buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class DescribedValue : Described
|
||||
{
|
||||
object descriptor;
|
||||
object value;
|
||||
|
||||
public DescribedValue(object descriptor, object value)
|
||||
{
|
||||
this.descriptor = descriptor;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public object Descriptor
|
||||
{
|
||||
get { return this.descriptor; }
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return this.value; }
|
||||
}
|
||||
|
||||
internal override void EncodeDescriptor(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.WriteObject(buffer, this.descriptor);
|
||||
}
|
||||
|
||||
internal override void EncodeValue(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.WriteObject(buffer, this.value);
|
||||
}
|
||||
|
||||
internal override void DecodeDescriptor(ByteBuffer buffer)
|
||||
{
|
||||
this.descriptor = Encoder.ReadObject(buffer);
|
||||
}
|
||||
|
||||
internal override void DecodeValue(ByteBuffer buffer)
|
||||
{
|
||||
this.value = Encoder.ReadObject(buffer);
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return this.value == null ? "nil" : this.value.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class DescribedValue : Described
|
||||
{
|
||||
object descriptor;
|
||||
object value;
|
||||
|
||||
public DescribedValue(object descriptor, object value)
|
||||
{
|
||||
this.descriptor = descriptor;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public object Descriptor
|
||||
{
|
||||
get { return this.descriptor; }
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return this.value; }
|
||||
}
|
||||
|
||||
internal override void EncodeDescriptor(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.WriteObject(buffer, this.descriptor);
|
||||
}
|
||||
|
||||
internal override void EncodeValue(ByteBuffer buffer)
|
||||
{
|
||||
Encoder.WriteObject(buffer, this.value);
|
||||
}
|
||||
|
||||
internal override void DecodeDescriptor(ByteBuffer buffer)
|
||||
{
|
||||
this.descriptor = Encoder.ReadObject(buffer);
|
||||
}
|
||||
|
||||
internal override void DecodeValue(ByteBuffer buffer)
|
||||
{
|
||||
this.value = Encoder.ReadObject(buffer);
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
public override string ToString()
|
||||
{
|
||||
return this.value == null ? "nil" : this.value.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Amqp.Types
|
|||
public const string TransactionRollback = "amqp:transaction:rollback";
|
||||
public const string TransactionTimeout = "amqp:transaction:timeout";
|
||||
|
||||
// messaging
|
||||
// messaging
|
||||
public const string MessageReleased = "amqp:message:released";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Fields : Map
|
||||
{
|
||||
public static Fields From(object[] array, int index)
|
||||
{
|
||||
object obj = array[index];
|
||||
if (obj != null)
|
||||
{
|
||||
Fields fields = array[index] as Fields;
|
||||
if (fields == null)
|
||||
{
|
||||
fields = new Fields();
|
||||
Map map = (Map)obj;
|
||||
foreach (var key in map.Keys)
|
||||
{
|
||||
fields.Add(key, map[key]);
|
||||
}
|
||||
|
||||
array[index] = fields;
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckKeyType(Type keyType)
|
||||
{
|
||||
Map.ValidateKeyType(typeof(Symbol), keyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Fields : Map
|
||||
{
|
||||
public static Fields From(object[] array, int index)
|
||||
{
|
||||
object obj = array[index];
|
||||
if (obj != null)
|
||||
{
|
||||
Fields fields = array[index] as Fields;
|
||||
if (fields == null)
|
||||
{
|
||||
fields = new Fields();
|
||||
Map map = (Map)obj;
|
||||
foreach (var key in map.Keys)
|
||||
{
|
||||
fields.Add(key, map[key]);
|
||||
}
|
||||
|
||||
array[index] = fields;
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckKeyType(Type keyType)
|
||||
{
|
||||
Map.ValidateKeyType(typeof(Symbol), keyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
namespace Amqp.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
using System;
|
||||
|
||||
public partial class Map
|
||||
{
|
||||
public new object this[object key]
|
||||
|
@ -34,18 +34,18 @@ namespace Amqp.Types
|
|||
this.CheckKeyType(key.GetType());
|
||||
base[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ValidateKeyType(Type expected, Type actual)
|
||||
{
|
||||
if (expected != actual)
|
||||
{
|
||||
throw new InvalidOperationException(Fx.Format(SRAmqp.InvalidMapKeyType, actual.Name, expected.Name));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckKeyType(Type keyType)
|
||||
{
|
||||
internal static void ValidateKeyType(Type expected, Type actual)
|
||||
{
|
||||
if (expected != actual)
|
||||
{
|
||||
throw new InvalidOperationException(Fx.Format(SRAmqp.InvalidMapKeyType, actual.Name, expected.Name));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckKeyType(Type keyType)
|
||||
{
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
|
|
|
@ -19,24 +19,24 @@ namespace Amqp
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Networking;
|
||||
using Windows.Networking.Sockets;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
sealed class TcpTransport : ITransport
|
||||
{
|
||||
readonly Queue<ByteBuffer> writeQueue;
|
||||
readonly Queue<ByteBuffer> writeQueue;
|
||||
Connection connection;
|
||||
StreamSocket socket;
|
||||
|
||||
public TcpTransport()
|
||||
{
|
||||
this.writeQueue = new Queue<ByteBuffer>();
|
||||
}
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
}
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.socket = new StreamSocket();
|
||||
this.socket.ConnectAsync(
|
||||
|
@ -73,15 +73,15 @@ namespace Amqp
|
|||
async void SendAsync(ByteBuffer buffer)
|
||||
{
|
||||
while (buffer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.socket.OutputStream.WriteAsync(buffer.Buffer.AsBuffer(buffer.Offset, buffer.Length));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.connection.OnIoException(exception);
|
||||
break;
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.socket.OutputStream.WriteAsync(buffer.Buffer.AsBuffer(buffer.Offset, buffer.Length));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.connection.OnIoException(exception);
|
||||
break;
|
||||
}
|
||||
|
||||
lock (this.writeQueue)
|
||||
|
|
|
@ -16,32 +16,32 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
{
|
||||
using global::Windows.System.Threading;
|
||||
|
||||
delegate void TimerCallback(object state);
|
||||
|
||||
class Timer
|
||||
{
|
||||
readonly TimerCallback callback;
|
||||
readonly object state;
|
||||
readonly ThreadPoolTimer timer;
|
||||
|
||||
public Timer(TimerCallback callback, object state, int dueTime, int period)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.state = state;
|
||||
this.timer = ThreadPoolTimer.CreatePeriodicTimer(this.OnTimer, TimeSpan.FromMilliseconds(dueTime));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.timer.Cancel();
|
||||
}
|
||||
|
||||
void OnTimer(ThreadPoolTimer t)
|
||||
{
|
||||
this.callback(this.state);
|
||||
{
|
||||
readonly TimerCallback callback;
|
||||
readonly object state;
|
||||
readonly ThreadPoolTimer timer;
|
||||
|
||||
public Timer(TimerCallback callback, object state, int dueTime, int period)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.state = state;
|
||||
this.timer = ThreadPoolTimer.CreatePeriodicTimer(this.OnTimer, TimeSpan.FromMilliseconds(dueTime));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.timer.Cancel();
|
||||
}
|
||||
|
||||
void OnTimer(ThreadPoolTimer t)
|
||||
{
|
||||
this.callback(this.state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using VSAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
static class Assert
|
||||
{
|
||||
public static void IsTrue(bool condition, string message = null)
|
||||
{
|
||||
VSAssert.IsTrue(condition, message ?? "Condition is not true.");
|
||||
}
|
||||
|
||||
public static void AreEqual(object expected, object actual, string message = null)
|
||||
{
|
||||
VSAssert.AreEqual(expected, actual, message ?? "Objects are not equal.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
using VSAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
static class Assert
|
||||
{
|
||||
public static void IsTrue(bool condition, string message = null)
|
||||
{
|
||||
VSAssert.IsTrue(condition, message ?? "Condition is not true.");
|
||||
}
|
||||
|
||||
public static void AreEqual(object expected, object actual, string message = null)
|
||||
{
|
||||
VSAssert.AreEqual(expected, actual, message ?? "Objects are not equal.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,99 +1,99 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class PerfTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
int totalCount;
|
||||
int completedCount;
|
||||
int initialCount;
|
||||
int batchCount;
|
||||
OutcomeCallback onOutcome;
|
||||
SenderLink sender;
|
||||
ManualResetEvent done;
|
||||
|
||||
[Description("Messages are sent unsettled. Completed count is incremented when the ack is received.")]
|
||||
//[TestMethod]
|
||||
public void PerfAtLeastOnceSend()
|
||||
{
|
||||
string testName = "PerfAtLeastOnceSend";
|
||||
Connection connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
this.sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
this.onOutcome = OnSendComplete;
|
||||
this.done = new ManualResetEvent(false);
|
||||
this.totalCount = 1000000;
|
||||
this.completedCount = 0;
|
||||
this.initialCount = 300;
|
||||
this.batchCount = 100;
|
||||
Trace.TraceLevel = TraceLevel.Information;
|
||||
|
||||
var watch = new System.Diagnostics.Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
this.SendMessages(initialCount);
|
||||
|
||||
this.done.WaitOne();
|
||||
watch.Stop();
|
||||
Trace.WriteLine(TraceLevel.Information, "total: {0}, time: {1}ms", this.totalCount, watch.ElapsedMilliseconds);
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
void SendMessages(int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
Message message = new Message("hello");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = "perf" };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
this.sender.Send(message, onOutcome, this);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnSendComplete(Message m, Outcome o, object state)
|
||||
{
|
||||
PerfTests thisPtr = (PerfTests)state;
|
||||
int sentCount = Interlocked.Increment(ref thisPtr.completedCount);
|
||||
if (sentCount >= thisPtr.totalCount)
|
||||
{
|
||||
thisPtr.done.Set();
|
||||
}
|
||||
else if (sentCount % thisPtr.batchCount == 0)
|
||||
{
|
||||
thisPtr.SendMessages(thisPtr.batchCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class PerfTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
int totalCount;
|
||||
int completedCount;
|
||||
int initialCount;
|
||||
int batchCount;
|
||||
OutcomeCallback onOutcome;
|
||||
SenderLink sender;
|
||||
ManualResetEvent done;
|
||||
|
||||
[Description("Messages are sent unsettled. Completed count is incremented when the ack is received.")]
|
||||
//[TestMethod]
|
||||
public void PerfAtLeastOnceSend()
|
||||
{
|
||||
string testName = "PerfAtLeastOnceSend";
|
||||
Connection connection = new Connection(address);
|
||||
Session session = new Session(connection);
|
||||
this.sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
this.onOutcome = OnSendComplete;
|
||||
this.done = new ManualResetEvent(false);
|
||||
this.totalCount = 1000000;
|
||||
this.completedCount = 0;
|
||||
this.initialCount = 300;
|
||||
this.batchCount = 100;
|
||||
Trace.TraceLevel = TraceLevel.Information;
|
||||
|
||||
var watch = new System.Diagnostics.Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
this.SendMessages(initialCount);
|
||||
|
||||
this.done.WaitOne();
|
||||
watch.Stop();
|
||||
Trace.WriteLine(TraceLevel.Information, "total: {0}, time: {1}ms", this.totalCount, watch.ElapsedMilliseconds);
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
void SendMessages(int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
Message message = new Message("hello");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = "perf" };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
this.sender.Send(message, onOutcome, this);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnSendComplete(Message m, Outcome o, object state)
|
||||
{
|
||||
PerfTests thisPtr = (PerfTests)state;
|
||||
int sentCount = Interlocked.Increment(ref thisPtr.completedCount);
|
||||
if (sentCount >= thisPtr.totalCount)
|
||||
{
|
||||
thisPtr.done.Set();
|
||||
}
|
||||
else if (sentCount % thisPtr.batchCount == 0)
|
||||
{
|
||||
thisPtr.SendMessages(thisPtr.batchCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using global::Amqp.Serialization;
|
||||
using global::Amqp.Types;
|
||||
using global::Amqp;
|
||||
|
||||
[AmqpContract(Name = "person", Code = 0)]
|
||||
[AmqpProvides(typeof(Student))]
|
||||
[AmqpProvides(typeof(Teacher))]
|
||||
class Person
|
||||
{
|
||||
public Person(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 1)]
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 2)]
|
||||
public int Age
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 3)]
|
||||
public DateTime? DateOfBirth;
|
||||
|
||||
public IDictionary<string, object> Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.properties == null)
|
||||
{
|
||||
this.properties = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
return this.properties;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 8)]
|
||||
Dictionary<string, object> properties;
|
||||
|
||||
[System.Runtime.Serialization.OnDeserialized]
|
||||
void OnDesrialized()
|
||||
{
|
||||
this.Age = this.Age + 1;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "student", Code = 1)]
|
||||
class Student : Person
|
||||
{
|
||||
Student() : base(null) { }
|
||||
|
||||
public Student(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
[AmqpMember(Name = "address", Order = 4)]
|
||||
public StreetAddress Address;
|
||||
|
||||
[AmqpMember(Name = "grades", Order = 10)]
|
||||
public List<int> Grades { get; set; }
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "teacher", Code = 2)]
|
||||
class Teacher : Person
|
||||
{
|
||||
public Teacher(string name)
|
||||
: base(name)
|
||||
{
|
||||
this.Id = EmployeeId.New();
|
||||
}
|
||||
|
||||
[AmqpMember(Name = "sallary", Order = 4)]
|
||||
public int Sallary;
|
||||
|
||||
[AmqpMember(Order = 10)]
|
||||
public EmployeeId Id
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 11)]
|
||||
public Dictionary<int, string> Classes
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[System.Runtime.Serialization.OnDeserialized]
|
||||
void OnDesrialized()
|
||||
{
|
||||
this.Sallary *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "address", Code = 3)]
|
||||
class StreetAddress
|
||||
{
|
||||
[AmqpMember]
|
||||
public string FullAddress;
|
||||
}
|
||||
|
||||
class EmployeeId : IAmqpSerializable
|
||||
{
|
||||
Guid uuid;
|
||||
|
||||
EmployeeId(Guid uuid)
|
||||
{
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public int EncodeSize
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
public void Encode(ByteBuffer buffer)
|
||||
{
|
||||
byte[] bytes = this.uuid.ToByteArray();
|
||||
buffer.Validate(true, bytes.Length);
|
||||
Buffer.BlockCopy(bytes, 0, buffer.Buffer, buffer.WritePos, bytes.Length);
|
||||
buffer.Append(bytes.Length);
|
||||
}
|
||||
|
||||
public void Decode(ByteBuffer buffer)
|
||||
{
|
||||
byte[] bytes = new byte[16];
|
||||
Buffer.BlockCopy(buffer.Buffer, buffer.Offset, bytes, 0, bytes.Length);
|
||||
this.uuid = new Guid(bytes);
|
||||
buffer.Complete(bytes.Length);
|
||||
}
|
||||
|
||||
public static EmployeeId New()
|
||||
{
|
||||
return new EmployeeId(Guid.NewGuid());
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is EmployeeId && ((EmployeeId)obj).uuid == this.uuid;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.uuid.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using global::Amqp.Serialization;
|
||||
using global::Amqp.Types;
|
||||
using global::Amqp;
|
||||
|
||||
[AmqpContract(Name = "person", Code = 0)]
|
||||
[AmqpProvides(typeof(Student))]
|
||||
[AmqpProvides(typeof(Teacher))]
|
||||
class Person
|
||||
{
|
||||
public Person(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 1)]
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 2)]
|
||||
public int Age
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 3)]
|
||||
public DateTime? DateOfBirth;
|
||||
|
||||
public IDictionary<string, object> Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.properties == null)
|
||||
{
|
||||
this.properties = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
return this.properties;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 8)]
|
||||
Dictionary<string, object> properties;
|
||||
|
||||
[System.Runtime.Serialization.OnDeserialized]
|
||||
void OnDesrialized()
|
||||
{
|
||||
this.Age = this.Age + 1;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "student", Code = 1)]
|
||||
class Student : Person
|
||||
{
|
||||
Student() : base(null) { }
|
||||
|
||||
public Student(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
[AmqpMember(Name = "address", Order = 4)]
|
||||
public StreetAddress Address;
|
||||
|
||||
[AmqpMember(Name = "grades", Order = 10)]
|
||||
public List<int> Grades { get; set; }
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "teacher", Code = 2)]
|
||||
class Teacher : Person
|
||||
{
|
||||
public Teacher(string name)
|
||||
: base(name)
|
||||
{
|
||||
this.Id = EmployeeId.New();
|
||||
}
|
||||
|
||||
[AmqpMember(Name = "sallary", Order = 4)]
|
||||
public int Sallary;
|
||||
|
||||
[AmqpMember(Order = 10)]
|
||||
public EmployeeId Id
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[AmqpMember(Order = 11)]
|
||||
public Dictionary<int, string> Classes
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[System.Runtime.Serialization.OnDeserialized]
|
||||
void OnDesrialized()
|
||||
{
|
||||
this.Sallary *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
[AmqpContract(Name = "address", Code = 3)]
|
||||
class StreetAddress
|
||||
{
|
||||
[AmqpMember]
|
||||
public string FullAddress;
|
||||
}
|
||||
|
||||
class EmployeeId : IAmqpSerializable
|
||||
{
|
||||
Guid uuid;
|
||||
|
||||
EmployeeId(Guid uuid)
|
||||
{
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public int EncodeSize
|
||||
{
|
||||
get { return 16; }
|
||||
}
|
||||
|
||||
public void Encode(ByteBuffer buffer)
|
||||
{
|
||||
byte[] bytes = this.uuid.ToByteArray();
|
||||
buffer.Validate(true, bytes.Length);
|
||||
Buffer.BlockCopy(bytes, 0, buffer.Buffer, buffer.WritePos, bytes.Length);
|
||||
buffer.Append(bytes.Length);
|
||||
}
|
||||
|
||||
public void Decode(ByteBuffer buffer)
|
||||
{
|
||||
byte[] bytes = new byte[16];
|
||||
Buffer.BlockCopy(buffer.Buffer, buffer.Offset, bytes, 0, bytes.Length);
|
||||
this.uuid = new Guid(bytes);
|
||||
buffer.Complete(bytes.Length);
|
||||
}
|
||||
|
||||
public static EmployeeId New()
|
||||
{
|
||||
return new EmployeeId(Guid.NewGuid());
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is EmployeeId && ((EmployeeId)obj).uuid == this.uuid;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.uuid.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,244 +1,244 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class TaskTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task BasicSendReceiveAsync()
|
||||
{
|
||||
string testName = "BasicSendReceiveAsync";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message();
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.ApplicationProperties["sn"]);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CustomMessgeBody()
|
||||
{
|
||||
string testName = "CustomMessgeBody";
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
Student student = new Student("Tom");
|
||||
student.Age = 16;
|
||||
student.Address = new StreetAddress() { FullAddress = "100 Main St. Small Town" };
|
||||
student.DateOfBirth = new System.DateTime(1988, 5, 1, 1, 2, 3, 100, System.DateTimeKind.Utc);
|
||||
|
||||
Message message = new Message(student);
|
||||
message.Properties = new Properties() { MessageId = "student" };
|
||||
await sender.SendAsync(message);
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message message2 = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message2.Properties);
|
||||
receiver.Accept(message);
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
|
||||
Student student2 = message2.GetBody<Student>();
|
||||
Assert.AreEqual(student.Age, student2.Age - 1); // incremented in OnDeserialized
|
||||
Assert.AreEqual(student.DateOfBirth, student2.DateOfBirth);
|
||||
Assert.AreEqual(student.Address.FullAddress, student2.Address.FullAddress);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LargeMessageSendReceiveAsync()
|
||||
{
|
||||
string testName = "LargeMessageSendReceiveAsync";
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
int messageSize = 100 * 1024;
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message(new string('D', messageSize));
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
string value = message.GetBody<string>();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0} body {1}x{2}",
|
||||
message.ApplicationProperties["sn"], value[0], value.Length);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LargeMessageOnMessageCallback()
|
||||
{
|
||||
string testName = "LargeMessageOnMessageCallback";
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
int messageSize = 100 * 1024;
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message(new string('D', messageSize));
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
sender.Send(message, null, null);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
ManualResetEvent done = new ManualResetEvent(false);
|
||||
int count = 0;
|
||||
receiver.Start(30, (link, message) =>
|
||||
{
|
||||
string value = message.GetBody<string>();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0} body {1}x{2}",
|
||||
message.ApplicationProperties["sn"], value[0], value.Length);
|
||||
receiver.Accept(message);
|
||||
|
||||
if (++count == nMsgs) done.Set();
|
||||
});
|
||||
|
||||
Assert.IsTrue(done.WaitOne(120000));
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CustomTransportConfiguration()
|
||||
{
|
||||
string testName = "CustomTransportConfiguration";
|
||||
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.TCP.NoDelay = true;
|
||||
factory.TCP.SendBufferSize = 16 * 1024;
|
||||
factory.TCP.SendTimeout = 30000;
|
||||
factory.SSL.RemoteCertificateValidationCallback = (a, b, c, d) => true;
|
||||
factory.AMQP.MaxFrameSize = 64 * 1024;
|
||||
factory.AMQP.HostName = "contoso.com";
|
||||
factory.AMQP.ContainerId = "container:" + testName;
|
||||
|
||||
Address sslAddress = new Address("amqps://guest:guest@127.0.0.1:5671");
|
||||
Connection connection = await factory.CreateAsync(sslAddress);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
Message message = new Message("custom transport config");
|
||||
message.Properties = new Properties() { MessageId = testName };
|
||||
await sender.SendAsync(message);
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message message2 = await receiver.ReceiveAsync();
|
||||
Assert.IsTrue(message2 != null, "no message received");
|
||||
receiver.Accept(message2);
|
||||
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task WebSocketSendReceiveAsync()
|
||||
{
|
||||
string testName = "WebSocketSendReceiveAsync";
|
||||
// assuming it matches the broker's setup
|
||||
Address wsAddress = new Address("ws://guest:guest@localhost:80");
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(wsAddress);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message();
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.ApplicationProperties["sn"]);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class TaskTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task BasicSendReceiveAsync()
|
||||
{
|
||||
string testName = "BasicSendReceiveAsync";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message();
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.ApplicationProperties["sn"]);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CustomMessgeBody()
|
||||
{
|
||||
string testName = "CustomMessgeBody";
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
Student student = new Student("Tom");
|
||||
student.Age = 16;
|
||||
student.Address = new StreetAddress() { FullAddress = "100 Main St. Small Town" };
|
||||
student.DateOfBirth = new System.DateTime(1988, 5, 1, 1, 2, 3, 100, System.DateTimeKind.Utc);
|
||||
|
||||
Message message = new Message(student);
|
||||
message.Properties = new Properties() { MessageId = "student" };
|
||||
await sender.SendAsync(message);
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message message2 = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message2.Properties);
|
||||
receiver.Accept(message);
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
|
||||
Student student2 = message2.GetBody<Student>();
|
||||
Assert.AreEqual(student.Age, student2.Age - 1); // incremented in OnDeserialized
|
||||
Assert.AreEqual(student.DateOfBirth, student2.DateOfBirth);
|
||||
Assert.AreEqual(student.Address.FullAddress, student2.Address.FullAddress);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LargeMessageSendReceiveAsync()
|
||||
{
|
||||
string testName = "LargeMessageSendReceiveAsync";
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
int messageSize = 100 * 1024;
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message(new string('D', messageSize));
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
string value = message.GetBody<string>();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0} body {1}x{2}",
|
||||
message.ApplicationProperties["sn"], value[0], value.Length);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LargeMessageOnMessageCallback()
|
||||
{
|
||||
string testName = "LargeMessageOnMessageCallback";
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
int messageSize = 100 * 1024;
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message(new string('D', messageSize));
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
sender.Send(message, null, null);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
ManualResetEvent done = new ManualResetEvent(false);
|
||||
int count = 0;
|
||||
receiver.Start(30, (link, message) =>
|
||||
{
|
||||
string value = message.GetBody<string>();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0} body {1}x{2}",
|
||||
message.ApplicationProperties["sn"], value[0], value.Length);
|
||||
receiver.Accept(message);
|
||||
|
||||
if (++count == nMsgs) done.Set();
|
||||
});
|
||||
|
||||
Assert.IsTrue(done.WaitOne(120000));
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CustomTransportConfiguration()
|
||||
{
|
||||
string testName = "CustomTransportConfiguration";
|
||||
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.TCP.NoDelay = true;
|
||||
factory.TCP.SendBufferSize = 16 * 1024;
|
||||
factory.TCP.SendTimeout = 30000;
|
||||
factory.SSL.RemoteCertificateValidationCallback = (a, b, c, d) => true;
|
||||
factory.AMQP.MaxFrameSize = 64 * 1024;
|
||||
factory.AMQP.HostName = "contoso.com";
|
||||
factory.AMQP.ContainerId = "container:" + testName;
|
||||
|
||||
Address sslAddress = new Address("amqps://guest:guest@127.0.0.1:5671");
|
||||
Connection connection = await factory.CreateAsync(sslAddress);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
Message message = new Message("custom transport config");
|
||||
message.Properties = new Properties() { MessageId = testName };
|
||||
await sender.SendAsync(message);
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message message2 = await receiver.ReceiveAsync();
|
||||
Assert.IsTrue(message2 != null, "no message received");
|
||||
receiver.Accept(message2);
|
||||
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task WebSocketSendReceiveAsync()
|
||||
{
|
||||
string testName = "WebSocketSendReceiveAsync";
|
||||
// assuming it matches the broker's setup
|
||||
Address wsAddress = new Address("ws://guest:guest@localhost:80");
|
||||
int nMsgs = 50;
|
||||
|
||||
Connection connection = await Connection.Factory.CreateAsync(wsAddress);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = new Message();
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
message.ApplicationProperties = new ApplicationProperties();
|
||||
message.ApplicationProperties["sn"] = i;
|
||||
await sender.SendAsync(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs; ++i)
|
||||
{
|
||||
Message message = await receiver.ReceiveAsync();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.ApplicationProperties["sn"]);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
await sender.CloseAsync();
|
||||
await receiver.CloseAsync();
|
||||
await session.CloseAsync();
|
||||
await connection.CloseAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,237 +1,237 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class TransactionTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
// if the project is targeted 4.5.1, TransactionScope can be created with
|
||||
// TransactionScopeAsyncFlowOption.Enabled option, and message can be sent
|
||||
// using SendAsync method.
|
||||
[TestMethod]
|
||||
public void TransactedPosting()
|
||||
{
|
||||
string testName = "TransactedPosting";
|
||||
int nMsgs = 5;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "commit" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// rollback
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs; i < nMsgs * 2; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "rollback" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
}
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "commit" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs * 2; i++)
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
Assert.IsTrue(message.Properties.MessageId.StartsWith("commit"));
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TransactedRetiring()
|
||||
{
|
||||
string testName = "TransactedRetiring";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
// send one extra for validation
|
||||
for (int i = 0; i < nMsgs + 1; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message[] messages = new Message[nMsgs];
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
messages[i] = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", messages[i].Properties.MessageId);
|
||||
}
|
||||
|
||||
// commit harf
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs / 2; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// rollback
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs / 2; i < nMsgs; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// after rollback, messages should be still acquired
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId);
|
||||
receiver.Release(message);
|
||||
}
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs / 2; i < nMsgs; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// only the last message is left
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
// at this point, the queue should have zero messages.
|
||||
// If there are messages, it is a bug in the broker.
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TransactedRetiringAndPosting()
|
||||
{
|
||||
string testName = "TransactedRetiringAndPosting";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
|
||||
receiver.SetCredit(2, false);
|
||||
Message message1 = receiver.Receive();
|
||||
Message message2 = receiver.Receive();
|
||||
|
||||
// ack message1 and send a new message in a txn
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
receiver.Accept(message1);
|
||||
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + nMsgs, GroupId = testName };
|
||||
sender.Send(message);
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// ack message2 and send a new message in a txn but abort the txn
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
receiver.Accept(message2);
|
||||
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + (nMsgs + 1), GroupId = testName };
|
||||
sender.Send(message1);
|
||||
}
|
||||
|
||||
receiver.Release(message2);
|
||||
|
||||
// receive all messages. should see the effect of the first txn
|
||||
receiver.SetCredit(nMsgs, false);
|
||||
for (int i = 1; i <= nMsgs; i++)
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
Assert.AreEqual("msg" + i, message.Properties.MessageId);
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Test.Amqp
|
||||
{
|
||||
[TestClass]
|
||||
public class TransactionTests
|
||||
{
|
||||
Address address = LinkTests.address;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void Initialize(TestContext context)
|
||||
{
|
||||
LinkTests.Initialize(context);
|
||||
}
|
||||
|
||||
// if the project is targeted 4.5.1, TransactionScope can be created with
|
||||
// TransactionScopeAsyncFlowOption.Enabled option, and message can be sent
|
||||
// using SendAsync method.
|
||||
[TestMethod]
|
||||
public void TransactedPosting()
|
||||
{
|
||||
string testName = "TransactedPosting";
|
||||
int nMsgs = 5;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "commit" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// rollback
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs; i < nMsgs * 2; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "rollback" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
}
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "commit" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
for (int i = 0; i < nMsgs * 2; i++)
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
Assert.IsTrue(message.Properties.MessageId.StartsWith("commit"));
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TransactedRetiring()
|
||||
{
|
||||
string testName = "TransactedRetiring";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
// send one extra for validation
|
||||
for (int i = 0; i < nMsgs + 1; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
Message[] messages = new Message[nMsgs];
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
messages[i] = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", messages[i].Properties.MessageId);
|
||||
}
|
||||
|
||||
// commit harf
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = 0; i < nMsgs / 2; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// rollback
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs / 2; i < nMsgs; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// after rollback, messages should be still acquired
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId);
|
||||
receiver.Release(message);
|
||||
}
|
||||
|
||||
// commit
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
for (int i = nMsgs / 2; i < nMsgs; i++)
|
||||
{
|
||||
receiver.Accept(messages[i]);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// only the last message is left
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
}
|
||||
|
||||
// at this point, the queue should have zero messages.
|
||||
// If there are messages, it is a bug in the broker.
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TransactedRetiringAndPosting()
|
||||
{
|
||||
string testName = "TransactedRetiringAndPosting";
|
||||
int nMsgs = 10;
|
||||
|
||||
Connection connection = new Connection(this.address);
|
||||
Session session = new Session(connection);
|
||||
SenderLink sender = new SenderLink(session, "sender-" + testName, "q1");
|
||||
|
||||
for (int i = 0; i < nMsgs; i++)
|
||||
{
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName };
|
||||
sender.Send(message);
|
||||
}
|
||||
|
||||
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1");
|
||||
|
||||
receiver.SetCredit(2, false);
|
||||
Message message1 = receiver.Receive();
|
||||
Message message2 = receiver.Receive();
|
||||
|
||||
// ack message1 and send a new message in a txn
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
receiver.Accept(message1);
|
||||
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + nMsgs, GroupId = testName };
|
||||
sender.Send(message);
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
|
||||
// ack message2 and send a new message in a txn but abort the txn
|
||||
using (var ts = new TransactionScope())
|
||||
{
|
||||
receiver.Accept(message2);
|
||||
|
||||
Message message = new Message("test");
|
||||
message.Properties = new Properties() { MessageId = "msg" + (nMsgs + 1), GroupId = testName };
|
||||
sender.Send(message1);
|
||||
}
|
||||
|
||||
receiver.Release(message2);
|
||||
|
||||
// receive all messages. should see the effect of the first txn
|
||||
receiver.SetCredit(nMsgs, false);
|
||||
for (int i = 1; i <= nMsgs; i++)
|
||||
{
|
||||
Message message = receiver.Receive();
|
||||
Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId);
|
||||
receiver.Accept(message);
|
||||
Assert.AreEqual("msg" + i, message.Properties.MessageId);
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,139 +1,139 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace TestAmqpBroker
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Amqp;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Usage()
|
||||
{
|
||||
Console.WriteLine("AmqpTestBroker url [url] [/creds:user:pwd] [/cert:ssl_cert] [/trace:level] [/queues:q1;q2;...]");
|
||||
Console.WriteLine(" url=amqp|amqps://host[:port] (can be multiple)");
|
||||
Console.WriteLine(" creds=username:passwrod");
|
||||
Console.WriteLine(" cert=ssl cert find value (thumbprint or subject)");
|
||||
Console.WriteLine(" trace=level (info, warn, error, frame)");
|
||||
Console.WriteLine(" queues: semicolon separated queue names. If not specified, the broker implicitly");
|
||||
Console.WriteLine(" creates a new node for any address and deletes it when the connection is closed.");
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Run(args);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine(exception.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Run(string[] args)
|
||||
{
|
||||
List<Uri> endpoints = new List<Uri>();
|
||||
string creds = null;
|
||||
string trace = null;
|
||||
string sslValue = null;
|
||||
string[] queues = null;
|
||||
bool parseEndpoint = true;
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (args[i][0] != '/' && parseEndpoint)
|
||||
{
|
||||
endpoints.Add(new Uri(args[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
parseEndpoint = false;
|
||||
if (args[i].StartsWith("/creds:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
creds = args[i].Substring(7);
|
||||
}
|
||||
else if (args[i].StartsWith("/trace:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
trace = args[i].Substring(7);
|
||||
}
|
||||
else if (args[i].StartsWith("/queues:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
queues = args[i].Substring(8).Split(';');
|
||||
}
|
||||
else if (args[i].StartsWith("/cert:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sslValue = args[i].Substring(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Unknown argument: {0}", args[i]);
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trace != null)
|
||||
{
|
||||
TraceLevel level = 0;
|
||||
switch (trace)
|
||||
{
|
||||
case "info":
|
||||
level = TraceLevel.Information;
|
||||
break;
|
||||
case "warn":
|
||||
level = TraceLevel.Warning;
|
||||
break;
|
||||
case "error":
|
||||
level = TraceLevel.Error;
|
||||
break;
|
||||
case "verbose":
|
||||
level = TraceLevel.Verbose;
|
||||
break;
|
||||
case "frame":
|
||||
level = TraceLevel.Frame;
|
||||
break;
|
||||
default:
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
Trace.TraceLevel = level;
|
||||
Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
}
|
||||
|
||||
var broker = new TestAmqpBroker(endpoints, creds, sslValue, queues);
|
||||
broker.Start();
|
||||
|
||||
Console.WriteLine("Broker started. Press the enter key to exit...");
|
||||
Console.ReadLine();
|
||||
|
||||
broker.Stop();
|
||||
Console.WriteLine("Broker stopped");
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace TestAmqpBroker
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Amqp;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Usage()
|
||||
{
|
||||
Console.WriteLine("AmqpTestBroker url [url] [/creds:user:pwd] [/cert:ssl_cert] [/trace:level] [/queues:q1;q2;...]");
|
||||
Console.WriteLine(" url=amqp|amqps://host[:port] (can be multiple)");
|
||||
Console.WriteLine(" creds=username:passwrod");
|
||||
Console.WriteLine(" cert=ssl cert find value (thumbprint or subject)");
|
||||
Console.WriteLine(" trace=level (info, warn, error, frame)");
|
||||
Console.WriteLine(" queues: semicolon separated queue names. If not specified, the broker implicitly");
|
||||
Console.WriteLine(" creates a new node for any address and deletes it when the connection is closed.");
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Run(args);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine(exception.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Run(string[] args)
|
||||
{
|
||||
List<Uri> endpoints = new List<Uri>();
|
||||
string creds = null;
|
||||
string trace = null;
|
||||
string sslValue = null;
|
||||
string[] queues = null;
|
||||
bool parseEndpoint = true;
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (args[i][0] != '/' && parseEndpoint)
|
||||
{
|
||||
endpoints.Add(new Uri(args[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
parseEndpoint = false;
|
||||
if (args[i].StartsWith("/creds:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
creds = args[i].Substring(7);
|
||||
}
|
||||
else if (args[i].StartsWith("/trace:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
trace = args[i].Substring(7);
|
||||
}
|
||||
else if (args[i].StartsWith("/queues:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
queues = args[i].Substring(8).Split(';');
|
||||
}
|
||||
else if (args[i].StartsWith("/cert:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sslValue = args[i].Substring(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Unknown argument: {0}", args[i]);
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trace != null)
|
||||
{
|
||||
TraceLevel level = 0;
|
||||
switch (trace)
|
||||
{
|
||||
case "info":
|
||||
level = TraceLevel.Information;
|
||||
break;
|
||||
case "warn":
|
||||
level = TraceLevel.Warning;
|
||||
break;
|
||||
case "error":
|
||||
level = TraceLevel.Error;
|
||||
break;
|
||||
case "verbose":
|
||||
level = TraceLevel.Verbose;
|
||||
break;
|
||||
case "frame":
|
||||
level = TraceLevel.Frame;
|
||||
break;
|
||||
default:
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
Trace.TraceLevel = level;
|
||||
Trace.TraceListener = (f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a));
|
||||
}
|
||||
|
||||
var broker = new TestAmqpBroker(endpoints, creds, sslValue, queues);
|
||||
broker.Start();
|
||||
|
||||
Console.WriteLine("Broker started. Press the enter key to exit...");
|
||||
Console.ReadLine();
|
||||
|
||||
broker.Stop();
|
||||
Console.WriteLine("Broker stopped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TestAmqpBroker")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("TestAmqpBroker")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("82f5fead-0cf9-43e1-bb1d-ad79da1b0700")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TestAmqpBroker")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("TestAmqpBroker")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("82f5fead-0cf9-43e1-bb1d-ad79da1b0700")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
Загрузка…
Ссылка в новой задаче