// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0
using System;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Net.Sockets;
using System.Security.Principal;
+using System.Security.Cryptography;
using System.Runtime.InteropServices;
+#if NET_4_5
+using System.Threading;
+using System.Threading.Tasks;
+#endif
namespace System.Net.NetworkInformation {
[MonoTODO ("IPv6 support is missing")]
static readonly string [] PingBinPaths = new string [] {
"/bin/ping",
"/sbin/ping",
- "/usr/sbin/ping"
+ "/usr/sbin/ping",
+#if MONODROID
+ "/system/bin/ping"
+#endif
};
static readonly string PingBinPath;
const int default_timeout = 4000; // 4 sec.
- const int identifier = 1; // no need to be const, but there's no place to change it.
+ ushort identifier;
// This value is correct as of Linux kernel version 2.6.25.9
// See /usr/include/linux/capability.h
BackgroundWorker worker;
object user_async_state;
+#if NET_4_5
+ CancellationTokenSource cts;
+#endif
public event PingCompletedEventHandler PingCompleted;
public Ping ()
{
+ // Generate a new random 16 bit identifier for every ping
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider ();
+ byte [] randomIdentifier = new byte [2];
+ rng.GetBytes (randomIdentifier);
+ identifier = (ushort)(randomIdentifier [0] + (randomIdentifier [1] << 8));
}
[DllImport ("libc", EntryPoint="capget")]
protected void OnPingCompleted (PingCompletedEventArgs e)
{
- if (PingCompleted != null)
- PingCompleted (this, e);
user_async_state = null;
worker = null;
+#if NET_4_5
+ cts = null;
+#endif
+
+ if (PingCompleted != null)
+ PingCompleted (this, e);
}
// Sync
ping.Start ();
#pragma warning disable 219
- // No need to read stdout or stderr as long as the output is less than 4k on linux <= 2.6.11 and 65k after that
- // string stdout = ping.StandardOutput.ReadToEnd ();
- // string stderr = ping.StandardError.ReadToEnd ();
+ string stdout = ping.StandardOutput.ReadToEnd ();
+ string stderr = ping.StandardError.ReadToEnd ();
#pragma warning restore 219
trip_time = (long) (DateTime.Now - sentTime).TotalMilliseconds;
public void SendAsync (IPAddress address, int timeout, byte [] buffer, PingOptions options, object userToken)
{
+#if NET_4_5
+ if ((worker != null) || (cts != null))
+ throw new InvalidOperationException ("Another SendAsync operation is in progress");
+#else
if (worker != null)
throw new InvalidOperationException ("Another SendAsync operation is in progress");
+#endif
worker = new BackgroundWorker ();
worker.DoWork += delegate (object o, DoWorkEventArgs ea) {
public void SendAsyncCancel ()
{
+#if NET_4_5
+ if (cts != null) {
+ cts.Cancel ();
+ return;
+ }
+#endif
+
if (worker == null)
throw new InvalidOperationException ("SendAsync operation is not in progress");
worker.CancelAsync ();
}
// to be sent
- public IcmpMessage (byte type, byte code, short identifier, short sequence, byte [] data)
+ public IcmpMessage (byte type, byte code, ushort identifier, ushort sequence, byte [] data)
{
bytes = new byte [data.Length + 8];
bytes [0] = type;
get { return bytes [1]; }
}
- public byte Identifier {
- get { return (byte) (bytes [4] + (bytes [5] << 8)); }
+ public ushort Identifier {
+ get { return (ushort) (bytes [4] + (bytes [5] << 8)); }
}
- public byte Sequence {
- get { return (byte) (bytes [6] + (bytes [7] << 8)); }
+ public ushort Sequence {
+ get { return (ushort) (bytes [6] + (bytes [7] << 8)); }
}
public byte [] Data {
get {
byte [] data = new byte [bytes.Length - 8];
- Buffer.BlockCopy (bytes, 0, data, 0, data.Length);
+ Buffer.BlockCopy (bytes, 8, data, 0, data.Length);
return data;
}
}
CultureInfo culture = CultureInfo.InvariantCulture;
StringBuilder args = new StringBuilder ();
uint t = Convert.ToUInt32 (Math.Floor ((timeout + 1000) / 1000.0));
-#if NET_2_0
bool is_mac = ((int) Environment.OSVersion.Platform == 6);
if (!is_mac)
-#endif
args.AppendFormat (culture, "-q -n -c {0} -w {1} -t {2} -M ", DefaultCount, t, options.Ttl);
-#if NET_2_0
else
args.AppendFormat (culture, "-q -n -c {0} -t {1} -o -m {2} ", DefaultCount, t, options.Ttl);
if (!is_mac)
-#endif
args.Append (options.DontFragment ? "do " : "dont ");
-#if NET_2_0
else if (options.DontFragment)
args.Append ("-D ");
-#endif
args.Append (address.ToString ());
return args.ToString ();
}
+#if NET_4_5
+ public Task<PingReply> SendPingAsync (IPAddress address, int timeout, byte [] buffer)
+ {
+ return SendPingAsync (address, default_timeout, default_buffer, new PingOptions ());
+ }
+
+ public Task<PingReply> SendPingAsync (IPAddress address, int timeout)
+ {
+ return SendPingAsync (address, default_timeout, default_buffer);
+ }
+
+ public Task<PingReply> SendPingAsync (IPAddress address)
+ {
+ return SendPingAsync (address, default_timeout);
+ }
+
+ public Task<PingReply> SendPingAsync (string hostNameOrAddress, int timeout, byte [] buffer)
+ {
+ return SendPingAsync (hostNameOrAddress, timeout, buffer, new PingOptions ());
+ }
+
+ public Task<PingReply> SendPingAsync (string hostNameOrAddress, int timeout, byte [] buffer, PingOptions options)
+ {
+ IPAddress address = Dns.GetHostEntry (hostNameOrAddress).AddressList [0];
+ return SendPingAsync (address, timeout, buffer, options);
+ }
+
+ public Task<PingReply> SendPingAsync (string hostNameOrAddress, int timeout)
+ {
+ return SendPingAsync (hostNameOrAddress, timeout, default_buffer);
+ }
+
+ public Task<PingReply> SendPingAsync (string hostNameOrAddress)
+ {
+ return SendPingAsync (hostNameOrAddress, default_timeout);
+ }
+
+ public Task<PingReply> SendPingAsync (IPAddress address, int timeout, byte [] buffer, PingOptions options)
+ {
+ if ((worker != null) || (cts != null))
+ throw new InvalidOperationException ("Another SendAsync operation is in progress");
+
+ var task = Task<PingReply>.Factory.StartNew (
+ () => Send (address, timeout, buffer, options), cts.Token);
+
+ task.ContinueWith ((t) => {
+ if (t.IsCanceled)
+ OnPingCompleted (new PingCompletedEventArgs (null, true, null, null));
+ else if (t.IsFaulted)
+ OnPingCompleted (new PingCompletedEventArgs (t.Exception, false, null, null));
+ else
+ OnPingCompleted (new PingCompletedEventArgs (null, false, null, t.Result));
+ });
+
+ return task;
+ }
+#endif
}
}
-#endif