Version
[pithos-ms-client] / trunk / Libraries / ParallelExtensionsExtras / Extensions / EAP / PingExtensions.cs
1 //--------------------------------------------------------------------------
2 // 
3 //  Copyright (c) Microsoft Corporation.  All rights reserved. 
4 // 
5 //  File: PingExtensions.cs
6 //
7 //--------------------------------------------------------------------------
8
9 using System.Threading.Tasks;
10
11 namespace System.Net.NetworkInformation
12 {
13     /// <summary>Extension methods for working with Ping asynchronously.</summary>
14     public static class PingExtensions
15     {
16         /// <summary>
17         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
18         /// </summary>
19         /// <param name="ping">The Ping.</param>
20         /// <param name="address">An IPAddress that identifies the computer that is the destination for the ICMP echo message.</param>
21         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
22         /// <returns>A task that represents the asynchronous operation.</returns>
23         public static Task<PingReply> SendTask(this Ping ping, IPAddress address, object userToken)
24         {
25             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(address, tcs));
26         }
27
28         /// <summary>
29         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
30         /// </summary>
31         /// <param name="ping">The Ping.</param>
32         /// <param name="hostNameOrAddress">
33         /// A String that identifies the computer that is the destination for the ICMP echo message. 
34         /// The value specified for this parameter can be a host name or a string representation of an IP address.
35         /// </param>
36         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
37         /// <returns>A task that represents the asynchronous operation.</returns>
38         public static Task<PingReply> SendTask(this Ping ping, string hostNameOrAddress, object userToken)
39         {
40             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(hostNameOrAddress, tcs));
41         }
42
43         /// <summary>
44         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
45         /// </summary>
46         /// <param name="ping">The Ping.</param>
47         /// <param name="address">An IPAddress that identifies the computer that is the destination for the ICMP echo message.</param>
48         /// <param name="timeout">
49         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
50         /// to wait for the ICMP echo reply message.
51         /// </param>
52         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
53         /// <returns>A task that represents the asynchronous operation.</returns>
54         public static Task<PingReply> SendTask(this Ping ping, IPAddress address, int timeout, object userToken)
55         {
56             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(address, timeout, tcs));
57         }
58
59         /// <summary>
60         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
61         /// </summary>
62         /// <param name="ping">The Ping.</param>
63         /// <param name="hostNameOrAddress">
64         /// A String that identifies the computer that is the destination for the ICMP echo message. 
65         /// The value specified for this parameter can be a host name or a string representation of an IP address.
66         /// </param>
67         /// <param name="timeout">
68         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
69         /// to wait for the ICMP echo reply message.
70         /// </param>
71         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
72         /// <returns>A task that represents the asynchronous operation.</returns>
73         public static Task<PingReply> SendTask(this Ping ping, string hostNameOrAddress, int timeout, object userToken)
74         {
75             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(hostNameOrAddress, timeout, tcs));
76         }
77
78         /// <summary>
79         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
80         /// </summary>
81         /// <param name="ping">The Ping.</param>
82         /// <param name="address">An IPAddress that identifies the computer that is the destination for the ICMP echo message.</param>
83         /// <param name="timeout">
84         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
85         /// to wait for the ICMP echo reply message.
86         /// </param>
87         /// <param name="buffer">
88         /// A Byte array that contains data to be sent with the ICMP echo message and returned 
89         /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
90         /// </param>
91         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
92         /// <returns>A task that represents the asynchronous operation.</returns>
93         public static Task<PingReply> SendTask(this Ping ping, IPAddress address, int timeout, byte[] buffer, object userToken)
94         {
95             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(address, timeout, buffer, tcs));
96         }
97
98         /// <summary>
99         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
100         /// </summary>
101         /// <param name="ping">The Ping.</param>
102         /// <param name="hostNameOrAddress">
103         /// A String that identifies the computer that is the destination for the ICMP echo message. 
104         /// The value specified for this parameter can be a host name or a string representation of an IP address.
105         /// </param>
106         /// <param name="timeout">
107         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
108         /// to wait for the ICMP echo reply message.
109         /// </param>
110         /// <param name="buffer">
111         /// A Byte array that contains data to be sent with the ICMP echo message and returned 
112         /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
113         /// </param>
114         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
115         /// <returns>A task that represents the asynchronous operation.</returns>
116         public static Task<PingReply> SendTask(this Ping ping, string hostNameOrAddress, int timeout, byte[] buffer, object userToken)
117         {
118             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(hostNameOrAddress, timeout, buffer, tcs));
119         }
120
121         /// <summary>
122         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
123         /// </summary>
124         /// <param name="ping">The Ping.</param>
125         /// <param name="address">An IPAddress that identifies the computer that is the destination for the ICMP echo message.</param>
126         /// <param name="timeout">
127         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
128         /// to wait for the ICMP echo reply message.
129         /// </param>
130         /// <param name="buffer">
131         /// A Byte array that contains data to be sent with the ICMP echo message and returned 
132         /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
133         /// </param>
134         /// <param name="options">A PingOptions object used to control fragmentation and Time-to-Live values for the ICMP echo message packet.</param>
135         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
136         /// <returns>A task that represents the asynchronous operation.</returns>
137         public static Task<PingReply> SendTask(this Ping ping, IPAddress address, int timeout, byte[] buffer, PingOptions options, object userToken)
138         {
139             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(address, timeout, buffer, options, tcs));
140         }
141
142         /// <summary>
143         /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
144         /// </summary>
145         /// <param name="ping">The Ping.</param>
146         /// <param name="hostNameOrAddress">
147         /// A String that identifies the computer that is the destination for the ICMP echo message. 
148         /// The value specified for this parameter can be a host name or a string representation of an IP address.
149         /// </param>
150         /// <param name="timeout">
151         /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message) 
152         /// to wait for the ICMP echo reply message.
153         /// </param>
154         /// <param name="buffer">
155         /// A Byte array that contains data to be sent with the ICMP echo message and returned 
156         /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
157         /// </param>
158         /// <param name="options">A PingOptions object used to control fragmentation and Time-to-Live values for the ICMP echo message packet.</param>
159         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
160         /// <returns>A task that represents the asynchronous operation.</returns>
161         public static Task<PingReply> SendTask(this Ping ping, string hostNameOrAddress, int timeout, byte[] buffer, PingOptions options, object userToken)
162         {
163             return SendTaskCore(ping, userToken, tcs => ping.SendAsync(hostNameOrAddress, timeout, buffer, options, tcs));
164         }
165
166         /// <summary>The core implementation of SendTask.</summary>
167         /// <param name="ping">The Ping.</param>
168         /// <param name="userToken">A user-defined object stored in the resulting Task.</param>
169         /// <param name="sendAsync">
170         /// A delegate that initiates the asynchronous send.
171         /// The provided TaskCompletionSource must be passed as the user-supplied state to the actual Ping.SendAsync method.
172         /// </param>
173         /// <returns></returns>
174         private static Task<PingReply> SendTaskCore(Ping ping, object userToken, Action<TaskCompletionSource<PingReply>> sendAsync)
175         {
176             // Validate we're being used with a real smtpClient.  The rest of the arg validation
177             // will happen in the call to sendAsync.
178             if (ping == null) throw new ArgumentNullException("ping");
179
180             // Create a TaskCompletionSource to represent the operation
181             var tcs = new TaskCompletionSource<PingReply>(userToken);
182
183             // Register a handler that will transfer completion results to the TCS Task
184             PingCompletedEventHandler handler = null;
185             handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Reply, () => ping.PingCompleted -= handler);
186             ping.PingCompleted += handler;
187
188             // Try to start the async operation.  If starting it fails (due to parameter validation)
189             // unregister the handler before allowing the exception to propagate.
190             try
191             {
192                 sendAsync(tcs);
193             }
194             catch(Exception exc)
195             {
196                 ping.PingCompleted -= handler;
197                 tcs.TrySetException(exc);
198             }
199
200             // Return the task to represent the asynchronous operation
201             return tcs.Task;
202         }
203     }
204 }