예제 #1
0
        public byte[] GetBytes(ulong lun, byte[] data, int offset, int count, bool isFinalData)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();
            _basicHeader.Immediate = true;
            _basicHeader.OpCode = OpCode.TextRequest;
            _basicHeader.FinalPdu = isFinalData;
            _basicHeader.TotalAhsLength = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag;

            _continue = !isFinalData;
            _lun = lun;
            _commandSequenceNumber = _connection.Session.CommandSequenceNumber;
            _expectedStatusSequenceNumber = _connection.ExpectedStatusSequenceNumber;

            byte[] buffer = new byte[Utilities.RoundUp(48 + count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] |= (byte)(_continue ? 0x40 : 0x00);
            Utilities.WriteBytesBigEndian(lun, buffer, 8);
            Utilities.WriteBytesBigEndian(_targetTransferTag, buffer, 20);
            Utilities.WriteBytesBigEndian(_commandSequenceNumber, buffer, 24);
            Utilities.WriteBytesBigEndian(_expectedStatusSequenceNumber, buffer, 28);
            Array.Copy(data, offset, buffer, 48, count);
            return buffer;
        }
예제 #2
0
        public byte[] GetBytes(byte[] data, int offset, int count, bool isFinalData, int dataSeqNumber,
                               uint bufferOffset, uint targetTransferTag)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();

            _basicHeader.Immediate         = false;
            _basicHeader.OpCode            = OpCode.ScsiDataOut;
            _basicHeader.FinalPdu          = isFinalData;
            _basicHeader.TotalAhsLength    = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag  = _connection.Session.CurrentTaskTag;

            byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = (byte)(isFinalData ? 0x80 : 0x00);
            Utilities.WriteBytesBigEndian(_lun, buffer, 8);
            Utilities.WriteBytesBigEndian(targetTransferTag, buffer, 20);
            Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28);
            Utilities.WriteBytesBigEndian(dataSeqNumber, buffer, 36);
            Utilities.WriteBytesBigEndian(bufferOffset, buffer, 40);

            Array.Copy(data, offset, buffer, 48, count);

            return(buffer);
        }
예제 #3
0
        public byte[] GetBytes(ulong lun, byte[] data, int offset, int count, bool isFinalData)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();

            _basicHeader.Immediate         = true;
            _basicHeader.OpCode            = OpCode.TextRequest;
            _basicHeader.FinalPdu          = isFinalData;
            _basicHeader.TotalAhsLength    = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag  = _connection.Session.CurrentTaskTag;

            _continue = !isFinalData;
            _lun      = lun;
            _commandSequenceNumber        = _connection.Session.CommandSequenceNumber;
            _expectedStatusSequenceNumber = _connection.ExpectedStatusSequenceNumber;

            byte[] buffer = new byte[MathUtilities.RoundUp(48 + count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] |= (byte)(_continue ? 0x40 : 0x00);
            EndianUtilities.WriteBytesBigEndian(lun, buffer, 8);
            EndianUtilities.WriteBytesBigEndian(_targetTransferTag, buffer, 20);
            EndianUtilities.WriteBytesBigEndian(_commandSequenceNumber, buffer, 24);
            EndianUtilities.WriteBytesBigEndian(_expectedStatusSequenceNumber, buffer, 28);
            Array.Copy(data, offset, buffer, 48, count);
            return(buffer);
        }
예제 #4
0
        public byte[] GetBytes(byte[] data, int offset, int count, bool isFinalData)
        {
            _basicHeader = new BasicHeaderSegment();
            _basicHeader.Immediate = true;
            _basicHeader.OpCode = OpCode.LoginRequest;
            _basicHeader.FinalPdu = isFinalData;
            _basicHeader.TotalAhsLength = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag;

            _transit = isFinalData;
            _continue = !isFinalData;
            _currentStage = _connection.CurrentLoginStage;
            if (_transit)
            {
                _nextStage = _connection.NextLoginStage;
            }
            _connectionId = _connection.Id;
            _commandSequenceNumber = _connection.Session.CommandSequenceNumber;
            _expectedStatusSequenceNumber = _connection.ExpectedStatusSequenceNumber;

            byte[] buffer = new byte[Utilities.RoundUp(48 + count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = PackState();
            buffer[2] = 0; // Max Version
            buffer[3] = 0; // Min Version
            Utilities.WriteBytesBigEndian(_connection.Session.InitiatorSessionId, buffer, 8);
            Utilities.WriteBytesBigEndian(IsidQualifier, buffer, 12);
            Utilities.WriteBytesBigEndian(_connection.Session.TargetSessionId, buffer, 14);
            Utilities.WriteBytesBigEndian(_connectionId, buffer, 20);
            Utilities.WriteBytesBigEndian(_commandSequenceNumber, buffer, 24);
            Utilities.WriteBytesBigEndian(_expectedStatusSequenceNumber, buffer, 28);
            Array.Copy(data, offset, buffer, 48, count);
            return buffer;
        }
예제 #5
0
        public void Parse(byte[] headerData, int headerOffset, byte[] bodyData)
        {
            BasicHeaderSegment _headerSegment = new BasicHeaderSegment();

            _headerSegment.ReadFrom(headerData, headerOffset);

            if (_headerSegment.OpCode != OpCode.LoginResponse)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.LoginResponse +
                                                   " was " + _headerSegment.OpCode);
            }

            UnpackState(headerData[headerOffset + 1]);
            MaxVersion                    = headerData[headerOffset + 2];
            ActiveVersion                 = headerData[headerOffset + 3];
            TargetSessionId               = Utilities.ToUInt16BigEndian(headerData, headerOffset + 14);
            StatusPresent                 = true;
            StatusSequenceNumber          = Utilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = Utilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = Utilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            StatusClass                   = headerData[headerOffset + 36];
            StatusCode                    = (LoginStatusCode)Utilities.ToUInt16BigEndian(headerData, headerOffset + 36);

            TextData = bodyData;
        }
