Пример #1
0
 public override async Task SendRequest(ReqType reqType, uint seq, byte[] plBuff, int offset, int len)
 {
     try
     {
         if (len > config.CMD_MAX_PLSZ)
         {
             throw new ArgumentException("len > CMD_MAX_PLSZ", nameof(len));
         }
         //write sequence number
         int pos    = config.CMD_HDR_SIZE;
         int seqLen = 0;
         if (seq > 0)
         {
             if (config.CMD_SEQ_SIZE == 4)
             {
                 sendBuff[pos++] = (byte)(seq & 0xFF);
                 sendBuff[pos++] = (byte)((seq >> 8) & 0xFF);
                 sendBuff[pos++] = (byte)((seq >> 16) & 0xFF);
                 sendBuff[pos++] = (byte)((seq >> 24) & 0xFF);
             }
             else
             {
                 throw new Exception("config.CMD_SEQ_SIZE != 4");
             }
             seqLen = config.CMD_SEQ_SIZE;
         }
         else
         {
             len = 0;
         }
         //write payload
         Buffer.BlockCopy(plBuff, offset, sendBuff, pos, len);
         pos        += len;
         sendBuff[0] = (byte)((int)reqType | (len + seqLen + config.CMD_CRC_SIZE));
         //write crc
         int testLen = len + seqLen + config.CMD_HDR_SIZE;
         sendBuff[testLen] = CRC8.Calculate(sendBuff, 0, testLen);
         //send data
         using (var cts = new CancellationTokenSource())
         {
             cts.CancelAfter(UseCommitTimeout?config.COMMIT_TIMEOUT:config.CMD_TIMEOUT);
             await link.WriteAsync(sendBuff, 0, testLen + config.CMD_CRC_SIZE, cts.Token);
         }
     }
     catch (TaskCanceledException ex)
     {
         throw new TimeoutException("SendRequest was timed out", ex);
     }
 }
Пример #2
0
        public override async Task <Answer> ReceiveAnswer()
        {
            try
            {
                int bRead = 0;
                using (var cts = new CancellationTokenSource())
                {
                    cts.CancelAfter(UseCommitTimeout?config.COMMIT_TIMEOUT:config.CMD_TIMEOUT);
                    bRead = await link.ReadAsync(recvBuff, 0, 1, cts.Token);

                    if (bRead != 1)
                    {
                        throw new NotSupportedException("Stream has reached EOF and cannot receive data");
                    }
                }
                int remSz = recvBuff[0] & config.CMD_SIZE_MASK;
                if (remSz < config.CMD_MIN_REMSZ || remSz > config.CMD_MAX_REMSZ)
                {
                    return(Answer.Invalid);
                }
                if (!Enum.TryParse <AnsType>((recvBuff[0] & config.ANS_ALL_MASK).ToString(), out AnsType ans))
                {
                    return(Answer.Invalid);
                }
                //calculate plSize
                var plSize = remSz - config.CMD_CRC_SIZE;
                switch (ans)
                {
                case AnsType.Ok:
                case AnsType.Pong:
                    if (plSize != config.CMD_SEQ_SIZE)
                    {
                        return(Answer.Invalid);
                    }
                    break;

                case AnsType.DataMarker:
                    if (plSize != config.CMD_SEQ_SIZE + 1)
                    {
                        return(Answer.Invalid);
                    }
                    break;

                case AnsType.Data:
                    if (plSize < config.CMD_SEQ_SIZE)
                    {
                        return(Answer.Invalid);
                    }
                    break;

                case AnsType.Resync:
                    break;

                default:
                    return(Answer.Invalid);
                }
                var rem = remSz;
                using (var cts = new CancellationTokenSource())
                {
                    cts.CancelAfter(UseCommitTimeout?config.COMMIT_TIMEOUT:config.CMD_TIMEOUT);
                    while (rem > 0)
                    {
                        rem -= await link.ReadAsync(recvBuff, config.CMD_HDR_SIZE + (remSz - rem), rem, cts.Token);
                    }
                }
                //verify CRC
                var testSz = config.CMD_HDR_SIZE + remSz - 1;
                if (recvBuff[testSz] != CRC8.Calculate(recvBuff, 0, testSz))
                {
                    return(Answer.Invalid);
                }
                //decode sequence number
                uint seq      = 0;
                var  seqPos   = config.CMD_HDR_SIZE;
                int  dataSize = 0;
                if (plSize >= config.CMD_SEQ_SIZE)
                {
                    if (config.CMD_SEQ_SIZE == 4)
                    {
                        seq = unchecked ((uint)(recvBuff[seqPos] | recvBuff[seqPos + 1] << 8 | recvBuff[seqPos + 2] << 16 | recvBuff[seqPos + 3] << 24));
                    }
                    else
                    {
                        throw new Exception("config.CMD_SEQ_SIZE != 4");
                    }
                    dataSize = plSize - config.CMD_SEQ_SIZE;
                }
                var dataPos = (dataSize > 0) ? config.CMD_HDR_SIZE + config.CMD_SEQ_SIZE : 0;
                return(new Answer(ans, seq, recvBuff, dataPos, dataSize));
            }
            catch (Exception ex) when(ex is TaskCanceledException || ex is TimeoutException)
            {
                throw new TimeoutException("ReceiveAnswer was timed out", ex);
            }
        }