123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Utilities;
- namespace ISCSI
- {
- public class ISCSIPDU
- {
- public const int BasicHeaderSegmentLength = 48;
- public bool ImmediateDelivery;
- public ISCSIOpCodeName OpCode;
- public bool Final;
- public byte[] OpCodeSpecificHeader = new byte[3];
- public byte TotalAHSLength;
- public uint DataSegmentLength;
- public byte[] LUNOrOpCodeSpecific = new byte[8];
- public uint InitiatorTaskTag;
- public byte[] OpCodeSpecific = new byte[28];
- public byte[] Data = new byte[0];
- protected ISCSIPDU()
- {
- }
- protected ISCSIPDU(byte[] buffer, int offset)
- {
- ImmediateDelivery = (buffer[offset + 0] & 0x40) != 0;
- OpCode = (ISCSIOpCodeName)(buffer[offset + 0] & 0x3F);
- Final = (buffer[offset + 1] & 0x80) != 0;
- Array.Copy(buffer, offset + 1, OpCodeSpecificHeader, 0, 3);
- OpCodeSpecificHeader[0] &= 0x7F;
- TotalAHSLength = buffer[offset + 4];
- DataSegmentLength = (uint)(buffer[offset + 5] << 16 | buffer[offset + 6] << 8 | buffer[offset + 7]);
- Array.Copy(buffer, offset + 8, LUNOrOpCodeSpecific, 0, 8);
- InitiatorTaskTag = BigEndianConverter.ToUInt32(buffer, offset + 16);
- Array.Copy(buffer, offset + 20, OpCodeSpecific, 0, 28);
- Data = new byte[DataSegmentLength];
- Array.Copy(buffer, offset + 48, Data, 0, DataSegmentLength);
- }
- virtual public byte[] GetBytes()
- {
- DataSegmentLength = (uint)Data.Length;
-
- byte[] buffer = new byte[this.Length];
- buffer[0x00] = (byte)OpCode;
- if (ImmediateDelivery)
- {
- buffer[0] |= 0x40;
- }
- Array.Copy(OpCodeSpecificHeader, 0, buffer, 1, 3);
- if (Final)
- {
- buffer[1] |= 0x80;
- }
- buffer[4] = TotalAHSLength;
- BigEndianWriter.WriteUInt24(buffer, 5, DataSegmentLength);
- Array.Copy(LUNOrOpCodeSpecific, 0, buffer, 8, 8);
- BigEndianWriter.WriteUInt32(buffer, 16, InitiatorTaskTag);
- Array.Copy(OpCodeSpecific, 0, buffer, 20, 28);
- Array.Copy(Data, 0, buffer, 48, DataSegmentLength);
- return buffer;
- }
- public int Length
- {
- get
- {
- int length = (int)(BasicHeaderSegmentLength + TotalAHSLength + DataSegmentLength);
- length = (int)Math.Ceiling((double)length / 4) * 4;
- return length;
- }
- }
- public static ISCSIPDU GetPDU(byte[] buffer, int offset)
- {
- byte opCode = (byte)(buffer[offset + 0x00] & 0x3F);
- switch ((ISCSIOpCodeName)opCode)
- {
- case ISCSIOpCodeName.NOPOut:
- return new NOPOutPDU(buffer, offset);
- case ISCSIOpCodeName.SCSICommand:
- return new SCSICommandPDU(buffer, offset);
- case ISCSIOpCodeName.LoginRequest:
- return new LoginRequestPDU(buffer, offset);
- case ISCSIOpCodeName.TextRequest:
- return new TextRequestPDU(buffer, offset);
- case ISCSIOpCodeName.SCSIDataOut:
- return new SCSIDataOutPDU(buffer, offset);
- case ISCSIOpCodeName.LogoutRequest:
- return new LogoutRequestPDU(buffer, offset);
- case ISCSIOpCodeName.NOPIn:
- return new NOPInPDU(buffer, offset);
- case ISCSIOpCodeName.SCSIResponse:
- return new SCSIResponsePDU(buffer, offset);
- case ISCSIOpCodeName.LoginResponse:
- return new LoginResponsePDU(buffer, offset);
- case ISCSIOpCodeName.TextResponse:
- return new TextResponsePDU(buffer, offset);
- case ISCSIOpCodeName.SCSIDataIn:
- return new SCSIDataInPDU(buffer, offset);
- case ISCSIOpCodeName.LogoutResponse:
- return new LogoutResponsePDU(buffer, offset);
- case ISCSIOpCodeName.ReadyToTransfer:
- return new ReadyToTransferPDU(buffer, offset);
- default:
- return new ISCSIPDU(buffer, offset);
- }
- }
- public static int GetPDULength(byte[] buffer)
- {
- return GetPDULength(buffer, 0);
- }
- public static int GetPDULength(byte[] buffer, int offset)
- {
- byte totalAHSLength = buffer[offset + 4];
- int dataSegmentLength = buffer[offset + 5] << 16 | buffer[offset + 6] << 8 | buffer[offset + 7];
- int length = BasicHeaderSegmentLength + totalAHSLength + dataSegmentLength;
- length = (int)Math.Ceiling((double)length / 4) * 4;
- return length;
- }
- }
- }
|