// 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.Security.Principal;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
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.
BackgroundWorker worker;
object user_async_state;
+ CancellationTokenSource cts;
public event PingCompletedEventHandler PingCompleted;
protected void OnPingCompleted (PingCompletedEventArgs e)
{
- if (PingCompleted != null)
- PingCompleted (this, e);
user_async_state = null;
worker = null;
+ cts = null;
+
+ if (PingCompleted != null)
+ PingCompleted (this, e);
}
// Sync
private PingReply SendUnprivileged (IPAddress address, int timeout, byte [] buffer, PingOptions options)
{
- DateTime sentTime = DateTime.Now;
+#if MONO_FEATURE_PROCESS_START
+ DateTime sentTime = DateTime.UtcNow;
Process ping = new Process ();
string args = BuildPingArgs (address, timeout, options);
ping.StartInfo.RedirectStandardOutput = true;
ping.StartInfo.RedirectStandardError = true;
+ IPStatus status = IPStatus.Unknown;
try {
ping.Start ();
string stderr = ping.StandardError.ReadToEnd ();
#pragma warning restore 219
- trip_time = (long) (DateTime.Now - sentTime).TotalMilliseconds;
+ trip_time = (long) (DateTime.UtcNow - sentTime).TotalMilliseconds;
if (!ping.WaitForExit (timeout) || (ping.HasExited && ping.ExitCode == 2))
- return new PingReply (address, buffer, options, trip_time, IPStatus.TimedOut);
-
- if (ping.ExitCode == 1)
- return new PingReply (address, buffer, options, trip_time, IPStatus.TtlExpired);
- } catch (Exception) {
- return new PingReply (address, buffer, options, trip_time, IPStatus.Unknown);
+ status = IPStatus.TimedOut;
+ else if (ping.ExitCode == 0)
+ status = IPStatus.Success;
+ else if (ping.ExitCode == 1)
+ status = IPStatus.TtlExpired;
+ } catch {
} finally {
- if (ping != null) {
- if (!ping.HasExited)
- ping.Kill ();
- ping.Dispose ();
- }
+ if (!ping.HasExited)
+ ping.Kill ();
+ ping.Dispose ();
}
- return new PingReply (address, buffer, options, trip_time, IPStatus.Success);
+ return new PingReply (address, buffer, options, trip_time, status);
+#else
+ throw new NotSupportedException ("Ping is not supported on this platform.");
+#endif // MONO_FEATURE_PROCESS_START
}
// Async
public void SendAsync (IPAddress address, int timeout, byte [] buffer, PingOptions options, object userToken)
{
- if (worker != null)
+ if ((worker != null) || (cts != null))
throw new InvalidOperationException ("Another SendAsync operation is in progress");
worker = new BackgroundWorker ();
public void SendAsyncCancel ()
{
+ if (cts != null) {
+ cts.Cancel ();
+ return;
+ }
+
if (worker == null)
throw new InvalidOperationException ("SendAsync operation is not in progress");
worker.CancelAsync ();
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);
+ bool is_mac = Platform.IsMacOS;
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 ();
}
+ 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
-