[System] Common NetworkInformation code from referencesource
[mono.git] / mcs / class / referencesource / System / net / System / Net / NetworkInformation / PingReply.cs
1 using System.Net.Sockets;
2 using System.Runtime.InteropServices;
3
4 namespace System.Net.NetworkInformation
5 {
6     
7     public class PingReply
8     {
9         IPAddress address;
10         PingOptions options;
11         IPStatus ipStatus;  // the status code returned by icmpsendecho, or the icmp status field on the raw socket
12         long rtt;  // the round trip time.
13         byte[] buffer; //buffer of the data
14
15
16         internal PingReply(){
17         }
18
19         internal PingReply (IPStatus ipStatus) {
20             this.ipStatus = ipStatus;
21             buffer = new byte[0];
22         }
23
24         // The downlevel constructor. 
25         internal PingReply (byte[] data, int dataLength, IPAddress address, int time) {
26             this.address = address;
27             rtt = time;
28
29
30             ipStatus = GetIPStatus ((IcmpV4Type)data[20],(IcmpV4Code) data[21]);
31
32             if (ipStatus == IPStatus.Success) {
33                 buffer = new byte[dataLength - 28];
34                 Array.Copy (data, 28, buffer, 0, dataLength - 28);
35             }
36             else
37                 buffer = new byte[0];
38         }
39
40 #if MONO
41         internal PingReply (IPAddress address, byte [] buffer, PingOptions options, long roundtripTime, IPStatus status)
42         {
43             this.address = address;
44             this.buffer = buffer;
45             this.options = options;
46             this.rtt = roundtripTime;
47             this.ipStatus = status;
48         }
49 #else
50         // the main constructor for the icmpsendecho apis
51         internal PingReply (IcmpEchoReply reply) {
52             address = new IPAddress (reply.address);
53             ipStatus = (IPStatus)reply.status; //the icmpsendecho ip status codes
54
55             //only copy the data if we succeed w/ the ping operation
56             if (ipStatus == IPStatus.Success) {
57                 rtt = (long)reply.roundTripTime;
58                 buffer = new byte[reply.dataSize];
59                 Marshal.Copy (reply.data, buffer, 0, reply.dataSize);
60                 options = new PingOptions (reply.options);
61             }
62             else
63                 buffer = new byte[0];
64
65         }
66
67                 // the main constructor for the icmpsendecho apis
68         internal PingReply (Icmp6EchoReply reply, IntPtr dataPtr, int sendSize) {
69             
70             address = new IPAddress(reply.Address.Address,reply.Address.ScopeID);
71             ipStatus = (IPStatus)reply.Status; //the icmpsendecho ip status codes
72
73             //only copy the data if we succeed w/ the ping operation
74             if (ipStatus == IPStatus.Success) {
75                 rtt = (long)reply.RoundTripTime;
76                 buffer = new byte[sendSize];
77                 Marshal.Copy (IntPtrHelper.Add(dataPtr, 36), buffer, 0, sendSize);
78                 //options = new PingOptions (reply.options);
79             }
80             else
81                 buffer = new byte[0];
82
83         }
84 #endif
85
86  
87         //translates the relevant icmpsendecho codes to a ipstatus code
88         private IPStatus GetIPStatus (IcmpV4Type type, IcmpV4Code code) {
89             switch (type) {
90                 case IcmpV4Type.ICMP4_ECHO_REPLY:
91                     return IPStatus.Success;
92                 case IcmpV4Type.ICMP4_SOURCE_QUENCH:
93                     return IPStatus.SourceQuench;
94                 case IcmpV4Type.ICMP4_PARAM_PROB:
95                     return IPStatus.ParameterProblem;
96                 case IcmpV4Type.ICMP4_TIME_EXCEEDED:
97                    return IPStatus.TtlExpired;
98
99                 case IcmpV4Type.ICMP4_DST_UNREACH:
100                 {
101                     switch (code) {
102                         case  IcmpV4Code.ICMP4_UNREACH_NET:
103                             return IPStatus.DestinationNetworkUnreachable;
104                         case  IcmpV4Code.ICMP4_UNREACH_HOST:
105                             return IPStatus.DestinationHostUnreachable;
106                         case  IcmpV4Code.ICMP4_UNREACH_PROTOCOL:
107                             return IPStatus.DestinationProtocolUnreachable;
108                         case  IcmpV4Code.ICMP4_UNREACH_PORT:
109                             return IPStatus.DestinationPortUnreachable;
110                         case  IcmpV4Code.ICMP4_UNREACH_FRAG_NEEDED:
111                             return IPStatus.PacketTooBig;
112                         default:
113                             return IPStatus.DestinationUnreachable;
114                     }
115                 }
116             }
117             return IPStatus.Unknown;
118         }
119
120         //the basic properties
121         public IPStatus Status { get { return ipStatus; } }
122         public IPAddress Address { get { return address; } }
123         public long RoundtripTime { get { return rtt; } }
124         public PingOptions Options { 
125             get {
126                 return options; 
127             } 
128         }
129         public byte[] Buffer { get { return buffer; } }
130     }
131 }