fb0134f31b98805da703a7bc961e89d1ddcb8298
[mono.git] / mcs / class / System / System.Net / IPEndPoint.cs
1 //
2 // System.Net.IPEndPoint.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System.Net.Sockets;
11
12 namespace System.Net {
13         [Serializable]
14         public class IPEndPoint : EndPoint {
15
16                 private IPAddress address;
17                 private int port;
18
19                 public const int MaxPort = 65535;
20                 public const int MinPort = 0;
21                 
22                 public IPEndPoint (IPAddress address, int port)
23                 {
24                         if (address == null)
25                                 throw new ArgumentNullException ("Value cannot be null");
26
27                         Address = address;
28                         Port = port;
29                 }
30                 
31                 public IPEndPoint (long iaddr, int port) : this (new IPAddress (iaddr), port)
32                 {
33                 }
34
35                 public IPAddress Address {
36                         get {
37                                 return (address);
38                         }
39                         set {
40                                 address=value;
41                         }
42                 }
43
44                 public override AddressFamily AddressFamily {
45                         get {
46                                 return address.AddressFamily;
47                         }
48                 }
49
50                 public int Port {
51                         get {
52                                 return port;
53                         }
54                         set {
55                                 // LAMESPEC: no mention of sanity checking
56                                 // PS: MS controls the range when setting the value
57                                 if (value < MinPort || value > MaxPort)
58                                         throw new ArgumentOutOfRangeException ("Invalid port");
59                         
60                                 port = value;
61                         }
62                 }
63
64                 // bytes 2 and 3 store the port, the rest
65                 // stores the address
66                 public override EndPoint Create(SocketAddress sockaddr) {
67                         int size=sockaddr.Size;
68                         
69                         // LAMESPEC: no mention of what to do if
70                         // sockaddr is bogus
71                         if(size<8) {
72                                 // absolute minimum amount needed for
73                                 // an address family, buffer size,
74                                 // port and address
75                                 return(null);
76                         }
77
78                         AddressFamily family=(AddressFamily)sockaddr[0];
79                         int port;
80
81                         IPEndPoint ipe = null;
82                         switch(family)
83                         {\r
84                                 case AddressFamily.InterNetwork:\r
85                                         port = (((int)sockaddr[2])<<8) + (int)sockaddr[3];
86                                         long address=(((long)sockaddr[7])<<24) +
87                                                 (((long)sockaddr[6])<<16) +
88                                                 (((long)sockaddr[5])<<8) +
89                                                 (long)sockaddr[4];
90
91                                         ipe = new IPEndPoint(address, port);\r
92                                         break;\r
93 #if NET_1_1\r
94                                 case AddressFamily.InterNetworkV6:\r
95                                         port    = (((int)sockaddr[2])<<8) + (int)sockaddr[3];
96
97                                         /// maybe flowid ?
98                                         int unknown     = (int)sockaddr[4] +
99                                                 (((int)sockaddr[5])<<8) +
100                                                 (((int)sockaddr[6])<<16) +
101                                                 (((int)sockaddr[7])<<24);
102
103                                         int scopeId     = (int)sockaddr[24] +
104                                                 (((int)sockaddr[25])<<8) +
105                                                 (((int)sockaddr[26])<<16) +
106                                                 (((int)sockaddr[27])<<24);
107
108                                         ushort[] addressData = new ushort[8];
109                                         for(int i=0; i<8; i++)
110                                                 addressData[i] = (ushort)((sockaddr[8+i*2] << 8) + sockaddr[8+i*2+1]);
111
112                                         ipe = new IPEndPoint (new IPAddress(addressData, scopeId), port);\r
113                                         break;\r
114 #endif\r
115                                 default:\r
116                                         return null;\r
117                         }
118
119                         return(ipe);
120                 }
121
122                 public override SocketAddress Serialize() {
123                         SocketAddress sockaddr = null;
124
125                         switch (address.AddressFamily)
126                         {\r
127                                 case AddressFamily.InterNetwork:\r
128                                         // .net produces a 16 byte buffer, even though
129                                         // only 8 bytes are used. I guess its just a
130                                         // holdover from struct sockaddr padding.
131                                         sockaddr = new SocketAddress(AddressFamily.InterNetwork, 16);
132
133                                         // bytes 2 and 3 store the port, the rest
134                                         // stores the address
135                                         sockaddr [2] = (byte) ((port>>8) & 0xff);
136                                         sockaddr [3] = (byte) (port & 0xff);
137
138                                         sockaddr [4] = (byte) (address.Address & 0xff);
139                                         sockaddr [5] = (byte) ((address.Address >> 8) & 0xff);
140                                         sockaddr [6] = (byte) ((address.Address >> 16) & 0xff);
141                                         sockaddr [7] = (byte) ((address.Address >> 24) & 0xff);\r
142                                         break;\r
143 #if NET_1_1\r
144                                 case AddressFamily.InterNetworkV6:\r
145                                         sockaddr = new SocketAddress(AddressFamily.InterNetworkV6, 28);
146
147                                         sockaddr [2] = (byte) ((port>>8) & 0xff);
148                                         sockaddr [3] = (byte) (port & 0xff);
149
150                                         byte[] addressBytes = address.GetAddressBytes();
151                                         for(int i=0; i<16; i++)
152                                                 sockaddr[8+i] = addressBytes[i];
153                                         
154                                         sockaddr [24] = (byte) (address.ScopeId & 0xff);
155                                         sockaddr [25] = (byte) ((address.ScopeId >> 8) & 0xff);
156                                         sockaddr [26] = (byte) ((address.ScopeId >> 16) & 0xff);
157                                         sockaddr [27] = (byte) ((address.ScopeId >> 24) & 0xff);\r
158                                         break;\r
159 #endif\r
160                         }
161
162                         return(sockaddr);
163                 }
164
165                 public override string ToString() {
166                         return(address.ToString() + ":" + port);
167                 }
168
169                 public override bool Equals (Object obj)
170                 {
171                         IPEndPoint p = obj as IPEndPoint;
172                         return p != null && 
173                                p.port == port && 
174                                p.address.Equals (address);
175                 }
176
177                 public override int GetHashCode ()
178                 {
179                         return address.GetHashCode () + port;
180                 }
181         }
182 }