private void readStateMachine() { string telegram; if (m_readQ.TryDequeue(out telegram)) { int loglinedisplay = Params.getParam("loglinedisplay", "viastdproto", 0); if (!m_readBuf.getData().Contains("line_display") || loglinedisplay == 1) { m_socketLog.log(LogTools.getCardString("ViaStdProto", "readStateMachine", "Received: <" + telegram + ">")); } m_readBuf.Assign(telegram); if (m_readBuf.getLength() == 0) // bad telegram, disconnect { m_socketLog.log(LogTools.getErrorString("ViaStdProto", "internalRead","Received telegram has invalid header or trailer (or no data) restarting the socket")); disconnect(); } // Data Telegram if (m_readBuf.isData()) { SeqNumStatus sNS = checkSeqErr(m_readBuf.getSeqNumber()); switch (sNS) { default: case SeqNumStatus.INVALID_ORDER: m_socketLog.log(LogTools.getErrorString("ViaStdProto", "internalRead", "Sequence number received " + m_readBuf.getSeqNumber() + ", but should have been " + incSeq(m_recSeqNum))); //+ ". Sending ACKN and ingoring message.")); m_recQ.Enqueue(m_readBuf.getData()); // put it in the receive queue to be passed to the software. m_recSeqNum = m_readBuf.getSeqNumber(); // accept whatever sequence number we just got... break; case SeqNumStatus.DUPLICATE: m_socketLog.log(LogTools.getErrorString("ViaStdProto", "internalRead", "Duplicate message received (sequence number: " + m_readBuf.getSeqNumber() + "), send ACKN and ignored message.")); break; case SeqNumStatus.OK: m_recSeqNum = m_readBuf.getSeqNumber(); // accept whatever sequence number we just got... m_recQ.Enqueue(m_readBuf.getData()); // put it in the receive queue to be passed to the software. break; } m_lastRecieve = DateTime.Now; m_ackWriteQueue.Enqueue(m_readBuf.getSeqNumber()); } // ACKN telegram else if (m_readBuf.isAck()) { //check if we sent a telegram which waits for an ACKN (or we were in that but got interrupted) if ((m_writeState == WriteState.WAIT_ACK)||(m_writeState == WriteState.WAIT_ASYNCH_INTERRUPT)) { // yes there is a telegram waiting for an ACKN // compare the sequence numbers ViaTelegram writeTele = new ViaTelegram(); writeTele.Assign(Encoding.ASCII.GetString(m_sendBuffer)); if (m_readBuf.getSeqNumber() == writeTele.getSeqNumber()) { m_sendSeqNum = incSeq(writeTele.getSeqNumber()); m_writeState = WriteState.READY; } else { m_writeState = WriteState.READY; m_socketLog.log(LogTools.getErrorString("viaStdProto", "internalRead", "Received ack telegram has wrong sequence number, accept anyway. Expected sequence number: " + writeTele.getSeqNumber() + ", got: " + m_readBuf.getSeqNumber())); } } else { m_socketLog.log(LogTools.getErrorString("ViaStdProto", "internalRead", "Received an ACKN telegram without having sent a telegram that's waiting for an ACK")); } m_lastRecieve = DateTime.Now; } else if (m_readBuf.isKeepAlive()) { m_lastRecieve = DateTime.Now; } else if (m_readBuf.isNak()) { disconnect(); m_socketLog.log(LogTools.getErrorString("viaStdProto", "readStateMachine", "NAK recieved, reset socket")); } else { m_socketLog.log(LogTools.getErrorString("viaStdProto", "readStateMachine", "unknown message recieved, ignore")); } } }
// Public Methods // ======================================================================================== // ---------------------------------------------------------------------------------------- // Constructor with all fields // addr: IP address // port: port number // server: true if we are the server, false if we are the client // srcid: our id Ex: "VLS1" // destid: id of target Ex: "MFC1", "IOC1" ... // toacknak: time to wait for ack before re-sending (in seconds) // datalen: length of telegram, pad telegram if shorter than datalen. // fillchar: character to pad with // binary: true: telegrams are binary (IO) false: telegrams are ASCII (data) // tokeepalive: time to wait before sending keep alive mesage (seconds) 0 = disabled // ---------------------------------------------------------------------------------------- public ViaStdProto(IPAddress addr, int port, bool server, string srcid, string destid, int toacknak, int datalen, char fillchar, bool binary, int tokeepalive) { m_addr = addr; m_port = port; m_server = server; m_srcid = srcid; m_destid = destid; m_datalen = datalen; m_fillchar = fillchar; m_binary = binary; m_recSeqNum = 0; m_sendSeqNum = 1; m_readBuf = new ViaTelegram(); m_writeBuf = new ViaTelegram(); m_numResends = 0; m_recQ = new ConcurrentQueue<string>(); m_readQ = new ConcurrentQueue<string>(); m_dataWriteQueue = new ConcurrentQueue<string>(); m_ackWriteQueue = new ConcurrentQueue<int>(); m_keepaliveStr = "00 keep alive telegram "; m_socketLog = null;// MainWindow.logBook.requestLog("Kiosk_Socket" + m_port + ".log"); m_socketLog.log(LogTools.getStatusString("ViaStdProto", "ViaStdProto", "Creating socket: \n" + "Addr = " + m_addr + "\tPort = " + m_port + "\tServer = " + m_server + "\tSrc ID = " + m_srcid + "\tDest ID = " + m_destid + "\tData Length = " + m_datalen + "\tBinary = " + m_binary)); m_recvAccumulator = ""; if (toacknak <= 0) { toacknak = 5000; //default the value to 5 seconds if no value was passed } m_toacknak = new TimeSpan(0, 0, 0, 0, toacknak); m_sendTimeout = m_toacknak; m_toKeepaliveSend = new TimeSpan(0, 0, tokeepalive); m_toKeepaliveRecv = new TimeSpan(0, 0, 2*tokeepalive); m_lastConnected = DateTime.Now; }