// Ping.cs created with MonoDevelop
// User: klose at 17:32 04.08.2012
// CVS release: $Id$
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2011  Thomas Klose, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Net;
using System.Threading;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;

namespace Hiperscan.GUI
{
	public class Ping
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
		private struct ICMP_OPTIONS
		{
			public Byte Ttl;
			public Byte Tos;
			public Byte Flags;
			public Byte OptionsSize;
			public IntPtr OptionsData;
		};
		
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
		private struct ICMP_ECHO_REPLY
		{
			public int Address;
			public int Status;
			public int RoundTripTime;
			public Int16 DataSize;
			public Int16 Reserved;
			public IntPtr DataPtr;
			public ICMP_OPTIONS Options;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]
			public String Data;
		}
		
		[DllImport("iphlpapi.dll", SetLastError = true)]
		private static extern IntPtr IcmpCreateFile();
		[DllImport("iphlpapi.dll", SetLastError = true)]
		private static extern bool IcmpCloseHandle(IntPtr handle);
		[DllImport("iphlpapi.dll", SetLastError = true)]
		private static extern Int32 IcmpSendEcho(IntPtr icmpHandle, Int32 destinationAddress, String requestData, Int32 requestSize, ref ICMP_OPTIONS requestOptions, ref ICMP_ECHO_REPLY replyBuffer, Int32 replySize, Int32 timeout);
		
		public static bool Send(string server)
		{
			if (MainClass.OS == MainClass.OSType.Windows)
			{
				IPAddress[] ipa = Dns.GetHostAddresses(server);
				
				ICMP_OPTIONS options = new ICMP_OPTIONS();
				ICMP_ECHO_REPLY echo_reply = new ICMP_ECHO_REPLY();
				
				IntPtr handle = IcmpCreateFile();
				Int32 ip = BitConverter.ToInt32(ipa[0].GetAddressBytes(), 0);
				string data = "x";
				options.Ttl = 255;
				
				Int32 replies = IcmpSendEcho(handle, ip,
				                             data, data.Length, ref options, ref echo_reply,
				                             Marshal.SizeOf(echo_reply), 30);

				IcmpCloseHandle(handle);
				return replies != 0;
			}
			else
			{
				try
				{
					System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
					System.Net.NetworkInformation.PingReply reply = ping.Send(server, 30);
					return (reply.Status == System.Net.NetworkInformation.IPStatus.Success);
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex.ToString());
					return false;
				}
			}
        }
	}
}