tag:blogger.com,1999:blog-51961035822411375782024-03-10T10:04:34.547+01:00eneter.netLightweight framework for interprocess communicationOndrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.comBlogger58125tag:blogger.com,1999:blog-5196103582241137578.post-4037417375357981042020-12-26T18:26:00.000+01:002020-12-26T18:26:47.524+01:00Eneter goes Open-SourceEneter has transformed to the open-source project.
Therefore, the source code for all platforms including accessory libraries (like special serializers and Secure Remote Password protocol) is now available under the MIT license on the GitHub portal here:
<ul>
<li><i>Eneter for .NET platforms</i> - <a href="https://github.com/ng-eneter/eneter-net">https://github.com/ng-eneter/eneter-net</a></li>
<li><i>Eneter for Java platforms</i> - <a href="https://github.com/ng-eneter/eneter-java">https://github.com/ng-eneter/eneter-java</a></li>
<li><i>Eneter for HTML5 javascript</i> - <a href="https://github.com/ng-eneter/eneter-javascript">https://github.com/ng-eneter/eneter-javascript</a></li>
</ul>
Projects for particular Eneter related accessories can be found here:
<ul>
<li><i>Protocol Buffers Serializer</i> - <a href="https://github.com/ng-eneter/eneter-protobuf">https://github.com/ng-eneter/eneter-protobuf</a></li>
<li><i>Secure Remote Password Authentication</i> - <a href="https://github.com/ng-eneter/eneter-srp">https://github.com/ng-eneter/eneter-srp</a></li>
<li><i>Fast Json Serializer</i> - <a href="https://https://github.com/ng-eneter/eneter-jsonnet">https://github.com/ng-eneter/eneter-jsonnet</a></li>
<li><i>Gson Serializer</i> - <a href="https://https://github.com/ng-eneter/eneter-gson">https://https://github.com/ng-eneter/eneter-gson</a></li>
</ul>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-82587730571846914942016-06-21T21:49:00.002+02:002020-05-24T19:29:26.995+02:00Authenticated and Encrypted RPCThis example shows how to implement Remote Procedure Calls which are authenticated and encrypted individually for each user and connection session.<br />
The example also shows how to retrieve the user name from within the called method.<br />
<br />
<a name='more'></a>The example can be downloaded <a href="http://eneter.net/Downloads/Examples/SRPAuthenticationForRPC.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
This is a simple example showing how to implement a client-service communication using RPC (Remote Procedure Call) which is authenticated and encrypted for each connected user and session (one user can have multiple connections at the same time).</div>
<div>
The authentication is based on <a href="http://srp.stanford.edu/whatisit.html">SRP (Secure Remote Password) protocol</a>.</div>
<div>
<br /></div>
<h4>
To Run Example</h4>
<div>
<ol style="background-color: white; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13.2px; line-height: 18.48px;">
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="http://eneter.net/Downloads/Examples/SRPAuthenticationForRPC.zip" style="color: #888888; text-decoration: none;">Download this example</a> and open it in Visual Studio.</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="http://www.eneter.net/ProductDownload.htm" style="color: #888888; text-decoration: none;">Download Eneter Messaging Framework for .NET platforms</a> or get the <a href="https://www.nuget.org/packages/Eneter.Messaging.Framework/">nuget package</a>.<br />(If your Visual Studio supports Nuget packages then it will be downloaded automatically when you compile.)</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="http://www.eneter.net/Downloads/Extensions/EneterSecureRemotePassword/EneterSecureRemotePassword100.zip" style="color: #888888; text-decoration: none;">Download Eneter Secure Remote Password</a> or get the <a href="https://www.nuget.org/packages/Eneter.SecureRemotePassword/" style="color: #888888; text-decoration: none;">nuget package</a>.<br /><span style="font-size: 13.2px; line-height: 18.48px;">(If your Visual Studio supports Nuget packages then it will be downloaded automatically when you compile.)</span></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">Compile projects and run the service and then the client application.</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">Login with the name Peter and the password pwd123.</li>
</ol>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNGLq0-oFZrKX_dsjbfADgOKfwjoARnTlWLXfHorFmChI5hagmnpJU-iUfjJft50CEAIdGK1bIwjedcaFKrZCj_ZoRpW85JmN83vl6fEYDqoz0l5eZOFycqQ6NwLEUC-hdVdDFrue3o6rk/s1600/AuthenticatedRpcClient.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNGLq0-oFZrKX_dsjbfADgOKfwjoARnTlWLXfHorFmChI5hagmnpJU-iUfjJft50CEAIdGK1bIwjedcaFKrZCj_ZoRpW85JmN83vl6fEYDqoz0l5eZOFycqQ6NwLEUC-hdVdDFrue3o6rk/s320/AuthenticatedRpcClient.png" width="320" /></a></div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;"><br /></span></span>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;"><br /></span></span>
<br />
<ol style="background-color: white; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13.2px; line-height: 18.48px;">
</ol>
<h3>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;">Service Application</span></span></h3>
</div>
<div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;">The service is a simple console application which uses RPC to expose an interface and uses the SRP protocol to authenticate connecting clients. Then once the client is authenticated it uses the calculated secret key to encrypt the communication. The key is unique for each connection.</span></span></div>
<div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;">The service implementation also shows how to get the name of the user who calls the remote method. See the method Sum in the Calculator class.</span></span></div>
<div>
<pre name="code">using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.Diagnostic;
using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.SecureRemotePassword;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading;
namespace Service
{
// Interface declaring the RPC service.
public interface ICalculator
{
double Sum(double a, double b);
}
// Implementation of the RPC service.
internal class Calculator : ICalculator
{
public double Sum(double a, double b)
{
double aResult = a + b;
// Example how to get a user name from within the method.
// Note: it must be called from the same thread as
// this method was originally called.
string aUserName = SrpAuthentication.GetUserName();
// Didplay results.
Console.WriteLine("{0}: {1} + {2} = {3}", aUserName, a, b, aResult);
return aResult;
}
}
// Simulates database of users.
internal static class UserDb
{
// Reperesents user authentication data stored in DB.
public class User
{
public User(string userName, byte[] salt, byte[] verifier)
{
UserName = userName;
Salt = salt;
Verifier = verifier;
}
public string UserName { get; private set; }
public byte[] Salt { get; private set; }
public byte[] Verifier { get; private set; }
}
private static HashSet<User> myUsers = new HashSet<User>();
public static void CreateUser(string userName, string password)
{
// Generate the random salt.
byte[] s = SRP.s();
// Compute private key from password nad salt.
byte[] x = SRP.x(password, s);
// Compute verifier.
byte[] v = SRP.v(x);
// Store user name, salt and the verifier.
// Note: do not store password nor the private key in database!
User aUser = new User(userName, s, v);
lock (myUsers)
{
myUsers.Add(aUser);
}
}
public static User GetUser(string userName)
{
lock (myUsers)
{
User aUser = myUsers.FirstOrDefault(x => x.UserName == userName);
return aUser;
}
}
}
// Encapsulates the SRP authentication.
internal static class SrpAuthentication
{
// Connection context for each connected client.
private class ConnectionContext
{
public ConnectionContext(string responseReceiverId, string userName)
{
ResponseReceiverId = responseReceiverId;
UserName = userName;
ThreadId = -1;
}
// Identifies the connection session.
public string ResponseReceiverId { get; private set; }
// Identifies the thread which is right now handling the request.
public int ThreadId { get; set; }
// Login name.
public string UserName { get; private set; }
// SRP values used during the authentication process.
public byte[] K { get; set; }
public byte[] A { get; set; }
public byte[] B { get; set; }
public byte[] s { get; set; }
// Serializer to serialize/deserialize messages once
// the authenticated connection is established.
// It uses the session key (calculated during RSP authentication)
// to encrypt/decrypt messages.
public ISerializer Serializer { get; set; }
}
// List of connected clients.
private static List<ConnectionContext> myConnections = new List<ConnectionContext>();
// Returns SRP response for login request.
public static object GetLoginResponseMessage(
string responseReceiverId, object loginRequestMessage)
{
// Deserialize the login request.
ISerializer aSerializer = new BinarySerializer();
LoginRequestMessage aLoginRequest =
aSerializer.Deserialize<LoginRequestMessage>(loginRequestMessage);
// Try to find the user in database.
UserDb.User aUser = UserDb.GetUser(aLoginRequest.UserName);
if (aUser != null &&
SRP.IsValid_A(aLoginRequest.A))
{
// Generate random service private ephemeral value.
byte[] b = SRP.b();
// Calculate service public ephemeral value.
byte[] B = SRP.B(b, aUser.Verifier);
// Calculate random scrambling value.
byte[] u = SRP.u(aLoginRequest.A, B);
// Calculate session key.
byte[] K = SRP.K_Service(aLoginRequest.A, aUser.Verifier, u, b);
// Prepare response message for the client.
// Note: client is then supposed to calculate the session key
// and send back the message proving it was able to calculate
// the same session key.
LoginResponseMessage aLoginResponse = new LoginResponseMessage();
aLoginResponse.s = aUser.Salt; // user salt
aLoginResponse.B = B; // service public ephemeral value
object aLoginResponseMessage =
aSerializer.Serialize<LoginResponseMessage>(aLoginResponse);
// Store the connection context.
ConnectionContext aConnection = new ConnectionContext(responseReceiverId, aUser.UserName);
aConnection.A = aLoginRequest.A;
aConnection.B = B;
aConnection.K = K;
aConnection.s = aUser.Salt;
lock (myConnections)
{
myConnections.Add(aConnection);
}
// Send the response to the client.
return aLoginResponseMessage;
}
// The client will be disconnected.
return null;
}
// Checks if the connecting client was able to calculate the same
// session key as the service.
// If the user entered an incorrect password the calculation
// will be different.
public static bool Authenticate(string responseReceiverId, object M1)
{
ConnectionContext aConnection;
lock (myConnections)
{
aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == responseReceiverId);
}
if (aConnection != null)
{
// Proving message from the client.
byte[] aClientM1 = (byte[])M1;
// Service calculates the proving message too.
byte[] aServiceM1 = SRP.M1(aConnection.A, aConnection.B, aConnection.K);
// If both messages are equql then it means the client proved its identity
// and the connection can be established.
if (aServiceM1.SequenceEqual(aClientM1))
{
// Create serializer which will encrypt the communication.
Rfc2898DeriveBytes anRfc = new Rfc2898DeriveBytes(aConnection.K, aConnection.s, 1000);
ISerializer aSerializer = new AesSerializer(new BinarySerializer(), anRfc, 256);
// Store serializer which will encrypt using the calculated key.
aConnection.Serializer = aSerializer;
// Clean properties which are not needed anymore.
aConnection.A = null;
aConnection.B = null;
aConnection.K = null;
aConnection.s = null;
return true;
}
lock (myConnections)
{
myConnections.RemoveAll(
x => x.ResponseReceiverId == responseReceiverId);
}
}
return false;
}
// Cancel the authentication sequense.
public static void CancelAuthentication(string responseReceiverId)
{
lock (myConnections)
{
myConnections.RemoveAll(x => x.ResponseReceiverId == responseReceiverId);
}
}
// Removes the connection.
public static void CloseConnection(string responseReceiverId)
{
lock (myConnections)
{
ConnectionContext aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == responseReceiverId);
if (aConnection != null)
{
myConnections.Remove(aConnection);
}
}
}
// Returns user name for the specific response receiver id.
public static string GetUserName(string responseReceiverId)
{
string aUserName = "";
lock (myConnections)
{
ConnectionContext aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == responseReceiverId);
if (aConnection != null)
{
aUserName = aConnection.UserName;
}
}
return aUserName;
}
// Returns user name for the current thread.
public static string GetUserName()
{
string aUserName = "";
lock (myConnections)
{
ConnectionContext aConnection = myConnections.FirstOrDefault(
x => x.ThreadId == Thread.CurrentThread.ManagedThreadId);
if (aConnection != null)
{
aUserName = aConnection.UserName;
}
}
return aUserName;
}
// This method is called when the RPC service needs to serialize or deserialize
// request/response for the particular user and connection.
public static ISerializer GetConnectionSpecificSerializer(string responseReceiverId)
{
ConnectionContext aUserContext;
lock (myConnections)
{
aUserContext = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == responseReceiverId);
}
if (aUserContext != null)
{
// Store also the thread id so that it is possible to identify a user
// from within the RPC method.
// Note: this is a workaround which will be resolved in a future Eneter release.
aUserContext.ThreadId = Thread.CurrentThread.ManagedThreadId;
// Return the connection specific serializer.
return aUserContext.Serializer;
}
throw new InvalidOperationException("Failed to get serializer for the given connection.");
}
}
class Program
{
static void Main(string[] args)
{
// Display Eneter errors and warnings on the console.
//EneterTrace.TraceLog = Console.Out;
// Simulate database of users.
UserDb.CreateUser("Peter", "pwd123");
UserDb.CreateUser("Frank", "pwd456");
try
{
// Instantiate class which provides the service.
ICalculator aCalculator = new Calculator();
// Create RPC service.
IRpcFactory aFactory = new RpcFactory()
{
// Note: this allows to encrypt/decrypt messages for each client
// individualy based on calculated session key.
SerializerProvider = OnGetSerializer
};
IRpcService<ICalculator> aRpcService =
aFactory.CreateSingleInstanceService<ICalculator>(aCalculator);
// Use TCP for the communication.
IMessagingSystemFactory aUnderlyingMessaging =
new TcpMessagingSystemFactory(new EasyProtocolFormatter());
// Use communication which is authenticated via SRP.
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(aUnderlyingMessaging,
OnGetLoginResponseMessage,
OnAuthenticate,
OnAuthenticationCancelled);
// Crete input channel and attach it to the receiver to start listening.
IDuplexInputChannel aInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8033/");
aInputChannel.ResponseReceiverConnected += OnClientConnected;
aInputChannel.ResponseReceiverDisconnected += OnClientDisconnected;
// Attach inout channel to the RPC service and start listning.
aRpcService.AttachDuplexInputChannel(aInputChannel);
Console.WriteLine("RPC service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach input channel to stop the listening thread.
aRpcService.DetachDuplexInputChannel();
}
catch (Exception err)
{
EneterTrace.Error("RPC Service failed.", err);
}
}
private static object OnGetLoginResponseMessage(string channelId,
string responseReceiverId, object loginRequestMessage)
{
return SrpAuthentication.GetLoginResponseMessage(responseReceiverId, loginRequestMessage);
}
private static bool OnAuthenticate(string channelId, string responseReceiverId,
object login, object handshakeMessage, object M1)
{
return SrpAuthentication.Authenticate(responseReceiverId, M1);
}
private static void OnAuthenticationCancelled(
string channelId, string responseReceiverId, object loginMessage)
{
SrpAuthentication.CancelAuthentication(responseReceiverId);
}
private static void OnClientConnected(object sender, ResponseReceiverEventArgs e)
{
string aUserName = SrpAuthentication.GetUserName(e.ResponseReceiverId);
Console.WriteLine(aUserName + " is logged in.");
}
// Remove the connection context if the client disconnects once the connection
// was established after the successful authentication.
private static void OnClientDisconnected(object sender, ResponseReceiverEventArgs e)
{
string aUserName = SrpAuthentication.GetUserName(e.ResponseReceiverId);
SrpAuthentication.CloseConnection(e.ResponseReceiverId);
Console.WriteLine(aUserName + " is logged out.");
}
// It is called by MultiTypedReceiver whenever it sends or receive a message from a connected client.
// It returns the serializer for the particular connection (which uses the agreed session key).
private static ISerializer OnGetSerializer(string responseReceiverId)
{
return SrpAuthentication.GetConnectionSpecificSerializer(responseReceiverId);
}
}
}
</pre>
</div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;"><br /></span></span>
<br />
<h3>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;">Client Application</span></span></h3>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13.2px; line-height: 18.48px;">The client is a simple winform application which provides UI for login. Then when connecting the service it uses the SRP protocol to authenticate. If the authentication is successful it uses the calculated secret key to encrypt the communication. </span>
<br />
<div>
<pre name="code">using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.Diagnostic;
using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
using Eneter.SecureRemotePassword;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
namespace WindowsFormClient
{
public partial class Form1 : Form
{
// Interface declaring the RPC service.
public interface ICalculator
{
double Sum(double a, double b);
}
// Encapsulates the SRP authentication for client.
private class SrpClientAuthentication
{
private LoginRequestMessage myLoginRequest;
private byte[] myPrivateKey_a;
private ISerializer mySerializer;
// It is called by the AuthenticationMessaging to get the login message.
public object GetLoginRequestMessage(string userName)
{
myPrivateKey_a = SRP.a();
byte[] A = SRP.A(myPrivateKey_a);
myLoginRequest = new LoginRequestMessage();
myLoginRequest.UserName = userName;
myLoginRequest.A = A;
// Serializer to serialize LoginRequestMessage.
ISerializer aSerializer = new BinarySerializer();
object aSerializedLoginRequest = aSerializer.Serialize<LoginRequestMessage>(myLoginRequest);
// Send the login request to start negotiation about the session key.
return aSerializedLoginRequest;
}
// It is called by the AuthenticationMessaging to handle the LoginResponseMessage received
// from the service.
public object GetProveMessage(
string userPassword, object loginResponseMessage)
{
// Deserialize LoginResponseMessage.
ISerializer aSerializer = new BinarySerializer();
LoginResponseMessage aLoginResponse =
aSerializer.Deserialize<LoginResponseMessage>(loginResponseMessage);
// Calculate scrambling parameter.
byte[] u = SRP.u(myLoginRequest.A, aLoginResponse.B);
if (SRP.IsValid_B_u(aLoginResponse.B, u))
{
// Calculate user private key.
byte[] x = SRP.x(userPassword, aLoginResponse.s);
// Calculate the session key which will be used for the encryption.
// Note: if everything is then this key will be the same as on the service side.
byte[] K = SRP.K_Client(aLoginResponse.B, x, u, myPrivateKey_a);
// Create serializer which will encrypt the communication.
Rfc2898DeriveBytes anRfc = new Rfc2898DeriveBytes(K, aLoginResponse.s, 1000);
mySerializer = new AesSerializer(new BinarySerializer(), anRfc, 256);
// Create M1 message to prove that the client has the correct session key.
byte[] M1 = SRP.M1(myLoginRequest.A, aLoginResponse.B, K);
return M1;
}
// Close the connection with the service.
return null;
}
// It is called whenever the client sends or receives the message from the service.
// It will return the serializer which serializes/deserializes messages using
// the connection password.
public ISerializer GetSerializer()
{
return mySerializer;
}
}
private SrpClientAuthentication mySrpAuthentication = new SrpClientAuthentication();
private IRpcClient<ICalculator> myRpcClient;
public Form1()
{
InitializeComponent();
EnableUiControls(false);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
IMessagingSystemFactory anUnderlyingMessaging =
new TcpMessagingSystemFactory(new EasyProtocolFormatter());
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(anUnderlyingMessaging,
OnGetLoginRequestMessage,
OnGetProveMessage)
{
// Timeout for the authentication.
// If the value is -1 then it is infinite (e.g. for debugging purposses)
AuthenticationTimeout = TimeSpan.FromMilliseconds(30000)
};
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8033/");
anOutputChannel.ConnectionClosed += OnConnectionClosed;
IRpcFactory aFactory = new RpcFactory()
{
SerializerProvider = OnGetSerializer
};
myRpcClient = aFactory.CreateClient<ICalculator>();
try
{
// Attach output channel and be able to call RPC.
myRpcClient.AttachDuplexOutputChannel(anOutputChannel);
EnableUiControls(true);
}
catch
{
MessageBox.Show("Incorrect user name or password.",
"Login Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// It is called if the service closes the connection.
private void OnConnectionClosed(object sender, DuplexChannelEventArgs e)
{
// It does not have to be invoked in the main UI thread.
// So in order to manipulate UI controls dispatch the call
// to the main UI thread.
if (InvokeRequired)
{
Action aCloseConnection = CloseConnection;
Invoke(aCloseConnection, null);
}
else
{
CloseConnection();
}
}
private void CloseConnection()
{
// Detach output channel and release the thread listening to responses.
if (myRpcClient != null && myRpcClient.IsDuplexOutputChannelAttached)
{
myRpcClient.DetachDuplexOutputChannel();
}
EnableUiControls(false);
}
private void EnableUiControls(bool isLoggedIn)
{
LoginTextBox.Enabled = !isLoggedIn;
PasswordTextBox.Enabled = !isLoggedIn;
LoginBtn.Enabled = !isLoggedIn;
LogoutBtn.Enabled = isLoggedIn;
Number1TextBox.Enabled = isLoggedIn;
Number2TextBox.Enabled = isLoggedIn;
CalculateBtn.Enabled = isLoggedIn;
ResultTextBox.Enabled = isLoggedIn;
}
// It is called by the AuthenticationMessaging to get the login message.
private object OnGetLoginRequestMessage(string channelId, string responseReceiverId)
{
string aUserName = LoginTextBox.Text;
return mySrpAuthentication.GetLoginRequestMessage(aUserName);
}
// It is called by the AuthenticationMessaging to handle the LoginResponseMessage received
// from the service.
private object OnGetProveMessage(
string channelId, string responseReceiverId, object loginResponseMessage)
{
string aUserPassword = PasswordTextBox.Text;
return mySrpAuthentication.GetProveMessage(aUserPassword, loginResponseMessage);
}
// It is called whenever the client sends or receives the message from the service.
// It will return the serializer which serializes/deserializes messages using
// the connection password.
private ISerializer OnGetSerializer(string responseReceiverId)
{
return mySrpAuthentication.GetSerializer();
}
private void CalculateBtn_Click(object sender, EventArgs e)
{
// Create message.
double a = double.Parse(Number1TextBox.Text);
double b = double.Parse(Number2TextBox.Text);
double aResult = myRpcClient.Proxy.Sum(a, b);
ResultTextBox.Text = aResult.ToString();
}
private void LoginBtn_Click(object sender, EventArgs e)
{
OpenConnection();
}
private void LogoutBtn_Click(object sender, EventArgs e)
{
CloseConnection();
}
}
}
</pre>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com4tag:blogger.com,1999:blog-5196103582241137578.post-86809916909065932142016-05-22T15:50:00.000+02:002016-05-22T15:54:40.292+02:00Xamarin: Simple Client Service CommunicationA very simple example showing how to implement a client-service communication between Xamarin Android client and a .NET service.<br />
<a name='more'></a><br />
The example can be downloaded <a href="http://eneter.net/Downloads/Examples/XamarinCalculator.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
This is a simple example showing how to implement a client-service communication between Android and .NET using Eneter for Xamarin. The service is a simple .NET application which calculates two numbers and the client is a simple Xamarin application which communicates with the service to calculate numbers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93q8Kjzw-U_fOZSH6KoTmaQbseHBAryN7TkejTFfRbua65GFdF0KuIeWm-Bq6sZIts4ccRTFwGYeKbGVJjd8RVOE5sxcH_iper2Beb2UE-lAf6CHZxMYlz5f0_KyoV8vfZ7QDxhkKhNQJ/s1600/XamarinCalculatorClient.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93q8Kjzw-U_fOZSH6KoTmaQbseHBAryN7TkejTFfRbua65GFdF0KuIeWm-Bq6sZIts4ccRTFwGYeKbGVJjd8RVOE5sxcH_iper2Beb2UE-lAf6CHZxMYlz5f0_KyoV8vfZ7QDxhkKhNQJ/s1600/XamarinCalculatorClient.png" /></a></div>
<br />
<br />
<h4>
To Run Example</h4>
<ol>
<li><a href="http://eneter.net/Downloads/Examples/XamarinCalculator.zip">Download this example</a>.</li>
<li>Open the solution in Visual Studio.</li>
<li>If your Visual Studio supports Nuget then just compile projects within the solution and Eneter libraries will be downloaded automatically.<br />If the Nuget is not supported then <a href="http://www.eneter.net/ProductDownload.htm">download and unzip Eneter Messaging Framework</a> for .NET platforms and update references in the CalculatorService project to <span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.dll</span> (for .NET 4.5) and in the AndroidCalculatorClient project to <span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.AndroidXamarin.dll</span>.</li>
<li>Run CalculatorService.</li>
<li>Run AndroidCalculatorClient - the emulator will start.</li>
</ol>
The example uses the emulator. If you want to use it on a real device you need to figure out the IP address which is assigned to the computer where you want to run the service.<br />
Then you need to modify the code in both client and service applications and use that IP address instead of currently used which are valid only for the emulator.<br />
<br />
<h3>
Xamarin Client</h3>
The client is a very simple Xamarin based Android application which provides UI controls to enter two numbers and the calculation button.<br />
If the button is pressed the application sends the message to the service. Then once the service returns the result it displays it on the screen.<br />
The whole communication is based on Eneter Messaging Framework. The Xamarin code can link <span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.XamarinAndroid.dll</span> to access the communication functionality provided by Eneter.<br />
<br />
The whole code is very simple:<br />
<pre class="brush: csharp">using Android.App;
using Android.OS;
using Android.Widget;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
using System;
namespace AndroidCalculatorClient
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
[Activity(Label = "AndroidCalculatorClient", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
// UI widgets.
private EditText myNumber1EditText;
private EditText myNumber2EditText;
private TextView myResultTextView;
private Button myCalculateBtn;
private Handler myUiThreadDispatcher = new Handler();
// Communication
private IDuplexTypedMessageSender<ResponseMessage, RequestMessage> mySender;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
myNumber1EditText = FindViewById<EditText>(Resource.Id.Number1EditText);
myNumber2EditText = FindViewById<EditText>(Resource.Id.Number2EditText);
myResultTextView = FindViewById<TextView>(Resource.Id.ResultTextView);
myCalculateBtn = FindViewById<Button>(Resource.Id.CalculateBtn);
myCalculateBtn.Click += OnCalculateBtnClick;
OpenConnection();
}
protected override void OnDestroy()
{
CloseConnection();
base.OnDestroy();
}
private void OpenConnection()
{
// Create message sender.
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory();
mySender = aSenderFactory.CreateDuplexTypedMessageSender<ResponseMessage, RequestMessage>();
mySender.ResponseReceived += OnResponseReceived;
// Create TCP messaging for the communication.
// Note: 10.0.2.2 is a special address for the Android emulator.
// If the emulator opens connection to 10.0.2.2 then it opens
// the connection to 127.0.0.1 on the machine where the emulator
// is running.
TcpMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory()
{
// Ensure incoming response messages are routed into
// the main UI thread.
OutputChannelThreading = new AndroidDispatching(myUiThreadDispatcher)
};
IDuplexOutputChannel aOutputChannel =
// When running on a real device please
// provide the IP address of the service here.
aMessaging.CreateDuplexOutputChannel("tcp://10.0.2.2:8060/");
// Atach output channel and be able to send messages and receive responses.
mySender.AttachDuplexOutputChannel(aOutputChannel);
}
private void CloseConnection()
{
// Detach the output channel and release the thread listening
// to response messages.
mySender.DetachDuplexOutputChannel();
}
private void OnCalculateBtnClick(object sender, EventArgs e)
{
// Send the calculation request to the service.
RequestMessage aRequest = new RequestMessage();
aRequest.Number1 = int.Parse(myNumber1EditText.Text);
aRequest.Number2 = int.Parse(myNumber2EditText.Text);
mySender.SendRequestMessage(aRequest);
}
// It is called when the result is received from the service.
private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<ResponseMessage> e)
{
// Display incoming result.
myResultTextView.Text = e.ResponseMessage.Result.ToString();
}
}
}
</pre>
<br />
<h3>
.NET Service</h3>
The service is a simple console application which uses Eneter Messaging Framework to listen for incoming requests. Once a message is received it calculates two numbers and sends back the result.<br />
<br />
Here is the whole implementation:<br />
<pre class="brush: csharp">using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using System;
namespace CalculatorService
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Create message receiver.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage> aReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>();
// Subscribe to process request messages.
aReceiver.MessageReceived += OnMessageReceived;
// Use TCP for the communication.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
// If you use a real android device please provide the IP address
// which is assigned to your computer within the network here.
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8060/");
// Attach the input channel to the receiver and start listening.
aReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The calculator service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel to stop listening.
aReceiver.DetachDuplexInputChannel();
}
private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<RequestMessage> e)
{
// Calculate numbers.
ResponseMessage aResponseMessage = new ResponseMessage();
aResponseMessage.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("{0} + {1} = {2}", e.RequestMessage.Number1, e.RequestMessage.Number2, aResponseMessage.Result);
// Send back the response message.
var aReceiver = (IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>)sender;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
</pre>
<br />Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com4tag:blogger.com,1999:blog-5196103582241137578.post-6526520676034548712016-03-29T13:45:00.002+02:002016-04-25T05:16:20.613+02:00Discovering Service within NetworkA simple example showing how to implement a mechanism allowing clients to connect a service within a network if clients do not know the service address.<br />
<a name='more'></a>The example can be downloaded from <a href="http://www.eneter.net/Downloads/Examples/ServiceDiscovery.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow implements a client-service communication where the client needs to connect a service but it does not know the service address. Therefore before connecting the client needs a mechanism to find the service address out. The example bellow demonstrates this mechanism using UDP multicast messaging. <br />
<br /></div>
<h4>
To Run Example</h4>
<div>
<ol>
<li><a href="http://www.eneter.net/Downloads/Examples/ServiceDiscovery.zip">Download this example</a>.</li>
<li>Open the ServiceDiscovery solution in Visual Studio.</li>
<li>If your Visual Studio supports Nuget then just compile projects within the solution.<br />(Eneter library will be downloaded automatically from the nuget.org server.)<br />Otherwise <a href="http://www.eneter.net/ProductDownload.htm">download and unzip Eneter Messaging Framework</a> for .NET platforms and update references to Eneter.Messaging.Framework.dll in Visual Studio projects.</li>
<li>Run DiscoverableService.</li>
<li>Run CalculatorClient.</li>
</ol>
<br /><ol>
</ol>
<h3>
UDP Multicast Messaging</h3>
</div>
<div>
The UDP protocol supports unicast, multicast and broadcast messaging. The unicast messaging is routing a message (datagram) to one particular host. The multicast messaging is routing a message to set of hosts (i.e. hosts which are registered within the particular multicast group). And broadcast messaging is routing a message to all hosts.</div>
<div>
The capability of sending one message to multiple recipients at the same time can be effectively used to find out the service address within the network. If a client needs to connect the service first it can send a broadcast or a multicast UDP message into the network requesting the service address. The service (running on some device within the network) can so receive that request and send back its address. The received address can be then used by the client to open the connection with the service.</div>
<div>
<br /></div>
<div>
In order to optimize the overhead on hosts which do not provide the searched service it is preferred to use multicast instead of broadcast messaging.</div>
<div>
In case of UDP multicast messaging the receiver needs to join a mulitcast group which is an IP address from the range 224.0.0.0 to 239.255.255.255 (the range from 224.0.0.0 - 224.0.0.255 is reserved for low-level routing protocol and you should not use it). By joining that multicast group the host sets its network interface to receive frames sent to that multicast IP address. It means if e.g. some process joins the multicast group 234.4.5.6 the host sets its network interface to receive and handle frames which are sent to the IP address 234.4.5.6. So if somebody then sends a message (UDP datagram) to the IP address 234.4.5.6 it is sent across the network and handled by hosts which has joined that group (and ignored by hosts which has not joined that group).</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXu9QR5cnG6WoyV4Tek0-Xn4BB5VIQDAQhei4J0jRExJNxvxduk9zqPX_QPQkqbiqieUnGwyvMnwK-6-P0TopUl8pwcFRPAbTBKF5cGqmyUzKvzXvuRvrItZUZLN2Ws4d1JM9an8HtZvlr/s1600/DiscoverableService.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="386" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXu9QR5cnG6WoyV4Tek0-Xn4BB5VIQDAQhei4J0jRExJNxvxduk9zqPX_QPQkqbiqieUnGwyvMnwK-6-P0TopUl8pwcFRPAbTBKF5cGqmyUzKvzXvuRvrItZUZLN2Ws4d1JM9an8HtZvlr/s400/DiscoverableService.png" width="400" /></a></div>
<br />
<br /></div>
<h3>
Service Application</h3>
<div>
The service application is a simple console application providing the 'rendezvous' service and the simple calculation service.</div>
<div>
The rendezvous service listens to the UDP multicast group 234.4.5.6 and when it receives a request message it sends back the IP address and the port of the calculation service. When the client receives the address it can then open the connection to the calculation service and use it to calculate numbers.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.MessagingSystems.UdpMessagingSystem;
using System;
namespace DiscoverableService
{
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
public class ResponseMessage
{
public int Result { get; set; }
}
class Program
{
private static string myServiceId = "My.Calculator.Service";
private static string myServiceAddress = "tcp://127.0.0.1:8044/";
private static IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage> myServiceReceiver;
private static IDuplexTypedMessageReceiver<string, string> myRendezvousReceiver;
static void Main(string[] args)
{
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
// Create service to calculate numbers.
// Note: This service will be possible to discover.
myServiceReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>();
myServiceReceiver.MessageReceived += OnServiceMessageReceived;
TcpMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel aServiceInputChannel =
aTcpMessaging.CreateDuplexInputChannel(myServiceAddress);
myServiceReceiver.AttachDuplexInputChannel(aServiceInputChannel);
Console.WriteLine("Calculator service is listening to " + myServiceAddress);
// Create the rendezvous service which receives requests to provide
// the TCP address address of the calculator service.
// It listens to the UDP multicast messages. Therefore everybody who needs
// to connect the calculator service can just send the multicat message into
// the network. The rendezvous service will receive it and sends
// back the TCP address of the calculator service.
myRendezvousReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<string, string>();
myRendezvousReceiver.MessageReceived += OnRendezvousMessageReceived;
UdpMessagingSystemFactory aUdpMessaging = new UdpMessagingSystemFactory(new EasyProtocolFormatter())
{
// The communication will be multicast
UnicastCommunication = false,
// This multicast group shall be joined.
MulticastGroupToReceive = "234.4.5.6"
};
// Start listen to 127.0.0.1:8045 as well as to the configured
// multicast group 234.4.5.6 on the port 8045.
IDuplexInputChannel aRendezvousInputChannel =
aUdpMessaging.CreateDuplexInputChannel("udp://127.0.0.1:8045/");
myRendezvousReceiver.AttachDuplexInputChannel(aRendezvousInputChannel);
Console.WriteLine("Rendezvous service is listening.");
Console.WriteLine("Press ENTER to stop.");
Console.ReadLine();
myRendezvousReceiver.DetachDuplexInputChannel();
myServiceReceiver.DetachDuplexInputChannel();
}
// It is called when a client requests the rendezvous service to provide the TCP address.
static void OnRendezvousMessageReceived(object sender,
TypedRequestReceivedEventArgs<string> e)
{
if (e.RequestMessage == myServiceId)
{
myRendezvousReceiver.SendResponseMessage(e.ResponseReceiverId, myServiceAddress);
}
}
// It is called when a client requests to calculate numbers.
private static void OnServiceMessageReceived(object sender,
TypedRequestReceivedEventArgs<RequestMessage> e)
{
ResponseMessage aResponseMessage = new ResponseMessage();
aResponseMessage.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
myServiceReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
</pre>
</div>
<h3>
Client Application</h3>
<div>
The client application is a simple WinForm application which sends the request message to the UDP multicast group 234.4.5.6 and waits until the rendezvous service returns the IP address and the port for the calculation service. Then it uses the received address to connect directly the calculation service.</div>
<div>
<br /></div>
<div>
The whole implementation is here:<br />
<br /></div>
<div>
<pre class="brush: csharp">using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.MessagingSystems.UdpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
using System;
using System.Windows.Forms;
namespace CalculatorClientSync
{
public partial class Form1 : Form
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
private IDuplexTypedMessageSender<ResponseMessage, RequestMessage> mySender;
public Form1()
{
InitializeComponent();
OpenConnection();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory()
{
// Timeout for synchrouse requests.
SyncResponseReceiveTimeout = TimeSpan.FromMilliseconds(5000)
};
// Create UDP client which uses UDP multicast message to retrieve
// the TCP address of the calculator service.
ISyncDuplexTypedMessageSender<string, string> aRendezvousSender =
aSenderFactory.CreateSyncDuplexTypedMessageSender<string, string>();
UdpMessagingSystemFactory aUdpMessaging =
new UdpMessagingSystemFactory(new EasyProtocolFormatter())
{
UnicastCommunication = false
};
// Create output channel which sends messages to the multicast group.
IDuplexOutputChannel aUdpOutputChannel =
aUdpMessaging.CreateDuplexOutputChannel("udp://234.4.5.6:8045/");
aRendezvousSender.AttachDuplexOutputChannel(aUdpOutputChannel);
// Send the request message to the multicast group
// to retrieve the TCP address of the calculator service.
// Once the message reaches the rendezvous service (listening to
// the same multicast group) it will response the TCP address of the service.
// If the resposne does not come wihtin the specified timeout (5 seconds)
// the timeout exception is thrown.
string aCalculatorServiceAddress = null;
try
{
aCalculatorServiceAddress =
aRendezvousSender.SendRequestMessage("My.Calculator.Service");
}
finally
{
// Rendezvous service is not needed anymore.
// So detach the output channel and release the thread lisening
// to response messages.
aRendezvousSender.DetachDuplexOutputChannel();
}
Console.WriteLine("Service address: " + aCalculatorServiceAddress);
// Connect the calculator service on the received TCP address.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory()
{
// Response messages will be routed to the main UI thread.
OutputChannelThreading = new WinFormsDispatching(this)
};
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel(aCalculatorServiceAddress);
// Attach the output channel and be able to send messages
// and receive response messages.
mySender =
aSenderFactory.CreateDuplexTypedMessageSender<ResponseMessage, RequestMessage>();
mySender.ResponseReceived += OnResponseFromCalculatorReceived;
mySender.AttachDuplexOutputChannel(anOutputChannel);
}
private void CloseConnection()
{
// Detach input channel and stop listening to response messages.
mySender.DetachDuplexOutputChannel();
}
private void CalculateBtn_Click(object sender, EventArgs e)
{
// Create the request message.
RequestMessage aRequest = new RequestMessage();
aRequest.Number1 = int.Parse(Number1TextBox.Text);
aRequest.Number2 = int.Parse(Number2TextBox.Text);
// Send request to the service to calculate 2 numbers.
mySender.SendRequestMessage(aRequest);
}
private void OnResponseFromCalculatorReceived(object sender,
TypedResponseReceivedEventArgs<ResponseMessage> e)
{
// Display received result.
ResultTextBox.Text = e.ResponseMessage.Result.ToString();
}
}
}
</pre>
</div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com0tag:blogger.com,1999:blog-5196103582241137578.post-84284669158493955692016-03-05T19:07:00.000+01:002016-03-05T19:07:03.261+01:00Converting Android Projects from Eclipse to Android StudioStep by step procedure how to convert Android projects from Eclipse to Android Studio.<br />
<br />
<a name='more'></a><br />
So far all Eneter Android examples which are published on this blog are created in the Eclipse IDE. It means if you download an Android example you will find an Eclipse project for it.<br />
However the official IDE for Android applications became Android Studio. Therefore here is a step by step guide how to convert projects from Eclipse to Android Studio.<br />
<br />
<ol>
<li>Start Android Studio.</li>
<li>From main menu choose: <span style="font-family: "courier new" , "courier" , monospace;">File/New/Import Project...</span></li>
<li>Browse to the directory with the Eclipse Android project you want to convert and press OK.</li>
<li>The window '<span style="font-family: "courier new" , "courier" , monospace;">Import Project from ADT (Eclipse Android)</span>' is open. Just press Finish to continue.</li>
<li>Android Studio will start to convert the project.<br />When the converting ends and you see an error like: '<span style="font-family: "courier new" , "courier" , monospace;">Failed to sync Gradle project</span>' it is probably because the Android SDK which is setup inside the project is not installed on your machine (e.g. it is too old (e.g. SDK version 7) and you do not use it for your development).</li>
<li>To fix that issue you need to setup an SDK version you have installed:
<ol>
<li>Click on the '<span style="font-family: "courier new" , "courier" , monospace;">Project</span>' tab-card on the left side.</li>
<li>Choose the '<span style="font-family: "courier new" , "courier" , monospace;">Project</span>' view from the combo-box located in the upper-left corner.</li>
<li>Navigate inside 'app' and open <span style="font-family: "courier new" , "courier" , monospace;">build.gradle</span> file.</li>
<li>Change <span style="font-family: "courier new" , "courier" , monospace;">compileSdkVersion</span> e.g. to 23</li>
<li>Change <span style="font-family: "courier new" , "courier" , monospace;">minSdkVersion</span> e.g. to 10</li>
<li>Change <span style="font-family: "courier new" , "courier" , monospace;">targetSdkVersion</span> e.g. to 23
<br /><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgitXbH3wa5pwMaObGe9JkCN-5z7oRibRP-T3JglI5w07_kJ5FAXdMvilqbF5i9yXmbvwBtwkcqpryBIy4jjZkfCboFbWgVBKoVJE3qBsMH6b89o_uEy5KfopvQvDaSXatw-NFCg0Ko8Zo5/s1600/ImportProjectFromEclipse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgitXbH3wa5pwMaObGe9JkCN-5z7oRibRP-T3JglI5w07_kJ5FAXdMvilqbF5i9yXmbvwBtwkcqpryBIy4jjZkfCboFbWgVBKoVJE3qBsMH6b89o_uEy5KfopvQvDaSXatw-NFCg0Ko8Zo5/s400/ImportProjectFromEclipse.png" width="400" /></a></div>
<br /><br />
</li>
</ol>
</li>
<li>To add the eneter library into the project you need to copy the eneter-messaging-android library into <span style="font-family: "courier new" , "courier" , monospace;">app/libs</span> directory. Then choose: <span style="font-family: "courier new" , "courier" , monospace;">File/ProjectStructure.../app/Dependencies</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYT8QQs1EIbfsI1RNH_YfKt1F3ngvDhLgH6Cl1ocOuPIel6cO-zBaNUNAtrGdYecKiRKSfa13tHfidBNEemj-Mwg6VO6ZpmwccZtzenPrM1CE1C-i7oaorpaDoWirvydZAAPO8IM5OEPc_/s1600/ProjectStructure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYT8QQs1EIbfsI1RNH_YfKt1F3ngvDhLgH6Cl1ocOuPIel6cO-zBaNUNAtrGdYecKiRKSfa13tHfidBNEemj-Mwg6VO6ZpmwccZtzenPrM1CE1C-i7oaorpaDoWirvydZAAPO8IM5OEPc_/s400/ProjectStructure.png" width="400" /></a></div>
<br /><br />
</li>
<li>Click on + icon on right-top and choose <span style="font-family: "courier new" , "courier" , monospace;">File Dependency</span>. Go into <span style="font-family: "courier new" , "courier" , monospace;">libs</span> directory and select the eneter library and press the OK button.<br /><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7HBDYCNC7WYhiw05q0BE9T7wWl17u1cLM0B4cGI6pRSIQ5Nhl2B2DX30hVH8tyNc60z7R4bGb3LJGZcD2bGQ1OovRIyZ4rIh1r0HXU7NqLDDA_NnFoWv1G3Z8uN7GOPg_QRxIVAdIOOn2/s1600/ProjectStructure2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7HBDYCNC7WYhiw05q0BE9T7wWl17u1cLM0B4cGI6pRSIQ5Nhl2B2DX30hVH8tyNc60z7R4bGb3LJGZcD2bGQ1OovRIyZ4rIh1r0HXU7NqLDDA_NnFoWv1G3Z8uN7GOPg_QRxIVAdIOOn2/s400/ProjectStructure2.png" width="400" /></a></div>
<br />
</li>
<li>The library is added in the project and you should be able to compile the code.</li>
</ol>
<div>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com0tag:blogger.com,1999:blog-5196103582241137578.post-61601964017956029092016-02-27T19:46:00.000+01:002016-03-05T13:01:13.886+01:00Communication using Secure Remote Password protocolSimple example showing how to implement secured communication using the SRP protocol.<br />
<a name='more'></a>The source code for this example can be found <a href="http://eneter.net/Downloads/Examples/MultiTyped_Authentication.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates how to secure the interprocess communication using the <a href="http://srp.stanford.edu/whatisit.html">Secure Remote Password protocol</a> (SRP). The example implements a simple client-service communication where the client needs to authenticate (user name + password) before consuming the service. Once the authentication is complete the further communication is encrypted with the strong key which was calculated during the SRP sequence and which is unique for each connection.</div>
<h4>
To Run Example</h4>
<div>
<ol>
<li><a href="http://eneter.net/Downloads/Examples/MultiTyped_Authentication.zip">Download this example</a> and open it in Visual Studio.</li>
<li><a href="http://www.eneter.net/ProductDownload.htm">Download Eneter Messaging Framework for .NET platforms</a> or get the nuget package.</li>
<li><a href="http://www.eneter.net/Downloads/Extensions/EneterSecureRemotePassword/EneterSecureRemotePassword100.zip">Download Eneter Secure Remote Password</a> or get the <a href="https://www.nuget.org/packages/Eneter.SecureRemotePassword/">nuget package</a>.</li>
<li>Compile projects and run the service and then the client application.</li>
<li>Login with the name Peter and the password pwd123.</li>
</ol>
<h3>
Secure Remote Password</h3>
<div>
SRP is a protocol which was created by Thomas Wu at Stanford University to allow the secure authentication based on a user name and a password.<br />
The protocol is robust i.e. tolerates wide range of attacks, preventing an attack on any part
or parts of the system from leading to further security
compromises.<br />
It does not require any trusted third party (e.g. a certificate issuer or PKI) which makes it very comfortable to use.<br />
For technical details please refer to <a href="http://srp.stanford.edu/">SRP home page</a> or <a href="https://www.isoc.org/isoc/conferences/ndss/98/wu.pdf">detailed SRP paper</a> or <a href="http://srp.stanford.edu/design.html">protocol summary</a>.<br />
<br />
The following diagram shows how the SRP sequence is implemented in this example:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirf3ht3-cyV8G2ijg7fP0aOQUm4AI55CDmKSY8HinkHfmx5P-McRNFDMQXRFZMaHtzbwmb3N6eN05E7USyTjmHeXVQqtR7CX6ONafWqLWiGTFP30mD5OScZyebIzfeXM3I47fAHqd1-ixs/s1600/SrpAuthenticationSequence.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirf3ht3-cyV8G2ijg7fP0aOQUm4AI55CDmKSY8HinkHfmx5P-McRNFDMQXRFZMaHtzbwmb3N6eN05E7USyTjmHeXVQqtR7CX6ONafWqLWiGTFP30mD5OScZyebIzfeXM3I47fAHqd1-ixs/s640/SrpAuthenticationSequence.png" width="426" /></a><br />
<br />
<br />
<h3>
Eneter.SecureRemotePassword</h3>
<div>
Eneter.SecureRemotePassword is the lightweight library which implements SRP formulas and exposes API to implement the SRP authentication. The API naming convention matches with the SRP specification so it should be intuitive to use in particular SRP steps.</div>
<br />
The interprocess communication is ensured by Eneter Messaging Framework which also provides <a href="http://www.eneter.net/OnlineHelp/EneterMessagingFramework/html/T_Eneter_Messaging_MessagingSystems_Composites_AuthenticatedConnection_AuthenticatedMessagingFactory.htm">AuthenticatedMessagingFactory</a> which allows to implement any custom authentication e.g. the authentication using the SRP protocol.<br />
<br />
<h3>
Service Application</h3>
</div>
<div>
The service is a simple console application which exposes services to calculate numbers. It uses the SRP to authenticate each connected client. The connection is established only in case the client provides the correct user name and password. The entire communication is then encrypted using AES.<br />
<br />
When a client requests to login a user the <span style="font-family: "courier new" , "courier" , monospace;">OnGetLoginResponseMessage</span> method is called. It finds the user in the database and generates secret and public ephemeral values of the service and then calculates the session key. Then it returns the message which contains the service public ephemeral value and the user random salt.<br />
<br />
When the client sends the M1 message to prove it knows the password the <span style="font-family: "courier new" , "courier" , monospace;">OnAuthenticate</span> method is called. The service calculates its own M1 and compares it with the received one. If equal the client is considered authenticated.<br />
<br /></div>
<div>
The whole implementation is very simple:<br />
<br /></div>
<div>
<pre class="brush: csharp">using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.Diagnostic;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.SecureRemotePassword;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace Service
{
[Serializable]
public class CalculateRequestMessage
{
public double Number1 { get; set; }
public double Number2 { get; set; }
}
[Serializable]
public class CalculateResponseMessage
{
public double Result { get; set; }
}
class Program
{
private class User
{
public User (string userName, byte[] salt, byte[] verifier)
{
UserName = userName;
Salt = salt;
Verifier = verifier;
}
public string UserName { get; private set; }
public byte[] Salt { get; private set; }
public byte[] Verifier { get; private set; }
}
// Simulates user database.
private static HashSet<User> myUsers = new HashSet<User>();
// Connection context for each connected client.
private class ConnectionContext
{
public ConnectionContext(string responseReceiverId, string userName)
{
ResponseReceiverId = responseReceiverId;
UserName = userName;
}
// Identifies the connection session.
public string ResponseReceiverId { get; private set; }
// Login name.
public string UserName { get; private set; }
// SRP values used during the authentication process.
public byte[] K { get; set; }
public byte[] A { get; set; }
public byte[] B { get; set; }
public byte[] s { get; set; }
// Serializer to serialize/deserialize messages once
// the authenticated connection is established.
// It uses the session key (calculated during RSP authentication)
// to encrypt/decrypt messages.
public ISerializer Serializer { get; set; }
}
// List of connected clients.
private static List<ConnectionContext> myConnections =
new List<ConnectionContext>();
static void Main(string[] args)
{
// Simulate database of users.
CreateUser("Peter", "pwd123");
CreateUser("Frank", "pwd456");
try
{
// Create multi-typed receiver.
// Note: this receiver can receive multiple types of messages.
IMultiTypedMessagesFactory aFactory = new MultiTypedMessagesFactory()
{
// Note: this allows to encrypt/decrypt messages
// for each client individualy
// based on calculated session key.
SerializerProvider = OnGetSerializer
};
IMultiTypedMessageReceiver aReceiver =
aFactory.CreateMultiTypedMessageReceiver();
// Register types of messages which can be processed by the receiver.
aReceiver.RegisterRequestMessageReceiver<CalculateRequestMessage>(OnCalculateRequest);
aReceiver.RegisterRequestMessageReceiver<int>(OnFactorialRequest);
// Use TCP for the communication.
IMessagingSystemFactory anUnderlyingMessaging =
new TcpMessagingSystemFactory(new EasyProtocolFormatter());
// Use authenticated communication.
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(anUnderlyingMessaging,
OnGetLoginResponseMessage, OnAuthenticate, OnAuthenticationCancelled);
// Crete input channel and attach it to the receiver to start listening.
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8033/");
anInputChannel.ResponseReceiverConnected += OnClientConnected;
anInputChannel.ResponseReceiverDisconnected += OnClientDisconnected;
aReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("Service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach input channel to stop the listening thread.
aReceiver.DetachDuplexInputChannel();
}
catch (Exception err)
{
EneterTrace.Error("Service failed.", err);
}
}
// It is called by AuthenticationMessaging to process the login request
// from the client.
private static object OnGetLoginResponseMessage(string channelId,
string responseReceiverId, object loginRequestMessage)
{
// Deserialize the login request.
ISerializer aSerializer = new BinarySerializer();
LoginRequestMessage aLoginRequest =
aSerializer.Deserialize<LoginRequestMessage>(loginRequestMessage);
// Try to find the user in database.
User aUser = GetUser(aLoginRequest.UserName);
if (aUser != null &&
SRP.IsValid_A(aLoginRequest.A))
{
// Generate random service private ephemeral value.
byte[] b = SRP.b();
// Calculate service public ephemeral value.
byte[] B = SRP.B(b, aUser.Verifier);
// Calculate random scrambling value.
byte[] u = SRP.u(aLoginRequest.A, B);
// Calculate session key.
byte[] K = SRP.K_Service(aLoginRequest.A, aUser.Verifier, u, b);
// Prepare response message for the client.
// Note: client is then supposed to calculate the session key
// and send back the message proving it was able to
// calculate the same session key.
LoginResponseMessage aLoginResponse = new LoginResponseMessage();
aLoginResponse.s = aUser.Salt; // user salt
aLoginResponse.B = B; // service public ephemeral value
object aLoginResponseMessage =
aSerializer.Serialize<LoginResponseMessage>(aLoginResponse);
// Store the connection context.
ConnectionContext aConnection =
new ConnectionContext(responseReceiverId, aUser.UserName);
aConnection.A = aLoginRequest.A;
aConnection.B = B;
aConnection.K = K;
aConnection.s = aUser.Salt;
lock (myConnections)
{
myConnections.Add(aConnection);
}
// Send the response to the client.
return aLoginResponseMessage;
}
// The client will be disconnected.
return null;
}
// It is called by AuthenticationMessaging to process the message from the client
// which shall prove the user provided the correct password and so the client was
// able to calculate the same session key as the service.
private static bool OnAuthenticate(string channelId, string responseReceiverId,
object login, object handshakeMessage, object M1)
{
ConnectionContext aConnection;
lock (myConnections)
{
aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == responseReceiverId);
}
if (aConnection != null)
{
// Proving message from the client.
byte[] aClientM1 = (byte[])M1;
// Service calculates the proving message too.
byte[] aServiceM1 = SRP.M1(aConnection.A, aConnection.B, aConnection.K);
// If both messages are equql then it means the client proved its identity
// and the connection can be established.
if (aServiceM1.SequenceEqual(aClientM1))
{
// Create serializer.
Rfc2898DeriveBytes anRfc =
new Rfc2898DeriveBytes(aConnection.K, aConnection.s, 1000);
ISerializer aSerializer =
new AesSerializer(new BinarySerializer(true), anRfc, 256);
// Store serializer which will encrypt using the calculated key.
aConnection.Serializer = aSerializer;
// Clean properties which are not needed anymore.
aConnection.A = null;
aConnection.B = null;
aConnection.K = null;
aConnection.s = null;
return true;
}
}
lock (myConnections)
{
myConnections.RemoveAll(x => x.ResponseReceiverId == responseReceiverId);
}
return false;
}
// Remove the connection context if the client disconnects during
// the authentication sequence.
private static void OnAuthenticationCancelled(
string channelId, string responseReceiverId, object loginMessage)
{
lock (myConnections)
{
myConnections.RemoveAll(x => x.ResponseReceiverId == responseReceiverId);
}
}
private static void OnClientConnected(object sender, ResponseReceiverEventArgs e)
{
string aUserName = "";
lock (myConnections)
{
ConnectionContext aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == e.ResponseReceiverId);
if (aConnection != null)
{
aUserName = aConnection.UserName;
}
}
Console.WriteLine(aUserName + " is logged in.");
}
// Remove the connection context if the client disconnects once the connection
// was established after the successful authentication.
private static void OnClientDisconnected(object sender, ResponseReceiverEventArgs e)
{
string aUserName = "";
lock (myConnections)
{
ConnectionContext aConnection = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == e.ResponseReceiverId);
aUserName = aConnection.UserName;
myConnections.Remove(aConnection);
}
Console.WriteLine(aUserName + " is logged out.");
}
// It is called by MultiTypedReceiver whenever it sends or receive a message
// from a connected client.
// It returns the serializer for the particular connection
// (which uses the agreed session key).
private static ISerializer OnGetSerializer(string responseReceiverId)
{
ConnectionContext aUserContext;
lock (myConnections)
{
aUserContext = myConnections.FirstOrDefault(x => x.ResponseReceiverId == responseReceiverId);
}
if (aUserContext != null)
{
return aUserContext.Serializer;
}
throw new InvalidOperationException("Failed to get serializer for the given connection.");
}
// It handles the request message from the client to calculate two numbers.
private static void OnCalculateRequest(
Object eventSender, TypedRequestReceivedEventArgs<CalculateRequestMessage> e)
{
ConnectionContext aUserContext;
lock (myConnections)
{
aUserContext = myConnections.FirstOrDefault(
x => x.ResponseReceiverId == e.ResponseReceiverId);
}
double aResult = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("User: " + aUserContext.UserName
+ " -> " + e.RequestMessage.Number1
+ " + " + e.RequestMessage.Number2 + " = " + aResult);
// Send back the result.
IMultiTypedMessageReceiver aReceiver = (IMultiTypedMessageReceiver)eventSender;
try
{
CalculateResponseMessage aResponse = new CalculateResponseMessage()
{
Result = aResult
};
aReceiver.SendResponseMessage<CalculateResponseMessage>(e.ResponseReceiverId, aResponse);
}
catch (Exception err)
{
EneterTrace.Error("Failed to send the response message.", err);
}
}
// It handles the request message from the client to calculate the factorial.
private static void OnFactorialRequest(Object eventSender, TypedRequestReceivedEventArgs<int> e)
{
ConnectionContext aUserContext;
lock (myConnections)
{
aUserContext = myConnections.FirstOrDefault(x => x.ResponseReceiverId == e.ResponseReceiverId);
}
int aResult = 1;
for (int i = 1; i < e.RequestMessage; ++i)
{
aResult *= i;
}
Console.WriteLine("User: " + aUserContext.UserName + " -> " + e.RequestMessage + "! = " + aResult);
// Send back the result.
IMultiTypedMessageReceiver aReceiver = (IMultiTypedMessageReceiver)eventSender;
try
{
aReceiver.SendResponseMessage<int>(e.ResponseReceiverId, aResult);
}
catch (Exception err)
{
EneterTrace.Error("Failed to send the response message.", err);
}
}
private static void CreateUser(string userName, string password)
{
// Generate the random salt.
byte[] s = SRP.s();
// Compute private key from password nad salt.
byte[] x = SRP.x(password, s);
// Compute verifier.
byte[] v = SRP.v(x);
// Store user name, salt and the verifier.
// Note: do not store password nor the private key!
User aUser = new User(userName, s, v);
lock (myUsers)
{
myUsers.Add(aUser);
}
}
private static User GetUser(string userName)
{
lock (myUsers)
{
User aUser = myUsers.FirstOrDefault(x => x.UserName == userName);
return aUser;
}
}
}
}
</pre>
</div>
<div>
<br /></div>
<h3>
Client Application</h3>
<div>
The client is a simple win-form application which provides the logging functionality. Once the user enters the username (Peter) and password (pwd123) the client connects the service and follows the SRP authentication sequence. If the authentication is correct the connection is established and the user can consume the service.<br />
<br />
When the user presses the login button the client will try to open the connection using the SRP sequence. The AuthenticatedMessaging will call the <span style="font-family: "courier new" , "courier" , monospace;">OnGetLoginRequestMessage</span> method. It generates private and public ephemeral values of the client and returns the login request message which contains the username and the public client ephemeral value.<br />
<br />
Then when the service sends the response for the login the <span style="font-family: "courier new" , "courier" , monospace;">OnGetProveMessage</span> method is called. It calculates the session key and the M1 message to prove it knows the password.</div>
<div>
<br /></div>
<div>
The implementation of the client is also very simple:</div>
<div>
<pre class="brush: csharp">using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
using Eneter.SecureRemotePassword;
using System;
using System.Security.Cryptography;
using System.Windows.Forms;
namespace WindowsFormClient
{
public partial class Form1 : Form
{
[Serializable]
public class CalculateRequestMessage
{
public double Number1 { get; set; }
public double Number2 { get; set; }
}
[Serializable]
public class CalculateResponseMessage
{
public double Result { get; set; }
}
private IMultiTypedMessageSender mySender;
private LoginRequestMessage myLoginRequest;
private byte[] myPrivateKey_a;
private ISerializer mySerializer;
public Form1()
{
InitializeComponent();
EnableUiControls(false);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
IMessagingSystemFactory anUnderlyingMessaging =
new TcpMessagingSystemFactory(new EasyProtocolFormatter());
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(
anUnderlyingMessaging, OnGetLoginRequestMessage, OnGetProveMessage)
{
// Receive response messages in the main UI thread.
// Note: UI controls can be accessed only from the UI thread.
// So if this is not set then your message handling method would have to
// route it manually.
OutputChannelThreading = new WinFormsDispatching(this),
// Timeout for the authentication.
// If the value is -1 then it is infinite (e.g. for debugging purposses)
AuthenticationTimeout = TimeSpan.FromMilliseconds(30000)
};
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8033/");
anOutputChannel.ConnectionClosed += OnConnectionClosed;
IMultiTypedMessagesFactory aFactory = new MultiTypedMessagesFactory()
{
SerializerProvider = OnGetSerializer
};
mySender = aFactory.CreateMultiTypedMessageSender();
// Register handlers for particular types of response messages.
mySender.RegisterResponseMessageReceiver<CalculateResponseMessage>(OnCalculateResponseMessage);
mySender.RegisterResponseMessageReceiver<int>(OnFactorialResponseMessage);
try
{
// Attach output channel and be able to send messages and receive responses.
mySender.AttachDuplexOutputChannel(anOutputChannel);
EnableUiControls(true);
}
catch
{
MessageBox.Show("Incorrect user name or password.",
"Login Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// It is called if the service closes the connection.
private void OnConnectionClosed(object sender, DuplexChannelEventArgs e)
{
CloseConnection();
}
private void CloseConnection()
{
// Detach output channel and release the thread listening to responses.
if (mySender != null && mySender.IsDuplexOutputChannelAttached)
{
mySender.DetachDuplexOutputChannel();
}
EnableUiControls(false);
}
private void EnableUiControls(bool isLoggedIn)
{
LoginTextBox.Enabled = !isLoggedIn;
PasswordTextBox.Enabled = !isLoggedIn;
LoginBtn.Enabled = !isLoggedIn;
LogoutBtn.Enabled = isLoggedIn;
Number1TextBox.Enabled = isLoggedIn;
Number2TextBox.Enabled = isLoggedIn;
CalculateBtn.Enabled = isLoggedIn;
ResultTextBox.Enabled = isLoggedIn;
FactorialNumberTextBox.Enabled = isLoggedIn;
CalculateFactorialBtn.Enabled = isLoggedIn;
FactorialResultTextBox.Enabled = isLoggedIn;
}
// It is called by the AuthenticationMessaging to get the login message.
private object OnGetLoginRequestMessage(string channelId, string responseReceiverId)
{
myPrivateKey_a = SRP.a();
byte[] A = SRP.A(myPrivateKey_a);
myLoginRequest = new LoginRequestMessage();
myLoginRequest.UserName = LoginTextBox.Text;
myLoginRequest.A = A;
// Serializer to serialize LoginRequestMessage.
ISerializer aSerializer = new BinarySerializer();
object aSerializedLoginRequest =
aSerializer.Serialize<LoginRequestMessage>(myLoginRequest);
// Send the login request to start negotiation about the session key.
return aSerializedLoginRequest;
}
// It is called by the AuthenticationMessaging to handle the LoginResponseMessage received
// from the service.
private object OnGetProveMessage(
string channelId, string responseReceiverId, object loginResponseMessage)
{
// Deserialize LoginResponseMessage.
ISerializer aSerializer = new BinarySerializer();
LoginResponseMessage aLoginResponse =
aSerializer.Deserialize<LoginResponseMessage>(loginResponseMessage);
// Calculate scrambling parameter.
byte[] u = SRP.u(myLoginRequest.A, aLoginResponse.B);
if (SRP.IsValid_B_u(aLoginResponse.B, u))
{
// Calculate user private key.
byte[] x = SRP.x(PasswordTextBox.Text, aLoginResponse.s);
// Calculate the session key which will be used for the encryption.
// Note: if everything is then this key will be the same as on the service side.
byte[] K = SRP.K_Client(aLoginResponse.B, x, u, myPrivateKey_a);
// Create serializer for encrypting the communication.
Rfc2898DeriveBytes anRfc = new Rfc2898DeriveBytes(K, aLoginResponse.s, 1000);
mySerializer = new AesSerializer(new BinarySerializer(true), anRfc, 256);
// Create M1 message to prove that the client has the correct session key.
byte[] M1 = SRP.M1(myLoginRequest.A, aLoginResponse.B, K);
return M1;
}
// Close the connection with the service.
return null;
}
// It is called whenever the client sends or receives the message from the service.
// It will return the serializer which serializes/deserializes messages using
// the connection password.
private ISerializer OnGetSerializer(string responseReceiverId)
{
return mySerializer;
}
private void CalculateBtn_Click(object sender, EventArgs e)
{
// Create message.
CalculateRequestMessage aRequest = new CalculateRequestMessage();
aRequest.Number1 = double.Parse(Number1TextBox.Text);
aRequest.Number2 = double.Parse(Number2TextBox.Text);
// Send message.
mySender.SendRequestMessage<CalculateRequestMessage>(aRequest);
}
private void CalculateFactorialBtn_Click(object sender, EventArgs e)
{
// Create message.
int aNumber = int.Parse(FactorialNumberTextBox.Text);
// Send Message.
mySender.SendRequestMessage<int>(aNumber);
}
// It is called when the service sents the response for calculation of two numbers.
private void OnCalculateResponseMessage(object sender,
TypedResponseReceivedEventArgs<CalculateResponseMessage> e)
{
ResultTextBox.Text = e.ResponseMessage.Result.ToString();
}
// It is called when the service sents the response for the factorial calculation.
private void OnFactorialResponseMessage(object sender,
TypedResponseReceivedEventArgs<int> e)
{
FactorialResultTextBox.Text = e.ResponseMessage.ToString();
}
private void LoginBtn_Click(object sender, EventArgs e)
{
OpenConnection();
}
private void LogoutBtn_Click(object sender, EventArgs e)
{
CloseConnection();
}
}
}
</pre>
</div>
<div>
<br /></div>
<ol>
</ol>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-22061213323449269022015-07-29T21:41:00.002+02:002016-06-21T20:49:00.668+02:00RPC from Windows Phone 8.1 client to .NET serviceSimple example showing how to call remote methods exposed by a .NET service application from Windows Phone 8.1 (Silverlight).<br />
<br />
<a name='more'></a>The source code from this example can be found <a href="http://eneter.net/Downloads/Examples/WinPhone81SilverlightRpcCalculator.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates how to implement the client-service communication using RPC (Remote Procedure Call) between a Windows Phone 8.1 (Silverlight) and a .NET applications.</div>
<div>
It implements a simple calculator where Windows Phone is the client application which calls remote methods exposed by the .NET service application to calculate two numbers.</div>
<div>
<br /></div>
<h3>
To Run Example</h3>
<div>
<ol>
<li><a href="http://www.eneter.net/ProductDownload.htm">Download Eneter.Messaging.Framework</a> for .NET platforms.</li>
<li><a href="http://eneter.net/Downloads/Examples/WinPhone81SilverlightRpcCalculator.zip">Download the example project</a>.</li>
<li>Open the solution in Visual Studio and update references to:<br /><span style="font-family: "courier new" , "courier" , monospace;">Eneter.Messaging.Framework.dll</span> - for .NET 4.5 CalculatorService project.<br /><span style="font-family: "courier new" , "courier" , monospace;">Eneter.Messaging.Framework.WindowsPhone.dll</span> - for CalculatorClientWindowsPhoneSilverlight project.</li>
<li>Figure out the IP address your computer within your network and update the IP address in the client as well ass in the service source code.</li>
<li>Run the CalculatorService application.</li>
<li>Deploy the client application to Windows Phone device and run it.</li>
<li>When client application is running press connect button and then you can start to try calculate numbers.</li>
</ol>
</div>
<div>
<br /></div>
<h3>
RPC from Windows Phone Silverlight</h3>
<div>
RPC functionality in Windows Phone Silverlight is not so elegant like in a classic .NET application. The reason is Windows Phone Silverlight does not support emitting of metadata and MSIL (Microsoft Intermediate Language). Therefore it is not possible to create the proxy for the given service interface in runtime. It means the RPC client in Eneter cannot provide the proxy (like in .NET) allowing to call service methods as if they are local methods.</div>
<div>
To overcome this issue Eneter provides a possibility to call methods explicitly by name and list of parameters. E.g.:<br />
<br /></div>
<div>
<pre class="brush: csharp">// Call remote method in the service.
int aResult = (int) myRpcClient.CallRemoteMethod("Calculate", a, b);
</pre>
<br /></div>
<h3>
Windows Phone Client Application</h3>
Windows Phone Client is a simple application which provides buttons to connect and disconnect from the service and a simple UI to insert two numbers and the button Calculate which triggers the remote call to the service.<br />
<br />
The whole implementation is very simple:<br />
<br />
<div>
<pre class="brush: csharp">using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Microsoft.Phone.Controls;
using System.Windows;
namespace CalculatorClientWindowsPhoneSilverlight
{
public partial class MainPage : PhoneApplicationPage
{
// Service interface.
public interface ICalculator
{
int Calculate(int a, int b);
}
private IRpcClient<ICalculator> myRpcClient;
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private void OnConnectBtnClick(object sender, RoutedEventArgs e)
{
OpenConnection();
}
private void OnDisconnectBtnClick(object sender, RoutedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
// Create RPC client.
IRpcFactory anRpcFactory = new RpcFactory();
myRpcClient = anRpcFactory.CreateClient<ICalculator>();
// Use TCP messaging.
// Note: provide IP address of your service computer.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel
= aMessaging.CreateDuplexOutputChannel("tcp://192.168.178.31:8099/");
// Attach output channel and be able to call remote methods.
myRpcClient.AttachDuplexOutputChannel(anOutputChannel);
}
private void CloseConnection()
{
myRpcClient.DetachDuplexOutputChannel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int a = int.Parse(Number1TextBox.Text);
int b = int.Parse(Number2TextBox.Text);
// Call remote method in the service.
int aResult = (int) myRpcClient.CallRemoteMethod("Calculate", a, b);
// Display the result.
ResultTextBox.Text = aResult.ToString();
}
}
}
</pre>
<br /></div>
<h3>
.NET Service Application</h3>
<div>
The service is a simple console application which exposes methods of <i>ICalculatorService</i> interface for remote procedure calls. When the client calls the remote method the Eneter framework forwards the call to the service and then when it returns the value it sends it back to the service.</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using System;
namespace CalculatorService
{
// Service interface.
public interface ICalculator
{
int Calculate(int a, int b);
}
// SErvice implementation.
public class Calculator : ICalculator
{
public int Calculate(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
//EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;
//EneterTrace.TraceLog = new StreamWriter("d:/tracefile.txt");
// Instantiate class which implements the application logic of the service.
ICalculator aCalculator = new Calculator();
// Create RPC service.
IRpcFactory anRpcFactory = new RpcFactory();
IRpcService<ICalculator> anRpcService
= anRpcFactory.CreateSingleInstanceService<ICalculator>(aCalculator);
// Use TCP for the communication.
// Note: provide IP address of your service computer.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel
= aMessaging.CreateDuplexInputChannel("tcp://192.168.178.31:8099/");
// Attach input channel to the service and start listening.
anRpcService.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The calculator service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel to stop listening.
anRpcService.DetachDuplexInputChannel();
}
}
}
</pre>
<br /></div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com0tag:blogger.com,1999:blog-5196103582241137578.post-16961040532193089332015-05-23T12:38:00.000+02:002016-01-09T09:07:51.845+01:00Live Video Streaming from Windows Phone 8.1Simple example showing how to implement live video streaming from Windows Phone 8.1 (Silverlight) to a standalone desktop application.<br />
<br />
<a name='more'></a><br />
The source code of this example can be downloaded from <a href="http://www.eneter.net/Downloads/Examples/VideoStreamFromWindowsPhone.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates how to stream live video from the camera to a standalone desktop application. It implements a simple client application running in Windows Phone 8.1 Silverlight which provides a UI to preview and record the video from the camera. When a user clicks the record button the application opens connection with the service application and starts streaming. The service application receives the stream and stores it into the MP4 (MPEG-4) file.<br />
<br />
The implementation of this scenario addresses following topics:</div>
<div>
<ul>
<li>Capturing video in Windows Phone 8.1</li>
<li>Streaming video across the network.</li>
<li>Receiving video in a desktop application and storing it to the file.</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbmeWq5y8q24GmDfCnMuuXtNQG32sP-LM-rsjFy-NabQViv11T3FMb0t2D5x3bwLprDnK5DLdKN5DFlGfQsrqveMM19gEOZKbbhjiFxzo7BAy6F2w-xk6qXpyakAyvfIm8JnXrXRvD-XkG/s1600/LiveVideostreamingWindowsPhone81.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="418" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbmeWq5y8q24GmDfCnMuuXtNQG32sP-LM-rsjFy-NabQViv11T3FMb0t2D5x3bwLprDnK5DLdKN5DFlGfQsrqveMM19gEOZKbbhjiFxzo7BAy6F2w-xk6qXpyakAyvfIm8JnXrXRvD-XkG/s640/LiveVideostreamingWindowsPhone81.png" width="640" /></a></div>
<h3>
</h3>
<h3>
</h3>
<div>
<br /></div>
<h3>
To Run Example</h3>
<div>
<ol>
<li><a href="http://www.eneter.net/ProductDownload.htm">Download Eneter Messaging Framework</a> for .NET platforms.</li>
<li><a href="http://www.eneter.net/Downloads/Examples/VideoStreamFromWindowsPhone.zip">Download the example project</a>.</li>
<li>Open the solution in Visual Studio and update references to:<br /><span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.dll</span> - for .NET 4.5<br /><span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.WindowsPhone.dll</span> - for Windows Phone 8.1 Silverlight</li>
<li>Figure out the IP address of your computer within your network and update the IP address in the client as well as the service source code.</li>
<li>Run the service application.</li>
<li>Deploy the client application to the Windows Phone device and runt it.</li>
</ol>
<br />
<ol>
</ol>
</div>
<ul>
</ul>
<h3>
Capturing Video in Windows Phone 8.1</h3>
</div>
<div>
To use the camera the application needs to have permissions for following capabilities:<br />
<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">ID_CAP_ISV_CAMERA</span><span style="font-family: inherit;"> - provides access to the camera.</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">ID_CAP_MICROPHONE</span><span style="font-family: inherit;"> - provides access to the phone's microphone.</span></li>
</ul>
<br />
They can be enabled in <span style="font-family: Courier New, Courier, monospace;">WMAppManifest.xml</span> (located in the Properties folder).<br />
<br />
To capture the video Windows Phone 8.1 offers the <a href="https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.capture.mediacapture.aspx" target="_blank"><span style="font-family: Courier New, Courier, monospace;">MediaCapture</span></a> class which provides functionality to preview and record the video (including audio). After instantiating the <span style="font-family: inherit;">MediaCapture </span>object needs to be initialized with proper settings (see <span style="font-family: Courier New, Courier, monospace;">ActivateCameraAsync()</span>) and then to enable the preview it needs to be associated with VideoBrush (see <span style="font-family: Courier New, Courier, monospace;">StartPreviewAsync()</span>).<br />
It is also very important to ensure <span style="font-family: inherit;">MediaCapture </span>is properly disposed when not needed or when the application is suspended. Failing to do so will cause problems to other applications accessing the camera. (E.g. when I did not dispose <span style="font-family: inherit;">MediaCapture </span>I could not start the application multiple times. Following starts always failed during the camera initialization and the phone had to be rebooted.)<br />
<br />
<h3>
Streaming Video Across Network</h3>
</div>
<div>
To record the video the method <span style="font-family: Courier New, Courier, monospace;"><a href="https://msdn.microsoft.com/en-us/library/windows/apps/hh700868.aspx" target="_blank">StartRecordToStreamAsync(..</a>)</span> is called. The method takes two parameters:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">MediaEncodingProfile</span> - specifies the video format (e.g. MP4 or WMV)</li>
<li><span style="font-family: Courier New, Courier, monospace;"><i><a href="https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.irandomaccessstream" target="_blank">IRandomAccessStream</a></i></span> - specifies the stream where to write captured video.</li>
</ul>
</div>
<div>
In order to provide streaming across the network custom <span style="font-family: Courier New, Courier, monospace;">MessageSendingStream</span> (derived from <i style="font-family: 'Courier New', Courier, monospace;">IRandomAccessStream</i><span style="font-family: inherit;">) is implemented and then used as an input parameter for </span><span style="font-family: Courier New, Courier, monospace;">StartRecordToStreamAsync(..)</span><span style="font-family: inherit;">.</span><br />
It does not implement the whole interface but only methods which are necessary for <span style="font-family: inherit;">MediaCapture </span>to write MPEG-4 format.<br />
<br />
When a user starts recording MessageSendingStream is instantiated and the connection with the service is open. Then StartRecordToStreamAsync(...) with MessageSendingStream is called and captured data is sent to the service.<br />
Since writing MP4 is not fully sequential the streaming message sent from the client to the service consists of two parts:<br />
<ul>
<li>4 bytes - integer number indicating the position inside MP4.</li>
<li>n bytes - video/audio data captured by the camera.</li>
</ul>
<br />
When the user stops recording MediaCapture completes writing and the connection with the service is closed. Once the connection is closed the service closes the MP4 file.<br />
<br /></div>
<h3>
Receiving Video in Desktop Application</h3>
<div>
Receiving the stream is quite straight forward. When the service receives the stream message it decodes the position (first 4 bytes) and writes incoming video data to the MP4 file on desired position.</div>
<div>
There can be multiple recording clients connected to the service. Therefore the service maintains for each connected client a separate MP4 file. Once the client disconnects the file is closed and ready for further using (e.g. cutting or replaying).</div>
<div>
<br /></div>
<h3>
Windows Phone Client</h3>
<div>
Windows phone client is a simple application displaying the video preview and providing buttons to start and stop the video capturing.</div>
<div>
When the user clicks start record it opens connection with the service and starts sending stream messages.</div>
<div>
When the user clicks stop recording or the application is suspended it completes the recording and closes the connection with the service.</div>
<div>
<br /></div>
<div>
The implementation consists of two major parts:</div>
<div>
<ul>
<li>Logic manipulating the camera - implemented in <span style="font-family: Courier New, Courier, monospace;">MainPage.xaml.cs</span> file</li>
<li>Logic sending the stream messages to the service - implemented in <span style="font-family: Courier New, Courier, monospace;">MessageSendingStream.cs</span> file.</li>
</ul>
Implementation of MainPage.xaml.cs:<br />
<br />
<pre class="brush: csharp">using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Navigation;
using Windows.Devices.Enumeration;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Phone.Media.Capture;
namespace PhoneCamera
{
public partial class MainPage : PhoneApplicationPage
{
// Stream sending messages to the service.
private MessageSendingStream myMessageSendingStream;
// Video capturing.
private VideoBrush myVideoRecorderBrush;
private MediaCapturePreviewSink myPreviewSink;
private MediaCapture myMediaCapture;
private MediaEncodingProfile myProfile;
private bool myIsRecording;
// Constructor
public MainPage()
{
InitializeComponent();
// Prepare ApplicationBar and buttons.
PhoneAppBar = (ApplicationBar)ApplicationBar;
PhoneAppBar.IsVisible = true;
StartRecordingBtn = ((ApplicationBarIconButton)ApplicationBar.Buttons[0]);
StopRecordingBtn = ((ApplicationBarIconButton)ApplicationBar.Buttons[1]);
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// Disable both buttons until initialization is completed.
StartRecordingBtn.IsEnabled = false;
StopRecordingBtn.IsEnabled = false;
try
{
await ActivateCameraAsync();
await StartPreviewAsync();
// Enable Start Recording button.
StartRecordingBtn.IsEnabled = true;
txtDebug.Text = "Ready...";
}
catch (Exception err)
{
txtDebug.Text = "ERROR: " + err.Message;
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
DeactivateCamera();
base.OnNavigatedFrom(e);
}
private async void OnStartRecordingClick(object sender, EventArgs e)
{
await StartRecordingAsync();
}
// Handle stop requests.
private async void OnStopRecordingClick(object sender, EventArgs e)
{
await StopRecordingAsync("Ready...");
}
private async Task ActivateCameraAsync()
{
// Find the camera device id to use
string aDeviceId = "";
var aDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
for (var i = 0; i < aDevices.Count; ++i)
{
aDeviceId = aDevices[i].Id;
}
// Capture settings.
var aSettings = new MediaCaptureInitializationSettings();
aSettings.AudioDeviceId = "";
aSettings.VideoDeviceId = aDeviceId;
aSettings.MediaCategory = MediaCategory.Other;
aSettings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;
aSettings.StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo;
//Create profile for MPEG-4 container which will have H.264 video.
myProfile = MediaEncodingProfile.CreateMp4(
Windows.Media.MediaProperties.VideoEncodingQuality.Qvga);
// Initialize the media capture with specified settings.
myMediaCapture = new MediaCapture();
await myMediaCapture.InitializeAsync(aSettings);
myIsRecording = false;
}
private void DeactivateCamera()
{
if (myMediaCapture != null)
{
if (myIsRecording)
{
// Note: Camera deactivation needs to run synchronous.
// Otherwise suspending/resuming during recording does not work.
myMediaCapture.StopRecordAsync().AsTask().Wait();
myIsRecording = false;
}
myMediaCapture.StopPreviewAsync().AsTask().Wait();
myMediaCapture.Dispose();
myMediaCapture = null;
}
if (myPreviewSink != null)
{
myPreviewSink.Dispose();
myPreviewSink = null;
}
ViewfinderRectangle.Fill = null;
if (myMessageSendingStream != null)
{
myMessageSendingStream.CloseConnection();
myMessageSendingStream.ConnectionBroken -= OnConnectionBroken;
}
}
private async void OnConnectionBroken(object sender, EventArgs e)
{
await StopRecordingAsync("Disconnected from server.");
}
private async Task StartPreviewAsync()
{
// List of supported video preview formats to be used by the default
// preview format selector.
var aSupportedVideoFormats = new List<string> { "nv12", "rgb32" };
// Find the supported preview format
var anAvailableMediaStreamProperties =
myMediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(
Windows.Media.Capture.MediaStreamType.VideoPreview)
.OfType<Windows.Media.MediaProperties.VideoEncodingProperties>()
.Where(p => p != null && !String.IsNullOrEmpty(p.Subtype)
&& aSupportedVideoFormats.Contains(p.Subtype.ToLower()))
.ToList();
var aPreviewFormat = anAvailableMediaStreamProperties.FirstOrDefault();
// Start Preview stream
myPreviewSink = new MediaCapturePreviewSink();
await myMediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(
Windows.Media.Capture.MediaStreamType.VideoPreview, aPreviewFormat);
await myMediaCapture.StartPreviewToCustomSinkAsync(
new MediaEncodingProfile { Video = aPreviewFormat }, myPreviewSink);
// Create the VideoBrush for the viewfinder.
myVideoRecorderBrush = new VideoBrush();
Microsoft.Devices.CameraVideoBrushExtensions.SetSource(myVideoRecorderBrush, myPreviewSink);
// Display video preview.
ViewfinderRectangle.Fill = myVideoRecorderBrush;
}
private async Task StartRecordingAsync()
{
// Disable Start Recoridng button.
StartRecordingBtn.IsEnabled = false;
try
{
// Connect the service.
// Note: use IP address of the service within your network.
// To figure out the IP address of you can execute from
// the command prompt: ipconfig -all
myMessageSendingStream =
new MessageSendingStream("tcp://192.168.178.31:8093/");
myMessageSendingStream.ConnectionBroken += OnConnectionBroken;
myMessageSendingStream.OpenConnection();
await myMediaCapture.StartRecordToStreamAsync(myProfile, myMessageSendingStream);
myIsRecording = true;
// Enable Stop Recording button.
StopRecordingBtn.IsEnabled = true;
txtDebug.Text = "Recording...";
}
catch (Exception err)
{
myMessageSendingStream.CloseConnection();
myMessageSendingStream.ConnectionBroken -= OnConnectionBroken;
txtDebug.Text = "ERROR: " + err.Message;
StartRecordingBtn.IsEnabled = true;
}
}
private async Task StopRecordingAsync(string textMessage)
{
// Note: Since this method does not have to be called from UI thread
// ensure UI controls are manipulated from the UI thread.
// Disable Stop Recording button.
ToUiThread(() => StopRecordingBtn.IsEnabled = false);
try
{
if (myIsRecording)
{
await myMediaCapture.StopRecordAsync();
myIsRecording = false;
}
// Enable Start Recording button and display Message.
ToUiThread(() =>
{
StartRecordingBtn.IsEnabled = true;
txtDebug.Text = textMessage;
});
}
catch (Exception err)
{
ToUiThread(() =>
{
txtDebug.Text = "ERROR: " + err.Message;
StopRecordingBtn.IsEnabled = true;
});
}
// Disconnect from the service.
myMessageSendingStream.CloseConnection();
myMessageSendingStream.ConnectionBroken -= OnConnectionBroken;
}
private void ToUiThread(Action x)
{
Dispatcher.BeginInvoke(x);
}
}
}
</pre>
<br />
Implementation of MessageSendingStream.cs is very simple too:<br />
<br />
<pre class="brush: csharp">using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using System;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage.Streams;
namespace PhoneCamera
{
// Implements IRandomAccessStream which is then used by MediaCapture for storing
// captured video and audi data.
// The implementation of this class sends the captured data across the network
// to the service where it is stored to the file.
internal class MessageSendingStream : IRandomAccessStream
{
private IDuplexOutputChannel myOutputChannel;
private ulong myPosition; // Current position in the stream.
private ulong mySize; // The size of the stream.
// Raised when the connection with the service is broken.
public event EventHandler ConnectionBroken;
public MessageSendingStream(string serviceAddress)
{
// Let's use TCP for the communication with fast encoding of messages.
var aFormatter = new EasyProtocolFormatter();
var aMessaging = new TcpMessagingSystemFactory(aFormatter);
aMessaging.ConnectTimeout = TimeSpan.FromMilliseconds(3000);
myOutputChannel = aMessaging.CreateDuplexOutputChannel(serviceAddress);
}
public void OpenConnection()
{
myOutputChannel.OpenConnection();
}
public void CloseConnection()
{
myOutputChannel.CloseConnection();
}
public bool CanRead { get { return false; } }
public bool CanWrite { get { return true; } }
public IRandomAccessStream CloneStream()
{ throw new NotSupportedException(); }
public IInputStream GetInputStreamAt(ulong position)
{ throw new NotSupportedException(); }
public IOutputStream GetOutputStreamAt(ulong position)
{ throw new NotSupportedException(); }
public ulong Position { get { return myPosition; } }
public void Seek(ulong position)
{
myPosition = position;
if (myPosition >= mySize)
{
mySize = myPosition + 1;
}
}
public ulong Size
{
get { return mySize; }
set { throw new NotSupportedException(); }
}
public void Dispose()
{
myOutputChannel.CloseConnection();
}
public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
{
throw new NotSupportedException();
}
public IAsyncOperation<bool> FlushAsync()
{
throw new NotSupportedException();
}
// Implements sending of video/audio data to the service.
// The message is encoded the following way:
// 4 bytes - position in MP4 file where data shall be put.
// n bytes - video/audio data.
public IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer)
{
Task<uint> aTask = new Task<uint>(() =>
{
uint aVideoDataLength = buffer.Length;
byte[] aMessage = new byte[aVideoDataLength + 4];
// Put position within MP4 file to the message.
byte[] aPosition = BitConverter.GetBytes((int)myPosition);
Array.Copy(aPosition, aMessage, aPosition.Length);
// Put video/audio data to the message.
buffer.CopyTo(0, aMessage, 4, (int)aVideoDataLength);
uint aTransferedSize = 0;
try
{
// Send the message to the service.
myOutputChannel.SendMessage(aMessage);
aTransferedSize = (uint)aVideoDataLength;
// Calculate new size of the stream.
if (myPosition + aVideoDataLength > mySize)
{
mySize = myPosition + aVideoDataLength;
}
}
catch
{
// If sending fails then the connection is broken.
if (ConnectionBroken != null)
{
ConnectionBroken(this, new EventArgs());
}
}
return aTransferedSize;
});
aTask.RunSynchronously();
Func<CancellationToken, IProgress<uint>, Task<uint>> aTaskProvider = (token, progress) => aTask;
return AsyncInfo.Run<uint, uint>(aTaskProvider);
}
}
}
</pre>
<br /></div>
<h3>
Desktop Service</h3>
<div>
Desktop service is a simple console application which listens to a specified IP address and port.</div>
<div>
When a client connects the service it creates the MP4 file and waits for stream messages. When a stream message is received it writes data to the file.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:
<br />
<pre class="brush: csharp">using Eneter.Messaging.MessagingSystems.ConnectionProtocols;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using System;
using System.Collections.Generic;
using System.IO;
namespace VideoStorageService
{
class Program
{
// The service can handle multiple clients.
// So this dictionary maintains open files per client.
private static Dictionary<string, FileStream> myActiveVideos = new Dictionary<string, FileStream>();
static void Main(string[] args)
{
var aFastEncoding = new EasyProtocolFormatter();
var aMessaging = new TcpMessagingSystemFactory(aFastEncoding);
var anInputChannel = aMessaging.CreateDuplexInputChannel("tcp://192.168.178.31:8093/");
// Subscribe to handle incoming data.
anInputChannel.MessageReceived += OnMessageReceived;
// Subscribe to handle client connection/disconnection.
anInputChannel.ResponseReceiverConnected += OnResponseReceiverConnected;
anInputChannel.ResponseReceiverDisconnected += OnClientDisconnected;
// Start listening.
anInputChannel.StartListening();
Console.WriteLine("Videostorage service is running. Press ENTER to stop.");
Console.WriteLine("The service is listening at: " + anInputChannel.ChannelId);
Console.ReadLine();
// Stop listening.
// Note: it releases the listening thread.
anInputChannel.StopListening();
}
private static void OnResponseReceiverConnected(object sender, ResponseReceiverEventArgs e)
{
Console.WriteLine("Connected client: " + e.ResponseReceiverId);
StartStoring(e.ResponseReceiverId);
}
private static void OnClientDisconnected(object sender, ResponseReceiverEventArgs e)
{
Console.WriteLine("Disconnected client: " + e.ResponseReceiverId);
StopStoring(e.ResponseReceiverId);
}
private static void OnMessageReceived(object sender, DuplexChannelMessageEventArgs e)
{
byte[] aVideoData = (byte[])e.Message;
StoreVideoData(e.ResponseReceiverId, aVideoData);
}
private static void StartStoring(string clientId)
{
// Create MP4 file for the client.
string aFileName = "./" + Guid.NewGuid().ToString() + ".mp4";
myActiveVideos[clientId] = new FileStream(aFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
}
private static void StopStoring(string clientId)
{
// Close MP4 file for the client.
FileStream aFileStream;
myActiveVideos.TryGetValue(clientId, out aFileStream);
if (aFileStream != null)
{
aFileStream.Close();
}
myActiveVideos.Remove(clientId);
}
private static void StoreVideoData(string clientId, byte[] videoData)
{
try
{
// Get MP4 file which is open for the client.
FileStream aFileStream;
myActiveVideos.TryGetValue(clientId, out aFileStream);
if (aFileStream != null)
{
// From first 4 bytes decode position in MP4 file
// where to write the video data.
int aPosition = BitConverter.ToInt32(videoData, 0);
// Set the position in the file.
aFileStream.Seek(aPosition, SeekOrigin.Begin);
// Write data to the file.
aFileStream.Write(videoData, 4, videoData.Length - 4);
}
}
catch (Exception err)
{
Console.WriteLine(err);
}
}
}
}
</pre>
<br /></div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com0tag:blogger.com,1999:blog-5196103582241137578.post-50660209325286854692014-12-21T21:05:00.000+01:002014-12-21T21:05:17.853+01:00Communication via WiFi without an External Wireless RouterShort explanation how to configure virtual wireless router on a Windows machine and how to use it for the interporcess communication.<br />
<a name='more'></a><br />
It is not always practical or possible to use an <b>external wireless router</b> in order to establish a WiFi network as a base for the interprocess communication.<br />
E.g. Android client application needs to interact with a .NET service running on the laptop anytime the laptop is turned on - it would be impractical to carry and manipulate a separate WiFi router in order to establish the network.<br />
<br />
The solution for such scenario is to configure the virtual wireless router on the Windows machine. It means the wireless network card can be configured to act as a WiFi router.<br />
(Of course while acting as the WiFi router it can still perform as a standard wireless network card and connect to other WiFi networks as before.)<br />
<br />
The possibility to configure virtual wireless router comes with Windows 7 (or higher).<br />
Also Windows Vista allows to create so called Ad-Hoc Wireless Network but it has several limitations: wireless network card cannot act as the WiFi router and as the wireless card at the same time. It means when the card is used as the router it cannot be used to connect other WiFi networks. You would need the second wireless card or to connect via the Ethernet cable. In addition when I tried it I was not able to see this Ad-Hoc network on Android device - so I was not able to use it.<br />
<br />
Therefore this is the step-by-step procedure how to configure the virtual WiFi router in Windows 7 (or higher) and how to identify the IP address which can be then used by the service:<br />
<ol>
<li>Open command prompt as Administrator.</li>
<li>
Create the virtual wireless network using the following command:<br />(When scanning WiFi the network will have name MyHotspot.)<br /><span style="font-family: Courier New, Courier, monospace;">
netsh wlan set hostednetwork mode=allow ssid=MyHotspot key=password123</span>
</li>
<li>
Start the virtual wireless network using the following command:<br /><span style="font-family: Courier New, Courier, monospace;">
netsh wlan start hostednetwork</span>
</li>
<li>
Get IP address of the Windows machine (I mean this is the IP address of the Windows machine within MyHotspot network.) Run the following command:<br /><span style="font-family: Courier New, Courier, monospace;">
ipconfig -all</span>
<br />
<b>in the list find<br />• Microsoft Hosted Network Virtual Adapter<br />• </b>and then <b>IPv4 Address</b> - this is the IP address the service will use.</li>
<li>Use the identified IP address in the service running on Windows machine. It means the service running on the Windows machine will listen to that address (and some port).<br />Use the same identified IP address in the client. It means the client will open connection on that address.<br /><br />
(E.g. in my case the IP address was 192.168.173.1 and I chose to use the port 8094.
So after modifying sources my .NET service starts listening to tcp://192.168.173.1:8094/ and my Android client opens the connection to the same address tcp://192.168.173.1:8094/)
</li>
</ol>
<br />
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-32191663361469571612014-12-07T17:06:00.001+01:002014-12-07T17:10:48.023+01:00Simple Authentication when Connecting ServiceSimple example showing how to implement authentication when connecting a service.<br />
<br />
<a name='more'></a><br />
The source code for this example can be downloaded <a href="http://www.eneter.net/Downloads/Examples/AuthenticatedConnection.zip">here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates how to implement the communication where clients need to authenticate in order to use a service. To demonstrate this scenario the example shows a simple client-service communication. The client application opens the authenticated connection and then sends 'Hello service' message. The service application authenticate every connected client and when it receives a message it just simply responses with 'Hello client'.</div>
<div>
<br /></div>
<h4>
To Run Example</h4>
<div>
<ol>
<li><a href="http://www.eneter.net/ProductDownload.htm">Download Eneter for .NET</a>.</li>
<li><a href="http://www.eneter.net/Downloads/Examples/AuthenticatedConnection.zip">Download this example</a> and open the solution in Visual Studio.</li>
<li>Add <span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.dll</span> library to 'References' in both projects inside the solution.</li>
<li>Build the solution.</li>
<li>Run HelloService.</li>
<li>Run HelloClient.</li>
</ol>
</div>
<div>
<br /></div>
<h3>
Authenticated Connection</h3>
<div>
The authenticated connection is the connection which verifies the identity of communicating parts. (If they are who they are saying they are.) The identities can be checked on the protocol level e.g. using TLS (Transport Layer Security) or its predecessor SSL (Secure Socket Layer) but this approach may not be always suitable.</div>
<div>
E.g. if a server application provides multiple services on one IP address and port and some services requires client identity verification and some not.</div>
<div>
Or if you need the identity verification but you do not want to encrypt the whole communication (e.g. because of performance reasons).</div>
<div>
In such cases you may need to implement own identity verification. To do so you can use authentication functionality from Eneter Messaging Framework.</div>
<div>
<br /></div>
<div>
The Eneter authentication implemented in the example bellow performs the following sequence:</div>
<div>
<ol>
<li>The client opens the connection and sends the login message.</li>
<li>The service receives the login message and tries to find the client and its password in the database. Then it uses the client password from the database and encrypts the generated GUID and sends it as the handshake message.</li>
<li>The client receives the handshake message and decrypts it with own password.<br />(Note: if the service identity is correct then the handshake message is encrypted with correct password and so the client can decrypt it.)<br />Then the client takes the originaly encrypted handshake message and encrypts it again and sends it to the service as the handshake response message.</li>
<li>The service receives the handshake response message and decrypts it two times. If the result is the original GUID then the identity is considered verified and it sends the acknowledge message that the connection is established.</li>
<li>The client receives the acknowledge message and the connection is finally open.<br />Now both sides can communicate with messages which are not encrypted.</li>
</ol>
</div>
<div>
Note: to improve the security you may consider to store (in database) and use password hash instead of real passwords.</div>
<div>
<br /></div>
<h3>
Service Application</h3>
<div>
The service is a simple console application which listens to connecting clients. When a client is opening the connection it performs the authentication sequence described above.</div>
<div>
Then when the connection is open it receives 'Hello service' message and responses 'Hello client' message.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
<div>
<br /></div>
<pre class="brush: csharp">using System;
using System.Collections.Generic;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.StringMessages;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace HelloService
{
class Program
{
private static Dictionary<string, string> myUsers = new Dictionary<string, string>();
private static IDuplexStringMessageReceiver myReceiver;
static void Main(string[] args)
{
//EneterTrace.TraceLog = new StreamWriter("d:/tracefile.txt");
// Simulate database with users.
myUsers["John"] = "password1";
myUsers["Steve"] = "password2";
// Create TCP based messaging.
IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();
// Use authenticated connection.
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(aTcpMessaging, GetHandshakeMessage, Authenticate);
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8092/");
// Use simple text messages.
IDuplexStringMessagesFactory aStringMessagesFactory = new DuplexStringMessagesFactory();
myReceiver = aStringMessagesFactory.CreateDuplexStringMessageReceiver();
myReceiver.RequestReceived += OnRequestReceived;
// Attach input channel and start listening.
// Note: the authentication sequence will be performed when
// a client connects the service.
myReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("Service is running. Press Enter to stop.");
Console.ReadLine();
// Detach input channel and stop listening.
// Note: tis will release the listening thread.
myReceiver.DetachDuplexInputChannel();
}
private static void OnRequestReceived(object sender, StringRequestReceivedEventArgs e)
{
// Handle received messages here.
Console.WriteLine("Received message: " + e.RequestMessage);
// Send back the response.
myReceiver.SendResponseMessage(e.ResponseReceiverId, "Hello client");
}
// Callback which is called when a client sends the login message.
// It shall verify the login and return the handshake message.
private static object GetHandshakeMessage(string channelId,
string responseReceiverId,
object loginMessage)
{
// Find the login name and password in "database"
// and encrypt the handshake message.
if (loginMessage is string)
{
string aLoginName = (string)loginMessage;
Console.WriteLine("Received login: " + aLoginName);
if (myUsers.ContainsKey(aLoginName))
{
string aPassword = myUsers[aLoginName];
ISerializer aSerializer = new AesSerializer(aPassword);
object aHandshakeMessage = aSerializer.Serialize<string>(Guid.NewGuid().ToString());
return aHandshakeMessage;
}
}
// Login was not ok so there is not handshake message
// and the connection will be closed.
Console.WriteLine("Login was not ok. The connection will be closed.");
return null;
}
// Callback which is called when a client sends the handshake response message.
private static bool Authenticate(string channelId,
string responseReceiverId,
object loginMessage,
object handshakeMessage,
object handshakeResponseMessage)
{
if (loginMessage is string)
{
// Get the password associated with the user.
string aLoginName = (string) loginMessage;
string aPassword = myUsers[aLoginName];
// Decrypt the handshake response message.
// Handshake response message is one more time encrypted handshake message.
// Therefore if the handshake response is decrypted two times it should be
// the originaly generated GUID.
try
{
ISerializer aSerializer = new AesSerializer(aPassword);
// Decrypt handshake response to get original GUID.
object aDecodedHandshakeResponse1 = aSerializer.Deserialize<byte[]>(handshakeResponseMessage);
string aDecodedHandshakeResponse2 = aSerializer.Deserialize<string>(aDecodedHandshakeResponse1);
// Decrypt original handshake message.
string anOriginalGuid = aSerializer.Deserialize<string>(handshakeMessage);
// If GUIDs are equal then the identity of the client is verified.
if (anOriginalGuid == aDecodedHandshakeResponse2)
{
Console.WriteLine("Client authenticated.");
// The handshake response is correct so the connection can be established.
return true;
}
}
catch (Exception err)
{
// Decoding of the response message failed.
// The authentication will not pass.
Console.WriteLine("Decoding handshake message failed.", err);
}
}
// Authentication did not pass.
Console.WriteLine("Authentication did not pass. The connection will be closed.");
return false;
}
}
}
</pre>
<div>
<br /></div>
<h3>
Client Application</h3>
<div>
The client is a simple console application which tries to opens the authenticated connection using the sequence described above. Once the connection is open it sends the 'Hello service' message and receives 'Hello client' message.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
<div>
<br /></div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.StringMessages;
using Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace HelloClient
{
class Program
{
private static IDuplexStringMessageSender mySender;
static void Main(string[] args)
{
// TCP messaging.
IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();
// Use authenticated connection.
IMessagingSystemFactory aMessaging =
new AuthenticatedMessagingFactory(aTcpMessaging, GetLoginMessage, GetHandshakeResponseMessage);
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8092/");
// Use simple text messages.
mySender = new DuplexStringMessagesFactory().CreateDuplexStringMessageSender();
// Subscribe to receive response messages.
mySender.ResponseReceived += OnResponseMessageReceived;
// Attach output channel and connect the service.
// Note: this step performs the authentication sequence.
// If the authentication is successful then the connection is open.
mySender.AttachDuplexOutputChannel(anOutputChannel);
// Send a message.
// Note: this message will not be encrypted.
mySender.SendMessage("Hello service");
Console.WriteLine("Client sent the message. Press ENTER to stop.");
Console.ReadLine();
// Detach output channel and stop listening.
// Note: it releases the tread listening to responses.
mySender.DetachDuplexOutputChannel();
}
private static void OnResponseMessageReceived(object sender, StringResponseReceivedEventArgs e)
{
// Process the incoming response here.
Console.WriteLine("Received response: " + e.ResponseMessage);
}
public static object GetLoginMessage(string channelId, string responseReceiverId)
{
return "John";
}
public static object GetHandshakeResponseMessage(string channelId,
string responseReceiverId,
object handshakeMessage)
{
try
{
ISerializer aSerializer = new AesSerializer("password1");
// Decrypt the hanshake message.
// If the service identity is correct then the handshake message
// is encrypted with correct client password and it is possible to decrypt it.
// If not the exception is thrown.
aSerializer.Deserialize<string>(handshakeMessage);
// Take the original handshake message and encrypt it.
object aHandshakeResponse = aSerializer.Serialize<byte[]>((byte[])handshakeMessage);
return aHandshakeResponse;
}
catch (Exception err)
{
Console.WriteLine("Processing handshake message failed. The connection will be closed.", err);
}
return null;
}
}
}
</pre>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-41600035522523736532014-08-18T21:06:00.001+02:002016-01-09T09:05:27.502+01:00Live Video from Raspberry Pi to .NETSimple example showing how to implement video streaming from Raspberry Pi camera to a .NET application.<br />
<br />
<a name='more'></a><br />
The source code for this example can be <a href="http://eneter.net/Downloads/Examples/RaspberryCamera.zip">downloaded here</a>.<br />
<br />
<h3>
Introduction</h3>
The example bellow demonstrates how to implement live video streaming from Raspberry Pi camera to a .NET application and display it.<br />
The example shows the implementation of a service running on Raspberry which captures the video from the camera and streams it to a .NET client which processes it and displays on the screen.<br />
To implement this scenario following topics need to be addressed by the implementation:<br />
<ul>
<li>Capturing video from the Raspberry Pi camera by the service application.</li>
<li>Streaming video across the network.</li>
<li>Processing and displaying video by the .NET client application.</li>
</ul>
The example streams the video via TCP but UDP or WebSockets can be used too.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdhAVaUJN1HODp3GAkKzO8oRjMY7Nv_QPe0m2bM-DUtJELwe2UxSPv1FY2bUpVThwgM0dtuGpeZazTtM2eRUf3a9D-Zw7dJEINjt4zfV79bg0LCzpMmlCU8UFxxgtJ3druM2FBYDSO70v2/s1600/RaspberryVideostreamingToNET.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdhAVaUJN1HODp3GAkKzO8oRjMY7Nv_QPe0m2bM-DUtJELwe2UxSPv1FY2bUpVThwgM0dtuGpeZazTtM2eRUf3a9D-Zw7dJEINjt4zfV79bg0LCzpMmlCU8UFxxgtJ3druM2FBYDSO70v2/s640/RaspberryVideostreamingToNET.png" width="640" /></a><br />
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
</div>
<div>
<br /></div>
<h4>
Capturing Video from Raspberry Pi Camera</h4>
<div>
<a href="http://www.raspberrypi.org/product/camera-module/" target="_blank">Raspberry Pi Camera</a> is a high definition camera producing video data in raw H 264 format.<br />
<br />
To control and capture the video Raspberry provides the console application '<span style="font-family: Courier New, Courier, monospace;">raspivid</span>' which can be executed with various parameters specifying how the video shall be captured. E.g. you can specify parameters like width, height or frames per seconds as well as if the video shall be produced to a file or to stdout (standard output).<br />
<br />
Also the service implemented in this example internally uses raspivid. To capture the video the service starts raspivid and then reads incoming video data from raspivid's stdout.<br />
<br />
The service starts raspivid with parameters suitable for live streaming:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">raspivid -n -vf -hf -ih -w 320 -h 240 -fps 24 -t 0 -o -</span><br />
<br />
<table border="0" cellpadding="1" cellspacing="0">
<tbody>
<tr>
<td style="width: 130px;"><span style="font-family: Courier New, Courier, monospace;">-n</span></td>
<td>No preview.</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-vf -hf</span></td>
<td>Flip video vertically and horizontally.</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-ih</span></td>
<td>Insert SPS and PPS inline headers to the video stream (e.g. so that if a second client connects to an ongoing capturing it can synchronize to image frames).</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-w 320 -h 240</span></td>
<td>Produce 320 x 240 pixels video.</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-fps 24</span></td>
<td>Produce video with 24 frames per second.</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-t 0</span></td>
<td>Capture video for infinite time.</td>
</tr>
<tr>
<td><span style="font-family: Courier New, Courier, monospace;">-o -</span></td>
<td>Produce video to standard output (so that it can be captured by the service).</td>
</tr>
</tbody>
</table>
<br />
There are other parameters you can try to play with. To list all of them you can run:<br />
<span style="font-family: Courier New, Courier, monospace;">raspivid -h</span><br />
<br />
<h4>
Streaming Video Across Network</h4>
<div>
Live video data continuously comming from raspivid stdout needs to be transfered across the network to the connected client.<br />
To transfer data the implementation uses <a href="http://www.eneter.net/ProductInfo.htm">Eneter Messaging Framework</a> the lightweight cross-platform library for the interprocess communication.<br />
<br /></div>
<div>
To avoid serialization/deserialization the communication is based directly on duplex channels. It means the service application running on Raspberry Pi uses duplex input channel and the .NET client running on PC uses duplex output channel.<br />
Then when a chunk of video data is read from raspivid stdout the service uses the duplex input channel to send data to connected clients. The .NET client then uses duplex output channel to receive the video data and to notify it for further processing (e.g. displaying).</div>
<div>
<br /></div>
<h4>
Processing and Displaying Video by .NET Client</h4>
<div>
Although H 264 is a very common encoding it is not a trivial task to play the live video encoded in this codec.</div>
<div>
<br /></div>
<div>
The major problem is Media Element (UI control from WPF) does not support playing video from a memory stream or just from an array of bytes. It expects a path to a local file or URL.</div>
<div>
I found <a href="http://social.msdn.microsoft.com/Forums/vstudio/en-US/6191ef1a-0010-4294-a5b4-451bbadca33a/directshowwebcam-in-wpf-natively-test-project?forum=wpf">some hack</a> proposing to register own protocol so that when the protocol name appears in URI the registered library will get the call but I did not want to go for such solution.</div>
<div>
Another problem is that if you have Windows Vista (or Windows XP) you would have to install codecs for H 264 (and when I did so I still did not manage to play raw H 264 bytes stored in the file).</div>
<div>
<br /></div>
<div>
Another alternative is to use VLC library from <a href="http://www.videolan.org/vlc/">Video Lan</a>. Although VLC does not support playing from the memory stream or from the array of bytes it supports playing video from the named pipe. It means if the video source is specified like<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">stream://\\\.\pipe\MyPipeName</span><br />
<br />
then VLC will try to open MyPipeName and play the video.</div>
<div>
<br /></div>
<div>
But also this is not out of the box solution.</div>
<div>
The major problem is the VLC library exports just pure C methods. And so it does not contain a WPF based UI control you can just drag and drop into your UI.</div>
<div>
There are several wrappers implementing UI controls based on VLC (e.g. very promising solution I tested is <a href="http://www.codeproject.com/Articles/109639/nVLC">nVLC</a> implemented by Roman Ginzburg) but these implementations look quite complex.</div>
<div>
<br /></div>
<div>
I like the approach described by Richard Starkey (<a href="http://www.helyar.net/2009/libvlc-media-player-in-c/">part 1</a> and <a href="http://www.helyar.net/2009/libvlc-media-player-in-c-part-2/">part 2</a>) to provide just a thin wrapper and to use the VLC functionality directly. The advantage of this approach is the solution is lightweight and give you the full flexibility. And as you can see from the implementation of the .NET client it is really not difficult to use.</div>
<div>
So I have slightly reworked Richard's original code and used it for the implementation of the .NET client. The implementation of the whole wrapper can be found in the <span style="font-family: Courier New, Courier, monospace;">VLC.cs</span> file.</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
<h3>
To Run Example</h3>
<div>
<b>Downloads</b></div>
<ol>
<li>Download and unzip this example.</li>
<li>Download 'Eneter for .NET' and 'Eneter for Java' from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.</li>
<li>Download and install VLC media player from <a href="https://www.videolan.org/">https://www.videolan.org/</a>. (VLC libraries will be used by .NET application to play the video stream)</li>
</ol>
<b>Raspberry Pi service application</b><br />
<ol>
<li>Open Java project <span style="font-family: Courier New, Courier, monospace;">raspberry-camera-service</span> in Eclipse and add reference to <span style="font-family: Courier New, Courier, monospace;">eneter-messaging.jar</span> which you downloaded.<br /><i>(Right click on the project -> Properties -> Java Build Path -> Libraries -> Add External Jars -> eneter-messaging-6.0.1.jar)</i></li>
<li>Build the project and then export it to executable jar.<br /><i>(Right click on the project -> Export... -> Java -> Runable JAR file -> Launch configuration -> Export Destination -> Package required libraries into generated JAR -> Finish.)</i></li>
<li>Copy the generated jar to the Raspberry device.</li>
<li>Start the application<br /><span style="font-family: Courier New, Courier, monospace;">java -jar raspberry-camera-service.jar</span></li>
</ol>
<b>.NET Client Application</b><br />
<ol>
<li>Open <span style="font-family: Courier New, Courier, monospace;">RaspberryCameraClient</span> solution and add reference to <span style="font-family: Courier New, Courier, monospace;">Eneter.Messaging.Framework.dll</span> which you downloaded.</li>
<li>Check if the path VLC is correct in <span style="font-family: 'Courier New', Courier, monospace;">MainWindow.xaml.cs.</span></li>
<li>Provide correct IP address to your Raspberry Pi service in <span style="font-family: Courier New, Courier, monospace;">MainWindow.xaml.cs</span>.</li>
<li>Compile and run.</li>
<li>Press 'Start Capturing'.</li>
</ol>
<br />
<div>
<br /></div>
<h3>
Raspberry Pi Service Application</h3>
<div>
Raspberry Pi Service is a simple console application implemented in Java. It listens for clients. When a client connects it starts the 'raspivid' application with specific parameters to start video capturing. Then it consumes the stdout from 'raspivid' and forwards video data to the connected client.</div>
<div>
<br /></div>
<div>
The code is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: java">package eneter.camera.service;
import java.io.InputStream;
import java.util.HashSet;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import eneter.messaging.messagingsystems.udpmessagingsystem.UdpMessagingSystemFactory;
import eneter.net.system.EventHandler;
class CameraService
{
// Channel used to response the image.
private IDuplexInputChannel myVideoChannel;
private Process myRaspiVidProcess;
private InputStream myVideoStream;
private HashSet<String> myConnectedClients = new HashSet<String>();
private boolean myClientsUpdatedFlag;
private Object myConnectionLock = new Object();
public void startService(String ipAddress, int port) throws Exception
{
try
{
// Use TCP messaging.
// Note: you can try UDP or WebSockets too.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
//IMessagingSystemFactory aMessaging = new UdpMessagingSystemFactory();
myVideoChannel = aMessaging.createDuplexInputChannel("tcp://" + ipAddress + ":" + port + "/");
myVideoChannel.responseReceiverConnected().subscribe(myClientConnected);
myVideoChannel.responseReceiverDisconnected().subscribe(myClientDisconnected);
myVideoChannel.startListening();
}
catch (Exception err)
{
stopService();
throw err;
}
}
public void stopService()
{
if (myVideoChannel != null)
{
myVideoChannel.stopListening();
}
}
private void onClientConnected(Object sender, ResponseReceiverEventArgs e)
{
EneterTrace.info("Client connected.");
try
{
synchronized (myConnectionLock)
{
myConnectedClients.add(e.getResponseReceiverId());
myClientsUpdatedFlag = true;
// If camera is not running start it.
if (myRaspiVidProcess == null)
{
// Captured video: 320x240 pixels, 24 frames/s
// And it also inserts SPS and PPS inline headers (-ih) so that
// later connected clients can synchronize to ongoing video frames.
String aToExecute = "raspivid -n -vf -hf -ih -w 320 -h 240 -fps 24 -t 0 -o -";
myRaspiVidProcess = Runtime.getRuntime().exec(aToExecute);
myVideoStream = myRaspiVidProcess.getInputStream();
Thread aRecordingThread = new Thread(myCaptureWorker);
aRecordingThread.start();
}
}
}
catch (Exception err)
{
String anErrorMessage = "Failed to start video capturing.";
EneterTrace.error(anErrorMessage, err);
return;
}
}
private void onClientDisconnected(Object sender, ResponseReceiverEventArgs e)
{
EneterTrace.info("Client disconnected.");
synchronized (myConnectionLock)
{
myConnectedClients.remove(e.getResponseReceiverId());
myClientsUpdatedFlag = true;
// If no client is connected then turn off the camera.
if (myConnectedClients.isEmpty() && myRaspiVidProcess != null)
{
myRaspiVidProcess.destroy();
myRaspiVidProcess = null;
}
}
}
private void doCaptureVideo()
{
try
{
String[] aClients = {};
byte[] aVideoData = new byte[4096];
while (myVideoStream.read(aVideoData) != -1)
{
// Only if amount of connected clients changed update
// the local list.
if (myClientsUpdatedFlag)
{
aClients = new String[myConnectedClients.size()];
synchronized (myConnectionLock)
{
myConnectedClients.toArray(aClients);
myClientsUpdatedFlag = false;
}
}
for (String aClient : aClients)
{
try
{
// Send captured data to all connected clients.
myVideoChannel.sendResponseMessage(aClient, aVideoData);
}
catch (Exception err)
{
// Ignore if sending to one of clients failed.
// E.g. in case it got disconnected.
}
}
}
}
catch (Exception err)
{
// Stream from raspivid got closed.
}
EneterTrace.info("Capturing thread ended.");
}
private EventHandler<ResponseReceiverEventArgs> myClientConnected
= new EventHandler<ResponseReceiverEventArgs>()
{
@Override
public void onEvent(Object sender, ResponseReceiverEventArgs e)
{
onClientConnected(sender, e);
}
};
private EventHandler<ResponseReceiverEventArgs> myClientDisconnected
= new EventHandler<ResponseReceiverEventArgs>()
{
@Override
public void onEvent(Object sender, ResponseReceiverEventArgs e)
{
onClientDisconnected(sender, e);
}
};
private Runnable myCaptureWorker = new Runnable()
{
@Override
public void run()
{
doCaptureVideo();
}
};
}
</pre>
</div>
<div>
<br /></div>
<h3>
.NET Client Application</h3>
<div>
.NET client is a simple WPF based application. When a user clicks on 'Start Capturing' button it creates the named pipe and sets VLC to use this named pipe as the video source. It also sets VLC to expect raw H 264 encoded video data. Then using Eneter it opens the connection with the Raspberry Pi service.</div>
<div>
Streamed video is then received in the OnResponseMessageReceived(...) method which just writes it to the named pipe.<br />
<br />
<span style="color: red;">Please do not forget to provide correct IP address to your Raspberry Pi and check if you do not need to update the path to VLC.</span></div>
<div>
<br /></div>
<div>
The code is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using System;
using System.IO.Pipes;
using System.Threading;
using System.Windows;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.MessagingSystems.UdpMessagingSystem;
using VLC;
namespace RaspberryCameraClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private IDuplexOutputChannel myVideoChannel;
// VLC will read video from the named pipe.
private NamedPipeServerStream myVideoPipe;
private VlcInstance myVlcInstance;
private VlcMediaPlayer myPlayer;
public MainWindow()
{
InitializeComponent();
System.Windows.Forms.Panel aVideoPanel = new System.Windows.Forms.Panel();
aVideoPanel.BackColor = System.Drawing.Color.Black;
VideoWindow.Child = aVideoPanel;
// If not installed in Provide path to your VLC.
myVlcInstance = new VlcInstance(@"c:\Program Files\VideoLAN\VLC\");
// Use TCP messaging.
// You can try to use UDP or WebSockets too.
myVideoChannel = new TcpMessagingSystemFactory()
//myVideoChannel = new UdpMessagingSystemFactory()
// Note: Provide address of your service here.
.CreateDuplexOutputChannel("tcp://192.168.1.17:8093/");
myVideoChannel.ResponseMessageReceived += OnResponseMessageReceived;
}
private void Window_Closed(object sender, EventArgs e)
{
StopCapturing();
}
private void OnStartCapturingButtonClick(object sender, RoutedEventArgs e)
{
StartCapturing();
}
private void OnStopCapturingButtonClick(object sender, RoutedEventArgs e)
{
StopCapturing();
}
private void StartCapturing()
{
// Use unique name for the pipe.
string aVideoPipeName = Guid.NewGuid().ToString();
// Open pipe that will be read by VLC.
myVideoPipe = new NamedPipeServerStream(@"\" + aVideoPipeName,
PipeDirection.Out, 1,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 0, 32764);
ManualResetEvent aVlcConnectedPipe = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(x =>
{
myVideoPipe.WaitForConnection();
// Indicate VLC has connected the pipe.
aVlcConnectedPipe.Set();
});
// VLC connects the pipe and starts playing.
using (VlcMedia aMedia = new VlcMedia(myVlcInstance, @"stream://\\\.\pipe\" + aVideoPipeName))
{
// Setup VLC so that it can process raw h264 data (i.e. not in mp4 container)
aMedia.AddOption(":demux=H264");
myPlayer = new VlcMediaPlayer(aMedia);
myPlayer.Drawable = VideoWindow.Child.Handle;
// Note: This will connect the pipe and read the video.
myPlayer.Play();
}
// Wait until VLC connects the pipe so that it is ready to receive the stream.
if (!aVlcConnectedPipe.WaitOne(5000))
{
throw new TimeoutException("VLC did not open connection with the pipe.");
}
// Open connection with service running on Raspberry.
myVideoChannel.OpenConnection();
}
private void StopCapturing()
{
// Close connection with the service on Raspberry.
myVideoChannel.CloseConnection();
// Close the video pipe.
if (myVideoPipe != null)
{
myVideoPipe.Close();
myVideoPipe = null;
}
// Stop VLC.
if (myPlayer != null)
{
myPlayer.Dispose();
myPlayer = null;
}
}
private void OnResponseMessageReceived(object sender, DuplexChannelMessageEventArgs e)
{
byte[] aVideoData = (byte[])e.Message;
// Forward received data to the named pipe so that VLC can process it.
myVideoPipe.Write(aVideoData, 0, aVideoData.Length);
}
}
}
</pre>
</div>
<div>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com2tag:blogger.com,1999:blog-5196103582241137578.post-73748742639480486472014-06-29T12:26:00.001+02:002016-06-21T20:50:01.050+02:00Remote Procedure Calls between .NET and Java using TCPSimple example showing RPC communication between .NET and Java.<br />
<br />
<a name='more'></a>The source code for this example can be downloaded from:<br />
<a href="http://www.eneter.net/Downloads/Examples/RpcCalculatorJavaService.zip">http://www.eneter.net/Downloads/Examples/RpcCalculatorJavaService.zip</a><br />
<br />
To use the example please download Eneter for .NET and Java from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a> and add the Eneter library into the project.<br />
<br />
<br />
<h3>
Introduction</h3>
<div>
<div>
This article is a free continuation of <a href="http://eneter.blogspot.de/2014/03/remote-procedure-calls-between-android.html">Remote Procedure Calls between Android and .NET</a> where Android is a client application and .NET is a service application.</div>
<div>
<br /></div>
<div>
The example bellow demonstrates how to use RPC between .NET and Java where .NET is the client application and Java is the service application.</div>
</div>
<div>
<br />
<br /></div>
<h3>
RPC between .NET and Java</h3>
<div>
<div>
As already described in the previous article RPC is a request-response communication where one application (typically client) requests to invoke a method in another application (typically service).</div>
<div>
<br /></div>
<div>
Therefore the key aspect in RPC is exposing methods which can be remotely invoked. The Eneter framework allows to specify these methods via the 'interface' keyword which is supported by both Java and C# languages.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgERpcRQxUbLVNUmUyN6nCDmutP6-gjlHmlfVZFIOJAZgoYd2YwoCISLysALHxu3FpTHO2dV8hTgDJOb1SMa9JLerLHjd_NNxWYDekWopd8__jwSJUPF4IEDylmbC50vnS1F_JdWgjrYXHk/s1600/RPCCommunicationNETJava.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgERpcRQxUbLVNUmUyN6nCDmutP6-gjlHmlfVZFIOJAZgoYd2YwoCISLysALHxu3FpTHO2dV8hTgDJOb1SMa9JLerLHjd_NNxWYDekWopd8__jwSJUPF4IEDylmbC50vnS1F_JdWgjrYXHk/s640/RPCCommunicationNETJava.png" width="640" /></a></div>
<div>
<br /></div>
<div>
For declaring the interface that shall work across .NET and Java it is important declarations in both environments are identical.</div>
<div>
<ul>
<li>Methods must have same names (names are case sensitive).</li>
<li>Input parameters must be of same types.</li>
<li>Input parameters must be in same order.</li>
</ul>
</div>
</div>
<div>
Due to language differences there are also following restrictions:</div>
<div>
<ul>
<li>Generics are not supported.</li>
<li>Overloading of methods is not allowed.</li>
</ul>
</div>
<br />
In general to declare, expose and use the interface between .NET and Java you need to do following steps:
<br />
<div>
On the service side:</div>
<div>
<div>
<ol>
<li>Declare API interface that shall be exposed (see ICalculator interface in Java).</li>
<li>Provide implementation for the interface (see Calculator class).</li>
<li>Use Eneter to expose the interface (see using RpcFactory instantiating IRpcService).</li>
<li>Use Eneter to start listening via TCP, WebSocket or UDP (see attaching the input channel to IRpcService).</li>
</ol>
</div>
<div>
On the client side:</div>
<div>
<ol>
<li>Declare identical API interface as in the service (see ICalculator interface in C#).</li>
<li>Use Eneter to provide the proxy implementation for the interface (see using RpcFactory instantiating IRpcClient).</li>
<li>Use Eneter to connect the proxy implementation with the service (see attaching the output channel to IRpcClient).</li>
<li>Use the 'Proxy' property to call methods from the interface.</li>
</ol>
<br />
<ol>
</ol>
<h3>
Java Service Application</h3>
<div>
The service is a simple console application that calculates numbers. It exposes ICalculation interface which declares methods that can be called from a .NET application.</div>
<div>
<br /></div>
<div>
Declaration of the interface:</div>
<div>
<br /></div>
<div>
<pre class="brush: java">/**
* Declares calculator service methods.
*/
public interface ICalculator
{
double sum(double a, double b);
double subtract(double a, double b);
double multiplay(double a, double b);
double divide(double a, double b);
}
</pre>
</div>
<div>
Implementation of the interface:</div>
<div>
<br /></div>
<div>
<pre class="brush: java">/**
* Implements service methods.
*/
public class Calculator implements ICalculator
{
@Override
public double sum(double a, double b)
{
return a + b;
}
@Override
public double subtract(double a, double b)
{
return a - b;
}
@Override
public double multiplay(double a, double b)
{
return a * b;
}
@Override
public double divide(double a, double b)
{
return a / b;
}
}
</pre>
</div>
<div>
Listening console application exposing the interface:</div>
<div>
<pre class="brush: java">package calculator;
import java.io.*;
import eneter.messaging.endpoints.rpc.*;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
public class Program
{
public static void main(String[] args) throws Exception
{
// Instantiate the calculator.
Calculator aCalculator = new Calculator();
// Expose the calculator as a service.
RpcFactory anRpcFactory = new RpcFactory();
IRpcService<ICalculator> aService =
anRpcFactory.createSingleInstanceService(aCalculator, ICalculator.class);
// Use TCP.
// Note: You can use other protocols e.g. WebSockets too.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.createDuplexInputChannel("tcp://127.0.0.1:8045/");
// Attach input channel and start listening.
aService.attachDuplexInputChannel(anInputChannel);
System.out.println("Calculator service is running. Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
// Detach input channel and stop listening.
aService.detachDuplexInputChannel();
}
}
</pre>
</div>
<div>
<br />
<br /></div>
<h3>
.NET Client Application</h3>
<div>
The client is a simple WinForm application using the Java service to calculate numbers. It declares the same interface like the Java service and uses RPC from Eneter framework to communicate with the Java service.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace CalculatorClient2
{
public partial class Form1 : Form
{
// Declare same interface as in Java service application.
// Note: do not forget case-sensitiveness. If Java methods start with
// small letters then also these methods must start with small letters.
public interface ICalculator
{
double sum(double a, double b);
double subtract(double a, double b);
double multiplay(double a, double b);
double divide(double a, double b);
}
private IRpcClient<ICalculator> myRpcClient;
public Form1()
{
InitializeComponent();
// Get RPC client for declared service interface.
IRpcFactory anRpcFactory = new RpcFactory();
myRpcClient = anRpcFactory.CreateClient<ICalculator>();
// Attach output channel and be able to communicate.
TcpMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8045/");
myRpcClient.AttachDuplexOutputChannel(anOutputChannel);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Stop listening by detaching the input channel.
myRpcClient.DetachDuplexOutputChannel();
}
private void SumButton_Click(object sender, EventArgs e)
{
double a = double.Parse(Number1TextBox.Text);
double b = double.Parse(Number2TextBox.Text);
ResultLabel.Text = myRpcClient.Proxy.sum(a, b).ToString();
}
private void SubtractButton_Click(object sender, EventArgs e)
{
double a = double.Parse(Number1TextBox.Text);
double b = double.Parse(Number2TextBox.Text);
ResultLabel.Text = myRpcClient.Proxy.subtract(a, b).ToString();
}
private void MultiplyButton_Click(object sender, EventArgs e)
{
double a = double.Parse(Number1TextBox.Text);
double b = double.Parse(Number2TextBox.Text);
ResultLabel.Text = myRpcClient.Proxy.multiplay(a, b).ToString();
}
private void DivideButton_Click(object sender, EventArgs e)
{
double a = double.Parse(Number1TextBox.Text);
double b = double.Parse(Number2TextBox.Text);
ResultLabel.Text = myRpcClient.Proxy.divide(a, b).ToString();
}
}
}
</pre>
</div>
</div>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com8tag:blogger.com,1999:blog-5196103582241137578.post-67501090697254279262014-05-17T21:05:00.004+02:002016-01-09T08:57:50.249+01:00WinForm Application as ServiceSimple example showing WinForm application as a service. It also shows how to set the threading model so that Eneter dispatches messages in main UI thread.<br />
<div>
<a name='more'></a><br />
The source code for this example can be <a href="http://www.eneter.net/Downloads/Examples/WinFormService.zip">downloaded here</a>.</div>
<div>
<br /></div>
<h3>
Introduction</h3>
<div>
I typically use a console application as a service in my examples. I have received several questions regarding how to implement the service as a WinForm application. So I have decided to write a separate article demonstrating this possibility.</div>
<div>
<br /></div>
<div>
The example bellow implements a simple request-response communication between two WinForm applications.</div>
<div>
The service WinForm application allows to start and stop the service with a button and it maintains a list of connected clients in the listbox. Then it allows to send a message to the selected client and it also allows to disconnect the selected client.</div>
<div>
The client WinForm application allows to connect or disconnect the service with a button. It also allows to send a message to the service and receive a message from the service.</div>
<div>
<br /></div>
<h4>
To Run Example</h4>
<div>
<ol>
<li><a href="http://www.eneter.net/ProductDownload.htm">Download Eneter for .NET</a>.</li>
<li>Download this example and open its solution in Visual Studio.</li>
<li>Add Eneter.Messaging.Framework.dll library to 'References' of both projects inside the solution.</li>
<li>Build the solution.</li>
<li>Run WinFormServiceApplication and press 'Start Service'.</li>
<li>Run WinFormClientApplication and press 'Open Connection'.</li>
<li>The client should get connected and should appear in the 'Connected Clients' list.</li>
</ol>
</div>
<h3>
Threading Model</h3>
<div>
To receive messages Eneter framework implements listening threads. When a message is then received it is the listening thread which notifies it. The problem is the listening thread is not the main UI thread. Therefore it is not possible to use this thread to access UI controls.</div>
<div>
To overcome this issue Eneter allows to specify the threading model. It means it allows to specify in which thread events receiving messages or notifying connection/disconnection shall be dispatched.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdpThUAsCM8MX9uBh2w-gPk3S5p4YsDXc6WCVEyt0ebm21NEIYlaztOJ8LG6cnmW7PjN-VUCSuonNYn4W9tRcSVuiqhrQJvROovM6Xv5B9ZvxLnciiF1qRZL5Bre8NKkXu9gXJa3zOVCqR/s1600/WinFormServiceExample.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdpThUAsCM8MX9uBh2w-gPk3S5p4YsDXc6WCVEyt0ebm21NEIYlaztOJ8LG6cnmW7PjN-VUCSuonNYn4W9tRcSVuiqhrQJvROovM6Xv5B9ZvxLnciiF1qRZL5Bre8NKkXu9gXJa3zOVCqR/s640/WinFormServiceExample.png" width="640" /></a><br />
<br /></div>
<div>
Eneter provides <a href="http://www.eneter.net/OnlineHelp/EneterMessagingFramework/html/N_Eneter_Messaging_Threading_Dispatching.htm">several threading models</a>. The example bellow uses WinFormsDispatching which ensures messages are received in the main UI thread.</div>
<div>
<br /></div>
<h3>
WinForm Service Application</h3>
<div>
The implementation of the service as a WinForm application is very similar to implement it as a console application. The only difference is you must consider the threading model.</div>
<div>
It means whether you want Eneter to notify messages in the main UI thread or not.</div>
<div>
If not then you cannot access UI controls directly but you must dispatch the access to the main UI thread.</div>
<div>
If yes then Eneter makes the dispatching for you and you can access UI controls.</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
namespace WinFormServiceApplication
{
public partial class Form1 : Form
{
// Receive string messages and send back string messages.
IDuplexTypedMessageReceiver<string, string> myReceiver;
public Form1()
{
InitializeComponent();
// Create message receiver.
// Note: it receives string and sends back string.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
myReceiver = aReceiverFactory.CreateDuplexTypedMessageReceiver<string, string>();
// Subscribe to get notified when a client connects, disconnects
// or sends a message.
myReceiver.ResponseReceiverConnected += OnClientConnected;
myReceiver.ResponseReceiverDisconnected += OnClientDisconnected;
myReceiver.MessageReceived += OnMessageReceived;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Detach input channel and stop listening.
myReceiver.DetachDuplexInputChannel();
}
private void OnClientConnected(object sender, ResponseReceiverEventArgs e)
{
// Add the client id to the listbox.
// Note: we can directly access the listbox because we set threading mode of
// InputChannelThreading to the main UI thread.
ConnectedClientsListBox.Items.Add(e.ResponseReceiverId);
}
private void OnClientDisconnected(object sender, ResponseReceiverEventArgs e)
{
// Remove the client from the listbox.
// Note: we can directly access the listbox because we set threading mode of
// InputChannelThreading to the main UI thread.
ConnectedClientsListBox.Items.Remove(e.ResponseReceiverId);
}
private void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<string> e)
{
// Insert received message at the beginning of the listbox.
// Note: we can directly access the listbox because we set threading mode of
// InputChannelThreading to the main UI thread.
ReceivedMessagesListBox.Items.Insert(0, e.RequestMessage);
}
private void StartServiceBtn_Click(object sender, EventArgs e)
{
if (myReceiver.IsDuplexInputChannelAttached)
{
// The channel is already attached so nothing to do.
return;
}
// Use TCP communication
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory()
{
// Set to receive messages in the main UI thread.
// Note: if this is not set then methods OnMessageReceived, OnClientConnected
// and OnClientDisconnected would not be called from main UI thread
// but from a listener thread.
InputChannelThreading = new WinFormsDispatching(this)
};
// Create input channel.
IDuplexInputChannel anInputChannel
= aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8033/");
// Attach the input channel and be able to receive messages
// and send back response messages.
myReceiver.AttachDuplexInputChannel(anInputChannel);
ServiceStatusLabel.Text = "Service Running";
}
private void StopServiceBtn_Click(object sender, EventArgs e)
{
// Detach input channel and stop listening.
myReceiver.DetachDuplexInputChannel();
ServiceStatusLabel.Text = "Service Not Running";
}
private void SendMessageBtn_Click(object sender, EventArgs e)
{
string aClientId = GetSelectedClient();
if (!string.IsNullOrEmpty(aClientId))
{
string aMessage = MessageTextBox.Text;
// Send message to client which is selected in the listbox.
myReceiver.SendResponseMessage(aClientId, aMessage);
}
}
private void DisconnectClientBtn_Click(object sender, EventArgs e)
{
// Disconnect client which is selected in the listbox.
string aClientId = GetSelectedClient();
if (!string.IsNullOrEmpty(aClientId))
{
myReceiver.AttachedDuplexInputChannel.DisconnectResponseReceiver(aClientId);
}
}
private string GetSelectedClient()
{
string aClientId = ConnectedClientsListBox.SelectedItem as string;
return aClientId;
}
}
}
</pre>
</div>
<div>
The implementation is very simple:</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
WinForm Client Application</h3>
<div>
I used WinForm application as client in many previous examples. Therefore there is nothing new here.</div>
<div>
<br /></div>
<div>
The implementation is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: csharp">using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Threading.Dispatching;
namespace WinFormClientApplication
{
public partial class Form1 : Form
{
// Sender which sends string request messages
// and receives string response messages.
IDuplexTypedMessageSender<string, string> mySender;
public Form1()
{
InitializeComponent();
// Create message sender.
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory();
mySender = aSenderFactory.CreateDuplexTypedMessageSender<string, string>();
// Subscribe to handle when a message is received or if the client
// is disconnected.
mySender.ConnectionClosed += OnConnectionClosed;
mySender.ResponseReceived += OnResponseReceived;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
mySender.DetachDuplexOutputChannel();
}
private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<string> e)
{
// Insert the received message at the beginning of the listbox.
// Note: we can directly access the UI control here because we set threading mode of
// OutputChannelThreading to the main UI thread.
ReceivedMessagesListBox.Items.Add(e.ResponseMessage);
}
private void OnConnectionClosed(object sender, DuplexChannelEventArgs e)
{
// The client got disconnected so set the status.
// Note: we can directly access the UI control here because we set threading mode of
// OutputChannelThreading to the main UI thread.
ConnectionStatusLabel.Text = "Client Not Connected";
}
private void OpenConnectionBtn_Click(object sender, EventArgs e)
{
if (!mySender.IsDuplexOutputChannelAttached)
{
// The output channel is not attached yet.
// So attach the output channel and be able to send
// request messagas and receive response messages.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory()
{
// Set to receive messages in the main UI thread.
// Note: if this is not set then methods OnResponseReceived and
// OnConnectionClosed would not be called from main UI thread
// but from a listener thread.
OutputChannelThreading = new WinFormsDispatching(this)
};
IDuplexOutputChannel anOutputChannel
= aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8033/");
mySender.AttachDuplexOutputChannel(anOutputChannel);
ConnectionStatusLabel.Text = "Client Connected";
}
else if (!mySender.AttachedDuplexOutputChannel.IsConnected)
{
// The output channel is attached but the client got disconnected.
// So jut reopen the connection.
mySender.AttachedDuplexOutputChannel.OpenConnection();
ConnectionStatusLabel.Text = "Client Connected";
}
}
private void CloseConnectionBtn_Click(object sender, EventArgs e)
{
mySender.DetachDuplexOutputChannel();
}
private void SendMessageBtn_Click(object sender, EventArgs e)
{
// If the client is connected to the service.
if (mySender.IsDuplexOutputChannelAttached &&
mySender.AttachedDuplexOutputChannel.IsConnected)
{
string aMessage = MessageTextBox.Text;
mySender.SendRequestMessage(aMessage);
}
}
}
}
</pre>
</div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com11tag:blogger.com,1999:blog-5196103582241137578.post-60016552052823829912014-05-11T14:58:00.000+02:002016-01-09T08:59:34.129+01:00HTML5: Request-Response Communication Using WebSocketsSimple example showing request-'multiple response' communication between HTML5 JavaScript and .NET using the WebSocket protocol.<br />
<br />
<a name='more'></a><br />
The source code for this example can be <a href="http://eneter.net/Downloads/Examples/PiCalculator.zip">downloaded here</a>.<br />
<br />
<h3>
Introduction</h3>
<div>
This is a free continuation of <a href="http://eneter.blogspot.de/2014/05/html5-real-time-push-notifications-from.html">HTML5: Real-Time Push Notifications from .NET Application</a> that shows how to push notification messages instantly without using polling or long-polling mechanism.</div>
<div>
<br /></div>
<div>
The example bellow demonstrates another type of scenario. It shows request-'multiple response' communication where JavaScript sends a request message and .NET application sends back multiple response messages.</div>
<div>
<br /></div>
<div>
The communication is realized via <a href="http://www.websocket.org/">WebSockets</a> (full-duplex single socket connection) and therefore it is not needed to use polling or long-polling mechanism to obtain multiple responses (as would be used in case of HTTP protocol).</div>
<div>
Using WebSockets allows to open connection and keep it open as long as needed. While the connection is open the client can send multiple request messages and the service can send multiple response messages whenever needed.</div>
<div>
<br /></div>
<div>
The example is based on <a href="http://www.eneter.net/ProductInfo.htm">Eneter Messaging Framework</a> the free lightweight cross-platform framework for the interprocess communication:<br />
<ul>
<li><a href="http://www.eneter.net/OnlineHelp/EneterMessagingFrameworkJavaScript/index.html">Eneter for JavaScript API documentation</a>.</li>
<li><a href="http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html">Eneter for .NET API documentation</a>.</li>
</ul>
</div>
<div>
<br /></div>
<h3>
Example Application</h3>
<div>
In order to demonstrate the request-'multiple response' scenario between JavaScript and .NET the example bellow implements a simple HTML 5 web-page and a simple .NET console application.</div>
<div>
The HTML 5 web-page is a client which opens the WebSocket connection with .NET and requests to calculate the PI number.</div>
<div>
The .NET console application acts as a service. When it receives a request it starts to calculate the PI number and after each calculation step it responses to the web-page the current result.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9r7L_ubwhz3Yz2BcyeBAkPquBQg9SPTmNoF0aTEUDGA8zlUAXcFI22_omCUbpocBayAod02PHH50_WAg5xKXgRpdYPe5PR_qYyz0L4eXH2U81kg3NbYYNIxXwbM9f8_icyV6TsAyA8qrg/s1600/RequestResponseBetweenJSNET.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9r7L_ubwhz3Yz2BcyeBAkPquBQg9SPTmNoF0aTEUDGA8zlUAXcFI22_omCUbpocBayAod02PHH50_WAg5xKXgRpdYPe5PR_qYyz0L4eXH2U81kg3NbYYNIxXwbM9f8_icyV6TsAyA8qrg/s640/RequestResponseBetweenJSNET.png" width="640" /></a></div>
<h4>
To Run Example</h4>
<div>
<ul>
<li>Download and unzip this example.</li>
<li>Download Eneter for .NET from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.</li>
<li>Open the example project in Visual Studio and add the reference to Eneter.Messaging.Framework.dll that you downloaded.</li>
<li>Build the application and execute it.</li>
<li>Open index.html (from HTML5PiClient directory) in an internet browser.</li>
<li>Press 'Open Connection' button and then 'Calculate PI' button.</li>
<li>You will see the web-page will get several responses and finally it will display the calculated PI number.</li>
</ul>
<br />
<ul>
</ul>
</div>
<h3>
.NET Service Application</h3>
<div>
The service application is a simple .NET console application listening via WebSockets to clients. When a client connects and sends the request it calculate the PI number in the loop and sends back responses containing the current state of the calculation.</div>
<div>
The service uses JSON serialization so that the web client application can deserialize it.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
<div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.WebSocketMessagingSystem;
namespace PiService
{
public class PiRequestMessage
{
public double CalculationStep { get; set; }
}
public class PiResponseMessage
{
public double Result { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Use JSON serializer which can be used by JavaScript too.
ISerializer aJsonSerialzier = new DataContractJsonStringSerializer();
// Factory to create message receivers.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory(aJsonSerialzier);
// Create message receiver.
IDuplexTypedMessageReceiver<PiResponseMessage, PiRequestMessage> aReceiver
= aReceiverFactory.CreateDuplexTypedMessageReceiver<PiResponseMessage, PiRequestMessage>();
// Subscribe to process incoming messages.
aReceiver.MessageReceived += OnMessageReceived;
// Subscribe to observe client connections/disconnections.
aReceiver.ResponseReceiverConnected += OnClientConnected;
aReceiver.ResponseReceiverDisconnected += OnClientDisconnected;
// Use WebSocket for the communication.
IMessagingSystemFactory aMessaging = new WebSocketMessagingSystemFactory();
// Attach input channel and be able to receive request messages
// and send back response messages.
IDuplexInputChannel anInputChennel = aMessaging.CreateDuplexInputChannel("ws://127.0.0.1:8091/PiCalculator/");
aReceiver.AttachDuplexInputChannel(anInputChennel);
Console.WriteLine("Pi service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach input channel and stop listening.
// Note: it releases the listening thread.
aReceiver.DetachDuplexInputChannel();
}
// Method which is invoked when the request message is received.
static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<PiRequestMessage> e)
{
// Get the receiver instance.
IDuplexTypedMessageReceiver<PiResponseMessage, PiRequestMessage> aReceiver
= (IDuplexTypedMessageReceiver<PiResponseMessage, PiRequestMessage>)sender;
PiResponseMessage aResponseMessage = new PiResponseMessage();
// Calculate PI and send back multiple response messages.
double aResult = 0.0;
double aDx = e.RequestMessage.CalculationStep;
for (double x = -1.0; x < 1.0; x += aDx)
{
aResult += 2 * Math.Sqrt(1 - x * x) * aDx;
// Send back the current result.
// Note: ResponseReceiverId identifies the client who sent the request.
aResponseMessage.Result = aResult;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
private static void OnClientConnected(object sender, ResponseReceiverEventArgs e)
{
Console.WriteLine("Client connected: " + e.ResponseReceiverId);
}
private static void OnClientDisconnected(object sender, ResponseReceiverEventArgs e)
{
Console.WriteLine("Client disconnected: " + e.ResponseReceiverId);
}
}
}
</pre>
</div>
<div>
<br /></div>
<h3>
JavaScript Client</h3>
<div>
The JavaScript client is a simple HTML 5 web-page. It uses Eneter for JavaScript to send request messages and receive responses. It allows to open the connection with the service and send the request message to calculate the PI number. Then it receives multiple response messages as the service proceeds with the calculation.</div>
<div>
<br /></div>
<div>
The implementation of the web-page is very simple:</div>
<div>
<br /></div>
<div>
<pre class="brush: js; html-script: true"><!DOCTYPE html>
<html>
<head>
<title>PI Calculator Client</title>
<!-- Import Eneter for JavaScript -->
<script src="eneter-messaging-6.0.1.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body onunload="closeConnection();">
<div>
<input type="button" onclick="openConnection();" value="Open Connection" /><br/>
<br/>
Calculation Step: <input id="CalculationStep" type="number" value="0.001" />
<input type="submit" onclick="calculatePi();" value="Calculate PI" /><br/>
Result: <input type="text" id="Result" value="" /><br/>
<br/>
<input type="button" onclick="closeConnection();" value="Close Connection" />
</div>
<script>
// Create message senders and provide callback to
// process response messages.
var myPiSender = new DuplexTypedMessageSender();
myPiSender.onResponseReceived = onResultReceived;
// Request message structure.
// Note: This structure will be serialized and
// sent as the message.
function PiRequestMessage(calculationStep) {
this.CalculationStep = calculationStep;
}
function openConnection() {
// Attach output channels and be able to send messages
// and receive response messages.
var anOutputChannel =
new WebSocketDuplexOutputChannel("ws://127.0.0.1:8091/PiCalculator/", null);
myPiSender.attachDuplexOutputChannel(anOutputChannel);
};
function closeConnection() {
// Detach output channels and close connections.
myPiSender.detachDuplexOutputChannel();
};
function calculatePi() {
// Create request message.
var aCalculationStep = document.getElementById("CalculationStep").value;
var aRequestMessage = new PiRequestMessage(aCalculationStep);
// Send request to sum numbers.
// Note: the message will be serialized by JSON
// and sent to the service.
// Note: service will send multiple response messages
// per one request message.
myPiSender.sendRequestMessage(aRequestMessage);
};
// Callback method called when a response message is received.
// Note: one request method will cause multiple responses.
function onResultReceived(typedResponseReceivedEventArgs) {
var aNumber = typedResponseReceivedEventArgs.ResponseMessage.Result;
// Display the result.
var anElement = document.getElementById("Result");
anElement.value = aNumber;
};
</script>
</body>
</html>
</pre>
</div>
<div>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com14tag:blogger.com,1999:blog-5196103582241137578.post-39269865121867956262014-05-03T21:28:00.000+02:002016-01-09T09:01:18.203+01:00HTML5: Real-Time Push Notifications from .NET ApplicationSimple example showing publish-subscribe scenario between HTML5 JavaScript and .NET without using polling or long-polling mechanisms.<br />
<br />
<a name='more'></a><br />
The source code for this example can be <a href="http://eneter.net/Downloads/Examples/JavaScriptCpuUsageNotification.zip">downloaded from here</a>.<br />
<br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates a publish-subscribe communication scenario between JavaScript and a .NET application. The HTML5 JavaScript client needs to subscribe for an event (or more events) in the .NET application. When the event occurs the .NET application notifies subscribed clients.</div>
<div>
<br />
The communication is realized via <a href="http://www.websocket.org/">WebSockets</a> (full-duplex single socket connection) and therefore it does not use a polling or long-polling mechanism which would be used in case of the HTTP protocol.<br />
<br />
Notification messages are pushed from the service to all subscribed clients instantly when the event occurs.<br />
<br /></div>
<h3>
Example Application</h3>
<div>
The example application is based on Eneter.Messaging.Framework the lightweight cross-platform framework for the interprocess communication which is very easy to use.</div>
<div>
The example also uses the <a href="http://www.chartjs.org/">Chart.js library</a>. A nice free library for drawing charts.<br />
<br />
<h4>
To Run Example</h4>
<br />
<ul>
<li>Download and unzip this example.</li>
<li>Download Eneter for .NET from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.</li>
<li>Download Eneter for Javascript from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.</li>
<li>Copy Eneter for Javascript into CpuUsageClient directory.</li>
<li>Open index.html file in an editor and ensure it uses the same version of eneter-messaging as you downloaded.</li>
<li>Open the example project in Visual Studio and add the reference to Eneter.Messaging.Framework.dll that you downloaded.</li>
<li>Build the application and execute it.</li>
<li>Open index.html (from CpuUsageClient directory) in an internet browser.</li>
<li>Press 'Open Connection' button and then 'Subscribe' button.</li>
<li>Web-page starts to get notifications and the chart is displayed.</li>
</ul>
</div>
<div>
<br /></div>
<div>
In order to demonstrate the publish-subscribe scenario between JavaScript and .NET the example bellow implements a simple .NET console application and a simple HTML5 web-page.</div>
<div>
The console application regularly checks the CPU usage and notifies its value.</div>
<div>
The HTML5 web-page subscribes to be notified about CPU usage. When it receives the notification it updates the value in the chart.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
</div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEileNDFKOM85JVllV9MT8Nfa6neLFvRBmhrbBrfPfgMW3xoLnV7-D_G3S99IGUbDi_7YTHEqTowK17RB18WLUlvyS6RW6U7VbZ1pKPCZXyAOKywr9tT6XnpWSqyUCt49JnOZil4zWbm_bS4/s1600/PublishSubscribeBetweenJSNET.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEileNDFKOM85JVllV9MT8Nfa6neLFvRBmhrbBrfPfgMW3xoLnV7-D_G3S99IGUbDi_7YTHEqTowK17RB18WLUlvyS6RW6U7VbZ1pKPCZXyAOKywr9tT6XnpWSqyUCt49JnOZil4zWbm_bS4/s640/PublishSubscribeBetweenJSNET.png" width="640" /></a><br />
<br /></div>
<h3>
Using Duplex Broker</h3>
<div>
The core idea of the example is using the duplex broker component from Eneter Messaging Framework. It provides functionality for sending notification events (publishing) as well as for subscribing to desired events.</div>
<div>
When then the duplex broker receives a notification message it forwards it all subscribers which are interested in this type of notification.</div>
<div>
The cross-platform aspect of the Eneter framework ensures messages between JavaScript and .NET are understood (e.g. it takes care about UTF16 vs UTF8 or little-endian vs big-endian).</div>
<div>
<br />
<br /></div>
<h3>
.NET Service Application</h3>
<div>
The service application is a simple .NET console application that regularly checks the CPU usage. Then it uses the broker component to publish the value. The broker searches which clients are subscribed for this type of events and forwards them the message.</div>
<div>
Also because JavaScript uses the JSON serializer the service uses the JSON serializer too. It also sets the duplex broker to use the JSON serializer.<br />
The whole implementation is very simple:</div>
<div>
<pre class="brush: csharp">using System;
using System.Diagnostics;
using System.Threading;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.WebSocketMessagingSystem;
using Eneter.Messaging.Nodes.Broker;
namespace CpuUsageService
{
// Message that will be notified.
public class CpuUpdateMessage
{
public float Usage { get; set; }
}
class Program
{
static void Main(string[] args)
{
// JavaScript uses JSON serializer so set using JSON.
ISerializer aSerializer = new DataContractJsonStringSerializer();
// Create broker.
IDuplexBrokerFactory aBrokerFactory = new DuplexBrokerFactory();
IDuplexBroker aBroker = aBrokerFactory.CreateBroker();
// Communicate using WebSockets.
IMessagingSystemFactory aMessaging = new WebSocketMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("ws://127.0.0.1:8843/CpuUsage/");
anInputChannel.ResponseReceiverConnected += (x, y) =>
{
Console.WriteLine("Connected client: " + y.ResponseReceiverId);
};
anInputChannel.ResponseReceiverDisconnected += (x, y) =>
{
Console.WriteLine("Disconnected client: " + y.ResponseReceiverId);
};
// Attach input channel and start listeing.
aBroker.AttachDuplexInputChannel(anInputChannel);
// Start working thread monitoring the CPU usage.
bool aStopWorkingThreadFlag = false;
Thread aWorkingThread = new Thread(() =>
{
PerformanceCounter aCpuCounter =
new PerformanceCounter("Processor", "% Processor Time", "_Total");
while (!aStopWorkingThreadFlag)
{
CpuUpdateMessage aMessage = new CpuUpdateMessage();
aMessage.Usage = aCpuCounter.NextValue();
//Console.WriteLine(aMessage.Usage);
// Serialize the message.
object aSerializedMessage = aSerializer.Serialize<CpuUpdateMessage>(aMessage);
// Notify subscribers via the broker.
// Note: The broker will forward the message to subscribed clients.
aBroker.SendMessage("MyCpuUpdate", aSerializedMessage);
Thread.Sleep(500);
}
});
aWorkingThread.Start();
Console.WriteLine("CpuUsageService is running press ENTER to stop.");
Console.ReadLine();
// Wait until the working thread stops.
aStopWorkingThreadFlag = true;
aWorkingThread.Join(3000);
// Detach the input channel and stop listening.
aBroker.DetachDuplexInputChannel();
}
}
}
</pre>
</div>
<div>
<br />
<br /></div>
<h3>
JavaScript Client</h3>
<div>
The JavaScript client is a simple HTML 5 web-page using the duplex broker client component for subscribing to CPU usage notifications. When the notification message is received it updates the chart displaying values. The chart is moving as new notification values are received.</div>
<div>
<pre class="brush: js; html-script: true"><!DOCTYPE html>
<html>
<head>
<title>CPU Usage Client</title>
<script src="Chart.js"></script></pre>
<pre class="brush: js; html-script: true"> <!- ENSURE HERE IS THE SAME ENETER VERSION AS YOU DOWNLOADED -->
<script src="eneter-messaging-6.0.1.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body onunload="closeConnection();">
<div>
<button type="button" onclick="openConnection();">1. Open Connection</button>
</div>
<div>
<button type="button" onclick="subscribe();">2. Subscribe</button>
<button type="button" onclick="unsubscribe();">3. Unsubscribe</button>
</div>
<div>
<button type="button" onclick="closeConnection();">4. Close Connection</button>
</div>
<div id="output">
</div>
<div>
<canvas id="canvas" height="300" width="300"></canvas>
</div>
<script>
// Initialize chart.
var myChartConfig = {
animation : false,
scaleOverlay : true,
scaleOverride : true,
scaleSteps : 10,
scaleStepWidth : 10,
scaleStartValue : 0
};
var myLineChartData = {
labels : ["", "", "", "", "", "", "", "", "", ""],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(220,220,220,1)",
pointStrokeColor : "#fff",
data : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
]
};
var myChart = new Chart(document.getElementById("canvas").getContext("2d"));
// Create the duplex output channel.
var myOutputChannel =
new WebSocketDuplexOutputChannel("ws://127.0.0.1:8843/CpuUsage/", null);
// Create BrokerClient
var myBrokerClient = new DuplexBrokerClient();
// Subscribe to notifications.
myBrokerClient.onBrokerMessageReceived = onBrokerMessageReceived;
function openConnection() {
// Attach output channel and be able to send messages and receive responses.
myBrokerClient.attachDuplexOutputChannel(myOutputChannel);
};
function closeConnection() {
// Detach output channel and stop listening to responses.
myBrokerClient.detachDuplexOutputChannel();
};
function subscribe() {
myBrokerClient.subscribe("MyCpuUpdate");
};
function unsubscribe() {
myBrokerClient.unsubscribe("MyCpuUpdate");
};
function onBrokerMessageReceived(brokerMessageReceivedEventArgs) {
// If the notified message is the CPU status update.
if (brokerMessageReceivedEventArgs.MessageTypeId === "MyCpuUpdate")
{
// Deserialize notified message content.
var aValue = JSON.parse(brokerMessageReceivedEventArgs.Message);
// Update data and draw the chart.
myLineChartData.datasets[0].data.shift();
myLineChartData.datasets[0].data.push(aValue.Usage);
myChart.Line(myLineChartData, myChartConfig);
}
};
</script>
</body>
</html>
</pre>
</div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com6tag:blogger.com,1999:blog-5196103582241137578.post-38379045961636253792014-04-25T13:40:00.000+02:002014-04-25T13:40:13.186+02:00Eneter JSON Serializer for JavaImplementation of JSON serializer that can be used with Eneter Messaging Framework for Java.<br />
<div>
<a name='more'></a>Eneter Messaging Framework uses the serialization to encode data structures into messages and the deserialization to decode messages back to data structures when they are received.</div>
<div>
<br /></div>
<h3>
Eneter for Java and JSON</h3>
<div>
Although the framework provides several built-in serializers the JSON serializer is not part of Eneter Messaging Framework for Java. The reason is JSON serialization is not part of Java platform and so Eneter would have to provide either its own implementation or would have to integrate with an existing implementation.</div>
<div>
The first alternative would mean to reinvent the wheel and the second one would create a dependency on a third party library which would violate one of Eneter principles to stay lightweight and easy to use.</div>
<div>
Therefore the solution is to provide the JSON serializer by reusing an existing implementation but outside the Eneter library.</div>
<div>
<br /></div>
<div>
The article shows implementation of Eneter JSON serializer for Java based on <a href="https://code.google.com/p/google-gson/" target="_blank">GSON</a> (Google's JSON serializer).<br />
<br />
To experiment with the example bellow you need to:<br />
<br />
<ul>
<li>download <a href="http://www.eneter.net/ProductDownload.htm" target="_blank">Eneter Messaging Framework for Java</a>.</li>
<li>download <a href="https://code.google.com/p/google-gson/downloads/list" target="_blank">google-gson library</a>.</li>
<li>create a Java project and reference both downloaded libraries.</li>
<li>create JsonSerializer class in that project and copy paste there implementation from this article.</li>
</ul>
</div>
<div>
<br /></div>
<h3>
Eneter Serializer</h3>
<div>
The serialization in Eneter is based on <i><a href="http://www.eneter.net/OnlineHelp/EneterMessagingFrameworkJava/eneter/messaging/dataprocessing/serializing/ISerializer.html" target="_blank">ISerializer</a></i> interface which consists of two simple methods: serialize(...) and deserialize(...).</div>
<div>
<br /></div>
<div>
<pre class="brush: java">public interface ISerializer
{
/**
* Serializes data.
*
* @param dataToSerialize Data to be serialized.
* @param clazz represents the serialized type.
* @return Object representing the serialized data.
* Based on the serializer implementation it can be byte[] or String.
* @throws Exception If the serialization fails.
*/
<T> Object serialize(T dataToSerialize, Class<T> clazz) throws Exception;
/**
* Deserializes data.
*
* @param serializedData Data to be deserialized.
* @return Deserialized object.
* @throws Exception If the deserialization fails.
*/
<T> T deserialize(Object serializedData, Class<T> clazz) throws Exception;
}
</pre>
</div>
<div>
<br /></div>
<div>
The interface is used across the whole framework and by providing a reference of this interface you can control which serializer will be used to encode and decode messages.<br />
<br />
<h3>
GSON in Eneter</h3>
Therefore, in order to integrate GSON (Google's implementation of JSON serializer) with Eneter we need to provide an implementation of <i>ISerializer</i> which would internally use GSON.<br />
<br />
The whole implementation of such wrapper is very easy:<br />
<br /></div>
<div>
<pre class="brush: java">public class JsonSerializer implements ISerializer
{
/**
* Serialize to JSON.
*/
@Override
public <T> T deserialize(Object serializedData, Class<T> clazz)
throws Exception
{
// Check input parameters.
if (serializedData == null)
{
throw new IllegalArgumentException("Input parameter serializedData is null.");
}
if (serializedData instanceof String == false)
{
throw new IllegalArgumentException("Input parameter serializedData is not String.");
}
// Serialize using GSON.
T aDeserializedObject = myGson.fromJson((String)serializedData, clazz);
return aDeserializedObject;
}
/**
* Deserialize from JSON.
*/
@Override
public <T> Object serialize(T dataToSerialize, Class<T> clazz)
throws Exception
{
// Deserialize using GSON.
String aSerializedObject = myGson.toJson(dataToSerialize);
return aSerializedObject;
}
private Gson myGson = new Gson();
}
</pre>
</div>
<div>
<br />
<h3>
Example of Using</h3>
If not specified Eneter uses XmlSerializer by default. Therefore to enable JSON serialization you need to provide the serializer reference when constructing the communication components.<br />
<br />
The following example shows how to use our JsonSerializer for sending messages:<br />
<br /></div>
<div>
<pre class="brush: java">// Provide JSON serializer when constructing the factory.
ISerializer aSerializer = new JsonSerializer();
IDuplexTypedMessagesFactory aFactory = new DuplexTypedMessagesFactory(aSerializer);
// Factory create duplex typed message sender that uses our JSON serializer.
myCreateUser = aFactory.createDuplexTypedMessageSender(String.class, UserData.class);
// Continue with subscribing and attaching the channel.
...
</pre>
</div>
<div>
<br />
And of course <b>do not forget</b> to set JSON serializer in the service too:<br />
<br /></div>
<div>
<pre class="brush: csharp">// Provide JSON serializer when constructing the factory.
ISerializer aSerializer = new DataContractJsonStringSerializer();
IDuplexTypedMessagesFactory aFactory = new DuplexTypedMessagesFactory(aSerializer);
// Factory create duplex typed message sender that uses our JSON serializer.
myCreateUser = aFactory.createDuplexTypedMessageReceiver<string, UserData>();
// Continue with subscribing and attaching the channel.
...
</pre>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com0tag:blogger.com,1999:blog-5196103582241137578.post-74312427022430314842014-03-23T19:08:00.000+01:002016-01-09T08:50:47.914+01:00Remote Procedure Calls between Android and .NETSimple example showing Remote Procedure Calls between Android and .NET based on TCP.<br />
And few words about RPC vs. Messaging.<br />
<br />
<a name='more'></a>The source code for this example can be downloaded from:<br />
<a href="http://www.eneter.net/Downloads/Examples/ClientServerRpc.zip">http://www.eneter.net/Downloads/Examples/ClientServerRpc.zip</a><br />
<br />
<h3>
Introduction</h3>
<div>
The example bellow demonstrates a simple client-server communication between Android and .NET using RPC (Remote Procedure Calls). The .NET application is a service exposing the interface and the Android application is a client calling remote methods from the interface.</div>
<div>
<br /></div>
<div>
<div>
The example is based on Eneter Messaging Framework. The framework is free and can be downloaded from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.</div>
<div>
More technical info about the framework can be found at <a href="http://www.eneter.net/ProductInfo.htm">http://www.eneter.net/ProductInfo.htm</a>.</div>
</div>
<div>
<br /></div>
<h3>
Remote Procedure Calls vs Messaging</h3>
<div>
<div>
RPC is a request-response communication scenario where one application (typically client) requests to invoke a method in another application (typically service) and waits until the invoked method returns.</div>
<div>
<br /></div>
<div>
The difference between RPC and messaging is that RPC is functionality oriented and the messaging is message oriented. It means RPC models the interprocess communication from the perspective of required functionality and the messaging models it from the perspective of messages flowing between applications.</div>
<div>
<br /></div>
<div>
Therefore the RPC communication model specifies functions/methods which are exposed by a service and can be executed from clients. It is typically synchronous request-response interaction with one response per request.</div>
<div>
<br /></div>
<div>
Modeling the communication via messaging is different. Instead of functionality it focuses on messages and also how these messages are routed between applications. It does not couple the interprocess interaction with execution of certain methods. This allows to model various communication scenarios. E.g. request-response with zero, one or multiple responses per request or e.g. publish-subscribe communication. The communication is typically asynchronous.</div>
<div>
<br /></div>
<div>
It is obvious the messaging provides more possibilities in designing interprocess communication than RPC. The price for possibilities is the complexity. In some cases using the messaging can be an overkill. E.g. asynchronous programming is more complicated and error prone than synchronous. On the other hand (ab)using RPC for advanced communication scenarios can result into workarounds and poor quality.</div>
<div>
<br /></div>
<div>
Eneter Messaging Framework provides functionality for both approaches. Messaging as well as RPC. In fact RPC is implemented using the messaging.</div>
<div>
From the framework concept perspective RPC is part of end-points. It provides <span style="font-family: Courier New, Courier, monospace;">RpcClient</span> and <span style="font-family: Courier New, Courier, monospace;">RpcService</span> components which can attach and detach communication channels as any other messaging component.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0JNp_RTriwvtY2AdF6oDHLrSeqmX9sRYt4C7WsJrJNM6GRtrNhbGF68FtxJUXH38xwQWatSHWKLyyGETyyQu8z9dADqrxmvu_A5U0I-b9pf-Vj14yzJhdvQOUajUoZ8f0zR4kLxHclcsT/s1600/RPCCommunicationAndroidNET.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0JNp_RTriwvtY2AdF6oDHLrSeqmX9sRYt4C7WsJrJNM6GRtrNhbGF68FtxJUXH38xwQWatSHWKLyyGETyyQu8z9dADqrxmvu_A5U0I-b9pf-Vj14yzJhdvQOUajUoZ8f0zR4kLxHclcsT/s640/RPCCommunicationAndroidNET.png" width="640" /></a><br />
<br /></div>
<div>
The goal of RPC in Eneter Messaging Framework is not to pretend the interprocess communication is like a local call.</div>
<div>
The goal is to provide a convenience for simple request-response scenarios. RPC allows to specify the service API by declaring a method interface (instead of declaring multiple message types and describing the communication protocol) and allows to perform request-response communication synchronously (instead of receiving response messages asynchronously).</div>
<div>
In addition RPC in Eneter Messaging Framework works across multiple platforms. It means you can use this technique e.g. between Java and .NET or between Android and .NET as demonstrated in the example bellow.<br />
<br /></div>
<div>
<h3>
To Run Example Code</h3>
<h4>
1. Download Eneter</h4>
The example source code from this article does not contain Eneter libraries. Therefore you need to download Eneter Messaging Framework for .NET and also for Android from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.<br />
<br />
<h4>
2. Add Eneter Libraries to the project</h4>
When you have downloaded Eneter libraries you need to add them to projects. Add <i>Eneter.Messaging.Framework.dll</i> to the RpcService solution and <i>eneter-messaging-android.jar</i> into the AndroidRpcClient project.<br />
<br />
Please follow this procedure (for Eclipse) to add libraries into the Android project: (To add a library into the project you need to import it instead of adding it via project properties. Also ensure Java compliance level is set to 6.0. <i>Properties -> Java Compiler -> JDK Compliance -> 1.6</i>.) Then you need to add Eneter libraries to projects and compile it.<br />
To add eneter to the Android project please follow this procedure for Eclipse:<br />
<br />
<ol>
<li>Create a new folder 'libs' in your project. (use exactly name libs)</li>
<li>Right click on 'libs' and choose <i>'Import...' -> 'General/File System' -> 'Next'</i>.</li>
<li>Then click 'Browser' button for 'From directory' and navigate to directory with libraries you want to add.</li>
<li>Select check boxes for libraries you want to add.</li>
<li>Press 'Finish'</li>
</ol>
<br />
<ol>
</ol>
<h4>
3. Compile and Run</h4>
</div>
<div>
<div>
When you have added Eneter libraries into the project you can compile it and run it.</div>
<div>
First execute RpcService and then AndroidRpcClient.</div>
</div>
<div>
<br /></div>
<h3>
TCP on Android</h3>
<div>
When you implement the communication via TCP on Android, you must count with two specifics:<br />
<br /></div>
<h4>
1. You must set INTERNET permission for your Android application!</h4>
<div>
If the permission is not set, the application is not allowed to communicate across the network. To set the INTERNET permission you must add the following line to <i>AndroidManifest.xml</i>.<br />
<br /></div>
<pre class="brush: xml"><uses-permission android:name="android.permission.INTERNET"/>
</pre>
<div>
<br />
An example of AndroidManifest.xml allowing communication across the network:<br />
<br /></div>
<pre class="brush: xml"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="eneter.androidrpcclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="eneter.androidrpcclient.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
</pre>
<div>
<br />
<h4>
2. The IP address 127.0.0.1 (loopback) cannot be set on the Android emulator to communicate with the .NET application!</h4>
The emulator acts as a separate device. Therefore, the IP address 127.0.0.1 is the loopback of that device and cannot be used for the communication with other applications running on the same computer as the emulator.<br />
<br />
Instead of that you must use a real IP address of the computer or the emulator can use the special address 10.0.2.2 that is routed to 127.0.0.1 (loopback) on the computer. In my example, the Android emulator uses 10.0.2.2 and the .NET service is listening to 127.0.0.1.<br />
<br /></div>
<h3>
.NET Service application</h3>
<div>
The service is a simple console application exposing a simple IMyService interface. The service is exposed using the RpcService component. RpcService then attaches the input channel and starts to listen to requests via TCP. When a request is received it is routed to the service method and the return value is then send back to the client.<br />
<br />
The whole implementation is very simple:<br />
<br /></div>
</div>
<div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace Service
{
// Service interface.
public interface IMyService
{
int Calculate(int a, int b);
string GetEcho(string text);
}
// Service implementation.
public class MyService : IMyService
{
public int Calculate(int a, int b)
{
int aResult = a + b;
Console.WriteLine("{0} + {1} = {2}", a, b, aResult);
return aResult;
}
public string GetEcho(string text)
{
Console.WriteLine("Received text = {0}", text);
return text;
}
}
class Program
{
static void Main(string[] args)
{
// Use single-instance service.
// It means all connected clients share the same instance of the service.
// Note: if needed you can choose per-client-instance mode too.
IRpcFactory aFactory = new RpcFactory();
IRpcService<IMyService> aService =
aFactory.CreateSingleInstanceService<IMyService>(new MyService());
// Use TCP for the communication.
// You also can use other protocols e.g. WebSockets.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8032/");
// Attach the input channel to the RpcService and start listening.
aService.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("RPC service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel and release the listening thread.
aService.DetachDuplexInputChannel();
}
}
}
</pre>
</div>
<div>
<br />
<h3>
Android Client Application</h3>
The client is a simple Android application which declares the same IMyService interface as the .NET service application. The IMyservice interface type is then provided to RpcClient which generates the proxy. The proxy is retrieved by myRpcClient.getProxy(). The retrieved proxy allows to call interface methods. The calls are then routed to the service where they are processed.<br />
<br />
Here is the whole client implementation:<br />
<br /></div>
<div>
<pre class="brush: java">package eneter.androidrpcclient;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.rpc.*;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.*;
public class MainActivity extends Activity
{
// Interface exposed by the service.
// Note: names of methods are case sensitive.
// So keep capitals as declared in C#.
public static interface IMyService
{
int Calculate(int a, int b);
String GetEcho(String text);
}
// UI controls
private EditText myNumber1EditText;
private EditText myNumber2EditText;
private EditText myResultEditText;
private Button myCalculateButton;
private EditText myEchoEditText;
private Button myGetEchoButton;
private EditText myEchoedEditText;
// Eneter communication.
IRpcClient<IMyService> myRpcClient;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get UI widgets.
myNumber1EditText = (EditText) findViewById(R.id.number1editText);
myNumber2EditText = (EditText) findViewById(R.id.number2EditText);
myResultEditText = (EditText) findViewById(R.id.resultEditText);
myEchoEditText = (EditText) findViewById(R.id.echoTexteditText);
myEchoedEditText = (EditText) findViewById(R.id.echoedEditText);
myCalculateButton = (Button) findViewById(R.id.caculateBtn);
myCalculateButton.setOnClickListener(myOnCalculateButtonClick);
myGetEchoButton = (Button) findViewById(R.id.getEchoBtn);
myGetEchoButton.setOnClickListener(myOnGetEchoButtonClick);
// Open the connection in another thread.
// Note: From Android 3.1 (Honeycomb) or higher
// it is not possible to open TCP connection
// from the main thread.
Thread anOpenConnectionThread = new Thread(new Runnable()
{
@Override
public void run()
{
openConnection();
}
});
anOpenConnectionThread.start();
}
@Override
public void onDestroy()
{
closeConnection();
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private void openConnection()
{
try
{
// Instantiate RPC client.
RpcFactory aFactory = new RpcFactory();
myRpcClient = aFactory.createClient(IMyService.class);
// Use TCP for the communication.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
// Note: special IP address used by the Android simulator.
// 10.0.2.2 is routed by the simulator to 127.0.0.1 of machine where
// the simulator is running.
// Use real IP address if you run it on a real Android device!
IDuplexOutputChannel anOutputChannel = aMessaging
.createDuplexOutputChannel("tcp://10.0.2.2:8032/");
// Attach the output channel to the RPC client and be able to
// communicate.
myRpcClient.attachDuplexOutputChannel(anOutputChannel);
}
catch (Exception err)
{
EneterTrace.error("Failed to open connection with the service.",
err);
}
}
private void closeConnection()
{
// Stop listening to response messages.
if (myRpcClient != null)
{
myRpcClient.detachDuplexOutputChannel();
}
}
private void onCalculateButtonClick(View v)
{
int aNumber1 = Integer.parseInt(myNumber1EditText.getText().toString());
int aNumber2 = Integer.parseInt(myNumber2EditText.getText().toString());
try
{
// Invoke the remote method.
int aResult = myRpcClient.getProxy().Calculate(aNumber1, aNumber2);
myResultEditText.setText(Integer.toString(aResult));
}
catch (Exception err)
{
EneterTrace.error("Failed to invoke the remote method.", err);
}
}
private void onGetEchoButtonClick(View v)
{
try
{
String aText = myEchoEditText.getText().toString();
String anEchoedText = myRpcClient.getProxy().GetEcho(aText);
myEchoedEditText.setText(anEchoedText);
}
catch (Exception err)
{
EneterTrace.error("Failed to invoke the remote method.", err);
}
}
private OnClickListener myOnCalculateButtonClick = new OnClickListener()
{
@Override
public void onClick(View v)
{
onCalculateButtonClick(v);
}
};
private OnClickListener myOnGetEchoButtonClick = new OnClickListener()
{
@Override
public void onClick(View v)
{
onGetEchoButtonClick(v);
}
};
}
</pre>
</div>
<div>
<br />
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com13tag:blogger.com,1999:blog-5196103582241137578.post-3098250269370764712013-12-15T16:54:00.000+01:002016-01-09T08:46:20.801+01:00Native C++: How to communicate with .NET applicationSimple example showing how to implement the interprocess communicate between an unmanaged (native) C++ application and a managed .NET application using Eneter Messaging Framework.<br />
<br />
<a name='more'></a>The source code for this example can be downloaded from here:<br />
<a href="http://eneter.net/Downloads/Examples/CalculatorNative.zip">http://eneter.net/Downloads/Examples/CalculatorNative.zip</a><br />
<br />
<h3>
Introduction</h3>
The example bellow shows how to implement the communication between an unmanaged C++ application and a standalone .NET (managed) application using Eneter Messaging Framework.<br />
<br />
To demonstrate this scenario the example implements a simple client-service communucation. The service is a .NET application calculating two numbers and the client is an unmanaged (native) C++ application using the service for the calculation.<br />
<br />
<br />
The example uses Eneter Messaging Framework. The framework is free for non-commercial use and can be downloaded from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.<br />
More detailed technical info can be found at <a href="http://www.eneter.net/ProductInfo.htm">technical info</a>.<br />
<br />
<h3>
Wrapper Library</h3>
The major challenge in this scenario is to use the managed Eneter functionality from the unmanaged C++ code. The idea is to provide a 'bridge' that would connect unmanged C++ with managed Eneter. The bridge would be a library that could be linked and used from the unmanaged C++ code but internally would direclty use managed Eneter functionality.<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX1Y3_WBb1cR3uXE_xbWk3hyJRMsCVyp9cGAjE8ckUnBloG5UuEsskodao7tethMfMDs25MK9difuiCuoGt-xBB8OraGbOwVCtSrRIMrfk_WQmxVDHkZBh2Y24eXO8SVXbf1fFmC51knb-/s1600/UnmanagedC%252B%252BCommunication.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX1Y3_WBb1cR3uXE_xbWk3hyJRMsCVyp9cGAjE8ckUnBloG5UuEsskodao7tethMfMDs25MK9difuiCuoGt-xBB8OraGbOwVCtSrRIMrfk_WQmxVDHkZBh2Y24eXO8SVXbf1fFmC51knb-/s640/UnmanagedC%252B%252BCommunication.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<div>
The bridge can be implemented as managed C++ assembly that wrapps the communication functionality based on the Eneter framework and exposes the C++ API that does not contain any managed types or syntax constructions - only pure types and syntax that can be understood by unmanaged C++.</div>
<div>
<br /></div>
<div>
Here is the C++ API declaration for our example. The API exposes the communication interface <span style="font-family: Courier New, Courier, monospace;"><i>IClient</i></span> which provides methods responsible for the communication with the service.</div>
<div>
It also provides the factory method <span style="font-family: Courier New, Courier, monospace;">CreateClient(...)</span> which is responsible for the instantiation of the <span style="font-family: Courier New, Courier, monospace;"><i>IClient</i></span> interface and the <span style="font-family: Courier New, Courier, monospace;">DestroyClient(...)</span> method that is responsible for correct releasing the client instance from the memory when it is not needed.<br />
<br /></div>
</div>
<div>
<pre class="brush: cpp">#pragma once
#ifdef WRAPPER_EXPORT
#define WRAPPER_API __declspec(dllexport)
#else
#define WRAPPER_API __declspec(dllimport)
#endif
// Example of an interface declaring the communication
// functionality.
class IClient
{
public:
virtual ~IClient(void){}
virtual void OpenConnection() = 0;
virtual void CloseConnection() = 0;
virtual int SendCalculateRequest(int a, int b) = 0;
};
// And here are factories for creating and destructing.
extern "C" WRAPPER_API IClient* CreateClient(const wchar_t* address);
extern "C" WRAPPER_API void DestroyClient(IClient* client);
</pre>
</div>
<div>
<br /></div>
<div>
And here is the internal implementation:<br />
(declaration)
</div>
<div>
<pre class="brush: cpp">#pragma once
#include <string>
#include <vcclr.h>
#include "CommunicationApi.h"
#using <..\\Debug\\Eneter.Messaging.Framework.dll>
using namespace System;
using namespace Eneter::Messaging::EndPoints::TypedMessages;
// Request message declared as managed class.
public ref class RequestMessage
{
public:
int Number1;
int Number2;
};
// Response message declared as managed class.
public ref class ResponseMessage
{
public:
int Result;
};
// Client declared as NATIVE class to be able to derive
// from IClient.
class Client : public IClient
{
public:
Client(const wchar_t* address);
virtual ~Client();
virtual void OpenConnection();
virtual void CloseConnection();
virtual int SendCalculateRequest(int a, int b);
private:
gcroot<String^> myAddress;
gcroot<ISyncDuplexTypedMessageSender<ResponseMessage^, RequestMessage^> ^> mySender;
};
</pre>
</div>
<div>
<br />
(definition)
<br />
<br /></div>
<div>
<pre class="brush: cpp">#include "StdAfx.h"
#include "Client.h"
#using <..\\Debug\\Eneter.Messaging.Framework.dll>
using namespace Eneter::Messaging::EndPoints::TypedMessages;
using namespace System;
using namespace Eneter::Messaging::MessagingSystems::MessagingSystemBase;
using namespace Eneter::Messaging::MessagingSystems::TcpMessagingSystem;
Client::Client(const wchar_t* address)
{
myAddress = gcnew String(address);
IDuplexTypedMessagesFactory^ aSenderFactory = gcnew DuplexTypedMessagesFactory(TimeSpan::FromSeconds(5));
mySender = aSenderFactory->CreateSyncDuplexTypedMessageSender<ResponseMessage^, RequestMessage^>();
}
Client::~Client(void)
{
CloseConnection();
}
void Client::OpenConnection()
{
// Let's use TCP.
// (But other protocols would work too.)
IMessagingSystemFactory^ aMessaging = gcnew TcpMessagingSystemFactory();
IDuplexOutputChannel^ anOutputChannel = aMessaging->CreateDuplexOutputChannel(myAddress);
// Attach the channel and be able to send request messages
// and receive responses.
mySender->AttachDuplexOutputChannel(anOutputChannel);
}
void Client::CloseConnection()
{
// Detach the output channel.
// Note: It releases the thread listening to responses.
mySender->DetachDuplexOutputChannel();
}
int Client::SendCalculateRequest(int a, int b)
{
RequestMessage^ aRequest = gcnew RequestMessage;
aRequest->Number1 = a;
aRequest->Number2 = b;
ResponseMessage^ aResponse = mySender->SendRequestMessage(aRequest);
return aResponse->Result;
}
</pre>
</div>
<div>
<br />
And here is the implementation of the factory method:<br />
<br /></div>
<div>
<pre class="brush: cpp">#include "Stdafx.h"
#include "CommunicationApi.h"
#include "Client.h"
IClient* CreateClient(const wchar_t* address)
{
// Native C++ representing the communication client.
IClient *aClient = new Client(address);
return aClient;
}
void DestroyClient(IClient* client)
{
delete client;
}
</pre>
</div>
<div>
<br />
<h3>
Unmanaged C++ Client</h3>
The unmanaged C++ client is a simple console application using the bridge library that wraps the Eneter communication lfunctionality.<br />
It opens the connection with the service and sends the calculation request to the service. Then it closes the connection and displays the result.<br />
<br />
The implementation is very simple:<br />
<br />
<br /></div>
<div>
<pre class="brush: cpp">#include "stdafx.h"
#include <iostream>
#include "../CommunicationWrapper/CommunicationApi.h"
int _tmain(int argc, _TCHAR* argv[])
{
// Create the communication wrapper.
IClient *aClient = CreateClient(L"tcp://127.0.0.1:4502/");
// Open the connection.
aClient->OpenConnection();
// Send the request and get the response.
int aResult = aClient->SendCalculateRequest(10, 20);
// Close the connection.
aClient->CloseConnection();
// Release the client from the memory.
DestroyClient(aClient);
// Display the result.
std::cout << "Result = " << aResult << std::endl;
return 0;
}
</pre>
</div>
<div>
<br />
<h3>
Managed C# Service</h3>
The managed service is a simple .NET console application listening to requests. When it receives a requests it calculates it and sends beck the response.<br />
<br />
Here is the whole implementation:<br />
<br /></div>
<div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace CalculatorService
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Create message receiver.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage> aReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>();
// Subscribe to process request messages.
aReceiver.MessageReceived += OnMessageReceived;
// Use TCP for the communication.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:4502/");
// Attach the input channel to the receiver and start listening.
aReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The calculator service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel to stop listening.
aReceiver.DetachDuplexInputChannel();
}
private static void OnMessageReceived(object sender,
TypedRequestReceivedEventArgs<RequestMessage> e)
{
// Calculate numbers.
ResponseMessage aResponseMessage = new ResponseMessage();
aResponseMessage.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("{0} + {1} = {2}", e.RequestMessage.Number1,
e.RequestMessage.Number2, aResponseMessage.Result);
// Send back the response message.
var aReceiver = (IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>)sender;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
</pre>
</div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com4tag:blogger.com,1999:blog-5196103582241137578.post-28267951036751999202013-08-26T22:39:00.001+02:002013-08-27T00:20:59.271+02:00Windows Security WikiA useful summary about Windows Security.<br />
<a name='more'></a><br />
<h3>
Introduction</h3>
<div>
Normally when implementing an application you do not need to care about security concepts present in Windows. But from time to time you may need to implement something where the security is involved.</div>
<div>
E.g. you want to implement a windows service that shall interact with desktop applications using 'Event Wait Handles' and 'Shared Memory'.
</div>
<div>
You deal with concepts like 'Process Integrity Level' and 'Process Sessions'. Eventually you have a working application and everything is fine (on your Windows 7) until you decide to run it on Windows 8 or Windows Server 2012. And this is where the real "fun" starts ;-). Difficult terminology, poor google results and nobody answers your questions on IT forums.<br />
<br />
This article is a short wiki I collected during my investigations. I think it could be useful for you too.<br />
<br /></div>
<h3>
Windows Security Model</h3>
<div>
The biggest problem in the security topic is difficult terminology (many abbreviations) and not easy to understand how things are related to each other.<br />
<br />
Therefore here is a model showing relations between most common terms:<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNfUZgHrfYGfg16UeAuTeYh5sFw81iHLr8w7bKDWKJIZarjX5BvO_buu9OJzKdM3PuMYdVmTO_iPzzqPVV8oyIKfNpoAlze7_bIT7S0FdgxW5JIcpBk_2qWPeoG7RoVsYc3DNitXOUuE4e/s1600/WindowsSecurityModel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNfUZgHrfYGfg16UeAuTeYh5sFw81iHLr8w7bKDWKJIZarjX5BvO_buu9OJzKdM3PuMYdVmTO_iPzzqPVV8oyIKfNpoAlze7_bIT7S0FdgxW5JIcpBk_2qWPeoG7RoVsYc3DNitXOUuE4e/s640/WindowsSecurityModel.png" width="640" /></a></div>
<br /></div>
<div>
<br /></div>
<h3>
Terms and Abbreviations Summary</h3>
<div>
<ul>
<li><b>Securable Objects</b> - files, folders, pipes, processes, threads, registry keys, printers, semaphores, event wait handles, ... and other objects that can be protected from unauthorized access.</li>
<li><b>Security Descriptor</b> - specifies security information about the object. I.e. it identifies the object owner SID, the primary group SID and most importantly SACL and DACL lists.</li>
<li><b>SID</b> - Security Identifier. It can identify user, group and computer accounts. SID is generated when the account is created. Windows internally refers to SIDs and not to user or account names.</li>
<li><b>ACL</b> - Access Control List. It is a list of protections specified for the object. ACL can be SACL or DACL. The entry of the list is called ACE.</li>
<li><b>ACE</b> - Access Control Entry. The entry of the ACL list. It specifies the access rights and to whom are these rights granted, denied or audited (logged).</li>
<li><b>DACL</b> - Discretionary Access Control List. It controls access to the object. It specifies to whom the access is allowed and to whom denied. The content of DACL is controlled by the owner of the security object.<br />If the object does not have any DACL the full access to everyone is allowed.<br />If the object has empty DACL nobody has the access.<br />DACL can have following entries:</li>
<ul>
<li><b>Access Allowed ACE</b> - the item in the DACL which specifies who is allowed to access the object. It consists of:</li>
<ul>
<li><i>Trustee SID</i> - identifies user, group or computer account to whom the access is granted.</li>
<li><i>Access Mask</i> - identifies what access is allowed. E.g. read, write, execute.</li>
</ul>
<li><b>Access Denied ACE</b> - the item in the DACL which specifies to whom the access is denied. E.g. you may need this rule if the access is granted to a group but you want to deny one user from that group. It consists of:</li>
<ul>
<li><i>Trustee SID</i> - identifies user, group or computer account to whom the access is denied.</li>
<li><i>Access Mask</i> - identifies what access is denied. E.g. write, execute.</li>
</ul>
</ul>
<li><b>SACL</b> - System Access Control List. It controls two things: auditing rules (how access to objects is recorded in the security log) and integrity level of the object (what is the minimal "trust" level needed to access the object). The content of the SACL is controlled by security administrators for the local system. These are users who have been assigned the 'Manage Auditing and Security Log' privilege (SeSecurityPrivilege).<br />SACL can have following entries:</li>
<ul>
<li><b>Audit ACE</b> - identifies the rule for auditing to the security log.</li>
<ul>
<li><i>Header</i> - specifies if the auditing occurs by success, failure or both when somebody accessed the object.</li>
<li><i>Trustee SID</i> - identifies user, group or computer account that shall be monitored.</li>
<li><i>Access Mask</i> - lists operations to audit.</li>
</ul>
<li><b>Mandatory Label ACE</b> - identifies the minimal integrity level to access the object. E.g. object with medium integrity level cannot be accessed by object with low integrity. It consists of:</li>
<ul>
<li><i>Integrity Level SID</i> - SID of the integrity level.</li>
<li><i>Mask</i> - defines restrictions on the access permissions that apply to processes with lower integrity level.</li>
</ul>
</ul>
<li><b>Logon Session</b> - context of the user during the logon time.</li>
<li><b>Access Token</b> - describes the security context of a process or thread. The access token is created when the user is logged on. Every process executed on behalf of the user will get the copy of user's access token. If the process (or thread) wants to access a securable object the access token will be compared with the security descriptor of that object to determine if the process (or thread) can access it.<br />It consists of:</li>
<ul>
<li><i>User SID</i> - identifies the user.</li>
<li><i>Group SIDs</i> - list of user's groups.</li>
<li><i>Integrity Level SID</i> - integrity level of the process.</li>
<li><i>Privileges</i> - user's privileges.</li>
</ul>
<li><b>Primary Token</b> - describes the security context of the user account associated with the process. Every process has a primary token.</li>
<li><b>Impersonation Token</b> - describes the security context of a client process. Impersonation allows a thread to interact with securable objects with another (client) security context. A thread that is impersonating a client has both a primary token and an impersonation token.</li>
<li><b>Integrity Level</b> - specifies a level of trust. There are four integrity levels: <i>low, medium, high and system</i>. The integrity level stored in the securable object specifies what is the minimal integrity level required from a process to access the object. If the level is lower the access is denied independently from access rules specified in DACL.</li>
<li><b>SDDL</b> - Security Descriptor Definition Language. It allows to define ACEs and SIDs as a text.<br />E.g. this is how you can define that the process with lower than medium integrity is not allowed to get write access rights:<br />S:(ML;;NW;;;ME).</li>
<ul>
<li>S - means SACL</li>
<li>ML - means Mandatory Label</li>
<li>NW - means NO_WRITE_UP policy.</li>
<li>ME - means medium integrity level.</li>
</ul>
</ul>
<div>
<br /></div>
<h3>
Integrity Level Check</h3>
</div>
<div>
When you read technical articles it is not really clear how checking of the integrity level works together with checking of access rights. Here is the sequence:</div>
<div>
<ol>
<li>Windows reads the access token and gets the integrity level of the process.</li>
<li>Integrity level of the process is compared with the integrity level of requested object (stored in the Mandatory Label ACE).</li>
<li>If the integrity level of the process is equal or higher than the integrity level of the secured object the access rights from DACL will be checked.<br />If the integrity level of the process is lower than the integrity level of the secured object the access is denied (regardless of what is in DACL).</li>
<li>If access rights from DACL are ok the access is granted.</li>
</ol>
</div>
<div>
For more details about integrity level read: <a href="http://blogs.technet.com/b/steriley/archive/2006/07/21/442870.aspx">Mandatory integrity control in Windows Vista</a>.</div>
<div>
<br /></div>
<div>
<h3>
Useful References:</h3>
</div>
<div>
<ul>
<li><a href="http://technet.microsoft.com/en-us/library/cc759267(v=ws.10).aspx">What Are Access Tokens?</a></li>
<li><a href="http://technet.microsoft.com/en-us/library/cc783702(v=ws.10).aspx">What Are Security Descriptors and Access Control Lists?</a></li>
<li><a href="http://technet.microsoft.com/en-us/library/cc781716(v=ws.10).aspx">How Security Descriptors and Access Control Lists Work</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb625957.aspx">What is the Windows Integrity Mechanism?</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb625963.aspx">Windows Integrity Mechanism Design</a></li>
<li><a href="http://blogs.technet.com/b/steriley/archive/2006/07/21/442870.aspx">Mandatory integrity control in Windows Vista</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa378890(v=vs.85).aspx">Interaction Between Threads and Securable Objects</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa446683(v=vs.85).aspx">How AccessCheck Works</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379286(v=vs.85).aspx">Null DACLs and Empty DACLs</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379567(v=vs.85).aspx">Security Descriptor Definition Language</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb625958.aspx">Appendix A: SDDL for Mandatory Labels</a></li>
<li><a href="http://technet.microsoft.com/en-us/library/cc759279(v=ws.10).aspx">User and computer accounts</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms721607(v=vs.85).aspx">Security Glossary</a></li>
</ul>
<br />
<br /></div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-68001138720167907532013-08-14T17:30:00.000+02:002013-08-14T17:55:00.067+02:00Protocol Buffers Serialization in .NET CommunicationUsing Protocol Buffers is much faster than BinaryFormatter. This is a short example how to use Protocol Buffers serialization for the communication between .NET applications.<br />
<br />
<a name='more'></a><br />
<h3>
Introduction</h3>
<div>
Protocol Buffers is a binary serialization originally developed by Google to share data among applications implemented in different languages like Java, C++ and Python. It became the open source and was ported to other languages and platforms too. </div>
<div>
The biggest advantage of Protocol Buffers is its <b>performance</b> and <b>availability on multiple platforms</b>.</div>
<div>
<br />
The source code of the example presented in this article can be <a href="http://eneter.net/Downloads/Extensions/EneterProtoBufSerializer/Examples/CalculatorProtoBuf.zip">downloaded from here</a>.<br />
<br /></div>
<div>
Protocol Buffers serialization is also available for .NET platforms and is much faster than classic BinaryFormatter. (<a href="https://code.google.com/p/eneter-protobuf-serializer/wiki/PerformanceMeasurements">Simple performance measurement</a>.)</div>
<div>
<br />
And Protocol Buffers are available for Eneter Messaging Framework too.</div>
<div>
<br /></div>
<div>
This article is a practical example showing how to use Protocol Buffers serialization for the communication between .NET applications.<br />
The example implements a simple request-response communication where the client uses the service to calculate two numbers.</div>
<div>
<br /></div>
<h3>
You Need to Download</h3>
<div>
<ul>
<li><b><a href="https://code.google.com/p/eneter-protobuf-serializer/">Eneter.ProtoBuf.Serializer</a></b> - protocol buffer serializer for Eneter, it also contains protocol buffer libraries and utility applications for 'proto' files.</li>
<li><b><a href="http://www.eneter.net/ProductDownload.htm">Eneter.Messaging.Framework</a></b> - communication framework that can be downloaded for free for non-commercial use.</li>
</ul>
If you like here are project pages for Protocol Buffers:<br />
<ul>
</ul>
</div>
<div>
<ul>
<li><a href="http://code.google.com/p/protobuf/">protobuf </a>- Google implementation of Protocol Buffers for Java, C++ and Python.</li>
<li><a href="https://code.google.com/p/protobuf-net/">protobuf-net</a> - Protocol Buffers implementation from Marc Gravell for .NET platforms.</li>
<li><a href="https://code.google.com/p/eneter-protobuf-serializer/">Eneter.ProtoBuf.Serializer</a> - Open source project to integrate Protocol Buffers and Eneter Messaging Framework.</li>
</ul>
<br />
<ul>
</ul>
</div>
<h3>
Add Following References into your Project</h3>
<div>
<ul>
<li><i>protobuf-net.dll</i> - protocol buffer serializer for .NET, Windows Phone, Silverlight and Compact Framework developed by Marc Gravell.</li>
<li><i>Eneter.ProtoBuf.Serializer.dll</i> - implements serializer for Eneter Messaging Framework using protobuf-net.dll.</li>
<li><i>Eneter.Messaging.Framework.dll</i> - lightweight cross-platform framework for interprocess communication.</li>
</ul>
<br />
<ul>
</ul>
</div>
<h3>
Serializing Messages Using Protocol Buffers</h3>
<div>
The original idea of Protocol Buffers is to declare messages in the 'proto' file which represents a contract describing data for the interaction.</div>
<div>
However Protocol Buffers implementation from Marc Gravell which we use in this example allows also to declare messages without using 'proto' files. It allows to declare messages as classes which are decorated with attributes - same way .NET developers are used from DataContractSerializer.</div>
<div>
<br /></div>
<div>
E.g.:</div>
<div>
<pre class="brush: csharp">[ProtoContract]
public class RequestMessage
{
[ProtoMember(1)]
public int Number1 { get; set; }
[ProtoMember(2)]
public int Number2 { get; set; }
}
</pre>
<pre class="brush: csharp"></pre>
</div>
<h3>
Service Application</h3>
<div>
Service is a simple .NET console application listening to requests to calculate two numbers. The service uses Protocol Buffers to deserialzie incoming messages and serialize response messages.<br />
<br />
The using of Protocol Buffers serializer is very simple. ProtoBufSerializer must be instantiated and provided to the constructor of DuplexTypedMessagesFactory. The factory will then create DuplexTypedMessageReceiver that will use ProtoBufSerializer for serializing/deserializing messages.<br />
<br /></div>
<div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.ProtoBuf;
using ProtoBuf;
namespace CalculatorService
{
// Request message.
[ProtoContract]
public class RequestMessage
{
[ProtoMember(1)]
public int Number1 { get; set; }
[ProtoMember(2)]
public int Number2 { get; set; }
}
// Response message.
[ProtoContract]
public class ResponseMessage
{
[ProtoMember(1)]
public int Result { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Create ProtoBuf serializer.
ISerializer aSerializer = new ProtoBufSerializer();
// Create message receiver.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory(aSerializer);
IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage> aReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>();
// Subscribe to process request messages.
aReceiver.MessageReceived += OnMessageReceived;
// Use TCP for the communication.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:4502/");
// Attach the input channel to the receiver and start listening.
aReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The calculator service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel to stop listening.
aReceiver.DetachDuplexInputChannel();
}
private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<RequestMessage> e)
{
// Calculate numbers.
ResponseMessage aResponseMessage = new ResponseMessage();
aResponseMessage.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("{0} + {1} = {2}", e.RequestMessage.Number1, e.RequestMessage.Number2, aResponseMessage.Result);
// Send back the response message.
var aReceiver = (IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>)sender;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
</pre>
<pre class="brush: csharp"></pre>
</div>
<h3>
Client Application</h3>
<div>
Client is a simple UI application allowing users to enter two numbers. It then uses the service application to calculate these numbers. The client uses Protocol Buffers to serialize request messages and deserialize incoming response messages.<br />
<br />
The using of Protocol Buffers is very simple. ProtoBufSerializer must be instantiated and provided to the constructor of DuplexTypedMessagesFactory. The factory will then create DuplexTypedMessageSender that will use ProtoBufSerializer for serializing/deserializing messages.<br />
<br /></div>
<div>
<pre class="brush: csharp">using System;
using System.Windows.Forms;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.ProtoBuf;
using ProtoBuf;
namespace CalculatorClientSync
{
public partial class Form1 : Form
{
// Request message.
[ProtoContract]
public class RequestMessage
{
[ProtoMember(1)]
public int Number1 { get; set; }
[ProtoMember(2)]
public int Number2 { get; set; }
}
// Response message.
[ProtoContract]
public class ResponseMessage
{
[ProtoMember(1)]
public int Result { get; set; }
}
private ISyncDuplexTypedMessageSender<ResponseMessage, RequestMessage> mySender;
public Form1()
{
InitializeComponent();
OpenConnection();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
// Create Protocol Buffers serializer.
ISerializer aSerializer = new ProtoBufSerializer();
// Create the synchronous message sender.
// It will wait max 5 seconds for the response.
// To wait infinite time use TimeSpan.FromMiliseconds(-1) or
// default constructor new DuplexTypedMessagesFactory()
IDuplexTypedMessagesFactory aSenderFactory =
new DuplexTypedMessagesFactory(TimeSpan.FromSeconds(5), aSerializer);
mySender = aSenderFactory.CreateSyncDuplexTypedMessageSender<ResponseMessage, RequestMessage>();
// Use TCP for the communication.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:4502/");
// Attach the output channel and be able to send messages
// and receive response messages.
mySender.AttachDuplexOutputChannel(anOutputChannel);
}
private void CloseConnection()
{
// Detach input channel and stop listening to response messages.
mySender.DetachDuplexOutputChannel();
}
private void CalculateBtn_Click(object sender, EventArgs e)
{
// Create the request message.
RequestMessage aRequest = new RequestMessage();
aRequest.Number1 = int.Parse(Number1TextBox.Text);
aRequest.Number2 = int.Parse(Number2TextBox.Text);
// Send request to the service to calculate 2 numbers.
// It waits until the response is received.
ResponseMessage aResponse = mySender.SendRequestMessage(aRequest);
// Display the result.
ResultTextBox.Text = aResponse.Result.ToString();
}
}
}
</pre>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com2tag:blogger.com,1999:blog-5196103582241137578.post-9521445989185407702013-08-12T10:42:00.000+02:002013-08-20T19:34:49.940+02:00Android: Fast Communication with .NET Using Protocol BuffersImprove the performance of interprocess communication between Android and .NET using fast binary serialization (Protocol Buffers) instead of XML or JSON.<br />
<div>
<a name='more'></a><br />
Related article: <a href="http://eneter.blogspot.sk/2012/03/android-how-to-communicate-with-net.html">Android: How to communicate with .NET application via TCP</a><br />
<br />
<h3>
Introduction</h3>
</div>
<div>
One of challanges in the interprocess communication when communicating across platforms (e.g. between Android and .NET) is how to encode (serialize) messages so that they can be understood by both platforms. Default binary serializers provided by platforms are not compatible and so the common solution is to encode messages into some text format e.g. XML or JSON.<br />
This can be perfectly ok in many cases but for applications with high performance expectations using the text format may not be an optimal solution.<br />
<br />
The example bellow demonstrates how to use Protocol Buffers binary serialization in the interprocess communication between Android and .NET applications.<br />
<br />
The whole example can be <a href="http://eneter.net/Downloads/Extensions/EneterProtoBufSerializer/Examples/AndroidNetCommunicationProtoBuf.zip">downloaded from here</a>.<br />
<br />
<h3>
You Need to Download</h3>
<ul>
<li><a href="https://code.google.com/p/eneter-protobuf-serializer/"><b>Eneter.ProtoBuf.Serializer</b></a> - protocol buffer serializer for Eneter, it also contains protocol buffer libraries and utility applications for 'proto' files.</li>
<li><b><a href="http://www.eneter.net/ProductDownload.htm">Eneter.Messaging.Framework</a></b> - communication framework that can be downloaded for free for non-commercial use.</li>
</ul>
If you like here are project pages for Protocol Buffers:<br />
<ul>
<li><a href="http://code.google.com/p/protobuf/">protobuf </a>- Google implementation of Protocol Buffers for Java, C++ and Python.</li>
<li><a href="https://code.google.com/p/protobuf-net/">protobuf-net</a> - Protocol Buffers implementation from Marc Gravell for .NET platforms.</li>
<li><a href="https://code.google.com/p/eneter-protobuf-serializer/">Eneter.ProtoBuf.Serializer</a> - Open source project to integrate Protocol Buffers and Eneter Messaging Framework.</li>
</ul>
<br /><ul>
</ul>
<h3>
Add Following References into your Project</h3>
Into .NET project:<br />
<ul>
<li><i>protobuf-net.dll</i> - protocol buffers serializer for .NET, Windows Phone, Silverlight and Compact Framework developed by Marc Gravell.</li>
<li><i>Eneter.ProtoBuf.Serializer.dll</i> - implements serializer for Eneter Messaging Framework using protobuf-net.dll.</li>
<li><i>Eneter.Messaging.Framework.dll</i> - lightweight cross-platform framework for interprocess communication.</li>
</ul>
Into Android project:<br />
<ul>
<li><i>protobuf.jar</i> - protocol buffers serializer for Java and Android developed by Google.</li>
<li><i>eneter-protobuf-serializer.jar</i> - implements serializer for Eneter Messaging Framework using protobuf.jar from Google.</li>
<li><i>eneter-messaging.jar</i> - lightweight cross-platform framework for interprocess communication.</li>
</ul>
<br />
<u><span style="color: blue;">Important:</span></u> please follow this procedure to add libraries into the Android project:<br />
(To add a library into the project you need to import it instead of adding it via project properties.)<br />
(Java compliance level must be set to 6.0. Properties -> Java Compiler -> JDK Compliance -> 1.6.)<br />
<ol>
<li>Create a new folder 'libs' in your project. (use exactly name libs)</li>
<li>Right click on 'libs' and choose 'Import...' -> 'General/File System' -> 'Next'.</li>
<li>Then click 'Browser' button for 'From directory' and navigate to directory with libraries you want to add.</li>
<li>Select check boxes for libraries you want to add.</li>
<li>Press 'Finish'</li>
</ol>
<br />
<ul>
</ul>
</div>
<h3>
Protocol Buffers</h3>
<div>
<div>
Protocol Buffers is a binary serialization originally developed by Google to share data among applications developed in different languages like Java, C++ and Python. It became the open source and was ported to other languages and platforms too.</div>
<div>
<br /></div>
<div>
The biggest advantage of Protocol Buffers is its <b>performance </b>and<b> availability on multiple platforms</b> what makes it an alternative to consider when designing the communication between applications.</div>
<div>
If you are interested a simple performance measurement is available at</div>
<div>
<a href="https://code.google.com/p/eneter-protobuf-serializer/wiki/PerformanceMeasurements">https://code.google.com/p/eneter-protobuf-serializer/wiki/PerformanceMeasurements</a>.</div>
</div>
<div>
<br /></div>
<h3>
Working with Protocol Buffers</h3>
<div>
<div>
The following procedure is optimized for defining messages for cross-platform communication:</div>
<div>
(If you want to use Protocol Buffers only in .NET you do not have to declare messages via the 'proto' file but you can declare them directly in the source code by attributing classes - same way as using DataContractSerializer.)</div>
<div>
<ol>
<li>Declare messages in the 'proto' file.</li>
<li>Compile the 'proto' file into the source code (C# and Java). It transforms declared messages to classes containing specified fields and the serialization functionality.</li>
<li>Include generated source files into C# and Java projects.</li>
<li>Initialize Eneter communication components to use EneterProtoBufSerializer.</li>
</ol>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHD0DxQtNlKL6XnmXktqAG09OkTqRDdOXAtwA3wwvJgcY6XfpPMyVVLmzVznA1_Qx_aNvGODexXk1a4PMUQIJS7GHxnBvwgKQEoQZwzu1To-nwZ-EOaoKaUpgkP7uwKGqMVm6idr5rxW-/s1600/UsingProtoBuf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHD0DxQtNlKL6XnmXktqAG09OkTqRDdOXAtwA3wwvJgcY6XfpPMyVVLmzVznA1_Qx_aNvGODexXk1a4PMUQIJS7GHxnBvwgKQEoQZwzu1To-nwZ-EOaoKaUpgkP7uwKGqMVm6idr5rxW-/s400/UsingProtoBuf.png" width="358" /></a></div>
<br /></div>
</div>
<h3>
Example Code</h3>
<div>
<div>
The example bellow is exactly the same as in my previous article <a href="http://eneter.blogspot.sk/2012/03/android-how-to-communicate-with-net.html">Android: How to communicate with .NET application via TCP</a>.</div>
<div>
The only difference is the code in this article uses <b>EneterProtoBufSerializer</b> instead of XmlStringSerializer.<br />
<br /></div>
<div>
Please, for details about how to use TCP on Android and how to setup the IP address in the emulator refer to <a href="http://eneter.blogspot.sk/2012/03/android-how-to-communicate-with-net.html">Android: How to communicate with .NET application via TCP</a>.</div>
</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCVh6APMYm0sXPI554-9NhPaEdWYkjXkkXWMnocRRV9mm8HdjndxX8MK8bEdedyLMYd74VY29OtjiOqR0dl_nxv4s_39kt31yihla7UHGDwPECO0xJQMsLbcr8jp2pwxE72APzl7OcdwXw/s1600/CommunicationBetweenAndroidandNETProtoBuf.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCVh6APMYm0sXPI554-9NhPaEdWYkjXkkXWMnocRRV9mm8HdjndxX8MK8bEdedyLMYd74VY29OtjiOqR0dl_nxv4s_39kt31yihla7UHGDwPECO0xJQMsLbcr8jp2pwxE72APzl7OcdwXw/s640/CommunicationBetweenAndroidandNETProtoBuf.png" width="640" /></a></div>
<br />
<br />
<h3>
proto File</h3>
The 'proto' file represents a contract describing messages that shall be used for the interaction.<br />
Messages are declared in the platform neutral 'protocol buffer' language - for the syntax details you can refer to <a href="https://developers.google.com/protocol-buffers/docs/proto">https://developers.google.com/protocol-buffers/docs/proto</a>.<br />
<br />
Messages in our example are declared in MessageDeclarations.proto:<br />
<br />
<pre class="brush: java">// Request Message
message MyRequest
{
required string Text = 1;
}
// Response Message
message MyResponse
{
required int32 Length = 1;
}
</pre>
<br />
The 'proto' file is then compiled to C# and Java source code. Declared messages are transformed to classes containing declared fields and serialization functionality.<br />
<br />
The following commands were used in our example to compile the 'proto' file:<br />
<span style="font-family: Courier New, Courier, monospace;">protogen.exe -i:MessageDeclarations.proto -o:MessageDeclarations.cs</span><br />
<span style="font-family: Courier New, Courier, monospace;">protoc.exe -I=./ --java_out=./ ./MessageDeclarations.proto</span><br />
<br /></div>
<h3>
Android Client Application</h3>
<div>
<div>
The Android client is a very simple application allowing user to put some text message and send the request to the service to get back the length of the text.</div>
<div>
When the response message is received it must be marshaled to the UI thread to display the result.</div>
<div>
<br /></div>
<div>
The client uses EneterProtoBufSerializer. In openConnection() method it instantiates the serializer and puts the reference to the DuplexTypedMessagesFactory ensuring the message sender will use Protocol Buffers.</div>
<div>
<br /></div>
<div>
<b><u><span style="color: blue;">Note:</span></u></b> To add the Eneter library into the Android project please follow the <a href="http://eneter.blogspot.sk/2013/03/how-to-add-eneter-library-into-android.html">recommended procedure</a>.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
</div>
<div>
<pre class="brush: java">package net.client;
import message.declarations.MessageDeclarations.*;
import eneter.messaging.dataprocessing.serializing.ISerializer;
import eneter.messaging.diagnostic.EneterTrace;
import eneter.messaging.endpoints.typedmessages.*;
import eneter.messaging.messagingsystems.messagingsystembase.*;
import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory;
import eneter.net.system.EventHandler;
import eneter.protobuf.ProtoBufSerializer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
public class AndroidNetCommunicationClientActivity extends Activity
{
// UI controls
private Handler myRefresh = new Handler();
private EditText myMessageTextEditText;
private EditText myResponseEditText;
private Button mySendRequestBtn;
// Sender sending MyRequest and as a response receiving MyResponse.
private IDuplexTypedMessageSender<MyResponse, MyRequest> mySender;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get UI widgets.
myMessageTextEditText = (EditText) findViewById(R.id.messageTextEditText);
myResponseEditText = (EditText) findViewById(R.id.messageLengthEditText);
mySendRequestBtn = (Button) findViewById(R.id.sendRequestBtn);
// Subscribe to handle the button click.
mySendRequestBtn.setOnClickListener(myOnSendRequestClickHandler);
// Open the connection in another thread.
// Note: From Android 3.1 (Honeycomb) or higher
// it is not possible to open TCP connection
// from the main thread.
Thread anOpenConnectionThread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
openConnection();
}
catch (Exception err)
{
EneterTrace.error("Open connection failed.", err);
}
}
});
anOpenConnectionThread.start();
}
@Override
public void onDestroy()
{
// Stop listening to response messages.
mySender.detachDuplexOutputChannel();
super.onDestroy();
}
private void openConnection() throws Exception
{
// Instantiate Protocol Buffer based serializer.
ISerializer aSerializer = new ProtoBufSerializer();
// Create sender sending MyRequest and as a response receiving MyResponse
// The sender will use Protocol Buffers to serialize/deserialize messages.
IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory(aSerializer);
mySender = aSenderFactory.createDuplexTypedMessageSender(MyResponse.class, MyRequest.class);
// Subscribe to receive response messages.
mySender.responseReceived().subscribe(myOnResponseHandler);
// Create TCP messaging for the communication.
// Note: 10.0.2.2 is a special alias to the loopback (127.0.0.1)
// on the development machine.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel
= aMessaging.createDuplexOutputChannel("tcp://10.0.2.2:8060/");
//= aMessaging.createDuplexOutputChannel("tcp://192.168.1.102:8060/");
// Attach the output channel to the sender and be able to send
// messages and receive responses.
mySender.attachDuplexOutputChannel(anOutputChannel);
}
private void onSendRequest(View v)
{
// Create the request message using ProtoBuf builder pattern.
final MyRequest aRequestMsg = MyRequest.newBuilder()
.setText(myMessageTextEditText.getText().toString())
.build();
// Send the request message.
try
{
mySender.sendRequestMessage(aRequestMsg);
}
catch (Exception err)
{
EneterTrace.error("Sending the message failed.", err);
}
}
private void onResponseReceived(Object sender,
final TypedResponseReceivedEventArgs<MyResponse> e)
{
// Display the result - returned number of characters.
// Note: Marshal displaying to the correct UI thread.
myRefresh.post(new Runnable()
{
@Override
public void run()
{
myResponseEditText.setText(Integer.toString(e.getResponseMessage().getLength()));
}
});
}
private EventHandler<TypedResponseReceivedEventArgs<MyResponse>> myOnResponseHandler
= new EventHandler<TypedResponseReceivedEventArgs<MyResponse>>()
{
@Override
public void onEvent(Object sender,
TypedResponseReceivedEventArgs<MyResponse> e)
{
onResponseReceived(sender, e);
}
};
private OnClickListener myOnSendRequestClickHandler = new OnClickListener()
{
@Override
public void onClick(View v)
{
onSendRequest(v);
}
};
}
</pre>
</div>
<div>
<br /></div>
<h3>
.NET Service Application</h3>
<div>
<div>
The .NET service is a simple console application listening to TCP and receiving requests to calculate the length of a given text.</div>
<div>
<br /></div>
<div>
The service uses EneterProtoBufSerializer. It instantiates the serializer and puts the reference to the DuplexTypedMessagesFactory ensuring the message receiver will use Protocol Buffers to deserialize incoming messages and serialize response messages.</div>
<div>
<br /></div>
<div>
The whole implementation is very simple:</div>
</div>
<div>
<pre class="brush: csharp">using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.ProtoBuf;
using message.declarations;
namespace ServiceExample
{
class Program
{
private static IDuplexTypedMessageReceiver<MyResponse, MyRequest> myReceiver;
static void Main(string[] args)
{
// Instantiate Protocol Buffer based serializer.
ISerializer aSerializer = new ProtoBufSerializer();
// Create message receiver receiving 'MyRequest' and receiving 'MyResponse'.
// The receiver will use Protocol Buffers to serialize/deserialize messages.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory(aSerializer);
myReceiver = aReceiverFactory.CreateDuplexTypedMessageReceiver<MyResponse, MyRequest>();
// Subscribe to handle messages.
myReceiver.MessageReceived += OnMessageReceived;
// Create TCP messaging.
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel
= aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8060/");
// Attach the input channel and start to listen to messages.
myReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The service is running. To stop press enter.");
Console.ReadLine();
// Detach the input channel and stop listening.
// It releases the thread listening to messages.
myReceiver.DetachDuplexInputChannel();
}
// It is called when a message is received.
private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<MyRequest> e)
{
Console.WriteLine("Received: " + e.RequestMessage.Text);
// Create the response message.
MyResponse aResponse = new MyResponse();
aResponse.Length = e.RequestMessage.Text.Length;
// Send the response message back to the client.
myReceiver.SendResponseMessage(e.ResponseReceiverId, aResponse);
}
}
}
</pre>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com2tag:blogger.com,1999:blog-5196103582241137578.post-50021678677813157382013-07-04T23:08:00.000+02:002013-08-05T09:45:13.378+02:00How to Design Interprocess CommunicationThere are many aspects and possibilities that must be considered when designing the interprocess communication. E.g. which communication protocol or transportation mechanism shall be used, how to serialize data, what is the communication behavior, what to do if the connection is broken, etc.<br />
This article will discuss the communication between processes and will try to provide a guide how<br />
to consider various aspects and possibilities when designing the communication between processes.<br />
<br />
<a name='more'></a><br />
<h3>
Software Architecture and Interprocess Communication</h3>
To design and implement the communication between processes first we need to understand how the<br />
interprocess communication is related to the software architecture.<br />
<br />
Therefore, what is the software architecture?<br />
<br />
There is no one commonly agreed definition for the term software architecture. In fact there are multiple definitions. But in general they say the software architecture is a way how a software system is structured. E.g. the definition from [Bas12]:<br />
<br />
<i>The software architecture of a system is the set of structures needed to reason about the system, which comprise software elements, relations among them, and properties of both.</i><br />
<br />
The term structure typically means something static. Therefore it is obvious the software architecture includes a decomposition of elements with their static relationships such as dependencies or hierarchies. And it may not be so obvious the software architecture includes dynamic behavior too. It means how dynamics such as message flow, passing through states or sequential or parallel running is organized (structured) in the software system.<br />
<br />
Therefore the architecture is not just a static organization of elements but also dynamic behavior which includes the interaction between elements. And if interacting elements are running in different processes it is the interprocess communication.<br />
<br />
The interprocess communication differs from the interaction within one process. It introduces many aspects that are not present in the interaction inside one process. E.g. transferring data across the network is much slower than a local call, or security aspect, or one communicating part can be temporarily unavailable, or communicating parts can be implemented in different programming languages and running on different operating systems, etc.<br />
All these aspects can have significant impact on the software system and therefore they need to be carefully considered when creating the software architecture.<br />
<br />
<h3>
Creating Software Architecture</h3>
The software architecture (set of structures representing the system) is derived from requirements. The<br />
software architect must recognize those requirements which have profound effect on structures representing the system. These requirements are called Architecturally Significant Requirements and it is not easy to find them.<br />
There are three categories of requirements:<br />
<ul>
<li>Functional requirements</li>
<li>Non-functional requirements</li>
<li>Constrains</li>
</ul>
<br />
<b><i>Functional requirements</i></b> describe what features are expected. They specify what the software shall do. Usually it is not so difficult to capture them into some kind of functional specification document.<br />
However, these requirements are typically not those that drive the structuring (architecting) the software.<br />
E.g. it is possible to satisfy same functional requirements by different architectures. But will they be equally good for the given product or project?<br />
It is typical a software system has required features but still needs to be reworked. E.g. because it is difficult to add a new feature, or because it is expensive to maintain it.<br />
<br />
<b><i>Non-functional requirements</i></b> represent certain quality attributes which are expected from the whole software system or from functional requirements. These quality attributes are typically not obvious just from functional requirements. In many cases they are just implicitly assumed. The software architect must capture them by talking to various stakeholders to understand the wider context of the software system. E.g. what drives your business to be successful and how the architecture shall support that? If a business driver is 'time to market' it means it may be important to be able to introduce new features in a short time. Or your application is recognized by customers because you are able to quickly customize it according to their needs. Or your application must provide outstanding performance. Or you want to port the application to various platforms.<br />
By analyzing these requirements you find yourself thinking about modules and layers with certain responsibilities, proposing mechanisms to extend some behavior or thinking about technologies you may need. Quality attributes force you to organize the software system into structures. Therefore nonfunctional requirements have the major impact on the software architecture.<br />
<br />
<b><i>Constrains</i></b> are requirements which specify what is defined and cannot be changed. E.g. using a certain programming language or operating system. There can be also constrains that have an impact on the architecture. E.g. it can be decided the software system must be a cloud based system. Or it must be closely integrated with some other system requiring the integration across multiple layers what can result to mirror the same architecture.<br />
<br />
<h3>
Quality Attributes and Interprocess Communication</h3>
As discussed above, quality attributes have the major impact on the software architecture. There are many types of quality attributes that can be reflected by the architecture:<br />
<br />
performance, usability, reliability, recoverability, security, modifiability, reusability, testability, scalability, extensibility, portability etc.<br />
<br />
(You can refer to ISO 25010 for various categories of quality attributes but there are more than specified in this standard.)<br />
<br />
The quality attributes affect the interprocess communication but also the interprocess communication may introduce new quality attributes to the software system. E.g. the interprocess communication may require to address topics like slow network, broken connection, confidential data, etc. This can result into additional quality attributes (non-functional requirements) for your system like performance, availability, recoverability, security, etc.<br />
<br />
<span style="color: blue;">The interprocess communication must provide the interaction between entities in accordance with quality attributes which are identified for the system.</span> There are various tactics you can apply in order to address quality attributes in your architecture. E.g. to achieve the modifiability you can use tactics like reducing size of a module, encapsulation or restricting dependencies. To address quality attributes in the interprocess communication you need to use tactics for the communication between processes.<br />
<br />
<h3>
Tactics for Interprocess Communication</h3>
The following part discusses quality attributes and tactics which are relevant for the interprocess communication. It summarizes quality attributes from the interprocess communication perspective and shows possibilities for designing the communication.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNZq7CJHx70egyCkT4x9Kns8uPlBYprD1KqeTEvsclgPfTzwG2c6KcFbv0B7t6uaXMaECcrgFUB7OxRT7TsTCTzx6W0Md0uWg64y1qbOCNB90dUyRIRXM_rjLRM4A1FOXikBwoIpXQAIT/s731/IPC_90dpi.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="581" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNZq7CJHx70egyCkT4x9Kns8uPlBYprD1KqeTEvsclgPfTzwG2c6KcFbv0B7t6uaXMaECcrgFUB7OxRT7TsTCTzx6W0Md0uWg64y1qbOCNB90dUyRIRXM_rjLRM4A1FOXikBwoIpXQAIT/s640/IPC_90dpi.png" width="640" /></a><br />
<br />
<h4>
Performance</h4>
The performance is about how much work a software system is able to perform for a specified time interval. In the interprocess communication the performance is related to the speed (how fast a message is serialized, sent, received and deserialized) and the throughput (how many requests is the system able to process).<br />
To address the performance:<br />
<br />
<ul>
<li>Consider to use binary serializer instead of XML or JSON.</li>
<li>In case of the interprocess communication on one computer prefer to use shared memory or named pipes instead of TCP, Web Sockets or HTTP.</li>
<li>In case of the communication across the network consider to use TCP or Web Sockets instead of HTTP. E.g. if the communication requires notification messages (pushed from the service) or one request can generate multiple responses. HTTP is not suitable because it is 'one request' - 'one response' protocol. Therefore various polling mechanisms or tricks must be used to achieve notifications or multiple responses. This is an overhead reducing the performance.</li>
<li>Prevent unnecessary opening and closing connections.</li>
<li>Prefer parallel processing of incoming connections on the service side.</li>
<li>You can consider using a load balancer component to distribute the workload across multiple computers.</li>
</ul>
<br />
<br />
<div>
<h4>
Resource Friendly</h4>
<div>
The resource friendly is an ability to minimize consuming resources. In the interprocess communication the resource consumption is related typically to consuming batteries in mobile devices. (How long the application can run and communicate without charging the battery?)</div>
<div>
To address the resource friendly:</div>
<div>
<ul>
<li>In order to save batteries the device can switch to the sleeping mode. Prefer to handle this state in your communication instead of programmatically preventing the device from the sleeping. E.g. you can consider opening connection only for needed time. Or you can consider providing a mechanism recovering the connection after the sleeping mode.</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<h4>
Interoperability</h4>
<div>
The interoperability is an ability to exchange data and correctly interpret them between diverse systems.</div>
<div>
To address the interoperability:</div>
<div>
<ul>
<li>Precisely design the API and provide a comprehensive documentation with examples.</li>
<li>You can consider using communication standards. But be careful to rely only on standards. The problem is the same standard can have "slightly" different implementation/interpretation in two different systems.</li>
<li>If you use a communication middleware then other systems will probably need to use the same middleware if they want to interact with your system. Analyze if it is a problem or not. Also consider which middleware you will choose. E.g. if you need the interoperability across multiple platforms then the middleware should be available on those platforms.</li>
<li>You can consider supporting multiple communication standards, mechanisms and middlewares in your software system.</li>
<li>You can consider encapsulating the communication functionality to a separate component (layer) which would be extensible. Then if needed you can extend the system by other communication technology in order to achieve the interoperability.</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<h4>
Accessibility</h4>
<div>
The accessibility is a degree a software system is accessible to various people. In the interprocess communication the accessibility is related to make the system accessible for various types of devices and platforms people may use.</div>
<div>
To address the accessibility:</div>
<div>
<ul>
<li>If you provide client applications for multiple devices and platforms (e.g. Android, iPhone, Windows Phone, HTML5, .NET ...) then you need to consider the multiplatform aspect in the communication too. E.g. binary data is not compatible among these platforms. So you may need to use e.g. XML or JSON serialization. Be aware of various string formats (UTF-8, UTF-16 …). If you transfer binary data be aware platforms may differ in encoding of numbers (littleendian, bigendian). </li>
<li>You can consider exposing the service via multiple communication protocols at the same time. E.g. the service can listen to TCP, Web Sockets and HTTP. (Windows Phone 7.0 client uses HTTP, HTML5 client uses Web Sockets and .NET client can use TCP.)</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<h4>
Availability</h4>
<div>
The availability is an ability of a system to stay operable and functional for a declared time of a given time interval. E.g. annual availability can be 99.9% (i.e. overall time the system can be down during the year is 8.76 hours).</div>
<div>
To address the availability:</div>
<div>
<ul>
<li>You can consider to provide identical backup services so that if the service gets unavailable (e.g. because of a maintenance or a crash) the communication is automatically rerouted to backups and overall system stays functional. (This approach can be a little tricky if the service received a request but failed before sent the response. There should be a mechanism handling this state. E.g. client may need to repeat the request in such case.)</li>
<li>Or you can consider providing multiple identical services. Incoming messages would be then multiplied and forwarded for parallel processing to all services. In case one service gets unavailable the request is still processed by rest of running services. So the overall system stays functional.</li>
<li>Consider to provide a mechanism constantly monitoring the network connection so that the disconnection is detected early and the system can handle it (e.g. to start a recovery procedure).</li>
</ul>
</div>
<div>
<br /></div>
</div>
<div>
<h4>
Recoverability</h4>
<div>
The recoverability is an ability of a system to recover from a failure and continue in functioning. In the interprocess communication the recoverability is related to recover from the broken connection.</div>
<div>
To address the recoverability:</div>
<div>
<ul>
<li>Consider to provide a mechanism constantly monitoring the connection so that the broken connection is detected early.</li>
<li>Consider to provide a reconnecting mechanism.</li>
<li>You can also consider providing a message buffering mechanism. So that in case of a disconnection sent messages are stored in the buffer until the connection is not recovered. Once the connection is reopen messages from the buffer are sent to the receiver. This can be useful for unstable networks where short sporadic disconnections can occur (e.g. a mobile device can get out of the signal).</li>
<li>If your application consists of multiple interacting processes consider to make the communication among them startup independent. E.g. sent messages can be buffered until the message receiver is up and running.</li>
</ul>
</div>
<div>
<br /></div>
</div>
<div>
<h4>
Reliability</h4>
<div>
The reliability in the interprocess communication is an ability to deliver messages.</div>
<div>
To address reliability:</div>
<div>
<ul>
<li>Consider to use acknowledged messaging. It means the message receiver will send back a confirmation message that the message was received. If the sender does not get the confirmation within a specified time it will consider the message as not delivered.</li>
<li>Consider to use persistent message queues. Messages are persisted in the queue and so they are not lost. The receiver can pick them up from the queue whenever is ready.</li>
</ul>
</div>
<div>
<br /></div>
</div>
<div>
<h4>
Security</h4>
<div>
The security consists of: confidentiality to protect messages from unauthorized access, integrity to protect messages from unauthorized manipulation and authenticity to verify identify of communicating parts (if they are really who they are saying they are).</div>
<div>
To address security in the interprocess communication:</div>
<div>
<ul>
<li>You can consider using secured TCP connection (SSL or TLS). The whole communication is encrypted so messages are protected from unauthorized access and manipulation and the protocol is also able to verify the identity of both communicating parts.</li>
<li>You can consider using symmetric AES to encrypt messages. It protects messages from unauthorized access and manipulation but is not able to verify the message sender identity.</li>
<li>You can consider using asymmetric RSA (with public and private keys) to encrypt messages. It protects messages from unauthorized access and manipulation and is able to verify message sender identity.</li>
<li>You can consider using digitally signed messages. This approach does not protect messages from the unauthorized access but protects them from unauthorized manipulation and is able to verify the message sender identity.</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<h4>
Scalability</h4>
<div>
Scalability is an ability to handle increasing workload by adding new resources. In the interprocess communication the scalability is related to increase the performance of the system by adding next computers hosting processing services.</div>
<div>
To address scalability:</div>
<div>
<ul>
<li>You can consider using the load balancer component that would maintain a list of identical services and distribute the workload among them.</li>
</ul>
</div>
<div>
<br /></div>
</div>
<div>
<h4>
Monitorability</h4>
<div>
Monitorability is an ability to monitor how the system is functioning. In the interprocess communication the monitorability is about monitoring the connection availability or monitoring the workload of a service.</div>
<div>
To address monitorability:</div>
<div>
<ul>
<li>You can consider providing a mechanism continuously monitoring the connection so that the system is informed whether the connection is working or not.</li>
<li>You can consider providing a service to monitor the workload on server computers. This workload information can be used e.g. by a load balancer to optimally distribute the workload among multiple servers.</li>
</ul>
</div>
<div>
<br /></div>
</div>
<div>
<h3>
References</h3>
<div>
[Bas12] Software Architecture in Practice (3rd Edition) by Len Bass, Paul Clements and Rick Kazman.</div>
</div>
<div>
<br /></div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com1tag:blogger.com,1999:blog-5196103582241137578.post-69946807396654391282013-04-28T13:29:00.001+02:002013-04-28T14:17:38.450+02:00Digital Signature<b>Summary:</b> A short explanation what is digital signature and how it works.<br />
<br />
<a name='more'></a><h3>
Introduction</h3>
In general the security includes following aspects:<br />
<ul>
<li><i>Confidentiality</i> - to protect messages from unauthorized access.</li>
<li><i>Integrity</i> - to protect messages from unauthorized manipulation.</li>
<li><i>Authenticity</i> - to verify identity of communicating parts. (If they are who they are saying they are.)</li>
</ul>
The digital signature is a solution covering Integrity and Authenticity. It means a digitally signed data is protected from unauthorized modification and it is also possible to verify the identity of its author.<br />
The digital signature (if not combined with encrypting of the message) does not protect data from unauthorized access. The digitally signed data can be read by anybody but it is possible to verify its author and check if the content was not altered by somebody else.<br />
<div>
<br /></div>
<h3>
How Digital Signature Works</h3>
<div>
<div>
The digital signature uses so called asymmetric encryption (e.g. RSA or DSA) which contains two encryption keys:</div>
<div>
<ul>
<li><i>Private key</i> - the secret key available only to its owner.</li>
<li><i>Public key</i> - the key available for everybody.</li>
</ul>
<div>
Private and public keys are related to each other. <span style="color: #6aa84f;">What is encrypted by the public key can be decrypted only by the corresponding private key and vice versa</span>.</div>
<div>
E.g. if John encrypts the message using Peter's public key then only Peter can decrypt it because only he has the corresponding private key.</div>
<div>
But it works also other way around. If Peter encrypts something with his private key then only corresponding public key can decrypt it. And exactly this is used for the digital signature. The main idea is <span style="color: #6aa84f;">if I can decrypt it by Peter's public key then I know it had to be encrypted by Peter because only he has the private key</span> => therefore I am able to identify it was Peter who encrypted it.</div>
</div>
</div>
<div>
<br /></div>
<div>
<div>
The digital signature uses the same principle. The difference is it does not encrypt the message but it calculates the checksum from data and the checksum is then encrypted by signer's private key. This encrypted checksum is what is called the digital signature.</div>
</div>
<div>
<br /></div>
<div>
<div>
Signing data:</div>
<div>
<ol>
<li>The checksum (e.g. SHA1) is calculated from data.</li>
<li>The checksum is encrypted by the signer private key => this <span style="color: #6aa84f;">encrypted checksum is the digital signature</span>.</li>
<li>The data is provided together with the digital signature.</li>
</ol>
<div>
<br /></div>
<div>
Reading signed data:</div>
<div>
<ol>
<li>The checksum is calculated from received data.</li>
<li>Signer's public key is used to decrypt the checksum (digital signature) coming with data.</li>
<li><span style="color: #6aa84f;">If the decrypted checksum is the same as the checksum calculated in the step 1 then data is not altered and it originates from the declared sender</span>.</li>
</ol>
</div>
</div>
</div>
<div>
<div>
So, in order to decrypt the digital signature we need to know who signed data and then use his public key. Therefore <span style="color: #6aa84f;">we need a mechanism how to get the signer's public key. Important is this mechanism must be safe ensuring the public key really belongs to the signer</span>. E.g. if somebody is able to hack the system and replace Peter's public key then this person can digitally sign data with his own private key (which corresponds with the fake public key) under Peter's name. Then if somebody reads such massage from "Peter" he would not be able to recognize something is wrong because the hacked system would provide him the fake public key that would be able to decrypt the fake signature - the signature verification would pass successfuly.</div>
<div>
<br /></div>
<div>
The mechanism providing the safe connection between the signer identity and his public key is called Digital Certificate.</div>
</div>
<div>
<br /></div>
<div>
<h3>
Digital Certificate</h3>
<div>
The digital certificate is like an ID card identifying its owner. <span style="color: #6aa84f;">It safely binds the public key with the particular signer</span> (e.g. person, company or organization). The digital certificate is typically issued by a trusted authority. This authority is called Certificate Authority (CA). It means there is a mutually trusted third party that can be asked to create the digital certificate. This trusted authority verifies the real identity of the applicant and then generates the private and corresponding public keys. The name of the owner and other public information including the public key and the validity time is then digitally signed by the certificate authority and put into one file which is called the public digital certificate.</div>
<div>
Therfore, <span style="color: #6aa84f;">the applicant receives two things from the certificate authority. The private key and the public digitial certificate</span>.</div>
<div>
The trick is <span style="color: #6aa84f;">the public certificate is digitally signed by the certificate authority so it is not easy to alter</span> the name and the associated public key inside. E.g. if somebody changes the public key or the name the digital signature from the certificate authority would not match anymore.</div>
<div>
<br /></div>
<div>
The owner of the cerificate can sign data with his private key and then attach his public certificate directly to signed data. The reader then uses the attached certificate to obtain the public key to decrypt the signature.</div>
<div>
<br /></div>
<div>
Signing and using the digital certificate:</div>
<div>
<ol>
<li>The checksum (e.g. SHA1) is calculated from data.</li>
<li>The checksum is encrypted by the signer private key => this <span style="color: #6aa84f;">encrypted checksum is the digital signature</span>.</li>
<li><span style="color: #6aa84f;">The data is provided together with the signature and the digital certificate</span>.</li>
</ol>
</div>
<div>
<br /></div>
<div>
Reading of signed data with attached certificate:</div>
<div>
<ol>
<li>The validity of the attached certificate is evaluated. It means if the certificate was issued by a trusted authority. If the certificate was not altered and if the certificate is valid.</li>
<li>The checksum is calculated from received data.</li>
<li>The <span style="color: #6aa84f;">public key from the certificate</span> is used to decrypt the digital signature (checksum) attached to the message.</li>
<li><span style="color: #6aa84f;">If the decrypted checksum is the same as the checksum calculated in the step 1 then data is not altered and it originates from the declared sender</span>.</li>
</ol>
</div>
</div>
<div>
<br /></div>
<br />Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com3tag:blogger.com,1999:blog-5196103582241137578.post-68822030224550507622013-03-23T15:45:00.000+01:002013-03-23T15:53:21.381+01:00Synchronous Client Service Communication<b>Summary:</b> Example showing how to implement synchronous request-response communication between applications.<br />
<br />
<a name='more'></a><br />
<div>
The source code for this example can be <a href="http://eneter.net/Downloads/Examples/SynchronousRequestResponse.zip">downloaded from here</a>. To compile the example you need to add the eneter library among references.<br />
<br />
<h3>
Introduction</h3>
The example bellow demonstrates a communication scenario where the client application sends a message to the service application and waits for the response.<br />
It means the client application does not continue after the sending but is blocked until the response is received or the timeout is exceeded.<br />
<br />
To demonstrates this scenario the example implements a simple service application calculating two numbers and a simple client application using the service to calculate numbers. When the client sends the request it waits until the calculation result is received from the service.<br />
The communication between applications is based on Websockets but you can use any other protocol or transportation mechanism e.g. TCP, SharedMemory, ...<br />
<br />
<br />
The example uses <span style="color: #bf9000;">Eneter Messaging Framework</span> that makes the whole communication very simple.<br />
(The framework is free for non-commercial use and can be downloaded from <a href="http://www.eneter.net/ProductDownload.htm">http://www.eneter.net/ProductDownload.htm</a>.<br />
More detailed technical info can be found at <a href="http://www.eneter.net/ProductInfo.htm">technical info</a>.)<br />
<br />
<br />
<h3>
Client Application</h3>
The client is a simple application allowing users to enter numbers and then send the calculation request to the service. Once the message is sent the client waits until the result is received.<br />
<br />
<pre class="brush: csharp">using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.WebSocketMessagingSystem;
namespace CalculatorClientSync
{
public partial class Form1 : Form
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
private ISyncDuplexTypedMessageSender<ResponseMessage, RequestMessage> mySender;
public Form1()
{
InitializeComponent();
OpenConnection();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
CloseConnection();
}
private void OpenConnection()
{
// Create the synchronous message sender.
// It will wait max 5 seconds for the response.
// To wait infinite time use TimeSpan.FromMiliseconds(-1) or
// default constructor new DuplexTypedMessagesFactory()
IDuplexTypedMessagesFactory aSenderFactory =
new DuplexTypedMessagesFactory(TimeSpan.FromSeconds(5));
mySender = aSenderFactory.CreateSyncDuplexTypedMessageSender<ResponseMessage, RequestMessage>();
// Use Websocket for the communication.
// If you want to use TCP then use TcpMessagingSystemFactory().
IMessagingSystemFactory aMessaging = new WebSocketMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessaging.CreateDuplexOutputChannel("ws://127.0.0.1:8099/Calculator/");
// Attach the output channel and be able to send messages
// and receive response messages.
mySender.AttachDuplexOutputChannel(anOutputChannel);
}
private void CloseConnection()
{
// Detach input channel and stop listening to response messages.
mySender.DetachDuplexOutputChannel();
}
private void CalculateBtn_Click(object sender, EventArgs e)
{
// Create the request message.
RequestMessage aRequest = new RequestMessage();
aRequest.Number1 = int.Parse(Number1TextBox.Text);
aRequest.Number2 = int.Parse(Number2TextBox.Text);
// Send request to the service to calculate 2 numbers.
// It waits until the response is received.
ResponseMessage aResponse = mySender.SendRequestMessage(aRequest);
// Display the result.
ResultTextBox.Text = aResponse.Result.ToString();
}
}
}
</pre>
<br />
<br />
<h3>
Service Application</h3>
The service is a simple console application listening to requests to calculate numbers. When the request is received it calculates numbers and sends back the result. The implementation is very simple.<br />
<br />
<br />
<pre class="brush: csharp">using System;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.WebSocketMessagingSystem;
namespace CalculatorService
{
// Request message.
public class RequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
// Response message.
public class ResponseMessage
{
public int Result { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Create message receiver.
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage> aReceiver =
aReceiverFactory.CreateDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>();
// Subscribe to process request messages.
aReceiver.MessageReceived += OnMessageReceived;
// Use WebSocket for the communication.
// Note: You can also other messagings. E.g. TcpMessagingSystemFactory
IMessagingSystemFactory aMessaging = new WebSocketMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessaging.CreateDuplexInputChannel("ws://127.0.0.1:8099/Calculator/");
// Attach the input channel to the receiver and start listening.
aReceiver.AttachDuplexInputChannel(anInputChannel);
Console.WriteLine("The calculator service is running. Press ENTER to stop.");
Console.ReadLine();
// Detach the input channel to stop listening.
aReceiver.DetachDuplexInputChannel();
}
private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<RequestMessage> e)
{
// Calculate numbers.
ResponseMessage aResponseMessage = new ResponseMessage();
aResponseMessage.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("{0} + {1} = {2}", e.RequestMessage.Number1, e.RequestMessage.Number2, aResponseMessage.Result);
// Send back the response message.
var aReceiver = (IDuplexTypedMessageReceiver<ResponseMessage, RequestMessage>)sender;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
</pre>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com2tag:blogger.com,1999:blog-5196103582241137578.post-41847601756286975082013-03-09T12:30:00.001+01:002016-03-05T19:13:12.252+01:00How to add Eneter Library into Android Project<b>Summary:</b> Step-by-step procedure showing how to add Eneter library into your Android project in Eclipse.<br />
<br />
<a name='more'></a><br />
<h3>
Introduction</h3>
<div>
<div>
It seems there is a lot of confusion regarding adding an external library into the Android project.</div>
<div>
If you use Eclipse and you add the library simply via '<i>Properties</i>' -> '<i>Java Build Path</i>' -> '<i>Libraries</i>' then you can get into a state that you can build your Android application but when you upload it into the Android device it will not work and will be forced to close.</div>
</div>
<div>
<br /></div>
<div>
When you then check LogCat you may see errors like:</div>
<div>
<ul>
<li>Could not find class ... or java.lang.ClassNotFoundException.</li>
<li>Failed resolving ...</li>
</ul>
The issue has already been discussed on <a href="http://stackoverflow.com/questions/3642928/adding-a-library-jar-to-an-eclipse-android-project">stackoverflow</a> too. And the same problem you can experience when you want to include eneter-messagin-android into your project.<br />
<br /></div>
<h3>
How to add library into Android project</h3>
<div>
To add a library into the project you need to import it instead of adding it via project properties. Here is the procedure how to do it:</div>
<div>
<ol>
<li>Create a new folder <i>libs</i> in your project.</li>
<li>Right click on '<i>libs</i>' and choose '<i>Import...</i>' -> '<i>General/File System</i>' -> '<i>Next</i>'.</li>
<li>Then click '<i>Browser</i>' button for '<i>From directory</i>' and navigate to directory with <span style="color: #b45f06;">eneter-messaging-android</span>' library.</li>
<li>Select check box for eneter-messaging-android.</li>
<li>Press '<i>Finish</i>'</li>
</ol>
</div>
Ondrejhttp://www.blogger.com/profile/11029096061173289386noreply@blogger.com12