www.pudn.com > TFTPUtil_Class_Version_1.3.0.zip > TFTPState.cs


using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.IO; 
using System.Net; 
using System.Net.Sockets; 
 
namespace TFTPUtil 
{ 
    public class TFTPState 
    { 
        #region VARS 
        private long StartTime = DateTime.Now.Ticks; 
        //A timestamp of when this instance was created 
        public long Timestamp = DateTime.Now.Ticks; 
        private long StopTime; 
        private int ResendInterval = 1; 
        private int Timeout = 10; 
        private int RecvBlkSize = 512; 
        private string RecvFilename; 
        private string LocalAddress; 
        private int LocalPort; 
        private string RemoteAddress; 
        private int RemotePort; 
        private int OrigOpcode; 
        private string Mode = "octet"; 
        private FileStream FS; 
        private BinaryReader BR; 
        private BinaryWriter BW; 
        public long FileLength; 
        private string Path = Directory.GetCurrentDirectory(); 
        private byte[] LastBytes; 
        public bool SentRecvLastBlock = false; 
        public byte BlockIDByte1 = 0; 
        public byte BlockIDByte2 = 0; 
        private FileMode FileWriteMode = FileMode.CreateNew; 
        public bool TimeoutOption = false; 
        public bool TransferSizeOption = false; 
        public bool BlocksizeOption = false; 
        public bool TimeoutOptionACK = false; 
        public bool BlocksizeOptionACK = false; 
        public TFTPTransferState TransferState; 
        private bool ClientMode = false; 
//        public bool ErrorOccurred = false; 
//        public string ErrorMsg = ""; 
        #endregion 
 
        ///  
        /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state 
        ///  
        /// The local IPAddress that the connection was received on 
        /// The local port that the connection was received on 
        /// The remote IPAddress that the connection was originated from 
        /// The remote port that the connection was originated from 
        /// The original opcode received or transmitted 
        /// The original filename that was received or transmitted 
        /// The original received or transmitted mode requested 
        public TFTPState(IPAddress vLocalAddress, 
            int vLocalPort, 
            IPAddress vRemoteAddress, 
            int vRemotePort, 
            int vOpcode, 
            string vFilename, 
            string vMode) 
        { 
            LocalAddress = vLocalAddress.ToString(); 
            LocalPort = vLocalPort; 
            RemotePort = vRemotePort; 
            RemoteAddress = vRemoteAddress.ToString(); 
            OrigOpcode = vOpcode; 
            Regex rgx = new Regex(@"\.\.\\|.*:\\"); 
            RecvFilename = rgx.Replace(vFilename, @"\"); 
            Mode = vMode; 
 
            TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename); 
 
            TransferState.Opened = false; 
        } 
 
        ///  
        /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state 
        ///  
        /// The local IPAddress that the connection was received on 
        /// The local port that the connection was received on 
        /// The remote IPAddress that the connection was originated from 
        /// The remote port that the connection was originated from 
        /// The original opcode received or transmitted 
        /// The original filename that was received or transmitted 
        /// The original received or transmitted mode requested 
        /// The path to use to send and receive files 
        public TFTPState(IPAddress vLocalAddress,  
            int vLocalPort,  
            IPAddress vRemoteAddress,  
            int vRemotePort,  
            int vOpcode,  
            string vFilename,  
            string vMode, 
            string vPath) 
        { 
            LocalAddress = vLocalAddress.ToString(); 
            LocalPort = vLocalPort; 
            RemotePort = vRemotePort; 
            RemoteAddress = vRemoteAddress.ToString(); 
            OrigOpcode = vOpcode; 
            Regex rgx = new Regex(@"\.\.\\|.*:\\"); 
            RecvFilename = rgx.Replace(vFilename, @"\"); 
            Mode = vMode; 
            if (Directory.Exists(vPath)) 
                Path = vPath; 
 
            //long size = 0; 
            //FileInfo info = new FileInfo(Path + "\\" + vFilename); 
            //if (info.Exists) 
            //    size = info.Length; 
 
            TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename); 
 
            //OnTFTPStateTransferEvent(new TFTPStateTransferEventArgs(TransferState)); 
            TransferState.Opened = false; 
        } 
 
