sexta-feira, 18 de dezembro de 2009

Multicasting UPnP Messages in the network

If you like and use it don't forget the credits and please leave a comment. Thanks

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace UPnP.Server
{
public delegate void ReceivedUPnPMSearchHandler(IPEndPoint from, String message);

public class SSDP
{
public Int32 DefaultPort { get; set; }

//OnReceived M-Search

public event ReceivedUPnPMSearchHandler OnReceivedMSearch;

//Holds the ip addresses of the currentMachine
List<IPAddress> MachineIPAddresses;
//Holds the multicast updclient sessions

Dictionary<IPAddress, UdpClient> MulticastSessions;

//Holds the unicast updclient sessions

Dictionary<IPAddress, UdpClient> UnicastSessions;

//Static variables to initialize sessions
private static IPAddress MulticastV4IPAddress = IPAddress.Parse("239.255.255.250");
private static IPEndPoint MulticastV4EndPoint = new IPEndPoint(MulticastV4IPAddress, 1900);

/// <summary>
/// Initializes the class and goes into initializing the sockets to use in the multicast.
/// </summary>

public SSDP()
{
InitializeSockets();
}

/// <summary>
/// Gets all the IPv4 addresses for the current machine
/// We will use this IPv4 Addresses in order to bind the Sockets
/// </summary>

private void InitializeIPAddresses()
{
MachineIPAddresses = new
List<IPAddress>();
foreach (IPAddress ipAddress in
Dns.GetHostAddresses(Dns.GetHostName()))
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
Console.WriteLine("Adding IP: {0}", ipAddress.ToString());
MachineIPAddresses.Add(ipAddress);
}
}

/// <summary>
/// Initializes the sockets, both unicast as multicast
/// Multicast will be used to broadcast informations about our service into the network
/// </summary>
private void InitializeSockets()
{
//Verifies if we have initialized the MachineIPAddresses for usage.
if (MachineIPAddresses == null)
this.InitializeIPAddresses();
MulticastSessions = new Dictionary<IPAddress, UdpClient>();
UnicastSessions = new Dictionary<IPAddress, UdpClient>();
//We will create a multicast and unicast socket for each machine ip address
foreach (IPAddress ipAddress in MachineIPAddresses)
{
//Creates the UdpClient for multicast
UdpClient multicastSession = new
UdpClient(AddressFamily.InterNetwork);
//this will allow us to connect to an port where other service is already connected. multicastSession.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//Binding the UdpClient to the IPv4 Address and to the defaultPort
multicastSession.Client.Bind(new IPEndPoint(ipAddress, DefaultPort));
//Defining as a multicast socket and joining the default group.
multicastSession.EnableBroadcast = true;
multicastSession.JoinMulticastGroup(MulticastV4IPAddress);
//Will allow us to listen to messages in the multicast group
multicastSession.BeginReceive(new AsyncCallback(ReceiveMessage), multicastSession);
MulticastSessions.Add(ipAddress, multicastSession);

//Creates the UdpClient for the unicast
UdpClient unicastSession = new UdpClient(AddressFamily.InterNetwork);
unicastSession.Client.Bind(new IPEndPoint(ipAddress, 0));
unicastSession.BeginReceive(new AsyncCallback(ReceiveMessage), unicastSession);
UnicastSessions.Add(ipAddress, unicastSession);
}
}

/// <summary>
/// Closes all the sockets
/// this is important to do before the application terminates.
/// </summary>
public void Dispose()
{
foreach (KeyValuePair<IPAddress, UdpClient> session in MulticastSessions)
session.Value.Close();
foreach (KeyValuePair<IPAddress, UdpClient> session in UnicastSessions)
session.Value.Close();
}

/// <summary>
/// Sends a message to the sockets in the multicast sessions
/// </summary>
/// &lt;param name="message">A preformated message to send to the multicast group</param>
public void SendMulticast(String message)
{
if (MachineIPAddresses == null)
InitializeIPAddresses();
foreach (IPAddress ipAddress in MachineIPAddresses)
SendMulticast(message, ipAddress);
}

/// <summary>
/// Sends a message to the sockets in the multicast sessions
/// </summary>
/// <param name="message">A preformated message to send to the multicast group</param>
/// <param name="to">The IPv4 of the socket group</param>
public void SendMulticast(String message, IPAddress to)
{
if (MulticastSessions == null)
InitializeSockets();

if (MulticastSessions[to] == null)
return;

UdpClient usession = MulticastSessions[to];
try { usession.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, to.GetAddressBytes()); }
catch (SocketException) { }
byte[] buffer = System.Text.UTF8Encoding.UTF8.GetBytes(message);
usession.Send(buffer, buffer.Length, MulticastV4EndPoint);
usession.Send(buffer, buffer.Length, MulticastV4EndPoint);
}

/// <summary>
/// Sends a message to the sockets in the unicast group.
/// We will use this to send a message to a client requesting a M-Search
/// </summary>
/// <param name="message">A preformated message to send to the unicast group</param>
/// <param name="to">The IPv4 of the destination</param>
public void SendUnicast(String message, IPEndPoint to)
{
UdpClient usession = UnicastSessions[to.Address];
if (usession == null) return;

byte[] buffer = System.Text.UTF8Encoding.UTF8.GetBytes(message);
usession.Send(buffer, buffer.Length, to);
}

/// <summary>
/// The multicast sockets receives a message and will invoke the specified OnReceive

/// </summary>
/// <param name="result"></param>
private void ReceiveMessage(IAsyncResult result)
{
byte[] buffer;
IPEndPoint ep = null;
UdpClient session = (UdpClient)result.AsyncState;
buffer = session.EndReceive(result, ref ep);
try
{
String message = System.Text.UTF8Encoding.UTF8.GetString(buffer);
if (message.Contains("M-SEARCH"))
{
Console.WriteLine("Received M-SEARCH from {0}", ((IPEndPoint)ep).Address.ToString());
if (OnReceivedMSearch != null) OnReceivedMSearch(ep, message);
}
}
catch (Exception) { }
session.BeginReceive(new AsyncCallback(ReceiveMessage), session);
}
}
}

C# and UPnP Socket made easy

I used transcoding in my place for years, first I just used the Windows Media player and the wonderfull XBox 360, but then that wasn't enought because I needed soft subtitles, for several reasons that are not called in here.
So I've changed the Server to be a TVersity Server, and it worked well during some time, before the Windows 7 was released and the confusion of Windows Foundation Media and DirectShow codecs, basicly the sofsubtitles don't work anymore, but TVersity had some minor issues to me, but issues never the less.
1. I can't do imedite fastforward
2. The files don't have description
and now without subtitles it was no longer a solution to me, so I keep on searching and found a new media server that back in the days that I was trying to find one it wasn't good enough to me now it was very good...
PS3 Media Server
Well I've tried for ages to build one Media Server of my own so being PS3 Media Server an open source one, I dig my hands into it.
And opened Visual Studio and started to play around.
So the first problem was building the Multicast and making the devices on my network knows that I was here.

I wasn't easy but reading the manual from UPnP Forum I was one step closer to get there.

So here is my first stage.
Multicasting UPnP Messages in the network.