using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using NLog; using DataClient.Struct; using System.IO; namespace DataClient { /// public class NETClient { private Logger log = LogManager.GetCurrentClassLogger(); private Encoding enc; private TcpClient tcpC = null; /// public double Status { get { if (stat.stat == NetStatus.Status.wait) return 0; if (stat.stat == NetStatus.Status.in_progress && stat.fullSize <= 0) return 0.01; if (stat.stat == NetStatus.Status.in_progress) return ((double)stat.size / stat.fullSize); stat.stat = NetStatus.Status.wait; stat.fullSize = 0; stat.size = 0; return 1; } } private NetStatus stat = new NetStatus(); /* 0x01 0x00 0x00 0x00 - 0001 - file list 0x03 0x00 0x00 0x00 - 0003 - pasp browse 0x04 0x00 0x00 0x00 - 0004 - pasp download 0x05 0x00 0x00 0x00 - 0005 - pasp find 0x06 0x00 0x00 0x00 - 0006 - prog list 0x07 0x00 0x00 0x00 - 0007 - prog download 0x09 0x00 0x00 0x00 - 0009 - download usov 0x0A 0x00 0x00 0x00 - 0010 - slit history - vdp cycle - vdp active - vdp last cycle - rmt watchdog - set rmt watchdog 0x11 0x00 0x00 0x00 - 0017 - print job - pasp find2 - pasp browse2 - arch history - download usov nhv - vdp sim med - vdp flags 0x1A 0x00 0x00 0x00 - 0026 - user flags 0x1B 0x00 0x00 0x00 - 0027 - user motd 0x1C 0x00 0x00 0x00 - 0028 - user mail 0x1D 0x00 0x00 0x00 - 0029 - download tvso 0x1E 0x00 0x00 0x00 - 0030 - pasp download tvso 0x1F 0x00 0x00 0x00 - 0031 - pasp find tvso - pasp browse tvsov 0x21 0x00 0x00 0x00 - 0033 - korpus cycle 0x22 0x00 0x00 0x00 - 0034 - korpus last cycle 0x23 0x00 0x00 0x00 - 0035 - download fdan 0x24 0x00 0x00 0x00 - 0036 - client version - measure id - read vdp config - write vdp config - read tvso config - delete vdp config 0x2A 0x00 0x00 0x00 - 0042 - get plav personal 0x2B 0x00 0x00 0x00 - 0043 - get server info 0x2C 0x00 0x00 0x00 - 0044 - ctrl split 0x2D 0x00 0x00 0x00 - 0045 - ctrl set time - ctrl end tc 0x2F 0x00 0x00 0x00 - 0047 - ctrl remove 0x30 0x00 0x00 0x00 - 0048 - ctrl spool 0x31 0x00 0x00 0x00 - 0049 - save pasport - save pasport 90 0x33 0x00 0x00 0x00 - 0051 - find time bugs 0x34 0x00 0x00 0x00 - 0052 - update pasport - get pasp by id - cp com find pasp by temp 0x37 0x00 0x00 0x00 - 0055 - get splav list 0x38 0x00 0x00 0x00 - 0056 - get field val list 0x39 0x00 0x00 0x00 - 0057 - get plav list form 0x3A 0x00 0x00 0x00 - 0058 - get pasp by priv 0x3B 0x00 0x00 0x00 - 0059 - print job 2 0x3C 0x00 0x00 0x00 - 0060 - get pasp by name - get pasp by id 90 0x3E 0x00 0x00 0x00 - 0062 - find pasp by temp 90 0x3F 0x00 0x00 0x00 - 0063 - get pasp by priv 90 0x40 0x00 0x00 0x00 - 0064 - get pasp by name 90 0x41 0x00 0x00 0x00 - 0065 - get plav list form 90 - ctrl split db - ctrl set time db - ctrl remove db 0x45 0x00 0x00 0x00 - 0069 - update stat 0x46 0x00 0x00 0x00 - 0070 - get cur params arr 0x47 0x00 0x00 0x00 - 0071 - get cur params 0x48 0x00 0x00 0x00 - 0072 - get cur params arr 5 0x49 0x00 0x00 0x00 - 0073 - get cur params 5 0x4A 0x00 0x00 0x00 - 0074 - fix db cycle - by name - test */ /// public enum Code : uint { /// Версия. version = 0, /// Загрузка. download = 2, /// Загрузка паспорта. pasp_download = 4, /// Время сервера. server_time = 8, /// Оставаться на связи. keep_alive = 11, /// Загрузка (nh). download_nh = 21, /// Структура директории. dir_browse = 23, /// Поиск команды по имени. by_name = uint.MaxValue, TCP_COM_FILE_LIST = 1, TCP_COM_PASP_BROWSE = 3, TCP_COM_PASP_FIND = 5, TCP_COM_PROG_LIST = 6, TCP_COM_PROG_DOWNLOAD = 7, TCP_COM_DOWNLOAD_USOV = 9, TCP_COM_SLIT_HISTORY = 10, TCP_COM_VDP_CYCLE = 12, TCP_COM_VDP_ACTIVE = 13, TCP_COM_VDP_LAST_CYCLE = 14, TCP_COM_RMT_WATCHDOG = 15, TCP_COM_SET_RMT_WATCHDOG = 16, TCP_COM_PRINT_JOB = 17, TCP_COM_PASP_FIND2 = 18, TCP_COM_PASP_BROWSE2 = 19, TCP_COM_ARCH_HISTORY = 20, TCP_COM_DOWNLOAD_USOV_NH = 22, TCP_COM_VDP_SIM_MED = 24, TCP_COM_VDP_FLAGS = 25, TCP_COM_USER_FLAGS = 26, TCP_COM_USER_MOTD = 27, TCP_COM_USER_MAIL = 28, TCP_COM_DOWNLOAD_TVSO = 29, TCP_COM_PASP_DOWNLOAD_TVSO = 30, TCP_COM_PASP_FIND_TVSO = 31, TCP_COM_PASP_BROWSE_TVSO = 32, TCP_COM_KORPUS_CYCLE = 33, TCP_COM_KORPUS_LAST_CYCLE = 34, TCP_COM_DOWNLOAD_FDAN = 35, TCP_COM_CLIENT_VERSION = 36, TCP_COM_MEASURE_ID = 37, TCP_COM_READ_VDP_CONFIG = 38, TCP_COM_WRITE_VDP_CONFIG = 39, TCP_COM_READ_TVSO_CONFIG = 40, TCP_COM_DELETE_VDP_CONFIG = 41, TCP_COM_GET_PLAV_PERSONAL = 42, TCP_COM_GET_SERVER_INFO = 43, TCP_COM_CTRL_SPLIT = 44, TCP_COM_CTRL_SET_TIME = 45, TCP_COM_CTRL_END_TC = 46, TCP_COM_CTRL_REMOVE = 47, TCP_COM_CTRL_SPOOL = 48, TCP_COM_SAVE_PASPORT = 49, TCP_COM_SAVE_PASPORT_90 = 50, TCP_COM_FIND_TIME_BUGS = 51, TCP_COM_UPDATE_PASPORT = 52, TCP_COM_GET_PASP_BY_ID = 53, TCP_COM_FIND_PASP_BY_TEMP = 54, TCP_COM_GET_SPLAV_LIST = 55, TCP_COM_GET_FIELD_VAL_LIST = 56, TCP_COM_GET_PLAV_LIST_FORM = 57, TCP_COM_GET_PASP_BY_PRIV = 58, TCP_COM_PRINT_JOB_2 = 59, TCP_COM_GET_PASP_BY_NAME = 60, TCP_COM_GET_PASP_BY_ID_90 = 61, TCP_COM_FIND_PASP_BY_TEMP_90 = 62, TCP_COM_GET_PASP_BY_PRIV_90 = 63, TCP_COM_GET_PASP_BY_NAME_90 = 64, TCP_COM_GET_PLAV_LIST_FORM_90 = 65, TCP_COM_CTRL_SPLIT_DB = 66, TCP_COM_CTRL_SET_TIME_DB = 67, TCP_COM_CTRL_REMOVE_DB = 68, TCP_COM_UPDATE_STAT = 69, TCP_COM_GET_CUR_PARAMS_ARR = 70, TCP_COM_GET_CUR_PARAMS = 71, TCP_COM_GET_CUR_PARAMS_ARR_5 = 72, TCP_COM_GET_CUR_PARAMS_5 = 73, TCP_COM_FIX_DB_CYCLE = 74, } /// public string Ip { get { return ip; } set { ip = (IPAddress.TryParse(value, out _)) ? value : ip; } } private string ip = "127.0.0.1"; /// public int Port { get { return port; } set { port = (value < 1) ? 1 : (value > 65535) ? 65535 : value; } } private int port = 1070; /// public int RetryCount { get { return retryCount; } set { retryCount = value < 1 ? 1 : value; } } private int retryCount = 3; /// public double RetryInterval { get { return retryInterval; } set { retryInterval = (value < 1) ? 1 : value; } } private double retryInterval = 1; //Construction /// public NETClient() { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); enc = Encoding.GetEncoding(866); tcpC = new TcpClient(new IPEndPoint(IPAddress.Parse(ip), port)); } /// public NETClient(string ip, int port) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); enc = Encoding.GetEncoding(866); Ip = ip; Port = port; tcpC = new TcpClient(); } //Work with socket functions /// private byte[] ReceiveBytesFull(NetworkStream ns) { try{ return ReceiveBytesFixSize(ns, uint.MaxValue); } catch { throw; } } /// private byte[] ReceiveBytesFixSize(NetworkStream ns, uint size) { if (size == 0) throw new ArgumentException("Size can't be zero."); if (!ns.Socket.Connected) throw new InvalidOperationException("NetworkStream not connected to server."); if (!ns.CanRead) throw new IOException("NetworkStream not access to Read."); var res = new List(); int tryCount = 0; do { if (!ns.Socket.Connected) throw new TimeoutException("Server drop connection."); if (!ns.DataAvailable) { Task.Delay(Convert.ToInt32(Math.Floor(retryInterval * 1000))).Wait(); tryCount++; continue; } tryCount = 0; var sz = ((size - res.Count) > 1024) ? 1024 : (size - res.Count); var buf = new byte[sz]; var length = ns.Read(buf, 0, buf.Length); for (var i = 0; i < length; i++) res.Add(buf[i]); if (res.Count == size) return res.ToArray(); } while (tryCount < retryCount); return res.ToArray(); } /// private bool SendBytes(NetworkStream ns, byte[] arr) { if (!ns.Socket.Connected) throw new InvalidOperationException("NetworkStream not connected to server."); if (!ns.CanWrite) throw new IOException("NetworkStream not access to Write."); try { ns.Write(arr, 0, arr.Length); } catch { return false; } return true; } //Support functions /// public byte[] CreateCode(uint code, string val = null, byte[] prefix = null, byte[] postfix = null) { var res = new List(); res.AddRange(BitConverter.GetBytes(code)); if (prefix != null) res.AddRange(prefix); if (val != null) { res.AddRange(BitConverter.GetBytes((uint)val.Length)); res.AddRange(enc.GetBytes(val)); res.Add(0x00); } if (postfix != null) res.AddRange(postfix); return res.ToArray(); } //Main functions /// public bool Connect() { if (Connected()) return true; if (tcpC == null) tcpC = new TcpClient(); try { tcpC.Connect(new IPEndPoint(IPAddress.Parse(ip), port)); } catch { return false; } return Connected(); } /// public bool Connected() { return (tcpC != null && tcpC.Connected); } /// public void Close() { if (tcpC != null && !tcpC.Connected) tcpC.Close(); } /// public bool SendBytes(byte[] send) { if (!Connected()) return false; try { return SendBytes(tcpC.GetStream(), send); } catch { throw; } } /// public byte[] ReceiveBytes() { if (!Connected()) return null; try { return ReceiveBytesFull(tcpC.GetStream()); } catch { return null; } } /// public byte[] ReceiveBytes(uint size) { if (!Connected()) return null; try { return ReceiveBytesFixSize(tcpC.GetStream(), size); } catch { return null; } } //SubMain functions /// private bool My_Connect() { if (stat.stat == NetStatus.Status.in_progress) throw new IOException("Previous method not finished."); stat.stat = NetStatus.Status.in_progress; if (Connected()) return false; if (!Connect()) { throw new InvalidOperationException("Can't create connection."); } return true; } /// private void My_Close(bool needClose) { if (needClose) Close(); stat.stat = NetStatus.Status.complete; } /// private byte[] GetFile(Code code, DateTime date, int vdp, int idx) { if (code != Code.download_nh && code != Code.download) throw new ArgumentException("Wrong code for this method."); bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } var str = date.ToString("yyyyMMdd") + "." + vdp.ToString("D2") + (idx % 16).ToString("X1"); try { if(!SendBytes(CreateCode((uint)code, str))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } var res = new List(); var endCycle = false; try { double cycleAwait = 0; int cycleCount = 0; var updateCycle = false; do { var tmp = ReceiveBytes(1); if (updateCycle) { RetryInterval = cycleAwait; RetryCount = cycleCount; updateCycle = false; } switch (tmp[0]) { case 0x00: case 0xff: endCycle = true; break; case 0x01: res.AddRange(ReceiveBytes(BitConverter.ToUInt32(ReceiveBytes(4)))); stat.size = (uint)res.Count; break; case 0x02: stat.fullSize = BitConverter.ToUInt32(ReceiveBytes(4)); break; case 0x03: //Need Brake for 5 seconds. (Await alrady create in ReceiveBytes function...)// updateCycle = true; cycleAwait = RetryInterval; RetryInterval = 1; cycleCount = RetryCount; RetryCount = 5; break; default: ReceiveBytes(); throw new ArgumentException("Wront flag when get files."); } } while (!endCycle); } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return res.ToArray(); } //COMMANDS FUNCTIONS /// public byte[] Full_Download_NH(DateTime date, int vdp, int idx) { try { return GetFile(Code.download_nh, date, vdp, idx); } catch { throw; } } /// public byte[] Full_Download(DateTime date, int vdp, int idx) { try { return GetFile(Code.download, date, vdp, idx); } catch { throw; } } /// public byte[] Full_By_Name(string val) { if (string.IsNullOrEmpty(val)) return null; bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if(!SendBytes(CreateCode((uint)Code.by_name, val))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } byte[] res = null; try { var tmp = ReceiveBytes(1); switch (tmp[0]) { case 0x00: break; case 0x01: res = ReceiveBytes(4); break; default: ReceiveBytes(); break; }; } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return res; } /// public string[] Full_Dir_Browse(string dir = "") { dir = (string.IsNullOrEmpty(dir)) ? "" : dir; bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if (!SendBytes(CreateCode((uint)Code.dir_browse, dir, new byte[] { 0x00 }))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } var res = new List(); try { bool endCycle = false; do { var tmp = ReceiveBytes(1); switch (tmp[0]) { case 0x00: res = null; endCycle = true; break; case 0x01: var str = enc.GetString(ReceiveBytes(BitConverter.ToUInt32(ReceiveBytes(4)))); if (str != "." && str != ".." && str != "error") if (dir == "") res.Add(str); else res.Add(dir + "/" + str); tmp = ReceiveBytes(1); if (tmp[0] != 0x00) throw new ArgumentException("Wrong get end line."); break; case 0xff: endCycle = true; break; default: res = null; ReceiveBytes(); endCycle = true; break; } } while (!endCycle); } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return res?.ToArray(); } /// public DateTime Full_Server_Time() { bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if (!SendBytes(CreateCode((uint)Code.server_time))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } int year, month, day, hour, minute, second; try { var buf = ReceiveBytes(2); year = buf[0] | buf[1] << 8; month = ReceiveBytes(1)[0]; day = ReceiveBytes(1)[0]; hour = ReceiveBytes(1)[0]; minute = ReceiveBytes(1)[0]; second = ReceiveBytes(1)[0]; } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return new DateTime(year, month, day, hour, minute, second); } /// public string Full_Version() { bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if (!SendBytes(CreateCode((uint)Code.version))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } string str = null; try { str = enc.GetString(ReceiveBytes(BitConverter.ToUInt32(ReceiveBytes(4)))); if (ReceiveBytes(1)[0] != 0x00) throw new ArgumentException("Wrong get end line."); } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return str; } /// public void Full_Keep_Alive() { bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if (!SendBytes(CreateCode((uint)Code.keep_alive))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } My_Close(needCloseConeection); } public Pasport Full_Pasp_Download(string file) { if (string.IsNullOrEmpty(file)) throw new ArgumentException("Path to file can't be null or empty."); bool needCloseConeection = false; try { needCloseConeection = My_Connect(); } catch { My_Close(needCloseConeection); throw; } try { if (!SendBytes(CreateCode((uint)Code.pasp_download, file))) throw new IOException("Can't send bytes to server."); } catch { My_Close(needCloseConeection); throw; } var pasp = new Pasport(); var res = new List(); try { res.AddRange(ReceiveBytes(1)); if (res.Count == 1 && res[0] == 0x01) { res.AddRange(ReceiveBytes(16)); if(res.Count == 17 && res[16] == 0x01) res.AddRange(ReceiveBytes(1512)); } pasp.PaspByte = res.ToArray(); } catch { My_Close(needCloseConeection); throw; } finally { My_Close(needCloseConeection); } return pasp; } } }