////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//   Wireless Communication Library 7                                         //
//                                                                            //
//   Copyright (C) 2006-2024 Mike Petrichenko                                 //
//                           Soft Service Company                             //
//                           All Rights Reserved                              //
//                                                                            //
//   http://www.btframework.com                                               //
//                                                                            //
//   support@btframework.com                                                  //
//   shop@btframework.com                                                     //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "..\Common\wclHelpers.h"
#include "..\Common\wclMessaging.h"

#include "wclConnectionErrors.h"

using wclCommon::CwclMessage;
using wclCommon::CwclMessageReceiver;

namespace wclCommunication
{
	/// <summary> The base class for all WCL connections. </summary>
	/// <remarks> A connection implements a hardware-dependent methods
	///  to communicate with a remote devices: IrDA, Classic Bluetooth, BLE,
	///  Serial etc. </remarks>
	class CwclCustomConnection
	{
		DISABLE_COPY(CwclCustomConnection);

	private:
		RTL_CRITICAL_SECTION	FCS;
		CwclMessageReceiver*	FReceiver;
		DWORD					FThreadId;
		
	protected:
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <remarks> <para> This method is for internal use only. </para>
		///   <para> If a derived class overrides this method it must always call
		///   the inherited implementation first. </para> </remarks>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message);

		/* Thread synchronization. */

		/// <summary> Enters the connection's critical section. </summary>
		/// <remarks> The method should be used to protect connection in
		///   multi-threaded applications. </remarks>
		void Enter();
		/// <summary> Exists *leaves) the connection's critical section. </summary>
		/// <remarks> The method should be used to protect connection in
		///   multi-threaded applications. </remarks>
		void Leave();
		
	public:
		/// <summary> Creates a new connection. </summary>
		CwclCustomConnection();
		/// <summary> Frees the connection. </summary>
		virtual ~CwclCustomConnection();

		/// <summary> Gets the connection message receiver object. </summary>
		/// <returns> The internal message receiver object. </returns>
		/// <seealso cref="CwclMessageReceiver" />
		CwclMessageReceiver* GetReceiver() const;
		/// <summary> Gets the connection message receiver object. </summary>
		/// <value> The internal message receiver object. </value>
		/// <seealso cref="CwclMessageReceiver" />
		__declspec(property(get = GetReceiver)) CwclMessageReceiver* Receiver;

		/// <summary> Gets the connection's thread ID. </summary>
		/// <returns> The thread ID. </returns>
		/// <remarks> The connection's thread ID is the ID of the thread that
		///   created and used to handle the connection. </remarks>
		DWORD GetThreadId() const;
		/// <summary> Gets the connection's thread ID. </summary>
		/// <value> The thread ID. </value>
		/// <remarks> The connection's thread ID is the ID of the thread that
		///   created and used to handle the connection. </remarks>
		__declspec(property(get = GetThreadId)) DWORD ThreadId;
	};

	/// <summary> The client connection states. </summary>
	typedef enum
	{
		/// <summary> A client is disconnected. </summary>
		csDisconnected,
		/// <summary> A client is preparing for connection. </summary>
		csPreparing,
		/// <summary> A client is connecting to a remote device. </summary>
		csConnecting,
		/// <summary> A client is connected to a remote device. </summary>
		csConnected,
		/// <summary> A client is disconnecting from a remote device. </summary>
		csDisconnecting
	} wclClientState;

	/// <summary> The <c>OnConnect</c> event handler prototype.  </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
	/// <remarks> If the <c>Error</c> parameter of the event is not
	///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
	///   method again from inside the event handler. </remarks>
	#define wclClientConnectionConnectEvent(_event_name_) \
		__event void _event_name_(void* Sender, const int Error)
	/// <summary> The <c>OnDisconnect</c> and <c>OnClose</c> events handler prototype. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	#define wclClientConnectionDisconnectEvent(_event_name_) \
		__event void _event_name_(void*Sender, const int Reason)

	/// <summary> The base class for all client oriented connections. </summary>
	/// <remarks> The class provides the basic methods for client
	///   connections. </remarks>
	/// <seealso cref="CwclCustomConnection" />
	class CwclClientConnection : public CwclCustomConnection
	{
		DISABLE_COPY(CwclClientConnection);
		
	private:
		wclClientState	FState;
		unsigned long	FTimeout;
		
		// Used to notify communication thread that the connection is ready for
		// communicate and is in valid connected state.
		HANDLE	FConnectedEvent;
		// Communication thread termination event.
		HANDLE	FDisconnectEvent;
		// Communication thread handle.
		HANDLE	FThread;
		
		// Internal communication thread routine. Calls HalConnect and if succeeded
		// calls HalCommunicate.
		static UINT __stdcall _ThreadProc(LPVOID lpParam);
		void CommunicationThread();

	protected:
		/// <summary> The internal disconnect method. Disconnects from a
		///   connected remote device. </summary>
		/// <param name="Reason"> The disconnection reason code. If the
		///   method has been called by the <c>Disconnect</c> method the
		///   reason is <see cref="WCL_E_SUCCESS" /> </param>
		void InternalDisconnect(const int Reason);

		/// <summary> Send a Disconnect notification message. </summary>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		void NotifyClosed(const int Reason);
		
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message) override;
		
		/// <summary> Fires the <c>OnConnect</c> event. </summary>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		virtual void DoConnect(const int Error);
		/// <summary> Fires the <c>OnDisconnect</c> event. </summary>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		virtual void DoDisconnect(const int Reason);
		
		/// <summary> Implements a hardware-dependent code that communicate with the
		///   connected remote device. </summary>
		/// <param name="Event"> The system even object handle (disconnect
		///   event). </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> Derived classes must override this method to implement
		///   a hardware-dependent code that exchanges data with a remote
		///   device. </para>
		///   <para> The method executes in a separate thread. </para>
		///   <para> The method implementation must monitor the <c>Event</c>
		///   parameter. The <c>Event</c> parameter is set if the
		///   <c>Disconnect</c> method was called and the method must terminate
		///   communication and exit. </para>
		///   <para> The default implementation simple waits for the <c>Event</c>
		///   and exists when the events signaled. </para> </remarks>
		virtual int HalCommunicate(const HANDLE Event);
		/// <summary> Implements a hardware-dependent code that connects to a
		///   remote device. </summary>
		/// <param name="Event"> The system even object handle. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> Derived classes must override this method to implement
		///   a hardware-dependent code that connects to a remote device. </para>
		///   <para> The method executes in a separate thread. </para>
		///   <para> The method implementation must monitor the <c>Event</c>
		///   parameter. The <c>Event</c> parameter is set if the
		///   <c>Disconnect</c> method was called. If the termination event was set
		///   the method must terminate connection operation. </para>
		///   <para> If connection to a remote device was terminated the method
		///   must release all allocated resources because the <c>HalDisconnect</c>
		///   will not be called. </para> </remarks>
		virtual int HalConnect(const HANDLE Event) = 0;
		/// <summary> Implements a hardware-dependent code that disconnects from the
		///   connected remote device. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> The method is called only if a connection to a remote
		///   device was established with success (the <c>Connect</c> method was
		///   success). </para>
		///   <para> The method will not be called if the connection to the  remote
		///   device was terminated in the middle of the <c>HalConnect</c>
		///   method. </para> </remarks>
		virtual int HalDisconnect() = 0;
		
	public:
		/// <summary> Creates a new client connection. </summary>
		CwclClientConnection();
		/// <summary> Frees the connection. </summary>
		virtual~CwclClientConnection();

		/// <summary> Connects to a remote device. </summary>
		/// <param name="Timeout"> The connect timeout in milliseconds. The
		///   default value is 10000 milliseconds. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The method starts a connection operation to a remote device.
		///   If the method success that does not mean that the connection was
		///   established. That just means that the connection operation was
		///   started. The real connection result will be passed to the
		///   <c>OnConnect</c> event handler. </remarks>
		int Connect(const unsigned long Timeout = 10000);
		/// <summary> Disconnects from the connected remote device. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The method disconnects from the connected remote device or
		///   terminates the pending connection. </remarks>
		int Disconnect();

		/// <summary> Gets the connection state. </summary>
		/// <returns> The <see cref="wclClientState" /> indicates the current
		///   connection state. </returns>
		/// <seealso cref="wclClientState" />
		wclClientState GetState() const;
		/// <summary> Gets the connection state. </summary>
		/// <value> The <see cref="wclClientState" /> indicates the current
		///   connection state. </value>
		/// <seealso cref="wclClientState" />
		__declspec(property(get = GetState)) wclClientState State;

		/// <summary> Gets the connect timeout value. </summary>
		/// <returns> The connect timeout value in milliseconds. </returns>
		unsigned long GetTimeout() const;
		/// <summary> Gets the connect timeout value. </summary>
		/// <value> The connect timeout value in milliseconds. </value>
		__declspec(property(get = GetTimeout)) unsigned long Timeout;