        ///  
        /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state 
        ///  
        /// The local IPAddress that the connection was received on 
        /// The local port that the connection was received on 
        /// The remote IPAddress that the connection was originated from 
        /// The remote port that the connection was originated from 
        /// The original opcode received or transmitted 
        /// The original filename that was received or transmitted 
        /// The original received or transmitted mode requested 
        /// The path to use to send and receive files 
        /// If set allows files to overwriten 
        /// The time in seconds before retransmiting a packet we didn't get an ACK for 
        /// The time in seconds before deleting the connection because we didn't get a response back 
        /// If the TFTP server should be in client mode 
        public TFTPState(IPAddress vLocalAddress, 
            int vLocalPort, 
            IPAddress vRemoteAddress, 
            int vRemotePort, 
            int vOpcode, 
            string vFilename, 
            string vMode, 
            string vPath, 
            bool vAllowOverwrite, 
            int vResendTime, 
            int vTimeout, 
            bool vClientMode, 
            int vBlockSize) 
        { 
            LocalAddress = vLocalAddress.ToString(); 
            LocalPort = vLocalPort; 
            RemotePort = vRemotePort; 
            RemoteAddress = vRemoteAddress.ToString(); 
            OrigOpcode = vOpcode; 
            Regex rgx = new Regex(@"\.\.\\|.*:\\"); 
            RecvFilename = rgx.Replace(vFilename, @"\"); 
            Mode = vMode; 
            if (Directory.Exists(vPath)) 
                Path = vPath; 
            if (vAllowOverwrite) 
                FileWriteMode = FileMode.Create; 
            ResendIntervalSeconds = vResendTime; 
            Timeout = vTimeout; 
            ClientMode = vClientMode; 
 
            if (vClientMode && (vOpcode == 2)) 
                BlockIDByte2 = 1; 
 
            if (ClientMode) 
                BlockSize = vBlockSize; 
 
            TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename); 
        } 
 
        ///  
        /// Deconstructor 
        ///  
        ~TFTPState() 
        { 
            TransferState = null; 
        } 
 
        ///  
        /// Closes all the local files used in the TFTP transfer and set the StopTransferTicks 
        ///  
        public void Close() 
        { 
            if (BR != null) 
                BR.Close(); 
            if (BW != null) 
                BW.Close(); 
            if (FS != null) 
                FS.Close(); 
            BW = null; 
            FS = null; 
            BR = null; 
            StopTime = DateTime.Now.Ticks; 
            if (TransferState != null) 
            { 
                TransferState.Closed = true; 
                TransferState.Opened = false; 
            } 
        } 
 
        ///  
        /// Writes the data we received from the remote 
        ///  
        /// A byte array containing the next bytes to write to the file 
        /// The first byte in the block ID we received from the remote 
        /// The second byte in the block ID we received from the remote 
        public void WriteData(byte[] DataBytes, byte RecvBlockIDByte1, byte RecvBlockIDByte2) 
        { 
            if (RecvBlockIDByte2 != BlockIDByte2) 
            { 
                if (FS == null || BW == null) 
                { 
                    FS = new FileStream(Path + "\\" + RecvFilename, FileWriteMode); 
                    BW = new BinaryWriter(FS); 
                    StartTime = DateTime.Now.Ticks; 
                } 
                BW.Write(DataBytes); 
                if (TransferSizeOption == false) 
                    FileLength += DataBytes.Length; 
                TransferState.BytesTransfered += DataBytes.Length; 
                BlockIDByte2 = RecvBlockIDByte2; 
                BlockIDByte1 = RecvBlockIDByte1; 
            } 
 
            this.Timestamp = DateTime.Now.Ticks; 
        } 
 
        ///  
        /// Returns a byte array containing the next section of data for the requested file 
        ///  
        /// The first byte in the block ID we received from the remote 
        /// The second byte in the block ID we received from the remote 
        ///  
        public byte[] GetData(byte RecvBlockIDByte1, byte RecvBlockIDByte2) 
        { 
            byte[] ReturnArray = { }; 
 
            if ((RecvBlockIDByte1 == BlockIDByte1) && (RecvBlockIDByte2 == BlockIDByte2)) 
            { 
                //We got an ACK for the last bock we sent so send next block 
 
                if (BlockIDByte2 == 255) 
                { 
                    ++BlockIDByte1; 
                    BlockIDByte2 = 0; 
                } 
                else 
                { 
                    ++BlockIDByte2; 
                } 
 
                if (FS == null && BR == null) 
                { 
                    FS = new FileStream(Path + "\\" + RecvFilename, FileMode.Open, FileAccess.Read, FileShare.Read); 
                    FileLength = FS.Length; 
                    BR = new BinaryReader(FS); 
                    StartTime = DateTime.Now.Ticks; 
                    TransferState.FileLength = FileLength; 
                    //OnTFTPStateTransferEvent(new TFTPStateTransferEventArgs(TransferState)); 
                } 
 
                if (BR.BaseStream.Position == FileLength) 
                { 
                    SentRecvLastBlock = true; 
                    this.Close(); 
                } 
                else if (BR.BaseStream.Position + BlockSize > FileLength) 
                { 
                    int NewSize = Convert.ToInt32(FileLength - Convert.ToInt32(BR.BaseStream.Position)); 
                    ReturnArray = BR.ReadBytes(NewSize); 
                    TransferState.BytesTransfered += NewSize; 
                    SentRecvLastBlock = true; 
                    Close(); 
                } 
                else 
                { 
                    TransferState.BytesTransfered += BlockSize; 
                    //I don't think we need to convert in windows but I don't have a good way of testing this 
                    //if (Mode == "netascii") 
                    //    ReturnArray = System.Text.Encoding.Convert(Encoding.Unicode, Encoding.ASCII, BR.ReadBytes(BlockSize)); 
                    //else 
                        ReturnArray = BR.ReadBytes(BlockSize); 
                    
                    LastBytes = ReturnArray; 
                } 
            } 
            else 
            { 
                //We didn't get an ACK for the last block we sent to resend it 
                ReturnArray = LastBytes; 
            } 
 
            this.Timestamp = DateTime.Now.Ticks; 
            return ReturnArray; 
        } 
 
