jiowchern/Regulus

View on GitHub
Regulus.Network/Package/SocketMessage.cs

Summary

Maintainability
B
4 hrs
Test Coverage
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace Regulus.Network.Package
{
    internal class SocketMessageInternal
    {

        public SocketMessageInternal(int PackageSize)
        {

            RemoteEndPoint = new IPEndPoint(IPAddress.Any, port: 0);
            Package = new byte[PackageSize];
        }
        public EndPoint RemoteEndPoint;
        public byte[] Package;
        public SocketError Error;
    }

    public sealed class SocketMessage
    {
        public const int SeqIndex = 0;
        public const int AckIndex = SeqIndex + 2;
        public const int AckbitsIndex = AckIndex + 2;
        public const int OpIndex = AckbitsIndex + 4;
        public const int PayloadlengthIndex = OpIndex + 1;
        public const int PayloadIndex = PayloadlengthIndex + 2;
        public const int Headsize = PayloadIndex + 2;
        public const int Udppackagesize = ushort.MaxValue;

        private readonly SocketMessageInternal m_Instance;


        public SocketMessage(int I)
        {
            m_Instance = new SocketMessageInternal(I);
        }


        private byte[] _Package { get { return m_Instance.Package; } }

        public EndPoint RemoteEndPoint { get { return m_Instance.RemoteEndPoint; } }

        public byte[] Package { get { return _Package; } }

        public SocketError Error { get { return m_Instance.Error; } }




        public bool CheckPayload()
        {
            ushort len = GetPayloadLength();
            return len == _Package.Length - PayloadIndex;
        }

        public int GetPayloadBufferSize()
        {
            int size = _Package.Length - PayloadIndex;
            if (size > 0)
                return size;
            return 0;
        }

        public bool WritePayload(IList<byte> Source, int Offset, int Count)
        {
            int bufferSize = GetPayloadBufferSize();

            if (Count > ushort.MaxValue)
                return false;
            if (bufferSize < Count)
                return false;
            if (Source.Count - Offset < Count)
                return false;


            for (int i = 0; i < Count; i++)
                _Package[PayloadIndex + i] = Source[Offset + i];

            SetPayloadLength((ushort)Count);

            return true;
        }


        private void SetPayloadLength(ushort Value)
        {
            SetUint16(PayloadlengthIndex, Value);
        }

        public ushort GetPayloadLength()
        {
            return GetUint16(PayloadlengthIndex);
        }

        public bool ReadPayload(IList<byte> Payload, int Offset)
        {

            ushort len = GetPayloadLength();

            if (_Package.Length - PayloadIndex < len)
                return false;
            if (Payload.Count - Offset < len)
                return false;

            for (int i = 0; i < len; ++i)
                Payload[Offset + i] = _Package[PayloadIndex + i];
            return true;
        }

        public void ReadPayload(IList<byte> Payload)
        {
            ushort len = GetPayloadLength();
            for (int i = 0; i < len; ++i)
                Payload.Add(_Package[PayloadIndex + i]);
        }


        public void SetOperation(byte Value)
        {
            SetUint8(OpIndex, checked((byte)Value));
        }
        public byte GetOperation()
        {
            return GetUint8(OpIndex);
        }




        public void SetAckFields(uint Value)
        {
            SetUint32(AckbitsIndex, Value);
        }

        public uint GetAckFields()
        {
            return GetUint32(AckbitsIndex);
        }


        public ushort GetAck()
        {
            return GetUint16(AckIndex);
        }

        public void SetAck(ushort Value)
        {
            SetUint16(AckIndex, Value);
        }


        public void SetSeq(ushort Sn)
        {
            SetUint16(SeqIndex, (ushort)Sn);
        }

        public ushort GetSeq()
        {
            return GetUint16(SeqIndex);
        }

        private void SetUint32(int Begin, uint Value)
        {
            _Package[Begin + 0] = (byte)(Value >> 0);
            _Package[Begin + 1] = (byte)(Value >> 8);
            _Package[Begin + 2] = (byte)(Value >> 16);
            _Package[Begin + 3] = (byte)(Value >> 24);
        }

        private uint GetUint32(int Begin)
        {
            if (_Package.Length - Begin > 4)
                return (uint)((_Package[0 + Begin] << 0) | (_Package[1 + Begin] << 8) | (_Package[2 + Begin] << 16) | (_Package[3 + Begin] << 24));
            throw new Exception("Illegal operation");
        }

        private void SetUint16(int Begin, ushort Value)
        {
            _Package[Begin + 0] = (byte)(Value >> 0);
            _Package[Begin + 1] = (byte)(Value >> 8);
        }

        private ushort GetUint16(int Begin)
        {
            if (_Package.Length - Begin > 2)
                return (ushort)((_Package[Begin + 0] << 0) | (_Package[Begin + 1] << 8));
            throw new Exception("Illegal operation");
        }

        private byte GetUint8(int Index)
        {
            if (_Package.Length - Index > 1)
                return _Package[Index];
            throw new Exception("Illegal operation");
        }

        private void SetUint8(int Begin, byte Value)
        {
            if (_Package.Length - Begin > 1)
                _Package[Begin] = Value;
        }

        public IEnumerable<ushort> GetAcks()
        {
            ushort ack = GetAck();
            uint fields = GetAckFields();
            ushort mark = 1;
            for (ushort i = 0; i < 32; i++)
                if ((mark & fields) != 0)
                    yield return (ushort)(ack + i + 1);
        }

        public static int GetHeadSize()
        {
            return Headsize;
        }

        public int ReadPayload(int SourceOffset, byte[] Buffer, int TargetOffset, int ReadCount)
        {
            ushort payloadLength = GetPayloadLength();
            if (payloadLength < SourceOffset)
                return 0;
            if (Buffer.Length < TargetOffset + ReadCount)
                return 0;


            int count = ReadCount;
            int payloadReadCount = payloadLength - SourceOffset;
            if (payloadReadCount < ReadCount)
                count = payloadReadCount;

            for (int i = 0; i < count; i++)
                Buffer[TargetOffset + i] = _Package[PayloadIndex + i + SourceOffset];

            return count;
        }

        public byte ReadPayload(int Offset)
        {
            return _Package[PayloadIndex + Offset];
        }

        public byte[] GetBuffer()
        {
            return _Package;
        }

        public void SetError(SocketError error)
        {
            m_Instance.Error = error;
        }

        public static int GetPayloadSize()
        {

            return Config.Default.PackageSize - Headsize;
        }

        public bool IsError()
        {
            return m_Instance.Error != SocketError.Success;
        }

        public void SetEndPoint(EndPoint EndPoint)
        {
            m_Instance.RemoteEndPoint = EndPoint;
        }

        public int GetPackageSize()
        {
            return Headsize + GetPayloadLength();
        }

        public void ClearPayload()
        {
            SetPayloadLength(Value: 0);
        }
    }



}