171 lines
5.2 KiB
C#
171 lines
5.2 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: HttpException
|
||
|
//
|
||
|
// Note:
|
||
|
// This file was ported, from the Coriolis codebase to Singularity by Mark Aiken.
|
||
|
//
|
||
|
|
||
|
namespace System.Net {
|
||
|
|
||
|
using System;
|
||
|
using System.Net.Sockets;
|
||
|
using System.Text;
|
||
|
using System.Globalization;
|
||
|
|
||
|
// a little perf app measured these times when comparing the internal
|
||
|
// buffer implemented as a managed byte[] or unmanaged memory IntPtr
|
||
|
// that's why we use byte[]
|
||
|
// byte[] total ms:19656
|
||
|
// IntPtr total ms:25671
|
||
|
|
||
|
public class SocketAddress {
|
||
|
|
||
|
internal int m_Size;
|
||
|
internal byte[]! m_Buffer;
|
||
|
|
||
|
private const int WriteableOffset = 2;
|
||
|
private const int MaxSize = 32; // IrDA requires 32 bytes
|
||
|
private bool m_changed = true;
|
||
|
private int m_hash;
|
||
|
|
||
|
public AddressFamily Family {
|
||
|
get {
|
||
|
int family;
|
||
|
#if BIGENDIAN
|
||
|
family = ((int)m_Buffer[0]<<8) | m_Buffer[1];
|
||
|
#else
|
||
|
family = m_Buffer[0] | ((int)m_Buffer[1]<<8);
|
||
|
#endif
|
||
|
return (AddressFamily)family;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Size of this SocketAddress
|
||
|
//
|
||
|
public int Size {
|
||
|
get {
|
||
|
return m_Size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// access to unmanaged serialized data. this doesn't
|
||
|
// allow access to the first 2 bytes of unmanaged memory
|
||
|
// that are supposed to contain the address family which
|
||
|
// is readonly.
|
||
|
//
|
||
|
public byte this[int offset] {
|
||
|
get {
|
||
|
//
|
||
|
// access
|
||
|
//
|
||
|
if (offset<0 || offset>=Size) {
|
||
|
throw new IndexOutOfRangeException();
|
||
|
}
|
||
|
return m_Buffer[offset];
|
||
|
}
|
||
|
set {
|
||
|
if (offset<0 || offset>=Size) {
|
||
|
throw new IndexOutOfRangeException();
|
||
|
}
|
||
|
if (m_Buffer[offset] != value) {
|
||
|
m_changed = true;
|
||
|
}
|
||
|
m_Buffer[offset] = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public SocketAddress(AddressFamily family) : this(family, MaxSize) {
|
||
|
}
|
||
|
|
||
|
public SocketAddress(AddressFamily family, int size) {
|
||
|
if (size<WriteableOffset) {
|
||
|
//
|
||
|
// it doesn't make sense to create a socket address with less than
|
||
|
// 2 bytes, that's where we store the address family.
|
||
|
//
|
||
|
throw new ArgumentOutOfRangeException("size");
|
||
|
}
|
||
|
m_Size = size;
|
||
|
byte[]! buf = m_Buffer = new byte[(size/IntPtr.Size+2)*IntPtr.Size];//sizeof DWORD
|
||
|
|
||
|
#if BIGENDIAN
|
||
|
buf[0] = unchecked((byte)((int)family>>8));
|
||
|
buf[1] = unchecked((byte)((int)family ));
|
||
|
#else
|
||
|
buf[0] = unchecked((byte)((int)family ));
|
||
|
buf[1] = unchecked((byte)((int)family>>8));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Can be called after the above method did work
|
||
|
//
|
||
|
internal int GetAddressSizeOffset()
|
||
|
{
|
||
|
return m_Buffer.Length-IntPtr.Size;
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object comparand) {
|
||
|
SocketAddress castedComparand = comparand as SocketAddress;
|
||
|
if (castedComparand == null || this.Size != castedComparand.Size) {
|
||
|
return false;
|
||
|
}
|
||
|
for(int i=0; i<this.Size; i++) {
|
||
|
if(this[i]!=castedComparand[i]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode() {
|
||
|
if (m_changed) {
|
||
|
m_changed = false;
|
||
|
m_hash = 0;
|
||
|
|
||
|
int i;
|
||
|
int size = Size & ~3;
|
||
|
|
||
|
for (i = 0; i < size; i += 4) {
|
||
|
m_hash ^= (int)m_Buffer[i]
|
||
|
| ((int)m_Buffer[i+1] << 8)
|
||
|
| ((int)m_Buffer[i+2] << 16)
|
||
|
| ((int)m_Buffer[i+3] << 24);
|
||
|
}
|
||
|
if ((Size & 3) != 0) {
|
||
|
|
||
|
int remnant = 0;
|
||
|
int shift = 0;
|
||
|
|
||
|
for (; i < Size; ++i) {
|
||
|
remnant |= ((int)m_Buffer[i]) << shift;
|
||
|
shift += 8;
|
||
|
}
|
||
|
m_hash ^= remnant;
|
||
|
}
|
||
|
}
|
||
|
return m_hash;
|
||
|
}
|
||
|
|
||
|
public override string! ToString() {
|
||
|
StringBuilder bytes = new StringBuilder();
|
||
|
for(int i=WriteableOffset; i<this.Size; i++) {
|
||
|
if (i>WriteableOffset) {
|
||
|
bytes.Append(",");
|
||
|
}
|
||
|
bytes.Append(this[i].ToString());
|
||
|
}
|
||
|
return Family.ToString() + ":" + Size.ToString() + ":{" + bytes.ToString() + "}";
|
||
|
}
|
||
|
|
||
|
} // class SocketAddress
|
||
|
|
||
|
|
||
|
} // namespace System.Net
|