        ///  
        /// A string representing the remote IP address of the connection 
        ///  
        public string RemoteIPAddress 
        { 
            get 
            { 
                return RemoteAddress; 
            } 
        } 
 
        ///  
        /// A string representing the local IP address we used for the connection 
        ///  
        public string LocalIPAddress 
        { 
            get 
            { 
                return LocalAddress; 
            } 
        } 
 
        ///  
        /// An integer representing the local port number for the connection 
        ///  
        public int LocalPortNumber 
        { 
            get 
            { 
                return LocalPort; 
            } 
        } 
 
        ///  
        /// An integer representing the port number of the remote connection 
        ///  
        public int RemotePortNumber 
        { 
            get 
            { 
                return RemotePort; 
            } 
            set 
            { 
                if (ClientMode) 
                    RemotePort = value; 
            } 
        } 
 
        ///  
        /// An integer representing the original TFTP opcode we received 
        ///  
        public int OriginalOpcode 
        { 
            get 
            { 
                return OrigOpcode; 
            } 
        } 
 
        ///  
        /// A string representing the filename we received in the TFTP message 
        ///  
        public string Filename 
        { 
            get 
            { 
                return RecvFilename; 
            } 
        } 
 
        ///  
        /// A string representation of the original TFTP command we received 
        ///  
        public string TransferType 
        { 
            get 
            { 
                string ReturnString = "unknown"; 
                switch (OriginalOpcode) 
                { 
                    case (1): 
                        ReturnString = "read"; 
                        break; 
                    case (2): 
                        ReturnString = "write"; 
                        break; 
                    case (3): 
                        ReturnString = "data"; 
                        break; 
                    case (4): 
                        ReturnString = "ACK"; 
                        break; 
                    case (5): 
                        ReturnString = "error"; 
                        break; 
                } 
                return ReturnString; 
            } 
        } 
 
        ///  
        /// A long representing the file size of the requested file 
        ///  
        public long Filesize 
        { 
            get 
            { 
                if (FileLength > 0) 
                { 
                    return FileLength; 
                } 
                else 
                { 
                    FileInfo info = new FileInfo(Path + "\\" + Filename); 
                    if (info.Exists) 
                        return info.Length; 
                    else 
                        return 0; 
                } 
            } 
        } 
 
        ///  
        /// A long that should be from System.DateTime.Now.Ticks when the trasnfer started 
        ///  
        public long StartTransferTicks 
        { 
            get 
            { 
                return StartTime; 
            } 
        } 
 
        ///  
        /// A long that should be from System.DateTime.Now.Ticks when the trasnfer completed 
        ///  
        public long StopTransferTicks 
        { 
            get 
            { 
                return StopTime; 
            } 
        } 
 
        ///  
        /// An integer representing the time in seconds before resending a packet that we got never got a response back on 
        ///  
        public int ResendIntervalSeconds 
        { 
            get 
            { 
                if ((ResendInterval > 0) && TimeoutOptionACK) 
                    //return RecvTimeout * 1000; 
                    return ResendInterval; 
                else 
                    //return 1000; 
                    return 1; 
            } 
            set 
            { 
                if ((value >= 1) || (value <= 255)) 
                    ResendInterval = value; 
            } 
        } 
 
        ///  
        /// An integer representing the time in seconds that we will timeout and delete the state if we didn't get a repsonse 
        ///  
        public int TimeoutSeconds 
        { 
            get 
            { 
                return Timeout; 
            } 
            set 
            { 
                if ((value >= 1) || (value <= 255)) 
                    Timeout = value; 
            } 
        } 
 
        ///  
        /// An integer representing the number of bytes to send in a DATA packet 
        ///  
        public int BlockSize 
        { 
            get 
            { 
                if (BlocksizeOptionACK && (RecvBlkSize >= 8) && (RecvBlkSize <= 65464)) 
                    return RecvBlkSize; 
                else 
                    return 512; 
            } 
            set 
            { 
                if ((value >= 8) && (value <= 65464)) 
                    RecvBlkSize = value; 
            } 
        } 
 
        public bool ErrorOccurred 
        { 
            get 
            { 
                return TransferState.ErrorOccurred; 
            } 
            set 
            { 
                TransferState.ErrorOccurred = value; 
            } 
        } 
 
        public string ErrorMsg 
        { 
 
            get 
            { 
                return TransferState.ErrorMsg; 
            } 
            set 
            { 
                TransferState.ErrorMsg = value; 
            } 
        } 
    } 
}