예제 #6
0
        public byte[] GetBytes(ScsiCommand cmd, byte[] immediateData, int offset, int count, bool isFinalData, bool willRead, bool willWrite, uint expected)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();

            _basicHeader.Immediate         = cmd.ImmediateDelivery;
            _basicHeader.OpCode            = OpCode.ScsiCommand;
            _basicHeader.FinalPdu          = isFinalData;
            _basicHeader.TotalAhsLength    = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag  = _connection.Session.CurrentTaskTag;

            byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = PackAttrByte(isFinalData, willRead, willWrite, cmd.TaskAttributes);
            Utilities.WriteBytesBigEndian(_lun, buffer, 8);
            Utilities.WriteBytesBigEndian(expected, buffer, 20);
            Utilities.WriteBytesBigEndian(_connection.Session.CommandSequenceNumber, buffer, 24);
            Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28);
            cmd.WriteTo(buffer, 32);

            if (immediateData != null && count != 0)
            {
                Array.Copy(immediateData, offset, buffer, 48, count);
            }

            return(buffer);
        }
예제 #7
0
        public byte[] GetBytes(ScsiCommand cmd, byte[] immediateData, int offset, int count, bool isFinalData, bool willRead, bool willWrite, uint expected)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();
            _basicHeader.Immediate = cmd.ImmediateDelivery;
            _basicHeader.OpCode = OpCode.ScsiCommand;
            _basicHeader.FinalPdu = isFinalData;
            _basicHeader.TotalAhsLength = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag;

            byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = PackAttrByte(isFinalData, willRead, willWrite, cmd.TaskAttributes);
            Utilities.WriteBytesBigEndian(_lun, buffer, 8);
            Utilities.WriteBytesBigEndian(expected, buffer, 20);
            Utilities.WriteBytesBigEndian(_connection.Session.CommandSequenceNumber, buffer, 24);
            Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28);
            cmd.WriteTo(buffer, 32);

            if (immediateData != null && count != 0)
            {
                Array.Copy(immediateData, offset, buffer, 48, count);
            }

            return buffer;
        }
예제 #8
0
        public void Parse(byte[] headerData, int headerOffset, byte[] bodyData)
        {
            Header = new BasicHeaderSegment();
            Header.ReadFrom(headerData, headerOffset);

            if (Header.OpCode != OpCode.ScsiDataIn)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.ScsiDataIn + " was " +
                                                   Header.OpCode);
            }

            UnpackFlags(headerData[headerOffset + 1]);
            if (StatusPresent)
            {
                Status = (ScsiStatus)headerData[headerOffset + 3];
            }

            Lun = EndianUtilities.ToUInt64BigEndian(headerData, headerOffset + 8);
            TargetTransferTag             = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 20);
            StatusSequenceNumber          = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            DataSequenceNumber            = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 36);
            BufferOffset  = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 40);
            ResidualCount = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 44);

            ReadData = bodyData;
        }
