TFTPState.cs
Upload User: hhy9292
Upload Date: 2014-10-04
Package Size: 37k
Code Size: 19k
Category:

Ftp Client

Development Platform:

Visual C++

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. using System.IO;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. namespace TFTPUtil
  9. {
  10.     public class TFTPState
  11.     {
  12.         #region VARS
  13.         private long StartTime = DateTime.Now.Ticks;
  14.         //A timestamp of when this instance was created
  15.         public long Timestamp = DateTime.Now.Ticks;
  16.         private long StopTime;
  17.         private int ResendInterval = 1;
  18.         private int Timeout = 10;
  19.         private int RecvBlkSize = 512;
  20.         private string RecvFilename;
  21.         private string LocalAddress;
  22.         private int LocalPort;
  23.         private string RemoteAddress;
  24.         private int RemotePort;
  25.         private int OrigOpcode;
  26.         private string Mode = "octet";
  27.         private FileStream FS;
  28.         private BinaryReader BR;
  29.         private BinaryWriter BW;
  30.         public long FileLength;
  31.         private string Path = Directory.GetCurrentDirectory();
  32.         private byte[] LastBytes;
  33.         public bool SentRecvLastBlock = false;
  34.         public byte BlockIDByte1 = 0;
  35.         public byte BlockIDByte2 = 0;
  36.         private FileMode FileWriteMode = FileMode.CreateNew;
  37.         public bool TimeoutOption = false;
  38.         public bool TransferSizeOption = false;
  39.         public bool BlocksizeOption = false;
  40.         public bool TimeoutOptionACK = false;
  41.         public bool BlocksizeOptionACK = false;
  42.         public TFTPTransferState TransferState;
  43.         private bool ClientMode = false;
  44. //        public bool ErrorOccurred = false;
  45. //        public string ErrorMsg = "";
  46.         #endregion
  47.         /// <summary>
  48.         /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state
  49.         /// </summary>
  50.         /// <param name="vLocalAddress">The local IPAddress that the connection was received on</param>
  51.         /// <param name="vLocalPort">The local port that the connection was received on</param>
  52.         /// <param name="vRemoteAddress">The remote IPAddress that the connection was originated from</param>
  53.         /// <param name="vRemotePort">The remote port that the connection was originated from</param>
  54.         /// <param name="vOpcode">The original opcode received or transmitted</param>
  55.         /// <param name="vFilename">The original filename that was received or transmitted</param>
  56.         /// <param name="vMode">The original received or transmitted mode requested</param>
  57.         public TFTPState(IPAddress vLocalAddress,
  58.             int vLocalPort,
  59.             IPAddress vRemoteAddress,
  60.             int vRemotePort,
  61.             int vOpcode,
  62.             string vFilename,
  63.             string vMode)
  64.         {
  65.             LocalAddress = vLocalAddress.ToString();
  66.             LocalPort = vLocalPort;
  67.             RemotePort = vRemotePort;
  68.             RemoteAddress = vRemoteAddress.ToString();
  69.             OrigOpcode = vOpcode;
  70.             Regex rgx = new Regex(@"..\|.*:\");
  71.             RecvFilename = rgx.Replace(vFilename, @"");
  72.             Mode = vMode;
  73.             TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename);
  74.             TransferState.Opened = false;
  75.         }
  76.         /// <summary>
  77.         /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state
  78.         /// </summary>
  79.         /// <param name="vLocalAddress">The local IPAddress that the connection was received on</param>
  80.         /// <param name="vLocalPort">The local port that the connection was received on</param>
  81.         /// <param name="vRemoteAddress">The remote IPAddress that the connection was originated from</param>
  82.         /// <param name="vRemotePort">The remote port that the connection was originated from</param>
  83.         /// <param name="vOpcode">The original opcode received or transmitted</param>
  84.         /// <param name="vFilename">The original filename that was received or transmitted</param>
  85.         /// <param name="vMode">The original received or transmitted mode requested</param>
  86.         /// <param name="vPath">The path to use to send and receive files</param>
  87.         public TFTPState(IPAddress vLocalAddress, 
  88.             int vLocalPort, 
  89.             IPAddress vRemoteAddress, 
  90.             int vRemotePort, 
  91.             int vOpcode, 
  92.             string vFilename, 
  93.             string vMode,
  94.             string vPath)
  95.         {
  96.             LocalAddress = vLocalAddress.ToString();
  97.             LocalPort = vLocalPort;
  98.             RemotePort = vRemotePort;
  99.             RemoteAddress = vRemoteAddress.ToString();
  100.             OrigOpcode = vOpcode;
  101.             Regex rgx = new Regex(@"..\|.*:\");
  102.             RecvFilename = rgx.Replace(vFilename, @"");
  103.             Mode = vMode;
  104.             if (Directory.Exists(vPath))
  105.                 Path = vPath;
  106.             //long size = 0;
  107.             //FileInfo info = new FileInfo(Path + "\" + vFilename);
  108.             //if (info.Exists)
  109.             //    size = info.Length;
  110.             TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename);
  111.             //OnTFTPStateTransferEvent(new TFTPStateTransferEventArgs(TransferState));
  112.             TransferState.Opened = false;
  113.         }
  114.         /// <summary>
  115.         /// Creates a new instance of the TFTPState class that keeps track of a TFTPServer state
  116.         /// </summary>
  117.         /// <param name="vLocalAddress">The local IPAddress that the connection was received on</param>
  118.         /// <param name="vLocalPort">The local port that the connection was received on</param>
  119.         /// <param name="vRemoteAddress">The remote IPAddress that the connection was originated from</param>
  120.         /// <param name="vRemotePort">The remote port that the connection was originated from</param>
  121.         /// <param name="vOpcode">The original opcode received or transmitted</param>
  122.         /// <param name="vFilename">The original filename that was received or transmitted</param>
  123.         /// <param name="vMode">The original received or transmitted mode requested</param>
  124.         /// <param name="vPath">The path to use to send and receive files</param>
  125.         /// <param name="vAllowOverwrite">If set allows files to overwriten</param>
  126.         /// <param name="vResendTime">The time in seconds before retransmiting a packet we didn't get an ACK for</param>
  127.         /// <param name="vTimeout">The time in seconds before deleting the connection because we didn't get a response back</param>
  128.         /// <param name="vClientMode">If the TFTP server should be in client mode</param>
  129.         public TFTPState(IPAddress vLocalAddress,
  130.             int vLocalPort,
  131.             IPAddress vRemoteAddress,
  132.             int vRemotePort,
  133.             int vOpcode,
  134.             string vFilename,
  135.             string vMode,
  136.             string vPath,
  137.             bool vAllowOverwrite,
  138.             int vResendTime,
  139.             int vTimeout,
  140.             bool vClientMode,
  141.             int vBlockSize)
  142.         {
  143.             LocalAddress = vLocalAddress.ToString();
  144.             LocalPort = vLocalPort;
  145.             RemotePort = vRemotePort;
  146.             RemoteAddress = vRemoteAddress.ToString();
  147.             OrigOpcode = vOpcode;
  148.             Regex rgx = new Regex(@"..\|.*:\");
  149.             RecvFilename = rgx.Replace(vFilename, @"");
  150.             Mode = vMode;
  151.             if (Directory.Exists(vPath))
  152.                 Path = vPath;
  153.             if (vAllowOverwrite)
  154.                 FileWriteMode = FileMode.Create;
  155.             ResendIntervalSeconds = vResendTime;
  156.             Timeout = vTimeout;
  157.             ClientMode = vClientMode;
  158.             if (vClientMode && (vOpcode == 2))
  159.                 BlockIDByte2 = 1;
  160.             if (ClientMode)
  161.                 BlockSize = vBlockSize;
  162.             TransferState = new TFTPTransferState(vOpcode, RemoteAddress, RemotePort, vFilename);
  163.         }
  164.         /// <summary>
  165.         /// Deconstructor
  166.         /// </summary>
  167.         ~TFTPState()
  168.         {
  169.             TransferState = null;
  170.         }
  171.         /// <summary>
  172.         /// Closes all the local files used in the TFTP transfer and set the StopTransferTicks
  173.         /// </summary>
  174.         public void Close()
  175.         {
  176.             if (BR != null)
  177.                 BR.Close();
  178.             if (BW != null)
  179.                 BW.Close();
  180.             if (FS != null)
  181.                 FS.Close();
  182.             BW = null;
  183.             FS = null;
  184.             BR = null;
  185.             StopTime = DateTime.Now.Ticks;
  186.             if (TransferState != null)
  187.             {
  188.                 TransferState.Closed = true;
  189.                 TransferState.Opened = false;
  190.             }
  191.         }
  192.         /// <summary>
  193.         /// Writes the data we received from the remote
  194.         /// </summary>
  195.         /// <param name="DataBytes">A byte array containing the next bytes to write to the file</param>
  196.         /// <param name="RecvBlockIDByte1">The first byte in the block ID we received from the remote</param>
  197.         /// <param name="RecvBlockIDByte2">The second byte in the block ID we received from the remote</param>
  198.         public void WriteData(byte[] DataBytes, byte RecvBlockIDByte1, byte RecvBlockIDByte2)
  199.         {
  200.             if (RecvBlockIDByte2 != BlockIDByte2)
  201.             {
  202.                 if (FS == null || BW == null)
  203.                 {
  204.                     FS = new FileStream(Path + "\" + RecvFilename, FileWriteMode);
  205.                     BW = new BinaryWriter(FS);
  206.                     StartTime = DateTime.Now.Ticks;
  207.                 }
  208.                 BW.Write(DataBytes);
  209.                 if (TransferSizeOption == false)
  210.                     FileLength += DataBytes.Length;
  211.                 TransferState.BytesTransfered += DataBytes.Length;
  212.                 BlockIDByte2 = RecvBlockIDByte2;
  213.                 BlockIDByte1 = RecvBlockIDByte1;
  214.             }
  215.             this.Timestamp = DateTime.Now.Ticks;
  216.         }
  217.         /// <summary>
  218.         /// Returns a byte array containing the next section of data for the requested file
  219.         /// </summary>
  220.         /// <param name="RecvBlockIDByte1">The first byte in the block ID we received from the remote</param>
  221.         /// <param name="RecvBlockIDByte2">The second byte in the block ID we received from the remote</param>
  222.         /// <returns></returns>
  223.         public byte[] GetData(byte RecvBlockIDByte1, byte RecvBlockIDByte2)
  224.         {
  225.             byte[] ReturnArray = { };
  226.             if ((RecvBlockIDByte1 == BlockIDByte1) && (RecvBlockIDByte2 == BlockIDByte2))
  227.             {
  228.                 //We got an ACK for the last bock we sent so send next block
  229.                 if (BlockIDByte2 == 255)
  230.                 {
  231.                     ++BlockIDByte1;
  232.                     BlockIDByte2 = 0;
  233.                 }
  234.                 else
  235.                 {
  236.                     ++BlockIDByte2;
  237.                 }
  238.                 if (FS == null && BR == null)
  239.                 {
  240.                     FS = new FileStream(Path + "\" + RecvFilename, FileMode.Open, FileAccess.Read, FileShare.Read);
  241.                     FileLength = FS.Length;
  242.                     BR = new BinaryReader(FS);
  243.                     StartTime = DateTime.Now.Ticks;
  244.                     TransferState.FileLength = FileLength;
  245.                     //OnTFTPStateTransferEvent(new TFTPStateTransferEventArgs(TransferState));
  246.                 }
  247.                 if (BR.BaseStream.Position == FileLength)
  248.                 {
  249.                     SentRecvLastBlock = true;
  250.                     this.Close();
  251.                 }
  252.                 else if (BR.BaseStream.Position + BlockSize > FileLength)
  253.                 {
  254.                     int NewSize = Convert.ToInt32(FileLength - Convert.ToInt32(BR.BaseStream.Position));
  255.                     ReturnArray = BR.ReadBytes(NewSize);
  256.                     TransferState.BytesTransfered += NewSize;
  257.                     SentRecvLastBlock = true;
  258.                     Close();
  259.                 }
  260.                 else
  261.                 {
  262.                     TransferState.BytesTransfered += BlockSize;
  263.                     //I don't think we need to convert in windows but I don't have a good way of testing this
  264.                     //if (Mode == "netascii")
  265.                     //    ReturnArray = System.Text.Encoding.Convert(Encoding.Unicode, Encoding.ASCII, BR.ReadBytes(BlockSize));
  266.                     //else
  267.                         ReturnArray = BR.ReadBytes(BlockSize);
  268.                    
  269.                     LastBytes = ReturnArray;
  270.                 }
  271.             }
  272.             else
  273.             {
  274.                 //We didn't get an ACK for the last block we sent to resend it
  275.                 ReturnArray = LastBytes;
  276.             }
  277.             this.Timestamp = DateTime.Now.Ticks;
  278.             return ReturnArray;
  279.         }
  280.         /// <summary>
  281.         /// A string representing the remote IP address of the connection
  282.         /// </summary>
  283.         public string RemoteIPAddress
  284.         {
  285.             get
  286.             {
  287.                 return RemoteAddress;
  288.             }
  289.         }
  290.         /// <summary>
  291.         /// A string representing the local IP address we used for the connection
  292.         /// </summary>
  293.         public string LocalIPAddress
  294.         {
  295.             get
  296.             {
  297.                 return LocalAddress;
  298.             }
  299.         }
  300.         /// <summary>
  301.         /// An integer representing the local port number for the connection
  302.         /// </summary>
  303.         public int LocalPortNumber
  304.         {
  305.             get
  306.             {
  307.                 return LocalPort;
  308.             }
  309.         }
  310.         /// <summary>
  311.         /// An integer representing the port number of the remote connection
  312.         /// </summary>
  313.         public int RemotePortNumber
  314.         {
  315.             get
  316.             {
  317.                 return RemotePort;
  318.             }
  319.             set
  320.             {
  321.                 if (ClientMode)
  322.                     RemotePort = value;
  323.             }
  324.         }
  325.         /// <summary>
  326.         /// An integer representing the original TFTP opcode we received
  327.         /// </summary>
  328.         public int OriginalOpcode
  329.         {
  330.             get
  331.             {
  332.                 return OrigOpcode;
  333.             }
  334.         }
  335.         /// <summary>
  336.         /// A string representing the filename we received in the TFTP message
  337.         /// </summary>
  338.         public string Filename
  339.         {
  340.             get
  341.             {
  342.                 return RecvFilename;
  343.             }
  344.         }
  345.         /// <summary>
  346.         /// A string representation of the original TFTP command we received
  347.         /// </summary>
  348.         public string TransferType
  349.         {
  350.             get
  351.             {
  352.                 string ReturnString = "unknown";
  353.                 switch (OriginalOpcode)
  354.                 {
  355.                     case (1):
  356.                         ReturnString = "read";
  357.                         break;
  358.                     case (2):
  359.                         ReturnString = "write";
  360.                         break;
  361.                     case (3):
  362.                         ReturnString = "data";
  363.                         break;
  364.                     case (4):
  365.                         ReturnString = "ACK";
  366.                         break;
  367.                     case (5):
  368.                         ReturnString = "error";
  369.                         break;
  370.                 }
  371.                 return ReturnString;
  372.             }
  373.         }
  374.         /// <summary>
  375.         /// A long representing the file size of the requested file
  376.         /// </summary>
  377.         public long Filesize
  378.         {
  379.             get
  380.             {
  381.                 if (FileLength > 0)
  382.                 {
  383.                     return FileLength;
  384.                 }
  385.                 else
  386.                 {
  387.                     FileInfo info = new FileInfo(Path + "\" + Filename);
  388.                     if (info.Exists)
  389.                         return info.Length;
  390.                     else
  391.                         return 0;
  392.                 }
  393.             }
  394.         }
  395.         /// <summary>
  396.         /// A long that should be from System.DateTime.Now.Ticks when the trasnfer started
  397.         /// </summary>
  398.         public long StartTransferTicks
  399.         {
  400.             get
  401.             {
  402.                 return StartTime;
  403.             }
  404.         }
  405.         /// <summary>
  406.         /// A long that should be from System.DateTime.Now.Ticks when the trasnfer completed
  407.         /// </summary>
  408.         public long StopTransferTicks
  409.         {
  410.             get
  411.             {
  412.                 return StopTime;
  413.             }
  414.         }
  415.         /// <summary>
  416.         /// An integer representing the time in seconds before resending a packet that we got never got a response back on
  417.         /// </summary>
  418.         public int ResendIntervalSeconds
  419.         {
  420.             get
  421.             {
  422.                 if ((ResendInterval > 0) && TimeoutOptionACK)
  423.                     //return RecvTimeout * 1000;
  424.                     return ResendInterval;
  425.                 else
  426.                     //return 1000;
  427.                     return 1;
  428.             }
  429.             set
  430.             {
  431.                 if ((value >= 1) || (value <= 255))
  432.                     ResendInterval = value;
  433.             }
  434.         }
  435.         /// <summary>
  436.         /// An integer representing the time in seconds that we will timeout and delete the state if we didn't get a repsonse
  437.         /// </summary>
  438.         public int TimeoutSeconds
  439.         {
  440.             get
  441.             {
  442.                 return Timeout;
  443.             }
  444.             set
  445.             {
  446.                 if ((value >= 1) || (value <= 255))
  447.                     Timeout = value;
  448.             }
  449.         }
  450.         /// <summary>
  451.         /// An integer representing the number of bytes to send in a DATA packet
  452.         /// </summary>
  453.         public int BlockSize
  454.         {
  455.             get
  456.             {
  457.                 if (BlocksizeOptionACK && (RecvBlkSize >= 8) && (RecvBlkSize <= 65464))
  458.                     return RecvBlkSize;
  459.                 else
  460.                     return 512;
  461.             }
  462.             set
  463.             {
  464.                 if ((value >= 8) && (value <= 65464))
  465.                     RecvBlkSize = value;
  466.             }
  467.         }
  468.         public bool ErrorOccurred
  469.         {
  470.             get
  471.             {
  472.                 return TransferState.ErrorOccurred;
  473.             }
  474.             set
  475.             {
  476.                 TransferState.ErrorOccurred = value;
  477.             }
  478.         }
  479.         public string ErrorMsg
  480.         {
  481.             get
  482.             {
  483.                 return TransferState.ErrorMsg;
  484.             }
  485.             set
  486.             {
  487.                 TransferState.ErrorMsg = value;
  488.             }
  489.         }
  490.     }
  491. }