svn path=/branches/mono-1-1-9/mcs/; revision=51206
[mono.git] / mcs / class / System / System.Net / IPEndPoint.cs
old mode 100755 (executable)
new mode 100644 (file)
index 6536652..2e81c62
@@ -7,12 +7,36 @@
 // (C) Ximian, Inc.  http://www.ximian.com
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System.Net.Sockets;
 
 namespace System.Net {
        [Serializable]
        public class IPEndPoint : EndPoint {
 
+               private IPAddress address;
+               private int port;
+
                public const int MaxPort = 65535;
                public const int MinPort = 0;
                
@@ -29,10 +53,9 @@ namespace System.Net {
                {
                }
 
-               private IPAddress address;
                public IPAddress Address {
                        get {
-                               return(address);
+                               return (address);
                        }
                        set {
                                address=value;
@@ -41,11 +64,10 @@ namespace System.Net {
 
                public override AddressFamily AddressFamily {
                        get {
-                               return AddressFamily.InterNetwork;
+                               return address.AddressFamily;
                        }
                }
 
-               private int port;
                public int Port {
                        get {
                                return port;
@@ -73,38 +95,93 @@ namespace System.Net {
                                // port and address
                                return(null);
                        }
+
                        AddressFamily family=(AddressFamily)sockaddr[0];
-                       if(family!=AddressFamily.InterNetwork) {
-                               return(null);
+                       int port;
+
+                       IPEndPoint ipe = null;
+                       switch(family)
+                       {\r
+                               case AddressFamily.InterNetwork:\r
+                                       port = (((int)sockaddr[2])<<8) + (int)sockaddr[3];
+                                       long address=(((long)sockaddr[7])<<24) +
+                                               (((long)sockaddr[6])<<16) +
+                                               (((long)sockaddr[5])<<8) +
+                                               (long)sockaddr[4];
+
+                                       ipe = new IPEndPoint(address, port);\r
+                                       break;\r
+#if NET_1_1\r
+                               case AddressFamily.InterNetworkV6:\r
+                                       port    = (((int)sockaddr[2])<<8) + (int)sockaddr[3];
+
+                                       /// maybe flowid ?
+                                       /*
+                                       int unknown     = (int)sockaddr[4] +
+                                               (((int)sockaddr[5])<<8) +
+                                               (((int)sockaddr[6])<<16) +
+                                               (((int)sockaddr[7])<<24);
+                                       */
+
+                                       int scopeId     = (int)sockaddr[24] +
+                                               (((int)sockaddr[25])<<8) +
+                                               (((int)sockaddr[26])<<16) +
+                                               (((int)sockaddr[27])<<24);
+
+                                       ushort[] addressData = new ushort[8];
+                                       for(int i=0; i<8; i++)
+                                               addressData[i] = (ushort)((sockaddr[8+i*2] << 8) + sockaddr[8+i*2+1]);
+
+                                       ipe = new IPEndPoint (new IPAddress(addressData, scopeId), port);\r
+                                       break;\r
+#endif\r
+                               default:\r
+                                       return null;\r
                        }
-                       
-                       int port=(((int)sockaddr[2])<<8) + (int)sockaddr[3];
-                       long address=(((long)sockaddr[4])<<24) +
-                               (((long)sockaddr[5])<<16) +
-                               (((long)sockaddr[6])<<8) +
-                               (long)sockaddr[7];
 
-                       IPEndPoint ipe = new IPEndPoint(address, port);
-                       
                        return(ipe);
                }
 
                public override SocketAddress Serialize() {
-                       // .net produces a 16 byte buffer, even though
-                       // only 8 bytes are used. I guess its just a
-                       // holdover from struct sockaddr padding.
-                       SocketAddress sockaddr = new SocketAddress(AddressFamily.InterNetwork, 16);
-
-                       // bytes 2 and 3 store the port, the rest
-                       // stores the address
-                       sockaddr[2]=(byte)((port>>8) & 0xff);
-                       sockaddr[3]=(byte)(port & 0xff);
-
-                       sockaddr[4]=(byte)((address.Address >> 24) & 0xff);
-                       sockaddr[5]=(byte)((address.Address >> 16) & 0xff);
-                       sockaddr[6]=(byte)((address.Address >> 8) & 0xff);
-                       sockaddr[7]=(byte)(address.Address & 0xff);
-                       
+                       SocketAddress sockaddr = null;
+
+                       switch (address.AddressFamily)
+                       {\r
+                               case AddressFamily.InterNetwork:\r
+                                       // .net produces a 16 byte buffer, even though
+                                       // only 8 bytes are used. I guess its just a
+                                       // holdover from struct sockaddr padding.
+                                       sockaddr = new SocketAddress(AddressFamily.InterNetwork, 16);
+
+                                       // bytes 2 and 3 store the port, the rest
+                                       // stores the address
+                                       sockaddr [2] = (byte) ((port>>8) & 0xff);
+                                       sockaddr [3] = (byte) (port & 0xff);
+                                       long addr = address.InternalIPv4Address;
+                                       sockaddr [4] = (byte) (addr & 0xff);
+                                       sockaddr [5] = (byte) ((addr >> 8) & 0xff);
+                                       sockaddr [6] = (byte) ((addr >> 16) & 0xff);
+                                       sockaddr [7] = (byte) ((addr >> 24) & 0xff);
+                                       break;\r
+#if NET_1_1\r
+                               case AddressFamily.InterNetworkV6:\r
+                                       sockaddr = new SocketAddress(AddressFamily.InterNetworkV6, 28);
+
+                                       sockaddr [2] = (byte) ((port>>8) & 0xff);
+                                       sockaddr [3] = (byte) (port & 0xff);
+
+                                       byte[] addressBytes = address.GetAddressBytes();
+                                       for(int i=0; i<16; i++)
+                                               sockaddr[8+i] = addressBytes[i];
+                                       
+                                       sockaddr [24] = (byte) (address.ScopeId & 0xff);
+                                       sockaddr [25] = (byte) ((address.ScopeId >> 8) & 0xff);
+                                       sockaddr [26] = (byte) ((address.ScopeId >> 16) & 0xff);
+                                       sockaddr [27] = (byte) ((address.ScopeId >> 24) & 0xff);\r
+                                       break;\r
+#endif\r
+                       }
+
                        return(sockaddr);
                }
 
@@ -114,12 +191,10 @@ namespace System.Net {
 
                public override bool Equals (Object obj)
                {
-                       if (obj is System.Net.IPEndPoint) {
-                               return ( ((IPEndPoint) obj).port == port &&
-                                        ((IPEndPoint) obj).address == address);
-                       }
-
-                       return false;
+                       IPEndPoint p = obj as IPEndPoint;
+                       return p != null && 
+                              p.port == port && 
+                              p.address.Equals (address);
                }
 
                public override int GetHashCode ()