예제 #9
0
        public byte[] GetBytes(byte[] data, int offset, int count, bool isFinalData)
        {
            _basicHeader                   = new BasicHeaderSegment();
            _basicHeader.Immediate         = true;
            _basicHeader.OpCode            = OpCode.LoginRequest;
            _basicHeader.FinalPdu          = isFinalData;
            _basicHeader.TotalAhsLength    = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag  = _connection.Session.CurrentTaskTag;

            _transit      = isFinalData;
            _continue     = !isFinalData;
            _currentStage = _connection.CurrentLoginStage;
            if (_transit)
            {
                _nextStage = _connection.NextLoginStage;
            }
            _connectionId                 = _connection.Id;
            _commandSequenceNumber        = _connection.Session.CommandSequenceNumber;
            _expectedStatusSequenceNumber = _connection.ExpectedStatusSequenceNumber;

            byte[] buffer = new byte[Utilities.RoundUp(48 + count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = PackState();
            buffer[2] = 0; // Max Version
            buffer[3] = 0; // Min Version
            Utilities.WriteBytesBigEndian(_connection.Session.InitiatorSessionId, buffer, 8);
            Utilities.WriteBytesBigEndian(IsidQualifier, buffer, 12);
            Utilities.WriteBytesBigEndian(_connection.Session.TargetSessionId, buffer, 14);
            Utilities.WriteBytesBigEndian(_connectionId, buffer, 20);
            Utilities.WriteBytesBigEndian(_commandSequenceNumber, buffer, 24);
            Utilities.WriteBytesBigEndian(_expectedStatusSequenceNumber, buffer, 28);
            Array.Copy(data, offset, buffer, 48, count);
            return(buffer);
        }
예제 #10
0
        public void Parse(byte[] headerData, int headerOffset)
        {
            Header = new BasicHeaderSegment();
            Header.ReadFrom(headerData, headerOffset);

            if (Header.OpCode != OpCode.Reject)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.Reject + " was " +
                                                   Header.OpCode);
            }

            Reason = (RejectReason)headerData[headerOffset + 2];
            StatusSequenceNumber          = Utilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = Utilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = Utilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            DataSequenceNumber            = Utilities.ToUInt32BigEndian(headerData, headerOffset + 36);
        }
예제 #11
0
        public byte[] GetBytes(LogoutReason reason)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();

            _basicHeader.Immediate         = true;
            _basicHeader.OpCode            = OpCode.LogoutRequest;
            _basicHeader.FinalPdu          = true;
            _basicHeader.TotalAhsLength    = 0;
            _basicHeader.DataSegmentLength = 0;
            _basicHeader.InitiatorTaskTag  = _connection.Session.CurrentTaskTag;

            byte[] buffer = new byte[MathUtilities.RoundUp(48, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] |= (byte)((byte)reason & 0x7F);
            EndianUtilities.WriteBytesBigEndian(_connection.Id, buffer, 20);
            EndianUtilities.WriteBytesBigEndian(_connection.Session.CommandSequenceNumber, buffer, 24);
            EndianUtilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28);
            return(buffer);
        }
예제 #12
0
        public void Parse(byte[] headerData, int headerOffset)
        {
            BasicHeaderSegment _headerSegment = new BasicHeaderSegment();

            _headerSegment.ReadFrom(headerData, headerOffset);

            if (_headerSegment.OpCode != OpCode.LogoutResponse)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.LogoutResponse +
                                                   " was " + _headerSegment.OpCode);
            }

            Response                      = (LogoutResponseCode)headerData[headerOffset + 2];
            StatusSequenceNumber          = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            Time2Wait                     = EndianUtilities.ToUInt16BigEndian(headerData, headerOffset + 40);
            Time2Retain                   = EndianUtilities.ToUInt16BigEndian(headerData, headerOffset + 42);
        }
예제 #13
0
        public void Parse(byte[] headerData, int headerOffset, byte[] bodyData)
        {
            BasicHeaderSegment _headerSegment = new BasicHeaderSegment();

            _headerSegment.ReadFrom(headerData, headerOffset);

            if (_headerSegment.OpCode != OpCode.TextResponse)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.TextResponse +
                                                   " was " + _headerSegment.OpCode);
            }

            Continue                      = (headerData[headerOffset + 1] & 0x40) != 0;
            _lun                          = Utilities.ToUInt64BigEndian(headerData, headerOffset + 8);
            _targetTransferTag            = Utilities.ToUInt32BigEndian(headerData, headerOffset + 20);
            StatusSequenceNumber          = Utilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = Utilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = Utilities.ToUInt32BigEndian(headerData, headerOffset + 32);

            TextData = bodyData;
        }
예제 #14
0
        public void Parse(byte[] headerData, int headerOffset)
        {
            Header = new BasicHeaderSegment();
            Header.ReadFrom(headerData, headerOffset);

            if (Header.OpCode != OpCode.ScsiResponse)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.ScsiResponse +
                                                   " was " + Header.OpCode);
            }

            ResponseCode                  = headerData[headerOffset + 2];
            StatusPresent                 = true;
            Status                        = (ScsiStatus)headerData[headerOffset + 3];
            StatusSequenceNumber          = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            ExpectedDataSequenceNumber    = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 36);
            BidiReadResidualCount         = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 40);
            ResidualCount                 = EndianUtilities.ToUInt32BigEndian(headerData, headerOffset + 44);
        }
