using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.IO; using System.Net; using System.Net.Sockets; using Wayne.Lib; using Wayne.ForecourtControl.OptBridge; using Wayne.FDCPOSLibrary; using Wayne.ForecourtControl.OptBridge.Fusion; namespace Wayne.ForecourtControl.Fusion { enum MsgType { Unknown, Polling, Present, Ack, Nack, Data, } internal class OptPollerThreadObj { public bool bTerminate = false; string name = ""; OptTCP optTCP; private FUSIONOpt opt; private int iOnDataReadTimeout = 4; public bool bDataReadTimeout = false; System.Threading.Timer timerOnDataRead = null; System.Threading.Timer timerOnRestartPolling = null; public OptPollerThreadObj(OptTCP optTCP, FUSIONOpt opt) { this.optTCP = optTCP; this.opt = opt; iOnDataReadTimeout = 4 * 1000; } public void optPollerThreadProc() { Thread.Sleep(1000); // gives time to AddOPT metods (the original caller) to return and register events Trace.WriteLine(string.Format("optPollerThreadProc Opt IPAddress={0}, IPPort={1}: init tp={2}", this.optTCP.sIPAddress, this.optTCP.IPPort, opt.Id)); int iOnDataReadTimeout = 4, iDartPollingInterval = 300; try { try { string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "OPTDataReadTimeout"); if (sValue.Length == 0) sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "Config", "DataReadTimeout"); if (sValue.Length > 0) iOnDataReadTimeout = Convert.ToInt32(sValue); if (iOnDataReadTimeout <= 10) iOnDataReadTimeout *= 1000; Trace.WriteLine(string.Format("iOnDataReadTimeout={0}", iOnDataReadTimeout)); } catch (Exception ex) { Trace.WriteLine("EXCEPTION! " + ex.Message); } try { string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "OPTDartPollingInterval"); if (sValue.Length > 0) iDartPollingInterval = Convert.ToInt32(sValue); Trace.WriteLine(string.Format("iDartPollingInterval={0}", iDartPollingInterval)); } catch (Exception ex) { Trace.WriteLine("EXCEPTION! " + ex.Message); } IPAddress serverIPAddress = null; IPEndPoint endPoint = null; optTCP.OptSocket = new TcpClient(); //optTCP.OptSocket.ReceiveTimeout = iOnDataReadTimeout; //optTCP.OptSocket.SendTimeout = iOnDataReadTimeout; bTerminate = false; bool bConnected = false; while (!bConnected && !bTerminate) { try { Trace.WriteLine(string.Format("Connect socket")); optTCP.OptSocket.Connect(optTCP.sIPAddress, optTCP.IPPort); bConnected = true; } catch (Exception ex) { Trace.WriteLine("optPollerThreadProc EXCEPTION on Connect socket!" + ex.Message + " - " + ex.StackTrace); try { if (optTCP.OptSocket != null && optTCP.OptSocket.GetStream() != null) optTCP.OptSocket.GetStream().Close(); } catch (Exception ex1) { Trace.WriteLine("optPollerThreadProc EXCEPTION on socket getStream!" + ex1.Message + " - " + ex1.StackTrace); } Thread.Sleep(1000); } } optTCP.ConnectionState = DeviceConnectionState.Connected; } catch (Exception ex) { Trace.WriteLine(string.Format("end: EXCEPTION! Stack chiamate: {0} Messaggio: {1}, tp={2}", ex.StackTrace, ex.Message, opt.Id)); bTerminate = true; return; } this.optTCP.bPollerRunning = true; int iReconnectTimeout = 3000; try { string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "ReconnectTimeout"); if (sValue.Length > 0) iReconnectTimeout = Convert.ToInt32(sValue); Trace.WriteLine(string.Format("iReconnectTimeout={0}", iReconnectTimeout)); } catch (Exception ex) { Trace.WriteLine("EXCEPTION! " + ex.Message); } string sbuffer = ""; OverallResult result = OverallResult.Success; NetworkStream networkStream = null; System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); MsgType responseType = MsgType.Unknown; bool bRespOk = false, bSendOk = false, bEnd = false; byte txNum = 0x00; byte rxNum = 0x00; byte[] dataRequest = null; byte[] dataResponse = null; int nretry = 0; int nWaitForDataResponse = 0; int nMaxWaitForDataResponse = 100; int ndartpoll = 0; int res = 0; bool bRestoredConnection = false; bool bFirstPoll = true; while (!bTerminate) { try { ndartpoll++; result = OverallResult.Success; networkStream = optTCP.OptSocket.GetStream(); //Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("tp={0} PendingRequest={1}, ndartpoll={2}", opt.Id, IsPendingRequest(), ndartpoll)); bRespOk = false; bSendOk = false; this.bDataReadTimeout = false; // check if there are pending request if ((dataRequest != null || IsPendingRequest()) && ndartpoll > 4) { if (!bRestoredConnection || dataRequest == null) dataRequest = GetPendingRequest(); else { Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("tp={0} was restored connection", opt.Id)); bRestoredConnection = false; } // if there are pending data send them if (dataResponse != null && bFirstPoll) { Trace.WriteLine(string.Format("tp={0} first poll - data pending", opt.Id)); this.opt.FireOnDataRead(dataResponse); bRespOk = true; dataRequest = null; continue; } bFirstPoll = false; nretry = 0; nWaitForDataResponse = 0; // attiva timer per timeout su ricezione risposta - non deve essere periodico, parte una sola volta dopo iOnDataReadTimeout secondi Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("tp={0} PendingRequest, create timer timerOnDataReadList", opt.Id)); this.timerOnDataRead = new System.Threading.Timer(new System.Threading.TimerCallback(OnDataReadTimerProc), this, iOnDataReadTimeout * 1000, Timeout.Infinite); do { nretry++; if (!bSendOk) res = Write(PreparePendingRequest(dataRequest, txNum)); else if (responseType == MsgType.Data && !bRespOk) res = Write(PreparePollingRequest(MsgType.Nack, txNum)); else res = Write(PreparePollingRequest(MsgType.Polling, 0)); bool crcok = false; if (res >= 0) dataResponse = ReadResponse(out responseType, out rxNum, out crcok, false); else responseType = MsgType.Unknown; if (responseType == MsgType.Ack) bSendOk = true; else if (responseType == MsgType.Nack) { if (nretry > 3) txNum = 0; } else if (responseType == MsgType.Data) { // if crc fails do not send the Ack; a new poll will be sent and the tp should resend data if (CheckResponse(dataResponse) && crcok) { lock (timerOnDataRead) { if (timerOnDataRead != null) { timerOnDataRead.Dispose(); timerOnDataRead = null; } } res = Write(PreparePollingRequest(MsgType.Ack, rxNum)); this.opt.FireOnDataRead(dataResponse); bRespOk = true; dataRequest = null; // read if there are pending data to discard if (ReadResponse(out responseType, out rxNum, out crcok, true) != null) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR DISCARD DATA!", opt.Id)); res = Write(PreparePollingRequest(MsgType.Polling, 0)); dataResponse = ReadResponse(out responseType, out rxNum, out crcok, false); if (responseType != MsgType.Present) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR Wrong Response {1} (should be 'Present')", opt.Id, responseType)); } else if (!crcok) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR CRC FAILS!", opt.Id)); } else if (responseType == MsgType.Present) { bSendOk = true; // set to true so that request msg is not sent again nWaitForDataResponse++; if (nWaitForDataResponse > 30) bDataReadTimeout = true; } else { Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR unexpected Response '{1}'", opt.Id, responseType)); nWaitForDataResponse++; // try call GetStream to check if socket is still valid; it wiil arise an exception catched below if (optTCP.OptSocket.GetStream() == null) bDataReadTimeout = true; else Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} stream is valid, continue", opt.Id)); } if (!bRespOk) Thread.Sleep(100); if (bDataReadTimeout) { Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR Data Response not arrived ! Disconnecting OPT !", opt.Id)); bTerminate = true; Thread.Sleep(iReconnectTimeout); } } while (!bRespOk && !bDataReadTimeout); if (responseType != MsgType.Nack) { if (txNum < 0x0F) txNum++; else txNum = 0x01; } } else { bool crcok; do { res = Write(PreparePollingRequest(MsgType.Polling, 0)); dataResponse = ReadResponse(out responseType, out rxNum, out crcok, false); if (responseType == MsgType.Data) { //if crc fails do not send the Ack; a new poll will be sent and the tp should resend data if (CheckResponse(dataResponse) && crcok) { res = Write(PreparePollingRequest(MsgType.Ack, rxNum)); // read if there are pending data to discard if (ReadResponse(out responseType, out rxNum, out crcok, true) != null) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR DISCARD DATA!", opt.Id)); } else if (!crcok) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR CRC FAILS!", opt.Id)); // at first polling after connection could happens that tp has data to send // needs to store data and send to SINP with first request if (ndartpoll > 1) Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR Wrong Response DATA !!??", opt.Id)); else { bRespOk = true; Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} First Polling - DATA received !", opt.Id)); } } else if (responseType == MsgType.Unknown) { if (optTCP.OptSocket.GetStream() == null) { bDataReadTimeout = true; bTerminate = true; } } else if (responseType == MsgType.Present) bRespOk = true; else Trace.WriteLine(string.Format("optPollerThreadProc: tp={0} ERROR Wrong Response {1} !!??", opt.Id, responseType)); } while (!bRespOk || bDataReadTimeout); } Thread.Sleep(iDartPollingInterval); } catch (Exception ex) { Trace.WriteLine(string.Format("tp={0} IOException in optPollerThreadProc! {1} - {2}", optTCP.Id, ex.Message, ex.StackTrace)); optTCP.CloseSocket(networkStream); if (!bTerminate) { bool bConnected = false; int nretries = 0; while (!bConnected && nretries <= 1) { try { if (nretries == 1) { optTCP.OptSocket = new TcpClient(); //optTCP.OptSocket.ReceiveTimeout = iOnDataReadTimeout; //optTCP.OptSocket.SendTimeout = iOnDataReadTimeout; Thread.Sleep(iReconnectTimeout); } Trace.WriteLine(string.Format("try reconnect socket: nretries={0}", nretries)); optTCP.OptSocket.Connect(optTCP.sIPAddress, optTCP.IPPort); bConnected = true; } catch (Exception ex2) { Trace.WriteLine(string.Format("tp={0} optPollerThreadProc EXCEPTION on Connect socket! {1} - {2}", optTCP.Id, ex2.Message, ex2.StackTrace)); optTCP.CloseSocket(networkStream); } nretries++; } if (!bConnected) bTerminate = true; else { bRestoredConnection = true; // set ndartpoll=3 so that it starts with a dart poll request needed to read a pending response from tp ndartpoll = 3; //optTCP.ConnectionState = DeviceConnectionState.Connected; } } } } this.optTCP.bPollerRunning = false; this.optTCP.Disconnect(); //this.optTCP.Connect(); int iOPTDartRestartPollingTimeout = 30000; try { string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "OPTDartRestartPollingTimeout"); if (sValue.Length > 0) iOPTDartRestartPollingTimeout = Convert.ToInt32(sValue); Trace.WriteLine(string.Format("iOPTDartRestartPollingTimeout={0}", iOPTDartRestartPollingTimeout)); } catch (Exception ex) { Trace.WriteLine("EXCEPTION! " + ex.Message); } this.timerOnRestartPolling = new System.Threading.Timer(new System.Threading.TimerCallback(OnRestartPollingTimerProc), this, iOPTDartRestartPollingTimeout, Timeout.Infinite); Trace.WriteLine(string.Format("optPollerThreadProc tp={0} end", this.optTCP.Id)); } public void OnRestartPollingTimerProc(Object me) { lock (timerOnRestartPolling) { try { Trace.WriteLine(string.Format("optPollerThreadProc OnRestartPollingTimerProc tp={0}, manager={1}, forecourtcontrol={2}, ConnectionState={3}", this.optTCP.Id, (optTCP.Opt.optBridge.manager != null) ? "!null":"null", (optTCP.Opt.optBridge.manager != null && optTCP.Opt.optBridge.manager.forecourtControl != null) ? "!null":"null", (optTCP.Opt.optBridge.manager != null && optTCP.Opt.optBridge.manager.forecourtControl != null) ? optTCP.Opt.optBridge.manager.forecourtControl.ConnectionState : DeviceConnectionState.Unknown)); if (optTCP.Opt.optBridge.manager == null || optTCP.Opt.optBridge.manager.forecourtControl == null || (optTCP.Opt.optBridge.manager != null && optTCP.Opt.optBridge.manager.forecourtControl != null && (optTCP.Opt.optBridge.manager.forecourtControl.ConnectionState == DeviceConnectionState.Connected || optTCP.Opt.managedBy == OPTManagedBy.SINP))) { if (timerOnRestartPolling != null) { timerOnRestartPolling.Dispose(); timerOnRestartPolling = null; this.bDataReadTimeout = true; Trace.WriteLine(string.Format("optPollerThreadProc OnRestartPollingTimerProc tp={0} call connect", this.optTCP.Id)); this.optTCP.Connect(); } } else Trace.WriteLine(string.Format("optPollerThreadProc OnRestartPollingTimerProc tp={0} not restarted - forecourtControl is not connected", this.optTCP.Id)); } catch (Exception ex) { Trace.WriteLine("Exception optPollerThreadProc OnRestartPollingTimerProc! " + ex.Message + " - " + ex.StackTrace); } } } public void OnDataReadTimerProc(Object me) { lock (timerOnDataRead) { if (timerOnDataRead != null) { timerOnDataRead.Dispose(); timerOnDataRead = null; this.bDataReadTimeout = true; Trace.WriteLine(string.Format("optPollerThreadProc OnDataReadTimerProc tp={0}", this.optTCP.Id)); } } } private byte[] PreparePollingRequest(MsgType pollingType, int txNum) { try { Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("optPollerThreadProc PreparePollingRequest tp={0}, pollingType={1}, txNum={2}", optTCP.Id, pollingType, txNum)); byte[] pollRequest = null; pollRequest = new byte[OptTCP.PollRequestLength]; // ??? che indirizzo va messo ? pollRequest[0] = (byte)(0x30 + optTCP.Id-1); if (pollingType == MsgType.Polling) pollRequest[1] = 0x20; else if (pollingType == MsgType.Ack) pollRequest[1] = (byte)(0xC0 + txNum); else pollRequest[1] = (byte)(0x50 + txNum); pollRequest[2] = 0xFA; return pollRequest; } catch (Exception ex) { Trace.WriteLine("Exception optPollerThreadProc! " + ex.Message + " - " + ex.StackTrace); } return null; } private byte[] PreparePendingRequest(byte[] data, int txNum) { try { if (data == null) { Trace.WriteLine(string.Format("optPollerThreadProc PreparePendingRequest tp={0}, invalid data !", optTCP.Id)); return null; } byte[] pollRequest = null; //pollRequest = new byte[2 + data.Length + OptTCP.FooterLength+2]; pollRequest = new byte[2 + data.Length]; pollRequest[0] = (byte)(0x30 + optTCP.Id - 1); pollRequest[1] = (byte)(0x30 + txNum); Array.Copy(data, 0, pollRequest, 2, data.Length); ushort checksum = Crc.CalcWayneCrc(0x0000, pollRequest, 2 + data.Length); Trace.WriteLine(string.Format("optPollerThreadProc PreparePendingRequest tp={0}, checksum={1}, dataLength={2}, pollRequest={3}", optTCP.Id, checksum, 2 + data.Length, pollRequest)); byte[] footer = new byte[OptTCP.FooterLength+2]; int index=0; if ((byte)(checksum) == 0xFA) footer[index++] = 0x10; footer[index++] = (byte)(checksum); if (((byte)(checksum >> 8)) == 0xFA) footer[index++] = 0x10; footer[index++] = (byte)(checksum >> 8); footer[index++] = 0x03; footer[index++] = 0xFA; //Array.Copy(footer, 0, pollRequest, 2 + data.Length, OptTCP.FooterLength); //Array.Copy(footer, 0, pollRequest, 2 + data.Length, index); byte[] returnRequest = null; returnRequest = new byte[2 + data.Length + index]; Array.Copy(pollRequest, 0, returnRequest, 0, 2 + data.Length); Array.Copy(footer, 0, returnRequest, 2 + data.Length, index); return returnRequest; } catch (Exception ex) { Trace.WriteLine("Exception PreparePendingRequest! " + ex.Message + " - " + ex.StackTrace); } return null; } private bool CheckResponse(byte[] pollingResponse) { return true; } private byte[] ReadByte(NetworkStream networkStream, out int nread, int iDartRWTimeout) { byte[] b = new byte[1]; int timeout = 0; nread = 0; try { // waits 200 msec 10*10 + 2*50 int retries = 0; while (timeout < iDartRWTimeout) { if (networkStream.DataAvailable) { nread = networkStream.Read(b, 0, 1); return b; } else if (retries < 10) { Thread.Sleep(10); timeout += 10; } else { Thread.Sleep(50); timeout += 50; } retries++; Trace.WriteLineIf(Trace.CheckTraceLevel(5), string.Format("ReadByte retries={0}", retries)); } } catch (IOException ex) { Trace.WriteLine(string.Format("IOException in ReadByte! networkStream.Connected={0}: {1} - {2}", this.optTCP.OptSocket.Client.Connected, ex.Message, ex.StackTrace)); networkStream.Write(new byte[0], 0, 0); if (ex.InnerException != null) Trace.WriteLine("IOException InnerException: " + ex.InnerException.Message+ " - " + ex.InnerException.StackTrace); } return null; } private byte[] ReadResponse(out MsgType responseType, out byte rxNum, out bool crcresult, bool bOnlyCheckDataPresent) { rxNum = 0; crcresult = true; try { int nreadzero = 0; responseType = MsgType.Present; NetworkStream networkStream = null; networkStream = this.optTCP.OptSocket.GetStream(); int iDartRWTimeout = 1500; string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "OPTDartRWTimeout"); if (sValue.Length > 0) iDartRWTimeout = Convert.ToInt32(sValue); if (bOnlyCheckDataPresent) iDartRWTimeout = 200; //networkStream.ReadTimeout = iDartRWTimeout; networkStream.WriteTimeout = iDartRWTimeout; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead init: tp={0}, read timeout={1}", optTCP.Id, iDartRWTimeout)); int iRetryReadZero = 1; //sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "OPTNumRetryZeroReading"); //if (sValue.Length > 0) // iRetryReadZero = Convert.ToInt32(sValue); //bool bSimulateReadTimeout; //sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "SimulateReadTimeout"); //if (sValue.Length > 0 && sValue == "1") //{ // Trace.WriteLine(string.Format("TPRead tp={0} SimulateReadTimeout", optTCP.Id)); // IniFile.IniWriteValue(ConfigurationParams.inifile, "OPT" + opt.Id.ToString(), "SimulateReadTimeout", "0"); // return null; //} // read 2 bytes header byte[] header = null; byte[] b = new byte[1]; int i; header = new byte[OptTCP.HeaderLength]; int nread = 0, nreadtot = 0; do { //Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("optPollerThreadProc: reading ...")); b = ReadByte(networkStream, out nread, iDartRWTimeout); if (nread > 0) header[nreadtot] = b[0]; else if (bOnlyCheckDataPresent) { return null; } nreadtot += nread; if (nread == 0) { nreadzero++; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0} read 0 bytes nreadzero={1}", optTCP.Id, nreadzero)); if (nreadzero == iRetryReadZero) { responseType = MsgType.Unknown; Trace.WriteLine(string.Format("TPRead tp={0} read 0 bytes ! return NULL!", optTCP.Id)); return null; } } else nreadzero = 0; } while (nreadtot < OptTCP.HeaderLength); // recognize response type if (header[1] == 0x20) responseType = MsgType.Polling; else if (header[1] == 0x70) responseType = MsgType.Present; else if (header[1] >= 0xC0 && header[1] <= 0xCF) { responseType = MsgType.Ack; rxNum = (byte)(header[1] - 0xC0); } else if (header[1] >= 0x50 && header[1] <= 0x5F) { responseType = MsgType.Nack; rxNum = (byte)(header[1] - 0x50); } else if (header[1] >= 0x30 && header[1] <= 0x3F) { responseType = MsgType.Data; rxNum = (byte)(header[1] - 0x30); } else { Trace.WriteLine(string.Format("TPRead tp={0} code='{1}' is INVALID ! Close socket!", optTCP.Id, header[1])); optTCP.CloseSocket(networkStream); responseType = MsgType.Unknown; return null; } Trace.WriteLineIf(Trace.CheckTraceLevel(2), string.Format("TPRead tp={0} code={1}, rxNum={2}", optTCP.Id, responseType, rxNum)); byte[] buffer = null; int bufferLength; if (responseType != MsgType.Data) bufferLength = 1; else bufferLength = 2; buffer = new byte[bufferLength]; nread = 0; nreadtot = 0; do { //Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("optPollerThreadProc: reading ...")); b = ReadByte(networkStream, out nread, iDartRWTimeout); if (nread > 0) buffer[nreadtot] = b[0]; nreadtot += nread; if (nread == 0) { nreadzero++; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0} read 0 bytes nreadzero={1}", optTCP.Id, nreadzero)); if (nreadzero == iRetryReadZero) { responseType = MsgType.Unknown; Trace.WriteLine(string.Format("TPRead tp={0} read 0 bytes ! return NULL!", optTCP.Id)); return null; } } else nreadzero = 0; } while (nreadtot < bufferLength); byte[] data = null; byte[] optResponse = null; int msglength = 0; if (responseType == MsgType.Data) { msglength = GetMsgLength(buffer); //--data = new byte[msglength - 2 + OptTCP.FooterLength]; data = new byte[msglength - bufferLength]; Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("TPRead tp={0} data msg length={1}, msglength={2}, bufferLength={3}", optTCP.Id, data.GetLength(0), msglength, bufferLength)); nread = 0; nreadtot = 0; do { //Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("optPollerThreadProc: reading ...")); b = ReadByte(networkStream, out nread, iDartRWTimeout); if (nread > 0) data[nreadtot] = b[0]; nreadtot += nread; if (nread == 0) { nreadzero++; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0} read 0 bytes nreadzero={1}", optTCP.Id, nreadzero)); if (nreadzero == iRetryReadZero) { responseType = MsgType.Unknown; Trace.WriteLine(string.Format("TPRead tp={0} read 0 bytes ! return NULL!", optTCP.Id)); return null; } } else nreadzero = 0; } //--while (nreadtot < msglength - 2 + OptTCP.FooterLength); while (nreadtot < msglength - bufferLength); Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0}, nreadtot={1} ", optTCP.Id, nreadtot)); // remove 2 bytes header (leave the length) and the footer for the response message optResponse = new byte[msglength]; Array.Copy(buffer, 0, optResponse, 0, bufferLength); //--Array.Copy(data, 0, optResponse, 2, msglength-2); Array.Copy(data, 0, optResponse, bufferLength, msglength-bufferLength); Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead copiato tp={0}, nreadtot={1} ", optTCP.Id, nreadtot)); //-- read the footer bool exit = false; nread = 0; nreadtot = 0; byte[] footer = new byte[OptTCP.FooterLength + 2]; do { b = ReadByte(networkStream, out nread, iDartRWTimeout); if (nread > 0) { footer[nreadtot] = b[0]; if (nreadtot > 1 && footer[nreadtot] == 0xFA && footer[nreadtot - 1] != 0x10) exit = true; } nreadtot += nread; if (nread == 0) { nreadzero++; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0} read 0 bytes nreadzero={1}", optTCP.Id, nreadzero)); if (nreadzero == iRetryReadZero) { responseType = MsgType.Unknown; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0} read 0 bytes ! return NULL!", optTCP.Id)); return null; } } else nreadzero = 0; } while (!exit); int footerlength = nreadtot; Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("TPRead tp={0}, footerlength={1}", optTCP.Id, footerlength)); //--byte[] message = new byte[OptTCP.HeaderLength + bufferLength + msglength]; byte[] message = new byte[OptTCP.HeaderLength + msglength + footerlength]; Array.Copy(header, 0, message, 0, OptTCP.HeaderLength); Array.Copy(buffer, 0, message, OptTCP.HeaderLength, bufferLength); //--Array.Copy(data, 0, message, OptTCP.HeaderLength, msglength - 2 + OptTCP.FooterLength); Array.Copy(data, 0, message, OptTCP.HeaderLength + bufferLength, msglength-bufferLength); Array.Copy(footer, 0, message, OptTCP.HeaderLength + msglength, footerlength); // check crc //--bool crcresult = this.CheckCrc(message, message.Length - 4); crcresult = this.CheckCrc(message, message.Length - footerlength); Trace.WriteLine(string.Format("TPRead tp={0}, message={1}, crcresult={2}", optTCP.Id, ASCIIEncoding.ASCII.GetString(message, 0, message.GetLength(0)), crcresult)); //Trace.WriteLine(string.Format("TPRead tp={0}, response={1}", optTCP.Id, ASCIIEncoding.ASCII.GetString(optResponse, 0, optResponse.GetLength(0)))); } else { // check transmission number // ... } return optResponse; } catch (SocketException sex) { Trace.WriteLine(string.Format("tp={0} socket Exception in ReadResponse! {1}: {2} - {3}", optTCP.Id, sex.ErrorCode, sex.Message, sex.StackTrace)); responseType = MsgType.Unknown; } catch (IOException ex) { Trace.WriteLine(string.Format("tp={0} IOException in ReadResponse! {1} - {2}", optTCP.Id, ex.Message, ex.StackTrace)); if (ex.InnerException != null) Trace.WriteLine(string.Format("tp={0} IOException InnerException: {1} - {2}", optTCP.Id, ex.InnerException.Message, ex.InnerException.StackTrace)); responseType = MsgType.Unknown; } catch (Exception ex) { Trace.WriteLine(string.Format("tp={0} Exception in ReadResponse! {1} - {2}", optTCP.Id, ex.Message, ex.StackTrace)); responseType = MsgType.Unknown; } return null; } private int GetMsgLength(byte[] header) { int length = 0; length = (int)((header[0] & 0x0F) + ((header[1] & 0x0F) << 4)); //switch (responseCode) //{ // case 0x3a: length = 2; break; // case 0x3d: length = 33; break; // case 0x3f: length = 21; break; // case 0x5a: length = 48; break; // case 0x3d: length = 111; break; // case 0x40: length = 5; break; // case 0x53: length = 186; break; // case 0x56: length = 63; break; // case 0x59: length = 203; break; // case 0x5b: length = 80; break; // case 0x5c: length = 16; break; // case 0x5d: length = 11; break; // case 0x66: length = 4; break; //} Trace.WriteLineIf(Trace.CheckTraceLevel(3), string.Format("optPollerThreadProc: getMsgLength length={0}", length)); return length; } private bool IsPendingRequest() { return (optTCP.OptRequestQueue.Count > 0); } private byte[] GetPendingRequest() { return optTCP.OptRequestQueue.Dequeue(); } private int Write(byte[] message) { //return optTCP.OptSocket.Client.Send(message); try { if (message == null) { Trace.WriteLine(string.Format("TPWrite tp={0}, msg='null'", optTCP.Id)); return -2; } Trace.WriteLine(string.Format("TPWrite tp={0}, msg='{1}'", optTCP.Id, ASCIIEncoding.ASCII.GetString(message, 0, message.GetLength(0)))); this.optTCP.OptSocket.GetStream().Write(message, 0, message.Length); } catch (SocketException sex) { Trace.WriteLine(string.Format("tp={0} socket Exception in Write! {1}: {2} - {3}", optTCP.Id, sex.ErrorCode, sex.Message, sex.StackTrace)); return -1; } catch (IOException ex) { Trace.WriteLine("IOException in Write! " + ex.Message + " - " + ex.StackTrace); if (ex.InnerException != null) Trace.WriteLine(string.Format("tp={0} IOException InnerException: {1} - {2}", optTCP.Id, ex.InnerException.Message, ex.InnerException.StackTrace)); return -1; } catch (Exception ex) { Trace.WriteLine(string.Format("tp={0} Exception in Write! {1} - {2}", optTCP.Id, ex.Message, ex.StackTrace)); return -1; } return 0; } private bool CheckCrc(byte[] bufferToCheck, int len) { UInt16 crc = Crc.CalcWayneCrc(0x0000, bufferToCheck, len); int posLow = 0, posHigh = 1; if (bufferToCheck[len] == 0x10 && bufferToCheck[len + 1] == 0xFA) { posLow++; posHigh++; } if (bufferToCheck[len + posHigh] == 0x10 && bufferToCheck[len + posHigh + 1] == 0xFA) posHigh++; return (((byte)(crc >> 8) == bufferToCheck[len + posHigh]) && ((byte)(crc) == bufferToCheck[len + posLow])); } } internal class OptTCP { public static int HeaderLength = 2; public static int FooterLength = 4; public static int PollResponseLength = 3; public static int PollRequestLength = 3; public bool bPollerRunning = false; private string _sIPAddress = ""; public string sIPAddress { get { return _sIPAddress; } } private int _IPPort = 0; public int IPPort { get { return _IPPort; } } private TcpClient _OptSocket = null; public TcpClient OptSocket { get { return _OptSocket; } set { _OptSocket = value; } } public int Id; private FUSIONOpt _opt; public FUSIONOpt Opt { get { return _opt; } } public OptPollerThreadObj optPollerThreadObj; public Thread optPollerThread; private Queue _OptRequestQueue = null; public Queue OptRequestQueue { get { return _OptRequestQueue; } } private AsyncResponseManager _asyncResponseManager; public AsyncResponseManager asyncResponseManager { get { return this._asyncResponseManager; } } //private DeviceConnectionState _ConnectionState = DeviceConnectionState.Disconnected; public DeviceConnectionState ConnectionState { get { return this._opt.ConnectionState; } set { if (this._opt.ConnectionState != value) { this._opt.WritableConnectionState = value; //if (this._opt.WritableConnectionState == DeviceConnectionState.Disconnected) // Connect(); } } } public event EventHandler OnConnectionStateChange; public OptTCP(int Id, string sIPAddress, int IPPort, FUSIONOpt opt) { this.Id = Id; _sIPAddress = sIPAddress; _IPPort = IPPort; _OptRequestQueue = new Queue(); _opt = opt; bPollerRunning = false; //this._asyncResponseManager = new AsyncResponseManager(); //this._asyncResponseManager.OnResponseTimeout += new EventHandler(asyncResponseManager_OnResponseTimeout); //OnMessageEnqueuing += new EventHandler(this.asyncResponseManager.OnMessageEnqueuing); } public bool Connect() { Trace.WriteLine(string.Format("OptTCP tp={0} Connect", this.Id)); if ((this.ConnectionState == DeviceConnectionState.Disconnected) || (this.ConnectionState == DeviceConnectionState.Disconnecting)) { if (optPollerThreadObj != null && !optPollerThreadObj.bTerminate) optPollerThreadObj.bTerminate = true; this.ConnectionState = DeviceConnectionState.Connecting; optPollerThreadObj = new OptPollerThreadObj(this, this._opt); optPollerThread = new Thread(new ThreadStart(optPollerThreadObj.optPollerThreadProc)); optPollerThread.Start(); } return true; } public void CloseSocket(NetworkStream networkStream) { try { if (networkStream != null) { networkStream.Close(); Trace.WriteLine("optPollerThreadProc networkStream closed"); } } catch (Exception ex3) { Trace.WriteLine("optPollerThreadProc EXCEPTION on closing networkStream!" + ex3.Message + " - " + ex3.StackTrace); } try { if (this.OptSocket != null) { this.OptSocket.Client.Close(); Trace.WriteLine("optPollerThreadProc optTCP.OptSocket.Client closed"); } } catch (Exception ex3) { Trace.WriteLine("optPollerThreadProc EXCEPTION on closing socket!" + ex3.Message + " - " + ex3.StackTrace); } try { if (this.OptSocket != null) { this.OptSocket.Close(); Trace.WriteLine("optPollerThreadProc optTCP.OptSocket closed"); } } catch (Exception ex3) { Trace.WriteLine("optPollerThreadProc EXCEPTION on closing socket!" + ex3.Message + " - " + ex3.StackTrace); } } public void Disconnect() { try { if (OptSocket != null) { this.optPollerThreadObj.bTerminate = true; Trace.WriteLine(string.Format("OptTCP tp={0} Disconnect - closing stream", this.Id)); OptSocket.GetStream().Close(); Trace.WriteLine(string.Format("OptTCP tp={0} Disconnect - closing socket", this.Id)); this.OptSocket.Close(); } } catch(Exception ex) { Trace.WriteLine("Exception in Disconnect! " + ex.Message + " - " + ex.StackTrace); } this._OptSocket = null; this.OptRequestQueue.Clear(); this.ConnectionState = DeviceConnectionState.Disconnected; } public void OptWrite(byte[] message, EventHandler requestCompleted, object userToken, object src) { try { EnqueueMessage(message, requestCompleted, userToken, src, true, null);//, new OptWriteCompletedEventArgs(true, userToken, 0)); } catch (Exception ex) { Trace.WriteLine("Exception! " + ex.Message + " - " + ex.StackTrace); } } public void EnqueueMessage(byte[] request, EventHandler requestCompleted, object userToken, object src, bool responseRequired, OptWriteCompletedEventArgs resultOptWrite) { //Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("EnqueueMessage(opt) init: tp={0}", this._opt.Id)); // enqueue the object in the socket elaboration queue Monitor.Enter(OptRequestQueue); OptRequestQueue.Enqueue(request); Monitor.Exit(OptRequestQueue); //Trace.WriteLineIf(Trace.CheckTraceLevel(4), string.Format("EnqueueMessage(opt) end: tp={0}", this._opt.Id)); } } }