
#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.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using System.Collections;

namespace MyCompany.Server.EncryptionSink
{
    /// <summary>
    /// References the callback method to be called by <see cref="EncryptionServerSink"/> to process the message stream.
    /// </summary>
    /// <remarks>
    /// <b>InputOutputStreamProcessorDelegate</b> provides a way for server 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 server sink provider.
    /// </summary>
	public class EncryptionServerSinkProvider: IServerChannelSinkProvider
	{
		private byte[] _encryptionKey;
		private String _encryptionAlgorithm;
        private InputOutputStreamProcessorDelegate _outputStreamDelegate;
        private InputOutputStreamProcessorDelegate _inputStreamDelegate;

		private IServerChannelSinkProvider _nextProvider;
        /// <summary>
        /// Initializes a new instance of <see cref="EncryptionServerSinkProvider"/> 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="EncryptionServerSinkProvider"/>.
        /// </param>    
        /// <param name="providerData">data specific to sink. Not used in this ctor</param>
		public EncryptionServerSinkProvider(IDictionary properties, ICollection providerData) 
		{ 
			_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 <see cref="System.Runtime.Remoting.Channels.IServerChannelSinkProvider"/> in the sink provider chain.
        /// </summary>
        /// <value>The next <see cref="System.Runtime.Remoting.Channels.IServerChannelSinkProvider"/> in the sink provider chain.</value>        		
		public IServerChannelSinkProvider Next
		{
			get {return _nextProvider; }
			set {_nextProvider = value;}
		}

        /// <summary>
        /// Creates a sink chain.
        /// </summary>
        /// <param name="channel">The channel for which to create the channel sink chain. </param>
        /// <returns>The first sink of the newly formed channel sink chain, or a null reference (Nothing in Visual Basic), indicating that this provider will not or cannot provide a connection for this endpoint.</returns>
		public IServerChannelSink CreateSink(IChannelReceiver channel)
		{
			// create other sinks in the chain
			IServerChannelSink next = _nextProvider.CreateSink(channel);				
	
			// put our sink on top of the chain and return it				
			return new EncryptionServerSink(next,_encryptionKey,_encryptionAlgorithm,_inputStreamDelegate,_outputStreamDelegate);
		}

        /// <summary>
        /// Returns the channel data for the channel that the current sink is associated with.
        /// </summary>
        /// <param name="channelData">An IChannelDataStore object in which the channel data is to be returned. </param>
        /// <remarks>This method does not do any thing</remarks>
		public void GetChannelData(IChannelDataStore channelData)
		{
			// not yet needed
		}

	}
}