예제 #15
0
        public static ProtocolDataUnit ReadFrom(Stream stream, bool headerDigestEnabled, bool dataDigestEnabled)
        {
            int numRead = 0;

            byte[] headerData = Utilities.ReadFully(stream, 48);
            numRead += 48;

            byte[] contentData = null;

            if (headerDigestEnabled)
            {
                uint digest = ReadDigest(stream);
                numRead += 4;
            }

            BasicHeaderSegment bhs = new BasicHeaderSegment();

            bhs.ReadFrom(headerData, 0);

            if (bhs.DataSegmentLength > 0)
            {
                contentData = Utilities.ReadFully(stream, bhs.DataSegmentLength);
                numRead    += bhs.DataSegmentLength;

                if (dataDigestEnabled)
                {
                    uint digest = ReadDigest(stream);
                    numRead += 4;
                }
            }

            int rem = 4 - numRead % 4;

            if (rem != 4)
            {
                Utilities.ReadFully(stream, rem);
            }

            return(new ProtocolDataUnit(headerData, contentData));
        }
예제 #16
0
        public void Parse(byte[] headerData, int headerOffset)
        {
            StatusPresent = false;

            Header = new BasicHeaderSegment();
            Header.ReadFrom(headerData, headerOffset);

            if (Header.OpCode != OpCode.ReadyToTransfer)
            {
                throw new InvalidProtocolException("Invalid opcode in response, expected " + OpCode.ReadyToTransfer +
                                                   " was " + Header.OpCode);
            }

            Lun = Utilities.ToUInt64BigEndian(headerData, headerOffset + 8);
            TargetTransferTag             = Utilities.ToUInt32BigEndian(headerData, headerOffset + 20);
            StatusSequenceNumber          = Utilities.ToUInt32BigEndian(headerData, headerOffset + 24);
            ExpectedCommandSequenceNumber = Utilities.ToUInt32BigEndian(headerData, headerOffset + 28);
            MaxCommandSequenceNumber      = Utilities.ToUInt32BigEndian(headerData, headerOffset + 32);
            ReadyToTransferSequenceNumber = Utilities.ToUInt32BigEndian(headerData, headerOffset + 36);
            BufferOffset          = Utilities.ToUInt32BigEndian(headerData, headerOffset + 40);
            DesiredTransferLength = Utilities.ToUInt32BigEndian(headerData, headerOffset + 44);
        }
예제 #17
0
        public static ProtocolDataUnit ReadFrom(Stream stream, bool headerDigestEnabled, bool dataDigestEnabled)
        {
            int numRead = 0;

            byte[] headerData = Utilities.ReadFully(stream, 48);
            numRead += 48;

            byte[] contentData = null;

            if (headerDigestEnabled)
            {
                uint digest = ReadDigest(stream);
                numRead += 4;
            }

            BasicHeaderSegment bhs = new BasicHeaderSegment();
            bhs.ReadFrom(headerData, 0);

            if (bhs.DataSegmentLength > 0)
            {
                contentData = Utilities.ReadFully(stream, bhs.DataSegmentLength);
                numRead += bhs.DataSegmentLength;

                if (dataDigestEnabled)
                {
                    uint digest = ReadDigest(stream);
                    numRead += 4;
                }
            }

            int rem = 4 - (numRead % 4);
            if (rem != 4)
            {
                Utilities.ReadFully(stream, rem);
            }

            return new ProtocolDataUnit(headerData, contentData);
        }
예제 #18
0
        public byte[] GetBytes(byte[] data, int offset, int count, bool isFinalData, int dataSeqNumber, uint bufferOffset, uint targetTransferTag)
        {
            BasicHeaderSegment _basicHeader = new BasicHeaderSegment();
            _basicHeader.Immediate = false;
            _basicHeader.OpCode = OpCode.ScsiDataOut;
            _basicHeader.FinalPdu = isFinalData;
            _basicHeader.TotalAhsLength = 0;
            _basicHeader.DataSegmentLength = count;
            _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag;

            byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)];
            _basicHeader.WriteTo(buffer, 0);
            buffer[1] = (byte)(isFinalData ? 0x80 : 0x00);
            Utilities.WriteBytesBigEndian(_lun, buffer, 8);
            Utilities.WriteBytesBigEndian(targetTransferTag, buffer, 20);
            Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28);
            Utilities.WriteBytesBigEndian(dataSeqNumber, buffer, 36);
            Utilities.WriteBytesBigEndian(bufferOffset, buffer, 40);

            Array.Copy(data, offset, buffer, 48, count);

            return buffer;
        }