a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
213 lines
5.6 KiB
C#
213 lines
5.6 KiB
C#
//
|
|
// 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 address, int port)
|
|
{
|
|
Address = new IPAddress (address);
|
|
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;
|
|
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;
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
return(sockaddr);
|
|
}
|
|
|
|
public override string ToString() {
|
|
return(address.ToString() + ":" + port);
|
|
}
|
|
|
|
public override bool Equals (object comparand)
|
|
{
|
|
IPEndPoint p = comparand as IPEndPoint;
|
|
return p != null &&
|
|
p.port == port &&
|
|
p.address.Equals (address);
|
|
}
|
|
|
|
public override int GetHashCode ()
|
|
{
|
|
return address.GetHashCode () + port;
|
|
}
|
|
}
|
|
}
|