Archive for March, 2012

RAIDar Protocol Sample for Metro

Here is a sample WinRT (Metro style app) code to utilize RAIDar Protocol. It employs DatagramSocket, instead of UdpClient of desktop app, in order to communicate with ReadyNAS system(s) by UDP broadcast.

Developed in C# and tested on Windows 8.1.

using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

private static List<string> responses = new List<string>();

internal static async Task<string[]> SendRequestAsync()
{
    // Prepare RAIDar Protocol request.
    const string request = "00 00 07 05 00 00 00 01 00 00 00 00 A4 A1 EF B8 FF FF FF FF 00 00 00 1C 00 00 00 00";
    string[] requestArray = request.Split();

    byte[] packet = new byte[28];
    for (int i = 0; i <= 27; ++i)
    {
        packet[i] = Byte.Parse(requestArray[i], NumberStyles.HexNumber);
    }

    // Instantiate DatagramSocket and register MessageReceived event.
    DatagramSocket socket = new DatagramSocket();
    socket.MessageReceived += ReceiveResponse;

    // Prepare EndpointPair (LocalHostName and LocalServiceName are null, RemoteHostName is
    // for UDP broadcast, RemoteServiceName (UDP port) is specially for RAIDar Protocol).
    EndpointPair endpoint = new EndpointPair(null, "", new HostName("255.255.255.255"), "22081");

    try
    {
        // Send request.
        IOutputStream stream = await socket.GetOutputStreamAsync(endpoint);
        await stream.WriteAsync(packet.AsBuffer());

        // Wait for timeout (3 seconds).
        await Task.Delay(TimeSpan.FromSeconds(3));

        return responses.ToArray();
    }
    finally
    {
        // Close DatagramSocket and unregister MessageReceived event.
        socket.Dispose();

        responses.Clear();
    }
}

private static void ReceiveResponse(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    // Read out response.
    using (DataReader reader = args.GetDataReader())
    {
        byte[] packet = reader.DetachBuffer().ToArray();

        // Check if response has valid length (Leading 28 bytes cannot be correctly decoded to text).
        if (packet.Length <= 28)
            return;

        // Decode response to text.
        string response = Encoding.UTF8.GetString(packet, 28, packet.Length - 28);

        // Remove unnecessary Tab and Lf.
        response = response.Replace("\t", "\n").Replace("\n\n", "\n").Replace("\n", Environment.NewLine);

        responses.Add(response);
    }
}

Complete source code