Files
myfriendsaround/main/Libs/NetworkAwarenessTest/NetworkDetection/NetworkDetector.cs
T
farcasclaudiu c0d31a8652 map improvement
user picture
image crop
2011-03-31 06:24:59 +03:00

388 lines
18 KiB
C#

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
/**********************************************/
/* Copyright of Gabor Dolhai @ 2010 */
/* under MS-Pl license */
/* can be used freely for anybody */
/* If you use this code please send me an */
/*email about your project to dolhaig at gmail*/
/*******************Thanks*********************/
namespace NetworkDetection
{
#region Custom Enums and EventArgs
public enum NetworkTypeRequestStatus
{
Default = 0,
Started,//represents BackgroundWorker started
Ended//BackgroundWorker Finished
}
public class NetworkAvailableEventArgs : System.EventArgs
{
public NetworkAvailableEventArgs(bool isOnline)
{
IsOnline = isOnline;
}
public bool IsOnline { get; private set; }
}
public class NetworkDetectorEventArgs : System.EventArgs
{
public NetworkDetectorEventArgs(bool isOnline, Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType netType)
{
IsOnline = isOnline;
NetType = netType;
}
public bool IsOnline { get; private set; }
public Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType NetType { get; private set; }
}
#endregion
public class NetworkDetector
{
private static readonly NetworkDetector _instance = new NetworkDetector();
#region Events
public event EventHandler<NetworkAvailableEventArgs> OnNetworkON;
public event EventHandler<NetworkAvailableEventArgs> OnNetworkOFF;
public event EventHandler<NetworkAvailableEventArgs> OnNetworkChanged;
public event EventHandler<NetworkDetectorEventArgs> OnZuneConnected;
public event EventHandler<NetworkDetectorEventArgs> OnZuneDisconnected;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedEthernet;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedWifi;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedNone;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedBroadbandGsm;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedBroadbandCdma;
public event EventHandler<NetworkDetectorEventArgs> OnConnectedOther;
public event EventHandler<NetworkDetectorEventArgs> OnLostNetworkType;
public event EventHandler<NetworkDetectorEventArgs> OnAsyncGetNetworkTypeCompleted;
#endregion
private System.Windows.Threading.DispatcherTimer updateTimer, pollTimer;
private Queue<long> requestQueue; //queue to store the requests timestemps
private BackgroundWorker networkWorker;
private bool online = false;
private Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType net;
private NetworkTypeRequestStatus requestStatus; //current status of the BackgroundWorker
private bool IsInstantRequestPresent;
private bool detailedMode;
private bool isZuneConnected;
private NetworkDetector()
{
requestQueue = new Queue<long>();
requestQueue.Clear();
requestStatus = NetworkTypeRequestStatus.Default;
updateTimer = new System.Windows.Threading.DispatcherTimer();
updateTimer.Tick += new EventHandler(updateTimer_Tick);
updateTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);//there is no need to restart the BGWorker sooner then 300 millisec because the ~3request/sec requestlimit
//updateTimer.Start();
pollTimer = new System.Windows.Threading.DispatcherTimer();
pollTimer.Tick += new EventHandler(pollTimer_Tick);
networkWorker = new BackgroundWorker();
networkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(networkWorker_RunWorkerCompleted);
networkWorker.DoWork += new DoWorkEventHandler(networkWorker_DoWork);
IsInstantRequestPresent = false;
detailedMode = false; //by default I hide the framework events for better Developer experience
isZuneConnected = false;
SetupNetworkChange(); //signing on the framework event
}
public static NetworkDetector Instance
{
get
{
return _instance;
}
}
#region BackgroundWorker
void networkWorker_DoWork(object sender, DoWorkEventArgs e)
{
Debug.WriteLine(">>>>> GetNetType started " + System.DateTime.Now.ToString("T") + " >>>>>");
e.Result = Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType;
}
//no need to lock the variables if We do everithing in the completed event handler
void networkWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DetectOnlineStatus();
if ((detailedMode) || (net != (Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType)e.Result))
{
//there is no need to get events all the time, just when really changing something or the DetailedMode is true
if (net != (Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType)e.Result)
RaiseNotify(OnLostNetworkType, new NetworkDetectorEventArgs(online, net));
net = (Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType)e.Result;
Debug.WriteLine(" New NetType: " + net.ToString());
if (net == Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Ethernet) Debug.WriteLine("!!!!! Zune is Connected");
switch (net)
{
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Ethernet:
if (!isZuneConnected)
{
isZuneConnected = true;
RaiseNotify(OnZuneConnected, new NetworkDetectorEventArgs(online, net));
}
RaiseNotify(OnConnectedEthernet, new NetworkDetectorEventArgs(online, net));
break;
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Wireless80211:
if (isZuneConnected)
{
isZuneConnected = false;
RaiseNotify(OnZuneDisconnected, new NetworkDetectorEventArgs(online, net));
}
RaiseNotify(OnConnectedWifi, new NetworkDetectorEventArgs(online, net));
break;
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.MobileBroadbandCdma:
if (isZuneConnected)
{
isZuneConnected = false;
RaiseNotify(OnZuneDisconnected, new NetworkDetectorEventArgs(online, net));
}
RaiseNotify(OnConnectedBroadbandCdma, new NetworkDetectorEventArgs(online, net));
break;
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.MobileBroadbandGsm:
if (isZuneConnected)
{
isZuneConnected = false;
RaiseNotify(OnZuneDisconnected, new NetworkDetectorEventArgs(online, net));
}
RaiseNotify(OnConnectedBroadbandGsm, new NetworkDetectorEventArgs(online, net));
break;
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.None:
if (!online)
{
if (isZuneConnected)
{
/*if we lost all network connection and the Zune was present before,
then we lost the Zune too. Normally when Zune is present and then we got
a None NetType, the PC just lost the internet connection but not the Zune sync*/
isZuneConnected = false;
RaiseNotify(OnZuneDisconnected, new NetworkDetectorEventArgs(online, net));
}
}
RaiseNotify(OnConnectedNone, new NetworkDetectorEventArgs(online, net));
break;
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.AsymmetricDsl:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Atm:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.BasicIsdn:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Ethernet3Megabit:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.FastEthernetFx:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.FastEthernetT:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Fddi:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.GenericModem:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.GigabitEthernet:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.HighPerformanceSerialBus:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.IPOverAtm:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Isdn:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Loopback:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.MultiRateSymmetricDsl:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Ppp:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.PrimaryIsdn:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.RateAdaptDsl:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Slip:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.SymmetricDsl:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.TokenRing:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Tunnel:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Unknown:
case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.VeryHighSpeedDsl:
default://theoretically we can't get here but better be prepared
RaiseNotify(OnConnectedOther, new NetworkDetectorEventArgs(online, net));
break;
}
}
for (int i = 0; i < requestQueue.Count; i++)
{
if (requestQueue.Peek() < System.DateTime.Now.Ticks) requestQueue.Dequeue();
//the requests before this moment just got answered
//if other requests are coming right after this, they will be served inside the next networkWorker_RunWorkerCompleted
}
if (requestQueue.Count == 0) updateTimer.Stop();
if (IsInstantRequestPresent) //the user requested a single poll
{
RaiseNotify(OnAsyncGetNetworkTypeCompleted, new NetworkDetectorEventArgs(online, net));
IsInstantRequestPresent = false;
}
requestStatus = NetworkTypeRequestStatus.Ended;
Debug.WriteLine("<<<<< GetNetType ended " + System.DateTime.Now.ToString("T") + " <<<<<");
}
#endregion
#region Private Functions
private void EnqueueRequest()
{
requestQueue.Enqueue(System.DateTime.Now.Ticks);
if (!updateTimer.IsEnabled) updateTimer.Start();
}
private void DetectOnlineStatus() //are we connected to any network or not
{
if (Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
if (!online)
{
online = true; //the network just came back
RaiseNotify(OnNetworkON, new NetworkAvailableEventArgs(online));
// do what is needed to GoOnline();
}
}
else
{
if (online)
{
online = false; //we just lost all network connectivity
RaiseNotify(OnNetworkOFF, new NetworkAvailableEventArgs(online));
Debug.WriteLine("----- No network available. -----");
// do what is needed to GoOffline();
}
}
}
void pollTimer_Tick(object sender, EventArgs e)
{
EnqueueRequest();
}
void updateTimer_Tick(object sender, EventArgs e)
{
if (requestQueue.Count > 0)
{
if (!networkWorker.IsBusy)
{
requestStatus = NetworkTypeRequestStatus.Started;
networkWorker.RunWorkerAsync();
}
}
}
#region Event Handling
private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
Debug.WriteLine("+++++ Changed started " + System.DateTime.Now.ToString("T") + " +++++");
DetectOnlineStatus();
if (detailedMode) RaiseNotify(OnNetworkChanged, new NetworkAvailableEventArgs(online));
Debug.WriteLine(" IsOnline : " + online.ToString());
Debug.WriteLine(" Current NetType: " + net.ToString());
Debug.WriteLine("+++++ Changed Ended " + System.DateTime.Now.ToString("T"));
Debug.WriteLine(" Changed GetNetType Launch" + System.DateTime.Now.ToString("T"));
EnqueueRequest();
}
private void SetupNetworkChange()
{
// Get current network availalability and store the
// initial value of the online variable
if (Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
online = true;
// do what is needed to GoOnline();
}
else
{
online = false;
// do what is needed to GoOffline();
}
// Now add a network change event handler to indicate network availability
EnqueueRequest();
System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged += new System.Net.NetworkInformation.NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
}
protected void RaiseNotify(EventHandler<NetworkDetectorEventArgs> handler, NetworkDetectorEventArgs e)
{
if (handler != null)
{
handler(this, e);
}
}
protected void RaiseNotify(EventHandler<NetworkAvailableEventArgs> handler, NetworkAvailableEventArgs e)
{
if (handler != null)
{
handler(this, e);
}
}
#endregion
#endregion
#region Public Functions and Properties
public void AsyncGetNetworkType()
{
//requestQueue.Enqueue(System.DateTime.Now.Ticks);
IsInstantRequestPresent = true;
if (!networkWorker.IsBusy)
{
requestStatus = NetworkTypeRequestStatus.Started;
networkWorker.RunWorkerAsync();
}
if (!updateTimer.IsEnabled) updateTimer.Start();
}
public void SetNetworkPolling(int Minutes, int Seconds, int Milliseconds)
{
pollTimer.Interval = new TimeSpan(0, 0, Minutes, Seconds, Milliseconds);
if (!pollTimer.IsEnabled) pollTimer.Start();
}
public void DisableNetworkPolling()
{
if (pollTimer.IsEnabled) pollTimer.Stop();
}
public Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType GetCurrentNetworkType()
{
return net;
}
public NetworkTypeRequestStatus GetRequestStatus()
{
//NetworkTypeRequestStatus temp = requestStatus;
//if (requestStatus == NetworkTypeRequestStatus.Ended) requestStatus = NetworkTypeRequestStatus.Default;
//return temp;
return requestStatus;
}
public bool DetailedMode
{
get
{
return detailedMode;
}
set
{
detailedMode = value;
}
}
public bool GetZuneStatus()
{
return isZuneConnected;
}
#endregion
}
}