summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHalil İbrahim Kalkan <hi_kalkan@yahoo.com>2013-04-08 21:44:58 +0300
committerHalil İbrahim Kalkan <hi_kalkan@yahoo.com>2013-04-08 21:44:58 +0300
commit79953cb56cda204f190ffcd9995b27ebea25e62d (patch)
treede939755c2e32eaa5fa3e41e21114e1c727ed0a4
parent934c543eb6b0bd7173038e45a7dac0241d091da4 (diff)
downloadscs-79953cb56cda204f190ffcd9995b27ebea25e62d.zip
scs-79953cb56cda204f190ffcd9995b27ebea25e62d.tar.gz
scs-79953cb56cda204f190ffcd9995b27ebea25e62d.tar.bz2
Adding to github
Adding to github
-rw-r--r--binaries/Scs.XML2697
-rw-r--r--binaries/Scs.dllbin0 -> 49664 bytes
-rw-r--r--performance-tests/Messaging/ClientApp/ClientApp.csproj73
-rw-r--r--performance-tests/Messaging/ClientApp/DuplexClientCustomProtocol.cs52
-rw-r--r--performance-tests/Messaging/ClientApp/DuplexClientCustomProtocolSynchronized.cs37
-rw-r--r--performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocol.cs51
-rw-r--r--performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocolSynchronized.cs36
-rw-r--r--performance-tests/Messaging/ClientApp/OneWayClientCustomProtocol.cs32
-rw-r--r--performance-tests/Messaging/ClientApp/OneWayClientDefaultProtocol.cs30
-rw-r--r--performance-tests/Messaging/ClientApp/Program.cs10
-rw-r--r--performance-tests/Messaging/ClientApp/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/Messaging/CommonLib/CommonLib.csproj60
-rw-r--r--performance-tests/Messaging/CommonLib/Consts.cs12
-rw-r--r--performance-tests/Messaging/CommonLib/MyWireProtocol.cs32
-rw-r--r--performance-tests/Messaging/CommonLib/MyWireProtocolFactory.cs12
-rw-r--r--performance-tests/Messaging/CommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/Messaging/ServerApp.sln54
-rw-r--r--performance-tests/Messaging/ServerApp/DuplexServerCustomProtocol.cs53
-rw-r--r--performance-tests/Messaging/ServerApp/DuplexServerDefaultProtocol.cs51
-rw-r--r--performance-tests/Messaging/ServerApp/OneWayServerCustomProtocol.cs49
-rw-r--r--performance-tests/Messaging/ServerApp/OneWayServerDefaultProtocol.cs47
-rw-r--r--performance-tests/Messaging/ServerApp/Program.cs10
-rw-r--r--performance-tests/Messaging/ServerApp/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/Messaging/ServerApp/ServerApp.csproj71
-rw-r--r--performance-tests/RMI/CalculatorClient/CalculatorClient.csproj67
-rw-r--r--performance-tests/RMI/CalculatorClient/Program.cs34
-rw-r--r--performance-tests/RMI/CalculatorClient/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/RMI/CalculatorCommonLib/CalculatorCommonLib.csproj59
-rw-r--r--performance-tests/RMI/CalculatorCommonLib/Consts.cs12
-rw-r--r--performance-tests/RMI/CalculatorCommonLib/ICalculatorService.cs15
-rw-r--r--performance-tests/RMI/CalculatorCommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/RMI/CalculatorServer/CalculatorServer.csproj67
-rw-r--r--performance-tests/RMI/CalculatorServer/Program.cs46
-rw-r--r--performance-tests/RMI/CalculatorServer/Properties/AssemblyInfo.cs36
-rw-r--r--performance-tests/RMI/SimpleCalculatorSystem.sln54
-rw-r--r--samples/CustomWireProtocol/ClientApp/ClientApp.csproj67
-rw-r--r--samples/CustomWireProtocol/ClientApp/Program.cs32
-rw-r--r--samples/CustomWireProtocol/ClientApp/Properties/AssemblyInfo.cs36
-rw-r--r--samples/CustomWireProtocol/CommonLib/CommonLib.csproj59
-rw-r--r--samples/CustomWireProtocol/CommonLib/MyWireProtocol.cs32
-rw-r--r--samples/CustomWireProtocol/CommonLib/MyWireProtocolFactory.cs12
-rw-r--r--samples/CustomWireProtocol/CommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--samples/CustomWireProtocol/ServerApp.sln54
-rw-r--r--samples/CustomWireProtocol/ServerApp/Program.cs41
-rw-r--r--samples/CustomWireProtocol/ServerApp/Properties/AssemblyInfo.cs36
-rw-r--r--samples/CustomWireProtocol/ServerApp/ServerApp.csproj67
-rw-r--r--samples/IrcChatSystem/ChatClientApp/ChatClientApp.csproj178
-rw-r--r--samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml16
-rw-r--r--samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml.cs26
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs103
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs155
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs93
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs41
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs60
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs26
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs140
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs109
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Controls/IMessagingAreaContainer.xaml.cs16
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml61
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml.cs469
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml55
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml.cs116
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/app_icon.icobin0 -> 15086 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/sound_off.pngbin0 -> 3138 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/sound_on.pngbin0 -> 2896 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/text_color_picker.icobin0 -> 1150 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/user_female.pngbin0 -> 11495 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Images/user_male.pngbin0 -> 8026 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Properties/AssemblyInfo.cs55
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Properties/Resources.Designer.cs63
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Properties/Resources.resx117
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Properties/Settings.Designer.cs26
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Properties/Settings.settings7
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Sounds/incoming_message.wavbin0 -> 60246 bytes
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml89
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml.cs699
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml29
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml.cs190
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml25
-rw-r--r--samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml.cs47
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/ChatCommonLib.csproj67
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/ChatMessage.cs51
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/MessageTextStyle.cs71
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserInfo.cs27
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserStatus.cs23
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatClient.cs56
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatService.cs49
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/IrcChat/Exceptions/NickInUseException.cs40
-rw-r--r--samples/IrcChatSystem/ChatCommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--samples/IrcChatSystem/ChatServerApp/App.xaml8
-rw-r--r--samples/IrcChatSystem/ChatServerApp/App.xaml.cs16
-rw-r--r--samples/IrcChatSystem/ChatServerApp/ChatServerApp.csproj123
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Images/app_icon.icobin0 -> 15086 bytes
-rw-r--r--samples/IrcChatSystem/ChatServerApp/IrcChat/Server/ChatService.cs385
-rw-r--r--samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml50
-rw-r--r--samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml.cs119
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Properties/AssemblyInfo.cs55
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Properties/Resources.Designer.cs63
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Properties/Resources.resx117
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Properties/Settings.Designer.cs26
-rw-r--r--samples/IrcChatSystem/ChatServerApp/Properties/Settings.settings7
-rw-r--r--samples/IrcChatSystem/ChatServerApp/app_icon.icobin0 -> 15086 bytes
-rw-r--r--samples/IrcChatSystem/IrcChatSystem.sln54
-rw-r--r--samples/OnlinePhoneBook/OnlinePhoneBook.sln66
-rw-r--r--samples/OnlinePhoneBook/PhoneBookClient/PhoneBookClient.csproj67
-rw-r--r--samples/OnlinePhoneBook/PhoneBookClient/Program.cs52
-rw-r--r--samples/OnlinePhoneBook/PhoneBookClient/Properties/AssemblyInfo.cs36
-rw-r--r--samples/OnlinePhoneBook/PhoneBookCommonLib/IPhoneBookService.cs33
-rw-r--r--samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookCommonLib.csproj59
-rw-r--r--samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookRecord.cs43
-rw-r--r--samples/OnlinePhoneBook/PhoneBookCommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--samples/OnlinePhoneBook/PhoneBookServer/PhoneBookServer.csproj68
-rw-r--r--samples/OnlinePhoneBook/PhoneBookServer/PhoneBookService.cs86
-rw-r--r--samples/OnlinePhoneBook/PhoneBookServer/Program.cs32
-rw-r--r--samples/OnlinePhoneBook/PhoneBookServer/Properties/AssemblyInfo.cs36
-rw-r--r--samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Program.cs27
-rw-r--r--samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Properties/AssemblyInfo.cs36
-rw-r--r--samples/OnlinePhoneBook/SimlifiedPhoneBookClient/SimlifiedPhoneBookClient.csproj66
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorClient/CalculatorClient.csproj67
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorClient/Program.cs33
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorClient/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorCommonLib/CalculatorCommonLib.csproj58
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorCommonLib/ICalculatorService.cs15
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorCommonLib/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorServer/CalculatorServer.csproj67
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorServer/Program.cs46
-rw-r--r--samples/SimpleCalculatorSystem/CalculatorServer/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleCalculatorSystem/SimpleCalculatorSystem.sln54
-rw-r--r--samples/SimpleMessaging/ClientApp/ClientApp.csproj61
-rw-r--r--samples/SimpleMessaging/ClientApp/Program.cs51
-rw-r--r--samples/SimpleMessaging/ClientApp/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleMessaging/RequestReplyStyleClient/Program.cs43
-rw-r--r--samples/SimpleMessaging/RequestReplyStyleClient/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleMessaging/RequestReplyStyleClient/RequestReplyStyleClient.csproj61
-rw-r--r--samples/SimpleMessaging/ServerApp/Program.cs66
-rw-r--r--samples/SimpleMessaging/ServerApp/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleMessaging/ServerApp/ServerApp.csproj61
-rw-r--r--samples/SimpleMessaging/SimpleMessaging.sln66
-rw-r--r--samples/SimpleMessaging/SynchronizedClient/Program.cs46
-rw-r--r--samples/SimpleMessaging/SynchronizedClient/Properties/AssemblyInfo.cs36
-rw-r--r--samples/SimpleMessaging/SynchronizedClient/SynchronizedClient.csproj60
-rw-r--r--src/Scs.sln30
-rw-r--r--src/Scs/Changes.txt37
-rw-r--r--src/Scs/Collections/ThreadSafeSortedList.cs197
-rw-r--r--src/Scs/Communication/Scs/Client/ClientReConnecter.cs109
-rw-r--r--src/Scs/Communication/Scs/Client/IConnectableClient.cs43
-rw-r--r--src/Scs/Communication/Scs/Client/IScsClient.cs13
-rw-r--r--src/Scs/Communication/Scs/Client/ScsClientBase.cs330
-rw-r--r--src/Scs/Communication/Scs/Client/ScsClientFactory.cs30
-rw-r--r--src/Scs/Communication/Scs/Client/Tcp/ScsTcpClient.cs40
-rw-r--r--src/Scs/Communication/Scs/Client/Tcp/TcpHelper.cs49
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelBase.cs176
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelEventArgs.cs24
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/ConnectionListenerBase.cs38
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/ICommunicationChannel.cs38
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/IConnectionListener.cs26
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpCommunicationChannel.cs210
-rw-r--r--src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpConnectionListener.cs124
-rw-r--r--src/Scs/Communication/Scs/Communication/CommunicationException.cs50
-rw-r--r--src/Scs/Communication/Scs/Communication/CommunicationStateException.cs50
-rw-r--r--src/Scs/Communication/Scs/Communication/CommunicationStates.cs18
-rw-r--r--src/Scs/Communication/Scs/Communication/EndPoints/ScsEndPoint.cs67
-rw-r--r--src/Scs/Communication/Scs/Communication/EndPoints/Tcp/ScsTcpEndPoint.cs84
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/IScsMessage.cs18
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/MessageEventArgs.cs24
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/PingMessage.cs44
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/ScsMessage.cs59
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/ScsRawDataMessage.cs59
-rw-r--r--src/Scs/Communication/Scs/Communication/Messages/ScsTextMessage.cs58
-rw-r--r--src/Scs/Communication/Scs/Communication/Messengers/IMessenger.cs44
-rw-r--r--src/Scs/Communication/Scs/Communication/Messengers/RequestReplyMessenger.cs387
-rw-r--r--src/Scs/Communication/Scs/Communication/Messengers/SynchronizedMessenger.cs216
-rw-r--r--src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocol.cs315
-rw-r--r--src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocolFactory.cs17
-rw-r--r--src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocol.cs39
-rw-r--r--src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocolFactory.cs14
-rw-r--r--src/Scs/Communication/Scs/Communication/Protocols/WireProtocolManager.cs28
-rw-r--r--src/Scs/Communication/Scs/Server/IScsServer.cs42
-rw-r--r--src/Scs/Communication/Scs/Server/IScsServerClient.cs38
-rw-r--r--src/Scs/Communication/Scs/Server/ScsServerBase.cs168
-rw-r--r--src/Scs/Communication/Scs/Server/ScsServerClient.cs223
-rw-r--r--src/Scs/Communication/Scs/Server/ScsServerFactory.cs20
-rw-r--r--src/Scs/Communication/Scs/Server/ScsServerManager.cs24
-rw-r--r--src/Scs/Communication/Scs/Server/ServerClientEventArgs.cs24
-rw-r--r--src/Scs/Communication/Scs/Server/Tcp/ScsTcpServer.cs35
-rw-r--r--src/Scs/Communication/ScsServices/Client/IScsServiceClient.cs24
-rw-r--r--src/Scs/Communication/ScsServices/Client/ScsServiceClient.cs274
-rw-r--r--src/Scs/Communication/ScsServices/Client/ScsServiceClientBuilder.cs36
-rw-r--r--src/Scs/Communication/ScsServices/Communication/AutoConnectRemoteInvokeProxy.cs57
-rw-r--r--src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteException.cs51
-rw-r--r--src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeMessage.cs36
-rw-r--r--src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeReturnMessage.cs33
-rw-r--r--src/Scs/Communication/ScsServices/Communication/RemoteInvokeProxy.cs63
-rw-r--r--src/Scs/Communication/ScsServices/Service/IScsServiceApplication.cs49
-rw-r--r--src/Scs/Communication/ScsServices/Service/IScsServiceClient.cs44
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsService.cs43
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsServiceApplication.cs370
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsServiceAttribute.cs26
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsServiceBuilder.cs21
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsServiceClient.cs146
-rw-r--r--src/Scs/Communication/ScsServices/Service/ScsServiceClientFactory.cs23
-rw-r--r--src/Scs/Communication/ScsServices/Service/ServiceClientEventArgs.cs24
-rw-r--r--src/Scs/Diagrams/ChannelsDiagram.cd37
-rw-r--r--src/Scs/Diagrams/ConnListenerDiagram.cd30
-rw-r--r--src/Scs/Diagrams/EndPointsDiagram.cd24
-rw-r--r--src/Scs/Diagrams/MessageObjectsDiagram.cd40
-rw-r--r--src/Scs/Diagrams/RequestReplyMessengerDiagram.cd47
-rw-r--r--src/Scs/Diagrams/RmiMessagesDiagram.cd35
-rw-r--r--src/Scs/Diagrams/ScsClientDiagram.cd45
-rw-r--r--src/Scs/Diagrams/ScsServerClientDiagram.cd26
-rw-r--r--src/Scs/Diagrams/ScsServerDiagram.cd26
-rw-r--r--src/Scs/Diagrams/ScsServiceClientDiagram.cd26
-rw-r--r--src/Scs/Diagrams/ScsServiceDiagram.cd26
-rw-r--r--src/Scs/Diagrams/ServiceSideClientDiagram.cd19
-rw-r--r--src/Scs/Diagrams/WireProtocolsDiagram.cd41
-rw-r--r--src/Scs/Properties/AssemblyInfo.cs36
-rw-r--r--src/Scs/Scs.csproj135
-rw-r--r--src/Scs/Threading/SequentialItemProcessor.cs172
-rw-r--r--src/Scs/Threading/Timer.cs167
219 files changed, 16746 insertions, 0 deletions
diff --git a/binaries/Scs.XML b/binaries/Scs.XML
new file mode 100644
index 0000000..4ad5e46
--- /dev/null
+++ b/binaries/Scs.XML
@@ -0,0 +1,2697 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>Scs</name>
+ </assembly>
+ <members>
+ <member name="T:Hik.Communication.Scs.Server.IScsServer">
+ <summary>
+ Represents a SCS server that is used to accept and manage client connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.IScsServer.Start">
+ <summary>
+ Starts the server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.IScsServer.Stop">
+ <summary>
+ Stops the server.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.IScsServer.ClientConnected">
+ <summary>
+ This event is raised when a new client connected to the server.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.IScsServer.ClientDisconnected">
+ <summary>
+ This event is raised when a client disconnected from the server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.IScsServer.WireProtocolFactory">
+ <summary>
+ Gets/sets wire protocol factory to create IWireProtocol objects.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.IScsServer.Clients">
+ <summary>
+ A collection of clients that are connected to the server.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.IScsClient">
+ <summary>
+ Represents a client to connect to server.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messengers.IMessenger">
+ <summary>
+ Represents an object that can send and receive messages.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.IMessenger.SendMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the remote application.
+ </summary>
+ <param name="message">Message to be sent</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Messengers.IMessenger.MessageReceived">
+ <summary>
+ This event is raised when a new message is received.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Messengers.IMessenger.MessageSent">
+ <summary>
+ This event is raised when a new message is sent without any error.
+ It does not guaranties that message is properly handled and processed by remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.IMessenger.WireProtocol">
+ <summary>
+ Gets/sets wire protocol that is used while reading and writing messages.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.IMessenger.LastReceivedMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.IMessenger.LastSentMessageTime">
+ <summary>
+ Gets the time of the last succesfully sent message.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.IConnectableClient">
+ <summary>
+ Represents a client for SCS servers.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.IConnectableClient.Connect">
+ <summary>
+ Connects to server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.IConnectableClient.Disconnect">
+ <summary>
+ Disconnects from server.
+ Does nothing if already disconnected.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.IConnectableClient.Connected">
+ <summary>
+ This event is raised when client connected to server.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.IConnectableClient.Disconnected">
+ <summary>
+ This event is raised when client disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.IConnectableClient.ConnectTimeout">
+ <summary>
+ Timeout for connecting to a server (as milliseconds).
+ Default value: 15 seconds (15000 ms).
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.IConnectableClient.CommunicationState">
+ <summary>
+ Gets the current communication state.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Communication.AutoConnectRemoteInvokeProxy`2">
+ <summary>
+ This class extends RemoteInvokeProxy to provide auto connect/disconnect mechanism
+ if client is not connected to the server when a service method is called.
+ </summary>
+ <typeparam name="TProxy">Type of the proxy class/interface</typeparam>
+ <typeparam name="TMessenger">Type of the messenger object that is used to send/receive messages</typeparam>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Communication.RemoteInvokeProxy`2">
+ <summary>
+ This class is used to generate a dynamic proxy to invoke remote methods.
+ It translates method invocations to messaging.
+ </summary>
+ <typeparam name="TProxy">Type of the proxy class/interface</typeparam>
+ <typeparam name="TMessenger">Type of the messenger object that is used to send/receive messages</typeparam>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Communication.RemoteInvokeProxy`2._clientMessenger">
+ <summary>
+ Messenger object that is used to send/receive messages.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.RemoteInvokeProxy`2.#ctor(Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger{`1})">
+ <summary>
+ Creates a new RemoteInvokeProxy object.
+ </summary>
+ <param name="clientMessenger">Messenger object that is used to send/receive messages</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.RemoteInvokeProxy`2.Invoke(System.Runtime.Remoting.Messaging.IMessage)">
+ <summary>
+ Overrides message calls and translates them to messages to remote application.
+ </summary>
+ <param name="msg">Method invoke message (from RealProxy base class)</param>
+ <returns>Method invoke return message (to RealProxy base class)</returns>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Communication.AutoConnectRemoteInvokeProxy`2._client">
+ <summary>
+ Reference to the client object that is used to connect/disconnect.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.AutoConnectRemoteInvokeProxy`2.#ctor(Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger{`1},Hik.Communication.Scs.Client.IConnectableClient)">
+ <summary>
+ Creates a new AutoConnectRemoteInvokeProxy object.
+ </summary>
+ <param name="clientMessenger">Messenger object that is used to send/receive messages</param>
+ <param name="client">Reference to the client object that is used to connect/disconnect</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.AutoConnectRemoteInvokeProxy`2.Invoke(System.Runtime.Remoting.Messaging.IMessage)">
+ <summary>
+ Overrides message calls and translates them to messages to remote application.
+ </summary>
+ <param name="msg">Method invoke message (from RealProxy base class)</param>
+ <returns>Method invoke return message (to RealProxy base class)</returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel">
+ <summary>
+ This class is used to communicate with a remote application over TCP/IP protocol.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase">
+ <summary>
+ This class provides base functionality for all communication channel classes.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel">
+ <summary>
+ Represents a communication channel.
+ A communication channel is used to communicate (send/receive messages) with a remote application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel.Start">
+ <summary>
+ Starts the communication with remote application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel.Disconnect">
+ <summary>
+ Closes messenger.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel.Disconnected">
+ <summary>
+ This event is raised when client disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.ICommunicationChannel.CommunicationState">
+ <summary>
+ Gets the current communication state.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.#ctor">
+ <summary>
+ Constructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.Disconnect">
+ <summary>
+ Disconnects from remote application and closes this channel.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.Start">
+ <summary>
+ Starts the communication with remote application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.SendMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the remote application.
+ </summary>
+ <param name="message">Message to be sent</param>
+ <exception cref="T:System.ArgumentNullException">Throws ArgumentNullException if message is null</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.StartInternal">
+ <summary>
+ Starts the communication with remote application really.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.SendMessageInternal(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the remote application.
+ This method is overrided by derived classes to really send to message.
+ </summary>
+ <param name="message">Message to be sent</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.OnDisconnected">
+ <summary>
+ Raises Disconnected event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.OnMessageReceived(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageReceived event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.OnMessageSent(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageSent event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.MessageReceived">
+ <summary>
+ This event is raised when a new message is received.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.MessageSent">
+ <summary>
+ This event is raised when a new message is sent without any error.
+ It does not guaranties that message is properly handled and processed by remote application.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.Disconnected">
+ <summary>
+ This event is raised when communication channel closed.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.CommunicationState">
+ <summary>
+ Gets the current communication state.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.LastReceivedMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.LastSentMessageTime">
+ <summary>
+ Gets the time of the last succesfully sent message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase.WireProtocol">
+ <summary>
+ Gets/sets wire protocol that the channel uses.
+ This property must set before first communication.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.ReceiveBufferSize">
+ <summary>
+ Size of the buffer that is used to receive bytes from TCP socket.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel._buffer">
+ <summary>
+ This buffer is used to receive bytes
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel._clientSocket">
+ <summary>
+ Socket object to send/reveice messages.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel._running">
+ <summary>
+ A flag to control thread's running
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel._syncLock">
+ <summary>
+ This object is just used for thread synchronizing (locking).
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.#ctor(System.Net.Sockets.Socket)">
+ <summary>
+ Creates a new TcpCommunicationChannel object.
+ </summary>
+ <param name="clientSocket">A connected Socket object that is
+ used to communicate over network</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.Disconnect">
+ <summary>
+ Disconnects from remote application and closes channel.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.StartInternal">
+ <summary>
+ Starts the thread to receive messages from socket.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.SendMessageInternal(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the remote application.
+ </summary>
+ <param name="message">Message to be sent</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.ReceiveCallback(System.IAsyncResult)">
+ <summary>
+ This method is used as callback method in _clientSocket's BeginReceive method.
+ It reveives bytes from socker.
+ </summary>
+ <param name="ar">Asyncronous call result</param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel.RemoteEndPoint">
+ <summary>
+ Gets the endpoint of remote application.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsService">
+ <summary>
+ Base class for all services that is serviced by IScsServiceApplication.
+ A class must be derived from ScsService to serve as a SCS service.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsService._currentClient">
+ <summary>
+ The current client for a thread that called service method.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsService.CurrentClient">
+ <summary>
+ Gets the current client which called this service method.
+ </summary>
+ <remarks>
+ This property is thread-safe, if returns correct client when
+ called in a service method if the method is called by SCS system,
+ else throws exception.
+ </remarks>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.CommunicationChannelEventArgs">
+ <summary>
+ Stores communication channel information to be used by an event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.CommunicationChannelEventArgs.#ctor(Hik.Communication.Scs.Communication.Channels.ICommunicationChannel)">
+ <summary>
+ Creates a new CommunicationChannelEventArgs object.
+ </summary>
+ <param name="channel">Communication channel that is associated with this event</param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Channels.CommunicationChannelEventArgs.Channel">
+ <summary>
+ Communication channel that is associated with this event.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.ScsClientFactory">
+ <summary>
+ This class is used to create SCS Clients to connect to a SCS server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientFactory.CreateClient(Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint)">
+ <summary>
+ Creates a new client to connect to a server using an end point.
+ </summary>
+ <param name="endpoint">End point of the server to connect it</param>
+ <returns>Created TCP client</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientFactory.CreateClient(System.String)">
+ <summary>
+ Creates a new client to connect to a server using an end point.
+ </summary>
+ <param name="endpointAddress">End point address of the server to connect it</param>
+ <returns>Created TCP client</returns>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage">
+ <summary>
+ This message is sent to invoke a method of a remote application.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.ScsMessage">
+ <summary>
+ Represents a message that is sent and received by server and client.
+ This is the base class for all messages.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.IScsMessage">
+ <summary>
+ Represents a message that is sent and received by server and client.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.IScsMessage.MessageId">
+ <summary>
+ Unique identified for this message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.IScsMessage.RepliedMessageId">
+ <summary>
+ Unique identified for this message.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsMessage.#ctor">
+ <summary>
+ Creates a new ScsMessage.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsMessage.#ctor(System.String)">
+ <summary>
+ Creates a new reply ScsMessage.
+ </summary>
+ <param name="repliedMessageId">
+ Replied message id if this is a reply for
+ a message.
+ </param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsMessage.ToString">
+ <summary>
+ Creates a string to represents this object.
+ </summary>
+ <returns>A string to represents this object</returns>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.ScsMessage.MessageId">
+ <summary>
+ Unique identified for this message.
+ Default value: New GUID.
+ Do not change if you do not want to do low level changes
+ such as custom wire protocols.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.ScsMessage.RepliedMessageId">
+ <summary>
+ This property is used to indicate that this is
+ a Reply message to a message.
+ It may be null if this is not a reply message.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage.ToString">
+ <summary>
+ Represents this object as string.
+ </summary>
+ <returns>String representation of this object</returns>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage.ServiceClassName">
+ <summary>
+ Name of the remove service class.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage.MethodName">
+ <summary>
+ Method of remote application to invoke.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage.Parameters">
+ <summary>
+ Parameters of method.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Client.IScsServiceClient`1">
+ <summary>
+ Represents a service client that consumes a SCS service.
+ </summary>
+ <typeparam name="T">Type of service interface</typeparam>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.IScsServiceClient`1.ServiceProxy">
+ <summary>
+ Reference to the service proxy to invoke remote service methods.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.IScsServiceClient`1.Timeout">
+ <summary>
+ Timeout value when invoking a service method.
+ If timeout occurs before end of remote method call, an exception is thrown.
+ Use -1 for no timeout (wait indefinite).
+ Default value: 60000 (1 minute).
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol">
+ <summary>
+ Default communication protocol between server and clients to send and receive a message.
+ It uses .NET binary serialization to write and read messages.
+
+ A Message format:
+ [Message Length (4 bytes)][Serialized Message Content]
+
+ If a message is serialized to byte array as N bytes, this protocol
+ adds 4 bytes size information to head of the message bytes, so total length is (4 + N) bytes.
+
+ This class can be derived to change serializer (default: BinaryFormatter). To do this,
+ SerializeMessage and DeserializeMessage methods must be overrided.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocol">
+ <summary>
+ Represents a byte-level communication protocol between applications.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocol.GetBytes(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Serializes a message to a byte array to send to remote application.
+ This method is synchronized. So, only one thread can call it concurrently.
+ </summary>
+ <param name="message">Message to be serialized</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocol.CreateMessages(System.Byte[])">
+ <summary>
+ Builds messages from a byte array that is received from remote application.
+ The Byte array may contain just a part of a message, the protocol must
+ cumulate bytes to build messages.
+ This method is synchronized. So, only one thread can call it concurrently.
+ </summary>
+ <param name="receivedBytes">Received bytes from remote application</param>
+ <returns>
+ List of messages.
+ Protocol can generate more than one message from a byte array.
+ Also, if received bytes are not sufficient to build a message, the protocol
+ may return an empty list (and save bytes to combine with next method call).
+ </returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocol.Reset">
+ <summary>
+ This method is called when connection with remote application is reset (connection is renewing or first connecting).
+ So, wire protocol must reset itself.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.MaxMessageLength">
+ <summary>
+ Maximum length of a message.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol._receiveMemoryStream">
+ <summary>
+ This MemoryStream object is used to collect receiving bytes to build messages.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.#ctor">
+ <summary>
+ Creates a new instance of BinarySerializationProtocol.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.GetBytes(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Serializes a message to a byte array to send to remote application.
+ This method is synchronized. So, only one thread can call it concurrently.
+ </summary>
+ <param name="message">Message to be serialized</param>
+ <exception cref="T:Hik.Communication.Scs.Communication.CommunicationException">Throws CommunicationException if message is bigger than maximum allowed message length.</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.CreateMessages(System.Byte[])">
+ <summary>
+ Builds messages from a byte array that is received from remote application.
+ The Byte array may contain just a part of a message, the protocol must
+ cumulate bytes to build messages.
+ This method is synchronized. So, only one thread can call it concurrently.
+ </summary>
+ <param name="receivedBytes">Received bytes from remote application</param>
+ <returns>
+ List of messages.
+ Protocol can generate more than one message from a byte array.
+ Also, if received bytes are not sufficient to build a message, the protocol
+ may return an empty list (and save bytes to combine with next method call).
+ </returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.Reset">
+ <summary>
+ This method is called when connection with remote application is reset (connection is renewing or first connecting).
+ So, wire protocol must reset itself.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.SerializeMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ This method is used to serialize a IScsMessage to a byte array.
+ This method can be overrided by derived classes to change serialization strategy.
+ It is a couple with DeserializeMessage method and must be overrided together.
+ </summary>
+ <param name="message">Message to be serialized</param>
+ <returns>
+ Serialized message bytes.
+ Does not include length of the message.
+ </returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.DeserializeMessage(System.Byte[])">
+ <summary>
+ This method is used to deserialize a IScsMessage from it's bytes.
+ This method can be overrided by derived classes to change deserialization strategy.
+ It is a couple with SerializeMessage method and must be overrided together.
+ </summary>
+ <param name="bytes">
+ Bytes of message to be deserialized (does not include message length. It consist
+ of a single whole message)
+ </param>
+ <returns>Deserialized message</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.ReadSingleMessage(System.Collections.Generic.ICollection{Hik.Communication.Scs.Communication.Messages.IScsMessage})">
+ <summary>
+ This method tries to read a single message and add to the messages collection.
+ </summary>
+ <param name="messages">Messages collection to collect messages</param>
+ <returns>
+ Returns a boolean value indicates that if there is a need to re-call this method.
+ </returns>
+ <exception cref="T:Hik.Communication.Scs.Communication.CommunicationException">Throws CommunicationException if message is bigger than maximum allowed message length.</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.WriteInt32(System.Byte[],System.Int32,System.Int32)">
+ <summary>
+ Writes a int value to a byte array from a starting index.
+ </summary>
+ <param name="buffer">Byte array to write int value</param>
+ <param name="startIndex">Start index of byte array to write</param>
+ <param name="number">An integer value to write</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.ReadInt32(System.IO.Stream)">
+ <summary>
+ Deserializes and returns a serialized integer.
+ </summary>
+ <returns>Deserialized integer</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.ReadByteArray(System.IO.Stream,System.Int32)">
+ <summary>
+ Reads a byte array with specified length.
+ </summary>
+ <param name="stream">Stream to read from</param>
+ <param name="length">Length of the byte array to read</param>
+ <returns>Read byte array</returns>
+ <exception cref="T:System.IO.EndOfStreamException">Throws EndOfStreamException if can not read from stream.</exception>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.DeserializationAppDomainBinder">
+ <summary>
+ This class is used in deserializing to allow deserializing objects that are defined
+ in assemlies that are load in runtime (like PlugIns).
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.IConnectionListener">
+ <summary>
+ Represents a communication listener.
+ A connection listener is used to accept incoming client connection requests.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.IConnectionListener.Start">
+ <summary>
+ Starts listening incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.IConnectionListener.Stop">
+ <summary>
+ Stops listening incoming connections.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.IConnectionListener.CommunicationChannelConnected">
+ <summary>
+ This event is raised when a new communication channel connected.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Client.ScsServiceClient`1">
+ <summary>
+ Represents a service client that consumes a SCS service.
+ </summary>
+ <typeparam name="T">Type of service interface</typeparam>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Client.ScsServiceClient`1._client">
+ <summary>
+ Underlying IScsClient object to communicate with server.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Client.ScsServiceClient`1._requestReplyMessenger">
+ <summary>
+ Messenger object to send/receive messages over _client.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Client.ScsServiceClient`1._realServiceProxy">
+ <summary>
+ This object is used to create a transparent proxy to invoke remote methods on server.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Client.ScsServiceClient`1._clientObject">
+ <summary>
+ The client object that is used to call method invokes in client side.
+ May be null if client has no methods to be invoked by server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.#ctor(Hik.Communication.Scs.Client.IScsClient,System.Object)">
+ <summary>
+ Creates a new ScsServiceClient object.
+ </summary>
+ <param name="client">Underlying IScsClient object to communicate with server</param>
+ <param name="clientObject">The client object that is used to call method invokes in client side.
+ May be null if client has no methods to be invoked by server.</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Connect">
+ <summary>
+ Connects to server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Disconnect">
+ <summary>
+ Disconnects from server.
+ Does nothing if already disconnected.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Dispose">
+ <summary>
+ Calls Disconnect method.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.RequestReplyMessenger_MessageReceived(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageReceived event of messenger.
+ It gets messages from server and invokes appropriate method.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.SendInvokeResponse(Hik.Communication.Scs.Communication.Messages.IScsMessage,System.Object,Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException)">
+ <summary>
+ Sends response to the remote application that invoked a service method.
+ </summary>
+ <param name="requestMessage">Request message</param>
+ <param name="returnValue">Return value to send</param>
+ <param name="exception">Exception to send</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Client_Connected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Connected event of _client object.
+ </summary>
+ <param name="sender">Source of object</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Client_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Disconnected event of _client object.
+ </summary>
+ <param name="sender">Source of object</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.OnConnected">
+ <summary>
+ Raises Connected event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClient`1.OnDisconnected">
+ <summary>
+ Raises Disconnected event.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Connected">
+ <summary>
+ This event is raised when client connected to server.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Disconnected">
+ <summary>
+ This event is raised when client disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.ScsServiceClient`1.ConnectTimeout">
+ <summary>
+ Timeout for connecting to a server (as milliseconds).
+ Default value: 15 seconds (15000 ms).
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.ScsServiceClient`1.CommunicationState">
+ <summary>
+ Gets the current communication state.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.ScsServiceClient`1.ServiceProxy">
+ <summary>
+ Reference to the service proxy to invoke remote service methods.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Client.ScsServiceClient`1.Timeout">
+ <summary>
+ Timeout value when invoking a service method.
+ If timeout occurs before end of remote method call, an exception is thrown.
+ Use -1 for no timeout (wait indefinite).
+ Default value: 60000 (1 minute).
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.ScsServerManager">
+ <summary>
+ Provides some functionality that are used by servers.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Server.ScsServerManager._lastClientId">
+ <summary>
+ Used to set an auto incremential unique identifier to clients.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerManager.GetClientId">
+ <summary>
+ Gets an unique number to be used as idenfitier of a client.
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocolFactory">
+ <summary>
+ This class is used to create Binary Serialization Protocol objects.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocolFactory">
+ <summary>
+ Defines a Wire Protocol Factory class that is used to create Wire Protocol objects.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.IScsWireProtocolFactory.CreateWireProtocol">
+ <summary>
+ Creates a new Wire Protocol object.
+ </summary>
+ <returns>Newly created wire protocol object</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocolFactory.CreateWireProtocol">
+ <summary>
+ Creates a new Wire Protocol object.
+ </summary>
+ <returns>Newly created wire protocol object</returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.ScsTextMessage">
+ <summary>
+ This message is used to send/receive a text as message data.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsTextMessage.#ctor">
+ <summary>
+ Creates a new ScsTextMessage object.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsTextMessage.#ctor(System.String)">
+ <summary>
+ Creates a new ScsTextMessage object with Text property.
+ </summary>
+ <param name="text">Message text that is being transmitted</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsTextMessage.#ctor(System.String,System.String)">
+ <summary>
+ Creates a new reply ScsTextMessage object with Text property.
+ </summary>
+ <param name="text">Message text that is being transmitted</param>
+ <param name="repliedMessageId">
+ Replied message id if this is a reply for
+ a message.
+ </param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsTextMessage.ToString">
+ <summary>
+ Creates a string to represents this object.
+ </summary>
+ <returns>A string to represents this object</returns>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.ScsTextMessage.Text">
+ <summary>
+ Message text that is being transmitted.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceBuilder">
+ <summary>
+ This class is used to build ScsService applications.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceBuilder.CreateService(Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint)">
+ <summary>
+ Creates a new SCS Service application using an EndPoint.
+ </summary>
+ <param name="endPoint">EndPoint that represents address of the service</param>
+ <returns>Created SCS service application</returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.ScsPingMessage">
+ <summary>
+ This message is used to send/receive ping messages.
+ Ping messages is used to keep connection alive between server and client.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsPingMessage.#ctor">
+ <summary>
+ Creates a new PingMessage object.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsPingMessage.#ctor(System.String)">
+ <summary>
+ Creates a new reply PingMessage object.
+ </summary>
+ <param name="repliedMessageId">
+ Replied message id if this is a reply for
+ a message.
+ </param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsPingMessage.ToString">
+ <summary>
+ Creates a string to represents this object.
+ </summary>
+ <returns>A string to represents this object</returns>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException">
+ <summary>
+ Represents a SCS Remote Exception.
+ This exception is used to send an exception from an application to another application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException.#ctor">
+ <summary>
+ Contstructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Contstructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException.#ctor(System.String)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException.#ctor(System.String,System.Exception)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ <param name="innerException">Inner exception</param>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.ScsServerBase">
+ <summary>
+ This class provides base functionality for server classes.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Server.ScsServerBase._connectionListener">
+ <summary>
+ This object is used to listen incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.#ctor">
+ <summary>
+ Constructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.Start">
+ <summary>
+ Starts the server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.Stop">
+ <summary>
+ Stops the server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.CreateConnectionListener">
+ <summary>
+ This method is implemented by derived classes to create appropriate connection listener to listen incoming connection requets.
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.ConnectionListener_CommunicationChannelConnected(System.Object,Hik.Communication.Scs.Communication.Channels.CommunicationChannelEventArgs)">
+ <summary>
+ Handles CommunicationChannelConnected event of _connectionListener object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.Client_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Disconnected events of all connected clients.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.OnClientConnected(Hik.Communication.Scs.Server.IScsServerClient)">
+ <summary>
+ Raises ClientConnected event.
+ </summary>
+ <param name="client">Connected client</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerBase.OnClientDisconnected(Hik.Communication.Scs.Server.IScsServerClient)">
+ <summary>
+ Raises ClientDisconnected event.
+ </summary>
+ <param name="client">Disconnected client</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.ScsServerBase.ClientConnected">
+ <summary>
+ This event is raised when a new client is connected.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.ScsServerBase.ClientDisconnected">
+ <summary>
+ This event is raised when a client disconnected from the server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerBase.WireProtocolFactory">
+ <summary>
+ Gets/sets wire protocol that is used while reading and writing messages.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerBase.Clients">
+ <summary>
+ A collection of clients that are connected to the server.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage">
+ <summary>
+ This message is used to send/receive a raw byte array as message data.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage.#ctor">
+ <summary>
+ Default empty constructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage.#ctor(System.Byte[])">
+ <summary>
+ Creates a new ScsRawDataMessage object with MessageData property.
+ </summary>
+ <param name="messageData">Message data that is being transmitted</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage.#ctor(System.Byte[],System.String)">
+ <summary>
+ Creates a new reply ScsRawDataMessage object with MessageData property.
+ </summary>
+ <param name="messageData">Message data that is being transmitted</param>
+ <param name="repliedMessageId">
+ Replied message id if this is a reply for
+ a message.
+ </param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage.ToString">
+ <summary>
+ Creates a string to represents this object.
+ </summary>
+ <returns>A string to represents this object</returns>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage.MessageData">
+ <summary>
+ Message data that is being transmitted.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ServiceClientEventArgs">
+ <summary>
+ Stores service client informations to be used by an event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ServiceClientEventArgs.#ctor(Hik.Communication.ScsServices.Service.IScsServiceClient)">
+ <summary>
+ Creates a new ServiceClientEventArgs object.
+ </summary>
+ <param name="client">Client that is associated with this event</param>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ServiceClientEventArgs.Client">
+ <summary>
+ Client that is associated with this event.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceClient">
+ <summary>
+ Implements IScsServiceClient.
+ It is used to manage and monitor a service client.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.IScsServiceClient">
+ <summary>
+ Represents a client that uses a SDS service.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceClient.Disconnect">
+ <summary>
+ Closes client connection.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceClient.GetClientProxy``1">
+ <summary>
+ Gets the client proxy interface that provides calling client methods remotely.
+ </summary>
+ <typeparam name="T">Type of client interface</typeparam>
+ <returns>Client interface</returns>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.IScsServiceClient.Disconnected">
+ <summary>
+ This event is raised when client is disconnected from service.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.IScsServiceClient.ClientId">
+ <summary>
+ Unique identifier for this client.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.IScsServiceClient.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.IScsServiceClient.CommunicationState">
+ <summary>
+ Gets the communication state of the Client.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceClient._serverClient">
+ <summary>
+ Reference to underlying IScsServerClient object.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceClient._requestReplyMessenger">
+ <summary>
+ This object is used to send messages to client.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceClient._realProxy">
+ <summary>
+ Last created proxy object to invoke remote medhods.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClient.#ctor(Hik.Communication.Scs.Server.IScsServerClient,Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger{Hik.Communication.Scs.Server.IScsServerClient})">
+ <summary>
+ Creates a new ScsServiceClient object.
+ </summary>
+ <param name="serverClient">Reference to underlying IScsServerClient object</param>
+ <param name="requestReplyMessenger">RequestReplyMessenger to send messages</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClient.Disconnect">
+ <summary>
+ Closes client connection.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClient.GetClientProxy``1">
+ <summary>
+ Gets the client proxy interface that provides calling client methods remotely.
+ </summary>
+ <typeparam name="T">Type of client interface</typeparam>
+ <returns>Client interface</returns>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClient.Client_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles disconnect event of _serverClient object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClient.OnDisconnected">
+ <summary>
+ Raises Disconnected event.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.ScsServiceClient.Disconnected">
+ <summary>
+ This event is raised when this client is disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceClient.ClientId">
+ <summary>
+ Unique identifier for this client.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceClient.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceClient.CommunicationState">
+ <summary>
+ Gets the communication state of the Client.
+ </summary>
+ </member>
+ <member name="T:Hik.Collections.ThreadSafeSortedList`2">
+ <summary>
+ This class is used to store key-value based items in a thread safe manner.
+ It uses System.Collections.Generic.SortedList internally.
+ </summary>
+ <typeparam name="TK">Key type</typeparam>
+ <typeparam name="TV">Value type</typeparam>
+ </member>
+ <member name="F:Hik.Collections.ThreadSafeSortedList`2._items">
+ <summary>
+ Internal collection to store items.
+ </summary>
+ </member>
+ <member name="F:Hik.Collections.ThreadSafeSortedList`2._lock">
+ <summary>
+ Used to synchronize access to _items list.
+ </summary>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.#ctor">
+ <summary>
+ Creates a new ThreadSafeSortedList object.
+ </summary>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.ContainsKey(`0)">
+ <summary>
+ Checks if collection contains spesified key.
+ </summary>
+ <param name="key">Key to check</param>
+ <returns>True; if collection contains given key</returns>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.ContainsValue(`1)">
+ <summary>
+ Checks if collection contains spesified item.
+ </summary>
+ <param name="item">Item to check</param>
+ <returns>True; if collection contains given item</returns>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.Remove(`0)">
+ <summary>
+ Removes an item from collection.
+ </summary>
+ <param name="key">Key of item to remove</param>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.GetAllItems">
+ <summary>
+ Gets all items in collection.
+ </summary>
+ <returns>Item list</returns>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.ClearAll">
+ <summary>
+ Removes all items from list.
+ </summary>
+ </member>
+ <member name="M:Hik.Collections.ThreadSafeSortedList`2.GetAndClearAllItems">
+ <summary>
+ Gets then removes all items in collection.
+ </summary>
+ <returns>Item list</returns>
+ </member>
+ <member name="P:Hik.Collections.ThreadSafeSortedList`2.Item(`0)">
+ <summary>
+ Gets/adds/replaces an item by key.
+ </summary>
+ <param name="key">Key to get/set value</param>
+ <returns>Item associated with this key</returns>
+ </member>
+ <member name="P:Hik.Collections.ThreadSafeSortedList`2.Count">
+ <summary>
+ Gets count of items in the collection.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.Tcp.TcpHelper">
+ <summary>
+ This class is used to simplify TCP socket operations.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.Tcp.TcpHelper.ConnectToServer(System.Net.EndPoint,System.Int32)">
+ <summary>
+ This code is used to connect to a TCP socket with timeout option.
+ </summary>
+ <param name="endPoint">IP endpoint of remote server</param>
+ <param name="timeoutMs">Timeout to wait until connect</param>
+ <returns>Socket object connected to server</returns>
+ <exception cref="T:System.Net.Sockets.SocketException">Throws SocketException if can not connect.</exception>
+ <exception cref="T:System.TimeoutException">Throws TimeoutException if can not connect within specified timeoutMs</exception>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.Tcp.ScsTcpClient">
+ <summary>
+ This class is used to communicate with server over TCP/IP protocol.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.ScsClientBase">
+ <summary>
+ This class provides base functionality for client classes.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ScsClientBase.DefaultConnectionAttemptTimeout">
+ <summary>
+ Default timeout value for connecting a server.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ScsClientBase._communicationChannel">
+ <summary>
+ The communication channel that is used by client to send and receive messages.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ScsClientBase._pingTimer">
+ <summary>
+ This timer is used to send PingMessage messages to server periodically.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.#ctor">
+ <summary>
+ Constructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.Connect">
+ <summary>
+ Connects to server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.Disconnect">
+ <summary>
+ Disconnects from server.
+ Does nothing if already disconnected.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.Dispose">
+ <summary>
+ Disposes this object and closes underlying connection.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.SendMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the server.
+ </summary>
+ <param name="message">Message to be sent</param>
+ <exception cref="T:Hik.Communication.Scs.Communication.CommunicationStateException">Throws a CommunicationStateException if client is not connected to the server.</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.CreateCommunicationChannel">
+ <summary>
+ This method is implemented by derived classes to create appropriate communication channel.
+ </summary>
+ <returns>Ready communication channel to communicate</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.CommunicationChannel_MessageReceived(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageReceived event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.CommunicationChannel_MessageSent(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageSent event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.CommunicationChannel_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Disconnected event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.PingTimer_Elapsed(System.Object,System.EventArgs)">
+ <summary>
+ Handles Elapsed event of _pingTimer to send PingMessage messages to server.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.OnConnected">
+ <summary>
+ Raises Connected event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.OnDisconnected">
+ <summary>
+ Raises Disconnected event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.OnMessageReceived(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageReceived event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ScsClientBase.OnMessageSent(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageSent event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.ScsClientBase.MessageReceived">
+ <summary>
+ This event is raised when a new message is received.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.ScsClientBase.MessageSent">
+ <summary>
+ This event is raised when a new message is sent without any error.
+ It does not guaranties that message is properly handled and processed by remote application.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.ScsClientBase.Connected">
+ <summary>
+ This event is raised when communication channel closed.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Client.ScsClientBase.Disconnected">
+ <summary>
+ This event is raised when client disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ScsClientBase.ConnectTimeout">
+ <summary>
+ Timeout for connecting to a server (as milliseconds).
+ Default value: 15 seconds (15000 ms).
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ScsClientBase.WireProtocol">
+ <summary>
+ Gets/sets wire protocol that is used while reading and writing messages.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ScsClientBase.CommunicationState">
+ <summary>
+ Gets the communication state of the Client.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ScsClientBase.LastReceivedMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ScsClientBase.LastSentMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.Tcp.ScsTcpClient._serverEndPoint">
+ <summary>
+ The endpoint address of the server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.Tcp.ScsTcpClient.#ctor(Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint)">
+ <summary>
+ Creates a new ScsTcpClient object.
+ </summary>
+ <param name="serverEndPoint">The endpoint address to connect to the server</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.Tcp.ScsTcpClient.CreateCommunicationChannel">
+ <summary>
+ Creates a communication channel using ServerIpAddress and ServerPort.
+ </summary>
+ <returns>Ready communication channel to communicate</returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint">
+ <summary>
+ Represens a TCP end point in SCS.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint">
+ <summary>
+ Represents a server side end point in SCS.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint.CreateEndPoint(System.String)">
+ <summary>
+ Create a Scs End Point from a string.
+ Address must be formatted as: protocol://address
+ For example: tcp://89.43.104.179:10048 for a TCP endpoint with
+ IP 89.43.104.179 and port 10048.
+ </summary>
+ <param name="endPointAddress">Address to create endpoint</param>
+ <returns>Created end point</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint.CreateServer">
+ <summary>
+ Creates a Scs Server that uses this end point to listen incoming connections.
+ </summary>
+ <returns>Scs Server</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint.CreateClient">
+ <summary>
+ Creates a Scs Server that uses this end point to connect to server.
+ </summary>
+ <returns>Scs Client</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.#ctor(System.Int32)">
+ <summary>
+ Creates a new ScsTcpEndPoint object with specified port number.
+ </summary>
+ <param name="tcpPort">Listening TCP Port for incoming connection requests on server</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.#ctor(System.String,System.Int32)">
+ <summary>
+ Creates a new ScsTcpEndPoint object with specified IP address and port number.
+ </summary>
+ <param name="ipAddress">IP address of the server</param>
+ <param name="port">Listening TCP Port for incoming connection requests on server</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.#ctor(System.String)">
+ <summary>
+ Creates a new ScsTcpEndPoint from a string address.
+ Address format must be like IPAddress:Port (For example: 127.0.0.1:10085).
+ </summary>
+ <param name="address">TCP end point Address</param>
+ <returns>Created ScsTcpEndpoint object</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.CreateServer">
+ <summary>
+ Creates a Scs Server that uses this end point to listen incoming connections.
+ </summary>
+ <returns>Scs Server</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.CreateClient">
+ <summary>
+ Creates a Scs Client that uses this end point to connect to server.
+ </summary>
+ <returns>Scs Client</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.ToString">
+ <summary>
+ Generates a string representation of this end point object.
+ </summary>
+ <returns>String representation of this end point object</returns>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.IpAddress">
+ <summary>
+ IP address of the server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint.TcpPort">
+ <summary>
+ Listening TCP Port for incoming connection requests on server.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceAttribute">
+ <summary>
+ Any SCS Service interface class must has this attribute.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceAttribute.#ctor">
+ <summary>
+ Creates a new ScsServiceAttribute object.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceAttribute.Version">
+ <summary>
+ Service Version. This property can be used to indicate the code version.
+ This value is sent to client application on an exception, so, client application can know that service version is changed.
+ Default value: NO_VERSION.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1">
+ <summary>
+ This class adds SendMessageAndWaitForResponse(...) and SendAndReceiveMessage methods
+ to a IMessenger for synchronous request/response style messaging.
+ It also adds queued processing of incoming messages.
+ </summary>
+ <typeparam name="T">Type of IMessenger object to use as underlying communication</typeparam>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.DefaultTimeout">
+ <summary>
+ Default Timeout value.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1._waitingMessages">
+ <summary>
+ This messages are waiting for a response those are used when
+ SendMessageAndWaitForResponse is called.
+ Key: MessageID of waiting request message.
+ Value: A WaitingMessage instance.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1._incomingMessageProcessor">
+ <summary>
+ This object is used to process incoming messages sequentially.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1._syncObj">
+ <summary>
+ This object is used for thread synchronization.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.#ctor(`0)">
+ <summary>
+ Creates a new RequestReplyMessenger.
+ </summary>
+ <param name="messenger">IMessenger object to use as underlying communication</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Start">
+ <summary>
+ Starts the messenger.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Stop">
+ <summary>
+ Stops the messenger.
+ Cancels all waiting threads in SendMessageAndWaitForResponse method and stops message queue.
+ SendMessageAndWaitForResponse method throws exception if there is a thread that is waiting for response message.
+ Also stops incoming message processing and deletes all messages in incoming message queue.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Dispose">
+ <summary>
+ Calls Stop method of this object.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.SendMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message.
+ </summary>
+ <param name="message">Message to be sent</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.SendMessageAndWaitForResponse(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message and waits a response for that message.
+ </summary>
+ <remarks>
+ Response message is matched with RepliedMessageId property, so if
+ any other message (that is not reply for sent message) is received
+ from remote application, it is not considered as a reply and is not
+ returned as return value of this method.
+
+ MessageReceived event is not raised for response messages.
+ </remarks>
+ <param name="message">message to send</param>
+ <returns>Response message</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.SendMessageAndWaitForResponse(Hik.Communication.Scs.Communication.Messages.IScsMessage,System.Int32)">
+ <summary>
+ Sends a message and waits a response for that message.
+ </summary>
+ <remarks>
+ Response message is matched with RepliedMessageId property, so if
+ any other message (that is not reply for sent message) is received
+ from remote application, it is not considered as a reply and is not
+ returned as return value of this method.
+
+ MessageReceived event is not raised for response messages.
+ </remarks>
+ <param name="message">message to send</param>
+ <param name="timeoutMilliseconds">Timeout duration as milliseconds.</param>
+ <returns>Response message</returns>
+ <exception cref="T:System.TimeoutException">Throws TimeoutException if can not receive reply message in timeout value</exception>
+ <exception cref="T:Hik.Communication.Scs.Communication.CommunicationException">Throws CommunicationException if communication fails before reply message.</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Messenger_MessageReceived(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageReceived event of Messenger object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Messenger_MessageSent(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageSent event of Messenger object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.OnMessageReceived(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageReceived event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.OnMessageSent(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageSent event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.MessageReceived">
+ <summary>
+ This event is raised when a new message is received from underlying messenger.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.MessageSent">
+ <summary>
+ This event is raised when a new message is sent without any error.
+ It does not guaranties that message is properly handled and processed by remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WireProtocol">
+ <summary>
+ Gets/sets wire protocol that is used while reading and writing messages.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.LastReceivedMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.LastSentMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Messenger">
+ <summary>
+ Gets the underlying IMessenger object.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.Timeout">
+ <summary>
+ Timeout value as milliseconds to wait for a receiving message on
+ SendMessageAndWaitForResponse and SendAndReceiveMessage methods.
+ Default value: 60000 (1 minute).
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessage">
+ <summary>
+ This class is used to store messaging context for a request message
+ until response is received.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessage.#ctor">
+ <summary>
+ Creates a new WaitingMessage object.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessage.ResponseMessage">
+ <summary>
+ Response message for request message
+ (null if response is not received yet).
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessage.WaitEvent">
+ <summary>
+ ManualResetEvent to block thread until response is received.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessage.State">
+ <summary>
+ State of the request message.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessageStates">
+ <summary>
+ This enum is used to store the state of a waiting message.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessageStates.WaitingForResponse">
+ <summary>
+ Still waiting for response.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessageStates.Cancelled">
+ <summary>
+ Message sending is cancelled.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger`1.WaitingMessageStates.ResponseReceived">
+ <summary>
+ Response is properly received.
+ </summary>
+ </member>
+ <member name="T:Hik.Threading.Timer">
+ <summary>
+ This class is a timer that performs some tasks periodically.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.Timer._taskTimer">
+ <summary>
+ This timer is used to perfom the task at spesified intervals.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.Timer._running">
+ <summary>
+ Indicates that whether timer is running or stopped.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.Timer._performingTasks">
+ <summary>
+ Indicates that whether performing the task or _taskTimer is in sleep mode.
+ This field is used to wait executing tasks when stopping Timer.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.Timer.#ctor(System.Int32)">
+ <summary>
+ Creates a new Timer.
+ </summary>
+ <param name="period">Task period of timer (as milliseconds)</param>
+ </member>
+ <member name="M:Hik.Threading.Timer.#ctor(System.Int32,System.Boolean)">
+ <summary>
+ Creates a new Timer.
+ </summary>
+ <param name="period">Task period of timer (as milliseconds)</param>
+ <param name="runOnStart">Indicates whether timer raises Elapsed event on Start method of Timer for once</param>
+ </member>
+ <member name="M:Hik.Threading.Timer.Start">
+ <summary>
+ Starts the timer.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.Timer.Stop">
+ <summary>
+ Stops the timer.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.Timer.WaitToStop">
+ <summary>
+ Waits the service to stop.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.Timer.TimerCallBack(System.Object)">
+ <summary>
+ This method is called by _taskTimer.
+ </summary>
+ <param name="state">Not used argument</param>
+ </member>
+ <member name="E:Hik.Threading.Timer.Elapsed">
+ <summary>
+ This event is raised periodically according to Period of Timer.
+ </summary>
+ </member>
+ <member name="P:Hik.Threading.Timer.Period">
+ <summary>
+ Task period of timer (as milliseconds).
+ </summary>
+ </member>
+ <member name="P:Hik.Threading.Timer.RunOnStart">
+ <summary>
+ Indicates whether timer raises Elapsed event on Start method of Timer for once.
+ Default: False.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.CommunicationStateException">
+ <summary>
+ This application is thrown if communication is not expected state.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.CommunicationException">
+ <summary>
+ This application is thrown in a communication error.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationException.#ctor">
+ <summary>
+ Contstructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Contstructor for serializing.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationException.#ctor(System.String)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationException.#ctor(System.String,System.Exception)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ <param name="innerException">Inner exception</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationStateException.#ctor">
+ <summary>
+ Contstructor.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationStateException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Contstructor for serializing.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationStateException.#ctor(System.String)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.CommunicationStateException.#ctor(System.String,System.Exception)">
+ <summary>
+ Contstructor.
+ </summary>
+ <param name="message">Exception message</param>
+ <param name="innerException">Inner exception</param>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.ServerClientEventArgs">
+ <summary>
+ Stores client information to be used by an event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ServerClientEventArgs.#ctor(Hik.Communication.Scs.Server.IScsServerClient)">
+ <summary>
+ Creates a new ServerClientEventArgs object.
+ </summary>
+ <param name="client">Client that is associated with this event</param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ServerClientEventArgs.Client">
+ <summary>
+ Client that is associated with this event.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.ScsServerClient">
+ <summary>
+ This class represents a client in server side.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.IScsServerClient">
+ <summary>
+ Represents a client from a perspective of a server.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.IScsServerClient.Disconnect">
+ <summary>
+ Disconnects from server.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.IScsServerClient.Disconnected">
+ <summary>
+ This event is raised when client disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.IScsServerClient.ClientId">
+ <summary>
+ Unique identifier for this client in server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.IScsServerClient.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.IScsServerClient.CommunicationState">
+ <summary>
+ Gets the current communication state.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Server.ScsServerClient._communicationChannel">
+ <summary>
+ The communication channel that is used by client to send and receive messages.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.#ctor(Hik.Communication.Scs.Communication.Channels.ICommunicationChannel)">
+ <summary>
+ Creates a new ScsClient object.
+ </summary>
+ <param name="communicationChannel">The communication channel that is used by client to send and receive messages</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.Disconnect">
+ <summary>
+ Disconnects from client and closes underlying communication channel.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.SendMessage(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Sends a message to the client.
+ </summary>
+ <param name="message">Message to be sent</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.CommunicationChannel_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Disconnected event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.CommunicationChannel_MessageReceived(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageReceived event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.CommunicationChannel_MessageSent(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageSent event of _communicationChannel object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.OnDisconnected">
+ <summary>
+ Raises Disconnected event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.OnMessageReceived(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageReceived event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerClient.OnMessageSent(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Raises MessageSent event.
+ </summary>
+ <param name="message">Received message</param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.ScsServerClient.MessageReceived">
+ <summary>
+ This event is raised when a new message is received.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.ScsServerClient.MessageSent">
+ <summary>
+ This event is raised when a new message is sent without any error.
+ It does not guaranties that message is properly handled and processed by remote application.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.Scs.Server.ScsServerClient.Disconnected">
+ <summary>
+ This event is raised when client is disconnected from server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.ClientId">
+ <summary>
+ Unique identifier for this client in server.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.CommunicationState">
+ <summary>
+ Gets the communication state of the Client.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.WireProtocol">
+ <summary>
+ Gets/sets wire protocol that is used while reading and writing messages.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.RemoteEndPoint">
+ <summary>
+ Gets endpoint of remote application.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.LastReceivedMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.Scs.Server.ScsServerClient.LastSentMessageTime">
+ <summary>
+ Gets the time of the last succesfully received message.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener">
+ <summary>
+ This class is used to listen and accept incoming TCP
+ connection requests on a TCP port.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase">
+ <summary>
+ This class provides base functionality for communication listener classes.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase.Start">
+ <summary>
+ Starts listening incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase.Stop">
+ <summary>
+ Stops listening incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase.OnCommunicationChannelConnected(Hik.Communication.Scs.Communication.Channels.ICommunicationChannel)">
+ <summary>
+ Raises CommunicationChannelConnected event.
+ </summary>
+ <param name="client"></param>
+ </member>
+ <member name="E:Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase.CommunicationChannelConnected">
+ <summary>
+ This event is raised when a new communication channel is connected.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener._endPoint">
+ <summary>
+ The endpoint address of the server to listen incoming connections.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener._listenerSocket">
+ <summary>
+ Server socket to listen incoming connection requests.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener._thread">
+ <summary>
+ The thread to listen socket
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener._running">
+ <summary>
+ A flag to control thread's running
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.#ctor(Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint)">
+ <summary>
+ Creates a new TcpConnectionListener for given endpoint.
+ </summary>
+ <param name="endPoint">The endpoint address of the server to listen incoming connections</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.Start">
+ <summary>
+ Starts listening incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.Stop">
+ <summary>
+ Stops listening incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.StartSocket">
+ <summary>
+ Starts listening socket.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.StopSocket">
+ <summary>
+ Stops listening socket.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener.DoListenAsThread">
+ <summary>
+ Entrance point of the thread.
+ This method is used by the thread to listen incoming requests.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceApplication">
+ <summary>
+ Implements IScsServiceApplication and provides all functionallity.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.IScsServiceApplication">
+ <summary>
+ Represents a SCS Service Application that is used to construct and manage a SCS service.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceApplication.Start">
+ <summary>
+ Starts service application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceApplication.Stop">
+ <summary>
+ Stops service application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceApplication.AddService``2(``1)">
+ <summary>
+ Adds a service object to this service application.
+ Only single service object can be added for a service interface type.
+ </summary>
+ <typeparam name="TServiceInterface">Service interface type</typeparam>
+ <typeparam name="TServiceClass">Service class type. Must be delivered from ScsService and must implement TServiceInterface.</typeparam>
+ <param name="service">An instance of TServiceClass.</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.IScsServiceApplication.RemoveService``1">
+ <summary>
+ Removes a previously added service object from this service application.
+ It removes object according to interface type.
+ </summary>
+ <typeparam name="TServiceInterface">Service interface type</typeparam>
+ <returns>True: removed. False: no service object with this interface</returns>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.IScsServiceApplication.ClientConnected">
+ <summary>
+ This event is raised when a new client connected to the service.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.IScsServiceApplication.ClientDisconnected">
+ <summary>
+ This event is raised when a client disconnected from the service.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceApplication._scsServer">
+ <summary>
+ Underlying IScsServer object to accept and manage client connections.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceApplication._serviceObjects">
+ <summary>
+ User service objects that is used to invoke incoming method invocation requests.
+ Key: Service interface type's name.
+ Value: Service object.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceApplication._serviceClients">
+ <summary>
+ All connected clients to service.
+ Key: Client's unique Id.
+ Value: Reference to the client.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.#ctor(Hik.Communication.Scs.Server.IScsServer)">
+ <summary>
+ Creates a new ScsServiceApplication object.
+ </summary>
+ <param name="scsServer">Underlying IScsServer object to accept and manage client connections</param>
+ <exception cref="T:System.ArgumentNullException">Throws ArgumentNullException if scsServer argument is null</exception>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.Start">
+ <summary>
+ Starts service application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.Stop">
+ <summary>
+ Stops service application.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.AddService``2(``1)">
+ <summary>
+ Adds a service object to this service application.
+ Only single service object can be added for a service interface type.
+ </summary>
+ <typeparam name="TServiceInterface">Service interface type</typeparam>
+ <typeparam name="TServiceClass">Service class type. Must be delivered from ScsService and must implement TServiceInterface.</typeparam>
+ <param name="service">An instance of TServiceClass.</param>
+ <exception cref="T:System.ArgumentNullException">Throws ArgumentNullException if service argument is null</exception>
+ <exception cref="T:System.Exception">Throws Exception if service is already added before</exception>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.RemoveService``1">
+ <summary>
+ Removes a previously added service object from this service application.
+ It removes object according to interface type.
+ </summary>
+ <typeparam name="TServiceInterface">Service interface type</typeparam>
+ <returns>True: removed. False: no service object with this interface</returns>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.ScsServer_ClientConnected(System.Object,Hik.Communication.Scs.Server.ServerClientEventArgs)">
+ <summary>
+ Handles ClientConnected event of _scsServer object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.ScsServer_ClientDisconnected(System.Object,Hik.Communication.Scs.Server.ServerClientEventArgs)">
+ <summary>
+ Handles ClientDisconnected event of _scsServer object.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.Client_MessageReceived(System.Object,Hik.Communication.Scs.Communication.Messages.MessageEventArgs)">
+ <summary>
+ Handles MessageReceived events of all clients, evaluates each message,
+ finds appropriate service object and invokes appropriate method.
+ </summary>
+ <param name="sender">Source of event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.SendInvokeResponse(Hik.Communication.Scs.Communication.Messengers.IMessenger,Hik.Communication.Scs.Communication.Messages.IScsMessage,System.Object,Hik.Communication.ScsServices.Communication.Messages.ScsRemoteException)">
+ <summary>
+ Sends response to the remote application that invoked a service method.
+ </summary>
+ <param name="client">Client that sent invoke message</param>
+ <param name="requestMessage">Request message</param>
+ <param name="returnValue">Return value to send</param>
+ <param name="exception">Exception to send</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.OnClientConnected(Hik.Communication.ScsServices.Service.IScsServiceClient)">
+ <summary>
+ Raises ClientConnected event.
+ </summary>
+ <param name="client"></param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.OnClientDisconnected(Hik.Communication.ScsServices.Service.IScsServiceClient)">
+ <summary>
+ Raises ClientDisconnected event.
+ </summary>
+ <param name="client"></param>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.ScsServiceApplication.ClientConnected">
+ <summary>
+ This event is raised when a new client connected to the service.
+ </summary>
+ </member>
+ <member name="E:Hik.Communication.ScsServices.Service.ScsServiceApplication.ClientDisconnected">
+ <summary>
+ This event is raised when a client disconnected from the service.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject">
+ <summary>
+ Represents a user service object.
+ It is used to invoke methods on a ScsService object.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject._methods">
+ <summary>
+ This collection stores a list of all methods of service object.
+ Key: Method name
+ Value: Informations about method.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject.#ctor(System.Type,Hik.Communication.ScsServices.Service.ScsService)">
+ <summary>
+ Creates a new ServiceObject.
+ </summary>
+ <param name="serviceInterfaceType">Type of service interface</param>
+ <param name="service">The service object that is used to invoke methods on</param>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject.InvokeMethod(System.String,System.Object[])">
+ <summary>
+ Invokes a method of Service object.
+ </summary>
+ <param name="methodName">Name of the method to invoke</param>
+ <param name="parameters">Parameters of method</param>
+ <returns>Return value of method</returns>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject.Service">
+ <summary>
+ The service object that is used to invoke methods on.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject.ServiceAttribute">
+ <summary>
+ ScsService attribute of Service object's class.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.CommunicationStates">
+ <summary>
+ Communication states.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.CommunicationStates.Connected">
+ <summary>
+ Connected.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.CommunicationStates.Disconnected">
+ <summary>
+ Disconnected.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1">
+ <summary>
+ This class is a wrapper for IMessenger and is used
+ to synchronize message receiving operation.
+ It extends RequestReplyMessenger.
+ It is suitable to use in applications those want to receive
+ messages by synchronized method calls instead of asynchronous
+ MessageReceived event.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1._receivingMessageQueue">
+ <summary>
+ A queue that is used to store receiving messages until Receive(...)
+ method is called to get them.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1._receiveWaiter">
+ <summary>
+ This object is used to synchronize/wait threads.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1._running">
+ <summary>
+ This boolean value indicates the running state of this class.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.#ctor(`0)">
+ <summary>
+ Creates a new SynchronizedMessenger object.
+ </summary>
+ <param name="messenger">A IMessenger object to be used to send/receive messages</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.#ctor(`0,System.Int32)">
+ <summary>
+ Creates a new SynchronizedMessenger object.
+ </summary>
+ <param name="messenger">A IMessenger object to be used to send/receive messages</param>
+ <param name="incomingMessageQueueCapacity">capacity of the incoming message queue</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.Start">
+ <summary>
+ Starts the messenger.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.Stop">
+ <summary>
+ Stops the messenger.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.ReceiveMessage">
+ <summary>
+ This method is used to receive a message from remote application.
+ It waits until a message is received.
+ </summary>
+ <returns>Received message</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.ReceiveMessage(System.Int32)">
+ <summary>
+ This method is used to receive a message from remote application.
+ It waits until a message is received or timeout occurs.
+ </summary>
+ <param name="timeout">
+ Timeout value to wait if no message is received.
+ Use -1 to wait indefinitely.
+ </param>
+ <returns>Received message</returns>
+ <exception cref="T:System.TimeoutException">Throws TimeoutException if timeout occurs</exception>
+ <exception cref="T:System.Exception">Throws Exception if SynchronizedMessenger stops before a message is received</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.ReceiveMessage``1">
+ <summary>
+ This method is used to receive a specific type of message from remote application.
+ It waits until a message is received.
+ </summary>
+ <returns>Received message</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.ReceiveMessage``1(System.Int32)">
+ <summary>
+ This method is used to receive a specific type of message from remote application.
+ It waits until a message is received or timeout occurs.
+ </summary>
+ <param name="timeout">
+ Timeout value to wait if no message is received.
+ Use -1 to wait indefinitely.
+ </param>
+ <returns>Received message</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.OnMessageReceived(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Overrides
+ </summary>
+ <param name="message"></param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messengers.SynchronizedMessenger`1.IncomingMessageQueueCapacity">
+ <summary>
+ Gets/sets capacity of the incoming message queue.
+ No message is received from remote application if
+ number of messages in internal queue exceeds this value.
+ Default value: int.MaxValue (2147483647).
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Messages.MessageEventArgs">
+ <summary>
+ Stores message to be used by an event.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Messages.MessageEventArgs.#ctor(Hik.Communication.Scs.Communication.Messages.IScsMessage)">
+ <summary>
+ Creates a new MessageEventArgs object.
+ </summary>
+ <param name="message">Message object that is associated with this event</param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Communication.Messages.MessageEventArgs.Message">
+ <summary>
+ Message object that is associated with this event.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Client.ClientReConnecter">
+ <summary>
+ This class is used to automatically re-connect to server if disconnected.
+ It attempts to reconnect to server periodically until connection established.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ClientReConnecter._client">
+ <summary>
+ Reference to client object.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ClientReConnecter._reconnectTimer">
+ <summary>
+ Timer to attempt ro reconnect periodically.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Client.ClientReConnecter._disposed">
+ <summary>
+ Indicates the dispose state of this object.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ClientReConnecter.#ctor(Hik.Communication.Scs.Client.IConnectableClient)">
+ <summary>
+ Creates a new ClientReConnecter object.
+ It is not needed to start ClientReConnecter since it automatically
+ starts when the client disconnected.
+ </summary>
+ <param name="client">Reference to client object</param>
+ <exception cref="T:System.ArgumentNullException">Throws ArgumentNullException if client is null.</exception>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ClientReConnecter.Dispose">
+ <summary>
+ Disposes this object.
+ Does nothing if already disposed.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ClientReConnecter.Client_Disconnected(System.Object,System.EventArgs)">
+ <summary>
+ Handles Disconnected event of _client object.
+ </summary>
+ <param name="sender">Source of the event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Client.ClientReConnecter.ReconnectTimer_Elapsed(System.Object,System.EventArgs)">
+ <summary>
+ Hadles Elapsed event of _reconnectTimer.
+ </summary>
+ <param name="sender">Source of the event</param>
+ <param name="e">Event arguments</param>
+ </member>
+ <member name="P:Hik.Communication.Scs.Client.ClientReConnecter.ReConnectCheckPeriod">
+ <summary>
+ Reconnect check period.
+ Default: 20 seconds.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Service.ScsServiceClientFactory">
+ <summary>
+ This class is used to create service client objects that is used in server-side.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Service.ScsServiceClientFactory.CreateServiceClient(Hik.Communication.Scs.Server.IScsServerClient,Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger{Hik.Communication.Scs.Server.IScsServerClient})">
+ <summary>
+ Creates a new service client object that is used in server-side.
+ </summary>
+ <param name="serverClient">Underlying server client object</param>
+ <param name="requestReplyMessenger">RequestReplyMessenger object to send/receive messages over serverClient</param>
+ <returns></returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.ScsServerFactory">
+ <summary>
+ This class is used to create SCS servers.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.ScsServerFactory.CreateServer(Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint)">
+ <summary>
+ Creates a new SCS Server using an EndPoint.
+ </summary>
+ <param name="endPoint">Endpoint that represents address of the server</param>
+ <returns>Created TCP server</returns>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Client.ScsServiceClientBuilder">
+ <summary>
+ This class is used to build service clients to remotely invoke methods of a SCS service.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClientBuilder.CreateClient``1(Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint,System.Object)">
+ <summary>
+ Creates a client to connect to a SCS service.
+ </summary>
+ <typeparam name="T">Type of service interface for remote method call</typeparam>
+ <param name="endpoint">EndPoint of the server</param>
+ <param name="clientObject">Client-side object that handles remote method calls from server to client.
+ May be null if client has no methods to be invoked by server</param>
+ <returns>Created client object to connect to the server</returns>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Client.ScsServiceClientBuilder.CreateClient``1(System.String,System.Object)">
+ <summary>
+ Creates a client to connect to a SCS service.
+ </summary>
+ <typeparam name="T">Type of service interface for remote method call</typeparam>
+ <param name="endpointAddress">EndPoint address of the server</param>
+ <param name="clientObject">Client-side object that handles remote method calls from server to client.
+ May be null if client has no methods to be invoked by server</param>
+ <returns>Created client object to connect to the server</returns>
+ </member>
+ <member name="T:Hik.Threading.SequentialItemProcessor`1">
+ <summary>
+ This class is used to process items sequentially in a multithreaded manner.
+ </summary>
+ <typeparam name="TItem">Type of item to process</typeparam>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._processMethod">
+ <summary>
+ The method delegate that is called to actually process items.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._queue">
+ <summary>
+ Item queue. Used to process items sequentially.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._currentProcessTask">
+ <summary>
+ A reference to the current Task that is processing an item in
+ ProcessItem method.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._isProcessing">
+ <summary>
+ Indicates state of the item processing.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._isRunning">
+ <summary>
+ A boolean value to control running of SequentialItemProcessor.
+ </summary>
+ </member>
+ <member name="F:Hik.Threading.SequentialItemProcessor`1._syncObj">
+ <summary>
+ An object to synchronize threads.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.SequentialItemProcessor`1.#ctor(System.Action{`0})">
+ <summary>
+ Creates a new SequentialItemProcessor object.
+ </summary>
+ <param name="processMethod">The method delegate that is called to actually process items</param>
+ </member>
+ <member name="M:Hik.Threading.SequentialItemProcessor`1.EnqueueMessage(`0)">
+ <summary>
+ Adds an item to queue to process the item.
+ </summary>
+ <param name="item">Item to add to the queue</param>
+ </member>
+ <member name="M:Hik.Threading.SequentialItemProcessor`1.Start">
+ <summary>
+ Starts processing of items.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.SequentialItemProcessor`1.Stop">
+ <summary>
+ Stops processing of items and waits stopping of current item.
+ </summary>
+ </member>
+ <member name="M:Hik.Threading.SequentialItemProcessor`1.ProcessItem">
+ <summary>
+ This method runs on a new seperated Task (thread) to process
+ items on the queue.
+ </summary>
+ </member>
+ <member name="T:Hik.Communication.Scs.Server.Tcp.ScsTcpServer">
+ <summary>
+ This class is used to create a TCP server.
+ </summary>
+ </member>
+ <member name="F:Hik.Communication.Scs.Server.Tcp.ScsTcpServer._endPoint">
+ <summary>
+ The endpoint address of the server to listen incoming connections.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.Tcp.ScsTcpServer.#ctor(Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint)">
+ <summary>
+ Creates a new ScsTcpServer object.
+ </summary>
+ <param name="endPoint">The endpoint address of the server to listen incoming connections</param>
+ </member>
+ <member name="M:Hik.Communication.Scs.Server.Tcp.ScsTcpServer.CreateConnectionListener">
+ <summary>
+ Creates a TCP connection listener.
+ </summary>
+ <returns>Created listener object</returns>
+ </member>
+ <member name="T:Hik.Communication.Scs.Communication.Protocols.WireProtocolManager">
+ <summary>
+ This class is used to get default protocols.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.WireProtocolManager.GetDefaultWireProtocolFactory">
+ <summary>
+ Creates a default wire protocol factory object to be used on communicating of applications.
+ </summary>
+ <returns>A new instance of default wire protocol</returns>
+ </member>
+ <member name="M:Hik.Communication.Scs.Communication.Protocols.WireProtocolManager.GetDefaultWireProtocol">
+ <summary>
+ Creates a default wire protocol object to be used on communicating of applications.
+ </summary>
+ <returns>A new instance of default wire protocol</returns>
+ </member>
+ <member name="T:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeReturnMessage">
+ <summary>
+ This message is sent as response message to a ScsRemoteInvokeMessage.
+ It is used to send return value of method invocation.
+ </summary>
+ </member>
+ <member name="M:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeReturnMessage.ToString">
+ <summary>
+ Represents this object as string.
+ </summary>
+ <returns>String representation of this object</returns>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeReturnMessage.ReturnValue">
+ <summary>
+ Return value of remote method invocation.
+ </summary>
+ </member>
+ <member name="P:Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeReturnMessage.RemoteException">
+ <summary>
+ If any exception occured during method invocation, this field contains Exception object.
+ If no exception occured, this field is null.
+ </summary>
+ </member>
+ </members>
+</doc>
diff --git a/binaries/Scs.dll b/binaries/Scs.dll
new file mode 100644
index 0000000..f3f6855
--- /dev/null
+++ b/binaries/Scs.dll
Binary files differ
diff --git a/performance-tests/Messaging/ClientApp/ClientApp.csproj b/performance-tests/Messaging/ClientApp/ClientApp.csproj
new file mode 100644
index 0000000..f34a440
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/ClientApp.csproj
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ClientApp</RootNamespace>
+ <AssemblyName>ClientApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DuplexClientCustomProtocolSynchronized.cs" />
+ <Compile Include="DuplexClientDefaultProtocolSynchronized.cs" />
+ <Compile Include="DuplexClientDefaultProtocol.cs" />
+ <Compile Include="OneWayClientDefaultProtocol.cs" />
+ <Compile Include="DuplexClientCustomProtocol.cs" />
+ <Compile Include="OneWayClientCustomProtocol.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CommonLib\CommonLib.csproj">
+ <Project>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</Project>
+ <Name>CommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocol.cs b/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocol.cs
new file mode 100644
index 0000000..016e6c6
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocol.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace ClientApp
+{
+ class DuplexClientCustomProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.WireProtocol = new MyWireProtocol(); //Set custom wire protocol!
+ client.MessageReceived += client_MessageReceived;
+
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ client.SendMessage(new ScsTextMessage("Hello from client!"));
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+
+ static void client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocolSynchronized.cs b/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocolSynchronized.cs
new file mode 100644
index 0000000..007fd63
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/DuplexClientCustomProtocolSynchronized.cs
@@ -0,0 +1,37 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace ClientApp
+{
+ class DuplexClientCustomProtocolSynchronized
+ {
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.WireProtocol = new MyWireProtocol();
+ using (var synchronizedMessenger = new SynchronizedMessenger<IScsClient>(client))
+ {
+ synchronizedMessenger.Start();
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ synchronizedMessenger.SendMessage(new ScsTextMessage("Hello from client!"));
+ var reply = synchronizedMessenger.ReceiveMessage<ScsTextMessage>();
+ }
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocol.cs b/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocol.cs
new file mode 100644
index 0000000..13a6e40
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocol.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace ClientApp
+{
+ class DuplexClientDefaultProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.MessageReceived += client_MessageReceived;
+
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ client.SendMessage(new ScsTextMessage("Hello from client!"));
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+
+ static void client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocolSynchronized.cs b/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocolSynchronized.cs
new file mode 100644
index 0000000..33d46ba
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/DuplexClientDefaultProtocolSynchronized.cs
@@ -0,0 +1,36 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace ClientApp
+{
+ class DuplexClientDefaultProtocolSynchronized
+ {
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ using (var synchronizedMessenger = new SynchronizedMessenger<IScsClient>(client))
+ {
+ synchronizedMessenger.Start();
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ synchronizedMessenger.SendMessage(new ScsTextMessage("Hello from client!"));
+ var reply = synchronizedMessenger.ReceiveMessage<ScsTextMessage>();
+ }
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/OneWayClientCustomProtocol.cs b/performance-tests/Messaging/ClientApp/OneWayClientCustomProtocol.cs
new file mode 100644
index 0000000..2d83559
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/OneWayClientCustomProtocol.cs
@@ -0,0 +1,32 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace ClientApp
+{
+ class OneWayClientCustomProtocol
+ {
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.WireProtocol = new MyWireProtocol();
+
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ client.SendMessage(new ScsTextMessage("Hello from client!"));
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/OneWayClientDefaultProtocol.cs b/performance-tests/Messaging/ClientApp/OneWayClientDefaultProtocol.cs
new file mode 100644
index 0000000..3d7ce3b
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/OneWayClientDefaultProtocol.cs
@@ -0,0 +1,30 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace ClientApp
+{
+ class OneWayClientDefaultProtocol
+ {
+ public static void Run()
+ {
+ Console.WriteLine("Press enter to connect to server and send " + Consts.MessageCount + " messages.");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.Connect();
+
+ for (var i = 0; i < Consts.MessageCount; i++)
+ {
+ client.SendMessage(new ScsTextMessage("Hello from client!"));
+ }
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/Program.cs b/performance-tests/Messaging/ClientApp/Program.cs
new file mode 100644
index 0000000..cee869d
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/Program.cs
@@ -0,0 +1,10 @@
+namespace ClientApp
+{
+ class Program
+ {
+ static void Main()
+ {
+ DuplexClientCustomProtocolSynchronized.Run();
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ClientApp/Properties/AssemblyInfo.cs b/performance-tests/Messaging/ClientApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7b4eed4
--- /dev/null
+++ b/performance-tests/Messaging/ClientApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ClientApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ClientApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("a9dbae74-bd80-4551-9ca8-bc212ea55174")]
+
+// 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")]
diff --git a/performance-tests/Messaging/CommonLib/CommonLib.csproj b/performance-tests/Messaging/CommonLib/CommonLib.csproj
new file mode 100644
index 0000000..7020b77
--- /dev/null
+++ b/performance-tests/Messaging/CommonLib/CommonLib.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CommonLib</RootNamespace>
+ <AssemblyName>CommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Consts.cs" />
+ <Compile Include="MyWireProtocol.cs" />
+ <Compile Include="MyWireProtocolFactory.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/Messaging/CommonLib/Consts.cs b/performance-tests/Messaging/CommonLib/Consts.cs
new file mode 100644
index 0000000..8eb31cf
--- /dev/null
+++ b/performance-tests/Messaging/CommonLib/Consts.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CommonLib
+{
+ public class Consts
+ {
+ public const int MessageCount = 1000000;
+ }
+}
diff --git a/performance-tests/Messaging/CommonLib/MyWireProtocol.cs b/performance-tests/Messaging/CommonLib/MyWireProtocol.cs
new file mode 100644
index 0000000..11227f4
--- /dev/null
+++ b/performance-tests/Messaging/CommonLib/MyWireProtocol.cs
@@ -0,0 +1,32 @@
+using System.Text;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Protocols.BinarySerialization;
+
+namespace CommonLib
+{
+ /// <summary>
+ /// This class is a sample custom wire protocol to use as wire protocol in SCS framework.
+ /// It extends BinarySerializationProtocol.
+ /// It is used just to send/receive ScsTextMessage messages.
+ ///
+ /// Since BinarySerializationProtocol automatically writes message length to the beggining
+ /// of the message, a message format of this class is:
+ ///
+ /// [Message length (4 bytes)][UTF-8 encoded text (N bytes)]
+ ///
+ /// So, total length of the message = (N + 4) bytes;
+ /// </summary>
+ public class MyWireProtocol : BinarySerializationProtocol
+ {
+ protected override byte[] SerializeMessage(IScsMessage message)
+ {
+ return Encoding.UTF8.GetBytes(((ScsTextMessage)message).Text);
+ }
+
+ protected override IScsMessage DeserializeMessage(byte[] bytes)
+ {
+ //Decode UTF8 encoded text and create a ScsTextMessage object
+ return new ScsTextMessage(Encoding.UTF8.GetString(bytes));
+ }
+ }
+}
diff --git a/performance-tests/Messaging/CommonLib/MyWireProtocolFactory.cs b/performance-tests/Messaging/CommonLib/MyWireProtocolFactory.cs
new file mode 100644
index 0000000..7f5f1ae
--- /dev/null
+++ b/performance-tests/Messaging/CommonLib/MyWireProtocolFactory.cs
@@ -0,0 +1,12 @@
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace CommonLib
+{
+ public class MyWireProtocolFactory : IScsWireProtocolFactory
+ {
+ public IScsWireProtocol CreateWireProtocol()
+ {
+ return new MyWireProtocol();
+ }
+ }
+}
diff --git a/performance-tests/Messaging/CommonLib/Properties/AssemblyInfo.cs b/performance-tests/Messaging/CommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8461698
--- /dev/null
+++ b/performance-tests/Messaging/CommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("CommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("50d012ed-8149-4bfb-8cb4-0f325628bdf7")]
+
+// 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")]
diff --git a/performance-tests/Messaging/ServerApp.sln b/performance-tests/Messaging/ServerApp.sln
new file mode 100644
index 0000000..10eed7d
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerApp", "ServerApp\ServerApp.csproj", "{F515CE95-6A3F-4E5E-867A-899FFFC90D43}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientApp", "ClientApp\ClientApp.csproj", "{8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLib", "CommonLib\CommonLib.csproj", "{7F7D3248-4432-4E7B-9CFD-25982668AD5B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|x86.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|x86.Build.0 = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Any CPU.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Mixed Platforms.Build.0 = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|x86.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|x86.Build.0 = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|x86.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|x86.Build.0 = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Any CPU.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Mixed Platforms.Build.0 = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|x86.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|x86.Build.0 = Release|x86
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/performance-tests/Messaging/ServerApp/DuplexServerCustomProtocol.cs b/performance-tests/Messaging/ServerApp/DuplexServerCustomProtocol.cs
new file mode 100644
index 0000000..88eafd9
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/DuplexServerCustomProtocol.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+namespace ServerApp
+{
+ public class DuplexServerCustomProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10033));
+
+ server.WireProtocolFactory = new MyWireProtocolFactory();
+ server.ClientConnected += server_ClientConnected;
+
+ server.Start();
+
+ Console.WriteLine("Press enter to stop server");
+ Console.ReadLine();
+
+ server.Stop();
+ }
+
+ static void server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+
+ var client = (IScsServerClient) sender;
+ client.SendMessage(new ScsTextMessage("Hello from server!"));
+
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ServerApp/DuplexServerDefaultProtocol.cs b/performance-tests/Messaging/ServerApp/DuplexServerDefaultProtocol.cs
new file mode 100644
index 0000000..8fbce3f
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/DuplexServerDefaultProtocol.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+namespace ServerApp
+{
+ public class DuplexServerDefaultProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10033));
+ server.ClientConnected += server_ClientConnected;
+
+ server.Start();
+
+ Console.WriteLine("Press enter to stop server");
+ Console.ReadLine();
+
+ server.Stop();
+ }
+
+ static void server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+
+ var client = (IScsServerClient) sender;
+ client.SendMessage(new ScsTextMessage("Hello from server!"));
+
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ServerApp/OneWayServerCustomProtocol.cs b/performance-tests/Messaging/ServerApp/OneWayServerCustomProtocol.cs
new file mode 100644
index 0000000..eb0da5f
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/OneWayServerCustomProtocol.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+namespace ServerApp
+{
+ public class OneWayServerCustomProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10033));
+
+ server.WireProtocolFactory = new MyWireProtocolFactory();
+ server.ClientConnected += server_ClientConnected;
+
+ server.Start();
+
+ Console.WriteLine("Press enter to stop server");
+ Console.ReadLine();
+
+ server.Stop();
+ }
+
+ static void server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ServerApp/OneWayServerDefaultProtocol.cs b/performance-tests/Messaging/ServerApp/OneWayServerDefaultProtocol.cs
new file mode 100644
index 0000000..fdf5887
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/OneWayServerDefaultProtocol.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Diagnostics;
+using CommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+namespace ServerApp
+{
+ public class OneWayServerDefaultProtocol
+ {
+ private static int _messageCount;
+ private static Stopwatch _stopwatch;
+
+ public static void Run()
+ {
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10033));
+ server.ClientConnected += server_ClientConnected;
+
+ server.Start();
+
+ Console.WriteLine("Press enter to stop server");
+ Console.ReadLine();
+
+ server.Stop();
+ }
+
+ static void server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ ++_messageCount;
+ if (_messageCount == 1)
+ {
+ _stopwatch = Stopwatch.StartNew();
+ }
+ else if (_messageCount == Consts.MessageCount)
+ {
+ _stopwatch.Stop();
+ Console.WriteLine(Consts.MessageCount + " message is received in " + _stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ServerApp/Program.cs b/performance-tests/Messaging/ServerApp/Program.cs
new file mode 100644
index 0000000..0aab3b5
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/Program.cs
@@ -0,0 +1,10 @@
+namespace ServerApp
+{
+ public class Program
+ {
+ static void Main()
+ {
+ DuplexServerCustomProtocol.Run();
+ }
+ }
+}
diff --git a/performance-tests/Messaging/ServerApp/Properties/AssemblyInfo.cs b/performance-tests/Messaging/ServerApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..125c23c
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ServerApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ServerApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("bae7ad3a-ea6a-44f7-8429-89f23b17abfe")]
+
+// 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")]
diff --git a/performance-tests/Messaging/ServerApp/ServerApp.csproj b/performance-tests/Messaging/ServerApp/ServerApp.csproj
new file mode 100644
index 0000000..f5a6c0f
--- /dev/null
+++ b/performance-tests/Messaging/ServerApp/ServerApp.csproj
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F515CE95-6A3F-4E5E-867A-899FFFC90D43}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ServerApp</RootNamespace>
+ <AssemblyName>ServerApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DuplexServerDefaultProtocol.cs" />
+ <Compile Include="OneWayServerCustomProtocol.cs" />
+ <Compile Include="DuplexServerCustomProtocol.cs" />
+ <Compile Include="OneWayServerDefaultProtocol.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CommonLib\CommonLib.csproj">
+ <Project>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</Project>
+ <Name>CommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/RMI/CalculatorClient/CalculatorClient.csproj b/performance-tests/RMI/CalculatorClient/CalculatorClient.csproj
new file mode 100644
index 0000000..d9b1a48
--- /dev/null
+++ b/performance-tests/RMI/CalculatorClient/CalculatorClient.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6DD6F730-E353-4B0C-9655-8370A943A7BF}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorClient</RootNamespace>
+ <AssemblyName>CalculatorClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CalculatorCommonLib\CalculatorCommonLib.csproj">
+ <Project>{6F2D58C9-0395-4048-A304-17304D12BC63}</Project>
+ <Name>CalculatorCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/RMI/CalculatorClient/Program.cs b/performance-tests/RMI/CalculatorClient/Program.cs
new file mode 100644
index 0000000..2532ea3
--- /dev/null
+++ b/performance-tests/RMI/CalculatorClient/Program.cs
@@ -0,0 +1,34 @@
+using System;
+using CalculatorCommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Client;
+using System.Diagnostics;
+
+namespace CalculatorClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.WriteLine("Press enter to connect to server and call " + Consts.MethodCallCount + " methods...");
+ Console.ReadLine();
+
+ using (var client = ScsServiceClientBuilder.CreateClient<ICalculatorService>(new ScsTcpEndPoint("127.0.0.1", 10083)))
+ {
+ client.Connect();
+
+ var stopwatch = Stopwatch.StartNew();
+ for (var i = 0; i < Consts.MethodCallCount; i++)
+ {
+ var division = client.ServiceProxy.Add(2, 3);
+ }
+
+ stopwatch.Stop();
+ Console.WriteLine(Consts.MethodCallCount + " remote method call made in " + stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + " ms.");
+ }
+
+ Console.WriteLine("Press enter to stop client application");
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/performance-tests/RMI/CalculatorClient/Properties/AssemblyInfo.cs b/performance-tests/RMI/CalculatorClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1c1a455
--- /dev/null
+++ b/performance-tests/RMI/CalculatorClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("5712ded0-d09a-4e56-8de4-1d9145854ee5")]
+
+// 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")]
diff --git a/performance-tests/RMI/CalculatorCommonLib/CalculatorCommonLib.csproj b/performance-tests/RMI/CalculatorCommonLib/CalculatorCommonLib.csproj
new file mode 100644
index 0000000..c5ac4f6
--- /dev/null
+++ b/performance-tests/RMI/CalculatorCommonLib/CalculatorCommonLib.csproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6F2D58C9-0395-4048-A304-17304D12BC63}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorCommonLib</RootNamespace>
+ <AssemblyName>CalculatorCommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Consts.cs" />
+ <Compile Include="ICalculatorService.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/RMI/CalculatorCommonLib/Consts.cs b/performance-tests/RMI/CalculatorCommonLib/Consts.cs
new file mode 100644
index 0000000..c220625
--- /dev/null
+++ b/performance-tests/RMI/CalculatorCommonLib/Consts.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CalculatorCommonLib
+{
+ public class Consts
+ {
+ public const int MethodCallCount = 1000000;
+ }
+}
diff --git a/performance-tests/RMI/CalculatorCommonLib/ICalculatorService.cs b/performance-tests/RMI/CalculatorCommonLib/ICalculatorService.cs
new file mode 100644
index 0000000..c04013f
--- /dev/null
+++ b/performance-tests/RMI/CalculatorCommonLib/ICalculatorService.cs
@@ -0,0 +1,15 @@
+using Hik.Communication.ScsServices.Service;
+
+namespace CalculatorCommonLib
+{
+ /// <summary>
+ /// This interface defines methods of calculator service that can be called by clients.
+ /// </summary>
+ [ScsService]
+ public interface ICalculatorService
+ {
+ int Add(int number1, int number2);
+
+ double Divide(double number1, double number2);
+ }
+}
diff --git a/performance-tests/RMI/CalculatorCommonLib/Properties/AssemblyInfo.cs b/performance-tests/RMI/CalculatorCommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4848095
--- /dev/null
+++ b/performance-tests/RMI/CalculatorCommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorCommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorCommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("8a08ef54-dde6-4f7a-8656-57518c5098ea")]
+
+// 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")]
diff --git a/performance-tests/RMI/CalculatorServer/CalculatorServer.csproj b/performance-tests/RMI/CalculatorServer/CalculatorServer.csproj
new file mode 100644
index 0000000..259762d
--- /dev/null
+++ b/performance-tests/RMI/CalculatorServer/CalculatorServer.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1BB6B428-E4C3-467F-824F-1DB84E310FF2}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorServer</RootNamespace>
+ <AssemblyName>CalculatorServer</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CalculatorCommonLib\CalculatorCommonLib.csproj">
+ <Project>{6F2D58C9-0395-4048-A304-17304D12BC63}</Project>
+ <Name>CalculatorCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/performance-tests/RMI/CalculatorServer/Program.cs b/performance-tests/RMI/CalculatorServer/Program.cs
new file mode 100644
index 0000000..8ec07ef
--- /dev/null
+++ b/performance-tests/RMI/CalculatorServer/Program.cs
@@ -0,0 +1,46 @@
+using System;
+using CalculatorCommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Service;
+
+namespace CalculatorServer
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a service application that runs on 10083 TCP port
+ var serviceApplication = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(10083));
+
+ //Create a CalculatorService and add it to service application
+ serviceApplication.AddService<ICalculatorService, CalculatorService>(new CalculatorService());
+
+ //Start service application
+ serviceApplication.Start();
+
+ Console.WriteLine("Calculator service is started. Press enter to stop...");
+ Console.ReadLine();
+
+ //Stop service application
+ serviceApplication.Stop();
+ }
+ }
+
+ public class CalculatorService : ScsService, ICalculatorService
+ {
+ public int Add(int number1, int number2)
+ {
+ return number1 + number2;
+ }
+
+ public double Divide(double number1, double number2)
+ {
+ if(number2 == 0.0)
+ {
+ throw new DivideByZeroException("number2 can not be zero!");
+ }
+
+ return number1 / number2;
+ }
+ }
+}
diff --git a/performance-tests/RMI/CalculatorServer/Properties/AssemblyInfo.cs b/performance-tests/RMI/CalculatorServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..46a9398
--- /dev/null
+++ b/performance-tests/RMI/CalculatorServer/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorServer")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("fc3f0ecf-46ea-437e-a535-82dffae3dc9e")]
+
+// 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")]
diff --git a/performance-tests/RMI/SimpleCalculatorSystem.sln b/performance-tests/RMI/SimpleCalculatorSystem.sln
new file mode 100644
index 0000000..236647f
--- /dev/null
+++ b/performance-tests/RMI/SimpleCalculatorSystem.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorServer", "CalculatorServer\CalculatorServer.csproj", "{1BB6B428-E4C3-467F-824F-1DB84E310FF2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorCommonLib", "CalculatorCommonLib\CalculatorCommonLib.csproj", "{6F2D58C9-0395-4048-A304-17304D12BC63}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorClient", "CalculatorClient\CalculatorClient.csproj", "{6DD6F730-E353-4B0C-9655-8370A943A7BF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|x86.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|x86.Build.0 = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Any CPU.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Mixed Platforms.Build.0 = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|x86.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|x86.Build.0 = Release|x86
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|x86.ActiveCfg = Release|Any CPU
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|x86.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|x86.Build.0 = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Any CPU.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Mixed Platforms.Build.0 = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|x86.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/CustomWireProtocol/ClientApp/ClientApp.csproj b/samples/CustomWireProtocol/ClientApp/ClientApp.csproj
new file mode 100644
index 0000000..a4f4557
--- /dev/null
+++ b/samples/CustomWireProtocol/ClientApp/ClientApp.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ClientApp</RootNamespace>
+ <AssemblyName>ClientApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CommonLib\CommonLib.csproj">
+ <Project>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</Project>
+ <Name>CommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/CustomWireProtocol/ClientApp/Program.cs b/samples/CustomWireProtocol/ClientApp/Program.cs
new file mode 100644
index 0000000..006c09a
--- /dev/null
+++ b/samples/CustomWireProtocol/ClientApp/Program.cs
@@ -0,0 +1,32 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+/* This application is build to demonstrate a CUSTOM WIRE PROTOCOL usage with SCS framework.
+ * This client application connects to a server and sends a message using MyWireProtocol class.
+ */
+
+namespace ClientApp
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.WriteLine("Press enter to connect to server and say Hello world!");
+ Console.ReadLine();
+
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10033)))
+ {
+ client.WireProtocol = new MyWireProtocol(); //Set custom wire protocol!
+
+ client.Connect();
+ client.SendMessage(new ScsTextMessage("Hello world!"));
+
+ Console.WriteLine("Press enter to disconnect from server");
+ Console.ReadLine();
+ }
+ }
+ }
+}
diff --git a/samples/CustomWireProtocol/ClientApp/Properties/AssemblyInfo.cs b/samples/CustomWireProtocol/ClientApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7b4eed4
--- /dev/null
+++ b/samples/CustomWireProtocol/ClientApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ClientApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ClientApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("a9dbae74-bd80-4551-9ca8-bc212ea55174")]
+
+// 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")]
diff --git a/samples/CustomWireProtocol/CommonLib/CommonLib.csproj b/samples/CustomWireProtocol/CommonLib/CommonLib.csproj
new file mode 100644
index 0000000..93fb6fb
--- /dev/null
+++ b/samples/CustomWireProtocol/CommonLib/CommonLib.csproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CommonLib</RootNamespace>
+ <AssemblyName>CommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MyWireProtocol.cs" />
+ <Compile Include="MyWireProtocolFactory.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/CustomWireProtocol/CommonLib/MyWireProtocol.cs b/samples/CustomWireProtocol/CommonLib/MyWireProtocol.cs
new file mode 100644
index 0000000..11227f4
--- /dev/null
+++ b/samples/CustomWireProtocol/CommonLib/MyWireProtocol.cs
@@ -0,0 +1,32 @@
+using System.Text;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Protocols.BinarySerialization;
+
+namespace CommonLib
+{
+ /// <summary>
+ /// This class is a sample custom wire protocol to use as wire protocol in SCS framework.
+ /// It extends BinarySerializationProtocol.
+ /// It is used just to send/receive ScsTextMessage messages.
+ ///
+ /// Since BinarySerializationProtocol automatically writes message length to the beggining
+ /// of the message, a message format of this class is:
+ ///
+ /// [Message length (4 bytes)][UTF-8 encoded text (N bytes)]
+ ///
+ /// So, total length of the message = (N + 4) bytes;
+ /// </summary>
+ public class MyWireProtocol : BinarySerializationProtocol
+ {
+ protected override byte[] SerializeMessage(IScsMessage message)
+ {
+ return Encoding.UTF8.GetBytes(((ScsTextMessage)message).Text);
+ }
+
+ protected override IScsMessage DeserializeMessage(byte[] bytes)
+ {
+ //Decode UTF8 encoded text and create a ScsTextMessage object
+ return new ScsTextMessage(Encoding.UTF8.GetString(bytes));
+ }
+ }
+}
diff --git a/samples/CustomWireProtocol/CommonLib/MyWireProtocolFactory.cs b/samples/CustomWireProtocol/CommonLib/MyWireProtocolFactory.cs
new file mode 100644
index 0000000..7f5f1ae
--- /dev/null
+++ b/samples/CustomWireProtocol/CommonLib/MyWireProtocolFactory.cs
@@ -0,0 +1,12 @@
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace CommonLib
+{
+ public class MyWireProtocolFactory : IScsWireProtocolFactory
+ {
+ public IScsWireProtocol CreateWireProtocol()
+ {
+ return new MyWireProtocol();
+ }
+ }
+}
diff --git a/samples/CustomWireProtocol/CommonLib/Properties/AssemblyInfo.cs b/samples/CustomWireProtocol/CommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8461698
--- /dev/null
+++ b/samples/CustomWireProtocol/CommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("CommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("50d012ed-8149-4bfb-8cb4-0f325628bdf7")]
+
+// 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")]
diff --git a/samples/CustomWireProtocol/ServerApp.sln b/samples/CustomWireProtocol/ServerApp.sln
new file mode 100644
index 0000000..10eed7d
--- /dev/null
+++ b/samples/CustomWireProtocol/ServerApp.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerApp", "ServerApp\ServerApp.csproj", "{F515CE95-6A3F-4E5E-867A-899FFFC90D43}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientApp", "ClientApp\ClientApp.csproj", "{8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLib", "CommonLib\CommonLib.csproj", "{7F7D3248-4432-4E7B-9CFD-25982668AD5B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|x86.ActiveCfg = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Debug|x86.Build.0 = Debug|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Any CPU.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|Mixed Platforms.Build.0 = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|x86.ActiveCfg = Release|x86
+ {F515CE95-6A3F-4E5E-867A-899FFFC90D43}.Release|x86.Build.0 = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|x86.ActiveCfg = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Debug|x86.Build.0 = Debug|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Any CPU.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|Mixed Platforms.Build.0 = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|x86.ActiveCfg = Release|x86
+ {8D1CD669-49E3-4F7E-98B1-6E4405BEBAD6}.Release|x86.Build.0 = Release|x86
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {7F7D3248-4432-4E7B-9CFD-25982668AD5B}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/CustomWireProtocol/ServerApp/Program.cs b/samples/CustomWireProtocol/ServerApp/Program.cs
new file mode 100644
index 0000000..593dadf
--- /dev/null
+++ b/samples/CustomWireProtocol/ServerApp/Program.cs
@@ -0,0 +1,41 @@
+using System;
+using CommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+/* This application is build to demonstrate a CUSTOM WIRE PROTOCOL usage with SCS framework.
+ * This server application listens incoming messages from client applications using MyWireProtocol class.
+ */
+
+namespace ServerApp
+{
+ public class Program
+ {
+ static void Main()
+ {
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10033));
+
+ server.WireProtocolFactory = new MyWireProtocolFactory(); //Set custom wire protocol factory!
+ server.ClientConnected += server_ClientConnected;
+
+ server.Start();
+
+ Console.WriteLine("Press enter to stop server");
+ Console.ReadLine();
+
+ server.Stop();
+ }
+
+ static void server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ Console.WriteLine("A new client is connected. Address: " + e.Client.RemoteEndPoint);
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ Console.WriteLine("A client sent a message: " + ((ScsTextMessage) e.Message).Text);
+ }
+ }
+}
diff --git a/samples/CustomWireProtocol/ServerApp/Properties/AssemblyInfo.cs b/samples/CustomWireProtocol/ServerApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..125c23c
--- /dev/null
+++ b/samples/CustomWireProtocol/ServerApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ServerApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ServerApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("bae7ad3a-ea6a-44f7-8429-89f23b17abfe")]
+
+// 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")]
diff --git a/samples/CustomWireProtocol/ServerApp/ServerApp.csproj b/samples/CustomWireProtocol/ServerApp/ServerApp.csproj
new file mode 100644
index 0000000..b624302
--- /dev/null
+++ b/samples/CustomWireProtocol/ServerApp/ServerApp.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F515CE95-6A3F-4E5E-867A-899FFFC90D43}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ServerApp</RootNamespace>
+ <AssemblyName>ServerApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CommonLib\CommonLib.csproj">
+ <Project>{7F7D3248-4432-4E7B-9CFD-25982668AD5B}</Project>
+ <Name>CommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/ChatClientApp.csproj b/samples/IrcChatSystem/ChatClientApp/ChatClientApp.csproj
new file mode 100644
index 0000000..6215d05
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/ChatClientApp.csproj
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6571B5F6-C92F-4266-ACC9-186347994E9F}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Hik.Samples.Scs.IrcChat</RootNamespace>
+ <AssemblyName>ChatClientApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject>Hik.Samples.Scs.IrcChat.ChatClientApplication</StartupObject>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationIcon>Images\app_icon.ico</ApplicationIcon>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="ChatClientApplication.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Compile Include="Client\ChatClient.cs" />
+ <Compile Include="Client\ChatController.cs" />
+ <Compile Include="Client\ClientHelper.cs" />
+ <Compile Include="Client\IChatController.cs" />
+ <Compile Include="Client\IChatRoomView.cs" />
+ <Compile Include="Client\ILoginFormView.cs" />
+ <Compile Include="Client\UserPreferences.cs" />
+ <Compile Include="Client\WindowsHelper.cs" />
+ <Compile Include="Controls\IMessagingAreaContainer.xaml.cs" />
+ <Compile Include="Controls\MessagingAreaControl.xaml.cs">
+ <DependentUpon>MessagingAreaControl.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Controls\UserCardControl.xaml.cs">
+ <DependentUpon>UserCardControl.xaml</DependentUpon>
+ </Compile>
+ <Page Include="Controls\MessagingAreaControl.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Windows\PrivateChatWindow.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Windows\TextColorPicker.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Windows\MainWindow.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Compile Include="ChatClientApplication.xaml.cs">
+ <DependentUpon>ChatClientApplication.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Windows\PrivateChatWindow.xaml.cs">
+ <DependentUpon>PrivateChatWindow.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Windows\TextColorPicker.xaml.cs">
+ <DependentUpon>TextColorPicker.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Windows\MainWindow.xaml.cs">
+ <DependentUpon>MainWindow.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Page Include="Controls\UserCardControl.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <AppDesigner Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ChatCommonLib\ChatCommonLib.csproj">
+ <Project>{A57047DE-CC39-4C01-955E-D73888A0C83D}</Project>
+ <Name>ChatCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Sounds\incoming_message.wav">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Resource Include="Images\app_icon.ico" />
+ <Resource Include="Images\text_color_picker.ico" />
+ <Content Include="Images\sound_on.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Images\sound_off.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Images\user_female.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Images\user_male.png">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml b/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml
new file mode 100644
index 0000000..ce81fc7
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml
@@ -0,0 +1,16 @@
+<Application x:Class="Hik.Samples.Scs.IrcChat.ChatClientApplication"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Application.Resources>
+ <Style TargetType="Border">
+ <Setter Property="BorderThickness" Value="1"></Setter>
+ <Setter Property="BorderBrush" Value="#FF878383"></Setter>
+ <Setter Property="CornerRadius" Value="6"></Setter>
+ <Setter Property="Background" Value="#FF111111" />
+ </Style>
+ <LinearGradientBrush x:Key="GreenButtonBackGround" EndPoint="0.5,1" StartPoint="0.5,0">
+ <GradientStop Color="#FF239032" Offset="0" />
+ <GradientStop Color="#FF003205" Offset="1" />
+ </LinearGradientBrush>
+ </Application.Resources>
+</Application>
diff --git a/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml.cs b/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml.cs
new file mode 100644
index 0000000..26a2b21
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/ChatClientApplication.xaml.cs
@@ -0,0 +1,26 @@
+using System.Windows;
+using Hik.Samples.Scs.IrcChat.Client;
+using Hik.Samples.Scs.IrcChat.Windows;
+
+namespace Hik.Samples.Scs.IrcChat
+{
+ /// <summary>
+ /// Interaction logic for App.xaml
+ /// </summary>
+ public partial class ChatClientApplication : Application
+ {
+ public ChatClientApplication()
+ {
+ Startup += AppStartUp;
+ }
+
+ static void AppStartUp(object sender, StartupEventArgs e)
+ {
+ var controller = new ChatController();
+ var mainWindow = new MainWindow(controller);
+ controller.ChatRoom = mainWindow;
+ controller.LoginForm = mainWindow;
+ mainWindow.Show();
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs b/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs
new file mode 100644
index 0000000..709df89
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs
@@ -0,0 +1,103 @@
+using System;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Contracts;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This class implements IChatClient to use to be invoked by Chat Server.
+ /// </summary>
+ internal class ChatClient : IChatClient
+ {
+ #region Private fields
+
+ /// <summary>
+ /// Reference to Chat Room window.
+ /// </summary>
+ private readonly IChatRoomView _chatRoom;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new ChatClient.
+ /// </summary>
+ /// <param name="chatRoom">Reference to Chat Room window</param>
+ public ChatClient(IChatRoomView chatRoom)
+ {
+ _chatRoom = chatRoom;
+ }
+
+ #endregion
+
+ #region IChatClient implementation
+
+ /// <summary>
+ /// This method is used to get user list from chat server.
+ /// It is called by server, once after user logged in to server.
+ /// </summary>
+ /// <param name="users">All online user informations</param>
+ public void GetUserList(UserInfo[] users)
+ {
+ foreach (var user in users)
+ {
+ _chatRoom.AddUserToList(user);
+ }
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that a message
+ /// is sent to chat room publicly.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message text</param>
+ public void OnMessageToRoom(string nick, ChatMessage message)
+ {
+ _chatRoom.OnMessageReceived(nick, message);
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that a message
+ /// is sent to the current used privately.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ public void OnPrivateMessage(string nick, ChatMessage message)
+ {
+ _chatRoom.OnPrivateMessageReceived(nick, message);
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that a new user
+ /// joined to chat room.
+ /// </summary>
+ /// <param name="userInfo">Informations of new user</param>
+ public void OnUserLogin(UserInfo userInfo)
+ {
+ _chatRoom.AddUserToList(userInfo);
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that an existing user
+ /// has left the chat room.
+ /// </summary>
+ /// <param name="nick">Informations of new user</param>
+ public void OnUserLogout(string nick)
+ {
+ _chatRoom.RemoveUserFromList(nick);
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that a user changed his/her status.
+ /// </summary>
+ /// <param name="nick">Nick of the user</param>
+ /// <param name="newStatus">New status of the user</param>
+ public void OnUserStatusChange(string nick, UserStatus newStatus)
+ {
+ _chatRoom.OnUserStatusChange(nick, newStatus);
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs b/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs
new file mode 100644
index 0000000..91a2241
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs
@@ -0,0 +1,155 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Client;
+using Hik.Communication.ScsServices.Communication.Messages;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Contracts;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This class is a mediator with view and SCS system.
+ /// </summary>
+ internal class ChatController : IChatController
+ {
+ #region Private fields
+
+ /// <summary>
+ /// Reference to login form.
+ /// </summary>
+ public ILoginFormView LoginForm { get; set; }
+
+ /// <summary>
+ /// Reference to chat room window.
+ /// </summary>
+ public IChatRoomView ChatRoom { get; set; }
+
+ /// <summary>
+ /// The object which handles remote method calls from server.
+ /// It implements IChatClient contract.
+ /// </summary>
+ private ChatClient _chatClient;
+
+ /// <summary>
+ /// This object is used to connect to SCS Chat Service as a client.
+ /// </summary>
+ private IScsServiceClient<IChatService> _scsClient;
+
+ #endregion
+
+ #region IChatController implementation
+
+ /// <summary>
+ /// Connects to the server.
+ /// It automatically Logins to server if connection success.
+ /// </summary>
+ public void Connect()
+ {
+ //Disconnect if currently connected
+ Disconnect();
+
+ //Create a ChatClient to handle remote method invocations by server
+ _chatClient = new ChatClient(ChatRoom);
+
+ //Create a SCS client to connect to SCS server
+ _scsClient = ScsServiceClientBuilder.CreateClient<IChatService>(new ScsTcpEndPoint(LoginForm.ServerIpAddress, LoginForm.ServerTcpPort), _chatClient);
+
+ //Register events of SCS client
+ _scsClient.Connected += ScsClient_Connected;
+ _scsClient.Disconnected += ScsClient_Disconnected;
+
+ //Connect to the server
+ _scsClient.Connect();
+ }
+
+ /// <summary>
+ /// Disconnects from server if it is connected.
+ /// </summary>
+ public void Disconnect()
+ {
+ if (_scsClient != null && _scsClient.CommunicationState == CommunicationStates.Connected)
+ {
+ try
+ {
+ _scsClient.Disconnect();
+ }
+ catch
+ {
+
+ }
+
+ _scsClient = null;
+ }
+ }
+
+ /// <summary>
+ /// Sends a public message to room.
+ /// It will be seen by all users in room.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ public void SendMessageToRoom(ChatMessage message)
+ {
+ _scsClient.ServiceProxy.SendMessageToRoom(message);
+ }
+
+ /// <summary>
+ /// Change status of user.
+ /// </summary>
+ /// <param name="newStatus">New status</param>
+ public void ChangeStatus(UserStatus newStatus)
+ {
+ _scsClient.ServiceProxy.ChangeStatus(newStatus);
+ }
+
+ /// <summary>
+ /// Sends a private message to a user.
+ /// </summary>
+ /// <param name="nick">Destination nick</param>
+ /// <param name="message">Message</param>
+ public void SendPrivateMessage(string nick, ChatMessage message)
+ {
+ _scsClient.ServiceProxy.SendPrivateMessage(nick, message);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// This method handles Connected event of _scsClient.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ScsClient_Connected(object sender, EventArgs e)
+ {
+ try
+ {
+ _scsClient.ServiceProxy.Login(LoginForm.CurrentUserInfo);
+ ChatRoom.OnLoggedIn();
+ }
+ catch (ScsRemoteException ex)
+ {
+ Disconnect();
+ ChatRoom.OnLoginError(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
+ }
+ catch
+ {
+ Disconnect();
+ ChatRoom.OnLoginError("Can not login to server. Please try again later.");
+ }
+ }
+
+ /// <summary>
+ /// This method handles Disconnected event of _scsClient.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ScsClient_Disconnected(object sender, EventArgs e)
+ {
+ ChatRoom.OnLoggedOut();
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs b/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs
new file mode 100644
index 0000000..9b417db
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs
@@ -0,0 +1,93 @@
+using System.IO;
+using System.Media;
+using System.Reflection;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This class includes come helper methods that are using in chat client.
+ /// </summary>
+ public static class ClientHelper
+ {
+ /// <summary>
+ /// Gets the directory of executing assembly.
+ /// </summary>
+ /// <returns>Current directory</returns>
+ public static string GetCurrentDirectory()
+ {
+ return (new FileInfo(Assembly.GetExecutingAssembly().Location)).Directory.FullName;
+ }
+
+ /// <summary>
+ /// Gets the size of a file as bytes
+ /// </summary>
+ /// <param name="filePath">Path of file</param>
+ /// <returns>Size of file</returns>
+ public static long GetFileSize(string filePath)
+ {
+ using (var file = File.Open(filePath, FileMode.Open))
+ {
+ var lengthOfFile = file.Length;
+ file.Close();
+ return lengthOfFile;
+ }
+ }
+
+ /// <summary>
+ /// Serializes an object and writes it to a file.
+ /// Uses .NET binary serialization.
+ /// </summary>
+ /// <param name="obj">object to be serialized</param>
+ /// <param name="filePath">Path of file to serialize</param>
+ /// <returns>bytes of object</returns>
+ public static void SerializeObjectToFile(object obj, string filePath)
+ {
+ using (var file = new FileStream(filePath, FileMode.Create))
+ {
+ new BinaryFormatter().Serialize(file, obj);
+ file.Flush();
+ }
+ }
+
+ /// <summary>
+ /// Deserializes an object from a file.
+ /// Uses .NET binary deserialization.
+ /// </summary>
+ /// <param name="filePath">Path of file to deserialize</param>
+ /// <returns>deserialized object</returns>
+ public static object DeserializeObjectFromFile(string filePath)
+ {
+ using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ return new BinaryFormatter().Deserialize(file);
+ }
+ }
+
+ /// <summary>
+ /// Plays incoming message sound (if sound is on).
+ /// </summary>
+ public static void PlayIncomingMessageSound()
+ {
+ if (!UserPreferences.Current.IsSoundOn)
+ {
+ return;
+ }
+
+ try
+ {
+ var filePath = Path.Combine(GetCurrentDirectory(), @"Sounds\incoming_message.wav");
+ if (!File.Exists(filePath))
+ {
+ return;
+ }
+
+ new SoundPlayer(filePath).Play();
+ }
+ catch
+ {
+
+ }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs b/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs
new file mode 100644
index 0000000..4fd90cf
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs
@@ -0,0 +1,41 @@
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This interface defines method of chat controller that can be used by views.
+ /// </summary>
+ public interface IChatController
+ {
+ /// <summary>
+ /// Connects to the server.
+ /// It automatically Logins to server if connection success.
+ /// </summary>
+ void Connect();
+
+ /// <summary>
+ /// Disconnects from server if it is connected.
+ /// </summary>
+ void Disconnect();
+
+ /// <summary>
+ /// Sends a public message to room.
+ /// It will be seen all users in room.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ void SendMessageToRoom(ChatMessage message);
+
+ /// <summary>
+ /// Change status of user.
+ /// </summary>
+ /// <param name="newStatus">New status</param>
+ void ChangeStatus(UserStatus newStatus);
+
+ /// <summary>
+ /// Sends a private message to a user.
+ /// </summary>
+ /// <param name="nick">Destination nick</param>
+ /// <param name="message">Message</param>
+ void SendPrivateMessage(string nick, ChatMessage message);
+ }
+} \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs b/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs
new file mode 100644
index 0000000..b5f11a8
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs
@@ -0,0 +1,60 @@
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This interface is used to interact with main chat room window by ChatController.
+ /// It is implemented by main window.
+ /// </summary>
+ public interface IChatRoomView
+ {
+ /// <summary>
+ /// This method is called when a message is sent to chat room.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ void OnMessageReceived(string nick, ChatMessage message);
+
+ /// <summary>
+ /// This method is called when a private message is sent to the current user.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">The message</param>
+ void OnPrivateMessageReceived(string nick, ChatMessage message);
+
+ /// <summary>
+ /// This method is called when user successfully logged in to chat server.
+ /// </summary>
+ void OnLoggedIn();
+
+ /// <summary>
+ /// This method is used to inform view if login is failed.
+ /// </summary>
+ /// <param name="errorMessage">Detail of error</param>
+ void OnLoginError(string errorMessage);
+
+ /// <summary>
+ /// This method is called when connection to server is closed.
+ /// </summary>
+ void OnLoggedOut();
+
+ /// <summary>
+ /// This methos is used to add a new user to user list in room view.
+ /// </summary>
+ /// <param name="userInfo">Informations of new user</param>
+ void AddUserToList(UserInfo userInfo);
+
+ /// <summary>
+ /// This metrhod is used to remove a user (that is disconnected from server) from user list in room view.
+ /// </summary>
+ /// <param name="nick">Nick of user to remove</param>
+ void RemoveUserFromList(string nick);
+
+ /// <summary>
+ /// This method is called from chat server to inform that a user changed his/her status.
+ /// </summary>
+ /// <param name="nick">Nick of the user</param>
+ /// <param name="newStatus">New status of the user</param>
+ void OnUserStatusChange(string nick, UserStatus newStatus);
+ }
+} \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs b/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs
new file mode 100644
index 0000000..1f746d9
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs
@@ -0,0 +1,26 @@
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This interface is used to interact with login form by ChatController.
+ /// ChatController gets user informations over this interface.
+ /// </summary>
+ public interface ILoginFormView
+ {
+ /// <summary>
+ /// IP address of server to be connected.
+ /// </summary>
+ string ServerIpAddress { get; }
+
+ /// <summary>
+ /// TCP Port number of server to be connected.
+ /// </summary>
+ int ServerTcpPort { get; }
+
+ /// <summary>
+ /// User Login informations to be used while logging on to the server.
+ /// </summary>
+ UserInfo CurrentUserInfo { get; }
+ }
+} \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs b/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs
new file mode 100644
index 0000000..64143c6
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This class is used to save and load preferences of the user.
+ /// </summary>
+ [Serializable]
+ internal class UserPreferences
+ {
+ /// <summary>
+ /// Gets the singleton instance of this class.
+ /// </summary>
+ public static UserPreferences Current
+ {
+ get
+ {
+ if (_current == null)
+ {
+ lock (SyncObj)
+ {
+ if (_current == null)
+ {
+ _current = LoadPreferences();
+ }
+ }
+ }
+
+ return _current;
+ }
+ }
+
+ /// <summary>
+ /// Nick of the user.
+ /// </summary>
+ public string Nick { get; set; }
+
+ /// <summary>
+ /// Path of user's avatar file.
+ /// </summary>
+ public string AvatarFile { get; set; }
+
+ /// <summary>
+ /// Sound preference of user.
+ /// True if sound is on.
+ /// </summary>
+ public bool IsSoundOn { get; set; }
+
+ /// <summary>
+ /// Ip address of the chat server.
+ /// </summary>
+ public string ServerIpAddress { get; set; }
+
+ /// <summary>
+ /// TCP port of the chat server.
+ /// </summary>
+ public int ServerTcpPort { get; set; }
+
+ /// <summary>
+ /// Text style of user.
+ /// </summary>
+ public MessageTextStyle TextStyle { get; private set; }
+
+ /// <summary>
+ /// The singleton instance of this class.
+ /// </summary>
+ private static UserPreferences _current;
+
+ /// <summary>
+ /// Used to synronize threads while creating singleton object.
+ /// </summary>
+ private static readonly object SyncObj = new object();
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ private UserPreferences()
+ {
+ IsSoundOn = true;
+ TextStyle = new MessageTextStyle();
+ }
+
+ /// <summary>
+ /// Saves preferences to the disc.
+ /// </summary>
+ public void Save()
+ {
+ try
+ {
+ ClientHelper.SerializeObjectToFile(
+ this,
+ Path.Combine(ClientHelper.GetCurrentDirectory(), "Preferences.bin")
+ );
+ }
+ catch
+ {
+
+ }
+ }
+
+ /// <summary>
+ /// Load last preferences from the disc.
+ /// </summary>
+ /// <returns>Last user preferences (or default values if not found)</returns>
+ private static UserPreferences LoadPreferences()
+ {
+ try
+ {
+ var preferenceFile = Path.Combine(ClientHelper.GetCurrentDirectory(), "Preferences.bin");
+ if (File.Exists(preferenceFile))
+ {
+ return (UserPreferences)ClientHelper.DeserializeObjectFromFile(preferenceFile);
+ }
+ }
+ catch
+ {
+
+ }
+
+ return CreateDefault();
+ }
+
+ /// <summary>
+ /// Creates a default-valued instance of this class.
+ /// </summary>
+ /// <returns>UserPreferences object with default values</returns>
+ private static UserPreferences CreateDefault()
+ {
+ return new UserPreferences
+ {
+ Nick = "User Nick",
+ AvatarFile = Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\user_male.png"),
+ ServerIpAddress = "127.0.0.1",
+ ServerTcpPort = 10048
+ };
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs b/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs
new file mode 100644
index 0000000..517bc1d
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Hik.Samples.Scs.IrcChat.Client
+{
+ /// <summary>
+ /// This class is used to flash window caption / taskbar button when a message received
+ /// and window is not active.
+ /// </summary>
+ public static class WindowsHelper
+ {
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FLASHWINFO
+ {
+ /// <summary>
+ /// The size of the structure in bytes.
+ /// </summary>
+ public uint cbSize;
+ /// <summary>
+ /// A Handle to the Window to be Flashed. The window can be either opened or minimized.
+ /// </summary>
+ public IntPtr hwnd;
+ /// <summary>
+ /// The Flash Status.
+ /// </summary>
+ public FlashWindowFlags dwFlags; //uint
+ /// <summary>
+ /// The number of times to Flash the window.
+ /// </summary>
+ public uint uCount;
+ /// <summary>
+ /// The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate.
+ /// </summary>
+ public uint dwTimeout;
+ }
+
+ public enum FlashWindowFlags : uint
+ {
+ /// <summary>
+ /// Stop flashing. The system restores the window to its original state.
+ /// </summary>
+ FLASHW_STOP = 0,
+
+ /// <summary>
+ /// Flash the window caption.
+ /// </summary>
+ FLASHW_CAPTION = 1,
+
+ /// <summary>
+ /// Flash the taskbar button.
+ /// </summary>
+ FLASHW_TRAY = 2,
+
+ /// <summary>
+ /// Flash both the window caption and taskbar button.
+ /// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
+ /// </summary>
+ FLASHW_ALL = 3,
+
+ /// <summary>
+ /// Flash continuously, until the FLASHW_STOP flag is set.
+ /// </summary>
+ FLASHW_TIMER = 4,
+
+ /// <summary>
+ /// Flash continuously until the window comes to the foreground.
+ /// </summary>
+ FLASHW_TIMERNOFG = 12
+ }
+
+
+ public static bool FlashWindow(IntPtr hWnd,
+ FlashWindowFlags fOptions,
+ uint FlashCount,
+ uint FlashRate)
+ {
+ if (IntPtr.Zero != hWnd)
+ {
+ FLASHWINFO fi = new FLASHWINFO();
+ fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO));
+ fi.dwFlags = fOptions;
+ fi.uCount = FlashCount;
+ fi.dwTimeout = FlashRate;
+ fi.hwnd = hWnd;
+
+ return FlashWindowEx(ref fi);
+ }
+ return false;
+ }
+
+ public static bool StopFlashingWindow(IntPtr hWnd)
+ {
+ if (IntPtr.Zero != hWnd)
+ {
+ FLASHWINFO fi = new FLASHWINFO();
+ fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO));
+ fi.dwFlags = (uint)FlashWindowFlags.FLASHW_STOP;
+ fi.hwnd = hWnd;
+
+ return FlashWindowEx(ref fi);
+ }
+ return false;
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Controls/IMessagingAreaContainer.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Controls/IMessagingAreaContainer.xaml.cs
new file mode 100644
index 0000000..d55ee92
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Controls/IMessagingAreaContainer.xaml.cs
@@ -0,0 +1,16 @@
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Controls
+{
+ /// <summary>
+ /// This interface defines methods of windows which contains a MessagingAreaControl.
+ /// </summary>
+ public interface IMessagingAreaContainer
+ {
+ /// <summary>
+ /// This method is used by MessagingAreaControl to send messages.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ void SendMessage(ChatMessage message);
+ }
+} \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml b/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml
new file mode 100644
index 0000000..5be12fb
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml
@@ -0,0 +1,61 @@
+<UserControl x:Class="Hik.Samples.Scs.IrcChat.Controls.MessagingAreaControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ mc:Ignorable="d"
+ d:DesignHeight="482" d:DesignWidth="677">
+ <Border Grid.Column="0" Margin="5,5,0,5">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*" />
+ <RowDefinition Height="60" />
+ </Grid.RowDefinitions>
+ <DockPanel LastChildFill="True">
+ <StackPanel Name="spTextStyleChanging" DockPanel.Dock="Bottom" Height="30" Grid.Row="1" Orientation="Horizontal">
+ <Label Name="lblTextColor" Width="30" Margin="5,1" Background="#FF343434" Foreground="#FFDEDEDE" Content="A" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="15" Padding="1" MouseLeftButtonUp="lblTextColor_MouseLeftButtonUp" />
+ <Label Name="lblTextBold" Width="30" Margin="0,1,5,1" Background="#FF343434" Foreground="#FFDEDEDE" Content="B" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="15" Padding="1" MouseLeftButtonUp="lblTextBold_MouseLeftButtonUp" />
+ <Label Name="lblTextItalic" Width="30" Margin="0,1,5,1" Background="#FF343434" Foreground="#FFDEDEDE" Content="I" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="15" Padding="1" MouseLeftButtonUp="lblTextItalic_MouseLeftButtonUp" />
+ <ComboBox Name="cmbTextFont" SelectedIndex="3" Margin="0,1,5,1" VerticalContentAlignment="Center" MinWidth="130" SelectionChanged="cmbTextFont_SelectionChanged">
+ <ComboBoxItem FontFamily="Arial" Margin="1">Arial</ComboBoxItem>
+ <ComboBoxItem FontFamily="Cambria" Margin="1">Cambria</ComboBoxItem>
+ <ComboBoxItem FontFamily="Segoe UI" Margin="1">Segoe UI</ComboBoxItem>
+ <ComboBoxItem FontFamily="Verdana" Margin="1">Verdana</ComboBoxItem>
+ <ComboBoxItem FontFamily="Times New Roman" Margin="1">Times New Roman</ComboBoxItem>
+ </ComboBox>
+ <ComboBox Name="cmbTextSize" SelectedIndex="2" Margin="0,1,5,1" VerticalContentAlignment="Center" MinWidth="40" SelectionChanged="cmbTextSize_SelectionChanged">
+ <ComboBoxItem Margin="1">8</ComboBoxItem>
+ <ComboBoxItem Margin="1">10</ComboBoxItem>
+ <ComboBoxItem Margin="1">12</ComboBoxItem>
+ <ComboBoxItem Margin="1">14</ComboBoxItem>
+ <ComboBoxItem Margin="1">16</ComboBoxItem>
+ </ComboBox>
+ <Image Source="/ChatClientApp;component/Images/sound_on.png" Name="imgSoundOnOff" MouseLeftButtonUp="imgSoundOnOff_MouseLeftButtonUp" />
+ </StackPanel>
+ <RichTextBox Name="txtMessageHistory" Margin="5" Background="#FF343434" Foreground="#FFDEDEDE" VerticalScrollBarVisibility="Visible">
+ <RichTextBox.Resources>
+ <Style TargetType="{x:Type Paragraph}">
+ <Setter Property="Margin" Value="0"/>
+ </Style>
+ </RichTextBox.Resources>
+ </RichTextBox>
+ </DockPanel>
+
+ <Grid Grid.Row="2">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="100" />
+ </Grid.ColumnDefinitions>
+ <RichTextBox Name="txtWriteMessage" Margin="5" Background="#FF343434" Foreground="#FFDEDEDE" VerticalScrollBarVisibility="Auto" AcceptsReturn="False" KeyDown="txtWriteMessage_KeyDown">
+ <RichTextBox.Resources>
+ <Style TargetType="{x:Type Paragraph}">
+ <Setter Property="Margin" Value="0"/>
+ </Style>
+ </RichTextBox.Resources>
+ </RichTextBox>
+ <Button Grid.Column="1" Content="Send" Margin="5" FontSize="16" Name="btnSendMessage" Click="btnSendMessage_Click" />
+ </Grid>
+ </Grid>
+ </Border>
+
+</UserControl>
diff --git a/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml.cs
new file mode 100644
index 0000000..5b92939
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Controls/MessagingAreaControl.xaml.cs
@@ -0,0 +1,469 @@
+using System;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Client;
+using Hik.Samples.Scs.IrcChat.Windows;
+
+namespace Hik.Samples.Scs.IrcChat.Controls
+{
+ /// <summary>
+ /// This control is used to show incoming messages and write new messages.
+ /// </summary>
+ public partial class MessagingAreaControl : UserControl
+ {
+ #region Public Properties
+
+ /// <summary>
+ /// Reference to the container window of this control.
+ /// </summary>
+ public IMessagingAreaContainer MessagingAreaContainer { get; set; }
+
+ /// <summary>
+ /// This property is used to set messaging area is read only or not.
+ /// </summary>
+ public bool IsReadOnly
+ {
+ get { return _isReadOnly; }
+ set
+ {
+ _isReadOnly = value;
+ btnSendMessage.IsEnabled = !_isReadOnly;
+ txtWriteMessage.IsEnabled = !_isReadOnly;
+ }
+ }
+ private bool _isReadOnly;
+
+ private void SetTextStyleControlsVisibility()
+ {
+ if (!IsInitialized)
+ {
+ return;
+ }
+ spTextStyleChanging.Visibility = _isTextStyleChangingEnabled
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+ }
+
+ /// <summary>
+ /// This property is used to hide or show text style changing controls.
+ /// </summary>
+ public bool IsTextStyleChangingEnabled
+ {
+ get { return IsTextStyleChangingEnabled; }
+ set
+ {
+ if (_isTextStyleChangingEnabled == value)
+ {
+ return;
+ }
+
+ _isTextStyleChangingEnabled = value;
+ SetTextStyleControlsVisibility(); ;
+ }
+ }
+ private bool _isTextStyleChangingEnabled = true;
+
+ #endregion
+
+ #region Constructor and initializing methods
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ public MessagingAreaControl()
+ {
+ _userPreferences = UserPreferences.Current;
+ InitializeComponent();
+ InitializeControls();
+ InitializeUserPreferences();
+ }
+
+ /// <summary>
+ /// Initializes some controls.
+ /// </summary>
+ private void InitializeControls()
+ {
+ txtMessageHistory.IsReadOnly = true;
+ }
+
+ /// <summary>
+ /// Gets user preferences and initializes controls.
+ /// </summary>
+ private void InitializeUserPreferences()
+ {
+ lblTextBold.FontWeight = _userPreferences.TextStyle.IsBold ? FontWeights.Bold : FontWeights.Normal;
+ lblTextColor.FontWeight = lblTextBold.FontWeight;
+ lblTextItalic.FontWeight = lblTextBold.FontWeight;
+ txtWriteMessage.FontWeight = lblTextBold.FontWeight;
+
+ lblTextItalic.FontStyle = _userPreferences.TextStyle.IsItalic ? FontStyles.Italic : FontStyles.Normal;
+ lblTextColor.FontStyle = lblTextItalic.FontStyle;
+ lblTextBold.FontStyle = lblTextItalic.FontStyle;
+ txtWriteMessage.FontStyle = lblTextItalic.FontStyle;
+
+ lblTextColor.Foreground =
+ new SolidColorBrush(
+ Color.FromRgb(
+ _userPreferences.TextStyle.TextColor.Red, _userPreferences.TextStyle.TextColor.Green, _userPreferences.TextStyle.TextColor.Blue
+ ));
+ lblTextBold.Foreground = lblTextColor.Foreground;
+ lblTextItalic.Foreground = lblTextColor.Foreground;
+ txtWriteMessage.Foreground = lblTextColor.Foreground;
+
+ for (var i = 0; i < cmbTextFont.Items.Count; i++)
+ {
+ if (((string)((ComboBoxItem)cmbTextFont.Items[i]).Content) == _userPreferences.TextStyle.FontFamily)
+ {
+ cmbTextFont.SelectedIndex = i;
+ break;
+ }
+ }
+
+ var textSizeAsString = _userPreferences.TextStyle.TextSize.ToString();
+ for (var i = 0; i < cmbTextSize.Items.Count; i++)
+ {
+ if (((string)((ComboBoxItem)cmbTextSize.Items[i]).Content) == textSizeAsString)
+ {
+ cmbTextSize.SelectedIndex = i;
+ break;
+ }
+ }
+
+ txtWriteMessage.FontFamily = new FontFamily(_userPreferences.TextStyle.FontFamily);
+ txtWriteMessage.FontSize = _userPreferences.TextStyle.TextSize;
+
+ RefreshSoundPicture();
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Reference to the user's text style.
+ /// </summary>
+ private readonly UserPreferences _userPreferences;
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Adds a new message to message history.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ public void MessageReceived(string nick, ChatMessage message)
+ {
+ //Create a new paragraph to write new message
+ var messageParagraph = new Paragraph();
+
+ //Set message as Bold if needed
+ if (message.TextStyle.IsBold)
+ {
+ messageParagraph.FontWeight = FontWeights.Bold;
+ }
+
+ //Set message as Italic if needed
+ if (message.TextStyle.IsItalic)
+ {
+ messageParagraph.FontStyle = FontStyles.Italic;
+ }
+
+ //Set message font if needed
+ if (!string.IsNullOrEmpty(message.TextStyle.FontFamily))
+ {
+ try
+ {
+ messageParagraph.FontFamily = new FontFamily(message.TextStyle.FontFamily);
+ }
+ catch
+ {
+
+ }
+ }
+
+ //Set message text size if needed
+ if (message.TextStyle.TextSize > 0)
+ {
+ messageParagraph.FontSize = message.TextStyle.TextSize;
+ }
+
+ //Set message color if needed
+ if (message.TextStyle.TextColor != null)
+ {
+ messageParagraph.Foreground =
+ new SolidColorBrush(
+ new Color
+ {
+ A = 255,
+ R = message.TextStyle.TextColor.Red,
+ G = message.TextStyle.TextColor.Green,
+ B = message.TextStyle.TextColor.Blue
+ });
+ }
+
+ //Add message to paragraph
+ messageParagraph.Inlines.Add(new Run(nick + ": " + message.MessageText));
+
+ //Add new parapraph to message history
+ txtMessageHistory.Document.Blocks.Add(messageParagraph);
+
+ if (txtMessageHistory.Document.Blocks.Count > 1000)
+ {
+ txtMessageHistory.Document.Blocks.Remove(txtMessageHistory.Document.Blocks.FirstBlock);
+ }
+
+ txtMessageHistory.ScrollToEnd();
+ }
+
+ #endregion
+
+ #region Private methods
+
+ #region Sending message
+
+ /// <summary>
+ /// Handles Client event of Send button.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void btnSendMessage_Click(object sender, RoutedEventArgs e)
+ {
+ SendMessage();
+ }
+
+ /// <summary>
+ /// Handles KeyDown event of txtWriteMessage textbox.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void txtWriteMessage_KeyDown(object sender, KeyEventArgs e)
+ {
+ //If user pressed to enter in message sending textbox, send message..
+ if (e.Key == Key.Enter)
+ {
+ SendMessage();
+ }
+ }
+
+ /// <summary>
+ /// Sends a message to the room.
+ /// </summary>
+ private void SendMessage()
+ {
+ string messageText = new TextRange(txtWriteMessage.Document.ContentStart, txtWriteMessage.Document.ContentEnd).Text.Trim();
+ if (string.IsNullOrEmpty(messageText) || MessagingAreaContainer == null)
+ {
+ return;
+ }
+
+ try
+ {
+ MessagingAreaContainer.SendMessage(
+ new ChatMessage(
+ messageText,
+ _userPreferences.TextStyle
+ ));
+ txtWriteMessage.Document.Blocks.Clear();
+ txtWriteMessage.Focus();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not send message to the server. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ #endregion
+
+ #region Changing / getting text styles
+
+ /// <summary>
+ /// Handles MouseLeftButtonUp of txtTextColor and opens a text color picker dialog
+ /// to select text color.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void lblTextColor_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ var colorPicker = new TextColorPicker();
+ if (colorPicker.ShowDialog() == true)
+ {
+ _userPreferences.TextStyle.TextColor.Red = colorPicker.SelectedColor.R;
+ _userPreferences.TextStyle.TextColor.Green = colorPicker.SelectedColor.G;
+ _userPreferences.TextStyle.TextColor.Blue = colorPicker.SelectedColor.B;
+
+ lblTextColor.Foreground = new SolidColorBrush(colorPicker.SelectedColor);
+ lblTextBold.Foreground = lblTextColor.Foreground;
+ lblTextItalic.Foreground = lblTextColor.Foreground;
+ txtWriteMessage.Foreground = lblTextColor.Foreground;
+ }
+ }
+
+ /// <summary>
+ /// Handles MouseLeftButtonUp event of lblTextBold to change Bold text option.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void lblTextBold_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ lblTextBold.FontWeight = lblTextBold.FontWeight == FontWeights.Normal
+ ? FontWeights.Bold
+ : FontWeights.Normal;
+
+ _userPreferences.TextStyle.IsBold = (lblTextBold.FontWeight == FontWeights.Bold);
+ lblTextColor.FontWeight = lblTextBold.FontWeight;
+ lblTextItalic.FontWeight = lblTextBold.FontWeight;
+ txtWriteMessage.FontWeight = lblTextBold.FontWeight;
+ }
+
+ /// <summary>
+ /// Handles MouseLeftButtonUp event of lblTextItalic to change Italic text option.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void lblTextItalic_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ lblTextItalic.FontStyle = lblTextItalic.FontStyle == FontStyles.Normal
+ ? FontStyles.Italic
+ : FontStyles.Normal;
+
+ _userPreferences.TextStyle.IsItalic = (lblTextItalic.FontStyle == FontStyles.Italic);
+ lblTextColor.FontStyle = lblTextItalic.FontStyle;
+ lblTextBold.FontStyle = lblTextItalic.FontStyle;
+ txtWriteMessage.FontStyle = lblTextItalic.FontStyle;
+ }
+
+ /// <summary>
+ /// Handles SelectionChanged event of text font combobox.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void cmbTextFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsInitialized)
+ {
+ return;
+ }
+
+ var selectedFont = GetSelectedTextFontFamily();
+ if (selectedFont == null)
+ {
+ return;
+ }
+
+ try
+ {
+ txtWriteMessage.FontFamily = new FontFamily(selectedFont);
+ _userPreferences.TextStyle.FontFamily = selectedFont;
+ }
+ catch
+ {
+
+ }
+ }
+
+ /// <summary>
+ /// Handles SelectionChanged event of text size combobox.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void cmbTextSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsInitialized)
+ {
+ return;
+ }
+
+ var selectedTextSize = GetSelectedTextSize();
+ txtWriteMessage.FontSize = selectedTextSize;
+ _userPreferences.TextStyle.TextSize = selectedTextSize;
+ }
+
+ /// <summary>
+ /// Handles MouseLeftButtonUp event of Sound image.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void imgSoundOnOff_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ _userPreferences.IsSoundOn = !_userPreferences.IsSoundOn;
+ RefreshSoundPicture();
+ }
+
+ /// <summary>
+ /// Gets selected font family.
+ /// </summary>
+ /// <returns>Selected font family</returns>
+ private string GetSelectedTextFontFamily()
+ {
+ if (cmbTextFont.SelectedIndex < 0)
+ {
+ return null;
+ }
+
+ var selectedItem = cmbTextFont.SelectedItem as ComboBoxItem;
+ if (selectedItem == null)
+ {
+ return null;
+ }
+
+ return selectedItem.Content as string;
+ }
+
+ /// <summary>
+ /// Gets selected text size.
+ /// </summary>
+ /// <returns>Text size</returns>
+ private int GetSelectedTextSize()
+ {
+ try
+ {
+ if (cmbTextFont.SelectedIndex < 0)
+ {
+ return 12; //Default value
+ }
+
+ var selectedItem = cmbTextSize.SelectedItem as ComboBoxItem;
+ if (selectedItem != null)
+ {
+ return Convert.ToInt32(selectedItem.Content as string);
+ }
+ }
+ catch
+ {
+
+ }
+
+ return 12; //Default value
+ }
+
+ /// <summary>
+ /// Refreshes sound image according to user preference.
+ /// </summary>
+ private void RefreshSoundPicture()
+ {
+ var imagePath = _userPreferences.IsSoundOn
+ ? Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\sound_on.png")
+ : Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\sound_off.png");
+ try
+ {
+ imgSoundOnOff.Source = new BitmapImage(new Uri(imagePath));
+ }
+ catch
+ {
+
+ }
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml b/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml
new file mode 100644
index 0000000..526d2c7
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml
@@ -0,0 +1,55 @@
+<UserControl x:Class="Hik.Samples.Scs.IrcChat.Controls.UserCardControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ mc:Ignorable="d"
+ d:DesignHeight="60" d:DesignWidth="300">
+ <Border Margin="0,0,5,5" Cursor="Hand">
+ <Border.Style>
+ <Style>
+ <Style.Setters>
+ <Setter Property="Border.BorderThickness" Value="1"></Setter>
+ <Setter Property="Border.BorderBrush" Value="#FF878383"></Setter>
+ <Setter Property="Border.CornerRadius" Value="6"></Setter>
+ <Setter Property="Border.Background" Value="#FF111111" />
+ </Style.Setters>
+ <Style.Triggers>
+ <Trigger Property="Border.IsMouseOver" Value="False">
+ <Setter Property="Border.Background">
+ <Setter.Value>
+ <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+ <GradientStop Offset="0" Color="#FF393939"/>
+ <GradientStop Offset="1" Color="Black"/>
+ </LinearGradientBrush>
+ </Setter.Value>
+ </Setter>
+ </Trigger>
+ <Trigger Property="Border.IsMouseOver" Value="True">
+ <Setter Property="Border.Background">
+ <Setter.Value>
+ <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+ <GradientStop Offset="0" Color="#FF696767"/>
+ <GradientStop Offset="1" Color="#FF3B3B3B"/>
+ </LinearGradientBrush>
+ </Setter.Value>
+ </Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="60" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Border Margin="3" Grid.Column="0" BorderThickness="1" Background="#FF272626">
+ <Image Stretch="UniformToFill" Source="/ChatClientApp;component/Images/user_male.png" Name="imgAvatar" />
+ </Border>
+ <StackPanel Grid.Column="1">
+ <Label Content="User Nick" Foreground="White" Height="Auto" Padding="2" Name="lblNick" Margin="3,1"></Label>
+ <Label Content="Available" Foreground="#FF2BE400" Padding="2" Name="lblStatus" Margin="3,0"></Label>
+ </StackPanel>
+ </Grid>
+ </Border>
+</UserControl>
diff --git a/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml.cs
new file mode 100644
index 0000000..6be6422
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Controls/UserCardControl.xaml.cs
@@ -0,0 +1,116 @@
+using System;
+using System.IO;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Client;
+
+namespace Hik.Samples.Scs.IrcChat.Controls
+{
+ /// <summary>
+ /// This control is used to show a User Card in right area of chat room.
+ /// </summary>
+ public partial class UserCardControl : UserControl
+ {
+ /// <summary>
+ /// Gets/sets the of the user.
+ /// </summary>
+ public string UserNick
+ {
+ get { return lblNick.Content.ToString(); }
+ set { lblNick.Content = value; }
+ }
+
+ /// <summary>
+ /// Sets status of the user.
+ /// </summary>
+ public UserStatus UserStatus
+ {
+ get { return _userStatus; }
+ set
+ {
+ _userStatus = value;
+ RefreshStatusLabel();
+ }
+ }
+ private UserStatus _userStatus;
+
+ /// <summary>
+ /// Sets avatar image of the user.
+ /// </summary>
+ public byte[] AvatarBytes
+ {
+ set
+ {
+ try
+ {
+ ChangeAvatar(value);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets ImageSource property of user avatar.
+ /// </summary>
+ public ImageSource AvatarImageSource
+ {
+ get { return imgAvatar.Source; }
+ }
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ public UserCardControl()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// Refreshes status of user on label according to _userStatus.
+ /// </summary>
+ private void RefreshStatusLabel()
+ {
+ switch (_userStatus)
+ {
+ case UserStatus.Busy:
+ lblStatus.Content = "Busy";
+ lblStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFF4E4E"));
+ break;
+ case UserStatus.Out:
+ lblStatus.Content = "Out";
+ lblStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF3179FE"));
+ break;
+ default: //Default: Available
+ lblStatus.Content = "Available";
+ lblStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF2BE400"));
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Changes avatar image of the user.
+ /// </summary>
+ /// <param name="bytesOfAvatar">byte of avatar file</param>
+ private void ChangeAvatar(byte[] bytesOfAvatar)
+ {
+ if (bytesOfAvatar == null)
+ {
+ var defaultAvatar = Path.Combine((Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\user_male.png")));
+ imgAvatar.Source = new BitmapImage(new Uri(defaultAvatar));
+ return;
+ }
+
+ //Save bytes into a temporary file
+ var tempSavePath = Path.GetTempFileName();
+ File.WriteAllBytes(tempSavePath, bytesOfAvatar);
+
+ //Change avatar picture.
+ imgAvatar.Source = new BitmapImage(new Uri(tempSavePath));
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/app_icon.ico b/samples/IrcChatSystem/ChatClientApp/Images/app_icon.ico
new file mode 100644
index 0000000..dc5af4a
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/app_icon.ico
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/sound_off.png b/samples/IrcChatSystem/ChatClientApp/Images/sound_off.png
new file mode 100644
index 0000000..7a800f3
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/sound_off.png
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/sound_on.png b/samples/IrcChatSystem/ChatClientApp/Images/sound_on.png
new file mode 100644
index 0000000..7bd29d6
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/sound_on.png
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/text_color_picker.ico b/samples/IrcChatSystem/ChatClientApp/Images/text_color_picker.ico
new file mode 100644
index 0000000..887e3ad
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/text_color_picker.ico
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/user_female.png b/samples/IrcChatSystem/ChatClientApp/Images/user_female.png
new file mode 100644
index 0000000..d47e5a8
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/user_female.png
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Images/user_male.png b/samples/IrcChatSystem/ChatClientApp/Images/user_male.png
new file mode 100644
index 0000000..f9796d7
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Images/user_male.png
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Properties/AssemblyInfo.cs b/samples/IrcChatSystem/ChatClientApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f093c9a
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 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("ChatClientApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ChatClientApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// 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")]
diff --git a/samples/IrcChatSystem/ChatClientApp/Properties/Resources.Designer.cs b/samples/IrcChatSystem/ChatClientApp/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..6e3255f
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Hik.Samples.Scs.IrcChat.Properties {
+ 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()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hik.Samples.Scs.IrcChat.Properties.Resources", typeof(Resources).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)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Properties/Resources.resx b/samples/IrcChatSystem/ChatClientApp/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Properties/Settings.Designer.cs b/samples/IrcChatSystem/ChatClientApp/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..95c7572
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Hik.Samples.Scs.IrcChat.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Properties/Settings.settings b/samples/IrcChatSystem/ChatClientApp/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatClientApp/Sounds/incoming_message.wav b/samples/IrcChatSystem/ChatClientApp/Sounds/incoming_message.wav
new file mode 100644
index 0000000..5e5184e
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Sounds/incoming_message.wav
Binary files differ
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml b/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml
new file mode 100644
index 0000000..b24b767
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml
@@ -0,0 +1,89 @@
+<Window xmlns:my="clr-namespace:Hik.Samples.Scs.IrcChat.Controls" x:Class="Hik.Samples.Scs.IrcChat.Windows.MainWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="SCS Chat Client" Height="517" Width="885" WindowStyle="SingleBorderWindow" WindowStartupLocation="CenterScreen" Closing="Window_Closing" Loaded="Window_Loaded" Icon="/ChatClientApp;component/Images/app_icon.ico">
+ <Grid>
+ <Grid Background="#FF1F1F1F">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="240" />
+ </Grid.ColumnDefinitions>
+ <my:MessagingAreaControl x:Name="messagingArea" />
+ <StackPanel Grid.Column="1" Margin="5">
+ <Border Margin="0,0,5,5" Height="80">
+ <Border.Background>
+ <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+ <GradientStop Color="#FF393939" Offset="0" />
+ <GradientStop Color="Black" Offset="1" />
+ </LinearGradientBrush>
+ </Border.Background>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="80" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Border Margin="3" Grid.Column="0" BorderThickness="1" Background="#FF272626">
+ <Image Stretch="UniformToFill" Name="imgCurrentUserAvatar" />
+ </Border>
+ <StackPanel Grid.Column="1">
+ <Label Content="User Nick" Foreground="White" Height="Auto" Padding="2" Name="lblCurrentUserNick" Margin="3,1"></Label>
+ <ComboBox Name="cmbCurrentUserStatus" Margin="3,1" Background="#FF353535" SelectionChanged="cmbCurrentUserStatus_SelectionChanged" SelectedIndex="0" HorizontalContentAlignment="Left" VerticalContentAlignment="Stretch" IsReadOnly="False" BorderBrush="{x:Null}" Foreground="White" BorderThickness="0">
+ <ComboBoxItem HorizontalContentAlignment="Stretch" Background="#FF353535" VerticalContentAlignment="Stretch">
+ <Label Content="Available" Foreground="#FF2BE400" />
+ </ComboBoxItem>
+ <ComboBoxItem HorizontalContentAlignment="Stretch" Background="#FF353535" VerticalContentAlignment="Stretch">
+ <Label Content="Busy" Foreground="#FFFF4E4E" />
+ </ComboBoxItem>
+ <ComboBoxItem HorizontalContentAlignment="Stretch" Background="#FF353535" VerticalContentAlignment="Stretch">
+ <Label Content="Out" Foreground="#FF3179FE" />
+ </ComboBoxItem>
+ </ComboBox>
+ </StackPanel>
+ </Grid>
+ </Border>
+ <ScrollViewer VerticalScrollBarVisibility="Auto">
+ <StackPanel Name="spUsers" >
+ </StackPanel>
+ </ScrollViewer>
+ </StackPanel>
+ </Grid>
+ <Grid Background="White" Opacity="0.7" Name="grdConnect"></Grid>
+ <Border Width="300" Height="115" Padding="2" Name="brdConnect" KeyDown="LoginForm_KeyDown">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="115" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Border Margin="2" BorderThickness="1" Background="#FF272626">
+ <Border.ContextMenu>
+ <ContextMenu>
+ <MenuItem Header="Change to male" Click="ChangeToMale_Click" />
+ <MenuItem Header="Change to female" Click="ChangeToFemale_Click" />
+ <MenuItem Header="Select a picture..." Click="SelectAvatar_Click" />
+ </ContextMenu>
+ </Border.ContextMenu>
+ <Image Grid.Column="0" Stretch="UniformToFill" Name="imgLoginAvatar" StretchDirection="Both" />
+ </Border>
+ <Grid Grid.Column="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="80" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="26"/>
+ <RowDefinition Height="26"/>
+ <RowDefinition Height="26"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Label Grid.Column="0" Grid.Row="0" Content="Nick:" Foreground="White" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" FontWeight="Bold" />
+ <Label Grid.Column="0" Grid.Row="1" Content="Server IP:" Foreground="White" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" FontWeight="Normal" />
+ <Label Grid.Column="0" Grid.Row="2" Content="Server Port:" Foreground="White" VerticalContentAlignment="Center" HorizontalContentAlignment="Right" FontWeight="Normal" />
+ <TextBox Grid.Column="1" Grid.Row="0" Margin="2" Text="User Nick" FontWeight="Bold" VerticalContentAlignment="Center" Name="txtNick" TextChanged="txtNick_TextChanged"></TextBox>
+ <TextBox Grid.Column="1" Grid.Row="1" Margin="2" Text="127.0.0.1" VerticalContentAlignment="Center" Name="txtServerIpAddress"></TextBox>
+ <TextBox Grid.Column="1" Grid.Row="2" Margin="2" Text="10048" VerticalContentAlignment="Center" Name="txtServerPort"></TextBox>
+ <Button Grid.Column="1" Content="Login" Grid.Row="3" Margin="2" FontSize="15" FontWeight="Bold" Name="btnLogin" Click="btnLogin_Click" />
+ </Grid>
+ </Grid>
+ </Border>
+ </Grid>
+</Window>
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml.cs
new file mode 100644
index 0000000..3451da8
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/MainWindow.xaml.cs
@@ -0,0 +1,699 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media.Imaging;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Client;
+using Hik.Samples.Scs.IrcChat.Controls;
+using Microsoft.Win32;
+
+namespace Hik.Samples.Scs.IrcChat.Windows
+{
+ /// <summary>
+ /// Interaction logic for MainWindow.xaml
+ /// </summary>
+ public partial class MainWindow : Window, IChatRoomView, ILoginFormView, IMessagingAreaContainer
+ {
+ #region ILoginFormView implementation
+
+ /// <summary>
+ /// IP address of server to be connected.
+ /// </summary>
+ public string ServerIpAddress
+ {
+ get
+ {
+ return (string)Dispatcher.Invoke(new Func<string>(() => txtServerIpAddress.Text));
+ }
+ }
+
+ /// <summary>
+ /// TCP Port number of server to be connected.
+ /// </summary>
+ public int ServerTcpPort
+ {
+ get
+ {
+ return (int)Dispatcher.Invoke(new Func<int>(() => Convert.ToInt32(txtServerPort.Text)));
+ }
+ }
+
+ /// <summary>
+ /// User Login informations to be used while logging on to the server.
+ /// </summary>
+ public UserInfo CurrentUserInfo
+ {
+ get
+ {
+ return (UserInfo)Dispatcher.Invoke(
+ new Func<UserInfo>(() => new UserInfo
+ {
+ Nick = txtNick.Text,
+ Status = UserStatus.Available,
+ AvatarBytes = GetBytesOfCurrentUserAvatar()
+ }));
+ }
+ }
+
+ #endregion
+
+ #region IChatRoomView implementation
+
+ /// <summary>
+ /// This method is called when a message is sent to chat room.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ public void OnMessageReceived(string nick, ChatMessage message)
+ {
+ Dispatcher.Invoke(new Action(() => messagingArea.MessageReceived(nick, message)));
+ }
+
+ /// <summary>
+ /// This method is called when a private message is sent to the current user.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">The message</param>
+ public void OnPrivateMessageReceived(string nick, ChatMessage message)
+ {
+ Dispatcher.Invoke(new Action(() => OnPrivateMessageReceivedInternal(nick, message)));
+ }
+
+ /// <summary>
+ /// This method is called when user successfully logged in to chat server.
+ /// </summary>
+ public void OnLoggedIn()
+ {
+ Dispatcher.Invoke(new Action(OnLoggedInInternal));
+ }
+
+ /// <summary>
+ /// This method is used to inform view if login is failed.
+ /// </summary>
+ /// <param name="errorMessage">Detail of error</param>
+ public void OnLoginError(string errorMessage)
+ {
+ MessageBox.Show(errorMessage, "Login Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+
+ /// <summary>
+ /// This method is called when connection to server is closed.
+ /// </summary>
+ public void OnLoggedOut()
+ {
+ Dispatcher.Invoke(new Action(OnLoggedOutInternal));
+ }
+
+ /// <summary>
+ /// This methos is used to add a new user to user list in room view.
+ /// </summary>
+ /// <param name="userInfo">Informations of new user</param>
+ public void AddUserToList(UserInfo userInfo)
+ {
+ Dispatcher.Invoke(new Action(() => AddUserToListInternal(userInfo)));
+ }
+
+ /// <summary>
+ /// This metrhod is used to remove a user (that is disconnected from server) from user list in room view.
+ /// </summary>
+ /// <param name="nick">Nick of user to remove</param>
+ public void RemoveUserFromList(string nick)
+ {
+ Dispatcher.Invoke(new Action(() => RemoveUserFromListInternal(nick)));
+ }
+
+ /// <summary>
+ /// This method is called from chat server to inform that a user changed his/her status.
+ /// </summary>
+ /// <param name="nick">Nick of the user</param>
+ /// <param name="newStatus">New status of the user</param>
+ public void OnUserStatusChange(string nick, UserStatus newStatus)
+ {
+ Dispatcher.Invoke(new Action(() => OnUserStatusChangeInternal(nick, newStatus)));
+ }
+
+ #endregion
+
+ #region IMessagingAreaContainer implementation
+
+ /// <summary>
+ /// Sends a message to the room.
+ /// </summary>
+ public void SendMessage(ChatMessage message)
+ {
+ _controller.SendMessageToRoom(message);
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Reference to the controller object.
+ /// </summary>
+ private readonly IChatController _controller;
+
+ /// <summary>
+ /// List of open private chat windows.
+ /// </summary>
+ private readonly SortedList<string, PrivateChatWindow> _privateChatWindows;
+
+ /// <summary>
+ /// Reference to the user preferences.
+ /// </summary>
+ private readonly UserPreferences _userPreferences;
+
+ #endregion
+
+ #region Constructor and Initialize methods
+
+ /// <summary>
+ /// Creates a new form with a reference to the controller object.
+ /// </summary>
+ /// <param name="controller">Reference to the controller object</param>
+ public MainWindow(IChatController controller)
+ {
+ _controller = controller;
+ _privateChatWindows = new SortedList<string, PrivateChatWindow>();
+ _userPreferences = UserPreferences.Current;
+
+ InitializeComponent();
+ InitializeControls();
+ }
+
+ /// <summary>
+ /// Initializes some controls.
+ /// </summary>
+ private void InitializeControls()
+ {
+ messagingArea.MessagingAreaContainer = this;
+ txtNick.Text = _userPreferences.Nick;
+ txtServerIpAddress.Text = _userPreferences.ServerIpAddress;
+ txtServerPort.Text = _userPreferences.ServerTcpPort.ToString();
+ InitializeUserAvatar();
+ }
+
+ /// <summary>
+ /// Initializes and shows user avatar.
+ /// </summary>
+ private void InitializeUserAvatar()
+ {
+ try
+ {
+ ChangeCurrentUserAvatar(_userPreferences.AvatarFile);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not load avatar image. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ #endregion
+
+ #region Handlers for events of window and controls
+
+ /// <summary>
+ /// Handles Loaded event of this Window.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ txtNick.Focus();
+ txtNick.SelectAll();
+ }
+
+ /// <summary>
+ /// Hansles Closing event of this window.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ _userPreferences.Save();
+ _controller.Disconnect();
+ }
+
+ /// <summary>
+ /// Handles TextChanged event of txtNick (on login screen).
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void txtNick_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ lblCurrentUserNick.Content = txtNick.Text;
+ }
+
+ /// <summary>
+ /// Handles Click event of 'Change to female' right menu item of avatar menu.
+ /// Changes login avatar to default female avatar.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ChangeToFemale_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ ChangeCurrentUserAvatar(Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\user_female.png"));
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not load avatar image. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ /// <summary>
+ /// Handles Click event of 'Change to male' right menu item of avatar menu.
+ /// Changes login avatar to default male avatar.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ChangeToMale_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ ChangeCurrentUserAvatar(Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\user_male.png"));
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not load avatar image. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ /// <summary>
+ /// Handles Click event of 'Select a picture...' menu item.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void SelectAvatar_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var avatarSelectDialog = new OpenFileDialog();
+ avatarSelectDialog.Filter = "JPG Files|*.jpg|JPEG Files|*.jpeg|GIF Files|*.gif|PNG files|*.png|BMP Files|*.bmp";
+ if (avatarSelectDialog.ShowDialog() == true)
+ {
+ var selectedFile = avatarSelectDialog.FileName;
+ if (ClientHelper.GetFileSize(selectedFile) > (100 * 1024))
+ {
+ MessageBox.Show("You can not select avatar file larger than 100 KB.", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ ChangeCurrentUserAvatar(selectedFile);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not load avatar image. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ /// <summary>
+ /// Handles Client event of Login button.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void btnLogin_Click(object sender, RoutedEventArgs e)
+ {
+ ConnectToServer();
+ }
+
+ /// <summary>
+ /// Handles KeyDown of Login form (actually the Border named brdConnect that contains login controls)
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void LoginForm_KeyDown(object sender, KeyEventArgs e)
+ {
+ //If user pressed to enter in login form, connect to server
+ if (e.Key == Key.Enter)
+ {
+ ConnectToServer();
+ }
+ }
+
+ /// <summary>
+ /// Handles SelectionChanged event of user status combobox
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void cmbCurrentUserStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsInitialized || cmbCurrentUserStatus.SelectedIndex < 0 || _controller == null)
+ {
+ return;
+ }
+
+ try
+ {
+ var newStatus = GetCurrentUserStatus();
+
+ _controller.ChangeStatus(newStatus);
+
+ //Change user's status on all open private chat windows
+ foreach (var chatWindow in _privateChatWindows.Values.ToList())
+ {
+ chatWindow.CurrentUserStatus = newStatus;
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not changes status. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ /// <summary>
+ /// Handles MouseDoubleClick event of all User cards.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void UserCard_MouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ if (e.ChangedButton != MouseButton.Left)
+ {
+ return;
+ }
+
+ var userCard = e.Source as UserCardControl;
+ if (userCard == null)
+ {
+ return;
+ }
+
+ if (_privateChatWindows.ContainsKey(userCard.UserNick))
+ {
+ _privateChatWindows[userCard.UserNick].Activate();
+ }
+ else
+ {
+ _privateChatWindows[userCard.UserNick] = CreatePrivateChatWindow(userCard);
+ }
+ }
+
+ /// <summary>
+ /// Handles Closed event of Private chat windows.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void PrivateChatWindow_Closed(object sender, EventArgs e)
+ {
+ var privateChatWindow = sender as PrivateChatWindow;
+ if (privateChatWindow == null)
+ {
+ return;
+ }
+
+ if (_privateChatWindows.ContainsKey(privateChatWindow.RemoteUserNick))
+ {
+ _privateChatWindows.Remove(privateChatWindow.RemoteUserNick);
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Connects to the server.
+ /// This method is called on login.
+ /// </summary>
+ private void ConnectToServer()
+ {
+ if(string.IsNullOrEmpty(txtNick.Text))
+ {
+ MessageBox.Show("You must enter a nick to login to server.", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ if (string.IsNullOrEmpty(txtServerIpAddress.Text))
+ {
+ MessageBox.Show("You must enter IP address to connect to server.", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ if (string.IsNullOrEmpty(txtServerPort.Text))
+ {
+ MessageBox.Show("You must enter TCP port to connect to server.", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
+ return;
+ }
+
+ try
+ {
+ _controller.Connect();
+ _userPreferences.Nick = txtNick.Text;
+ _userPreferences.ServerIpAddress = txtServerIpAddress.Text;
+ try { _userPreferences.ServerTcpPort = Convert.ToInt32(txtServerPort.Text); } catch { }
+ _userPreferences.Save();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Can not connected to the server. Check Server IP and port. Error Detail: " + ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ /// <summary>
+ /// This method is used to hide Login form when user succussfully logged into server.
+ /// </summary>
+ private void OnLoggedInInternal()
+ {
+ grdConnect.Visibility = Visibility.Collapsed;
+ brdConnect.Visibility = Visibility.Collapsed;
+ }
+
+ /// <summary>
+ /// This method is used to show Login form when connection to server is broken/closed.
+ /// </summary>
+ private void OnLoggedOutInternal()
+ {
+ foreach (var privateChatWindow in _privateChatWindows.Values.ToList())
+ {
+ privateChatWindow.Close();
+ }
+
+ spUsers.Children.Clear();
+ grdConnect.Visibility = Visibility.Visible;
+ brdConnect.Visibility = Visibility.Visible;
+ }
+
+ /// <summary>
+ /// This method is used to send private message to proper private messaging window.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ private void OnPrivateMessageReceivedInternal(string nick, ChatMessage message)
+ {
+ var userCard = FindUserInList(nick);
+ if (userCard == null)
+ {
+ return;
+ }
+
+ if (!_privateChatWindows.ContainsKey(nick))
+ {
+ //Create new private chat window
+ _privateChatWindows[nick] = CreatePrivateChatWindow(userCard);
+
+ //Set initial state as minimized
+ _privateChatWindows[nick].WindowState = WindowState.Minimized;
+
+ //Flash the window button on taskbar to inform user
+ WindowsHelper.FlashWindow(new WindowInteropHelper(_privateChatWindows[nick]).Handle, WindowsHelper.FlashWindowFlags.FLASHW_ALL, 2, 1000);
+ }
+
+ _privateChatWindows[nick].MessageReceived(message);
+ }
+
+ /// <summary>
+ /// Creates a new PrivateChatWindow from a user card.
+ /// </summary>
+ /// <param name="userCard">User card to use while creating window</param>
+ /// <returns>Created window</returns>
+ private PrivateChatWindow CreatePrivateChatWindow(UserCardControl userCard)
+ {
+ var window = new PrivateChatWindow(_controller)
+ {
+ CurrentUserNick = txtNick.Text,
+ CurrentUserStatus = GetCurrentUserStatus(),
+ CurrentUserAvatar = imgCurrentUserAvatar.Source,
+ RemoteUserNick = userCard.UserNick,
+ RemoteUserStatus = userCard.UserStatus,
+ RemoteUserAvatar = userCard.AvatarImageSource
+ };
+ window.Closed += PrivateChatWindow_Closed;
+ window.Show();
+ return window;
+ }
+
+ /// <summary>
+ /// Adds user to user list in right area of the window.
+ /// </summary>
+ /// <param name="userInfo">New user informations</param>
+ private void AddUserToListInternal(UserInfo userInfo)
+ {
+ //Do not add the current user (that is using the application) to user list
+ if (userInfo.Nick == CurrentUserInfo.Nick)
+ {
+ return;
+ }
+
+ //Do not add user to list if it is already exists.
+ if (FindUserInList(userInfo.Nick) != null)
+ {
+ return;
+ }
+
+ //Find correct order (by name) to insert the user
+ var orderedIndex = 0;
+ foreach (UserCardControl userCardControl in spUsers.Children)
+ {
+ if (userInfo.Nick.CompareTo(userCardControl.UserNick) < 0)
+ {
+ break;
+ }
+ orderedIndex++;
+ }
+
+ //Create user control
+ var userCard = new UserCardControl
+ {
+ UserNick = userInfo.Nick,
+ UserStatus = userInfo.Status,
+ AvatarBytes = userInfo.AvatarBytes,
+ Height = 60
+ };
+ userCard.MouseDoubleClick += UserCard_MouseDoubleClick;
+
+ //Insert user to user list
+ spUsers.Children.Insert(
+ orderedIndex,
+ userCard
+ );
+
+ //Enable private messaging window if any open with that user
+ if (_privateChatWindows.ContainsKey(userInfo.Nick))
+ {
+ _privateChatWindows[userInfo.Nick].UserLoggedIn();
+ _privateChatWindows[userInfo.Nick].RemoteUserStatus = userInfo.Status;
+ _privateChatWindows[userInfo.Nick].RemoteUserAvatar = userCard.AvatarImageSource;
+ }
+ }
+
+ /// <summary>
+ /// Removes an existing user from user list.
+ /// </summary>
+ /// <param name="nick"></param>
+ private void RemoveUserFromListInternal(string nick)
+ {
+ //Enable private messaging window is any open with that user
+ if (_privateChatWindows.ContainsKey(nick))
+ {
+ _privateChatWindows[nick].UserLoggedOut();
+ }
+
+ //Find user in list
+ var userCard = FindUserInList(nick);
+
+ //Remove if found
+ if (userCard != null)
+ {
+ spUsers.Children.Remove(userCard);
+ userCard.MouseDoubleClick -= UserCard_MouseDoubleClick;
+ }
+ }
+
+ /// <summary>
+ /// Changes status of a user in user list.
+ /// </summary>
+ /// <param name="nick">Nick of the user</param>
+ /// <param name="newStatus">New status of the user</param>
+ public void OnUserStatusChangeInternal(string nick, UserStatus newStatus)
+ {
+ //Find user in list
+ var userCard = FindUserInList(nick);
+
+ //Change status of user if found
+ if (userCard != null)
+ {
+ userCard.UserStatus = newStatus;
+ }
+
+ //Change status of user if any private chat window is open
+ if (_privateChatWindows.ContainsKey(nick))
+ {
+ _privateChatWindows[nick].RemoteUserStatus = newStatus;
+ }
+ }
+
+ /// <summary>
+ /// Searches a user (by nick) in user list and gets user card control of user.
+ /// </summary>
+ /// <param name="nick">Nick to search</param>
+ /// <returns>Found user card of user</returns>
+ private UserCardControl FindUserInList(string nick)
+ {
+ return spUsers.Children.Cast<UserCardControl>().FirstOrDefault(userCardControl => userCardControl.UserNick == nick);
+ }
+
+ /// <summary>
+ /// Changes avatar of the current user by a file.
+ /// </summary>
+ /// <param name="avatarPath">File path of new avatar</param>
+ private void ChangeCurrentUserAvatar(string avatarPath)
+ {
+ imgLoginAvatar.Source = new BitmapImage(new Uri(avatarPath));
+ imgCurrentUserAvatar.Source = imgLoginAvatar.Source;
+ _userPreferences.AvatarFile = avatarPath;
+ }
+
+ /// <summary>
+ /// Gets status of the current user from combobox.
+ /// </summary>
+ /// <returns>Status of current user</returns>
+ private UserStatus GetCurrentUserStatus()
+ {
+ switch (cmbCurrentUserStatus.SelectedIndex)
+ {
+ case 0:
+ return UserStatus.Available;
+ case 1:
+ return UserStatus.Busy;
+ default:
+ return UserStatus.Out;
+ }
+ }
+
+ /// <summary>
+ /// Gets bytes of current user avatar.
+ /// </summary>
+ /// <returns>Bytes of user avatar file</returns>
+ private byte[] GetBytesOfCurrentUserAvatar()
+ {
+ if (string.IsNullOrEmpty(_userPreferences.AvatarFile))
+ {
+ return null;
+ }
+
+ try
+ {
+ if (!File.Exists(_userPreferences.AvatarFile))
+ {
+ return null;
+ }
+
+ return File.ReadAllBytes(_userPreferences.AvatarFile);
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml b/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml
new file mode 100644
index 0000000..83dfd27
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml
@@ -0,0 +1,29 @@
+<Window xmlns:my="clr-namespace:Hik.Samples.Scs.IrcChat.Controls" x:Class="Hik.Samples.Scs.IrcChat.Windows.PrivateChatWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="Remote User Nick" Height="441" Width="555" Icon="/ChatClientApp;component/Images/app_icon.ico">
+ <Grid Background="#FF1F1F1F">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="115" />
+ </Grid.ColumnDefinitions>
+ <my:MessagingAreaControl x:Name="MessageHistory" />
+ <Grid Grid.Column="1">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="115" />
+ <RowDefinition Height="32"/>
+ <RowDefinition Height="*" />
+ <RowDefinition Height="32"/>
+ <RowDefinition Height="115" />
+ </Grid.RowDefinitions>
+ <Border Margin="5" BorderThickness="1" Background="#FF272626">
+ <Image Grid.Row="0" Stretch="UniformToFill" Name="imgRemoteUserAvatar" StretchDirection="Both" />
+ </Border>
+ <Label Grid.Row="1" Content="Available" Foreground="#FF2BE400" Padding="1" Name="lblRemoteUserStatus" HorizontalContentAlignment="Left" VerticalAlignment="Top" Margin="5,1"></Label>
+ <Label Grid.Row="3" Content="Available" Foreground="#FF2BE400" Padding="1" Name="lblCurrentUserStatus" HorizontalContentAlignment="Left" VerticalAlignment="Bottom" Margin="5,1"></Label>
+ <Border Grid.Row="4" Margin="5" BorderThickness="1" Background="#FF272626">
+ <Image Stretch="UniformToFill" Name="imgCurrentUserAvatar" StretchDirection="Both" />
+ </Border>
+ </Grid>
+ </Grid>
+</Window>
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml.cs
new file mode 100644
index 0000000..c801d54
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/PrivateChatWindow.xaml.cs
@@ -0,0 +1,190 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Interop;
+using System.Windows.Media;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Client;
+using Hik.Samples.Scs.IrcChat.Controls;
+
+namespace Hik.Samples.Scs.IrcChat.Windows
+{
+ /// <summary>
+ /// Interaction logic for PrivateChatWindow.xaml
+ /// </summary>
+ public partial class PrivateChatWindow : Window, IMessagingAreaContainer
+ {
+ #region Public properties
+
+ /// <summary>
+ /// Nick of the current user.
+ /// </summary>
+ public string CurrentUserNick { set; get; }
+
+ /// <summary>
+ /// Sets the status of the current user.
+ /// </summary>
+ public UserStatus CurrentUserStatus
+ {
+ set { SetStatus(lblCurrentUserStatus, value); }
+ }
+
+ /// <summary>
+ /// Sets the avatar picture of current user.
+ /// </summary>
+ public ImageSource CurrentUserAvatar
+ {
+ set { imgCurrentUserAvatar.Source = value; }
+ }
+
+ /// <summary>
+ /// Gets/Sets the nick of the remote user.
+ /// </summary>
+ public string RemoteUserNick
+ {
+ set
+ {
+ _remoteUserNick = value;
+ Title = _remoteUserNick;
+ }
+
+ get { return _remoteUserNick; }
+ }
+ private string _remoteUserNick;
+
+ /// <summary>
+ /// Sets the status of the remote user.
+ /// </summary>
+ public UserStatus RemoteUserStatus
+ {
+ set
+ {
+ _remoteUserStatus = value;
+ SetStatus(lblRemoteUserStatus, _remoteUserStatus);
+ }
+ }
+ private UserStatus _remoteUserStatus;
+
+ /// <summary>
+ /// Sets the avatar picture of the remote user.
+ /// </summary>
+ public ImageSource RemoteUserAvatar
+ {
+ set { imgRemoteUserAvatar.Source = value; }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Reference to chat controller to send private messages to remote user.
+ /// </summary>
+ private readonly IChatController _controller;
+
+ /// <summary>
+ /// WindowInteropHelper object that is used to get a Handle to this window.
+ /// </summary>
+ private readonly WindowInteropHelper _windowInteropHelper;
+
+ #endregion
+
+ #region Contructor and initializing methods
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="controller">Reference to chat controller to send private messages to remote user</param>
+ public PrivateChatWindow(IChatController controller)
+ {
+ _controller = controller;
+ _windowInteropHelper = new WindowInteropHelper(this);
+ InitializeComponent();
+ InitializeControls();
+ }
+
+ private void InitializeControls()
+ {
+ MessageHistory.MessagingAreaContainer = this;
+ MessageHistory.IsTextStyleChangingEnabled = false;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// This method is used to add a new message to message history of that window.
+ /// </summary>
+ /// <param name="message">Message</param>
+ public void MessageReceived(ChatMessage message)
+ {
+ MessageHistory.MessageReceived(_remoteUserNick, message);
+ if (!IsActive)
+ {
+ //Flash taskbar button if this window is not active
+ WindowsHelper.FlashWindow(_windowInteropHelper.Handle, WindowsHelper.FlashWindowFlags.FLASHW_TRAY, 1, 1000);
+ ClientHelper.PlayIncomingMessageSound();
+ }
+ }
+
+ /// <summary>
+ /// This method is called when remote user has logged off.
+ /// </summary>
+ public void UserLoggedOut()
+ {
+ Title = RemoteUserNick + " - offline";
+ MessageHistory.IsReadOnly = true;
+ lblRemoteUserStatus.Content = "Offline";
+ lblRemoteUserStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFDDDDDD"));
+ }
+
+ /// <summary>
+ /// This method is called when remote user has logged in again.
+ /// </summary>
+ public void UserLoggedIn()
+ {
+ Title = RemoteUserNick;
+ MessageHistory.IsReadOnly = false;
+ }
+
+ /// <summary>
+ /// This method is called by MessagingAreaControl to send messages.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ public void SendMessage(ChatMessage message)
+ {
+ _controller.SendPrivateMessage(RemoteUserNick, message);
+ MessageHistory.MessageReceived(CurrentUserNick, message);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Sets status of a user to a label.
+ /// </summary>
+ /// <param name="statusLabel">Label to show user status</param>
+ /// <param name="status">New status of the user</param>
+ private static void SetStatus(Label statusLabel, UserStatus status)
+ {
+ switch (status)
+ {
+ case UserStatus.Busy:
+ statusLabel.Content = "Busy";
+ statusLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFF4E4E"));
+ break;
+ case UserStatus.Out:
+ statusLabel.Content = "Out";
+ statusLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF3179FE"));
+ break;
+ default: //Default: Available
+ statusLabel.Content = "Available";
+ statusLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF2BE400"));
+ break;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml b/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml
new file mode 100644
index 0000000..ee16d2c
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml
@@ -0,0 +1,25 @@
+<Window x:Class="Hik.Samples.Scs.IrcChat.Windows.TextColorPicker"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="Select text color" Height="211" Width="339" Icon="/ChatClientApp;component/Images/text_color_picker.ico">
+ <Grid Background="#FF606060">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Label Background="#FF343434" Grid.Column="0" Grid.Row="0" Content="Sample text" Foreground="White" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="1" Grid.Row="0" Content="Sample text" Foreground="#FFFF5C5C" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="0" Grid.Row="1" Content="Sample text" Foreground="#FF3EA2FF" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="1" Grid.Row="1" Content="Sample text" Foreground="#FFEAFE44" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="0" Grid.Row="2" Content="Sample text" Foreground="Lime" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="1" Grid.Row="2" Content="Sample text" Foreground="#FFFF41FA" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="0" Grid.Row="3" Content="Sample text" Foreground="#FF47F1E9" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ <Label Background="#FF343434" Grid.Column="1" Grid.Row="3" Content="Sample text" Foreground="#FFFFBA41" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="1" Padding="3" MouseLeftButtonUp="Label_MouseLeftButtonUp" />
+ </Grid>
+</Window>
diff --git a/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml.cs b/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml.cs
new file mode 100644
index 0000000..5ff4374
--- /dev/null
+++ b/samples/IrcChatSystem/ChatClientApp/Windows/TextColorPicker.xaml.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Hik.Samples.Scs.IrcChat.Windows
+{
+ /// <summary>
+ /// Interaction logic for ColorPicker.xaml
+ /// </summary>
+ public partial class TextColorPicker : Window
+ {
+ public Color SelectedColor { get; private set; }
+
+ public TextColorPicker()
+ {
+ InitializeComponent();
+ }
+
+ private void Label_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ var selectedLabel = sender as Label;
+ if (selectedLabel == null)
+ {
+ return;
+ }
+
+ var brush = selectedLabel.Foreground as SolidColorBrush;
+ if(brush == null)
+ {
+ return;
+ }
+
+ SelectedColor = brush.Color;
+
+ DialogResult = true;
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/ChatCommonLib.csproj b/samples/IrcChatSystem/ChatCommonLib/ChatCommonLib.csproj
new file mode 100644
index 0000000..ff95d88
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/ChatCommonLib.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A57047DE-CC39-4C01-955E-D73888A0C83D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Hik.Samples.Scs</RootNamespace>
+ <AssemblyName>ChatCommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Debug\ChatCommonLib.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Release\ChatCommonLib.XML</DocumentationFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IrcChat\Arguments\ChatMessage.cs" />
+ <Compile Include="IrcChat\Arguments\MessageTextStyle.cs" />
+ <Compile Include="IrcChat\Exceptions\NickInUseException.cs" />
+ <Compile Include="IrcChat\Arguments\UserStatus.cs" />
+ <Compile Include="IrcChat\Contracts\IChatClient.cs" />
+ <Compile Include="IrcChat\Contracts\IChatService.cs" />
+ <Compile Include="IrcChat\Arguments\UserInfo.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/ChatMessage.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/ChatMessage.cs
new file mode 100644
index 0000000..3fe595e
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/ChatMessage.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Hik.Samples.Scs.IrcChat.Arguments
+{
+ /// <summary>
+ /// Represents a chat message that can be sent and received by chat users.
+ /// </summary>
+ [Serializable]
+ public class ChatMessage
+ {
+ /// <summary>
+ /// Message text.
+ /// </summary>
+ public string MessageText { get; set; }
+
+ ///<summary>
+ /// Text style of this message.
+ ///</summary>
+ public MessageTextStyle TextStyle { get; set; }
+
+ /// <summary>
+ /// Creates a new ChatMessage.
+ /// </summary>
+ public ChatMessage()
+ {
+ TextStyle = new MessageTextStyle();
+ MessageText = "";
+ }
+
+ /// <summary>
+ /// Creates a new ChatMessage.
+ /// </summary>
+ /// <param name="messageText">Message text</param>
+ public ChatMessage(string messageText)
+ {
+ TextStyle = new MessageTextStyle();
+ MessageText = messageText;
+ }
+
+ /// <summary>
+ /// Creates a new ChatMessage.
+ /// </summary>
+ /// <param name="messageText">Message text</param>
+ /// <param name="textStyle">Text style of this message</param>
+ public ChatMessage(string messageText, MessageTextStyle textStyle)
+ {
+ TextStyle = textStyle;
+ MessageText = messageText;
+ }
+ }
+} \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/MessageTextStyle.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/MessageTextStyle.cs
new file mode 100644
index 0000000..4467c22
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/MessageTextStyle.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Hik.Samples.Scs.IrcChat.Arguments
+{
+ /// <summary>
+ /// Represents text style of messages.
+ /// </summary>
+ [Serializable]
+ public class MessageTextStyle
+ {
+ /// <summary>
+ /// True, if message is sent as Bold.
+ /// </summary>
+ public bool IsBold { get; set; }
+
+ /// <summary>
+ /// True, if message is sent as italic.
+ /// </summary>
+ public bool IsItalic { get; set; }
+
+ /// <summary>
+ /// Font family of message.
+ /// </summary>
+ public string FontFamily { get; set; }
+
+ /// <summary>
+ /// Message text color.
+ /// </summary>
+ public Color TextColor { get; set; }
+
+ /// <summary>
+ /// Size of message text.
+ /// </summary>
+ public int TextSize { get; set; }
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ public MessageTextStyle()
+ {
+ FontFamily = "Verdana";
+ TextColor = new Color {Blue = 255, Green = 255, Red = 255};
+ TextSize = 12;
+ }
+
+ /// <summary>
+ /// Represents a color.
+ /// </summary>
+ [Serializable]
+ public class Color
+ {
+ /// <summary>
+ /// Red value of color.
+ /// </summary>
+ public byte Red { get; set; }
+
+ /// <summary>
+ /// Green value of color.
+ /// </summary>
+ public byte Green { get; set; }
+
+ /// <summary>
+ /// Blue value of color.
+ /// </summary>
+ public byte Blue { get; set; }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserInfo.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserInfo.cs
new file mode 100644
index 0000000..c228e8b
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserInfo.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Hik.Samples.Scs.IrcChat.Arguments
+{
+ /// <summary>
+ /// Represents a chat user.
+ /// This object particularly used in Login of a user.
+ /// </summary>
+ [Serializable]
+ public class UserInfo
+ {
+ /// <summary>
+ /// Nick of user.
+ /// </summary>
+ public string Nick { get; set; }
+
+ /// <summary>
+ /// Bytes of avatar of user.
+ /// </summary>
+ public byte[] AvatarBytes { get; set; }
+
+ /// <summary>
+ /// Status of user.
+ /// </summary>
+ public UserStatus Status { get; set; }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserStatus.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserStatus.cs
new file mode 100644
index 0000000..2644f62
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Arguments/UserStatus.cs
@@ -0,0 +1,23 @@
+namespace Hik.Samples.Scs.IrcChat.Arguments
+{
+ /// <summary>
+ /// Represents state of a chat user.
+ /// </summary>
+ public enum UserStatus
+ {
+ /// <summary>
+ /// User if online and available for incoming messages.
+ /// </summary>
+ Available,
+
+ /// <summary>
+ /// User is busy and may not answer to messages.
+ /// </summary>
+ Busy,
+
+ /// <summary>
+ /// User is out.
+ /// </summary>
+ Out
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatClient.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatClient.cs
new file mode 100644
index 0000000..bf24c2f
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatClient.cs
@@ -0,0 +1,56 @@
+using Hik.Communication.ScsServices.Service;
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Contracts
+{
+ /// <summary>
+ /// This interface defines methods of chat client.
+ /// Defined methods are called by chat server.
+ /// </summary>
+ public interface IChatClient
+ {
+ /// <summary>
+ /// This method is used to get user list from chat server.
+ /// It is called by server once after user logged in to server.
+ /// </summary>
+ /// <param name="users">All online user informations</param>
+ void GetUserList(UserInfo[] users);
+
+ /// <summary>
+ /// This method is called from chat server to inform that a message
+ /// is sent to chat room publicly.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ void OnMessageToRoom(string nick, ChatMessage message);
+
+ /// <summary>
+ /// This method is called from chat server to inform that a message
+ /// is sent to the current user privately.
+ /// </summary>
+ /// <param name="nick">Nick of sender</param>
+ /// <param name="message">Message</param>
+ void OnPrivateMessage(string nick, ChatMessage message);
+
+ /// <summary>
+ /// This method is called from chat server to inform that a new user
+ /// joined to chat room.
+ /// </summary>
+ /// <param name="userInfo">Informations of new user</param>
+ void OnUserLogin(UserInfo userInfo);
+
+ /// <summary>
+ /// This method is called from chat server to inform that an existing user
+ /// has left the chat room.
+ /// </summary>
+ /// <param name="nick">Informations of new user</param>
+ void OnUserLogout(string nick);
+
+ /// <summary>
+ /// This method is called from chat server to inform that a user changed his/her status.
+ /// </summary>
+ /// <param name="nick">Nick of the user</param>
+ /// <param name="newStatus">New status of the user</param>
+ void OnUserStatusChange(string nick, UserStatus newStatus);
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatService.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatService.cs
new file mode 100644
index 0000000..5f554b2
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Contracts/IChatService.cs
@@ -0,0 +1,49 @@
+using Hik.Communication.ScsServices.Service;
+using Hik.Samples.Scs.IrcChat.Arguments;
+
+namespace Hik.Samples.Scs.IrcChat.Contracts
+{
+ /// <summary>
+ /// This interface defines Chat Service Contract.
+ /// It is used by Chat clients to interact with Chat Server.
+ /// </summary>
+ [ScsService(Version = "1.0.0.0")]
+ public interface IChatService
+ {
+ /// <summary>
+ /// Used to login to chat service.
+ /// </summary>
+ /// <param name="userInfo">User informations</param>
+ void Login(UserInfo userInfo);
+
+ /// <summary>
+ /// Sends a public message to room.
+ /// It will be seen by all users in room.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ void SendMessageToRoom(ChatMessage message);
+
+ /// <summary>
+ /// Sends a private message to a specific user.
+ /// Message will be seen only by destination user.
+ /// </summary>
+ /// <param name="destinationNick">Nick of the destination user
+ /// who will receive the message</param>
+ /// <param name="message">Message to be sent</param>
+ void SendPrivateMessage(string destinationNick, ChatMessage message);
+
+ /// <summary>
+ /// Changes status of a user and inform all other users.
+ /// </summary>
+ /// <param name="newStatus">New status of user</param>
+ void ChangeStatus(UserStatus newStatus);
+
+ /// <summary>
+ /// Used to logout from chat service.
+ /// Client may not call this method while logging out (in an application crash situation),
+ /// it will also be logged out automatically when connection fails between
+ /// client and server.
+ /// </summary>
+ void Logout();
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/IrcChat/Exceptions/NickInUseException.cs b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Exceptions/NickInUseException.cs
new file mode 100644
index 0000000..41f3424
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/IrcChat/Exceptions/NickInUseException.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Hik.Samples.Scs.IrcChat.Exceptions
+{
+ /// <summary>
+ /// This exception is thrown by Chat server if a user wants to login
+ /// with a nick that is being used by another user.
+ /// </summary>
+ [Serializable]
+ public class NickInUseException : ApplicationException
+ {
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public NickInUseException()
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public NickInUseException(SerializationInfo serializationInfo, StreamingContext context)
+ : base(serializationInfo, context)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ public NickInUseException(string message)
+ : base(message)
+ {
+
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatCommonLib/Properties/AssemblyInfo.cs b/samples/IrcChatSystem/ChatCommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ffe4eba
--- /dev/null
+++ b/samples/IrcChatSystem/ChatCommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("ChatCommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ChatCommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("c57972ac-fbe0-4cfa-ad54-70e1a3fc7dbc")]
+
+// 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")]
diff --git a/samples/IrcChatSystem/ChatServerApp/App.xaml b/samples/IrcChatSystem/ChatServerApp/App.xaml
new file mode 100644
index 0000000..e7ee178
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/App.xaml
@@ -0,0 +1,8 @@
+<Application x:Class="ChatServerApp.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ StartupUri="IrcChat/Server/MainWindow.xaml">
+ <Application.Resources>
+
+ </Application.Resources>
+</Application>
diff --git a/samples/IrcChatSystem/ChatServerApp/App.xaml.cs b/samples/IrcChatSystem/ChatServerApp/App.xaml.cs
new file mode 100644
index 0000000..9baf508
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/App.xaml.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace ChatServerApp
+{
+ /// <summary>
+ /// Interaction logic for App.xaml
+ /// </summary>
+ public partial class App : Application
+ {
+ }
+}
diff --git a/samples/IrcChatSystem/ChatServerApp/ChatServerApp.csproj b/samples/IrcChatSystem/ChatServerApp/ChatServerApp.csproj
new file mode 100644
index 0000000..25e6b31
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/ChatServerApp.csproj
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{277B1094-3C64-4EDE-A17E-A975D797A30B}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Hik.Samples.Scs</RootNamespace>
+ <AssemblyName>ChatServerApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationIcon>app_icon.ico</ApplicationIcon>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="IrcChat\Server\MainWindow.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="IrcChat\Server\ChatService.cs" />
+ <Compile Include="IrcChat\Server\MainWindow.xaml.cs">
+ <DependentUpon>MainWindow.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <AppDesigner Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ChatCommonLib\ChatCommonLib.csproj">
+ <Project>{A57047DE-CC39-4C01-955E-D73888A0C83D}</Project>
+ <Name>ChatCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\app_icon.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="app_icon.ico" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatServerApp/Images/app_icon.ico b/samples/IrcChatSystem/ChatServerApp/Images/app_icon.ico
new file mode 100644
index 0000000..dc5af4a
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Images/app_icon.ico
Binary files differ
diff --git a/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/ChatService.cs b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/ChatService.cs
new file mode 100644
index 0000000..9ba3bca
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/ChatService.cs
@@ -0,0 +1,385 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Hik.Collections;
+using Hik.Communication.ScsServices.Service;
+using Hik.Samples.Scs.IrcChat.Arguments;
+using Hik.Samples.Scs.IrcChat.Contracts;
+using Hik.Samples.Scs.IrcChat.Exceptions;
+
+namespace Hik.Samples.Scs.IrcChat.Server
+{
+ /// <summary>
+ /// This class implements Chat Service Contract.
+ /// </summary>
+ internal class ChatService : ScsService, IChatService
+ {
+ #region Public Events
+
+ /// <summary>
+ /// This event is raised when online user list is changes.
+ /// It is usually raised when a new user log in or a user log out.
+ /// </summary>
+ public event EventHandler UserListChanged;
+
+ #endregion
+
+ #region Public Properties
+
+ /// <summary>
+ /// Gets a list of online users.
+ /// </summary>
+ public List<UserInfo> UserList
+ {
+ get
+ {
+ return (from client in _clients.GetAllItems()
+ select client.User).ToList();
+ }
+ }
+
+ #endregion
+
+ #region Private Fields
+
+ /// <summary>
+ /// List of all connected clients.
+ /// </summary>
+ private readonly ThreadSafeSortedList<long, ChatClient> _clients;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ public ChatService()
+ {
+ _clients = new ThreadSafeSortedList<long, ChatClient>();
+ }
+
+ #endregion
+
+ #region IChatService methods
+
+ /// <summary>
+ /// Used to login to chat service.
+ /// </summary>
+ /// <param name="userInfo">User informations</param>
+ public void Login(UserInfo userInfo)
+ {
+ //Check nick if it is being used by another user
+ if (FindClientByNick(userInfo.Nick) != null)
+ {
+ throw new NickInUseException("The nick '" + userInfo.Nick + "' is being used by another user. Please select another one.");
+ }
+
+ //Get a reference to the current client that is calling this method
+ var client = CurrentClient;
+
+ //Get a proxy object to call methods of client when needed
+ var clientProxy = client.GetClientProxy<IChatClient>();
+
+ //Create a ChatClient and store it in a collection
+ var chatClient = new ChatClient(client, clientProxy, userInfo);
+ _clients[client.ClientId] = chatClient;
+
+ //Register to Disconnected event to know when user connection is closed
+ client.Disconnected += Client_Disconnected;
+
+ //Start a new task to send user list to new user and to inform
+ //all users that a new user joined to room
+ Task.Factory.StartNew(
+ () =>
+ {
+ OnUserListChanged();
+ SendUserListToClient(chatClient);
+ SendUserLoginInfoToAllClients(userInfo);
+ });
+ }
+
+ /// <summary>
+ /// Sends a public message to room.
+ /// It will be seen all users in room.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ public void SendMessageToRoom(ChatMessage message)
+ {
+ //Get ChatClient object
+ var senderClient = _clients[CurrentClient.ClientId];
+ if (senderClient == null)
+ {
+ throw new ApplicationException("Can not send message before login.");
+ }
+
+ //Send message to all online users
+ Task.Factory.StartNew(
+ () =>
+ {
+ foreach (var chatClient in _clients.GetAllItems())
+ {
+ try
+ {
+ chatClient.ClientProxy.OnMessageToRoom(senderClient.User.Nick, message);
+ }
+ catch
+ {
+
+ }
+ }
+ });
+ }
+
+ /// <summary>
+ /// Sends a private message to a specific user.
+ /// Message will be seen only by destination user.
+ /// </summary>
+ /// <param name="destinationNick">Nick of the destination user who will receive message</param>
+ /// <param name="message">Message to be sent</param>
+ public void SendPrivateMessage(string destinationNick, ChatMessage message)
+ {
+ //Get ChatClient object for sender user
+ var senderClient = _clients[CurrentClient.ClientId];
+ if (senderClient == null)
+ {
+ throw new ApplicationException("Can not send message before login.");
+ }
+
+ //Get ChatClient object for destination user
+ var receiverClient = FindClientByNick(destinationNick);
+ if (receiverClient == null)
+ {
+ throw new ApplicationException("There is no online user with nick " + destinationNick);
+ }
+
+ //Send message to destination user
+ receiverClient.ClientProxy.OnPrivateMessage(senderClient.User.Nick, message);
+ }
+
+ /// <summary>
+ /// Changes status of a user and inform all other users.
+ /// </summary>
+ /// <param name="newStatus">New status of user</param>
+ public void ChangeStatus(UserStatus newStatus)
+ {
+ //Get ChatClient object
+ var senderClient = _clients[CurrentClient.ClientId];
+ if (senderClient == null)
+ {
+ throw new ApplicationException("Can not change state before login.");
+ }
+
+ //Set new status
+ senderClient.User.Status = newStatus;
+
+ //Send status of user to all online users
+ Task.Factory.StartNew(
+ () =>
+ {
+ foreach (var chatClient in _clients.GetAllItems())
+ {
+ try
+ {
+ chatClient.ClientProxy.OnUserStatusChange(senderClient.User.Nick, newStatus);
+ }
+ catch
+ {
+
+ }
+ }
+ });
+ }
+
+ /// <summary>
+ /// Used to logout from chat service.
+ /// Client may not call this method while logging out (in an application crash situation),
+ /// it will also be logged out automatically when connection fails between client and server.
+ /// </summary>
+ public void Logout()
+ {
+ ClientLogout(CurrentClient.ClientId);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles Disconnected event of all clients.
+ /// </summary>
+ /// <param name="sender">Client object that is disconnected</param>
+ /// <param name="e">Event arguments (not used in this event)</param>
+ private void Client_Disconnected(object sender, EventArgs e)
+ {
+ //Get client object
+ var client = (IScsServiceClient)sender;
+
+ //Perform logout (so, if client did not call Logout method before close,
+ //we do logout automatically.
+ ClientLogout(client.ClientId);
+ }
+
+ /// <summary>
+ /// This method is used to send list of all online users to a new joined user.
+ /// </summary>
+ /// <param name="client">New user that is joined to service</param>
+ private void SendUserListToClient(ChatClient client)
+ {
+ //Get all users except new user
+ var userList = UserList.Where((user) => (user.Nick != client.User.Nick)).ToArray();
+
+ //Do not send list if no user available (except the new user)
+ if (userList.Length <= 0)
+ {
+ return;
+ }
+
+ client.ClientProxy.GetUserList(userList);
+ }
+
+ /// <summary>
+ /// This method is called when a client Calls Logout method of service or a client
+ /// connection fails.
+ /// </summary>
+ /// <param name="clientId">Unique Id of client that is logged out</param>
+ private void ClientLogout(long clientId)
+ {
+ //Get client from client list, if not in list do not continue
+ var client = _clients[clientId];
+ if (client == null)
+ {
+ return;
+ }
+
+ //Remove client from online clients list
+ _clients.Remove(client.Client.ClientId);
+
+ //Unregister to Disconnected event (not needed really)
+ client.Client.Disconnected -= Client_Disconnected;
+
+ //Start a new task to inform all other users
+ Task.Factory.StartNew(
+ () =>
+ {
+ OnUserListChanged();
+ SendUserLogoutInfoToAllClients(client.User.Nick);
+ });
+ }
+
+ /// <summary>
+ /// This method is used to inform all online clients
+ /// that a new user joined to room.
+ /// </summary>
+ /// <param name="userInfo">New joined user's informations</param>
+ private void SendUserLoginInfoToAllClients(UserInfo userInfo)
+ {
+ foreach (var client in _clients.GetAllItems())
+ {
+ //Do not send informations to user that is logged in.
+ if (client.User.Nick == userInfo.Nick)
+ {
+ continue;
+ }
+
+ try
+ {
+ client.ClientProxy.OnUserLogin(userInfo);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method is used to inform all online clients
+ /// that a user disconnected from chat server.
+ /// </summary>
+ /// <param name="nick">Nick of disconnected user</param>
+ private void SendUserLogoutInfoToAllClients(string nick)
+ {
+ foreach (var client in _clients.GetAllItems())
+ {
+ try
+ {
+ client.ClientProxy.OnUserLogout(nick);
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ /// <summary>
+ /// Finds ChatClient ojbect by given nick.
+ /// </summary>
+ /// <param name="nick">Nick to search</param>
+ /// <returns>Found ChatClient for that nick, or null if not found</returns>
+ private ChatClient FindClientByNick(string nick)
+ {
+ return (from client in _clients.GetAllItems()
+ where client.User.Nick == nick
+ select client).FirstOrDefault();
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises UserListChanged event.
+ /// </summary>
+ private void OnUserListChanged()
+ {
+ var handler = UserListChanged;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+ #region Sub classes
+
+ /// <summary>
+ /// This class is used to store informations for a connected client.
+ /// </summary>
+ private sealed class ChatClient
+ {
+ /// <summary>
+ /// Scs client reference.
+ /// </summary>
+ public IScsServiceClient Client { get; private set; }
+
+ /// <summary>
+ /// Proxy object to call remote methods of chat client.
+ /// </summary>
+ public IChatClient ClientProxy { get; private set; }
+
+ /// <summary>
+ /// User informations of client.
+ /// </summary>
+ public UserInfo User { get; private set; }
+
+ /// <summary>
+ /// Creates a new ChatClient object.
+ /// </summary>
+ /// <param name="client">Scs client reference</param>
+ /// <param name="clientProxy">Proxy object to call remote methods of chat client</param>
+ /// <param name="userInfo">User informations of client</param>
+ public ChatClient(IScsServiceClient client, IChatClient clientProxy, UserInfo userInfo)
+ {
+ Client = client;
+ ClientProxy = clientProxy;
+ User = userInfo;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml
new file mode 100644
index 0000000..cf5f454
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml
@@ -0,0 +1,50 @@
+<Window x:Class="Hik.Samples.Scs.IrcChat.Server.MainWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="SCS Chat Server" Height="300" Width="500" Icon="/ChatServerApp;component/app_icon.ico">
+ <Grid Background="#FF1F1F1F">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="70"></RowDefinition>
+ <RowDefinition Height="*"></RowDefinition>
+ </Grid.RowDefinitions>
+ <Border Grid.Row="0" BorderThickness="1" Padding="5" Margin="10" BorderBrush="#FF878383" CornerRadius="10">
+ <Border.Background>
+ <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+ <GradientStop Color="Black" Offset="0" />
+ <GradientStop Color="#FF323232" Offset="1" />
+ </LinearGradientBrush>
+ </Border.Background>
+ <Grid UseLayoutRounding="True">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <StackPanel Orientation="Horizontal">
+ <Label Content="Server Port: " VerticalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalAlignment="Left" Padding="2" Margin="3" Foreground="White" />
+ <TextBox Name="txtPort" Text="10048" VerticalAlignment="Center" Width="60" TextAlignment="Center" Margin="3" Background="White" />
+ </StackPanel>
+ <StackPanel Orientation="Horizontal" Grid.Column="2" HorizontalAlignment="Right">
+ <Button Name="btnStartServer" Content="Start Server" VerticalAlignment="Center" Margin="3,0" Padding="4" Click="btnStartServer_Click"></Button>
+ <Button Name="btnStopServer" Content="Stop Server" VerticalAlignment="Center" Margin="3,0" Padding="4" Click="btnStopServer_Click" IsEnabled="False" />
+ </StackPanel>
+ </Grid>
+ </Border>
+ <Border Grid.Row="1" BorderThickness="1" Padding="5" Margin="10,0,10,10" BorderBrush="#FF878383" CornerRadius="10">
+ <Border.Background>
+ <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
+ <GradientStop Color="Black" Offset="0" />
+ <GradientStop Color="#FF323232" Offset="1" />
+ </LinearGradientBrush>
+ </Border.Background>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="25"></RowDefinition>
+ <RowDefinition Height="*"></RowDefinition>
+ </Grid.RowDefinitions>
+ <Label Content="Online Users" Foreground="Lime" HorizontalContentAlignment="Center" FontWeight="Normal" FontSize="13" FontStyle="Normal" FontStretch="Normal" />
+ <TextBlock Grid.Row="1" Name="lblUsers" TextWrapping="Wrap" Text="user1, user2, user3" Margin="5" FontSize="12" Foreground="Gainsboro"/>
+ </Grid>
+ </Border>
+ </Grid>
+</Window>
diff --git a/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml.cs b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml.cs
new file mode 100644
index 0000000..6ccefd5
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/IrcChat/Server/MainWindow.xaml.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Text;
+using System.Windows;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Service;
+using Hik.Samples.Scs.IrcChat.Contracts;
+
+namespace Hik.Samples.Scs.IrcChat.Server
+{
+ /// <summary>
+ /// Interaction logic for MainWindow.xaml
+ /// </summary>
+ public partial class MainWindow : Window
+ {
+ /// <summary>
+ /// This object is used to host Chat Service on a SCS server.
+ /// </summary>
+ private IScsServiceApplication _serviceApplication;
+
+ /// <summary>
+ /// Chat Service object that serves clients.
+ /// </summary>
+ private ChatService _chatService;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ public MainWindow()
+ {
+ InitializeComponent();
+ lblUsers.Text = "";
+ }
+
+ /// <summary>
+ /// Handles Client event of 'Start Server' button.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void btnStartServer_Click(object sender, RoutedEventArgs e)
+ {
+ //Get TCP port number from textbox
+ int port;
+ try
+ {
+ port = Convert.ToInt32(txtPort.Text);
+ if (port <= 0 || port > 65536)
+ {
+ throw new Exception(port + " is not a valid TCP port number.");
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("TCP port must be a positive number. Exception detail: " + ex.Message);
+ return;
+ }
+
+ try
+ {
+ _serviceApplication = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(port));
+ _chatService = new ChatService();
+ _serviceApplication.AddService<IChatService, ChatService>(_chatService);
+ _chatService.UserListChanged += chatService_UserListChanged;
+ _serviceApplication.Start();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Service can not be started. Exception detail: " + ex.Message);
+ return;
+ }
+
+ btnStartServer.IsEnabled = false;
+ btnStopServer.IsEnabled = true;
+ txtPort.IsEnabled = false;
+ }
+
+ private void chatService_UserListChanged(object sender, EventArgs e)
+ {
+ Dispatcher.Invoke(new Action(UpdateUserList));
+ }
+
+ /// <summary>
+ /// Handles Client event of 'Stop Server' button.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void btnStopServer_Click(object sender, RoutedEventArgs e)
+ {
+ if (_serviceApplication == null)
+ {
+ return;
+ }
+
+ _serviceApplication.Stop();
+
+ btnStartServer.IsEnabled = true;
+ btnStopServer.IsEnabled = false;
+ txtPort.IsEnabled = true;
+ }
+
+ /// <summary>
+ /// Updates user list on GUI.
+ /// </summary>
+ private void UpdateUserList()
+ {
+ var users = new StringBuilder();
+ foreach (var user in _chatService.UserList)
+ {
+ if (users.Length > 0)
+ {
+ users.Append(", ");
+ }
+
+ users.Append(user.Nick);
+ }
+
+ lblUsers.Text = users.ToString();
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatServerApp/Properties/AssemblyInfo.cs b/samples/IrcChatSystem/ChatServerApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6854d1e
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 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("ChatServerApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ChatServerApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// 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")]
diff --git a/samples/IrcChatSystem/ChatServerApp/Properties/Resources.Designer.cs b/samples/IrcChatSystem/ChatServerApp/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..97d941c
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Hik.Samples.Scs.Properties {
+ 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()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Hik.Samples.Scs.Properties.Resources", typeof(Resources).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)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatServerApp/Properties/Resources.resx b/samples/IrcChatSystem/ChatServerApp/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatServerApp/Properties/Settings.Designer.cs b/samples/IrcChatSystem/ChatServerApp/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..6e716de
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Hik.Samples.Scs.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/samples/IrcChatSystem/ChatServerApp/Properties/Settings.settings b/samples/IrcChatSystem/ChatServerApp/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/samples/IrcChatSystem/ChatServerApp/app_icon.ico b/samples/IrcChatSystem/ChatServerApp/app_icon.ico
new file mode 100644
index 0000000..dc5af4a
--- /dev/null
+++ b/samples/IrcChatSystem/ChatServerApp/app_icon.ico
Binary files differ
diff --git a/samples/IrcChatSystem/IrcChatSystem.sln b/samples/IrcChatSystem/IrcChatSystem.sln
new file mode 100644
index 0000000..90fbb76
--- /dev/null
+++ b/samples/IrcChatSystem/IrcChatSystem.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatCommonLib", "ChatCommonLib\ChatCommonLib.csproj", "{A57047DE-CC39-4C01-955E-D73888A0C83D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatServerApp", "ChatServerApp\ChatServerApp.csproj", "{277B1094-3C64-4EDE-A17E-A975D797A30B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatClientApp", "ChatClientApp\ChatClientApp.csproj", "{6571B5F6-C92F-4266-ACC9-186347994E9F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {A57047DE-CC39-4C01-955E-D73888A0C83D}.Release|x86.ActiveCfg = Release|Any CPU
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Debug|x86.ActiveCfg = Debug|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Debug|x86.Build.0 = Debug|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Release|Any CPU.ActiveCfg = Release|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Release|Mixed Platforms.Build.0 = Release|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Release|x86.ActiveCfg = Release|x86
+ {277B1094-3C64-4EDE-A17E-A975D797A30B}.Release|x86.Build.0 = Release|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Debug|x86.ActiveCfg = Debug|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Debug|x86.Build.0 = Debug|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Release|Any CPU.ActiveCfg = Release|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Release|Mixed Platforms.Build.0 = Release|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Release|x86.ActiveCfg = Release|x86
+ {6571B5F6-C92F-4266-ACC9-186347994E9F}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/OnlinePhoneBook/OnlinePhoneBook.sln b/samples/OnlinePhoneBook/OnlinePhoneBook.sln
new file mode 100644
index 0000000..4bcd0fc
--- /dev/null
+++ b/samples/OnlinePhoneBook/OnlinePhoneBook.sln
@@ -0,0 +1,66 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneBookCommonLib", "PhoneBookCommonLib\PhoneBookCommonLib.csproj", "{10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneBookServer", "PhoneBookServer\PhoneBookServer.csproj", "{739C7AC7-A88F-482D-A459-831600D03E4D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneBookClient", "PhoneBookClient\PhoneBookClient.csproj", "{03750D57-CFAC-4262-9C3F-C06A6265361B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimlifiedPhoneBookClient", "SimlifiedPhoneBookClient\SimlifiedPhoneBookClient.csproj", "{C37B1CDC-3F1E-4694-AFAD-235725A9A811}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Debug|x86.ActiveCfg = Debug|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Debug|x86.Build.0 = Debug|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Release|Any CPU.ActiveCfg = Release|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Release|Mixed Platforms.Build.0 = Release|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Release|x86.ActiveCfg = Release|x86
+ {739C7AC7-A88F-482D-A459-831600D03E4D}.Release|x86.Build.0 = Release|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Debug|x86.ActiveCfg = Debug|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Debug|x86.Build.0 = Debug|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Release|Any CPU.ActiveCfg = Release|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Release|Mixed Platforms.Build.0 = Release|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Release|x86.ActiveCfg = Release|x86
+ {03750D57-CFAC-4262-9C3F-C06A6265361B}.Release|x86.Build.0 = Release|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Debug|x86.ActiveCfg = Debug|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Debug|x86.Build.0 = Debug|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Release|Any CPU.ActiveCfg = Release|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Release|Mixed Platforms.Build.0 = Release|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Release|x86.ActiveCfg = Release|x86
+ {C37B1CDC-3F1E-4694-AFAD-235725A9A811}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/OnlinePhoneBook/PhoneBookClient/PhoneBookClient.csproj b/samples/OnlinePhoneBook/PhoneBookClient/PhoneBookClient.csproj
new file mode 100644
index 0000000..19e7acf
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookClient/PhoneBookClient.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{03750D57-CFAC-4262-9C3F-C06A6265361B}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBookClient</RootNamespace>
+ <AssemblyName>PhoneBookClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\PhoneBookCommonLib\PhoneBookCommonLib.csproj">
+ <Project>{10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}</Project>
+ <Name>PhoneBookCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/OnlinePhoneBook/PhoneBookClient/Program.cs b/samples/OnlinePhoneBook/PhoneBookClient/Program.cs
new file mode 100644
index 0000000..d34fa05
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookClient/Program.cs
@@ -0,0 +1,52 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Client;
+using PhoneBookCommonLib;
+
+/* This is a simple client application that uses phone book server.
+ */
+
+namespace PhoneBookClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a client to connecto to phone book service on local server and 10048 TCP port.
+ var client = ScsServiceClientBuilder.CreateClient<IPhoneBookService>(
+ new ScsTcpEndPoint("127.0.0.1", 10048));
+
+ Console.WriteLine("Press enter to connect to phone book service...");
+ Console.ReadLine();
+
+ //Connect to the server
+ client.Connect();
+
+ var person1 = new PhoneBookRecord { Name = "Halil ibrahim", Phone = "5881112233" };
+ var person2 = new PhoneBookRecord { Name = "John Nash", Phone = "58833322211" };
+
+ //Add some persons
+ client.ServiceProxy.AddPerson(person1);
+ client.ServiceProxy.AddPerson(person2);
+
+ //Search for a person
+ var person = client.ServiceProxy.FindPerson("Halil");
+ if (person != null)
+ {
+ Console.WriteLine("Person is found:");
+ Console.WriteLine(person);
+ }
+ else
+ {
+ Console.WriteLine("Can not find person!");
+ }
+
+ Console.WriteLine();
+ Console.WriteLine("Press enter to disconnect from phone book service...");
+ Console.ReadLine();
+
+ //Disconnect from server
+ client.Disconnect();
+ }
+ }
+}
diff --git a/samples/OnlinePhoneBook/PhoneBookClient/Properties/AssemblyInfo.cs b/samples/OnlinePhoneBook/PhoneBookClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..26c72ec
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("PhoneBookClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("PhoneBookClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("c28c191a-1ca4-4049-97aa-3dd515ba6603")]
+
+// 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")]
diff --git a/samples/OnlinePhoneBook/PhoneBookCommonLib/IPhoneBookService.cs b/samples/OnlinePhoneBook/PhoneBookCommonLib/IPhoneBookService.cs
new file mode 100644
index 0000000..9f73c49
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookCommonLib/IPhoneBookService.cs
@@ -0,0 +1,33 @@
+using Hik.Communication.ScsServices.Service;
+
+namespace PhoneBookCommonLib
+{
+ /// <summary>
+ /// This interface defines methods of Phone Book Service
+ /// that can be called remotely by client applications.
+ /// </summary>
+ [ScsService(Version = "1.0.0.0")]
+ public interface IPhoneBookService
+ {
+ /// <summary>
+ /// Adds a new person to phone book.
+ /// </summary>
+ /// <param name="recordToAdd">Person informations to add</param>
+ void AddPerson(PhoneBookRecord recordToAdd);
+
+ /// <summary>
+ /// Deletes a person from phone book.
+ /// </summary>
+ /// <param name="name">Name of the person to delete</param>
+ /// <returns>True, if a person is deleted, false if person is not found</returns>
+ bool DeletePerson(string name);
+
+ /// <summary>
+ /// Searches a person in phone book by name of person.
+ /// </summary>
+ /// <param name="name">Name of person to search.
+ /// Name might not fully match, it can be a part of person's name</param>
+ /// <returns>Person informations if found, else null</returns>
+ PhoneBookRecord FindPerson(string name);
+ }
+}
diff --git a/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookCommonLib.csproj b/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookCommonLib.csproj
new file mode 100644
index 0000000..0210926
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookCommonLib.csproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBookCommonLib</RootNamespace>
+ <AssemblyName>PhoneBookCommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IPhoneBookService.cs" />
+ <Compile Include="PhoneBookRecord.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookRecord.cs b/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookRecord.cs
new file mode 100644
index 0000000..a1c5706
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookCommonLib/PhoneBookRecord.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace PhoneBookCommonLib
+{
+ /// <summary>
+ /// Represents a record in phone book.
+ /// </summary>
+ [Serializable]
+ public class PhoneBookRecord
+ {
+ /// <summary>
+ /// Name of the person.
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Phone number of the person.
+ /// </summary>
+ public string Phone { get; set; }
+
+ /// <summary>
+ /// Creation date of this record.
+ /// </summary>
+ public DateTime CreationDate { get; set; }
+
+ /// <summary>
+ /// Creates a new PhoneBookRecord object.
+ /// </summary>
+ public PhoneBookRecord()
+ {
+ CreationDate = DateTime.Now;
+ }
+
+ /// <summary>
+ /// Generates a string representation of this object.
+ /// </summary>
+ /// <returns>String representation of this object</returns>
+ public override string ToString()
+ {
+ return string.Format("Name = {0}, Phone = {1}", Name, Phone);
+ }
+ }
+} \ No newline at end of file
diff --git a/samples/OnlinePhoneBook/PhoneBookCommonLib/Properties/AssemblyInfo.cs b/samples/OnlinePhoneBook/PhoneBookCommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e685388
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookCommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("PhoneBookCommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("PhoneBookCommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("14d99672-f6af-4ef8-8613-49f23b49636a")]
+
+// 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")]
diff --git a/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookServer.csproj b/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookServer.csproj
new file mode 100644
index 0000000..5cd77d9
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookServer.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{739C7AC7-A88F-482D-A459-831600D03E4D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBookServer</RootNamespace>
+ <AssemblyName>PhoneBookServer</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="PhoneBookService.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\PhoneBookCommonLib\PhoneBookCommonLib.csproj">
+ <Project>{10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}</Project>
+ <Name>PhoneBookCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookService.cs b/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookService.cs
new file mode 100644
index 0000000..d9b3389
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookServer/PhoneBookService.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using Hik.Communication.ScsServices.Service;
+using PhoneBookCommonLib;
+
+namespace PhoneBookServer
+{
+ /// <summary>
+ /// This class implements Phone Book Service contract.
+ /// </summary>
+ class PhoneBookService : ScsService, IPhoneBookService
+ {
+ /// <summary>
+ /// Current records that are added to phone book service.
+ /// Key: Name of the person.
+ /// Value: PhoneBookRecord object.
+ /// </summary>
+ private readonly SortedList<string, PhoneBookRecord> _records;
+
+ /// <summary>
+ /// Creates a new PhoneBookService object.
+ /// </summary>
+ public PhoneBookService()
+ {
+ _records = new SortedList<string, PhoneBookRecord>();
+ }
+
+ /// <summary>
+ /// Adds a new person to phone book.
+ /// </summary>
+ /// <param name="recordToAdd">Person informations to add</param>
+ public void AddPerson(PhoneBookRecord recordToAdd)
+ {
+ if (recordToAdd == null)
+ {
+ throw new ArgumentNullException("recordToAdd");
+ }
+
+ _records[recordToAdd.Name] = recordToAdd;
+ Console.WriteLine("A new person is added: "+ recordToAdd.Name + " (" + recordToAdd.Phone + ")");
+ }
+
+ /// <summary>
+ /// Deletes a person from phone book.
+ /// </summary>
+ /// <param name="name">Name of the person to delete</param>
+ /// <returns>True, if a person is deleted, false if person is not found</returns>
+ public bool DeletePerson(string name)
+ {
+ if (!_records.ContainsKey(name))
+ {
+ return false;
+ }
+
+ _records.Remove(name);
+ return true;
+ }
+
+ /// <summary>
+ /// Searches a person in phone book by name of person.
+ /// </summary>
+ /// <param name="name">Name of person to search.
+ /// Name might not fully match, it can be a part of person's name</param>
+ /// <returns>Person informations if found, else null</returns>
+ public PhoneBookRecord FindPerson(string name)
+ {
+ //Get recods by name if there is a record exactly match to given name
+ if (_records.ContainsKey(name))
+ {
+ return _records[name];
+ }
+
+ //Search all records to check if there is a name string that contains given name
+ foreach (var record in _records)
+ {
+ if (record.Key.ToLower().Contains(name.ToLower()))
+ {
+ return record.Value;
+ }
+ }
+
+ //Not found
+ return null;
+ }
+ }
+}
diff --git a/samples/OnlinePhoneBook/PhoneBookServer/Program.cs b/samples/OnlinePhoneBook/PhoneBookServer/Program.cs
new file mode 100644
index 0000000..56ae262
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookServer/Program.cs
@@ -0,0 +1,32 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Service;
+using PhoneBookCommonLib;
+
+/* This is a simple phone book server application that runs on SCS framework.
+ */
+
+namespace PhoneBookServer
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a Scs Service application that runs on 10048 TCP port.
+ var server = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(10048));
+
+ //Add Phone Book Service to service application
+ server.AddService<IPhoneBookService, PhoneBookService>(new PhoneBookService());
+
+ //Start server
+ server.Start();
+
+ //Wait user to stop server by pressing Enter
+ Console.WriteLine("Phone Book Server started successfully. Press enter to stop...");
+ Console.ReadLine();
+
+ //Stop server
+ server.Stop();
+ }
+ }
+}
diff --git a/samples/OnlinePhoneBook/PhoneBookServer/Properties/AssemblyInfo.cs b/samples/OnlinePhoneBook/PhoneBookServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c706336
--- /dev/null
+++ b/samples/OnlinePhoneBook/PhoneBookServer/Properties/AssemblyInfo.cs
@@ -0,0 +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("PhoneBookServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("PhoneBookServer")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("f3344e62-7cde-4cf2-8982-d93ee153dcd9")]
+
+// 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")]
diff --git a/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Program.cs b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Program.cs
new file mode 100644
index 0000000..370e58b
--- /dev/null
+++ b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Program.cs
@@ -0,0 +1,27 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Client;
+using PhoneBookCommonLib;
+
+/* This is the simplest client application that uses phone book server.
+ * (Just 2 lines of code to connect to the server and call a method.
+ */
+
+namespace SimlifiedPhoneBookClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.ReadLine();
+
+ //Create a client to connecto to phone book service on local server and 10048 TCP port.
+ var client = ScsServiceClientBuilder.CreateClient<IPhoneBookService>(new ScsTcpEndPoint("127.0.0.1", 10048));
+
+ //Directly call a method (it automatically connects, calls and disconnects)
+ client.ServiceProxy.AddPerson(new PhoneBookRecord { Name = "Halil ibrahim", Phone = "5881112233" });
+
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Properties/AssemblyInfo.cs b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f4e779a
--- /dev/null
+++ b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("SimlifiedPhoneBookClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("SimlifiedPhoneBookClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("f37932c6-8c52-456c-9fc9-e26c17e3d186")]
+
+// 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")]
diff --git a/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/SimlifiedPhoneBookClient.csproj b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/SimlifiedPhoneBookClient.csproj
new file mode 100644
index 0000000..6ed9344
--- /dev/null
+++ b/samples/OnlinePhoneBook/SimlifiedPhoneBookClient/SimlifiedPhoneBookClient.csproj
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C37B1CDC-3F1E-4694-AFAD-235725A9A811}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SimlifiedPhoneBookClient</RootNamespace>
+ <AssemblyName>SimlifiedPhoneBookClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs">
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\PhoneBookCommonLib\PhoneBookCommonLib.csproj">
+ <Project>{10ECC585-8B5F-499E-B65F-F6B0DA17DEA2}</Project>
+ <Name>PhoneBookCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleCalculatorSystem/CalculatorClient/CalculatorClient.csproj b/samples/SimpleCalculatorSystem/CalculatorClient/CalculatorClient.csproj
new file mode 100644
index 0000000..d9b1a48
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorClient/CalculatorClient.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6DD6F730-E353-4B0C-9655-8370A943A7BF}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorClient</RootNamespace>
+ <AssemblyName>CalculatorClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CalculatorCommonLib\CalculatorCommonLib.csproj">
+ <Project>{6F2D58C9-0395-4048-A304-17304D12BC63}</Project>
+ <Name>CalculatorCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleCalculatorSystem/CalculatorClient/Program.cs b/samples/SimpleCalculatorSystem/CalculatorClient/Program.cs
new file mode 100644
index 0000000..09b209a
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorClient/Program.cs
@@ -0,0 +1,33 @@
+using System;
+using CalculatorCommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Client;
+
+namespace CalculatorClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.WriteLine("Press enter to connect to server and call methods...");
+ Console.ReadLine();
+
+ //Create a client that can call methods of Calculator Service that is running on local computer and 10083 TCP port
+ //Since IScsServiceClient is IDisposible, it closes connection at the end of the using block
+ using (var client = ScsServiceClientBuilder.CreateClient<ICalculatorService>(new ScsTcpEndPoint("127.0.0.1", 10083)))
+ {
+ //Connect to the server
+ client.Connect();
+
+ //Call a remote method of server
+ var division = client.ServiceProxy.Divide(42, 3);
+
+ //Write the result to the screen
+ Console.WriteLine("Result: " + division);
+ }
+
+ Console.WriteLine("Press enter to stop client application");
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/samples/SimpleCalculatorSystem/CalculatorClient/Properties/AssemblyInfo.cs b/samples/SimpleCalculatorSystem/CalculatorClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1c1a455
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("5712ded0-d09a-4e56-8de4-1d9145854ee5")]
+
+// 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")]
diff --git a/samples/SimpleCalculatorSystem/CalculatorCommonLib/CalculatorCommonLib.csproj b/samples/SimpleCalculatorSystem/CalculatorCommonLib/CalculatorCommonLib.csproj
new file mode 100644
index 0000000..90eca61
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorCommonLib/CalculatorCommonLib.csproj
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6F2D58C9-0395-4048-A304-17304D12BC63}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorCommonLib</RootNamespace>
+ <AssemblyName>CalculatorCommonLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ICalculatorService.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleCalculatorSystem/CalculatorCommonLib/ICalculatorService.cs b/samples/SimpleCalculatorSystem/CalculatorCommonLib/ICalculatorService.cs
new file mode 100644
index 0000000..c04013f
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorCommonLib/ICalculatorService.cs
@@ -0,0 +1,15 @@
+using Hik.Communication.ScsServices.Service;
+
+namespace CalculatorCommonLib
+{
+ /// <summary>
+ /// This interface defines methods of calculator service that can be called by clients.
+ /// </summary>
+ [ScsService]
+ public interface ICalculatorService
+ {
+ int Add(int number1, int number2);
+
+ double Divide(double number1, double number2);
+ }
+}
diff --git a/samples/SimpleCalculatorSystem/CalculatorCommonLib/Properties/AssemblyInfo.cs b/samples/SimpleCalculatorSystem/CalculatorCommonLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4848095
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorCommonLib/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorCommonLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorCommonLib")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("8a08ef54-dde6-4f7a-8656-57518c5098ea")]
+
+// 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")]
diff --git a/samples/SimpleCalculatorSystem/CalculatorServer/CalculatorServer.csproj b/samples/SimpleCalculatorSystem/CalculatorServer/CalculatorServer.csproj
new file mode 100644
index 0000000..259762d
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorServer/CalculatorServer.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1BB6B428-E4C3-467F-824F-1DB84E310FF2}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CalculatorServer</RootNamespace>
+ <AssemblyName>CalculatorServer</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CalculatorCommonLib\CalculatorCommonLib.csproj">
+ <Project>{6F2D58C9-0395-4048-A304-17304D12BC63}</Project>
+ <Name>CalculatorCommonLib</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleCalculatorSystem/CalculatorServer/Program.cs b/samples/SimpleCalculatorSystem/CalculatorServer/Program.cs
new file mode 100644
index 0000000..8ec07ef
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorServer/Program.cs
@@ -0,0 +1,46 @@
+using System;
+using CalculatorCommonLib;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.ScsServices.Service;
+
+namespace CalculatorServer
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a service application that runs on 10083 TCP port
+ var serviceApplication = ScsServiceBuilder.CreateService(new ScsTcpEndPoint(10083));
+
+ //Create a CalculatorService and add it to service application
+ serviceApplication.AddService<ICalculatorService, CalculatorService>(new CalculatorService());
+
+ //Start service application
+ serviceApplication.Start();
+
+ Console.WriteLine("Calculator service is started. Press enter to stop...");
+ Console.ReadLine();
+
+ //Stop service application
+ serviceApplication.Stop();
+ }
+ }
+
+ public class CalculatorService : ScsService, ICalculatorService
+ {
+ public int Add(int number1, int number2)
+ {
+ return number1 + number2;
+ }
+
+ public double Divide(double number1, double number2)
+ {
+ if(number2 == 0.0)
+ {
+ throw new DivideByZeroException("number2 can not be zero!");
+ }
+
+ return number1 / number2;
+ }
+ }
+}
diff --git a/samples/SimpleCalculatorSystem/CalculatorServer/Properties/AssemblyInfo.cs b/samples/SimpleCalculatorSystem/CalculatorServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..46a9398
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/CalculatorServer/Properties/AssemblyInfo.cs
@@ -0,0 +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("CalculatorServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("CalculatorServer")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("fc3f0ecf-46ea-437e-a535-82dffae3dc9e")]
+
+// 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")]
diff --git a/samples/SimpleCalculatorSystem/SimpleCalculatorSystem.sln b/samples/SimpleCalculatorSystem/SimpleCalculatorSystem.sln
new file mode 100644
index 0000000..236647f
--- /dev/null
+++ b/samples/SimpleCalculatorSystem/SimpleCalculatorSystem.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorServer", "CalculatorServer\CalculatorServer.csproj", "{1BB6B428-E4C3-467F-824F-1DB84E310FF2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorCommonLib", "CalculatorCommonLib\CalculatorCommonLib.csproj", "{6F2D58C9-0395-4048-A304-17304D12BC63}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorClient", "CalculatorClient\CalculatorClient.csproj", "{6DD6F730-E353-4B0C-9655-8370A943A7BF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|x86.ActiveCfg = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Debug|x86.Build.0 = Debug|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Any CPU.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|Mixed Platforms.Build.0 = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|x86.ActiveCfg = Release|x86
+ {1BB6B428-E4C3-467F-824F-1DB84E310FF2}.Release|x86.Build.0 = Release|x86
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {6F2D58C9-0395-4048-A304-17304D12BC63}.Release|x86.ActiveCfg = Release|Any CPU
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|x86.ActiveCfg = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Debug|x86.Build.0 = Debug|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Any CPU.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|Mixed Platforms.Build.0 = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|x86.ActiveCfg = Release|x86
+ {6DD6F730-E353-4B0C-9655-8370A943A7BF}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/SimpleMessaging/ClientApp/ClientApp.csproj b/samples/SimpleMessaging/ClientApp/ClientApp.csproj
new file mode 100644
index 0000000..58743d4
--- /dev/null
+++ b/samples/SimpleMessaging/ClientApp/ClientApp.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{5F6A7126-4996-41AF-A4C1-13DA3D54C71B}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ClientApp</RootNamespace>
+ <AssemblyName>ClientApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleMessaging/ClientApp/Program.cs b/samples/SimpleMessaging/ClientApp/Program.cs
new file mode 100644
index 0000000..cfec50d
--- /dev/null
+++ b/samples/SimpleMessaging/ClientApp/Program.cs
@@ -0,0 +1,51 @@
+using System;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+/* This program is build to demonstrate a client application that connects to a server
+ * and sends/receives messages in basic way of SCS framework.
+ */
+
+namespace ClientApp
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a client object to connect a server on 127.0.0.1 (local) IP and listens 10085 TCP port
+ var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10085));
+
+ //Register to MessageReceived event to receive messages from server.
+ client.MessageReceived += Client_MessageReceived;
+
+ Console.WriteLine("Press enter to connect to the server...");
+ Console.ReadLine(); //Wait user to press enter
+
+ client.Connect(); //Connect to the server
+
+ Console.Write("Write some message to be sent to server: ");
+ var messageText = Console.ReadLine(); //Get a message from user
+
+ //Send message to the server
+ client.SendMessage(new ScsTextMessage(messageText));
+
+ Console.WriteLine("Press enter to disconnect from server...");
+ Console.ReadLine(); //Wait user to press enter
+
+ client.Disconnect(); //Close connection to server
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ //Client only accepts text messages
+ var message = e.Message as ScsTextMessage;
+ if (message == null)
+ {
+ return;
+ }
+
+ Console.WriteLine("Server sent a message: " + message.Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/samples/SimpleMessaging/ClientApp/Properties/AssemblyInfo.cs b/samples/SimpleMessaging/ClientApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a10a169
--- /dev/null
+++ b/samples/SimpleMessaging/ClientApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ClientApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ClientApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("eee05ea3-074b-45e7-8cbf-8c4cf2ad4cf5")]
+
+// 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")]
diff --git a/samples/SimpleMessaging/RequestReplyStyleClient/Program.cs b/samples/SimpleMessaging/RequestReplyStyleClient/Program.cs
new file mode 100644
index 0000000..7916b96
--- /dev/null
+++ b/samples/SimpleMessaging/RequestReplyStyleClient/Program.cs
@@ -0,0 +1,43 @@
+using System;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+
+/* This program is build to demonstrate a client application that connects to a server
+ * and sends/receives messages in using RequestReplyMessenger.
+ */
+
+namespace RequestReplyStyleClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.WriteLine("Press enter to connect to the server...");
+ Console.ReadLine(); //Wait user to press enter
+
+ //Create a client object to connect a server on 127.0.0.1 (local) IP and listens 10085 TCP port
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10085)))
+ {
+ //Create a RequestReplyMessenger that uses the client as internal messenger.
+ using (var requestReplyMessenger = new RequestReplyMessenger<IScsClient>(client))
+ {
+ requestReplyMessenger.Start(); //Start request/reply messenger
+ client.Connect(); //Connect to the server
+
+ Console.Write("Write some message to be sent to server: ");
+ var messageText = Console.ReadLine(); //Get a message from user
+
+ //Send user message to the server and get response
+ var response = requestReplyMessenger.SendMessageAndWaitForResponse(new ScsTextMessage(messageText));
+
+ Console.WriteLine("Response to message: " + ((ScsTextMessage) response).Text);
+
+ Console.WriteLine("Press enter to disconnect from server...");
+ Console.ReadLine(); //Wait user to press enter
+ }
+ }
+ }
+ }
+}
diff --git a/samples/SimpleMessaging/RequestReplyStyleClient/Properties/AssemblyInfo.cs b/samples/SimpleMessaging/RequestReplyStyleClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6112008
--- /dev/null
+++ b/samples/SimpleMessaging/RequestReplyStyleClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("RequestReplyStyleClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("RequestReplyStyleClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("70a9a155-d522-4415-b673-b42003f8186f")]
+
+// 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")]
diff --git a/samples/SimpleMessaging/RequestReplyStyleClient/RequestReplyStyleClient.csproj b/samples/SimpleMessaging/RequestReplyStyleClient/RequestReplyStyleClient.csproj
new file mode 100644
index 0000000..b098f39
--- /dev/null
+++ b/samples/SimpleMessaging/RequestReplyStyleClient/RequestReplyStyleClient.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3671E987-CA41-4DAF-8D43-CF86E9AD9519}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>RequestReplyStyleClient</RootNamespace>
+ <AssemblyName>RequestReplyStyleClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleMessaging/ServerApp/Program.cs b/samples/SimpleMessaging/ServerApp/Program.cs
new file mode 100644
index 0000000..449cf0c
--- /dev/null
+++ b/samples/SimpleMessaging/ServerApp/Program.cs
@@ -0,0 +1,66 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Server;
+
+/* This program is build to demonstrate a server application that listens incoming
+ * client connections and reply messages.
+ */
+
+namespace ServerApp
+{
+ class Program
+ {
+ static void Main()
+ {
+ //Create a server that listens 10085 TCP port for incoming connections
+ var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10085));
+
+ //Register events of the server to be informed about clients
+ server.ClientConnected += Server_ClientConnected;
+ server.ClientDisconnected += Server_ClientDisconnected;
+
+ server.Start(); //Start the server
+
+ Console.WriteLine("Server is started successfully. Press enter to stop...");
+ Console.ReadLine(); //Wait user to press enter
+
+ server.Stop(); //Stop the server
+ }
+
+ static void Server_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ Console.WriteLine("A new client is connected. Client Id = " + e.Client.ClientId);
+
+ //Register to MessageReceived event to receive messages from new client
+ e.Client.MessageReceived += Client_MessageReceived;
+ }
+
+ static void Server_ClientDisconnected(object sender, ServerClientEventArgs e)
+ {
+ Console.WriteLine("A client is disconnected! Client Id = " + e.Client.ClientId);
+ }
+
+ static void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var message = e.Message as ScsTextMessage; //Server only accepts text messages
+ if (message == null)
+ {
+ return;
+ }
+
+ //Get a reference to the client
+ var client = (IScsServerClient)sender;
+
+ Console.WriteLine("Client sent a message: " + message.Text +
+ " (Cliend Id = " + client.ClientId + ")");
+
+ //Send reply message to the client
+ client.SendMessage(
+ new ScsTextMessage(
+ "Hello client. I got your message (" + message.Text + ")",
+ message.MessageId //Set first message's id as replied message id
+ ));
+ }
+ }
+}
diff --git a/samples/SimpleMessaging/ServerApp/Properties/AssemblyInfo.cs b/samples/SimpleMessaging/ServerApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c0a3988
--- /dev/null
+++ b/samples/SimpleMessaging/ServerApp/Properties/AssemblyInfo.cs
@@ -0,0 +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("ServerApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ServerApp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("849b296f-ea34-47ab-a0e1-d8a178496264")]
+
+// 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")]
diff --git a/samples/SimpleMessaging/ServerApp/ServerApp.csproj b/samples/SimpleMessaging/ServerApp/ServerApp.csproj
new file mode 100644
index 0000000..2c79b88
--- /dev/null
+++ b/samples/SimpleMessaging/ServerApp/ServerApp.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3731733F-5B49-4677-B353-43475305644D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ServerApp</RootNamespace>
+ <AssemblyName>ServerApp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/samples/SimpleMessaging/SimpleMessaging.sln b/samples/SimpleMessaging/SimpleMessaging.sln
new file mode 100644
index 0000000..663cd07
--- /dev/null
+++ b/samples/SimpleMessaging/SimpleMessaging.sln
@@ -0,0 +1,66 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerApp", "ServerApp\ServerApp.csproj", "{3731733F-5B49-4677-B353-43475305644D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientApp", "ClientApp\ClientApp.csproj", "{5F6A7126-4996-41AF-A4C1-13DA3D54C71B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RequestReplyStyleClient", "RequestReplyStyleClient\RequestReplyStyleClient.csproj", "{3671E987-CA41-4DAF-8D43-CF86E9AD9519}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SynchronizedClient", "SynchronizedClient\SynchronizedClient.csproj", "{256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3731733F-5B49-4677-B353-43475305644D}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Debug|x86.ActiveCfg = Debug|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Debug|x86.Build.0 = Debug|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Release|Any CPU.ActiveCfg = Release|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Release|Mixed Platforms.Build.0 = Release|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Release|x86.ActiveCfg = Release|x86
+ {3731733F-5B49-4677-B353-43475305644D}.Release|x86.Build.0 = Release|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Debug|x86.ActiveCfg = Debug|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Debug|x86.Build.0 = Debug|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Release|Any CPU.ActiveCfg = Release|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Release|Mixed Platforms.Build.0 = Release|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Release|x86.ActiveCfg = Release|x86
+ {5F6A7126-4996-41AF-A4C1-13DA3D54C71B}.Release|x86.Build.0 = Release|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Debug|x86.ActiveCfg = Debug|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Debug|x86.Build.0 = Debug|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Release|Any CPU.ActiveCfg = Release|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Release|Mixed Platforms.Build.0 = Release|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Release|x86.ActiveCfg = Release|x86
+ {3671E987-CA41-4DAF-8D43-CF86E9AD9519}.Release|x86.Build.0 = Release|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Debug|x86.ActiveCfg = Debug|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Debug|x86.Build.0 = Debug|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Release|Any CPU.ActiveCfg = Release|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Release|Mixed Platforms.Build.0 = Release|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Release|x86.ActiveCfg = Release|x86
+ {256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/SimpleMessaging/SynchronizedClient/Program.cs b/samples/SimpleMessaging/SynchronizedClient/Program.cs
new file mode 100644
index 0000000..aa7e3d2
--- /dev/null
+++ b/samples/SimpleMessaging/SynchronizedClient/Program.cs
@@ -0,0 +1,46 @@
+using System;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+
+/* This program is build to demonstrate a client application that connects to a server
+ * and sends/receives messages in using SynchronizedMessenger.
+ */
+
+namespace SynchronizedClient
+{
+ class Program
+ {
+ static void Main()
+ {
+ Console.WriteLine("Press enter to connect to the server...");
+ Console.ReadLine(); //Wait user to press enter
+
+ //Create a client object to connect a server on 127.0.0.1 (local) IP and listens 10085 TCP port
+ using (var client = ScsClientFactory.CreateClient(new ScsTcpEndPoint("127.0.0.1", 10085)))
+ {
+ //Create a SynchronizedMessenger that uses the client as internal messenger.
+ using (var synchronizedMessenger = new SynchronizedMessenger<IScsClient>(client))
+ {
+ synchronizedMessenger.Start(); //Start synchronized messenger messenger
+ client.Connect(); //Connect to the server
+
+ Console.Write("Write some message to be sent to server: ");
+ var messageText = Console.ReadLine(); //Get a message from user
+
+ //Send a message to the server
+ synchronizedMessenger.SendMessage(new ScsTextMessage(messageText));
+
+ //Receive a message from the server
+ var receivedMessage = synchronizedMessenger.ReceiveMessage<ScsTextMessage>();
+
+ Console.WriteLine("Response to message: " + (receivedMessage.Text));
+
+ Console.WriteLine("Press enter to disconnect from server...");
+ Console.ReadLine(); //Wait user to press enter
+ }
+ }
+ }
+ }
+}
diff --git a/samples/SimpleMessaging/SynchronizedClient/Properties/AssemblyInfo.cs b/samples/SimpleMessaging/SynchronizedClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6731277
--- /dev/null
+++ b/samples/SimpleMessaging/SynchronizedClient/Properties/AssemblyInfo.cs
@@ -0,0 +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("SynchronizedClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("SynchronizedClient")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("c705458e-5ba3-49fb-93e8-a3a813fb15b7")]
+
+// 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")]
diff --git a/samples/SimpleMessaging/SynchronizedClient/SynchronizedClient.csproj b/samples/SimpleMessaging/SynchronizedClient/SynchronizedClient.csproj
new file mode 100644
index 0000000..ae29c57
--- /dev/null
+++ b/samples/SimpleMessaging/SynchronizedClient/SynchronizedClient.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{256CA4BD-6131-4BD6-8EDB-BA9C2C706DA4}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SynchronizedClient</RootNamespace>
+ <AssemblyName>SynchronizedClient</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Scs">
+ <HintPath>..\..\..\Scs-Binaries\Scs.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/Scs.sln b/src/Scs.sln
new file mode 100644
index 0000000..dcbc4c2
--- /dev/null
+++ b/src/Scs.sln
@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scs", "Scs\Scs.csproj", "{0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/Scs/Changes.txt b/src/Scs/Changes.txt
new file mode 100644
index 0000000..574ae60
--- /dev/null
+++ b/src/Scs/Changes.txt
@@ -0,0 +1,37 @@
+# Version 1.1.0.1 - 13.06.2011 - Halil ibrahim Kalkan
+ # Bugfix:
+ # Ping message must not be raised by messaging layer.
+
+# Version 1.1.0.0 - 28.05.2011 - Halil ibrahim Kalkan
+ # Additions:
+ # ClientDisconnected event added to IScsServiceApplication and IScsServer classes.
+ # MessageSent event is added to IMessenger interface.
+ # SynchronizedMessenger class is added to receive messages as synchronized.
+ # Changes/Improvements:
+ # Changed background thread mechanism to provide more scalable framework.
+ Used TPL Tasks and Async sockets instead of directly use of threads and blocking sockets (Added SequentialItemProcessor class).
+ # Added IScsWireProtocolFactory interface and changed IScsServer.WireProtocol to IScsServer.WireProtocolFactory.
+ Also, IScsWireProtocol is completely changed.
+ (This change is not backward compatible)
+ # BinarySerializationProtocol class is made public to allow user to override serialization methods.
+ # Codes completely revised, some parts refactored and commented.
+ # BugFix:
+ # Fixed a potential minor bug in Timer.
+
+# Version 1.0.2.0 - 11.05.2011 - Halil ibrahim Kalkan
+ Feature:
+ # Added RemoteEndPoint property to get address of client application in server side.
+ (Added to ICommunicationChannel, IScsServerClient and IScsServiceClient)
+
+# Version 1.0.1.0 - 10.04.2011 - Halil ibrahim Kalkan
+ Feature:
+ # Added ConnectTimeout property to IConnectableClient to provide a way of setting
+ timeout value while connecting to a server.
+
+# Version 1.0.0.1 - 10.04.2011 - Halil ibrahim Kalkan
+ BugFix:
+ # RequestReplyMessenger starts when a client is created. It must start when connected to server.
+ Otherwise, if user does not connect to client, a thread remains running.
+
+# Version 1.0.0.0 - 01.02.2011 - Halil ibrahim Kalkan
+ First stable release. \ No newline at end of file
diff --git a/src/Scs/Collections/ThreadSafeSortedList.cs b/src/Scs/Collections/ThreadSafeSortedList.cs
new file mode 100644
index 0000000..10a980d
--- /dev/null
+++ b/src/Scs/Collections/ThreadSafeSortedList.cs
@@ -0,0 +1,197 @@
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Hik.Collections
+{
+ /// <summary>
+ /// This class is used to store key-value based items in a thread safe manner.
+ /// It uses System.Collections.Generic.SortedList internally.
+ /// </summary>
+ /// <typeparam name="TK">Key type</typeparam>
+ /// <typeparam name="TV">Value type</typeparam>
+ public class ThreadSafeSortedList<TK, TV>
+ {
+ /// <summary>
+ /// Gets/adds/replaces an item by key.
+ /// </summary>
+ /// <param name="key">Key to get/set value</param>
+ /// <returns>Item associated with this key</returns>
+ public TV this[TK key]
+ {
+ get
+ {
+ _lock.EnterReadLock();
+ try
+ {
+ return _items.ContainsKey(key) ? _items[key] : default(TV);
+ }
+ finally
+ {
+ _lock.ExitReadLock();
+ }
+ }
+
+ set
+ {
+ _lock.EnterWriteLock();
+ try
+ {
+ _items[key] = value;
+ }
+ finally
+ {
+ _lock.ExitWriteLock();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets count of items in the collection.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ _lock.EnterReadLock();
+ try
+ {
+ return _items.Count;
+ }
+ finally
+ {
+ _lock.ExitReadLock();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Internal collection to store items.
+ /// </summary>
+ protected readonly SortedList<TK, TV> _items;
+
+ /// <summary>
+ /// Used to synchronize access to _items list.
+ /// </summary>
+ protected readonly ReaderWriterLockSlim _lock;
+
+ /// <summary>
+ /// Creates a new ThreadSafeSortedList object.
+ /// </summary>
+ public ThreadSafeSortedList()
+ {
+ _items = new SortedList<TK, TV>();
+ _lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
+ }
+
+ /// <summary>
+ /// Checks if collection contains spesified key.
+ /// </summary>
+ /// <param name="key">Key to check</param>
+ /// <returns>True; if collection contains given key</returns>
+ public bool ContainsKey(TK key)
+ {
+ _lock.EnterReadLock();
+ try
+ {
+ return _items.ContainsKey(key);
+ }
+ finally
+ {
+ _lock.ExitReadLock();
+ }
+ }
+
+ /// <summary>
+ /// Checks if collection contains spesified item.
+ /// </summary>
+ /// <param name="item">Item to check</param>
+ /// <returns>True; if collection contains given item</returns>
+ public bool ContainsValue(TV item)
+ {
+ _lock.EnterReadLock();
+ try
+ {
+ return _items.ContainsValue(item);
+ }
+ finally
+ {
+ _lock.ExitReadLock();
+ }
+ }
+
+ /// <summary>
+ /// Removes an item from collection.
+ /// </summary>
+ /// <param name="key">Key of item to remove</param>
+ public bool Remove(TK key)
+ {
+ _lock.EnterWriteLock();
+ try
+ {
+ if (!_items.ContainsKey(key))
+ {
+ return false;
+ }
+
+ _items.Remove(key);
+ return true;
+ }
+ finally
+ {
+ _lock.ExitWriteLock();
+ }
+ }
+
+ /// <summary>
+ /// Gets all items in collection.
+ /// </summary>
+ /// <returns>Item list</returns>
+ public List<TV> GetAllItems()
+ {
+ _lock.EnterReadLock();
+ try
+ {
+ return new List<TV>(_items.Values);
+ }
+ finally
+ {
+ _lock.ExitReadLock();
+ }
+ }
+
+ /// <summary>
+ /// Removes all items from list.
+ /// </summary>
+ public void ClearAll()
+ {
+ _lock.EnterWriteLock();
+ try
+ {
+ _items.Clear();
+ }
+ finally
+ {
+ _lock.ExitWriteLock();
+ }
+ }
+
+ /// <summary>
+ /// Gets then removes all items in collection.
+ /// </summary>
+ /// <returns>Item list</returns>
+ public List<TV> GetAndClearAllItems()
+ {
+ _lock.EnterWriteLock();
+ try
+ {
+ var list = new List<TV>(_items.Values);
+ _items.Clear();
+ return list;
+ }
+ finally
+ {
+ _lock.ExitWriteLock();
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/ClientReConnecter.cs b/src/Scs/Communication/Scs/Client/ClientReConnecter.cs
new file mode 100644
index 0000000..88f0159
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/ClientReConnecter.cs
@@ -0,0 +1,109 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Threading;
+
+namespace Hik.Communication.Scs.Client
+{
+ /// <summary>
+ /// This class is used to automatically re-connect to server if disconnected.
+ /// It attempts to reconnect to server periodically until connection established.
+ /// </summary>
+ public class ClientReConnecter : IDisposable
+ {
+ /// <summary>
+ /// Reconnect check period.
+ /// Default: 20 seconds.
+ /// </summary>
+ public int ReConnectCheckPeriod
+ {
+ get { return _reconnectTimer.Period; }
+ set { _reconnectTimer.Period = value; }
+ }
+
+ /// <summary>
+ /// Reference to client object.
+ /// </summary>
+ private readonly IConnectableClient _client;
+
+ /// <summary>
+ /// Timer to attempt ro reconnect periodically.
+ /// </summary>
+ private readonly Timer _reconnectTimer;
+
+ /// <summary>
+ /// Indicates the dispose state of this object.
+ /// </summary>
+ private volatile bool _disposed;
+
+ /// <summary>
+ /// Creates a new ClientReConnecter object.
+ /// It is not needed to start ClientReConnecter since it automatically
+ /// starts when the client disconnected.
+ /// </summary>
+ /// <param name="client">Reference to client object</param>
+ /// <exception cref="ArgumentNullException">Throws ArgumentNullException if client is null.</exception>
+ public ClientReConnecter(IConnectableClient client)
+ {
+ if (client == null)
+ {
+ throw new ArgumentNullException("client");
+ }
+
+ _client = client;
+ _client.Disconnected += Client_Disconnected;
+ _reconnectTimer = new Timer(20000);
+ _reconnectTimer.Elapsed += ReconnectTimer_Elapsed;
+ _reconnectTimer.Start();
+ }
+
+ /// <summary>
+ /// Disposes this object.
+ /// Does nothing if already disposed.
+ /// </summary>
+ public void Dispose()
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ _disposed = true;
+ _client.Disconnected -= Client_Disconnected;
+ _reconnectTimer.Stop();
+ }
+
+ /// <summary>
+ /// Handles Disconnected event of _client object.
+ /// </summary>
+ /// <param name="sender">Source of the event</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_Disconnected(object sender, EventArgs e)
+ {
+ _reconnectTimer.Start();
+ }
+
+ /// <summary>
+ /// Hadles Elapsed event of _reconnectTimer.
+ /// </summary>
+ /// <param name="sender">Source of the event</param>
+ /// <param name="e">Event arguments</param>
+ private void ReconnectTimer_Elapsed(object sender, EventArgs e)
+ {
+ if (_disposed || _client.CommunicationState == CommunicationStates.Connected)
+ {
+ _reconnectTimer.Stop();
+ return;
+ }
+
+ try
+ {
+ _client.Connect();
+ _reconnectTimer.Stop();
+ }
+ catch
+ {
+ //No need to catch since it will try to re-connect again
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/IConnectableClient.cs b/src/Scs/Communication/Scs/Client/IConnectableClient.cs
new file mode 100644
index 0000000..9bbf7c0
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/IConnectableClient.cs
@@ -0,0 +1,43 @@
+using System;
+using Hik.Communication.Scs.Communication;
+
+namespace Hik.Communication.Scs.Client
+{
+ /// <summary>
+ /// Represents a client for SCS servers.
+ /// </summary>
+ public interface IConnectableClient : IDisposable
+ {
+ /// <summary>
+ /// This event is raised when client connected to server.
+ /// </summary>
+ event EventHandler Connected;
+
+ /// <summary>
+ /// This event is raised when client disconnected from server.
+ /// </summary>
+ event EventHandler Disconnected;
+
+ /// <summary>
+ /// Timeout for connecting to a server (as milliseconds).
+ /// Default value: 15 seconds (15000 ms).
+ /// </summary>
+ int ConnectTimeout { get; set; }
+
+ /// <summary>
+ /// Gets the current communication state.
+ /// </summary>
+ CommunicationStates CommunicationState { get; }
+
+ /// <summary>
+ /// Connects to server.
+ /// </summary>
+ void Connect();
+
+ /// <summary>
+ /// Disconnects from server.
+ /// Does nothing if already disconnected.
+ /// </summary>
+ void Disconnect();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/IScsClient.cs b/src/Scs/Communication/Scs/Client/IScsClient.cs
new file mode 100644
index 0000000..27cafe2
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/IScsClient.cs
@@ -0,0 +1,13 @@
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace Hik.Communication.Scs.Client
+{
+ /// <summary>
+ /// Represents a client to connect to server.
+ /// </summary>
+ public interface IScsClient : IMessenger, IConnectableClient
+ {
+ //Does not define any additional member
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/ScsClientBase.cs b/src/Scs/Communication/Scs/Client/ScsClientBase.cs
new file mode 100644
index 0000000..11cf673
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/ScsClientBase.cs
@@ -0,0 +1,330 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Channels;
+using Hik.Communication.Scs.Communication.Protocols;
+using Hik.Threading;
+
+namespace Hik.Communication.Scs.Client
+{
+ /// <summary>
+ /// This class provides base functionality for client classes.
+ /// </summary>
+ internal abstract class ScsClientBase : IScsClient
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new message is received.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageReceived;
+
+ /// <summary>
+ /// This event is raised when a new message is sent without any error.
+ /// It does not guaranties that message is properly handled and processed by remote application.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageSent;
+
+ /// <summary>
+ /// This event is raised when communication channel closed.
+ /// </summary>
+ public event EventHandler Connected;
+
+ /// <summary>
+ /// This event is raised when client disconnected from server.
+ /// </summary>
+ public event EventHandler Disconnected;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Timeout for connecting to a server (as milliseconds).
+ /// Default value: 15 seconds (15000 ms).
+ /// </summary>
+ public int ConnectTimeout { get; set; }
+
+ /// <summary>
+ /// Gets/sets wire protocol that is used while reading and writing messages.
+ /// </summary>
+ public IScsWireProtocol WireProtocol
+ {
+ get { return _wireProtocol; }
+ set
+ {
+ if (CommunicationState == CommunicationStates.Connected)
+ {
+ throw new ApplicationException("Wire protocol can not be changed while connected to server.");
+ }
+
+ _wireProtocol = value;
+ }
+ }
+ private IScsWireProtocol _wireProtocol;
+
+ /// <summary>
+ /// Gets the communication state of the Client.
+ /// </summary>
+ public CommunicationStates CommunicationState
+ {
+ get
+ {
+ return _communicationChannel != null
+ ? _communicationChannel.CommunicationState
+ : CommunicationStates.Disconnected;
+ }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastReceivedMessageTime
+ {
+ get
+ {
+ return _communicationChannel != null
+ ? _communicationChannel.LastReceivedMessageTime
+ : DateTime.MinValue;
+ }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastSentMessageTime
+ {
+ get
+ {
+ return _communicationChannel != null
+ ? _communicationChannel.LastSentMessageTime
+ : DateTime.MinValue;
+ }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Default timeout value for connecting a server.
+ /// </summary>
+ private const int DefaultConnectionAttemptTimeout = 15000; //15 seconds.
+
+ /// <summary>
+ /// The communication channel that is used by client to send and receive messages.
+ /// </summary>
+ private ICommunicationChannel _communicationChannel;
+
+ /// <summary>
+ /// This timer is used to send PingMessage messages to server periodically.
+ /// </summary>
+ private readonly Timer _pingTimer;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ protected ScsClientBase()
+ {
+ _pingTimer = new Timer(30000);
+ _pingTimer.Elapsed += PingTimer_Elapsed;
+ ConnectTimeout = DefaultConnectionAttemptTimeout;
+ WireProtocol = WireProtocolManager.GetDefaultWireProtocol();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Connects to server.
+ /// </summary>
+ public void Connect()
+ {
+ WireProtocol.Reset();
+ _communicationChannel = CreateCommunicationChannel();
+ _communicationChannel.WireProtocol = WireProtocol;
+ _communicationChannel.Disconnected += CommunicationChannel_Disconnected;
+ _communicationChannel.MessageReceived += CommunicationChannel_MessageReceived;
+ _communicationChannel.MessageSent += CommunicationChannel_MessageSent;
+ _communicationChannel.Start();
+ _pingTimer.Start();
+ OnConnected();
+ }
+
+ /// <summary>
+ /// Disconnects from server.
+ /// Does nothing if already disconnected.
+ /// </summary>
+ public void Disconnect()
+ {
+ if (CommunicationState != CommunicationStates.Connected)
+ {
+ return;
+ }
+
+ _communicationChannel.Disconnect();
+ }
+
+ /// <summary>
+ /// Disposes this object and closes underlying connection.
+ /// </summary>
+ public void Dispose()
+ {
+ Disconnect();
+ }
+
+ /// <summary>
+ /// Sends a message to the server.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ /// <exception cref="CommunicationStateException">Throws a CommunicationStateException if client is not connected to the server.</exception>
+ public void SendMessage(IScsMessage message)
+ {
+ if (CommunicationState != CommunicationStates.Connected)
+ {
+ throw new CommunicationStateException("Client is not connected to the server.");
+ }
+
+ _communicationChannel.SendMessage(message);
+ }
+
+ #endregion
+
+ #region Abstract methods
+
+ /// <summary>
+ /// This method is implemented by derived classes to create appropriate communication channel.
+ /// </summary>
+ /// <returns>Ready communication channel to communicate</returns>
+ protected abstract ICommunicationChannel CreateCommunicationChannel();
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles MessageReceived event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_MessageReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message is ScsPingMessage)
+ {
+ return;
+ }
+
+ OnMessageReceived(e.Message);
+ }
+
+ /// <summary>
+ /// Handles MessageSent event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_MessageSent(object sender, MessageEventArgs e)
+ {
+ OnMessageSent(e.Message);
+ }
+
+ /// <summary>
+ /// Handles Disconnected event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_Disconnected(object sender, EventArgs e)
+ {
+ _pingTimer.Stop();
+ OnDisconnected();
+ }
+
+ /// <summary>
+ /// Handles Elapsed event of _pingTimer to send PingMessage messages to server.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void PingTimer_Elapsed(object sender, EventArgs e)
+ {
+ if (CommunicationState != CommunicationStates.Connected)
+ {
+ return;
+ }
+
+ try
+ {
+ var lastMinute = DateTime.Now.AddMinutes(-1);
+ if (_communicationChannel.LastReceivedMessageTime > lastMinute || _communicationChannel.LastSentMessageTime > lastMinute)
+ {
+ return;
+ }
+
+ _communicationChannel.SendMessage(new ScsPingMessage());
+ }
+ catch
+ {
+
+ }
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises Connected event.
+ /// </summary>
+ protected virtual void OnConnected()
+ {
+ var handler = Connected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Raises Disconnected event.
+ /// </summary>
+ protected virtual void OnDisconnected()
+ {
+ var handler = Disconnected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageReceived event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageReceived(IScsMessage message)
+ {
+ var handler = MessageReceived;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageSent event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageSent(IScsMessage message)
+ {
+ var handler = MessageSent;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/ScsClientFactory.cs b/src/Scs/Communication/Scs/Client/ScsClientFactory.cs
new file mode 100644
index 0000000..877e8dd
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/ScsClientFactory.cs
@@ -0,0 +1,30 @@
+using Hik.Communication.Scs.Communication.EndPoints;
+
+namespace Hik.Communication.Scs.Client
+{
+ /// <summary>
+ /// This class is used to create SCS Clients to connect to a SCS server.
+ /// </summary>
+ public static class ScsClientFactory
+ {
+ /// <summary>
+ /// Creates a new client to connect to a server using an end point.
+ /// </summary>
+ /// <param name="endpoint">End point of the server to connect it</param>
+ /// <returns>Created TCP client</returns>
+ public static IScsClient CreateClient(ScsEndPoint endpoint)
+ {
+ return endpoint.CreateClient();
+ }
+
+ /// <summary>
+ /// Creates a new client to connect to a server using an end point.
+ /// </summary>
+ /// <param name="endpointAddress">End point address of the server to connect it</param>
+ /// <returns>Created TCP client</returns>
+ public static IScsClient CreateClient(string endpointAddress)
+ {
+ return CreateClient(ScsEndPoint.CreateEndPoint(endpointAddress));
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/Tcp/ScsTcpClient.cs b/src/Scs/Communication/Scs/Client/Tcp/ScsTcpClient.cs
new file mode 100644
index 0000000..20ee206
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/Tcp/ScsTcpClient.cs
@@ -0,0 +1,40 @@
+using Hik.Communication.Scs.Communication.Channels;
+using Hik.Communication.Scs.Communication.Channels.Tcp;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using System.Net;
+
+namespace Hik.Communication.Scs.Client.Tcp
+{
+ /// <summary>
+ /// This class is used to communicate with server over TCP/IP protocol.
+ /// </summary>
+ internal class ScsTcpClient : ScsClientBase
+ {
+ /// <summary>
+ /// The endpoint address of the server.
+ /// </summary>
+ private readonly ScsTcpEndPoint _serverEndPoint;
+
+ /// <summary>
+ /// Creates a new ScsTcpClient object.
+ /// </summary>
+ /// <param name="serverEndPoint">The endpoint address to connect to the server</param>
+ public ScsTcpClient(ScsTcpEndPoint serverEndPoint)
+ {
+ _serverEndPoint = serverEndPoint;
+ }
+
+ /// <summary>
+ /// Creates a communication channel using ServerIpAddress and ServerPort.
+ /// </summary>
+ /// <returns>Ready communication channel to communicate</returns>
+ protected override ICommunicationChannel CreateCommunicationChannel()
+ {
+ return new TcpCommunicationChannel(
+ TcpHelper.ConnectToServer(
+ new IPEndPoint(IPAddress.Parse(_serverEndPoint.IpAddress), _serverEndPoint.TcpPort),
+ ConnectTimeout
+ ));
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Client/Tcp/TcpHelper.cs b/src/Scs/Communication/Scs/Client/Tcp/TcpHelper.cs
new file mode 100644
index 0000000..f0cd38b
--- /dev/null
+++ b/src/Scs/Communication/Scs/Client/Tcp/TcpHelper.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Hik.Communication.Scs.Client.Tcp
+{
+ /// <summary>
+ /// This class is used to simplify TCP socket operations.
+ /// </summary>
+ internal static class TcpHelper
+ {
+ /// <summary>
+ /// This code is used to connect to a TCP socket with timeout option.
+ /// </summary>
+ /// <param name="endPoint">IP endpoint of remote server</param>
+ /// <param name="timeoutMs">Timeout to wait until connect</param>
+ /// <returns>Socket object connected to server</returns>
+ /// <exception cref="SocketException">Throws SocketException if can not connect.</exception>
+ /// <exception cref="TimeoutException">Throws TimeoutException if can not connect within specified timeoutMs</exception>
+ public static Socket ConnectToServer(EndPoint endPoint, int timeoutMs)
+ {
+ var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ try
+ {
+ socket.Blocking = false;
+ socket.Connect(endPoint);
+ socket.Blocking = true;
+ return socket;
+ }
+ catch (SocketException socketException)
+ {
+ if (socketException.ErrorCode != 10035)
+ {
+ socket.Close();
+ throw;
+ }
+
+ if (!socket.Poll(timeoutMs * 1000, SelectMode.SelectWrite))
+ {
+ socket.Close();
+ throw new TimeoutException("The host failed to connect. Timeout occured.");
+ }
+
+ socket.Blocking = true;
+ return socket;
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelBase.cs b/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelBase.cs
new file mode 100644
index 0000000..506dce5
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelBase.cs
@@ -0,0 +1,176 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace Hik.Communication.Scs.Communication.Channels
+{
+ /// <summary>
+ /// This class provides base functionality for all communication channel classes.
+ /// </summary>
+ internal abstract class CommunicationChannelBase : ICommunicationChannel
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new message is received.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageReceived;
+
+ /// <summary>
+ /// This event is raised when a new message is sent without any error.
+ /// It does not guaranties that message is properly handled and processed by remote application.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageSent;
+
+ /// <summary>
+ /// This event is raised when communication channel closed.
+ /// </summary>
+ public event EventHandler Disconnected;
+
+ #endregion
+
+ #region Public abstract properties
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ public abstract ScsEndPoint RemoteEndPoint { get; }
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Gets the current communication state.
+ /// </summary>
+ public CommunicationStates CommunicationState { get; protected set; }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastReceivedMessageTime { get; protected set; }
+
+ /// <summary>
+ /// Gets the time of the last succesfully sent message.
+ /// </summary>
+ public DateTime LastSentMessageTime { get; protected set; }
+
+ /// <summary>
+ /// Gets/sets wire protocol that the channel uses.
+ /// This property must set before first communication.
+ /// </summary>
+ public IScsWireProtocol WireProtocol { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ protected CommunicationChannelBase()
+ {
+ CommunicationState = CommunicationStates.Disconnected;
+ LastReceivedMessageTime = DateTime.MinValue;
+ LastSentMessageTime = DateTime.MinValue;
+ }
+
+ #endregion
+
+ #region Public abstract methods
+
+ /// <summary>
+ /// Disconnects from remote application and closes this channel.
+ /// </summary>
+ public abstract void Disconnect();
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts the communication with remote application.
+ /// </summary>
+ public void Start()
+ {
+ StartInternal();
+ CommunicationState = CommunicationStates.Connected;
+ }
+
+ /// <summary>
+ /// Sends a message to the remote application.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ /// <exception cref="ArgumentNullException">Throws ArgumentNullException if message is null</exception>
+ public void SendMessage(IScsMessage message)
+ {
+ if (message == null)
+ {
+ throw new ArgumentNullException("message");
+ }
+
+ SendMessageInternal(message);
+ }
+
+ #endregion
+
+ #region Protected abstract methods
+
+ /// <summary>
+ /// Starts the communication with remote application really.
+ /// </summary>
+ protected abstract void StartInternal();
+
+ /// <summary>
+ /// Sends a message to the remote application.
+ /// This method is overrided by derived classes to really send to message.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ protected abstract void SendMessageInternal(IScsMessage message);
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises Disconnected event.
+ /// </summary>
+ protected virtual void OnDisconnected()
+ {
+ var handler = Disconnected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageReceived event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageReceived(IScsMessage message)
+ {
+ var handler = MessageReceived;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageSent event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageSent(IScsMessage message)
+ {
+ var handler = MessageSent;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelEventArgs.cs b/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelEventArgs.cs
new file mode 100644
index 0000000..e40849c
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/CommunicationChannelEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Channels
+{
+ /// <summary>
+ /// Stores communication channel information to be used by an event.
+ /// </summary>
+ internal class CommunicationChannelEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Communication channel that is associated with this event.
+ /// </summary>
+ public ICommunicationChannel Channel { get; private set; }
+
+ /// <summary>
+ /// Creates a new CommunicationChannelEventArgs object.
+ /// </summary>
+ /// <param name="channel">Communication channel that is associated with this event</param>
+ public CommunicationChannelEventArgs(ICommunicationChannel channel)
+ {
+ Channel = channel;
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/ConnectionListenerBase.cs b/src/Scs/Communication/Scs/Communication/Channels/ConnectionListenerBase.cs
new file mode 100644
index 0000000..f630ce4
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/ConnectionListenerBase.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Channels
+{
+ /// <summary>
+ /// This class provides base functionality for communication listener classes.
+ /// </summary>
+ internal abstract class ConnectionListenerBase : IConnectionListener
+ {
+ /// <summary>
+ /// This event is raised when a new communication channel is connected.
+ /// </summary>
+ public event EventHandler<CommunicationChannelEventArgs> CommunicationChannelConnected;
+
+ /// <summary>
+ /// Starts listening incoming connections.
+ /// </summary>
+ public abstract void Start();
+
+ /// <summary>
+ /// Stops listening incoming connections.
+ /// </summary>
+ public abstract void Stop();
+
+ /// <summary>
+ /// Raises CommunicationChannelConnected event.
+ /// </summary>
+ /// <param name="client"></param>
+ protected virtual void OnCommunicationChannelConnected(ICommunicationChannel client)
+ {
+ var handler = CommunicationChannelConnected;
+ if (handler != null)
+ {
+ handler(this, new CommunicationChannelEventArgs(client));
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/ICommunicationChannel.cs b/src/Scs/Communication/Scs/Communication/Channels/ICommunicationChannel.cs
new file mode 100644
index 0000000..cf9e89c
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/ICommunicationChannel.cs
@@ -0,0 +1,38 @@
+using System;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace Hik.Communication.Scs.Communication.Channels
+{
+ /// <summary>
+ /// Represents a communication channel.
+ /// A communication channel is used to communicate (send/receive messages) with a remote application.
+ /// </summary>
+ internal interface ICommunicationChannel : IMessenger
+ {
+ /// <summary>
+ /// This event is raised when client disconnected from server.
+ /// </summary>
+ event EventHandler Disconnected;
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ ScsEndPoint RemoteEndPoint { get; }
+
+ /// <summary>
+ /// Gets the current communication state.
+ /// </summary>
+ CommunicationStates CommunicationState { get; }
+
+ /// <summary>
+ /// Starts the communication with remote application.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Closes messenger.
+ /// </summary>
+ void Disconnect();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/IConnectionListener.cs b/src/Scs/Communication/Scs/Communication/Channels/IConnectionListener.cs
new file mode 100644
index 0000000..2245941
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/IConnectionListener.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Channels
+{
+ /// <summary>
+ /// Represents a communication listener.
+ /// A connection listener is used to accept incoming client connection requests.
+ /// </summary>
+ internal interface IConnectionListener
+ {
+ /// <summary>
+ /// This event is raised when a new communication channel connected.
+ /// </summary>
+ event EventHandler<CommunicationChannelEventArgs> CommunicationChannelConnected;
+
+ /// <summary>
+ /// Starts listening incoming connections.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Stops listening incoming connections.
+ /// </summary>
+ void Stop();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpCommunicationChannel.cs b/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpCommunicationChannel.cs
new file mode 100644
index 0000000..0b3e310
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpCommunicationChannel.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.Scs.Communication.Channels.Tcp
+{
+ /// <summary>
+ /// This class is used to communicate with a remote application over TCP/IP protocol.
+ /// </summary>
+ internal class TcpCommunicationChannel : CommunicationChannelBase
+ {
+ #region Public properties
+
+ ///<summary>
+ /// Gets the endpoint of remote application.
+ ///</summary>
+ public override ScsEndPoint RemoteEndPoint
+ {
+ get
+ {
+ return _remoteEndPoint;
+ }
+ }
+ private readonly ScsTcpEndPoint _remoteEndPoint;
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Size of the buffer that is used to receive bytes from TCP socket.
+ /// </summary>
+ private const int ReceiveBufferSize = 4 * 1024; //4KB
+
+ /// <summary>
+ /// This buffer is used to receive bytes
+ /// </summary>
+ private readonly byte[] _buffer;
+
+ /// <summary>
+ /// Socket object to send/reveice messages.
+ /// </summary>
+ private readonly Socket _clientSocket;
+
+ /// <summary>
+ /// A flag to control thread's running
+ /// </summary>
+ private volatile bool _running;
+
+ /// <summary>
+ /// This object is just used for thread synchronizing (locking).
+ /// </summary>
+ private readonly object _syncLock;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new TcpCommunicationChannel object.
+ /// </summary>
+ /// <param name="clientSocket">A connected Socket object that is
+ /// used to communicate over network</param>
+ public TcpCommunicationChannel(Socket clientSocket)
+ {
+ _clientSocket = clientSocket;
+ _clientSocket.NoDelay = true;
+
+ var ipEndPoint = (IPEndPoint)_clientSocket.RemoteEndPoint;
+ _remoteEndPoint = new ScsTcpEndPoint(ipEndPoint.Address.ToString(), ipEndPoint.Port);
+
+ _buffer = new byte[ReceiveBufferSize];
+ _syncLock = new object();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Disconnects from remote application and closes channel.
+ /// </summary>
+ public override void Disconnect()
+ {
+ if (CommunicationState != CommunicationStates.Connected)
+ {
+ return;
+ }
+
+ _running = false;
+ try
+ {
+ if (_clientSocket.Connected)
+ {
+ _clientSocket.Close();
+ }
+
+ _clientSocket.Dispose();
+ }
+ catch
+ {
+
+ }
+
+ CommunicationState = CommunicationStates.Disconnected;
+ OnDisconnected();
+ }
+
+ #endregion
+
+ #region Protected methods
+
+ /// <summary>
+ /// Starts the thread to receive messages from socket.
+ /// </summary>
+ protected override void StartInternal()
+ {
+ _running = true;
+ _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, 0, new AsyncCallback(ReceiveCallback), null);
+ }
+
+ /// <summary>
+ /// Sends a message to the remote application.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ protected override void SendMessageInternal(IScsMessage message)
+ {
+ //Send message
+ var totalSent = 0;
+ lock (_syncLock)
+ {
+ //Create a byte array from message according to current protocol
+ var messageBytes = WireProtocol.GetBytes(message);
+ //Send all bytes to the remote application
+ while (totalSent < messageBytes.Length)
+ {
+ var sent = _clientSocket.Send(messageBytes, totalSent, messageBytes.Length - totalSent, SocketFlags.None);
+ if (sent <= 0)
+ {
+ throw new CommunicationException("Message could not be sent via TCP socket. Only " + totalSent + " bytes of " + messageBytes.Length + " bytes are sent.");
+ }
+
+ totalSent += sent;
+ }
+
+ LastSentMessageTime = DateTime.Now;
+ OnMessageSent(message);
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// This method is used as callback method in _clientSocket's BeginReceive method.
+ /// It reveives bytes from socker.
+ /// </summary>
+ /// <param name="ar">Asyncronous call result</param>
+ private void ReceiveCallback(IAsyncResult ar)
+ {
+ if(!_running)
+ {
+ return;
+ }
+
+ try
+ {
+ //Get received bytes count
+ var bytesRead = _clientSocket.EndReceive(ar);
+ if (bytesRead > 0)
+ {
+ LastReceivedMessageTime = DateTime.Now;
+
+ //Copy received bytes to a new byte array
+ var receivedBytes = new byte[bytesRead];
+ Array.Copy(_buffer, 0, receivedBytes, 0, bytesRead);
+
+ //Read messages according to current wire protocol
+ var messages = WireProtocol.CreateMessages(receivedBytes);
+
+ //Raise MessageReceived event for all received messages
+ foreach (var message in messages)
+ {
+ OnMessageReceived(message);
+ }
+ }
+ else
+ {
+ throw new CommunicationException("Tcp socket is closed");
+ }
+
+ //Read more bytes if still running
+ if (_running)
+ {
+ _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, 0, new AsyncCallback(ReceiveCallback), null);
+ }
+ }
+ catch
+ {
+ Disconnect();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpConnectionListener.cs b/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpConnectionListener.cs
new file mode 100644
index 0000000..773ff80
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Channels/Tcp/TcpConnectionListener.cs
@@ -0,0 +1,124 @@
+using System.Net.Sockets;
+using System.Threading;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+
+namespace Hik.Communication.Scs.Communication.Channels.Tcp
+{
+ /// <summary>
+ /// This class is used to listen and accept incoming TCP
+ /// connection requests on a TCP port.
+ /// </summary>
+ internal class TcpConnectionListener : ConnectionListenerBase
+ {
+ /// <summary>
+ /// The endpoint address of the server to listen incoming connections.
+ /// </summary>
+ private readonly ScsTcpEndPoint _endPoint;
+
+ /// <summary>
+ /// Server socket to listen incoming connection requests.
+ /// </summary>
+ private TcpListener _listenerSocket;
+
+ /// <summary>
+ /// The thread to listen socket
+ /// </summary>
+ private Thread _thread;
+
+ /// <summary>
+ /// A flag to control thread's running
+ /// </summary>
+ private volatile bool _running;
+
+ /// <summary>
+ /// Creates a new TcpConnectionListener for given endpoint.
+ /// </summary>
+ /// <param name="endPoint">The endpoint address of the server to listen incoming connections</param>
+ public TcpConnectionListener(ScsTcpEndPoint endPoint)
+ {
+ _endPoint = endPoint;
+ }
+
+ /// <summary>
+ /// Starts listening incoming connections.
+ /// </summary>
+ public override void Start()
+ {
+ StartSocket();
+ _running = true;
+ _thread = new Thread(DoListenAsThread);
+ _thread.Start();
+ }
+
+ /// <summary>
+ /// Stops listening incoming connections.
+ /// </summary>
+ public override void Stop()
+ {
+ _running = false;
+ StopSocket();
+ }
+
+ /// <summary>
+ /// Starts listening socket.
+ /// </summary>
+ private void StartSocket()
+ {
+ _listenerSocket = new TcpListener(System.Net.IPAddress.Any, _endPoint.TcpPort);
+ _listenerSocket.Start();
+ }
+
+ /// <summary>
+ /// Stops listening socket.
+ /// </summary>
+ private void StopSocket()
+ {
+ try
+ {
+ _listenerSocket.Stop();
+ }
+ catch
+ {
+
+ }
+ }
+
+ /// <summary>
+ /// Entrance point of the thread.
+ /// This method is used by the thread to listen incoming requests.
+ /// </summary>
+ private void DoListenAsThread()
+ {
+ while (_running)
+ {
+ try
+ {
+ var clientSocket = _listenerSocket.AcceptSocket();
+ if (clientSocket.Connected)
+ {
+ OnCommunicationChannelConnected(new TcpCommunicationChannel(clientSocket));
+ }
+ }
+ catch
+ {
+ //Disconnect, wait for a while and connect again.
+ StopSocket();
+ Thread.Sleep(1000);
+ if (!_running)
+ {
+ return;
+ }
+
+ try
+ {
+ StartSocket();
+ }
+ catch
+ {
+
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/CommunicationException.cs b/src/Scs/Communication/Scs/Communication/CommunicationException.cs
new file mode 100644
index 0000000..4a8c9c3
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/CommunicationException.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Hik.Communication.Scs.Communication
+{
+ /// <summary>
+ /// This application is thrown in a communication error.
+ /// </summary>
+ [Serializable]
+ public class CommunicationException : Exception
+ {
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public CommunicationException()
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor for serializing.
+ /// </summary>
+ public CommunicationException(SerializationInfo serializationInfo, StreamingContext context)
+ : base(serializationInfo, context)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ public CommunicationException(string message)
+ : base(message)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ /// <param name="innerException">Inner exception</param>
+ public CommunicationException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/CommunicationStateException.cs b/src/Scs/Communication/Scs/Communication/CommunicationStateException.cs
new file mode 100644
index 0000000..6501e6b
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/CommunicationStateException.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Hik.Communication.Scs.Communication
+{
+ /// <summary>
+ /// This application is thrown if communication is not expected state.
+ /// </summary>
+ [Serializable]
+ public class CommunicationStateException : CommunicationException
+ {
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public CommunicationStateException()
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor for serializing.
+ /// </summary>
+ public CommunicationStateException(SerializationInfo serializationInfo, StreamingContext context)
+ : base(serializationInfo, context)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ public CommunicationStateException(string message)
+ : base(message)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ /// <param name="innerException">Inner exception</param>
+ public CommunicationStateException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/CommunicationStates.cs b/src/Scs/Communication/Scs/Communication/CommunicationStates.cs
new file mode 100644
index 0000000..0e2da97
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/CommunicationStates.cs
@@ -0,0 +1,18 @@
+namespace Hik.Communication.Scs.Communication
+{
+ /// <summary>
+ /// Communication states.
+ /// </summary>
+ public enum CommunicationStates
+ {
+ /// <summary>
+ /// Connected.
+ /// </summary>
+ Connected,
+
+ /// <summary>
+ /// Disconnected.
+ /// </summary>
+ Disconnected
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/EndPoints/ScsEndPoint.cs b/src/Scs/Communication/Scs/Communication/EndPoints/ScsEndPoint.cs
new file mode 100644
index 0000000..f731a93
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/EndPoints/ScsEndPoint.cs
@@ -0,0 +1,67 @@
+using System;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+using Hik.Communication.Scs.Server;
+
+namespace Hik.Communication.Scs.Communication.EndPoints
+{
+ ///<summary>
+ /// Represents a server side end point in SCS.
+ ///</summary>
+ public abstract class ScsEndPoint
+ {
+ /// <summary>
+ /// Create a Scs End Point from a string.
+ /// Address must be formatted as: protocol://address
+ /// For example: tcp://89.43.104.179:10048 for a TCP endpoint with
+ /// IP 89.43.104.179 and port 10048.
+ /// </summary>
+ /// <param name="endPointAddress">Address to create endpoint</param>
+ /// <returns>Created end point</returns>
+ public static ScsEndPoint CreateEndPoint(string endPointAddress)
+ {
+ //Check if end point address is null
+ if (string.IsNullOrEmpty(endPointAddress))
+ {
+ throw new ArgumentNullException("endPointAddress");
+ }
+
+ //If not protocol specified, assume TCP.
+ var endPointAddr = endPointAddress;
+ if (!endPointAddr.Contains("://"))
+ {
+ endPointAddr = "tcp://" + endPointAddr;
+ }
+
+ //Split protocol and address parts
+ var splittedEndPoint = endPointAddr.Split(new[] { "://" }, StringSplitOptions.RemoveEmptyEntries);
+ if (splittedEndPoint.Length != 2)
+ {
+ throw new ApplicationException(endPointAddress + " is not a valid endpoint address.");
+ }
+
+ //Split end point, find protocol and address
+ var protocol = splittedEndPoint[0].Trim().ToLower();
+ var address = splittedEndPoint[1].Trim();
+ switch (protocol)
+ {
+ case "tcp":
+ return new ScsTcpEndPoint(address);
+ default:
+ throw new ApplicationException("Unsupported protocol " + protocol + " in end point " + endPointAddress);
+ }
+ }
+
+ /// <summary>
+ /// Creates a Scs Server that uses this end point to listen incoming connections.
+ /// </summary>
+ /// <returns>Scs Server</returns>
+ internal abstract IScsServer CreateServer();
+
+ /// <summary>
+ /// Creates a Scs Server that uses this end point to connect to server.
+ /// </summary>
+ /// <returns>Scs Client</returns>
+ internal abstract IScsClient CreateClient();
+ }
+} \ No newline at end of file
diff --git a/src/Scs/Communication/Scs/Communication/EndPoints/Tcp/ScsTcpEndPoint.cs b/src/Scs/Communication/Scs/Communication/EndPoints/Tcp/ScsTcpEndPoint.cs
new file mode 100644
index 0000000..df1bca8
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/EndPoints/Tcp/ScsTcpEndPoint.cs
@@ -0,0 +1,84 @@
+using System;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Client.Tcp;
+using Hik.Communication.Scs.Server;
+using Hik.Communication.Scs.Server.Tcp;
+
+namespace Hik.Communication.Scs.Communication.EndPoints.Tcp
+{
+ /// <summary>
+ /// Represens a TCP end point in SCS.
+ /// </summary>
+ public sealed class ScsTcpEndPoint : ScsEndPoint
+ {
+ ///<summary>
+ /// IP address of the server.
+ ///</summary>
+ public string IpAddress { get; set; }
+
+ ///<summary>
+ /// Listening TCP Port for incoming connection requests on server.
+ ///</summary>
+ public int TcpPort { get; private set; }
+
+ /// <summary>
+ /// Creates a new ScsTcpEndPoint object with specified port number.
+ /// </summary>
+ /// <param name="tcpPort">Listening TCP Port for incoming connection requests on server</param>
+ public ScsTcpEndPoint(int tcpPort)
+ {
+ TcpPort = tcpPort;
+ }
+
+ /// <summary>
+ /// Creates a new ScsTcpEndPoint object with specified IP address and port number.
+ /// </summary>
+ /// <param name="ipAddress">IP address of the server</param>
+ /// <param name="port">Listening TCP Port for incoming connection requests on server</param>
+ public ScsTcpEndPoint(string ipAddress, int port)
+ {
+ IpAddress = ipAddress;
+ TcpPort = port;
+ }
+
+ /// <summary>
+ /// Creates a new ScsTcpEndPoint from a string address.
+ /// Address format must be like IPAddress:Port (For example: 127.0.0.1:10085).
+ /// </summary>
+ /// <param name="address">TCP end point Address</param>
+ /// <returns>Created ScsTcpEndpoint object</returns>
+ public ScsTcpEndPoint(string address)
+ {
+ var splittedAddress = address.Trim().Split(':');
+ IpAddress = splittedAddress[0].Trim();
+ TcpPort = Convert.ToInt32(splittedAddress[1].Trim());
+ }
+
+ /// <summary>
+ /// Creates a Scs Server that uses this end point to listen incoming connections.
+ /// </summary>
+ /// <returns>Scs Server</returns>
+ internal override IScsServer CreateServer()
+ {
+ return new ScsTcpServer(this);
+ }
+
+ /// <summary>
+ /// Creates a Scs Client that uses this end point to connect to server.
+ /// </summary>
+ /// <returns>Scs Client</returns>
+ internal override IScsClient CreateClient()
+ {
+ return new ScsTcpClient(this);
+ }
+
+ /// <summary>
+ /// Generates a string representation of this end point object.
+ /// </summary>
+ /// <returns>String representation of this end point object</returns>
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(IpAddress) ? ("tcp://" + TcpPort) : ("tcp://" + IpAddress + ":" + TcpPort);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Scs/Communication/Scs/Communication/Messages/IScsMessage.cs b/src/Scs/Communication/Scs/Communication/Messages/IScsMessage.cs
new file mode 100644
index 0000000..5fd5ac3
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/IScsMessage.cs
@@ -0,0 +1,18 @@
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// Represents a message that is sent and received by server and client.
+ /// </summary>
+ public interface IScsMessage
+ {
+ /// <summary>
+ /// Unique identified for this message.
+ /// </summary>
+ string MessageId { get; }
+
+ /// <summary>
+ /// Unique identified for this message.
+ /// </summary>
+ string RepliedMessageId { get; set; }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messages/MessageEventArgs.cs b/src/Scs/Communication/Scs/Communication/Messages/MessageEventArgs.cs
new file mode 100644
index 0000000..dab8639
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/MessageEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// Stores message to be used by an event.
+ /// </summary>
+ public class MessageEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Message object that is associated with this event.
+ /// </summary>
+ public IScsMessage Message { get; private set; }
+
+ /// <summary>
+ /// Creates a new MessageEventArgs object.
+ /// </summary>
+ /// <param name="message">Message object that is associated with this event</param>
+ public MessageEventArgs(IScsMessage message)
+ {
+ Message = message;
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messages/PingMessage.cs b/src/Scs/Communication/Scs/Communication/Messages/PingMessage.cs
new file mode 100644
index 0000000..6f153ba
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/PingMessage.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// This message is used to send/receive ping messages.
+ /// Ping messages is used to keep connection alive between server and client.
+ /// </summary>
+ [Serializable]
+ public sealed class ScsPingMessage : ScsMessage
+ {
+ ///<summary>
+ /// Creates a new PingMessage object.
+ ///</summary>
+ public ScsPingMessage()
+ {
+
+ }
+
+ /// <summary>
+ /// Creates a new reply PingMessage object.
+ /// </summary>
+ /// <param name="repliedMessageId">
+ /// Replied message id if this is a reply for
+ /// a message.
+ /// </param>
+ public ScsPingMessage(string repliedMessageId)
+ : this()
+ {
+ RepliedMessageId = repliedMessageId;
+ }
+
+ /// <summary>
+ /// Creates a string to represents this object.
+ /// </summary>
+ /// <returns>A string to represents this object</returns>
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(RepliedMessageId)
+ ? string.Format("ScsPingMessage [{0}]", MessageId)
+ : string.Format("ScsPingMessage [{0}] Replied To [{1}]", MessageId, RepliedMessageId);
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messages/ScsMessage.cs b/src/Scs/Communication/Scs/Communication/Messages/ScsMessage.cs
new file mode 100644
index 0000000..240f149
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/ScsMessage.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// Represents a message that is sent and received by server and client.
+ /// This is the base class for all messages.
+ /// </summary>
+ [Serializable]
+ public class ScsMessage : IScsMessage
+ {
+ /// <summary>
+ /// Unique identified for this message.
+ /// Default value: New GUID.
+ /// Do not change if you do not want to do low level changes
+ /// such as custom wire protocols.
+ /// </summary>
+ public string MessageId { get; set; }
+
+ /// <summary>
+ /// This property is used to indicate that this is
+ /// a Reply message to a message.
+ /// It may be null if this is not a reply message.
+ /// </summary>
+ public string RepliedMessageId { get; set; }
+
+ /// <summary>
+ /// Creates a new ScsMessage.
+ /// </summary>
+ public ScsMessage()
+ {
+ MessageId = Guid.NewGuid().ToString();
+ }
+
+ /// <summary>
+ /// Creates a new reply ScsMessage.
+ /// </summary>
+ /// <param name="repliedMessageId">
+ /// Replied message id if this is a reply for
+ /// a message.
+ /// </param>
+ public ScsMessage(string repliedMessageId)
+ : this()
+ {
+ RepliedMessageId = repliedMessageId;
+ }
+
+ /// <summary>
+ /// Creates a string to represents this object.
+ /// </summary>
+ /// <returns>A string to represents this object</returns>
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(RepliedMessageId)
+ ? string.Format("ScsMessage [{0}]", MessageId)
+ : string.Format("ScsMessage [{0}] Replied To [{1}]", MessageId, RepliedMessageId);
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messages/ScsRawDataMessage.cs b/src/Scs/Communication/Scs/Communication/Messages/ScsRawDataMessage.cs
new file mode 100644
index 0000000..0382c55
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/ScsRawDataMessage.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// This message is used to send/receive a raw byte array as message data.
+ /// </summary>
+ [Serializable]
+ public class ScsRawDataMessage : ScsMessage
+ {
+ /// <summary>
+ /// Message data that is being transmitted.
+ /// </summary>
+ public byte[] MessageData { get; set; }
+
+ /// <summary>
+ /// Default empty constructor.
+ /// </summary>
+ public ScsRawDataMessage()
+ {
+
+ }
+
+ /// <summary>
+ /// Creates a new ScsRawDataMessage object with MessageData property.
+ /// </summary>
+ /// <param name="messageData">Message data that is being transmitted</param>
+ public ScsRawDataMessage(byte[] messageData)
+ {
+ MessageData = messageData;
+ }
+
+ /// <summary>
+ /// Creates a new reply ScsRawDataMessage object with MessageData property.
+ /// </summary>
+ /// <param name="messageData">Message data that is being transmitted</param>
+ /// <param name="repliedMessageId">
+ /// Replied message id if this is a reply for
+ /// a message.
+ /// </param>
+ public ScsRawDataMessage(byte[] messageData, string repliedMessageId)
+ : this(messageData)
+ {
+ RepliedMessageId = repliedMessageId;
+ }
+
+ /// <summary>
+ /// Creates a string to represents this object.
+ /// </summary>
+ /// <returns>A string to represents this object</returns>
+ public override string ToString()
+ {
+ var messageLength = MessageData == null ? 0 : MessageData.Length;
+ return string.IsNullOrEmpty(RepliedMessageId)
+ ? string.Format("ScsRawDataMessage [{0}]: {1} bytes", MessageId, messageLength)
+ : string.Format("ScsRawDataMessage [{0}] Replied To [{1}]: {2} bytes", MessageId, RepliedMessageId, messageLength);
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messages/ScsTextMessage.cs b/src/Scs/Communication/Scs/Communication/Messages/ScsTextMessage.cs
new file mode 100644
index 0000000..b5665fa
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messages/ScsTextMessage.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace Hik.Communication.Scs.Communication.Messages
+{
+ /// <summary>
+ /// This message is used to send/receive a text as message data.
+ /// </summary>
+ [Serializable]
+ public class ScsTextMessage : ScsMessage
+ {
+ /// <summary>
+ /// Message text that is being transmitted.
+ /// </summary>
+ public string Text { get; set; }
+
+ /// <summary>
+ /// Creates a new ScsTextMessage object.
+ /// </summary>
+ public ScsTextMessage()
+ {
+
+ }
+
+ /// <summary>
+ /// Creates a new ScsTextMessage object with Text property.
+ /// </summary>
+ /// <param name="text">Message text that is being transmitted</param>
+ public ScsTextMessage(string text)
+ {
+ Text = text;
+ }
+
+ /// <summary>
+ /// Creates a new reply ScsTextMessage object with Text property.
+ /// </summary>
+ /// <param name="text">Message text that is being transmitted</param>
+ /// <param name="repliedMessageId">
+ /// Replied message id if this is a reply for
+ /// a message.
+ /// </param>
+ public ScsTextMessage(string text, string repliedMessageId)
+ : this(text)
+ {
+ RepliedMessageId = repliedMessageId;
+ }
+
+ /// <summary>
+ /// Creates a string to represents this object.
+ /// </summary>
+ /// <returns>A string to represents this object</returns>
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(RepliedMessageId)
+ ? string.Format("ScsTextMessage [{0}]: {1}", MessageId, Text)
+ : string.Format("ScsTextMessage [{0}] Replied To [{1}]: {2}", MessageId, RepliedMessageId, Text);
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messengers/IMessenger.cs b/src/Scs/Communication/Scs/Communication/Messengers/IMessenger.cs
new file mode 100644
index 0000000..176b479
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messengers/IMessenger.cs
@@ -0,0 +1,44 @@
+using System;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace Hik.Communication.Scs.Communication.Messengers
+{
+ /// <summary>
+ /// Represents an object that can send and receive messages.
+ /// </summary>
+ public interface IMessenger
+ {
+ /// <summary>
+ /// This event is raised when a new message is received.
+ /// </summary>
+ event EventHandler<MessageEventArgs> MessageReceived;
+
+ /// <summary>
+ /// This event is raised when a new message is sent without any error.
+ /// It does not guaranties that message is properly handled and processed by remote application.
+ /// </summary>
+ event EventHandler<MessageEventArgs> MessageSent;
+
+ /// <summary>
+ /// Gets/sets wire protocol that is used while reading and writing messages.
+ /// </summary>
+ IScsWireProtocol WireProtocol { get; set; }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ DateTime LastReceivedMessageTime { get; }
+
+ /// <summary>
+ /// Gets the time of the last succesfully sent message.
+ /// </summary>
+ DateTime LastSentMessageTime { get; }
+
+ /// <summary>
+ /// Sends a message to the remote application.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ void SendMessage(IScsMessage message);
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messengers/RequestReplyMessenger.cs b/src/Scs/Communication/Scs/Communication/Messengers/RequestReplyMessenger.cs
new file mode 100644
index 0000000..f346c9e
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messengers/RequestReplyMessenger.cs
@@ -0,0 +1,387 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Protocols;
+using Hik.Threading;
+
+namespace Hik.Communication.Scs.Communication.Messengers
+{
+ /// <summary>
+ /// This class adds SendMessageAndWaitForResponse(...) and SendAndReceiveMessage methods
+ /// to a IMessenger for synchronous request/response style messaging.
+ /// It also adds queued processing of incoming messages.
+ /// </summary>
+ /// <typeparam name="T">Type of IMessenger object to use as underlying communication</typeparam>
+ public class RequestReplyMessenger<T> : IMessenger, IDisposable where T : IMessenger
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new message is received from underlying messenger.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageReceived;
+
+ /// <summary>
+ /// This event is raised when a new message is sent without any error.
+ /// It does not guaranties that message is properly handled and processed by remote application.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageSent;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Gets/sets wire protocol that is used while reading and writing messages.
+ /// </summary>
+ public IScsWireProtocol WireProtocol
+ {
+ get { return Messenger.WireProtocol; }
+ set { Messenger.WireProtocol = value; }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastReceivedMessageTime
+ {
+ get
+ {
+ return Messenger.LastReceivedMessageTime;
+ }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastSentMessageTime
+ {
+ get
+ {
+ return Messenger.LastSentMessageTime;
+ }
+ }
+
+ /// <summary>
+ /// Gets the underlying IMessenger object.
+ /// </summary>
+ public T Messenger { get; private set; }
+
+ /// <summary>
+ /// Timeout value as milliseconds to wait for a receiving message on
+ /// SendMessageAndWaitForResponse and SendAndReceiveMessage methods.
+ /// Default value: 60000 (1 minute).
+ /// </summary>
+ public int Timeout { get; set; }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Default Timeout value.
+ /// </summary>
+ private const int DefaultTimeout = 60000;
+
+ /// <summary>
+ /// This messages are waiting for a response those are used when
+ /// SendMessageAndWaitForResponse is called.
+ /// Key: MessageID of waiting request message.
+ /// Value: A WaitingMessage instance.
+ /// </summary>
+ private readonly SortedList<string, WaitingMessage> _waitingMessages;
+
+ /// <summary>
+ /// This object is used to process incoming messages sequentially.
+ /// </summary>
+ private readonly SequentialItemProcessor<IScsMessage> _incomingMessageProcessor;
+
+ /// <summary>
+ /// This object is used for thread synchronization.
+ /// </summary>
+ private readonly object _syncObj = new object();
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new RequestReplyMessenger.
+ /// </summary>
+ /// <param name="messenger">IMessenger object to use as underlying communication</param>
+ public RequestReplyMessenger(T messenger)
+ {
+ Messenger = messenger;
+ messenger.MessageReceived += Messenger_MessageReceived;
+ messenger.MessageSent += Messenger_MessageSent;
+ _incomingMessageProcessor = new SequentialItemProcessor<IScsMessage>(OnMessageReceived);
+ _waitingMessages = new SortedList<string, WaitingMessage>();
+ Timeout = DefaultTimeout;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts the messenger.
+ /// </summary>
+ public virtual void Start()
+ {
+ _incomingMessageProcessor.Start();
+ }
+
+ /// <summary>
+ /// Stops the messenger.
+ /// Cancels all waiting threads in SendMessageAndWaitForResponse method and stops message queue.
+ /// SendMessageAndWaitForResponse method throws exception if there is a thread that is waiting for response message.
+ /// Also stops incoming message processing and deletes all messages in incoming message queue.
+ /// </summary>
+ public virtual void Stop()
+ {
+ _incomingMessageProcessor.Stop();
+
+ //Pulse waiting threads for incoming messages, since underlying messenger is disconnected
+ //and can not receive messages anymore.
+ lock (_syncObj)
+ {
+ foreach (var waitingMessage in _waitingMessages.Values)
+ {
+ waitingMessage.State = WaitingMessageStates.Cancelled;
+ waitingMessage.WaitEvent.Set();
+ }
+
+ _waitingMessages.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Calls Stop method of this object.
+ /// </summary>
+ public void Dispose()
+ {
+ Stop();
+ }
+
+ /// <summary>
+ /// Sends a message.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ public void SendMessage(IScsMessage message)
+ {
+ Messenger.SendMessage(message);
+ }
+
+ /// <summary>
+ /// Sends a message and waits a response for that message.
+ /// </summary>
+ /// <remarks>
+ /// Response message is matched with RepliedMessageId property, so if
+ /// any other message (that is not reply for sent message) is received
+ /// from remote application, it is not considered as a reply and is not
+ /// returned as return value of this method.
+ ///
+ /// MessageReceived event is not raised for response messages.
+ /// </remarks>
+ /// <param name="message">message to send</param>
+ /// <returns>Response message</returns>
+ public IScsMessage SendMessageAndWaitForResponse(IScsMessage message)
+ {
+ return SendMessageAndWaitForResponse(message, Timeout);
+ }
+
+ /// <summary>
+ /// Sends a message and waits a response for that message.
+ /// </summary>
+ /// <remarks>
+ /// Response message is matched with RepliedMessageId property, so if
+ /// any other message (that is not reply for sent message) is received
+ /// from remote application, it is not considered as a reply and is not
+ /// returned as return value of this method.
+ ///
+ /// MessageReceived event is not raised for response messages.
+ /// </remarks>
+ /// <param name="message">message to send</param>
+ /// <param name="timeoutMilliseconds">Timeout duration as milliseconds.</param>
+ /// <returns>Response message</returns>
+ /// <exception cref="TimeoutException">Throws TimeoutException if can not receive reply message in timeout value</exception>
+ /// <exception cref="CommunicationException">Throws CommunicationException if communication fails before reply message.</exception>
+ public IScsMessage SendMessageAndWaitForResponse(IScsMessage message, int timeoutMilliseconds)
+ {
+ //Create a waiting message record and add to list
+ var waitingMessage = new WaitingMessage();
+ lock (_syncObj)
+ {
+ _waitingMessages[message.MessageId] = waitingMessage;
+ }
+
+ try
+ {
+ //Send message
+ Messenger.SendMessage(message);
+
+ //Wait for response
+ waitingMessage.WaitEvent.Wait(timeoutMilliseconds);
+
+ //Check for exceptions
+ switch (waitingMessage.State)
+ {
+ case WaitingMessageStates.WaitingForResponse:
+ throw new TimeoutException("Timeout occured. Can not received response.");
+ case WaitingMessageStates.Cancelled:
+ throw new CommunicationException("Disconnected before response received.");
+ }
+
+ //return response message
+ return waitingMessage.ResponseMessage;
+ }
+ finally
+ {
+ //Remove message from waiting messages
+ lock (_syncObj)
+ {
+ if (_waitingMessages.ContainsKey(message.MessageId))
+ {
+ _waitingMessages.Remove(message.MessageId);
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles MessageReceived event of Messenger object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Messenger_MessageReceived(object sender, MessageEventArgs e)
+ {
+ //Check if there is a waiting thread for this message in SendMessageAndWaitForResponse method
+ if (!string.IsNullOrEmpty(e.Message.RepliedMessageId))
+ {
+ WaitingMessage waitingMessage = null;
+ lock (_syncObj)
+ {
+ if (_waitingMessages.ContainsKey(e.Message.RepliedMessageId))
+ {
+ waitingMessage = _waitingMessages[e.Message.RepliedMessageId];
+ }
+ }
+
+ //If there is a thread waiting for this response message, pulse it
+ if (waitingMessage != null)
+ {
+ waitingMessage.ResponseMessage = e.Message;
+ waitingMessage.State = WaitingMessageStates.ResponseReceived;
+ waitingMessage.WaitEvent.Set();
+ return;
+ }
+ }
+
+ _incomingMessageProcessor.EnqueueMessage(e.Message);
+ }
+
+ /// <summary>
+ /// Handles MessageSent event of Messenger object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Messenger_MessageSent(object sender, MessageEventArgs e)
+ {
+ OnMessageSent(e.Message);
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises MessageReceived event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageReceived(IScsMessage message)
+ {
+ var handler = MessageReceived;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageSent event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageSent(IScsMessage message)
+ {
+ var handler = MessageSent;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ #endregion
+
+ #region WaitingMessage class
+
+ /// <summary>
+ /// This class is used to store messaging context for a request message
+ /// until response is received.
+ /// </summary>
+ private sealed class WaitingMessage
+ {
+ /// <summary>
+ /// Response message for request message
+ /// (null if response is not received yet).
+ /// </summary>
+ public IScsMessage ResponseMessage { get; set; }
+
+ /// <summary>
+ /// ManualResetEvent to block thread until response is received.
+ /// </summary>
+ public ManualResetEventSlim WaitEvent { get; private set; }
+
+ /// <summary>
+ /// State of the request message.
+ /// </summary>
+ public WaitingMessageStates State { get; set; }
+
+ /// <summary>
+ /// Creates a new WaitingMessage object.
+ /// </summary>
+ public WaitingMessage()
+ {
+ WaitEvent = new ManualResetEventSlim(false);
+ State = WaitingMessageStates.WaitingForResponse;
+ }
+ }
+
+ /// <summary>
+ /// This enum is used to store the state of a waiting message.
+ /// </summary>
+ private enum WaitingMessageStates
+ {
+ /// <summary>
+ /// Still waiting for response.
+ /// </summary>
+ WaitingForResponse,
+
+ /// <summary>
+ /// Message sending is cancelled.
+ /// </summary>
+ Cancelled,
+
+ /// <summary>
+ /// Response is properly received.
+ /// </summary>
+ ResponseReceived
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Messengers/SynchronizedMessenger.cs b/src/Scs/Communication/Scs/Communication/Messengers/SynchronizedMessenger.cs
new file mode 100644
index 0000000..065cfd4
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Messengers/SynchronizedMessenger.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.Scs.Communication.Messengers
+{
+ /// <summary>
+ /// This class is a wrapper for IMessenger and is used
+ /// to synchronize message receiving operation.
+ /// It extends RequestReplyMessenger.
+ /// It is suitable to use in applications those want to receive
+ /// messages by synchronized method calls instead of asynchronous
+ /// MessageReceived event.
+ /// </summary>
+ public class SynchronizedMessenger<T> : RequestReplyMessenger<T> where T : IMessenger
+ {
+ #region Public properties
+
+ ///<summary>
+ /// Gets/sets capacity of the incoming message queue.
+ /// No message is received from remote application if
+ /// number of messages in internal queue exceeds this value.
+ /// Default value: int.MaxValue (2147483647).
+ ///</summary>
+ public int IncomingMessageQueueCapacity { get; set; }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// A queue that is used to store receiving messages until Receive(...)
+ /// method is called to get them.
+ /// </summary>
+ private readonly Queue<IScsMessage> _receivingMessageQueue;
+
+ /// <summary>
+ /// This object is used to synchronize/wait threads.
+ /// </summary>
+ private readonly ManualResetEventSlim _receiveWaiter;
+
+ /// <summary>
+ /// This boolean value indicates the running state of this class.
+ /// </summary>
+ private volatile bool _running;
+
+ #endregion
+
+ #region Constructors
+
+ ///<summary>
+ /// Creates a new SynchronizedMessenger object.
+ ///</summary>
+ ///<param name="messenger">A IMessenger object to be used to send/receive messages</param>
+ public SynchronizedMessenger(T messenger)
+ : this(messenger, int.MaxValue)
+ {
+
+ }
+
+ ///<summary>
+ /// Creates a new SynchronizedMessenger object.
+ ///</summary>
+ ///<param name="messenger">A IMessenger object to be used to send/receive messages</param>
+ ///<param name="incomingMessageQueueCapacity">capacity of the incoming message queue</param>
+ public SynchronizedMessenger(T messenger, int incomingMessageQueueCapacity)
+ : base(messenger)
+ {
+ _receiveWaiter = new ManualResetEventSlim();
+ _receivingMessageQueue = new Queue<IScsMessage>();
+ IncomingMessageQueueCapacity = incomingMessageQueueCapacity;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts the messenger.
+ /// </summary>
+ public override void Start()
+ {
+ lock (_receivingMessageQueue)
+ {
+ _running = true;
+ }
+
+ base.Start();
+ }
+
+ /// <summary>
+ /// Stops the messenger.
+ /// </summary>
+ public override void Stop()
+ {
+ base.Stop();
+
+ lock (_receivingMessageQueue)
+ {
+ _running = false;
+ _receiveWaiter.Set();
+ }
+ }
+
+ /// <summary>
+ /// This method is used to receive a message from remote application.
+ /// It waits until a message is received.
+ /// </summary>
+ /// <returns>Received message</returns>
+ public IScsMessage ReceiveMessage()
+ {
+ return ReceiveMessage(System.Threading.Timeout.Infinite);
+ }
+
+ /// <summary>
+ /// This method is used to receive a message from remote application.
+ /// It waits until a message is received or timeout occurs.
+ /// </summary>
+ /// <param name="timeout">
+ /// Timeout value to wait if no message is received.
+ /// Use -1 to wait indefinitely.
+ /// </param>
+ /// <returns>Received message</returns>
+ /// <exception cref="TimeoutException">Throws TimeoutException if timeout occurs</exception>
+ /// <exception cref="Exception">Throws Exception if SynchronizedMessenger stops before a message is received</exception>
+ public IScsMessage ReceiveMessage(int timeout)
+ {
+ while (_running)
+ {
+ lock (_receivingMessageQueue)
+ {
+ //Check if SynchronizedMessenger is running
+ if (!_running)
+ {
+ throw new Exception("SynchronizedMessenger is stopped. Can not receive message.");
+ }
+
+ //Get a message immediately if any message does exists
+ if (_receivingMessageQueue.Count > 0)
+ {
+ return _receivingMessageQueue.Dequeue();
+ }
+
+ _receiveWaiter.Reset();
+ }
+
+ //Wait for a message
+ var signalled = _receiveWaiter.Wait(timeout);
+
+ //If not signalled, throw exception
+ if (!signalled)
+ {
+ throw new TimeoutException("Timeout occured. Can not received any message");
+ }
+ }
+
+ throw new Exception("SynchronizedMessenger is stopped. Can not receive message.");
+ }
+
+ /// <summary>
+ /// This method is used to receive a specific type of message from remote application.
+ /// It waits until a message is received.
+ /// </summary>
+ /// <returns>Received message</returns>
+ public TMessage ReceiveMessage<TMessage>() where TMessage : IScsMessage
+ {
+ return ReceiveMessage<TMessage>(System.Threading.Timeout.Infinite);
+ }
+
+ /// <summary>
+ /// This method is used to receive a specific type of message from remote application.
+ /// It waits until a message is received or timeout occurs.
+ /// </summary>
+ /// <param name="timeout">
+ /// Timeout value to wait if no message is received.
+ /// Use -1 to wait indefinitely.
+ /// </param>
+ /// <returns>Received message</returns>
+ public TMessage ReceiveMessage<TMessage>(int timeout) where TMessage : IScsMessage
+ {
+ var receivedMessage = ReceiveMessage(timeout);
+ if (!(receivedMessage is TMessage))
+ {
+ throw new Exception("Unexpected message received." +
+ " Expected type: " + typeof(TMessage).Name +
+ ". Received message type: " + receivedMessage.GetType().Name);
+ }
+
+ return (TMessage)receivedMessage;
+ }
+
+ #endregion
+
+ #region Protected methods
+
+ /// <summary>
+ /// Overrides
+ /// </summary>
+ /// <param name="message"></param>
+ protected override void OnMessageReceived(IScsMessage message)
+ {
+ lock (_receivingMessageQueue)
+ {
+ if (_receivingMessageQueue.Count < IncomingMessageQueueCapacity)
+ {
+ _receivingMessageQueue.Enqueue(message);
+ }
+
+ _receiveWaiter.Set();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocol.cs b/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocol.cs
new file mode 100644
index 0000000..a84784b
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocol.cs
@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.Scs.Communication.Protocols.BinarySerialization
+{
+ /// <summary>
+ /// Default communication protocol between server and clients to send and receive a message.
+ /// It uses .NET binary serialization to write and read messages.
+ ///
+ /// A Message format:
+ /// [Message Length (4 bytes)][Serialized Message Content]
+ ///
+ /// If a message is serialized to byte array as N bytes, this protocol
+ /// adds 4 bytes size information to head of the message bytes, so total length is (4 + N) bytes.
+ ///
+ /// This class can be derived to change serializer (default: BinaryFormatter). To do this,
+ /// SerializeMessage and DeserializeMessage methods must be overrided.
+ /// </summary>
+ public class BinarySerializationProtocol : IScsWireProtocol
+ {
+ #region Private fields
+
+ /// <summary>
+ /// Maximum length of a message.
+ /// </summary>
+ private const int MaxMessageLength = 128 * 1024 * 1024; //128 Megabytes.
+
+ /// <summary>
+ /// This MemoryStream object is used to collect receiving bytes to build messages.
+ /// </summary>
+ private MemoryStream _receiveMemoryStream;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new instance of BinarySerializationProtocol.
+ /// </summary>
+ public BinarySerializationProtocol()
+ {
+ _receiveMemoryStream = new MemoryStream();
+ }
+
+ #endregion
+
+ #region IScsWireProtocol implementation
+
+ /// <summary>
+ /// Serializes a message to a byte array to send to remote application.
+ /// This method is synchronized. So, only one thread can call it concurrently.
+ /// </summary>
+ /// <param name="message">Message to be serialized</param>
+ /// <exception cref="CommunicationException">Throws CommunicationException if message is bigger than maximum allowed message length.</exception>
+ public byte[] GetBytes(IScsMessage message)
+ {
+ //Serialize the message to a byte array
+ var serializedMessage = SerializeMessage(message);
+
+ //Check for message length
+ var messageLength = serializedMessage.Length;
+ if (messageLength > MaxMessageLength)
+ {
+ throw new CommunicationException("Message is too big (" + messageLength + " bytes). Max allowed length is " + MaxMessageLength + " bytes.");
+ }
+
+ //Create a byte array including the length of the message (4 bytes) and serialized message content
+ var bytes = new byte[messageLength + 4];
+ WriteInt32(bytes, 0, messageLength);
+ Array.Copy(serializedMessage, 0, bytes, 4, messageLength);
+
+ //Return serialized message by this protocol
+ return bytes;
+ }
+
+ /// <summary>
+ /// Builds messages from a byte array that is received from remote application.
+ /// The Byte array may contain just a part of a message, the protocol must
+ /// cumulate bytes to build messages.
+ /// This method is synchronized. So, only one thread can call it concurrently.
+ /// </summary>
+ /// <param name="receivedBytes">Received bytes from remote application</param>
+ /// <returns>
+ /// List of messages.
+ /// Protocol can generate more than one message from a byte array.
+ /// Also, if received bytes are not sufficient to build a message, the protocol
+ /// may return an empty list (and save bytes to combine with next method call).
+ /// </returns>
+ public IEnumerable<IScsMessage> CreateMessages(byte[] receivedBytes)
+ {
+ //Write all received bytes to the _receiveMemoryStream
+ _receiveMemoryStream.Write(receivedBytes, 0, receivedBytes.Length);
+ //Create a list to collect messages
+ var messages = new List<IScsMessage>();
+ //Read all available messages and add to messages collection
+ while (ReadSingleMessage(messages)) { }
+ //Return message list
+ return messages;
+ }
+
+ /// <summary>
+ /// This method is called when connection with remote application is reset (connection is renewing or first connecting).
+ /// So, wire protocol must reset itself.
+ /// </summary>
+ public void Reset()
+ {
+ if (_receiveMemoryStream.Length > 0)
+ {
+ _receiveMemoryStream = new MemoryStream();
+ }
+ }
+
+ #endregion
+
+ #region Proptected virtual methods
+
+ /// <summary>
+ /// This method is used to serialize a IScsMessage to a byte array.
+ /// This method can be overrided by derived classes to change serialization strategy.
+ /// It is a couple with DeserializeMessage method and must be overrided together.
+ /// </summary>
+ /// <param name="message">Message to be serialized</param>
+ /// <returns>
+ /// Serialized message bytes.
+ /// Does not include length of the message.
+ /// </returns>
+ protected virtual byte[] SerializeMessage(IScsMessage message)
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ new BinaryFormatter().Serialize(memoryStream, message);
+ return memoryStream.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// This method is used to deserialize a IScsMessage from it's bytes.
+ /// This method can be overrided by derived classes to change deserialization strategy.
+ /// It is a couple with SerializeMessage method and must be overrided together.
+ /// </summary>
+ /// <param name="bytes">
+ /// Bytes of message to be deserialized (does not include message length. It consist
+ /// of a single whole message)
+ /// </param>
+ /// <returns>Deserialized message</returns>
+ protected virtual IScsMessage DeserializeMessage(byte[] bytes)
+ {
+ //Create a MemoryStream to convert bytes to a stream
+ using (var deserializeMemoryStream = new MemoryStream(bytes))
+ {
+ //Go to head of the stream
+ deserializeMemoryStream.Position = 0;
+
+ //Deserialize the message
+ var binaryFormatter = new BinaryFormatter
+ {
+ AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
+ Binder = new DeserializationAppDomainBinder()
+ };
+
+ //Return the deserialized message
+ return (IScsMessage) binaryFormatter.Deserialize(deserializeMemoryStream);
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// This method tries to read a single message and add to the messages collection.
+ /// </summary>
+ /// <param name="messages">Messages collection to collect messages</param>
+ /// <returns>
+ /// Returns a boolean value indicates that if there is a need to re-call this method.
+ /// </returns>
+ /// <exception cref="CommunicationException">Throws CommunicationException if message is bigger than maximum allowed message length.</exception>
+ private bool ReadSingleMessage(ICollection<IScsMessage> messages)
+ {
+ //Go to the begining of the stream
+ _receiveMemoryStream.Position = 0;
+
+ //If stream has less than 4 bytes, that means we can not even read length of the message
+ //So, return false to wait more bytes from remore application.
+ if (_receiveMemoryStream.Length < 4)
+ {
+ return false;
+ }
+
+ //Read length of the message
+ var messageLength = ReadInt32(_receiveMemoryStream);
+ if (messageLength > MaxMessageLength)
+ {
+ throw new Exception("Message is too big (" + messageLength + " bytes). Max allowed length is " + MaxMessageLength + " bytes.");
+ }
+
+ //If message is zero-length (It must not be but good approach to check it)
+ if (messageLength == 0)
+ {
+ //if no more bytes, return immediately
+ if (_receiveMemoryStream.Length == 4)
+ {
+ _receiveMemoryStream = new MemoryStream(); //Clear the stream
+ return false;
+ }
+
+ //Create a new memory stream from current except first 4-bytes.
+ var bytes = _receiveMemoryStream.ToArray();
+ _receiveMemoryStream = new MemoryStream();
+ _receiveMemoryStream.Write(bytes, 4, bytes.Length - 4);
+ return true;
+ }
+
+ //If all bytes of the message is not received yet, return to wait more bytes
+ if (_receiveMemoryStream.Length < (4 + messageLength))
+ {
+ _receiveMemoryStream.Position = _receiveMemoryStream.Length;
+ return false;
+ }
+
+ //Read bytes of serialized message and deserialize it
+ var serializedMessageBytes = ReadByteArray(_receiveMemoryStream, messageLength);
+ messages.Add(DeserializeMessage(serializedMessageBytes));
+
+ //Read remaining bytes to an array
+ var remainingBytes = ReadByteArray(_receiveMemoryStream, (int)(_receiveMemoryStream.Length - (4 + messageLength)));
+
+ //Re-create the receive memory stream and write remaining bytes
+ _receiveMemoryStream = new MemoryStream();
+ _receiveMemoryStream.Write(remainingBytes, 0, remainingBytes.Length);
+
+ //Return true to re-call this method to try to read next message
+ return (remainingBytes.Length > 4);
+ }
+
+ /// <summary>
+ /// Writes a int value to a byte array from a starting index.
+ /// </summary>
+ /// <param name="buffer">Byte array to write int value</param>
+ /// <param name="startIndex">Start index of byte array to write</param>
+ /// <param name="number">An integer value to write</param>
+ private static void WriteInt32(byte[] buffer, int startIndex, int number)
+ {
+ buffer[startIndex] = (byte)((number >> 24) & 0xFF);
+ buffer[startIndex + 1] = (byte)((number >> 16) & 0xFF);
+ buffer[startIndex + 2] = (byte)((number >> 8) & 0xFF);
+ buffer[startIndex + 3] = (byte)((number) & 0xFF);
+ }
+
+ /// <summary>
+ /// Deserializes and returns a serialized integer.
+ /// </summary>
+ /// <returns>Deserialized integer</returns>
+ private static int ReadInt32(Stream stream)
+ {
+ var buffer = ReadByteArray(stream, 4);
+ return ((buffer[0] << 24) |
+ (buffer[1] << 16) |
+ (buffer[2] << 8) |
+ (buffer[3])
+ );
+ }
+
+ /// <summary>
+ /// Reads a byte array with specified length.
+ /// </summary>
+ /// <param name="stream">Stream to read from</param>
+ /// <param name="length">Length of the byte array to read</param>
+ /// <returns>Read byte array</returns>
+ /// <exception cref="EndOfStreamException">Throws EndOfStreamException if can not read from stream.</exception>
+ private static byte[] ReadByteArray(Stream stream, int length)
+ {
+ var buffer = new byte[length];
+ var totalRead = 0;
+ while (totalRead < length)
+ {
+ var read = stream.Read(buffer, totalRead, length - totalRead);
+ if (read <= 0)
+ {
+ throw new EndOfStreamException("Can not read from stream! Input stream is closed.");
+ }
+
+ totalRead += read;
+ }
+
+ return buffer;
+ }
+
+ #endregion
+
+ #region Nested classes
+
+ /// <summary>
+ /// This class is used in deserializing to allow deserializing objects that are defined
+ /// in assemlies that are load in runtime (like PlugIns).
+ /// </summary>
+ protected sealed class DeserializationAppDomainBinder : SerializationBinder
+ {
+ public override Type BindToType(string assemblyName, string typeName)
+ {
+ var toAssemblyName = assemblyName.Split(',')[0];
+ return (from assembly in AppDomain.CurrentDomain.GetAssemblies()
+ where assembly.FullName.Split(',')[0] == toAssemblyName
+ select assembly.GetType(typeName)).FirstOrDefault();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocolFactory.cs b/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocolFactory.cs
new file mode 100644
index 0000000..ded08ae
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Protocols/BinarySerialization/BinarySerializationProtocolFactory.cs
@@ -0,0 +1,17 @@
+namespace Hik.Communication.Scs.Communication.Protocols.BinarySerialization
+{
+ /// <summary>
+ /// This class is used to create Binary Serialization Protocol objects.
+ /// </summary>
+ public class BinarySerializationProtocolFactory : IScsWireProtocolFactory
+ {
+ /// <summary>
+ /// Creates a new Wire Protocol object.
+ /// </summary>
+ /// <returns>Newly created wire protocol object</returns>
+ public IScsWireProtocol CreateWireProtocol()
+ {
+ return new BinarySerializationProtocol();
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocol.cs b/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocol.cs
new file mode 100644
index 0000000..0ea3fb6
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocol.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.Scs.Communication.Protocols
+{
+ /// <summary>
+ /// Represents a byte-level communication protocol between applications.
+ /// </summary>
+ public interface IScsWireProtocol
+ {
+ /// <summary>
+ /// Serializes a message to a byte array to send to remote application.
+ /// This method is synchronized. So, only one thread can call it concurrently.
+ /// </summary>
+ /// <param name="message">Message to be serialized</param>
+ byte[] GetBytes(IScsMessage message);
+
+ /// <summary>
+ /// Builds messages from a byte array that is received from remote application.
+ /// The Byte array may contain just a part of a message, the protocol must
+ /// cumulate bytes to build messages.
+ /// This method is synchronized. So, only one thread can call it concurrently.
+ /// </summary>
+ /// <param name="receivedBytes">Received bytes from remote application</param>
+ /// <returns>
+ /// List of messages.
+ /// Protocol can generate more than one message from a byte array.
+ /// Also, if received bytes are not sufficient to build a message, the protocol
+ /// may return an empty list (and save bytes to combine with next method call).
+ /// </returns>
+ IEnumerable<IScsMessage> CreateMessages(byte[] receivedBytes);
+
+ /// <summary>
+ /// This method is called when connection with remote application is reset (connection is renewing or first connecting).
+ /// So, wire protocol must reset itself.
+ /// </summary>
+ void Reset();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocolFactory.cs b/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocolFactory.cs
new file mode 100644
index 0000000..3cc2489
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Protocols/IScsWireProtocolFactory.cs
@@ -0,0 +1,14 @@
+namespace Hik.Communication.Scs.Communication.Protocols
+{
+ ///<summary>
+ /// Defines a Wire Protocol Factory class that is used to create Wire Protocol objects.
+ ///</summary>
+ public interface IScsWireProtocolFactory
+ {
+ /// <summary>
+ /// Creates a new Wire Protocol object.
+ /// </summary>
+ /// <returns>Newly created wire protocol object</returns>
+ IScsWireProtocol CreateWireProtocol();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Communication/Protocols/WireProtocolManager.cs b/src/Scs/Communication/Scs/Communication/Protocols/WireProtocolManager.cs
new file mode 100644
index 0000000..0685046
--- /dev/null
+++ b/src/Scs/Communication/Scs/Communication/Protocols/WireProtocolManager.cs
@@ -0,0 +1,28 @@
+using Hik.Communication.Scs.Communication.Protocols.BinarySerialization;
+
+namespace Hik.Communication.Scs.Communication.Protocols
+{
+ /// <summary>
+ /// This class is used to get default protocols.
+ /// </summary>
+ internal static class WireProtocolManager
+ {
+ /// <summary>
+ /// Creates a default wire protocol factory object to be used on communicating of applications.
+ /// </summary>
+ /// <returns>A new instance of default wire protocol</returns>
+ public static IScsWireProtocolFactory GetDefaultWireProtocolFactory()
+ {
+ return new BinarySerializationProtocolFactory();
+ }
+
+ /// <summary>
+ /// Creates a default wire protocol object to be used on communicating of applications.
+ /// </summary>
+ /// <returns>A new instance of default wire protocol</returns>
+ public static IScsWireProtocol GetDefaultWireProtocol()
+ {
+ return new BinarySerializationProtocol();
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/IScsServer.cs b/src/Scs/Communication/Scs/Server/IScsServer.cs
new file mode 100644
index 0000000..a87e7a1
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/IScsServer.cs
@@ -0,0 +1,42 @@
+using System;
+using Hik.Collections;
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// Represents a SCS server that is used to accept and manage client connections.
+ /// </summary>
+ public interface IScsServer
+ {
+ /// <summary>
+ /// This event is raised when a new client connected to the server.
+ /// </summary>
+ event EventHandler<ServerClientEventArgs> ClientConnected;
+
+ /// <summary>
+ /// This event is raised when a client disconnected from the server.
+ /// </summary>
+ event EventHandler<ServerClientEventArgs> ClientDisconnected;
+
+ /// <summary>
+ /// Gets/sets wire protocol factory to create IWireProtocol objects.
+ /// </summary>
+ IScsWireProtocolFactory WireProtocolFactory { get; set; }
+
+ /// <summary>
+ /// A collection of clients that are connected to the server.
+ /// </summary>
+ ThreadSafeSortedList<long, IScsServerClient> Clients { get; }
+
+ /// <summary>
+ /// Starts the server.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Stops the server.
+ /// </summary>
+ void Stop();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/IScsServerClient.cs b/src/Scs/Communication/Scs/Server/IScsServerClient.cs
new file mode 100644
index 0000000..3e60bef
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/IScsServerClient.cs
@@ -0,0 +1,38 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// Represents a client from a perspective of a server.
+ /// </summary>
+ public interface IScsServerClient : IMessenger
+ {
+ /// <summary>
+ /// This event is raised when client disconnected from server.
+ /// </summary>
+ event EventHandler Disconnected;
+
+ /// <summary>
+ /// Unique identifier for this client in server.
+ /// </summary>
+ long ClientId { get; }
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ ScsEndPoint RemoteEndPoint { get; }
+
+ /// <summary>
+ /// Gets the current communication state.
+ /// </summary>
+ CommunicationStates CommunicationState { get; }
+
+ /// <summary>
+ /// Disconnects from server.
+ /// </summary>
+ void Disconnect();
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/ScsServerBase.cs b/src/Scs/Communication/Scs/Server/ScsServerBase.cs
new file mode 100644
index 0000000..d5019ea
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/ScsServerBase.cs
@@ -0,0 +1,168 @@
+using System;
+using Hik.Collections;
+using Hik.Communication.Scs.Communication.Channels;
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// This class provides base functionality for server classes.
+ /// </summary>
+ internal abstract class ScsServerBase : IScsServer
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new client is connected.
+ /// </summary>
+ public event EventHandler<ServerClientEventArgs> ClientConnected;
+
+ /// <summary>
+ /// This event is raised when a client disconnected from the server.
+ /// </summary>
+ public event EventHandler<ServerClientEventArgs> ClientDisconnected;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Gets/sets wire protocol that is used while reading and writing messages.
+ /// </summary>
+ public IScsWireProtocolFactory WireProtocolFactory { get; set; }
+
+ /// <summary>
+ /// A collection of clients that are connected to the server.
+ /// </summary>
+ public ThreadSafeSortedList<long, IScsServerClient> Clients { get; private set; }
+
+ #endregion
+
+ #region Private properties
+
+ /// <summary>
+ /// This object is used to listen incoming connections.
+ /// </summary>
+ private IConnectionListener _connectionListener;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ protected ScsServerBase()
+ {
+ Clients = new ThreadSafeSortedList<long, IScsServerClient>();
+ WireProtocolFactory = WireProtocolManager.GetDefaultWireProtocolFactory();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts the server.
+ /// </summary>
+ public virtual void Start()
+ {
+ _connectionListener = CreateConnectionListener();
+ _connectionListener.CommunicationChannelConnected += ConnectionListener_CommunicationChannelConnected;
+ _connectionListener.Start();
+ }
+
+ /// <summary>
+ /// Stops the server.
+ /// </summary>
+ public virtual void Stop()
+ {
+ if (_connectionListener != null)
+ {
+ _connectionListener.Stop();
+ }
+
+ foreach (var client in Clients.GetAllItems())
+ {
+ client.Disconnect();
+ }
+ }
+
+ #endregion
+
+ #region Protected abstract methods
+
+ /// <summary>
+ /// This method is implemented by derived classes to create appropriate connection listener to listen incoming connection requets.
+ /// </summary>
+ /// <returns></returns>
+ protected abstract IConnectionListener CreateConnectionListener();
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles CommunicationChannelConnected event of _connectionListener object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ConnectionListener_CommunicationChannelConnected(object sender, CommunicationChannelEventArgs e)
+ {
+ var client = new ScsServerClient(e.Channel)
+ {
+ ClientId = ScsServerManager.GetClientId(),
+ WireProtocol = WireProtocolFactory.CreateWireProtocol()
+ };
+
+ client.Disconnected += Client_Disconnected;
+ Clients[client.ClientId] = client;
+ OnClientConnected(client);
+ e.Channel.Start();
+ }
+
+ /// <summary>
+ /// Handles Disconnected events of all connected clients.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_Disconnected(object sender, EventArgs e)
+ {
+ var client = (IScsServerClient) sender;
+ Clients.Remove(client.ClientId);
+ OnClientDisconnected(client);
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises ClientConnected event.
+ /// </summary>
+ /// <param name="client">Connected client</param>
+ protected virtual void OnClientConnected(IScsServerClient client)
+ {
+ var handler = ClientConnected;
+ if (handler != null)
+ {
+ handler(this, new ServerClientEventArgs(client));
+ }
+ }
+
+ /// <summary>
+ /// Raises ClientDisconnected event.
+ /// </summary>
+ /// <param name="client">Disconnected client</param>
+ protected virtual void OnClientDisconnected(IScsServerClient client)
+ {
+ var handler = ClientDisconnected;
+ if (handler != null)
+ {
+ handler(this, new ServerClientEventArgs(client));
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/ScsServerClient.cs b/src/Scs/Communication/Scs/Server/ScsServerClient.cs
new file mode 100644
index 0000000..398ec79
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/ScsServerClient.cs
@@ -0,0 +1,223 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Channels;
+using Hik.Communication.Scs.Communication.Protocols;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// This class represents a client in server side.
+ /// </summary>
+ internal class ScsServerClient : IScsServerClient
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new message is received.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageReceived;
+
+ /// <summary>
+ /// This event is raised when a new message is sent without any error.
+ /// It does not guaranties that message is properly handled and processed by remote application.
+ /// </summary>
+ public event EventHandler<MessageEventArgs> MessageSent;
+
+ /// <summary>
+ /// This event is raised when client is disconnected from server.
+ /// </summary>
+ public event EventHandler Disconnected;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Unique identifier for this client in server.
+ /// </summary>
+ public long ClientId { get; set; }
+
+ /// <summary>
+ /// Gets the communication state of the Client.
+ /// </summary>
+ public CommunicationStates CommunicationState
+ {
+ get
+ {
+ return _communicationChannel.CommunicationState;
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets wire protocol that is used while reading and writing messages.
+ /// </summary>
+ public IScsWireProtocol WireProtocol
+ {
+ get { return _communicationChannel.WireProtocol; }
+ set { _communicationChannel.WireProtocol = value; }
+ }
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ public ScsEndPoint RemoteEndPoint
+ {
+ get { return _communicationChannel.RemoteEndPoint; }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastReceivedMessageTime
+ {
+ get
+ {
+ return _communicationChannel.LastReceivedMessageTime;
+ }
+ }
+
+ /// <summary>
+ /// Gets the time of the last succesfully received message.
+ /// </summary>
+ public DateTime LastSentMessageTime
+ {
+ get
+ {
+ return _communicationChannel.LastSentMessageTime;
+ }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// The communication channel that is used by client to send and receive messages.
+ /// </summary>
+ private readonly ICommunicationChannel _communicationChannel;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new ScsClient object.
+ /// </summary>
+ /// <param name="communicationChannel">The communication channel that is used by client to send and receive messages</param>
+ public ScsServerClient(ICommunicationChannel communicationChannel)
+ {
+ _communicationChannel = communicationChannel;
+ _communicationChannel.MessageReceived += CommunicationChannel_MessageReceived;
+ _communicationChannel.MessageSent += CommunicationChannel_MessageSent;
+ _communicationChannel.Disconnected += CommunicationChannel_Disconnected;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Disconnects from client and closes underlying communication channel.
+ /// </summary>
+ public void Disconnect()
+ {
+ _communicationChannel.Disconnect();
+ }
+
+ /// <summary>
+ /// Sends a message to the client.
+ /// </summary>
+ /// <param name="message">Message to be sent</param>
+ public void SendMessage(IScsMessage message)
+ {
+ _communicationChannel.SendMessage(message);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles Disconnected event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_Disconnected(object sender, EventArgs e)
+ {
+ OnDisconnected();
+ }
+
+ /// <summary>
+ /// Handles MessageReceived event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var message = e.Message;
+ if (message is ScsPingMessage)
+ {
+ _communicationChannel.SendMessage(new ScsPingMessage { RepliedMessageId = message.MessageId });
+ return;
+ }
+
+ OnMessageReceived(message);
+ }
+
+ /// <summary>
+ /// Handles MessageSent event of _communicationChannel object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void CommunicationChannel_MessageSent(object sender, MessageEventArgs e)
+ {
+ OnMessageSent(e.Message);
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises Disconnected event.
+ /// </summary>
+ private void OnDisconnected()
+ {
+ var handler = Disconnected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageReceived event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ private void OnMessageReceived(IScsMessage message)
+ {
+ var handler = MessageReceived;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ /// <summary>
+ /// Raises MessageSent event.
+ /// </summary>
+ /// <param name="message">Received message</param>
+ protected virtual void OnMessageSent(IScsMessage message)
+ {
+ var handler = MessageSent;
+ if (handler != null)
+ {
+ handler(this, new MessageEventArgs(message));
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/src/Scs/Communication/Scs/Server/ScsServerFactory.cs b/src/Scs/Communication/Scs/Server/ScsServerFactory.cs
new file mode 100644
index 0000000..d03b832
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/ScsServerFactory.cs
@@ -0,0 +1,20 @@
+using Hik.Communication.Scs.Communication.EndPoints;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// This class is used to create SCS servers.
+ /// </summary>
+ public static class ScsServerFactory
+ {
+ /// <summary>
+ /// Creates a new SCS Server using an EndPoint.
+ /// </summary>
+ /// <param name="endPoint">Endpoint that represents address of the server</param>
+ /// <returns>Created TCP server</returns>
+ public static IScsServer CreateServer(ScsEndPoint endPoint)
+ {
+ return endPoint.CreateServer();
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/ScsServerManager.cs b/src/Scs/Communication/Scs/Server/ScsServerManager.cs
new file mode 100644
index 0000000..dd2505a
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/ScsServerManager.cs
@@ -0,0 +1,24 @@
+using System.Threading;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// Provides some functionality that are used by servers.
+ /// </summary>
+ internal static class ScsServerManager
+ {
+ /// <summary>
+ /// Used to set an auto incremential unique identifier to clients.
+ /// </summary>
+ private static long _lastClientId;
+
+ /// <summary>
+ /// Gets an unique number to be used as idenfitier of a client.
+ /// </summary>
+ /// <returns></returns>
+ public static long GetClientId()
+ {
+ return Interlocked.Increment(ref _lastClientId);
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/ServerClientEventArgs.cs b/src/Scs/Communication/Scs/Server/ServerClientEventArgs.cs
new file mode 100644
index 0000000..875b8e0
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/ServerClientEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Hik.Communication.Scs.Server
+{
+ /// <summary>
+ /// Stores client information to be used by an event.
+ /// </summary>
+ public class ServerClientEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Client that is associated with this event.
+ /// </summary>
+ public IScsServerClient Client { get; private set; }
+
+ /// <summary>
+ /// Creates a new ServerClientEventArgs object.
+ /// </summary>
+ /// <param name="client">Client that is associated with this event</param>
+ public ServerClientEventArgs(IScsServerClient client)
+ {
+ Client = client;
+ }
+ }
+}
diff --git a/src/Scs/Communication/Scs/Server/Tcp/ScsTcpServer.cs b/src/Scs/Communication/Scs/Server/Tcp/ScsTcpServer.cs
new file mode 100644
index 0000000..fe8a3f7
--- /dev/null
+++ b/src/Scs/Communication/Scs/Server/Tcp/ScsTcpServer.cs
@@ -0,0 +1,35 @@
+using Hik.Communication.Scs.Communication.Channels;
+using Hik.Communication.Scs.Communication.Channels.Tcp;
+using Hik.Communication.Scs.Communication.EndPoints.Tcp;
+
+namespace Hik.Communication.Scs.Server.Tcp
+{
+ /// <summary>
+ /// This class is used to create a TCP server.
+ /// </summary>
+ internal class ScsTcpServer : ScsServerBase
+ {
+ /// <summary>
+ /// The endpoint address of the server to listen incoming connections.
+ /// </summary>
+ private readonly ScsTcpEndPoint _endPoint;
+
+ /// <summary>
+ /// Creates a new ScsTcpServer object.
+ /// </summary>
+ /// <param name="endPoint">The endpoint address of the server to listen incoming connections</param>
+ public ScsTcpServer(ScsTcpEndPoint endPoint)
+ {
+ _endPoint = endPoint;
+ }
+
+ /// <summary>
+ /// Creates a TCP connection listener.
+ /// </summary>
+ /// <returns>Created listener object</returns>
+ protected override IConnectionListener CreateConnectionListener()
+ {
+ return new TcpConnectionListener(_endPoint);
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Client/IScsServiceClient.cs b/src/Scs/Communication/ScsServices/Client/IScsServiceClient.cs
new file mode 100644
index 0000000..414d0c9
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Client/IScsServiceClient.cs
@@ -0,0 +1,24 @@
+using Hik.Communication.Scs.Client;
+
+namespace Hik.Communication.ScsServices.Client
+{
+ /// <summary>
+ /// Represents a service client that consumes a SCS service.
+ /// </summary>
+ /// <typeparam name="T">Type of service interface</typeparam>
+ public interface IScsServiceClient<out T> : IConnectableClient where T : class
+ {
+ /// <summary>
+ /// Reference to the service proxy to invoke remote service methods.
+ /// </summary>
+ T ServiceProxy { get; }
+
+ /// <summary>
+ /// Timeout value when invoking a service method.
+ /// If timeout occurs before end of remote method call, an exception is thrown.
+ /// Use -1 for no timeout (wait indefinite).
+ /// Default value: 60000 (1 minute).
+ /// </summary>
+ int Timeout { get; set; }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Client/ScsServiceClient.cs b/src/Scs/Communication/ScsServices/Client/ScsServiceClient.cs
new file mode 100644
index 0000000..32ddee1
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Client/ScsServiceClient.cs
@@ -0,0 +1,274 @@
+using System;
+using System.Reflection;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+using Hik.Communication.ScsServices.Communication;
+using Hik.Communication.ScsServices.Communication.Messages;
+
+namespace Hik.Communication.ScsServices.Client
+{
+ /// <summary>
+ /// Represents a service client that consumes a SCS service.
+ /// </summary>
+ /// <typeparam name="T">Type of service interface</typeparam>
+ internal class ScsServiceClient<T> : IScsServiceClient<T> where T : class
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when client connected to server.
+ /// </summary>
+ public event EventHandler Connected;
+
+ /// <summary>
+ /// This event is raised when client disconnected from server.
+ /// </summary>
+ public event EventHandler Disconnected;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Timeout for connecting to a server (as milliseconds).
+ /// Default value: 15 seconds (15000 ms).
+ /// </summary>
+ public int ConnectTimeout
+ {
+ get { return _client.ConnectTimeout; }
+ set { _client.ConnectTimeout = value; }
+ }
+
+ /// <summary>
+ /// Gets the current communication state.
+ /// </summary>
+ public CommunicationStates CommunicationState
+ {
+ get { return _client.CommunicationState; }
+ }
+
+ /// <summary>
+ /// Reference to the service proxy to invoke remote service methods.
+ /// </summary>
+ public T ServiceProxy { get; private set; }
+
+ /// <summary>
+ /// Timeout value when invoking a service method.
+ /// If timeout occurs before end of remote method call, an exception is thrown.
+ /// Use -1 for no timeout (wait indefinite).
+ /// Default value: 60000 (1 minute).
+ /// </summary>
+ public int Timeout
+ {
+ get { return _requestReplyMessenger.Timeout; }
+ set { _requestReplyMessenger.Timeout = value; }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Underlying IScsClient object to communicate with server.
+ /// </summary>
+ private readonly IScsClient _client;
+
+ /// <summary>
+ /// Messenger object to send/receive messages over _client.
+ /// </summary>
+ private readonly RequestReplyMessenger<IScsClient> _requestReplyMessenger;
+
+ /// <summary>
+ /// This object is used to create a transparent proxy to invoke remote methods on server.
+ /// </summary>
+ private readonly AutoConnectRemoteInvokeProxy<T, IScsClient> _realServiceProxy;
+
+ /// <summary>
+ /// The client object that is used to call method invokes in client side.
+ /// May be null if client has no methods to be invoked by server.
+ /// </summary>
+ private readonly object _clientObject;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new ScsServiceClient object.
+ /// </summary>
+ /// <param name="client">Underlying IScsClient object to communicate with server</param>
+ /// <param name="clientObject">The client object that is used to call method invokes in client side.
+ /// May be null if client has no methods to be invoked by server.</param>
+ public ScsServiceClient(IScsClient client, object clientObject)
+ {
+ _client = client;
+ _clientObject = clientObject;
+
+ _client.Connected += Client_Connected;
+ _client.Disconnected += Client_Disconnected;
+
+ _requestReplyMessenger = new RequestReplyMessenger<IScsClient>(client);
+ _requestReplyMessenger.MessageReceived += RequestReplyMessenger_MessageReceived;
+
+ _realServiceProxy = new AutoConnectRemoteInvokeProxy<T, IScsClient>(_requestReplyMessenger, this);
+ ServiceProxy = (T)_realServiceProxy.GetTransparentProxy();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Connects to server.
+ /// </summary>
+ public void Connect()
+ {
+ _client.Connect();
+ }
+
+ /// <summary>
+ /// Disconnects from server.
+ /// Does nothing if already disconnected.
+ /// </summary>
+ public void Disconnect()
+ {
+ _client.Disconnect();
+ }
+
+ /// <summary>
+ /// Calls Disconnect method.
+ /// </summary>
+ public void Dispose()
+ {
+ Disconnect();
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles MessageReceived event of messenger.
+ /// It gets messages from server and invokes appropriate method.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void RequestReplyMessenger_MessageReceived(object sender, MessageEventArgs e)
+ {
+ //Cast message to ScsRemoteInvokeMessage and check it
+ var invokeMessage = e.Message as ScsRemoteInvokeMessage;
+ if (invokeMessage == null)
+ {
+ return;
+ }
+
+ //Check client object.
+ if(_clientObject == null)
+ {
+ SendInvokeResponse(invokeMessage, null, new ScsRemoteException("Client does not wait for method invocations by server."));
+ return;
+ }
+
+ //Invoke method
+ object returnValue;
+ try
+ {
+ var type = _clientObject.GetType();
+ var method = type.GetMethod(invokeMessage.MethodName);
+ returnValue = method.Invoke(_clientObject, invokeMessage.Parameters);
+ }
+ catch (TargetInvocationException ex)
+ {
+ var innerEx = ex.InnerException;
+ SendInvokeResponse(invokeMessage, null, new ScsRemoteException(innerEx.Message, innerEx));
+ return;
+ }
+ catch (Exception ex)
+ {
+ SendInvokeResponse(invokeMessage, null, new ScsRemoteException(ex.Message, ex));
+ return;
+ }
+
+ //Send return value
+ SendInvokeResponse(invokeMessage, returnValue, null);
+ }
+
+ /// <summary>
+ /// Sends response to the remote application that invoked a service method.
+ /// </summary>
+ /// <param name="requestMessage">Request message</param>
+ /// <param name="returnValue">Return value to send</param>
+ /// <param name="exception">Exception to send</param>
+ private void SendInvokeResponse(IScsMessage requestMessage, object returnValue, ScsRemoteException exception)
+ {
+ try
+ {
+ _requestReplyMessenger.SendMessage(
+ new ScsRemoteInvokeReturnMessage
+ {
+ RepliedMessageId = requestMessage.MessageId,
+ ReturnValue = returnValue,
+ RemoteException = exception
+ });
+ }
+ catch
+ {
+
+ }
+ }
+
+ /// <summary>
+ /// Handles Connected event of _client object.
+ /// </summary>
+ /// <param name="sender">Source of object</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_Connected(object sender, EventArgs e)
+ {
+ _requestReplyMessenger.Start();
+ OnConnected();
+ }
+
+ /// <summary>
+ /// Handles Disconnected event of _client object.
+ /// </summary>
+ /// <param name="sender">Source of object</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_Disconnected(object sender, EventArgs e)
+ {
+ _requestReplyMessenger.Stop();
+ OnDisconnected();
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Raises Connected event.
+ /// </summary>
+ private void OnConnected()
+ {
+ var handler = Connected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Raises Disconnected event.
+ /// </summary>
+ private void OnDisconnected()
+ {
+ var handler = Disconnected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/src/Scs/Communication/ScsServices/Client/ScsServiceClientBuilder.cs b/src/Scs/Communication/ScsServices/Client/ScsServiceClientBuilder.cs
new file mode 100644
index 0000000..ee9280e
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Client/ScsServiceClientBuilder.cs
@@ -0,0 +1,36 @@
+using Hik.Communication.Scs.Communication.EndPoints;
+
+namespace Hik.Communication.ScsServices.Client
+{
+ /// <summary>
+ /// This class is used to build service clients to remotely invoke methods of a SCS service.
+ /// </summary>
+ public class ScsServiceClientBuilder
+ {
+ /// <summary>
+ /// Creates a client to connect to a SCS service.
+ /// </summary>
+ /// <typeparam name="T">Type of service interface for remote method call</typeparam>
+ /// <param name="endpoint">EndPoint of the server</param>
+ /// <param name="clientObject">Client-side object that handles remote method calls from server to client.
+ /// May be null if client has no methods to be invoked by server</param>
+ /// <returns>Created client object to connect to the server</returns>
+ public static IScsServiceClient<T> CreateClient<T>(ScsEndPoint endpoint, object clientObject = null) where T : class
+ {
+ return new ScsServiceClient<T>(endpoint.CreateClient(), clientObject);
+ }
+
+ /// <summary>
+ /// Creates a client to connect to a SCS service.
+ /// </summary>
+ /// <typeparam name="T">Type of service interface for remote method call</typeparam>
+ /// <param name="endpointAddress">EndPoint address of the server</param>
+ /// <param name="clientObject">Client-side object that handles remote method calls from server to client.
+ /// May be null if client has no methods to be invoked by server</param>
+ /// <returns>Created client object to connect to the server</returns>
+ public static IScsServiceClient<T> CreateClient<T>(string endpointAddress, object clientObject = null) where T : class
+ {
+ return CreateClient<T>(ScsEndPoint.CreateEndPoint(endpointAddress), clientObject);
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Communication/AutoConnectRemoteInvokeProxy.cs b/src/Scs/Communication/ScsServices/Communication/AutoConnectRemoteInvokeProxy.cs
new file mode 100644
index 0000000..42b24c5
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Communication/AutoConnectRemoteInvokeProxy.cs
@@ -0,0 +1,57 @@
+using System.Runtime.Remoting.Messaging;
+using Hik.Communication.Scs.Client;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messengers;
+
+namespace Hik.Communication.ScsServices.Communication
+{
+ /// <summary>
+ /// This class extends RemoteInvokeProxy to provide auto connect/disconnect mechanism
+ /// if client is not connected to the server when a service method is called.
+ /// </summary>
+ /// <typeparam name="TProxy">Type of the proxy class/interface</typeparam>
+ /// <typeparam name="TMessenger">Type of the messenger object that is used to send/receive messages</typeparam>
+ internal class AutoConnectRemoteInvokeProxy<TProxy, TMessenger> : RemoteInvokeProxy<TProxy, TMessenger> where TMessenger : IMessenger
+ {
+ /// <summary>
+ /// Reference to the client object that is used to connect/disconnect.
+ /// </summary>
+ private readonly IConnectableClient _client;
+
+ /// <summary>
+ /// Creates a new AutoConnectRemoteInvokeProxy object.
+ /// </summary>
+ /// <param name="clientMessenger">Messenger object that is used to send/receive messages</param>
+ /// <param name="client">Reference to the client object that is used to connect/disconnect</param>
+ public AutoConnectRemoteInvokeProxy(RequestReplyMessenger<TMessenger> clientMessenger, IConnectableClient client)
+ : base(clientMessenger)
+ {
+ _client = client;
+ }
+
+ /// <summary>
+ /// Overrides message calls and translates them to messages to remote application.
+ /// </summary>
+ /// <param name="msg">Method invoke message (from RealProxy base class)</param>
+ /// <returns>Method invoke return message (to RealProxy base class)</returns>
+ public override IMessage Invoke(IMessage msg)
+ {
+ if (_client.CommunicationState == CommunicationStates.Connected)
+ {
+ //If already connected, behave as base class (RemoteInvokeProxy).
+ return base.Invoke(msg);
+ }
+
+ //Connect, call method and finally disconnect
+ _client.Connect();
+ try
+ {
+ return base.Invoke(msg);
+ }
+ finally
+ {
+ _client.Disconnect();
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteException.cs b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteException.cs
new file mode 100644
index 0000000..3383368
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteException.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Hik.Communication.ScsServices.Communication.Messages
+{
+ /// <summary>
+ /// Represents a SCS Remote Exception.
+ /// This exception is used to send an exception from an application to another application.
+ /// </summary>
+ [Serializable]
+ public class ScsRemoteException : Exception
+ {
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public ScsRemoteException()
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ public ScsRemoteException(SerializationInfo serializationInfo, StreamingContext context)
+ : base(serializationInfo, context)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ public ScsRemoteException(string message)
+ : base(message)
+ {
+
+ }
+
+ /// <summary>
+ /// Contstructor.
+ /// </summary>
+ /// <param name="message">Exception message</param>
+ /// <param name="innerException">Inner exception</param>
+ public ScsRemoteException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeMessage.cs b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeMessage.cs
new file mode 100644
index 0000000..b482f3a
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeMessage.cs
@@ -0,0 +1,36 @@
+using System;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.ScsServices.Communication.Messages
+{
+ /// <summary>
+ /// This message is sent to invoke a method of a remote application.
+ /// </summary>
+ [Serializable]
+ public class ScsRemoteInvokeMessage : ScsMessage
+ {
+ /// <summary>
+ /// Name of the remove service class.
+ /// </summary>
+ public string ServiceClassName { get; set; }
+
+ /// <summary>
+ /// Method of remote application to invoke.
+ /// </summary>
+ public string MethodName { get; set; }
+
+ /// <summary>
+ /// Parameters of method.
+ /// </summary>
+ public object[] Parameters { get; set; }
+
+ /// <summary>
+ /// Represents this object as string.
+ /// </summary>
+ /// <returns>String representation of this object</returns>
+ public override string ToString()
+ {
+ return string.Format("ScsRemoteInvokeMessage: {0}.{1}(...)", ServiceClassName, MethodName);
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeReturnMessage.cs b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeReturnMessage.cs
new file mode 100644
index 0000000..7d4f14f
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Communication/Messages/ScsRemoteInvokeReturnMessage.cs
@@ -0,0 +1,33 @@
+using System;
+using Hik.Communication.Scs.Communication.Messages;
+
+namespace Hik.Communication.ScsServices.Communication.Messages
+{
+ /// <summary>
+ /// This message is sent as response message to a ScsRemoteInvokeMessage.
+ /// It is used to send return value of method invocation.
+ /// </summary>
+ [Serializable]
+ public class ScsRemoteInvokeReturnMessage : ScsMessage
+ {
+ /// <summary>
+ /// Return value of remote method invocation.
+ /// </summary>
+ public object ReturnValue { get; set; }
+
+ /// <summary>
+ /// If any exception occured during method invocation, this field contains Exception object.
+ /// If no exception occured, this field is null.
+ /// </summary>
+ public ScsRemoteException RemoteException { get; set; }
+
+ /// <summary>
+ /// Represents this object as string.
+ /// </summary>
+ /// <returns>String representation of this object</returns>
+ public override string ToString()
+ {
+ return string.Format("ScsRemoteInvokeReturnMessage: Returns {0}, Exception = {1}", ReturnValue, RemoteException);
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Communication/RemoteInvokeProxy.cs b/src/Scs/Communication/ScsServices/Communication/RemoteInvokeProxy.cs
new file mode 100644
index 0000000..b6f0caa
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Communication/RemoteInvokeProxy.cs
@@ -0,0 +1,63 @@
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Proxies;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messengers;
+using Hik.Communication.ScsServices.Communication.Messages;
+
+namespace Hik.Communication.ScsServices.Communication
+{
+ /// <summary>
+ /// This class is used to generate a dynamic proxy to invoke remote methods.
+ /// It translates method invocations to messaging.
+ /// </summary>
+ /// <typeparam name="TProxy">Type of the proxy class/interface</typeparam>
+ /// <typeparam name="TMessenger">Type of the messenger object that is used to send/receive messages</typeparam>
+ internal class RemoteInvokeProxy<TProxy, TMessenger> : RealProxy where TMessenger : IMessenger
+ {
+ /// <summary>
+ /// Messenger object that is used to send/receive messages.
+ /// </summary>
+ private readonly RequestReplyMessenger<TMessenger> _clientMessenger;
+
+ /// <summary>
+ /// Creates a new RemoteInvokeProxy object.
+ /// </summary>
+ /// <param name="clientMessenger">Messenger object that is used to send/receive messages</param>
+ public RemoteInvokeProxy(RequestReplyMessenger<TMessenger> clientMessenger)
+ : base(typeof(TProxy))
+ {
+ _clientMessenger = clientMessenger;
+ }
+
+ /// <summary>
+ /// Overrides message calls and translates them to messages to remote application.
+ /// </summary>
+ /// <param name="msg">Method invoke message (from RealProxy base class)</param>
+ /// <returns>Method invoke return message (to RealProxy base class)</returns>
+ public override IMessage Invoke(IMessage msg)
+ {
+ var message = msg as IMethodCallMessage;
+ if (message == null)
+ {
+ return null;
+ }
+
+ var requestMessage = new ScsRemoteInvokeMessage
+ {
+ ServiceClassName = typeof (TProxy).Name,
+ MethodName = message.MethodName,
+ Parameters = message.InArgs
+ };
+
+ var responseMessage = _clientMessenger.SendMessageAndWaitForResponse(requestMessage) as ScsRemoteInvokeReturnMessage;
+ if (responseMessage == null)
+ {
+ return null;
+ }
+
+ return responseMessage.RemoteException != null
+ ? new ReturnMessage(responseMessage.RemoteException, message)
+ : new ReturnMessage(responseMessage.ReturnValue, null, 0, message.LogicalCallContext, message);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Scs/Communication/ScsServices/Service/IScsServiceApplication.cs b/src/Scs/Communication/ScsServices/Service/IScsServiceApplication.cs
new file mode 100644
index 0000000..8fdb2f0
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/IScsServiceApplication.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Represents a SCS Service Application that is used to construct and manage a SCS service.
+ /// </summary>
+ public interface IScsServiceApplication
+ {
+ /// <summary>
+ /// This event is raised when a new client connected to the service.
+ /// </summary>
+ event EventHandler<ServiceClientEventArgs> ClientConnected;
+
+ /// <summary>
+ /// This event is raised when a client disconnected from the service.
+ /// </summary>
+ event EventHandler<ServiceClientEventArgs> ClientDisconnected;
+
+ /// <summary>
+ /// Starts service application.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Stops service application.
+ /// </summary>
+ void Stop();
+
+ /// <summary>
+ /// Adds a service object to this service application.
+ /// Only single service object can be added for a service interface type.
+ /// </summary>
+ /// <typeparam name="TServiceInterface">Service interface type</typeparam>
+ /// <typeparam name="TServiceClass">Service class type. Must be delivered from ScsService and must implement TServiceInterface.</typeparam>
+ /// <param name="service">An instance of TServiceClass.</param>
+ void AddService<TServiceInterface, TServiceClass>(TServiceClass service)
+ where TServiceClass : ScsService, TServiceInterface
+ where TServiceInterface : class;
+
+ /// <summary>
+ /// Removes a previously added service object from this service application.
+ /// It removes object according to interface type.
+ /// </summary>
+ /// <typeparam name="TServiceInterface">Service interface type</typeparam>
+ /// <returns>True: removed. False: no service object with this interface</returns>
+ bool RemoveService<TServiceInterface>() where TServiceInterface : class;
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/IScsServiceClient.cs b/src/Scs/Communication/ScsServices/Service/IScsServiceClient.cs
new file mode 100644
index 0000000..e60f91d
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/IScsServiceClient.cs
@@ -0,0 +1,44 @@
+using System;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.EndPoints;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Represents a client that uses a SDS service.
+ /// </summary>
+ public interface IScsServiceClient
+ {
+ /// <summary>
+ /// This event is raised when client is disconnected from service.
+ /// </summary>
+ event EventHandler Disconnected;
+
+ /// <summary>
+ /// Unique identifier for this client.
+ /// </summary>
+ long ClientId { get; }
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ ScsEndPoint RemoteEndPoint { get; }
+
+ /// <summary>
+ /// Gets the communication state of the Client.
+ /// </summary>
+ CommunicationStates CommunicationState { get; }
+
+ /// <summary>
+ /// Closes client connection.
+ /// </summary>
+ void Disconnect();
+
+ /// <summary>
+ /// Gets the client proxy interface that provides calling client methods remotely.
+ /// </summary>
+ /// <typeparam name="T">Type of client interface</typeparam>
+ /// <returns>Client interface</returns>
+ T GetClientProxy<T>() where T : class;
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsService.cs b/src/Scs/Communication/ScsServices/Service/ScsService.cs
new file mode 100644
index 0000000..2321343
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsService.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Base class for all services that is serviced by IScsServiceApplication.
+ /// A class must be derived from ScsService to serve as a SCS service.
+ /// </summary>
+ public abstract class ScsService
+ {
+ /// <summary>
+ /// The current client for a thread that called service method.
+ /// </summary>
+ [ThreadStatic]
+ private static IScsServiceClient _currentClient;
+
+ /// <summary>
+ /// Gets the current client which called this service method.
+ /// </summary>
+ /// <remarks>
+ /// This property is thread-safe, if returns correct client when
+ /// called in a service method if the method is called by SCS system,
+ /// else throws exception.
+ /// </remarks>
+ protected internal IScsServiceClient CurrentClient
+ {
+ get
+ {
+ if (_currentClient == null)
+ {
+ throw new Exception("Client channel can not be obtained. CurrentClient property must be called by the thread which runs the service method.");
+ }
+
+ return _currentClient;
+ }
+
+ internal set
+ {
+ _currentClient = value;
+ }
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsServiceApplication.cs b/src/Scs/Communication/ScsServices/Service/ScsServiceApplication.cs
new file mode 100644
index 0000000..2faa20b
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsServiceApplication.cs
@@ -0,0 +1,370 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Hik.Collections;
+using Hik.Communication.Scs.Communication.Messages;
+using Hik.Communication.Scs.Communication.Messengers;
+using Hik.Communication.Scs.Server;
+using Hik.Communication.ScsServices.Communication.Messages;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Implements IScsServiceApplication and provides all functionallity.
+ /// </summary>
+ internal class ScsServiceApplication : IScsServiceApplication
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when a new client connected to the service.
+ /// </summary>
+ public event EventHandler<ServiceClientEventArgs> ClientConnected;
+
+ /// <summary>
+ /// This event is raised when a client disconnected from the service.
+ /// </summary>
+ public event EventHandler<ServiceClientEventArgs> ClientDisconnected;
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Underlying IScsServer object to accept and manage client connections.
+ /// </summary>
+ private readonly IScsServer _scsServer;
+
+ /// <summary>
+ /// User service objects that is used to invoke incoming method invocation requests.
+ /// Key: Service interface type's name.
+ /// Value: Service object.
+ /// </summary>
+ private readonly ThreadSafeSortedList<string, ServiceObject> _serviceObjects;
+
+ /// <summary>
+ /// All connected clients to service.
+ /// Key: Client's unique Id.
+ /// Value: Reference to the client.
+ /// </summary>
+ private readonly ThreadSafeSortedList<long, IScsServiceClient> _serviceClients;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Creates a new ScsServiceApplication object.
+ /// </summary>
+ /// <param name="scsServer">Underlying IScsServer object to accept and manage client connections</param>
+ /// <exception cref="ArgumentNullException">Throws ArgumentNullException if scsServer argument is null</exception>
+ public ScsServiceApplication(IScsServer scsServer)
+ {
+ if (scsServer == null)
+ {
+ throw new ArgumentNullException("scsServer");
+ }
+
+ _scsServer = scsServer;
+ _scsServer.ClientConnected += ScsServer_ClientConnected;
+ _scsServer.ClientDisconnected += ScsServer_ClientDisconnected;
+ _serviceObjects = new ThreadSafeSortedList<string, ServiceObject>();
+ _serviceClients = new ThreadSafeSortedList<long, IScsServiceClient>();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts service application.
+ /// </summary>
+ public void Start()
+ {
+ _scsServer.Start();
+ }
+
+ /// <summary>
+ /// Stops service application.
+ /// </summary>
+ public void Stop()
+ {
+ _scsServer.Stop();
+ }
+
+ /// <summary>
+ /// Adds a service object to this service application.
+ /// Only single service object can be added for a service interface type.
+ /// </summary>
+ /// <typeparam name="TServiceInterface">Service interface type</typeparam>
+ /// <typeparam name="TServiceClass">Service class type. Must be delivered from ScsService and must implement TServiceInterface.</typeparam>
+ /// <param name="service">An instance of TServiceClass.</param>
+ /// <exception cref="ArgumentNullException">Throws ArgumentNullException if service argument is null</exception>
+ /// <exception cref="Exception">Throws Exception if service is already added before</exception>
+ public void AddService<TServiceInterface, TServiceClass>(TServiceClass service)
+ where TServiceClass : ScsService, TServiceInterface
+ where TServiceInterface : class
+ {
+ if (service == null)
+ {
+ throw new ArgumentNullException("service");
+ }
+
+ var type = typeof(TServiceInterface);
+ if(_serviceObjects[type.Name] != null)
+ {
+ throw new Exception("Service '" + type.Name + "' is already added before.");
+ }
+
+ _serviceObjects[type.Name] = new ServiceObject(type, service);
+ }
+
+ /// <summary>
+ /// Removes a previously added service object from this service application.
+ /// It removes object according to interface type.
+ /// </summary>
+ /// <typeparam name="TServiceInterface">Service interface type</typeparam>
+ /// <returns>True: removed. False: no service object with this interface</returns>
+ public bool RemoveService<TServiceInterface>()
+ where TServiceInterface : class
+ {
+ return _serviceObjects.Remove(typeof(TServiceInterface).Name);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles ClientConnected event of _scsServer object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ScsServer_ClientConnected(object sender, ServerClientEventArgs e)
+ {
+ var requestReplyMessenger = new RequestReplyMessenger<IScsServerClient>(e.Client);
+ requestReplyMessenger.MessageReceived += Client_MessageReceived;
+ requestReplyMessenger.Start();
+
+ var serviceClient = ScsServiceClientFactory.CreateServiceClient(e.Client, requestReplyMessenger);
+ _serviceClients[serviceClient.ClientId] = serviceClient;
+ OnClientConnected(serviceClient);
+ }
+
+ /// <summary>
+ /// Handles ClientDisconnected event of _scsServer object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void ScsServer_ClientDisconnected(object sender, ServerClientEventArgs e)
+ {
+ var serviceClient = _serviceClients[e.Client.ClientId];
+ if (serviceClient == null)
+ {
+ return;
+ }
+
+ _serviceClients.Remove(e.Client.ClientId);
+ OnClientDisconnected(serviceClient);
+ }
+
+ /// <summary>
+ /// Handles MessageReceived events of all clients, evaluates each message,
+ /// finds appropriate service object and invokes appropriate method.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_MessageReceived(object sender, MessageEventArgs e)
+ {
+ //Get RequestReplyMessenger object (sender of event) to get client
+ var requestReplyMessenger = (RequestReplyMessenger<IScsServerClient>) sender;
+
+ //Cast message to ScsRemoteInvokeMessage and check it
+ var invokeMessage = e.Message as ScsRemoteInvokeMessage;
+ if (invokeMessage == null)
+ {
+ return;
+ }
+
+ try
+ {
+ //Get client object
+ var client = _serviceClients[requestReplyMessenger.Messenger.ClientId];
+ if (client == null)
+ {
+ requestReplyMessenger.Messenger.Disconnect();
+ return;
+ }
+
+ //Get service object
+ var serviceObject = _serviceObjects[invokeMessage.ServiceClassName];
+ if (serviceObject == null)
+ {
+ SendInvokeResponse(requestReplyMessenger, invokeMessage, null, new ScsRemoteException("There is no service with name '" + invokeMessage.ServiceClassName + "'"));
+ return;
+ }
+
+ //Invoke method
+ try
+ {
+ object returnValue;
+ //Set client to service, so user service can get client
+ //in service method using CurrentClient property.
+ serviceObject.Service.CurrentClient = client;
+ try
+ {
+ returnValue = serviceObject.InvokeMethod(invokeMessage.MethodName, invokeMessage.Parameters);
+ }
+ finally
+ {
+ //Set CurrentClient as null since method call completed
+ serviceObject.Service.CurrentClient = null;
+ }
+
+ //Send method invocation return value to the client
+ SendInvokeResponse(requestReplyMessenger, invokeMessage, returnValue, null);
+ }
+ catch (TargetInvocationException ex)
+ {
+ var innerEx = ex.InnerException;
+ SendInvokeResponse(requestReplyMessenger, invokeMessage, null, new ScsRemoteException(innerEx.Message + Environment.NewLine + "Service Version: " + serviceObject.ServiceAttribute.Version, innerEx));
+ return;
+ }
+ catch (Exception ex)
+ {
+ SendInvokeResponse(requestReplyMessenger, invokeMessage, null, new ScsRemoteException(ex.Message + Environment.NewLine + "Service Version: " + serviceObject.ServiceAttribute.Version, ex));
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ SendInvokeResponse(requestReplyMessenger, invokeMessage, null, new ScsRemoteException("An error occured during remote service method call.", ex));
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Sends response to the remote application that invoked a service method.
+ /// </summary>
+ /// <param name="client">Client that sent invoke message</param>
+ /// <param name="requestMessage">Request message</param>
+ /// <param name="returnValue">Return value to send</param>
+ /// <param name="exception">Exception to send</param>
+ private static void SendInvokeResponse(IMessenger client, IScsMessage requestMessage, object returnValue, ScsRemoteException exception)
+ {
+ try
+ {
+ client.SendMessage(
+ new ScsRemoteInvokeReturnMessage
+ {
+ RepliedMessageId = requestMessage.MessageId,
+ ReturnValue = returnValue,
+ RemoteException = exception
+ });
+ }
+ catch
+ {
+
+ }
+ }
+
+ /// <summary>
+ /// Raises ClientConnected event.
+ /// </summary>
+ /// <param name="client"></param>
+ private void OnClientConnected(IScsServiceClient client)
+ {
+ var handler = ClientConnected;
+ if (handler != null)
+ {
+ handler(this, new ServiceClientEventArgs(client));
+ }
+ }
+
+ /// <summary>
+ /// Raises ClientDisconnected event.
+ /// </summary>
+ /// <param name="client"></param>
+ private void OnClientDisconnected(IScsServiceClient client)
+ {
+ var handler = ClientDisconnected;
+ if (handler != null)
+ {
+ handler(this, new ServiceClientEventArgs(client));
+ }
+ }
+
+ #endregion
+
+ #region ServiceObject class
+
+ /// <summary>
+ /// Represents a user service object.
+ /// It is used to invoke methods on a ScsService object.
+ /// </summary>
+ private sealed class ServiceObject
+ {
+ /// <summary>
+ /// The service object that is used to invoke methods on.
+ /// </summary>
+ public ScsService Service { get; private set; }
+
+ /// <summary>
+ /// ScsService attribute of Service object's class.
+ /// </summary>
+ public ScsServiceAttribute ServiceAttribute { get; private set; }
+
+ /// <summary>
+ /// This collection stores a list of all methods of service object.
+ /// Key: Method name
+ /// Value: Informations about method.
+ /// </summary>
+ private readonly SortedList<string, MethodInfo> _methods;
+
+ /// <summary>
+ /// Creates a new ServiceObject.
+ /// </summary>
+ /// <param name="serviceInterfaceType">Type of service interface</param>
+ /// <param name="service">The service object that is used to invoke methods on</param>
+ public ServiceObject(Type serviceInterfaceType, ScsService service)
+ {
+ Service = service;
+ var classAttributes = serviceInterfaceType.GetCustomAttributes(typeof(ScsServiceAttribute), true);
+ if (classAttributes.Length <= 0)
+ {
+ throw new Exception("Service interface (" + serviceInterfaceType.Name + ") must has ScsService attribute.");
+ }
+
+ ServiceAttribute = classAttributes[0] as ScsServiceAttribute;
+ _methods = new SortedList<string, MethodInfo>();
+ foreach (var methodInfo in serviceInterfaceType.GetMethods())
+ {
+ _methods.Add(methodInfo.Name, methodInfo);
+ }
+ }
+
+ /// <summary>
+ /// Invokes a method of Service object.
+ /// </summary>
+ /// <param name="methodName">Name of the method to invoke</param>
+ /// <param name="parameters">Parameters of method</param>
+ /// <returns>Return value of method</returns>
+ public object InvokeMethod(string methodName, params object[] parameters)
+ {
+ //Check if there is a method with name methodName
+ if (!_methods.ContainsKey(methodName))
+ {
+ throw new Exception("There is not a method with name '" + methodName + "' in service class.");
+ }
+
+ //Get method
+ var method = _methods[methodName];
+
+ //Invoke method and return invoke result
+ return method.Invoke(Service, parameters);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsServiceAttribute.cs b/src/Scs/Communication/ScsServices/Service/ScsServiceAttribute.cs
new file mode 100644
index 0000000..e73a2d4
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsServiceAttribute.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Any SCS Service interface class must has this attribute.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class)]
+ public class ScsServiceAttribute : Attribute
+ {
+ /// <summary>
+ /// Service Version. This property can be used to indicate the code version.
+ /// This value is sent to client application on an exception, so, client application can know that service version is changed.
+ /// Default value: NO_VERSION.
+ /// </summary>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// Creates a new ScsServiceAttribute object.
+ /// </summary>
+ public ScsServiceAttribute()
+ {
+ Version = "NO_VERSION";
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsServiceBuilder.cs b/src/Scs/Communication/ScsServices/Service/ScsServiceBuilder.cs
new file mode 100644
index 0000000..1860532
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsServiceBuilder.cs
@@ -0,0 +1,21 @@
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Server;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// This class is used to build ScsService applications.
+ /// </summary>
+ public static class ScsServiceBuilder
+ {
+ /// <summary>
+ /// Creates a new SCS Service application using an EndPoint.
+ /// </summary>
+ /// <param name="endPoint">EndPoint that represents address of the service</param>
+ /// <returns>Created SCS service application</returns>
+ public static IScsServiceApplication CreateService(ScsEndPoint endPoint)
+ {
+ return new ScsServiceApplication(ScsServerFactory.CreateServer(endPoint));
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsServiceClient.cs b/src/Scs/Communication/ScsServices/Service/ScsServiceClient.cs
new file mode 100644
index 0000000..eda5caa
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsServiceClient.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Runtime.Remoting.Proxies;
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.EndPoints;
+using Hik.Communication.Scs.Communication.Messengers;
+using Hik.Communication.Scs.Server;
+using Hik.Communication.ScsServices.Communication;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Implements IScsServiceClient.
+ /// It is used to manage and monitor a service client.
+ /// </summary>
+ internal class ScsServiceClient : IScsServiceClient
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised when this client is disconnected from server.
+ /// </summary>
+ public event EventHandler Disconnected;
+
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Unique identifier for this client.
+ /// </summary>
+ public long ClientId
+ {
+ get { return _serverClient.ClientId; }
+ }
+
+ ///<summary>
+ /// Gets endpoint of remote application.
+ ///</summary>
+ public ScsEndPoint RemoteEndPoint
+ {
+ get { return _serverClient.RemoteEndPoint; }
+ }
+
+ /// <summary>
+ /// Gets the communication state of the Client.
+ /// </summary>
+ public CommunicationStates CommunicationState
+ {
+ get
+ {
+ return _serverClient.CommunicationState;
+ }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// Reference to underlying IScsServerClient object.
+ /// </summary>
+ private readonly IScsServerClient _serverClient;
+
+ /// <summary>
+ /// This object is used to send messages to client.
+ /// </summary>
+ private readonly RequestReplyMessenger<IScsServerClient> _requestReplyMessenger;
+
+ /// <summary>
+ /// Last created proxy object to invoke remote medhods.
+ /// </summary>
+ private RealProxy _realProxy;
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new ScsServiceClient object.
+ /// </summary>
+ /// <param name="serverClient">Reference to underlying IScsServerClient object</param>
+ /// <param name="requestReplyMessenger">RequestReplyMessenger to send messages</param>
+ public ScsServiceClient(IScsServerClient serverClient, RequestReplyMessenger<IScsServerClient> requestReplyMessenger)
+ {
+ _serverClient = serverClient;
+ _serverClient.Disconnected += Client_Disconnected;
+ _requestReplyMessenger = requestReplyMessenger;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Closes client connection.
+ /// </summary>
+ public void Disconnect()
+ {
+ _serverClient.Disconnect();
+ }
+
+ /// <summary>
+ /// Gets the client proxy interface that provides calling client methods remotely.
+ /// </summary>
+ /// <typeparam name="T">Type of client interface</typeparam>
+ /// <returns>Client interface</returns>
+ public T GetClientProxy<T>() where T : class
+ {
+ _realProxy = new RemoteInvokeProxy<T, IScsServerClient>(_requestReplyMessenger);
+ return (T)_realProxy.GetTransparentProxy();
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// Handles disconnect event of _serverClient object.
+ /// </summary>
+ /// <param name="sender">Source of event</param>
+ /// <param name="e">Event arguments</param>
+ private void Client_Disconnected(object sender, EventArgs e)
+ {
+ _requestReplyMessenger.Stop();
+ OnDisconnected();
+ }
+
+ #endregion
+
+ #region Event raising methods
+
+ /// <summary>
+ /// Raises Disconnected event.
+ /// </summary>
+ private void OnDisconnected()
+ {
+ var handler = Disconnected;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ScsServiceClientFactory.cs b/src/Scs/Communication/ScsServices/Service/ScsServiceClientFactory.cs
new file mode 100644
index 0000000..abbd955
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ScsServiceClientFactory.cs
@@ -0,0 +1,23 @@
+using Hik.Communication.Scs.Communication;
+using Hik.Communication.Scs.Communication.Messengers;
+using Hik.Communication.Scs.Server;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// This class is used to create service client objects that is used in server-side.
+ /// </summary>
+ internal static class ScsServiceClientFactory
+ {
+ /// <summary>
+ /// Creates a new service client object that is used in server-side.
+ /// </summary>
+ /// <param name="serverClient">Underlying server client object</param>
+ /// <param name="requestReplyMessenger">RequestReplyMessenger object to send/receive messages over serverClient</param>
+ /// <returns></returns>
+ public static IScsServiceClient CreateServiceClient(IScsServerClient serverClient, RequestReplyMessenger<IScsServerClient> requestReplyMessenger)
+ {
+ return new ScsServiceClient(serverClient, requestReplyMessenger);
+ }
+ }
+}
diff --git a/src/Scs/Communication/ScsServices/Service/ServiceClientEventArgs.cs b/src/Scs/Communication/ScsServices/Service/ServiceClientEventArgs.cs
new file mode 100644
index 0000000..deab72a
--- /dev/null
+++ b/src/Scs/Communication/ScsServices/Service/ServiceClientEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Hik.Communication.ScsServices.Service
+{
+ /// <summary>
+ /// Stores service client informations to be used by an event.
+ /// </summary>
+ public class ServiceClientEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Client that is associated with this event.
+ /// </summary>
+ public IScsServiceClient Client { get; private set; }
+
+ /// <summary>
+ /// Creates a new ServiceClientEventArgs object.
+ /// </summary>
+ /// <param name="client">Client that is associated with this event</param>
+ public ServiceClientEventArgs(IScsServiceClient client)
+ {
+ Client = client;
+ }
+ }
+}
diff --git a/src/Scs/Diagrams/ChannelsDiagram.cd b/src/Scs/Diagrams/ChannelsDiagram.cd
new file mode 100644
index 0000000..55ddc50
--- /dev/null
+++ b/src/Scs/Diagrams/ChannelsDiagram.cd
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Communication.Channels.CommunicationChannelBase" Collapsed="true">
+ <Position X="4" Y="0.75" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAIAQCAAIC4QACAAAAQAAAAgAAAAAAEAAgAAAgA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\CommunicationChannelBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Channels.Tcp.TcpCommunicationChannel" Collapsed="true">
+ <Position X="4" Y="1.75" Width="2" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAQAAAAgAAABAgIAAAAAAAAAAAAgAAAAAAMAAABgAQA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\Tcp\TcpCommunicationChannel.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Communication.Channels.ICommunicationChannel">
+ <Position X="0.5" Y="3.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAAAACAAAAgAAAAAAAAAAAAAAAAAAAEAAgAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\ICommunicationChannel.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.Scs.Communication.IMessenger">
+ <Position X="0.5" Y="0.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAQAAAIAQQACAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\IMessenger.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ConnListenerDiagram.cd b/src/Scs/Diagrams/ConnListenerDiagram.cd
new file mode 100644
index 0000000..b84ed96
--- /dev/null
+++ b/src/Scs/Diagrams/ConnListenerDiagram.cd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Communication.Channels.ConnectionListenerBase" Collapsed="true">
+ <Position X="3.75" Y="0.75" Width="2" />
+ <TypeIdentifier>
+ <HashCode>EAAAAACAACAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\ConnectionListenerBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Channels.Tcp.TcpConnectionListener" Collapsed="true">
+ <Position X="3.75" Y="1.75" Width="2" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>BAAAAQAAACAAAAACAAABAAAACAAAAAAAIAAAAEAAAQA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\Tcp\TcpConnectionListener.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Communication.Channels.IConnectionListener">
+ <Position X="0.5" Y="0.75" Width="3" />
+ <TypeIdentifier>
+ <HashCode>EAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Channels\IConnectionListener.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/EndPointsDiagram.cd b/src/Scs/Diagrams/EndPointsDiagram.cd
new file mode 100644
index 0000000..cf37040
--- /dev/null
+++ b/src/Scs/Diagrams/EndPointsDiagram.cd
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint">
+ <Position X="1.25" Y="1.25" Width="3.75" />
+ <TypeIdentifier>
+ <HashCode>AAACAAAAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\EndPoints\ScsEndPoint.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.EndPoints.Tcp.ScsTcpEndPoint">
+ <Position X="5.75" Y="1.25" Width="3" />
+ <InheritanceLine Type="Hik.Communication.Scs.Communication.EndPoints.ScsEndPoint" FixedFromPoint="true">
+ <Path>
+ <Point X="5" Y="1.875" />
+ <Point X="5.75" Y="1.875" />
+ </Path>
+ </InheritanceLine>
+ <TypeIdentifier>
+ <HashCode>AAACAAAAAAAAAAAAAACAAAAAAABAAAAAAAAAAAAAAEA=</HashCode>
+ <FileName>Communication\Scs\Communication\EndPoints\Tcp\ScsTcpEndPoint.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/MessageObjectsDiagram.cd b/src/Scs/Diagrams/MessageObjectsDiagram.cd
new file mode 100644
index 0000000..e7c64fd
--- /dev/null
+++ b/src/Scs/Diagrams/MessageObjectsDiagram.cd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="NameAndType">
+ <Class Name="Hik.Communication.Scs.Communication.Messages.ScsTextMessage">
+ <Position X="5" Y="3.5" Width="1.5" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\ScsTextMessage.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Messages.PingMessage">
+ <Position X="2.75" Y="3.5" Width="1.5" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\PingMessage.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Messages.ScsMessage">
+ <Position X="4.75" Y="1" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAgAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\ScsMessage.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Messages.ScsRawDataMessage">
+ <Position X="7.25" Y="3.5" Width="1.75" />
+ <TypeIdentifier>
+ <HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\ScsRawDataMessage.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Communication.Messages.IScsMessage">
+ <Position X="2.75" Y="1" Width="1.75" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAgAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\IScsMessage.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/RequestReplyMessengerDiagram.cd b/src/Scs/Diagrams/RequestReplyMessengerDiagram.cd
new file mode 100644
index 0000000..79a0471
--- /dev/null
+++ b/src/Scs/Diagrams/RequestReplyMessengerDiagram.cd
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger&lt;T&gt;">
+ <Position X="0.5" Y="3.75" Width="5.5" />
+ <Members>
+ <Method Name="Dispose" Hidden="true" />
+ <Property Name="LastReceivedMessageTime" Hidden="true" />
+ <Property Name="LastSentMessageTime" Hidden="true" />
+ <Property Name="Messenger" Hidden="true" />
+ <Method Name="Messenger_MessageReceived" Hidden="true" />
+ <Method Name="Messenger_MessageSent" Hidden="true" />
+ <Method Name="OnMessageReceived" Hidden="true" />
+ <Method Name="OnMessageSent" Hidden="true" />
+ <Method Name="RequestReplyMessenger" Hidden="true" />
+ <Property Name="WireProtocol" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ <Compartment Name="Events" Collapsed="true" />
+ </Compartments>
+ <NestedTypes>
+ <Class Name="Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger&lt;T&gt;.WaitingMessage" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>Communication\Scs\Communication\Messengers\RequestReplyMessenger.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Class>
+ <Enum Name="Hik.Communication.Scs.Communication.Messengers.RequestReplyMessenger&lt;T&gt;.WaitingMessageStates" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>Communication\Scs\Communication\Messengers\RequestReplyMessenger.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Enum>
+ </NestedTypes>
+ <TypeIdentifier>
+ <HashCode>ABAEABBgQDAAICYQACAAACQAAAAAAEIAIAAAAAAAAgg=</HashCode>
+ <FileName>Communication\Scs\Communication\Messengers\RequestReplyMessenger.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Communication.Messengers.IMessenger">
+ <Position X="0.5" Y="0.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAQAAAIAQQACAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messengers\IMessenger.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/RmiMessagesDiagram.cd b/src/Scs/Diagrams/RmiMessagesDiagram.cd
new file mode 100644
index 0000000..1e8fdfb
--- /dev/null
+++ b/src/Scs/Diagrams/RmiMessagesDiagram.cd
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeMessage">
+ <Position X="0.5" Y="2.5" Width="2.75" />
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAIACAAAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Communication\Messages\ScsRemoteInvokeMessage.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.ScsServices.Communication.Messages.ScsRemoteInvokeReturnMessage">
+ <Position X="3.5" Y="2.5" Width="3.5" />
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAEEAAAAAAAAAgAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Communication\Messages\ScsRemoteInvokeReturnMessage.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Messages.ScsMessage">
+ <Position X="2" Y="0.5" Width="2.75" />
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAgAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Messages\ScsMessage.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ScsClientDiagram.cd b/src/Scs/Diagrams/ScsClientDiagram.cd
new file mode 100644
index 0000000..42f4042
--- /dev/null
+++ b/src/Scs/Diagrams/ScsClientDiagram.cd
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Client.ScsClientBase" Collapsed="true">
+ <Position X="1" Y="4.75" Width="4" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ <Compartment Name="Properties" Collapsed="true" />
+ <Compartment Name="Events" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>CAQAAAIAQCABZCwQACAAAKQAAAAQAAIAAQEAAgAEQgA=</HashCode>
+ <FileName>Communication\Scs\Client\ScsClientBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="Hik.Communication.Scs.Client.Tcp.ScsTcpClient">
+ <Position X="1" Y="5.75" Width="4" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAQAAAA=</HashCode>
+ <FileName>Communication\Scs\Client\Tcp\ScsTcpClient.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Client.IConnectableClient">
+ <Position X="3.5" Y="0.5" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAAAAAAAQAgAAAAAAIAAAAAAAAAAAAAAAgAEAAA=</HashCode>
+ <FileName>Communication\Scs\Client\IConnectableClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.Scs.Client.IScsClient" Collapsed="true">
+ <Position X="2" Y="3.75" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Client\IScsClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.Scs.Communication.IMessenger">
+ <Position X="0.5" Y="0.5" Width="2.75" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAQAAAIAQQACAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\IMessenger.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ScsServerClientDiagram.cd b/src/Scs/Diagrams/ScsServerClientDiagram.cd
new file mode 100644
index 0000000..67c39cf
--- /dev/null
+++ b/src/Scs/Diagrams/ScsServerClientDiagram.cd
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Server.ScsServerClient" Collapsed="true">
+ <Position X="4" Y="3.5" Width="3" />
+ <TypeIdentifier>
+ <HashCode>CAQAAAIAQAAAICwQgCAAACQAAAAQAAAAAAEAAgAAAgA=</HashCode>
+ <FileName>Communication\Scs\Server\ScsServerClient.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Server.IScsServerClient">
+ <Position X="4" Y="0.5" Width="3" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAAAAAAAAAgAgAAAAAAAAAAAAAAAAAEAAgAAAAA=</HashCode>
+ <FileName>Communication\Scs\Server\IScsServerClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.Scs.Communication.IMessenger">
+ <Position X="0.5" Y="0.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAQAAAIAQQACAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\IMessenger.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ScsServerDiagram.cd b/src/Scs/Diagrams/ScsServerDiagram.cd
new file mode 100644
index 0000000..5a35b95
--- /dev/null
+++ b/src/Scs/Diagrams/ScsServerDiagram.cd
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Server.Tcp.ScsTcpServer">
+ <Position X="0.5" Y="4.5" Width="3.75" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAQAAAAAAAIAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Server\Tcp\ScsTcpServer.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="Hik.Communication.Scs.Server.ScsServerBase" Collapsed="true">
+ <Position X="0.5" Y="3.5" Width="3.75" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAGEIBAAAAKAAQAAAAAAAAAAAJAAAIAAAACA=</HashCode>
+ <FileName>Communication\Scs\Server\ScsServerBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Server.IScsServer">
+ <Position X="0.5" Y="0.5" Width="3.75" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAACAAAAAAACAAAAAAAAAAAAAAJAAAIAAAACA=</HashCode>
+ <FileName>Communication\Scs\Server\IScsServer.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ScsServiceClientDiagram.cd b/src/Scs/Diagrams/ScsServiceClientDiagram.cd
new file mode 100644
index 0000000..5cb9470
--- /dev/null
+++ b/src/Scs/Diagrams/ScsServiceClientDiagram.cd
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.ScsServices.Client.ScsServiceClient&lt;T&gt;" Collapsed="true">
+ <Position X="4.25" Y="2.25" Width="2" />
+ <TypeIdentifier>
+ <HashCode>QAQABAIAECEAQEgAAAgAAIAAAAAAABIAAAAAAgAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Client\ScsServiceClient.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Client.IConnectableClient">
+ <Position X="0.5" Y="0.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAAAAAAAQAgAAAAAAIAAAAAAAAAAAAAAAgAAAAA=</HashCode>
+ <FileName>Communication\Scs\Client\IConnectableClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.ScsServices.Client.IScsServiceClient&lt;T&gt;">
+ <Position X="4.25" Y="0.5" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Client\IScsServiceClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ScsServiceDiagram.cd b/src/Scs/Diagrams/ScsServiceDiagram.cd
new file mode 100644
index 0000000..6de8205
--- /dev/null
+++ b/src/Scs/Diagrams/ScsServiceDiagram.cd
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.ScsServices.Service.ScsServiceApplication" Collapsed="true">
+ <Position X="0.5" Y="3.25" Width="2.5" />
+ <NestedTypes>
+ <Class Name="Hik.Communication.ScsServices.Service.ScsServiceApplication.ServiceObject" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>Communication\ScsServices\Service\ScsServiceApplication.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Class>
+ </NestedTypes>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAGAABCIAACAAAQAAAAAAAAKAJAAAIDAAAAQ=</HashCode>
+ <FileName>Communication\ScsServices\Service\ScsServiceApplication.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.ScsServices.Service.IScsServiceApplication">
+ <Position X="0.5" Y="0.5" Width="4.25" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAJAAAICAAAAQ=</HashCode>
+ <FileName>Communication\ScsServices\Service\IScsServiceApplication.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/ServiceSideClientDiagram.cd b/src/Scs/Diagrams/ServiceSideClientDiagram.cd
new file mode 100644
index 0000000..db73465
--- /dev/null
+++ b/src/Scs/Diagrams/ServiceSideClientDiagram.cd
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.ScsServices.Service.ScsServiceClient" Collapsed="true">
+ <Position X="4" Y="0.75" Width="1.5" />
+ <TypeIdentifier>
+ <HashCode>AAQABAIAAAEgAAgAgAAAAAAAAAAAABAAAAAAAgAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Service\ScsServiceClient.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.ScsServices.Service.IScsServiceClient">
+ <Position X="0.5" Y="0.5" Width="3.25" />
+ <TypeIdentifier>
+ <HashCode>AAQAAAAAAAAAAAgAgAAAAAAAAAAAAAAAAAAAAgAAAAA=</HashCode>
+ <FileName>Communication\ScsServices\Service\IScsServiceClient.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Diagrams/WireProtocolsDiagram.cd b/src/Scs/Diagrams/WireProtocolsDiagram.cd
new file mode 100644
index 0000000..ab569c4
--- /dev/null
+++ b/src/Scs/Diagrams/WireProtocolsDiagram.cd
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
+ <Class Name="Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol" Collapsed="true">
+ <Position X="4.75" Y="0.5" Width="2.5" />
+ <NestedTypes>
+ <Class Name="Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocol.DeserializationAppDomainBinder" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>Communication\Scs\Communication\Protocols\BinarySerialization\BinarySerializationProtocol.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Class>
+ </NestedTypes>
+ <TypeIdentifier>
+ <HashCode>AACAAAACAAAABAABQQMAAIAAAAAACAAAAAAQAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Protocols\BinarySerialization\BinarySerializationProtocol.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="Hik.Communication.Scs.Communication.Protocols.BinarySerialization.BinarySerializationProtocolFactory" Collapsed="true">
+ <Position X="4.75" Y="2.25" Width="2.5" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Protocols\BinarySerialization\BinarySerializationProtocolFactory.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="Hik.Communication.Scs.Communication.Protocols.IScsWireProtocol">
+ <Position X="0.5" Y="0.5" Width="4" />
+ <TypeIdentifier>
+ <HashCode>AACAAAAAAAAABAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Protocols\IScsWireProtocol.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="Hik.Communication.Scs.Communication.Protocols.IScsWireProtocolFactory">
+ <Position X="0.5" Y="2.25" Width="4" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>Communication\Scs\Communication\Protocols\IScsWireProtocolFactory.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/Scs/Properties/AssemblyInfo.cs b/src/Scs/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6601ece
--- /dev/null
+++ b/src/Scs/Properties/AssemblyInfo.cs
@@ -0,0 +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("Scs")]
+[assembly: AssemblyDescription("Simple Client/Server Framework")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Halil ibrahim Kalkan")]
+[assembly: AssemblyProduct("Scs")]
+[assembly: AssemblyCopyright("")]
+[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("20dfc06b-5632-4956-beaf-a5e0bb126bb5")]
+
+// 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.1.0.1")]
+[assembly: AssemblyFileVersion("1.1.0.1")]
diff --git a/src/Scs/Scs.csproj b/src/Scs/Scs.csproj
new file mode 100644
index 0000000..66bfd66
--- /dev/null
+++ b/src/Scs/Scs.csproj
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{0DC81B09-3ABF-4BB3-8C08-4E8EE4432BDC}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Hik</RootNamespace>
+ <AssemblyName>Scs</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Debug\Scs.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>bin\Release\Scs.XML</DocumentationFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Collections\ThreadSafeSortedList.cs" />
+ <Compile Include="Communication\ScsServices\Client\IScsServiceClient.cs" />
+ <Compile Include="Communication\ScsServices\Client\ScsServiceClient.cs" />
+ <Compile Include="Communication\ScsServices\Client\ScsServiceClientBuilder.cs" />
+ <Compile Include="Communication\ScsServices\Communication\AutoConnectRemoteInvokeProxy.cs" />
+ <Compile Include="Communication\ScsServices\Communication\Messages\ScsRemoteException.cs" />
+ <Compile Include="Communication\ScsServices\Communication\Messages\ScsRemoteInvokeMessage.cs" />
+ <Compile Include="Communication\ScsServices\Communication\Messages\ScsRemoteInvokeReturnMessage.cs" />
+ <Compile Include="Communication\ScsServices\Communication\RemoteInvokeProxy.cs" />
+ <Compile Include="Communication\Scs\Communication\Messengers\RequestReplyMessenger.cs" />
+ <Compile Include="Communication\ScsServices\Service\IScsServiceApplication.cs" />
+ <Compile Include="Communication\ScsServices\Service\IScsServiceClient.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsService.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsServiceApplication.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsServiceAttribute.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsServiceBuilder.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsServiceClient.cs" />
+ <Compile Include="Communication\ScsServices\Service\ScsServiceClientFactory.cs" />
+ <Compile Include="Communication\ScsServices\Service\ServiceClientEventArgs.cs" />
+ <Compile Include="Communication\Scs\Client\ClientReConnecter.cs" />
+ <Compile Include="Communication\Scs\Client\IConnectableClient.cs" />
+ <Compile Include="Communication\Scs\Client\IScsClient.cs" />
+ <Compile Include="Communication\Scs\Client\ScsClientBase.cs" />
+ <Compile Include="Communication\Scs\Client\ScsClientFactory.cs" />
+ <Compile Include="Communication\Scs\Client\Tcp\ScsTcpClient.cs" />
+ <Compile Include="Communication\Scs\Client\Tcp\TcpHelper.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\CommunicationChannelBase.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\CommunicationChannelEventArgs.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\ConnectionListenerBase.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\ICommunicationChannel.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\IConnectionListener.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\Tcp\TcpCommunicationChannel.cs" />
+ <Compile Include="Communication\Scs\Communication\Channels\Tcp\TcpConnectionListener.cs" />
+ <Compile Include="Communication\Scs\Communication\CommunicationStateException.cs" />
+ <Compile Include="Communication\Scs\Communication\CommunicationStates.cs" />
+ <Compile Include="Communication\Scs\Communication\CommunicationException.cs" />
+ <Compile Include="Communication\Scs\Communication\EndPoints\ScsEndPoint.cs" />
+ <Compile Include="Communication\Scs\Communication\EndPoints\Tcp\ScsTcpEndPoint.cs" />
+ <Compile Include="Communication\Scs\Communication\Messengers\IMessenger.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\IScsMessage.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\MessageEventArgs.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\PingMessage.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\ScsMessage.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\ScsRawDataMessage.cs" />
+ <Compile Include="Communication\Scs\Communication\Messages\ScsTextMessage.cs" />
+ <Compile Include="Communication\Scs\Communication\Protocols\BinarySerialization\BinarySerializationProtocol.cs" />
+ <Compile Include="Communication\Scs\Communication\Protocols\BinarySerialization\BinarySerializationProtocolFactory.cs" />
+ <Compile Include="Communication\Scs\Communication\Protocols\IScsWireProtocol.cs" />
+ <Compile Include="Communication\Scs\Communication\Protocols\IScsWireProtocolFactory.cs" />
+ <Compile Include="Communication\Scs\Communication\Protocols\WireProtocolManager.cs" />
+ <Compile Include="Communication\Scs\Communication\Messengers\SynchronizedMessenger.cs" />
+ <Compile Include="Communication\Scs\Server\IScsServer.cs" />
+ <Compile Include="Communication\Scs\Server\IScsServerClient.cs" />
+ <Compile Include="Communication\Scs\Server\ScsServerBase.cs" />
+ <Compile Include="Communication\Scs\Server\ScsServerClient.cs" />
+ <Compile Include="Communication\Scs\Server\ScsServerFactory.cs" />
+ <Compile Include="Communication\Scs\Server\ScsServerManager.cs" />
+ <Compile Include="Communication\Scs\Server\ServerClientEventArgs.cs" />
+ <Compile Include="Communication\Scs\Server\Tcp\ScsTcpServer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Threading\SequentialItemProcessor.cs" />
+ <Compile Include="Threading\Timer.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Diagrams\ChannelsDiagram.cd" />
+ <None Include="Diagrams\ConnListenerDiagram.cd" />
+ <None Include="Diagrams\EndPointsDiagram.cd" />
+ <None Include="Diagrams\MessageObjectsDiagram.cd" />
+ <None Include="Diagrams\RequestReplyMessengerDiagram.cd" />
+ <None Include="Diagrams\RmiMessagesDiagram.cd" />
+ <None Include="Diagrams\ScsClientDiagram.cd" />
+ <None Include="Diagrams\ScsServerClientDiagram.cd" />
+ <None Include="Diagrams\ScsServerDiagram.cd" />
+ <None Include="Diagrams\ScsServiceClientDiagram.cd" />
+ <None Include="Diagrams\ScsServiceDiagram.cd" />
+ <None Include="Diagrams\ServiceSideClientDiagram.cd" />
+ <None Include="Diagrams\WireProtocolsDiagram.cd" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Changes.txt" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/Scs/Threading/SequentialItemProcessor.cs b/src/Scs/Threading/SequentialItemProcessor.cs
new file mode 100644
index 0000000..185aae1
--- /dev/null
+++ b/src/Scs/Threading/SequentialItemProcessor.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Hik.Threading
+{
+ /// <summary>
+ /// This class is used to process items sequentially in a multithreaded manner.
+ /// </summary>
+ /// <typeparam name="TItem">Type of item to process</typeparam>
+ public class SequentialItemProcessor<TItem>
+ {
+ #region Private fields
+
+ /// <summary>
+ /// The method delegate that is called to actually process items.
+ /// </summary>
+ private readonly Action<TItem> _processMethod;
+
+ /// <summary>
+ /// Item queue. Used to process items sequentially.
+ /// </summary>
+ private readonly Queue<TItem> _queue;
+
+ /// <summary>
+ /// A reference to the current Task that is processing an item in
+ /// ProcessItem method.
+ /// </summary>
+ private Task _currentProcessTask;
+
+ /// <summary>
+ /// Indicates state of the item processing.
+ /// </summary>
+ private bool _isProcessing;
+
+ /// <summary>
+ /// A boolean value to control running of SequentialItemProcessor.
+ /// </summary>
+ private bool _isRunning;
+
+ /// <summary>
+ /// An object to synchronize threads.
+ /// </summary>
+ private readonly object _syncObj = new object();
+
+ #endregion
+
+ #region Constructor
+
+ /// <summary>
+ /// Creates a new SequentialItemProcessor object.
+ /// </summary>
+ /// <param name="processMethod">The method delegate that is called to actually process items</param>
+ public SequentialItemProcessor(Action<TItem> processMethod)
+ {
+ _processMethod = processMethod;
+ _queue = new Queue<TItem>();
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Adds an item to queue to process the item.
+ /// </summary>
+ /// <param name="item">Item to add to the queue</param>
+ public void EnqueueMessage(TItem item)
+ {
+ //Add the item to the queue and start a new Task if needed
+ lock (_syncObj)
+ {
+ if (!_isRunning)
+ {
+ return;
+ }
+
+ _queue.Enqueue(item);
+
+ if (!_isProcessing)
+ {
+ _currentProcessTask = Task.Factory.StartNew(ProcessItem);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Starts processing of items.
+ /// </summary>
+ public void Start()
+ {
+ _isRunning = true;
+ }
+
+ /// <summary>
+ /// Stops processing of items and waits stopping of current item.
+ /// </summary>
+ public void Stop()
+ {
+ _isRunning = false;
+
+ //Clear all incoming messages
+ lock (_syncObj)
+ {
+ _queue.Clear();
+ }
+
+ //Check if is there a message that is being processed now
+ if (!_isProcessing)
+ {
+ return;
+ }
+
+ //Wait current processing task to finish
+ try
+ {
+ _currentProcessTask.Wait();
+ }
+ catch
+ {
+
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// This method runs on a new seperated Task (thread) to process
+ /// items on the queue.
+ /// </summary>
+ private void ProcessItem()
+ {
+ //Try to get an item from queue to process it.
+ TItem itemToProcess;
+ lock (_syncObj)
+ {
+ if (!_isRunning || _isProcessing)
+ {
+ return;
+ }
+
+ if (_queue.Count <= 0)
+ {
+ return;
+ }
+
+ _isProcessing = true;
+ itemToProcess = _queue.Dequeue();
+ }
+
+ //Process the item (by calling the _processMethod delegate)
+ _processMethod(itemToProcess);
+
+ //Process next item if available
+ lock (_syncObj)
+ {
+ _isProcessing = false;
+ if (!_isRunning || _queue.Count <= 0)
+ {
+ return;
+ }
+
+ //Start a new task
+ _currentProcessTask = Task.Factory.StartNew(ProcessItem);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Scs/Threading/Timer.cs b/src/Scs/Threading/Timer.cs
new file mode 100644
index 0000000..331f6e7
--- /dev/null
+++ b/src/Scs/Threading/Timer.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Threading;
+
+namespace Hik.Threading
+{
+ /// <summary>
+ /// This class is a timer that performs some tasks periodically.
+ /// </summary>
+ public class Timer
+ {
+ #region Public events
+
+ /// <summary>
+ /// This event is raised periodically according to Period of Timer.
+ /// </summary>
+ public event EventHandler Elapsed;
+
+ #endregion
+
+ #region Public fields
+
+ /// <summary>
+ /// Task period of timer (as milliseconds).
+ /// </summary>
+ public int Period { get; set; }
+
+ /// <summary>
+ /// Indicates whether timer raises Elapsed event on Start method of Timer for once.
+ /// Default: False.
+ /// </summary>
+ public bool RunOnStart { get; set; }
+
+ #endregion
+
+ #region Private fields
+
+ /// <summary>
+ /// This timer is used to perfom the task at spesified intervals.
+ /// </summary>
+ private readonly System.Threading.Timer _taskTimer;
+
+ /// <summary>
+ /// Indicates that whether timer is running or stopped.
+ /// </summary>
+ private volatile bool _running;
+
+ /// <summary>
+ /// Indicates that whether performing the task or _taskTimer is in sleep mode.
+ /// This field is used to wait executing tasks when stopping Timer.
+ /// </summary>
+ private volatile bool _performingTasks;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Creates a new Timer.
+ /// </summary>
+ /// <param name="period">Task period of timer (as milliseconds)</param>
+ public Timer(int period)
+ : this(period, false)
+ {
+
+ }
+
+ /// <summary>
+ /// Creates a new Timer.
+ /// </summary>
+ /// <param name="period">Task period of timer (as milliseconds)</param>
+ /// <param name="runOnStart">Indicates whether timer raises Elapsed event on Start method of Timer for once</param>
+ public Timer(int period, bool runOnStart)
+ {
+ Period = period;
+ RunOnStart = runOnStart;
+ _taskTimer = new System.Threading.Timer(TimerCallBack, null, Timeout.Infinite, Timeout.Infinite);
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Starts the timer.
+ /// </summary>
+ public void Start()
+ {
+ _running = true;
+ _taskTimer.Change(RunOnStart ? 0 : Period, Timeout.Infinite);
+ }
+
+ /// <summary>
+ /// Stops the timer.
+ /// </summary>
+ public void Stop()
+ {
+ lock (_taskTimer)
+ {
+ _running = false;
+ _taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ }
+ }
+
+ /// <summary>
+ /// Waits the service to stop.
+ /// </summary>
+ public void WaitToStop()
+ {
+ lock (_taskTimer)
+ {
+ while (_performingTasks)
+ {
+ Monitor.Wait(_taskTimer);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ /// <summary>
+ /// This method is called by _taskTimer.
+ /// </summary>
+ /// <param name="state">Not used argument</param>
+ private void TimerCallBack(object state)
+ {
+ lock (_taskTimer)
+ {
+ if (!_running || _performingTasks)
+ {
+ return;
+ }
+
+ _taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ _performingTasks = true;
+ }
+
+ try
+ {
+ if (Elapsed != null)
+ {
+ Elapsed(this, new EventArgs());
+ }
+ }
+ catch
+ {
+
+ }
+ finally
+ {
+ lock (_taskTimer)
+ {
+ _performingTasks = false;
+ if (_running)
+ {
+ _taskTimer.Change(Period, Timeout.Infinite);
+ }
+
+ Monitor.Pulse(_taskTimer);
+ }
+ }
+ }
+
+ #endregion
+ }
+}