
#region Copyright
// (c) Copyright Axalto Inc., 2006.                    
// All rights reserved.
//
// This file is part of the SmartCard.NET Framework SDK Code Samples.
//
// This source code is intended only as a supplement to Axalto
// Development Tools and/or on-line documentation.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
#endregion

using System;
using System.IO;
using System.Collections;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Runtime.Remoting.Channels;

namespace MyCompany.Client.EncryptionSink
{
    /// <summary>
    /// References the callback method to be called by <see cref="EncryptionClientSink"/> to process the message stream.
    /// </summary>
    /// <remarks>
    /// <b>InputOutputStreamProcessorDelegate</b> provides a way for client application to do its custom processing of the
    /// message stream (incoming or outgoing) 
    /// </remarks>
    /// <param name="mem">Message stream passed to the callback method for processing.</param>
    /// <returns>Message stream returned by the callback method to the EncryptionSink.</returns>
    public delegate MemoryStream InputOutputStreamProcessorDelegate(MemoryStream mem); 

    /// <summary>
    /// Provides the implementation for the Encryption client sink provider.
    /// </summary>
	public class EncryptionClientSinkProvider: IClientChannelSinkProvider
	{
		private IClientChannelSinkProvider _nextProvider;

		private byte[] _encryptionKey;
		private String _encryptionAlgorithm;
        private InputOutputStreamProcessorDelegate _outputStreamDelegate;
        private InputOutputStreamProcessorDelegate _inputStreamDelegate;

        /// <summary>
        /// Initializes a new instance of <see cref="EncryptionClientSinkProvider"/> with specified properties.
        /// </summary>
        /// <param name="properties">An <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionsidictionaryclasstopic.asp">IDictionary</a>
        /// of configuration properties to use with the new instance of <see cref="EncryptionClientSinkProvider"/>.
        /// </param>        
		public EncryptionClientSinkProvider(IDictionary properties) 
		{
			_encryptionAlgorithm = (String) properties["algorithm"];
			_encryptionKey = (byte[]) properties["key"];

            _inputStreamDelegate = (InputOutputStreamProcessorDelegate)properties["_inStreamDelegate"];
            _outputStreamDelegate = (InputOutputStreamProcessorDelegate)properties["_outStreamDelegate"];

            if (_encryptionKey == null) 			
                throw new ArgumentException();
		}

        /// <summary>
        /// Gets or sets the next <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeremotingchannelsiclientchannelsinkproviderclasstopic.asp">IClientChannelSinkProvider</a> in the sink provider chain.
        /// </summary>
        /// <value>The next <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeremotingchannelsiclientchannelsinkproviderclasstopic.asp">IClientChannelSinkProvider</a> in the sink provider chain.</value>        
		public IClientChannelSinkProvider Next
		{
            [SecurityPermission(SecurityAction.LinkDemand, Infrastructure=true)]
			get {return _nextProvider; }

            [SecurityPermission(SecurityAction.LinkDemand, Infrastructure=true)]
			set {_nextProvider = value;}
		}

        /// <summary>
        /// Creates a sink chain.
        /// </summary>
        /// <param name="channel">Channel for which this sink chain is being constructed. </param>
        /// <param name="url">URL of object to connect to or the channel URI for the target object.</param>
        /// <param name="remoteChannelData">A channel data object describing a channel on the remote server.</param>
        /// <returns>The first sink of the newly formed channel sink chain, or a null reference (<b>Nothing</b> in 
        /// Visual Basic) indicating that this provider will not or cannot provide a connection for this endpoint.
        ///</returns>
        [SecurityPermission(SecurityAction.LinkDemand, Infrastructure=true)]
		public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData) 
		{
			// create other sinks in the chain
			IClientChannelSink next = _nextProvider.CreateSink(channel,
				url,
				remoteChannelData);	
	
			// put our sink on top of the chain and return it				
			return new EncryptionClientSink(next,_encryptionKey,_encryptionAlgorithm,_inputStreamDelegate,_outputStreamDelegate);
		}
	}
}

