//
// System.Net.IPEndPoint.cs
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
//
// (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;
public IPEndPoint (IPAddress address, int port)
{
if (address == null)
throw new ArgumentNullException ("address");
Address = address;
Port = port;
}
public IPEndPoint (long iaddr, int port)
{
Address = new IPAddress (iaddr);
Port = port;
}
public IPAddress Address {
get {
return (address);
}
set {
address=value;
}
}
public override AddressFamily AddressFamily {
get {
return address.AddressFamily;
}
}
public int Port {
get {
return port;
}
set {
// LAMESPEC: no mention of sanity checking
// PS: MS controls the range when setting the value
if (value < MinPort || value > MaxPort)
throw new ArgumentOutOfRangeException ("Invalid port");
port = value;
}
}
// bytes 2 and 3 store the port, the rest
// stores the address
public override EndPoint Create (SocketAddress socketAddress)
{
if (socketAddress == null)
throw new ArgumentNullException ("socketAddress");
if (socketAddress.Family != AddressFamily)
throw new ArgumentException ("The IPEndPoint was created using " + AddressFamily +
" AddressFamily but SocketAddress contains " + socketAddress.Family +
" instead, please use the same type.");
SocketAddress sockaddr = socketAddress;
int size =sockaddr.Size;
AddressFamily family = sockaddr.Family;
int port;
IPEndPoint ipe = null;
switch(family)
{
case AddressFamily.InterNetwork:
if (size < 8) {
return(null);
}
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);
break;
#if NET_1_1
case AddressFamily.InterNetworkV6:
if (size < 28) {
return(null);
}
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);
break;
#endif
default:
return null;
}
return(ipe);
}
public override SocketAddress Serialize() {
SocketAddress sockaddr = null;
switch (address.AddressFamily)
{
case AddressFamily.InterNetwork:
// .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;
#if NET_1_1
case AddressFamily.InterNetworkV6:
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);
break;
#endif
}
return(sockaddr);
}
public override string ToString() {
return(address.ToString() + ":" + port);
}
public override bool Equals (Object obj)
{
IPEndPoint p = obj as IPEndPoint;
return p != null &&
p.port == port &&
p.address.Equals (address);
}
public override int GetHashCode ()
{
return address.GetHashCode () + port;
}
}
}
|