		/// <summary> The event fires when a connection to a remote device
		///   has been completed (with or without success). </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		/// <remarks> If the <c>Error</c> parameter of the event is not
		///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
		///   method again from inside the event handler. </remarks>
		wclClientConnectionConnectEvent(OnConnect);
		/// <summary> The event fires when the remote connected device has been
		///   disconnected. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		wclClientConnectionDisconnectEvent(OnDisconnect);
	};

	/// <summary> The <c>OnData</c> event handler prototype. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Data"> The pointer to the received data buffer.
	///   It is guaranteed that the parameter points to a valid data buffer.
	///   The data buffer is valid only inside the event handler. If an
	///   application needs to use the data outside the event handle it must
	///   allocate own buffer and copy data into it. </param>
	/// <param name="Size"> The data buffer size. It is guaranteed that the size
	///   is greater than 0. </param>
	#define wclConnectionDataEvent(_event_name_) \
		__event void _event_name_(void* Sender, const void* const Data, \
		const unsigned long Size)

	// Forward declaration.
	class CwclCustomClientDataProcessor;

	/// <summary> The base class for the client connection that requires data
	///   exchange with a remote device. </summary>
	/// <seealso cref="CwclClientConnection" />
	class CwclClientDataConnection : public CwclClientConnection
	{
		DISABLE_COPY(CwclClientDataConnection);

	private:
		friend class CwclCustomClientDataProcessor;

		CwclCustomClientDataProcessor*	FProcessor;

	protected:
		/// <summary> Send a data notification message. </summary>
		/// <param name="Data"> The data buffer contains received data. </param>
		/// <param name="Size"> The length of the received data. </param>
		void NotifyDataReceived(const void* const Data, const unsigned long Size);
		
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message) override;
		
		/// <summary> Fires the <c>OnData</c> event. </summary>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		virtual void DoData(const void* const Data, const unsigned long Size);
		
		/// <summary> Reads the read buffer size. </summary>
		/// <param name="Size"> On output he read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size reading code. </remarks>
		virtual int HalGetReadBufferSize(unsigned long& Size) = 0;
		/// <summary> Reads the write buffer size. </summary>
		/// <param name="Size"> On output the write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size reading code. </remarks>
		virtual int HalGetWriteBufferSize(unsigned long& Size) = 0;
		
		/// <summary> Sets the read buffer size. </summary>
		/// <param name="Size"> The new read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size setting code. </remarks>
		virtual int HalSetReadBufferSize(const unsigned long Size) = 0;
		/// <summary> Sets the write buffer size. </summary>
		/// <param name="Size"> The new write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size setting code. </remarks>
		virtual int HalSetWriteBufferSize(const unsigned long Size) = 0;
		
		/// <summary> Implements a hardware-dependent code that sends data to the
		///   connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement a
		///   hardware-dependent code that sends data to the connected device.
		///   The method executes in the main thread and must be
		///   synchronous. </remarks>
		virtual int HalWrite(const void* const Data, const unsigned long Size,
			unsigned long& Written) = 0;
		
	public:
		/// <summary> Creates a new client data connection. </summary>
		CwclClientDataConnection();
		
		/// <summary> Reads the read buffer size. </summary>
		/// <param name="Size"> On output he read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int GetReadBufferSize(unsigned long& Size);
		/// <summary> Reads the write buffer size. </summary>
		/// <param name="Size"> On output the write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int GetWriteBufferSize(unsigned long& Size);
		
		/// <summary> Sets the read buffer size. </summary>
		/// <param name="Size"> The new read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int SetReadBufferSize(const unsigned long Size);
		/// <summary> Sets the write buffer size. </summary>
		/// <param name="Size"> The new write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int SetWriteBufferSize(const unsigned long Size);
		
		/// <summary> Sends data to the connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The write is synchronous operation. </remarks>
		int Write(const void* const Data, const unsigned long Size, unsigned long& Written);

		/// <summary> Gets the current Data Processor object assigned to the
		///   Connection. </summary>
		/// <returns> The <see cref="CwclCustomClientDataProcessor" /> object
		///   used by the Connection to process data. </returns>
		/// <seealso cref="CwclCustomClientDataProcessor" />
		CwclCustomClientDataProcessor* GetProcessor() const;
		__declspec(property(get = GetProcessor)) CwclCustomClientDataProcessor* Processor;

		/// <summary> The event fires when new data is received from the
		///   connected remote device. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		wclConnectionDataEvent(OnData);
	};

	// Forward declaration.
	class CwclServerConnection;

	/// <summary> The base class for all server client connection. </summary>
	/// <remarks> The class provides the basic methods for server
	///   connections. </remarks>
	/// <seealso cref="CwclCustomConnection" />
	class CwclServerClientConnection : public CwclCustomConnection
	{
		DISABLE_COPY(CwclServerClientConnection);
		
	private:
		friend class CwclServerConnection;

		bool					FDisconnected; // Internal flag used to indicate disconnection.
		CwclServerConnection*	FServer; // Owner.
		
		void*					FParams; // Custom connection parameters.
		
		HANDLE					FDisconnectEvent;
		HANDLE					FThread;
		HANDLE					FThreadInitDoneEvent;
		int						FThreadInitResult;
		
		// Internal communication thread routine. Calls HalConnect and if succeeded
		// calls HalCommunicate.
		static UINT __stdcall _ThreadProc(LPVOID lpParam);
		void CommunicationThread();
		// Executes disconnection from remote device.
		void InternalDisconnect(const int Reason);
		
	protected:
		/// <summary> Send a Disconnect notification message. </summary>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		void NotifyClosed(const int Reason);
		
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message) override;
		
		/// <summary> Fires the <c>OnConnect</c> event. </summary>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		virtual void DoConnect(const int Error);
		/// <summary> Fires the <c>OnDisconnect</c> event. </summary>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		virtual void DoDisconnect(const int Reason);
		
		/// <summary> The method accepts the client connection request. </summary>
		/// <param name="Server"> A <see cref="CwclServerConnection" />
		///   object owns the client connection. </param>
		/// <param name="Params"> An optional pointer to the hardware-dependent
		///   data contains information about client connection request. </param>
		/// <param name="ParamsSize"> An optional parameters size. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> The method called by the server when connection from a
		///   remote client device has already been accepted. </para>
		///   <para> The method is always called from the main (or from the same)
		///   thread that runs the server. </para>
		///   <para> The method prepares the class for communication with a remote
		///   client. </para>
		///   <para> If the method fails it disconnects already accepted client
		///   connection. </para> </remarks>
		/// <seealso cref="CwclServerConnection" />
		virtual int Accept(CwclServerConnection* const Server, const void* const Params,
			const unsigned long ParamsSize);
		
		/// <summary> Hardware-dependent method that prepares to communicate
		///   with a connected remote client device. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to provide a
		///   hardware-dependent code that prepares the class to communicate
		///   with a remote connected device. </remarks>
		virtual int HalAccept() = 0;
		/// <summary> Implements a hardware-dependent code that communicate with the
		///   connected remote device. </summary>
		/// <param name="Event"> The system even object handle (disconnect
		///   event). </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> Derived classes must override this method to implement
		///   a hardware-dependent code that exchanges data with a remote
		///   device. </para>
		///   <para> The method executes in a separate thread. </para>
		///   <para> The method implementation must monitor the <c>Event</c>
		///   parameter. The <c>Event</c> parameter is set if the
		///   <c>Disconnect</c> method was called and the method must terminate
		///   communication and exit. </para>
		///   <para> The default implementation simple waits for the <c>Event</c>
		///   and exists when the events signaled. </para> </remarks>
		virtual int HalCommunicate(const HANDLE Event);
		/// <summary> Implements a hardware-dependent code that disconnects from the
		///   connected remote device. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to provide a
		///   hardware-dependent code that disconnects from a remote connected
		///   device. </remarks>
		virtual int HalDisconnect() = 0;

		/// <summary> Gets the connection state. </summary>
		/// <returns> <c>True</c> if the connection is disconnected. </returns>
		bool GetDisconnected() const;
		/// <summary> Gets the connection state. </summary>
		/// <value> <c>True</c> if the connection is disconnected. </value>
		__declspec(property(get = GetDisconnected)) bool Disconnected;

		/// <summary> Custom connection parameters. </summary>
		/// <returns> The pointer to the custom connection parameters. </returns>
		/// <remarks> The parameters passed from the
		///   <see cref="CwclServerConnection" /> object and contains
		///   hardware-dependent data about accepted client connections. </remarks>
		void* GetParams() const;
		__declspec(property(get = GetParams)) void* Params;

	public:
		/// <summary> Creates a new server client connection. </summary>
		CwclServerClientConnection();
		/// <summary> Frees the connection. </summary>
		virtual ~CwclServerClientConnection();

		/// <summary> Disconnects from the connected remote device. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> The method disconnects from the connected remote
		///   device. </para>
		///   <para> The method also frees the object. After calling this method an
		///   application must not use the object. </para> </remarks>
		int Disconnect();

		/// <summary> Gets the client owner. </summary>
		/// <returns> The <see cref="CwclServerConnection" /> object
		///   that owns the connection. </returns>
		/// <seealso cref="CwclServerConnection" />
		CwclServerConnection* GetServer() const;
		__declspec(property(get = GetServer)) CwclServerConnection* Server;

		/// <summary> The event fires when a connection to a remote device
		///   has been completed (with or without success). </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		/// <remarks> If the <c>Error</c> parameter of the event is not
		///   <see cref="WCL_E_SUCCESS" /> an application may call <c>Connect</c>
		///   method again from inside the event handler. </remarks>
		wclClientConnectionConnectEvent(OnConnect);
		/// <summary> The event fires when the remote connected device has been
		///   disconnected. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		wclClientConnectionDisconnectEvent(OnDisconnect);
	};

	/// <summary> The server connections states. </summary>
	typedef enum
	{
		/// <summary> A server is closed. </summary>
		ssClosed,
		/// <summary> A server is preparing for connection. </summary>
		ssPreparing,
		/// <summary> A server is listening. </summary>
		ssListening,
		/// <summary> A server is closing. </summary>
		ssClosing
	} wclServerState;

	/// <summary> The server's <c>OnConnect</c> event handler prototype. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> The
	///   <see cref="CwclServerClientConnection" /> represents a remote
	///   connected client. </param>
	/// <param name="Error"> The connection operation result code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
	///   device was established and the remote device is connected. Otherwise
	///   the connection was not established and the remote device is
	///   not connected. </param>
	/// <seealso cref="CwclServerClientConnection" />
	#define wclServerConnectionConnectEvent(_event_name_) \
		__event void _event_name_(void* Sender, CwclServerClientConnection* const Client, \
		const int Error)
	/// <summary> The server's <c>OnDisconnect</c> event handler prototype. </summary>
	/// <summary> The prototype of the <c>OnDisconnect</c> event handler for
	///   server connections. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> The
	///   <see cref="CwclServerClientConnection" /> represents a remote
	///   connected client. </param>
	/// <param name="Reason"> The disconnection code. If the
	///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
	///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
	///   reason. </param>
	/// <seealso cref="CwclServerClientConnection" />
	#define wclServerConnectionDisconnectEvent(_event_name_) \
		__event void _event_name_(void* Sender, CwclServerClientConnection* const Client, \
		const int Reason)

	/// <summary> The base class for all server connections. </summary>
	/// <remarks> An application must never create this class directly.
	///   Instead of that an application must use high-level
	///   components. </remarks>
	/// <seealso cref="CwclCustomConnection" />
	class CwclServerConnection : public CwclCustomConnection
	{
		DISABLE_COPY(CwclServerConnection);

	private:
		friend class CwclServerClientConnection;
		typedef std::list<CwclServerClientConnection*> CLIENTS;

		// Clients list.
		CLIENTS*		FClients;
		wclServerState	FState;

		// Client that should be deleted.
		CwclServerClientConnection* FClientToDelete;
		
		// Communication thread termination event.
		HANDLE			FCloseEvent;
		// Communication thread handle.
		HANDLE			FThread;
		// Indicates the communication thread has been initialized.
		HANDLE			FThreadInitDoneEvent;
		// Indicates the thread initialization result.
		int				FThreadInitResult;
		
		void ClientConnect(void* Sender, const int Error);
		void ClientDisconnect(void* Sender, const int Reason);
		
		// Internal communication thread routine. Calls HalConnect and if succeeded
		// calls HalCommunicate.
		static UINT __stdcall _ThreadProc(LPVOID lpParam);
		void CommunicationThread();

		void DeleteClient(CwclServerClientConnection* const Client);
		
	protected:
		/// <summary> Unhooks events from the client that should be deleted. </summary>
		virtual void UnhookDeletedClientEvents(CwclServerClientConnection* const Client);

		/// <summary> Closes the server. </summary>
		/// <param name="Reason"> The close reason code. If the server closed by
		///   the <c>Close</c> method call the <c>Reason</c> is
		///   <see cref="WCL_E_SUCCESS" /> </param>
		void InternalClose(const int Reason);

		/// <summary> Sends a notification to the main thread to create and init
		///   new client connection. </summary>
		/// <param name="Params"> An optional pointer to the hardware-dependent
		///   data contains information about client connection request. </param>
		/// <param name="ParamsSize"> An optional parameters size. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The <c>HalListen</c> method should call this method to
		///   create and initialize new client connection. </remarks>
		int CreateNewClientConnection(const void* const Params, const unsigned long ParamsSize);
		
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message) override;
		
		/// <summary> Fires the <c>OnClosed</c> event. </summary>
		/// <param name="Reason"> The close reason code. If the server closed by
		///   the <c>Close</c> method call the <c>Reason</c> is
		///   <see cref="WCL_E_SUCCESS" /> </param>
		virtual void DoClosed(const int Reason);
		/// <summary> Fires the <c>OnConnect</c> event. </summary>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a remote
		///   connected client. </param>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		/// <seealso cref="CwclServerClientConnection" />
		virtual void DoConnect(CwclServerClientConnection* const Client, const int Error);
		/// <summary> Fires the <c>OnDisconnect</c> event. </summary>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a remote
		///   connected client. </param>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		/// <seealso cref="CwclServerClientConnection" />
		virtual void DoDisconnect(CwclServerClientConnection* const Client, const int Reason);
		/// <summary> Fires the <c>OnListen</c> event. </summary>
		virtual void DoListen();
		
		/// <summary> The method sets the client's event handlers. </summary>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a client
		///   connection. </param>
		/// <seealso cref="CwclServerClientConnection" />
		virtual void SetClientEvents(CwclServerClientConnection* const Client);
		
		/// <summary> Implements a hardware-dependent method for listening the client
		///   connections. </summary>
		/// <param name="Event"> The termination event handle. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement
		///   a hardware-dependent code for listening for incoming
		///   connections. </remarks>
		virtual int HalListen(const HANDLE Event) = 0;
		/// <summary> Implements a hardware-dependent method to stop
		///   listening. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The method is called only if the <c>HalListen</c> was
		///   success. </remarks>
		virtual int HalClose() = 0;
		/// <summary> The method creates a hardware and transport-dependent
		///   client connection. </summary>
		/// <returns> If the method success the return value is the object
		///   represents the client connection. Otherwise the method returns
		///   <c>NULL</c>. </returns>
		/// <remarks> A derived class must override this method to create a
		///   custom HAL server client connection. </remarks>
		/// <seealso cref="CwclServerClientConnection" />
		virtual CwclServerClientConnection* HalCreateClient() = 0;
		/// <summary> Implements a hardware-dependent code that prepares for
		///   listening. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement a
		///   hardware-dependent code that prepares the server connection. </remarks>
		virtual int HalPrepare() = 0;

	public:
		/// <summary> Creates a new server connection. </summary>
		CwclServerConnection();
		/// <summary> Frees the server connection. </summary>
		virtual ~CwclServerConnection();
		
		/// <summary> The method disconnects all connected clients and closes the
		///   server. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The method must be called from the same thread that called
		///   the <c>Listen</c> method. The method is not thread-safe. </remarks>
		int Close();
		/// <summary> The method starts listening for client connections. </summary>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int Listen();
		
		/// <summary> Gets a connected client by its index. </summary>
		/// <param name="Index"> Client's index. </param>
		/// <returns> The connected client. </returns>
		/// <seealso cref="CwclServerClientConnection" />
		CwclServerClientConnection* GetClients(const size_t Index) const;
		/// <summary> Gets a connected client by its index. </summary>
		/// <value> The connected client. </value>
		/// <seealso cref="CwclServerClientConnection" />
		__declspec(property(get = GetClients)) CwclServerClientConnection* Clients[];

		/// <summary> Gets the number of connected clients. </summary>
		/// <returns> The number of the connected clients. </returns>
		size_t GetClientsCount() const;
		/// <summary> Gets the number of connected clients. </summary>
		/// <value> The number of the connected clients. </value>
		__declspec(property(get = GetClientsCount)) size_t ClientsCount;
		
		/// <summary> Gets the connection state. </summary>
		/// <returns> The <see cref="wclServerState" /> indicates the current
		///   connection state. </returns>
		/// <seealso cref="wclServerState" />
		wclServerState GetState() const;
		/// <summary> Gets the connection state. </summary>
		/// <value> The <see cref="wclServerState" /> indicates the current
		///   connection state. </value>
		/// <seealso cref="wclServerState" />
		__declspec(property(get = GetState)) wclServerState State;
		
		/// <summary> The event fires when the server is closed. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		wclClientConnectionDisconnectEvent(OnClosed);
		/// <summary> The event fires when a remote client is connected to
		///   the server. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a remote
		///   connected client. </param>
		/// <param name="Error"> The connection operation result code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection to a remote
		///   device was established and the remote device is connected. Otherwise
		///   the connection was not established and the remote device is
		///   not connected. </param>
		/// <seealso cref="CwclServerClientConnection" />
		wclServerConnectionConnectEvent(OnConnect);
		/// <summary> The event fires when a remote client has disconnected from the
		///   server. </summary>
		/// <summary> The prototype of the <c>OnDisconnect</c> event handler for
		///   server connections. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a remote
		///   connected client. </param>
		/// <param name="Reason"> The disconnection code. If the
		///   parameter is <see cref="WCL_E_SUCCESS" /> the connection was closed
		///   by the <c>Disconnect</c> call. Otherwise indicates the disconnection
		///   reason. </param>
		/// <seealso cref="CwclServerClientConnection" />
		wclServerConnectionDisconnectEvent(OnDisconnect);
		/// <summary> The event fires when the server is ready to accept incoming
		///   connections (is in listening state). </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		wclNotifyEvent(OnListen);
	};

	// Forward declaration.
	class CwclServerDataConnection;
	class CwclCustomServerClientDataProcessor;

	/// <summary> The base class for the server client connection that
	///   requires data exchange with a remote device. </summary>
	/// <seealso cref="CwclServerClientConnection" />
	class CwclServerClientDataConnection : public CwclServerClientConnection
	{
		DISABLE_COPY(CwclServerClientDataConnection);

	private:
		friend class CwclCustomServerClientDataProcessor;

		CwclCustomServerClientDataProcessor*	FProcessor;

	protected:
		/// <summary> Send a data notification message. </summary>
		/// <param name="Data"> The data buffer contains received data. </param>
		/// <param name="Size"> The length of the received data. </param>
		void NotifyDataReceived(const void* const Data, const unsigned long Size);
		
		/// <summary> The message receiver calls this method when a new notification
		///   message has been received. </summary>
		/// <param name="Message"> A <see cref="CwclMessage" /> object
		///   represents the notification message. </param>
		/// <seealso cref="CwclMessage" />
		virtual void MessageReceived(const CwclMessage* const Message) override;
		
		/// <summary> The method accepts the client connection request. </summary>
		/// <param name="Server"> A <see cref="CwclServerConnection" />
		///   object owns the client connection. </param>
		/// <param name="Params"> An optional pointer to the hardware-dependent
		///   data contains information about client connection request. </param>
		/// <param name="ParamsSize"> An optional parameters size. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> <para> The method called by the server when connection from a
		///   remote client device has already been accepted. </para>
		///   <para> The method is always called from the main (or from the same)
		///   thread that runs the server. </para>
		///   <para> The method prepares the class for communication with a remote
		///   client. </para>
		///   <para> If the method fails it disconnects already accepted client
		///   connection. </para>
		///   <para> The <c>Server</c> parameter must be a
		///   <see cref="CwclServerDataConnection" />
		///    object. </para> </remarks>
		/// <seealso cref="CwclServerConnection" />
		/// <seealso cref="CwclServerDataConnection" />
		virtual int Accept(CwclServerConnection* const Server, const void* const Params,
			const unsigned long ParamsSize) override;
		
		/// <summary> Fires the <c>OnData</c> event. </summary>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		virtual void DoData(const void* const Data, const unsigned long Size);

		/// <summary> Reads the read buffer size. </summary>
		/// <param name="Size"> On output he read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size reading code. </remarks>
		virtual int HalGetReadBufferSize(unsigned long& Size) = 0;
		/// <summary> Reads the write buffer size. </summary>
		/// <param name="Size"> On output the write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size reading code. </remarks>
		virtual int HalGetWriteBufferSize(unsigned long& Size) = 0;

		/// <summary> Sets the read buffer size. </summary>
		/// <param name="Size"> The new read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size setting code. </remarks>
		virtual int HalSetReadBufferSize(const unsigned long Size) = 0;
		/// <summary> Sets the write buffer size. </summary>
		/// <param name="Size"> The new write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement the
		///  buffer size setting code. </remarks>
		virtual int HalSetWriteBufferSize(const unsigned long Size) = 0;

		/// <summary> Implements a hardware-dependent code that sends data to the
		///   connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement a
		///   hardware-dependent code that sends data to the connected device.
		///   The method executes in the main thread and must be
		///   synchronous. </remarks>
		virtual int HalWrite(const void* const Data, const unsigned long Size,
			unsigned long& Written) = 0;

	public:
		/// <summary> Creates a new server client data connection. </summary>
		CwclServerClientDataConnection();

		/// <summary> Reads the read buffer size. </summary>
		/// <param name="Size"> On output he read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int GetReadBufferSize(unsigned long& Size);
		/// <summary> Reads the write buffer size. </summary>
		/// <param name="Size"> On output the write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int GetWriteBufferSize(unsigned long& Size);

		/// <summary> Sets the read buffer size. </summary>
		/// <param name="Size"> The new read buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int SetReadBufferSize(const unsigned long Size);
		/// <summary> Sets the write buffer size. </summary>
		/// <param name="Size"> The new write buffer size in bytes. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int SetWriteBufferSize(const unsigned long Size);

		/// <summary> Sends data to the connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> The write is synchronous operation. </remarks>
		int Write(const void* const Data, const unsigned long Size,
			unsigned long& Written);

		/// <summary> Gets the current Data Processor object assigned to the
		///   Connection. </summary>
		/// <returns> The <see cref="CwclCustomServerClientDataProcessor" /> object
		///   used by the Connection to process data. </returns>
		/// <seealso cref="CwclCustomServerClientDataProcessor" />
		CwclCustomServerClientDataProcessor* GetProcessor() const;
		/// <summary> Gets the current Data Processor object assigned to the
		///   Connection. </summary>
		/// <value> The <see cref="CwclCustomServerClientDataProcessor" /> object
		///   used by the Connection to process data. </value>
		/// <seealso cref="CwclCustomServerClientDataProcessor" />
		__declspec(property(get = GetProcessor)) CwclCustomServerClientDataProcessor* Processor;

		/// <summary> The event fires when new data is received from the
		///   connected remote device. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		wclConnectionDataEvent(OnData);
	};

	/// <summary> The server's <c>OnData</c> event handler prototype. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Client"> A
	///   <see cref="CwclServerClientDataConnection" /> object
	///   represents a remote client connection. </param>
	/// <param name="Data"> The pointer to the received data buffer.
	///   It is guaranteed that the parameter points to a valid data buffer.
	///   The data buffer is valid only inside the event handler. If an
	///   application needs to use the data outside the event handle it must
	///   allocate own buffer and copy data into it. </param>
	/// <param name="Size"> The data buffer size. It is guaranteed that the size
	///   is greater than 0. </param>
	/// <seealso cref="CwclServerClientDataConnection" />
	#define wclServerConnectionDataEvent(_event_name_) \
		__event void _event_name_(void* Sender, CwclServerClientDataConnection* const Client, \
		const void* const Data, const unsigned long Size)

	/// <summary> The base class for the server connection that
	///   requires data exchange with a remote device. </summary>
	/// <seealso cref="CwclServerConnection" />
	class CwclServerDataConnection : public CwclServerConnection
	{
		DISABLE_COPY(CwclServerDataConnection);

	private:
		void ClientData(void* Sender, const void* const Data, const unsigned long Size);
		
	protected:
		/// <summary> Unhooks events from the client that should be deleted. </summary>
		virtual void UnhookDeletedClientEvents(CwclServerClientConnection* const Client) override;

		/// <summary> The method sets the client's event handlers. </summary>
		/// <param name="Client"> The
		///   <see cref="CwclServerClientConnection" /> represents a client
		///   connection. </param>
		/// <seealso cref="CwclServerClientConnection" />
		virtual void SetClientEvents(CwclServerClientConnection* const Client) override;
		
		/// <summary> Fires the <c>OnData</c> event. </summary>
		/// <param name="Client"> A
		///   <see cref="CwclServerClientDataConnection" /> object
		///   represents a remote client connection. </param>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		/// <seealso cref="CwclServerClientDataConnection" />
		virtual void DoData(CwclServerClientDataConnection* const Client, const void* const Data,
			const unsigned long Size);
		
	public:
		/// <summary> Creates a new client data connection. </summary>
		CwclServerDataConnection();
		
		/// <summary> The event fires when new data is received from the
		///   connected remote device. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Client"> A
		///   <see cref="CwclServerClientDataConnection" /> object
		///   represents a remote client connection. </param>
		/// <param name="Data"> The pointer to the received data buffer.
		///   It is guaranteed that the parameter points to a valid data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the event handle it must
		///   allocate own buffer and copy data into it. </param>
		/// <param name="Size"> The data buffer size. It is guaranteed that the size
		///   is greater than 0. </param>
		/// <seealso cref="CwclServerClientDataConnection" />
		wclServerConnectionDataEvent(OnData);
	};

	class CwclCustomDataProcessor;

	/// <summary> The <see cref="CwclCustomDataProcessor" /> <c>OnWrite</c> event
	///   handler prototype. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Data"> The pointer to the data buffer that a Data Processor
	///   needs to send to a connection. </param>
	/// <param name="Size"> The data buffer size. </param>
	/// <param name="Written"> The amount of bytes actually written to the
	///   device. </param>
	/// <param name="WriteResult"> The write operation result. </param>
	/// <seealso cref="CwclCustomDataProcessor" />
	#define wclDataProcessorWriteEvent(_event_name_) \
		__event void _event_name_(void* Sender, const void* const Data, \
		const unsigned long Size, unsigned long& Written, int& WriteResult)

	/// <summary> The base class for all WCL Data Processors. </summary>
	/// <remarks> The Data Processor is a class the allows to add additional
	///   data processing for Connections. </remarks>
	class CwclCustomDataProcessor
	{
		DISABLE_COPY(CwclCustomDataProcessor);

	protected:
		/// <summary> Fires the <c>OnWrite</c> event. </summary>
		/// <param name="Data"> The pointer to the data buffer that a Data Processor
		///   needs to send to a connection. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <param name="WriteResult"> The write operation result. </param>
		virtual void DoWrite(const void* const Data, const unsigned long Size,
			unsigned long& Written, int& WriteResult);

		/// <summary> Implements a connection-dependent code that sends data to the
		///   connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		/// <remarks> A derived class must override this method to implement a
		///   connection-dependent code that sends data to the connected
		///   device. </remarks>
		virtual int WriteData(const void* const Data, const unsigned long Size,
			unsigned long& Written) = 0;
		
		/// <summary> Sends data to the connected device. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		int Write(const void* const Data, const unsigned long Size);

	public:
		/// <summary> Creates new Data Processor object. </summary>
		CwclCustomDataProcessor();
		/// <summary> Frees the Data Processor object. </summary>
		virtual ~CwclCustomDataProcessor();

		/// <summary> The method called by the Connection when data has been
		///   received from a remote device. </summary>
		/// <param name="Data"> The pointer to the received data buffer.
		///   The data buffer is valid only inside the event handler. If an
		///   application needs to use the data outside the method it must
		///   allocate own buffer and copy data. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <remarks> <para> A derived classes must override this method to process
		///   the received data. </para>
		///   <para> The <c>Data</c> parameter is valid only inside the
		///   procedure. If a derived class needs to use data outside the method it
		///   must copy the data into internal buffer. </para> </remarks>
		virtual void ProcessData(const void* const Data, const unsigned long Size) = 0;

		/// <summary> The event fires when the Data Processor needs to write data
		///   to a connection but a connection is not assigned. </summary>
		/// <param name="Sender"> The object that initiated the event. </param>
		/// <param name="Data"> The pointer to the data buffer that a Data Processor
		///   needs to send to a connection. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <param name="WriteResult"> The write operation result. </param>
		wclDataProcessorWriteEvent(OnWrite);
	};

	/// <summary> The base class for all WCL Client Data Processors. </summary>
	/// <remarks> The Client Data Processor allows to add additional data
	///   processing for the Client Data Connections. </remarks>
	/// <seealso cref="CwclCustomDataProcessor" />
	/// <seealso cref="CwclClientDataConnection" />
	class CwclCustomClientDataProcessor : public CwclCustomDataProcessor
	{
		DISABLE_COPY(CwclCustomClientDataProcessor);

	private:
		friend class CwclClientDataConnection;

		CwclClientDataConnection*	FConnection;
		bool						FConnectionSet;
		
	protected:
		/// <summary> Writes data to the Client Connection. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		virtual int WriteData(const void* const Data, const unsigned long Size,
			unsigned long& Written) override;
		
	public:
		/// <summary> Creates new Client Data Processor. </summary>
		/// <param name="Connection"> A <see cref="CwclClientDataConnection" />
		///   object that is used to communicate with a remote device. </param>
		/// <seealso cref="CwclClientDataConnection" />
		CwclCustomClientDataProcessor(CwclClientDataConnection* const Connection);
		/// <summary> Frees the Data Processor. </summary>
		virtual ~CwclCustomClientDataProcessor();
		
		/// <summary> Gets the connection object used to communicate with a remote
		///   device. </summary>
		/// <returns> The <see cref="CwclClientDataConnection" /> object. </returns>
		/// <seealso cref="CwclClientDataConnection" />
		CwclClientDataConnection* GetConnection() const;
		__declspec(property(get = GetConnection)) CwclClientDataConnection* Connection;
	};

	/// <summary> The Data Client Component's event handler prototype for
	///   <c>OnCreateProcessor</c> and <c>OnDestroyProcessor</c>
	///   events. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The <see cref="CwclClientDataConnection" />
	///   object that requires a Data Processor. </param>
	/// <seealso cref="CwclClientDataConnection" />
	/// <seealso cref="CwclCustomClientDataProcessor" />
	#define wclClientConnectionProcessorEvent(_event_name_) \
		__event void _event_name_(void* Sender, CwclClientDataConnection* const Connection)

	/// <summary> The base class for all WCL Server Client Data
	///   Processors. </summary>
	/// <remarks> The Server Client Data Processor allows to add additional data
	///   processing for the Server Client Data Connections. </remarks>
	/// <seealso cref="CwclCustomDataProcessor" />
	/// <seealso cref="CwclServerClientDataConnection" />
	class CwclCustomServerClientDataProcessor : public CwclCustomDataProcessor
	{
		DISABLE_COPY(CwclCustomServerClientDataProcessor);

	private:
		friend class CwclServerClientDataConnection;

		CwclServerClientDataConnection*	FConnection;
		bool							FConnectionSet;
		
	protected:
		/// <summary> Writes data to the Connection. </summary>
		/// <param name="Data"> The pointer to the data buffer that should be sent
		///   to the connected device. </param>
		/// <param name="Size"> The data buffer size. </param>
		/// <param name="Written"> The amount of bytes actually written to the
		///   device. </param>
		/// <returns> If the function succeed the return value is
		///   <see cref="WCL_E_SUCCESS" />. Otherwise the method returns one of
		///   the WCL error codes. </returns>
		virtual int WriteData(const void* const Data, const unsigned long Size,
			unsigned long& Written) override;
		
	public:
		/// <summary> Creates new Client Data Processor. </summary>
		/// <param name="Connection"> A
		///   <see cref="CwclServerClientDataConnection" /> object that is used to
		///   communicate with a remote device. </param>
		/// <seealso cref="CwclServerClientDataConnection" />
		CwclCustomServerClientDataProcessor(CwclServerClientDataConnection* const Connection);
		/// <summary> Frees the Data Processor. </summary>
		virtual ~CwclCustomServerClientDataProcessor();
		
		/// <summary> Gets the connection object used to communicate with a remote
		///   device. </summary>
		/// <returns> The <see cref="CwclServerClientDataConnection" />
		///   object. </returns>
		/// <seealso cref="CwclServerClientDataConnection" />
		CwclServerClientDataConnection* GetConnection() const;
		__declspec(property(get = GetConnection)) CwclServerClientDataConnection* Connection;
	};

	/// <summary> The Data Server Component's event handler prototype for
	///   <c>OnCreateProcessor</c> and <c>OnDestroyProcessor</c>
	///   events. </summary>
	/// <param name="Sender"> The object that initiated the event. </param>
	/// <param name="Connection"> The
	///   <see cref="CwclServerClientDataConnection" /> object that requires a
	///   Data Processor. </param>
	/// <seealso cref="CwclServerDataConnection" />
	/// <seealso cref="CwclServerClientDataConnection" />
	#define wclServerConnectionProcessorEvent(_event_name_) \
		__event void _event_name_(void* Sender, CwclServerClientDataConnection* const Connection)
}