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);
}
}
}

Sem comentários: