public PlainPoderosaSocket(Socket s) { _socket = s; _buf = new byte[ProtocolsPlugin.Instance.ProtocolOptions.SocketBufferSize]; _dataFragment = new ByteDataFragment(_buf, 0, 0); _callbackRoot = new AsyncCallback(RepeatCallback); }
/// <summary> /// /// </summary> /// <param name="host"></param> /// <param name="settings"></param> /// <param name="connection"></param> /// <exclude/> public TerminalTransmission(AbstractTerminal host, ITerminalSettings settings, ITerminalConnection connection) { _host = host; _settings = settings; _connection = connection; _dataForLocalEcho = new ByteDataFragment(); }
public void OnReception(ByteDataFragment data) { ProcessBuffer(data); if (!_parent.IsClosed) { _negotiator.Flush(_parent.RawSocket); } }
//IByteAsuncInputStreamのハンドラで例外が来るとけっこう惨事なのでこの中でしっかりガード private GenericResult OnReceptionCore(ByteDataFragment data) { try { _callback.OnReception(_dataFragment); return(GenericResult.Succeeded); } catch (Exception ex) { RuntimeUtil.ReportException(ex); Close(); return(GenericResult.Failed); } }
public void Transmit(ByteDataFragment data) { if (_monitors != null) { ResetEnumerator(); while (_enumerator.MoveNext()) { _enumerator.Current.Transmit(data); } } _transmitter.Transmit(data); }
public void OnReception(ByteDataFragment data) { if (_monitors != null) { ResetEnumerator(); while (_enumerator.MoveNext()) { _enumerator.Current.OnReception(data); } } _receiver.OnReception(data); }
//CR NUL -> CR 変換および IACからはじまるシーケンスの処理 private void ProcessBuffer(ByteDataFragment data) { int limit = data.Offset + data.Length; int offset = data.Offset; byte[] buf = data.Buffer; //Debug.WriteLine(String.Format("Telnet len={0}, proc={1}", data.Length, _negotiator.InProcessing)); while (offset < limit) { while (offset < limit && _negotiator.InProcessing) { if (_negotiator.Process(buf[offset++]) == TelnetNegotiator.ProcessResult.REAL_0xFF) { _callback.OnReception(_localdata.Set(buf, offset - 1, 1)); } } int delim = offset; while (delim < limit) { byte b = buf[delim]; if (b == 0xFF) { _gotCR = false; _negotiator.StartNegotiate(); break; } if (b == 0 && _gotCR) { _gotCR = false; break; //CR NUL } _gotCR = (b == 0xd); delim++; } if (delim > offset) { _callback.OnReception(_localdata.Set(buf, offset, delim - offset)); //delimの手前まで処理 } offset = delim + 1; } }
/// <summary> /// Thread input from stream /// </summary> /// <param name="asyncInput"></param> private void InputThread(IByteAsyncInputStream asyncInput) { byte[] buff = new byte[4096]; ByteDataFragment _dataFragment = new ByteDataFragment(); try { bool endOfStream = false; while (!_terminateInputThread && !_processExited) { IAsyncResult asyncResult = _inputStream.BeginRead(buff, 0, buff.Length, null, null); while (!_terminateInputThread && !_processExited) { bool signaled = asyncResult.AsyncWaitHandle.WaitOne(500); if (signaled) { int len = _inputStream.EndRead(asyncResult); if (len == 0) { endOfStream = true; goto EndThread; } _dataFragment.Set(buff, 0, len); asyncInput.OnReception(_dataFragment); break; } } } EndThread: if (endOfStream || _processExited) { _skipInputThreadJoin = true; // avoids deadlock Close(); asyncInput.OnNormalTermination(); } } catch (Exception e) { RuntimeUtil.SilentReportException(e); _skipInputThreadJoin = true; // avoids deadlock Close(); asyncInput.OnAbnormalTermination("Input thread error: " + e.Message); } }
public PlainPoderosaSocket(Socket s) { _socket = s; _buf = new byte[ProtocolsPlugin.Instance.ProtocolOptions.SocketBufferSize]; _dataFragment = new ByteDataFragment(_buf, 0, 0); _callbackRoot = new AsyncCallback(RepeatCallback); }
//こっちは非同期であることを確認 public void OnReception(ByteDataFragment data) { Assert.AreNotEqual(Thread.CurrentThread, _mainThread); }
public void Transmit(ByteDataFragment data) { Transmit(data.Buffer, data.Offset, data.Length); }
public void Transmit(ByteDataFragment data) { Transmit(data.Buffer, data.Offset, data.Length); }
/// <summary> /// Implements IPoderosaSocket. /// </summary> public void Transmit(ByteDataFragment data) { // do nothing }
// サーバからの受信データを解析する // Readerクラスから呼ばれる public override void OnReception(ByteDataFragment fragment) { byte[] data = fragment.Buffer; int offset = fragment.Offset; int length = fragment.Length; int i; byte c; Debug.WriteLine(String.Format("OnReception len={0} state={1} pos={2}", length, _state.ToString(), _CurrentPos)); if (_state == State.GetFileInfo) { // ファイル情報を取得する _state = State.WaitingZPAD; ParseFileInfo(data, offset, length); return; } else if (_state == State.GetFileData) { // ファイルの内容を読み取り、書き込む。 int p = ParseFileData(data, offset, length); offset += p; length -= p; } for (i = 0; i < length; i++) { c = data[offset + i]; // 0x11, 0x13, 0x81, 0x83は無視する if ((c & 0x7f) == XON || (c & 0x7f) == XOFF) continue; if (_state == State.WaitingZPAD) { switch (c) { case ZPAD: _state = State.WaitingZDLE; break; default: break; } } else if (_state == State.WaitingZDLE) { switch (c) { case ZPAD: break; case ZDLE: _state = State.GetHeaderFormat; break; default: _state = State.WaitingZPAD; break; } } else if (_state == State.GetHeaderFormat) { switch (c) { case ZBIN: _PktInCount = 7; _state = State.GetBinaryData; break; case ZHEX: _PktInCount = 7; _state = State.GetHexData; break; case ZBIN32: _PktInCount = 9; _state = State.GetBinaryData; break; default: _state = State.WaitingZPAD; break; } // initialize variables _PktInIndex = 0; _HexLo = false; } else if (_state == State.GetBinaryData) // binary('A') data { _PktIn[_PktInIndex++] = c; _PktInCount--; if (_PktInCount <= 0) { _state = State.WaitingZPAD; if (CheckHeader(_PktIn, _PktInCount)) { ParseHeader(); if (_RxType == ZDATA) i += ParseFileData(data, offset + 10, length - 10); else if (_RxType == ZFILE) ParseFileInfo(data, offset + 10, length - 10); } } } else if (_state == State.GetHexData) // HEX('B') data { if (c <= '9') { c -= 0x30; } else if ((c >= 'a') && (c <= 'f')) { c -= 0x57; } else { _state = State.WaitingZPAD; break; // for loop } if (_HexLo) { // lower _PktIn[_PktInIndex] |= c; _PktInIndex++; _HexLo = false; _PktInCount--; if (_PktInCount <= 0) { _state = State.GetHexEOL; _PktInCount = 2; // CRとLFの分をスキップする } } else { // upper _PktIn[_PktInIndex] = (byte)(c << 4); _HexLo = true; } } else if (_state == State.GetHexEOL) { _PktInCount--; if (_PktInCount <= 0) { _state = State.WaitingZPAD; if (CheckHeader(_PktIn, _PktInCount)) { ParseHeader(); } } } } }
public void Transmit(ByteDataFragment data) { _socket.Send(data.Buffer, data.Offset, data.Length, SocketFlags.None); }
//IByteAsuncInputStreamのハンドラで例外が来るとけっこう惨事なのでこの中でしっかりガード private GenericResult OnReceptionCore(ByteDataFragment data) { try { _callback.OnReception(_dataFragment); return GenericResult.Succeeded; } catch (Exception ex) { RuntimeUtil.ReportException(ex); Close(); return GenericResult.Failed; } }
public void RepeatAsyncRead(IByteAsyncInputStream cb) { if (_callback != null) throw new InvalidOperationException("duplicated AsyncRead() is attempted"); _callback = cb; _dataFragment = new ByteDataFragment(); new Thread(new ThreadStart(AsyncEntry)).Start(); //_stream.BeginRead(_buf, 0, _buf.Length, new AsyncCallback(RepeatCallback), null); }
public abstract void OnReception(ByteDataFragment data);
//CR NUL -> CR 変換および IACからはじまるシーケンスの処理 private void ProcessBuffer(ByteDataFragment data) { int limit = data.Offset + data.Length; int offset = data.Offset; byte[] buf = data.Buffer; //Debug.WriteLine(String.Format("Telnet len={0}, proc={1}", data.Length, _negotiator.InProcessing)); while (offset < limit) { while (offset < limit && _negotiator.InProcessing) { if (_negotiator.Process(buf[offset++]) == TelnetNegotiator.ProcessResult.REAL_0xFF) _callback.OnReception(_localdata.Set(buf, offset - 1, 1)); } int delim = offset; while (delim < limit) { byte b = buf[delim]; if (b == 0xFF) { _gotCR = false; _negotiator.StartNegotiate(); break; } if (b == 0 && _gotCR) { _gotCR = false; break; //CR NUL } _gotCR = (b == 0xd); delim++; } if (delim > offset) _callback.OnReception(_localdata.Set(buf, offset, delim - offset)); //delimの手前まで処理 offset = delim + 1; } }
public void OnReception(ByteDataFragment data) { ProcessBuffer(data); if (!_parent.IsClosed) _negotiator.Flush(_parent.RawSocket); }
public TelnetReceiver(TelnetTerminalConnection parent, TelnetNegotiator negotiator) { _parent = parent; _negotiator = negotiator; _localdata = new ByteDataFragment(); }
public void Transmit(ByteDataFragment data) { _receiver.OnReception(data); }
// サーバからの受信データを解析する // Readerクラスから呼ばれる public override void OnReception(ByteDataFragment fragment) { Interlocked.Exchange(ref _lastReceptionTimeUtcTicks, DateTime.UtcNow.Ticks); byte[] data = fragment.Buffer; int offset = fragment.Offset; int length = fragment.Length; //Debug.WriteLine(String.Format("OnReception len={0} state={1}", length, _state.ToString())); if (_state == State.None || _state == State.Error || Volatile.Read(ref _aborting)) { return; } string errorMessage = null; for (int i = 0; i < length; i++) { if (Volatile.Read(ref _aborting)) { return; } byte c = data[offset + i]; // abort sequence detection if (c == CAN) { _canCount++; if (_canCount > 5) { _state = State.None; // don't accept any more ProcessAbortByPeer(); return; } } else { _canCount = 0; } // 0x11, 0x13, 0x81, 0x83は無視する if ((c & 0x7f) == XON || (c & 0x7f) == XOFF) continue; CheckByte: switch (_state) { case State.WaitingZPAD: { switch (c) { case ZPAD: _state = State.WaitingZDLE; break; default: break; } } break; case State.WaitingZDLE: { switch (c) { case ZPAD: break; case ZDLE: _state = State.GetHeaderFormat; break; default: _state = State.WaitingZPAD; break; } } break; case State.GetHeaderFormat: { switch (c) { case ZBIN: //Debug.WriteLine("ZBIN"); _crcType = CRCType.CRC16; _bytesNeeded = 7; _state = State.GetBinaryData; break; case ZHEX: //Debug.WriteLine("ZHEX"); _crcType = CRCType.CRC16; _bytesNeeded = 7; _state = State.GetHexData; break; case ZBIN32: //Debug.WriteLine("ZBIN32"); _crcType = CRCType.CRC32; _bytesNeeded = 9; _state = State.GetBinaryData; break; default: _state = State.WaitingZPAD; break; } // initialize variables _rcvPacketLen = 0; _hexLo = false; _gotZDLE = false; } break; case State.GetBinaryData: { // binary('A') or binary('C') data if (_gotZDLE) { // unescape _rcvPacket[_rcvPacketLen++] = (byte)(c ^ 0x40); _bytesNeeded--; _gotZDLE = false; } else if (c == ZDLE) { _gotZDLE = true; } else { _rcvPacket[_rcvPacketLen++] = c; _bytesNeeded--; _gotZDLE = false; } if (_bytesNeeded <= 0) { _state = State.WaitingZPAD; Header hdr; if (CheckHeader(_crcType, _rcvPacket, _rcvPacketLen, out hdr)) { ProcessHeader(hdr); if (hdr.Type == ZDATA) { _state = State.GetFileData; _rcvPacketLen = 0; _gotZDLE = false; } else if (hdr.Type == ZFILE) { _state = State.GetFileInfo; _rcvPacketLen = 0; _gotZDLE = false; } } } } break; case State.GetHexData: { // HEX('B') data if ((c >= '0') && (c <= '9')) { c -= 0x30; } else if ((c >= 'a') && (c <= 'f')) { c -= 0x57; } else { Debug.WriteLine("Unexpected character in {0}", _state); errorMessage = XZModemPlugin.Instance.Strings.GetString("Message.ZModem.InvalidHeader"); goto Error; } if (_hexLo) { // lower _rcvPacket[_rcvPacketLen++] |= c; _hexLo = false; _bytesNeeded--; if (_bytesNeeded <= 0) { Header hdr; if (CheckHeader(_crcType, _rcvPacket, _rcvPacketLen, out hdr)) { ProcessHeader(hdr); _state = State.GetHexEOL; _bytesNeeded = 2; // CR LF } else { _state = State.WaitingZPAD; } } } else { // upper _rcvPacket[_rcvPacketLen] = (byte)(c << 4); _hexLo = true; } } break; case State.GetHexEOL: { byte cc = (byte)(c & 0x7f); // sz sends { 0x0d, 0x8a } as CR/LF if (cc == 0x0a || cc == 0x0d) { _bytesNeeded--; if (_bytesNeeded <= 0) { _state = State.WaitingZPAD; } } else { _state = State.WaitingZPAD; goto CheckByte; } } break; case State.GetFileInfo: case State.GetFileData: { if (_rcvPacketLen >= _rcvPacket.Length) { Debug.WriteLine("Buffer full in {0}", _state); errorMessage = XZModemPlugin.Instance.Strings.GetString("Message.ZModem.BufferFull"); goto Error; } if (_gotZDLE) { if (c == ZCRCE || c == ZCRCG || c == ZCRCQ || c == ZCRCW) { // end of frame. need CRC bytes. _rcvPacket[_rcvPacketLen++] = c; _gotZDLE = false; _bytesNeeded = (_crcType == CRCType.CRC32) ? 4 : 2; // CRC bytes _state = (_state == State.GetFileInfo) ? State.GetFileInfoCRC : (_state == State.GetFileData) ? State.GetFileDataCRC : State.Error; } else { // unescape _rcvPacket[_rcvPacketLen++] = (byte)(c ^ 0x40); _gotZDLE = false; } } else if (c == ZDLE) { _gotZDLE = true; } else { _rcvPacket[_rcvPacketLen++] = c; _gotZDLE = false; } } break; case State.GetFileInfoCRC: case State.GetFileDataCRC: { if (_rcvPacketLen >= _rcvPacket.Length) { Debug.WriteLine("Buffer full in {0}", _state); errorMessage = XZModemPlugin.Instance.Strings.GetString("Message.ZModem.BufferFull"); goto Error; } if (_gotZDLE) { // unescape _rcvPacket[_rcvPacketLen++] = (byte)(c ^ 0x40); _bytesNeeded--; _gotZDLE = false; } else if (c == ZDLE) { _gotZDLE = true; } else { _rcvPacket[_rcvPacketLen++] = c; _bytesNeeded--; _gotZDLE = false; } if (_bytesNeeded <= 0) { int dataLen = _rcvPacketLen - (_crcType == CRCType.CRC32 ? 5 : 3); if (_state == State.GetFileInfoCRC) { if (CheckCRC(_crcType, _rcvPacket, _rcvPacketLen)) { ParseFileInfo(_rcvPacket, 0, dataLen); _rcvPacketLen = 0; _gotZDLE = false; _state = State.WaitingZPAD; } else { Debug.WriteLine("CRC Error in {0}", _state); errorMessage = XZModemPlugin.Instance.Strings.GetString("Message.ZModem.CRCError"); goto Error; } } else if (_state == State.GetFileDataCRC) { byte frameType = _rcvPacket[dataLen]; //Debug.WriteLine("frameType = 0x{0:x2}", frameType); if (CheckCRC(_crcType, _rcvPacket, _rcvPacketLen)) { ProcessFileData(_rcvPacket, 0, dataLen); _rcvPacketLen = 0; _gotZDLE = false; if (frameType == ZCRCE) { // finished _state = State.WaitingZPAD; } else if (frameType == ZCRCW) { SendACK(); // read next subpacket _state = State.WaitingZPAD; } else { // read next subpacket _state = State.GetFileData; } } else { Debug.WriteLine("CRC Error in {0}", _state); errorMessage = XZModemPlugin.Instance.Strings.GetString("Message.ZModem.CRCError"); goto Error; } } } } break; } } return; Error: _state = State.Error; Abort(errorMessage, false); }
public void OnReception(ByteDataFragment data) { try { bool pass_to_terminal = true; if (_modalTerminalTask != null) { bool show_input = _modalTerminalTask.ShowInputInTerminal; _modalTerminalTask.OnReception(data); if (!show_input) pass_to_terminal = false; //入力を見せない(XMODEMとか)のときはターミナルに与えない } //バイナリログの出力 _logService.BinaryLogger.Write(data); if (pass_to_terminal) { TerminalDocument document = _document; lock (document) { //_invalidateParam.Reset(); //ここから旧Input() _manipulator.Load(GetDocument().CurrentLine, 0); _manipulator.CaretColumn = GetDocument().CaretColumn; _manipulator.DefaultDecoration = _currentdecoration; //処理本体 _decoder.OnReception(data); GetDocument().ReplaceCurrentLine(_manipulator.Export()); GetDocument().CaretColumn = _manipulator.CaretColumn; //ここまで //右端にキャレットが来たときは便宜的に次行の頭にもっていく if (document.CaretColumn == document.TerminalWidth) { document.CurrentLineNumber++; //これによって次行の存在を保証 document.CaretColumn = 0; } CheckDiscardDocument(); AdjustTransientScrollBar(); //現在行が下端に見えるようなScrollBarValueを計算 int n = document.CurrentLineNumber - document.TerminalHeight + 1 - document.FirstLineNumber; if (n < 0) n = 0; //Debug.WriteLine(String.Format("E={0} C={1} T={2} H={3} LC={4} MAX={5} n={6}", _transientScrollBarEnabled, _tag.Document.CurrentLineNumber, _tag.Document.TopLineNumber, _tag.Connection.TerminalHeight, _transientScrollBarLargeChange, _transientScrollBarMaximum, n)); if (IsAutoScrollMode(n)) { _scrollBarValues.Value = n; document.TopLineNumber = n + document.FirstLineNumber; } else _scrollBarValues.Value = document.TopLineNumber - document.FirstLineNumber; //Invalidateをlockの外に出す。このほうが安全と思われた //受信スレッド内ではマークをつけるのみ。タイマーで行うのはIntelliSenseに副作用あるので一時停止 //_promptRecognizer.SetContentUpdateMark(); _promptRecognizer.Recognize(); } if (_afterExitLockActions.Count > 0) { Control main = _session.OwnerWindow.AsControl(); foreach (AfterExitLockDelegate action in _afterExitLockActions) { main.Invoke(action); } _afterExitLockActions.Clear(); } } if (_modalTerminalTask != null) _modalTerminalTask.NotifyEndOfPacket(); _session.NotifyViewsDataArrived(); } catch (Exception ex) { RuntimeUtil.ReportException(ex); } }
public void Transmit(ByteDataFragment data) { _socket.Send(data.Buffer, data.Offset, data.Length, SocketFlags.None); }
public TelnetReceiver(TelnetTerminalConnection parent, TelnetNegotiator negotiator) { _parent = parent; _negotiator = negotiator; _localdata = new ByteDataFragment(); }
//こっちは非同期であることを確認 public void OnReception(ByteDataFragment data) { Assert.AreNotEqual(Thread.CurrentThread, _mainThread); }
public void OnReception(ByteDataFragment data) { //処理本体 byte[] t = data.Buffer; int last = data.Offset + data.Length; int offset = data.Offset; while (offset < last) { ProcessByte(t[offset++]); } }
public void OnReception(ByteDataFragment data) { try { bool pass_to_terminal = true; if (_modalTerminalTask != null) { bool show_input = _modalTerminalTask.ShowInputInTerminal; _modalTerminalTask.OnReception(data); if (!show_input) pass_to_terminal = false; //���͂�����Ȃ�(XMODEM�Ƃ�)�̂Ƃ��̓^�[�~�i���ɗ^���Ȃ� } //�o�C�i�����O�̏o�� _logService.BinaryLogger.Write(data); if (pass_to_terminal) { TerminalDocument document = _document; lock (document) { //_invalidateParam.Reset(); //�������狌Input() _manipulator.Load(GetDocument().CurrentLine, 0); _manipulator.CaretColumn = GetDocument().CaretColumn; _manipulator.DefaultDecoration = _currentdecoration; //�����{�� _decoder.OnReception(data); GetDocument().ReplaceCurrentLine(_manipulator.Export()); GetDocument().CaretColumn = _manipulator.CaretColumn; //�����܂� //�E�[�ɃL�����b�g�������Ƃ��͕X�I�Ɏ��s�̓��ɂ���Ă��� if (document.CaretColumn == document.TerminalWidth) { document.CurrentLineNumber++; //����ɂ���Ď��s�̑��݂�ۏ� document.CaretColumn = 0; } CheckDiscardDocument(); AdjustTransientScrollBar(); //���ݍs�����[�Ɍ�����悤��ScrollBarValue��v�Z int n = document.CurrentLineNumber - document.TerminalHeight + 1 - document.FirstLineNumber; if (n < 0) n = 0; //Debug.WriteLine(String.Format("E={0} C={1} T={2} H={3} LC={4} MAX={5} n={6}", _transientScrollBarEnabled, _tag.Document.CurrentLineNumber, _tag.Document.TopLineNumber, _tag.Connection.TerminalHeight, _transientScrollBarLargeChange, _transientScrollBarMaximum, n)); if (IsAutoScrollMode(n)) { _scrollBarValues.Value = n; document.TopLineNumber = n + document.FirstLineNumber; } else _scrollBarValues.Value = document.TopLineNumber - document.FirstLineNumber; //Invalidate��lock�̊O�ɏo���B���̂ق������S�Ǝv��ꂽ //��M�X���b�h��ł̓}�[�N�����̂݁B�^�C�}�[�ōs���̂�IntelliSense�ɕ���p����̂ňꎞ��~ //_promptRecognizer.SetContentUpdateMark(); _promptRecognizer.Recognize(); } if (_afterExitLockActions.Count > 0) { Control main = _session.OwnerWindow.AsControl(); foreach (AfterExitLockDelegate action in _afterExitLockActions) { main.Invoke(action); } _afterExitLockActions.Clear(); } } if (_modalTerminalTask != null) _modalTerminalTask.NotifyEndOfPacket(); _session.NotifyViewsDataArrived(); } catch (Exception ex) { RuntimeUtil.ReportException(ex); } }
/// <summary> /// Pump thread /// </summary> /// <param name="receiver"></param> private void PumpThread(IByteAsyncInputStream receiver) { lock (_pumpThreadSync) { while (true) { if (_isClosed) break; if (_generator != null) { IEnumerable<byte[]> generator = _generator; _generator = null; _isProcessing = true; foreach (byte[] data in generator) { if (_isClosed) break; ByteDataFragment fragment = new ByteDataFragment(data, 0, data.Length); receiver.OnReception(fragment); } _isProcessing = false; Monitor.PulseAll(_pumpThreadSync); } if (_isClosed) break; Monitor.Wait(_pumpThreadSync); } } }
private void AdjustBuffer(ref ByteDataFragment fragment) { if (_buffer == null || _buffer.Position == 0) return; _buffer.Write(fragment.Buffer, fragment.Offset, fragment.Length); int count = (int)_buffer.Position; _buffer.Close(); fragment.Set(_buffer.ToArray(), 0, count); }
public SSHSocket(SSHTerminalConnection parent) : base(parent) { _data = new ByteDataFragment(); }
public override void OnReception(ByteDataFragment fragment) { if (_state == State.Stopped) { return; } if (_state == State.Aborting) { Send(CAN); Send(CAN); _state = State.Stopped; return; } byte[] data = fragment.Buffer; int offset = fragment.Offset; int length = fragment.Length; byte response; for (int i = 0; i < length; ++i) { byte c = data[offset + i]; if (c == LETTER_C || c == ACK || c == NAK || c == CAN) { response = c; goto GotResponse; } } return; GotResponse: Interlocked.Exchange(ref _lastResponseTimeUtcTicks, DateTime.UtcNow.Ticks); switch (response) { case NAK: Trace("--> NAK"); Resend: if (_state == State.AfterEOT) { Trace("<-- EOT(resend)"); Send(EOT); } else { SendBlock(_crcMode, true); } break; case LETTER_C: Trace("--> C"); _crcMode = true; goto Resend; case ACK: Trace("--> ACK"); if (_state == State.AfterEOT) { _state = State.Stopped; Completed(false, true, XZModemPlugin.Instance.Strings.GetString("Message.XModem.SendComplete")); } else { SendBlock(_crcMode, false); } break; case CAN: Trace("--> CAN"); _state = State.Stopped; Abort(XZModemPlugin.Instance.Strings.GetString("Message.ZModem.Aborted"), false); break; } }
public SSHSocket(SSHTerminalConnection parent) : base(parent) { _data = new ByteDataFragment(); }
public void OnReception(ByteDataFragment data) { }
public override void OnReception(ByteDataFragment fragment) { if (_timer != null) { _timer.Dispose(); _timer = null; } //Debug.WriteLine(String.Format("Received {0}", count)); //_debugStream.Write(data, offset, count); //_debugStream.Flush(); AdjustBuffer(ref fragment); byte[] data = fragment.Buffer; int offset = fragment.Offset; int count = fragment.Length; byte head = data[offset]; if (head == EOT) { //successfully exit SendByte(ACK); _site.MainWindow.Information(XZModemPlugin.Instance.Strings.GetString("Message.XModem.ReceiveComplete")); Complete(); //_debugStream.Close(); } else { int required = 3 + (head == STX ? 1024 : 128) + (_crcEnabled ? 2 : 1); if (required > count) { ReserveBuffer(data, offset, count); //途中で切れていた場合 //Debug.WriteLine(String.Format("Reserving #{0} last={1} offset={2} count={3}", seq, last, offset, count)); return; } byte seq = data[offset + 1]; byte neg = data[offset + 2]; if (seq != _sequenceNumber || seq + neg != 255) { Fail(XZModemPlugin.Instance.Strings.GetString("Message.XModem.SequenceError")); } else { //Debug.WriteLine(String.Format("Processing #{0}", seq)); bool success; int body_offset = offset + 3; int body_len = head == STX ? 1024 : 128; int checksum_offset = offset + 3 + body_len; if (_crcEnabled) { ushort sent = (ushort)((((ushort)data[checksum_offset]) << 8) + (ushort)data[checksum_offset + 1]); ushort sum = CalcCRC(data, body_offset, body_len); success = (sent == sum); } else { byte sent = data[checksum_offset]; byte sum = 0; for (int i = body_offset; i < checksum_offset; i++) sum += data[i]; success = (sent == sum); } _buffer = null; //ブロックごとにACKを待つ仕様なので、もらってきたデータが複数ブロックにまたがることはない。したがってここで破棄して構わない。 if (success) { SendByte(ACK); _sequenceNumber++; int t = checksum_offset - 1; while (t >= body_offset && data[t] == 26) t--; //Ctrl+Zで埋まっているところは無視 int len = t + 1 - body_offset; _outputStream.Write(data, body_offset, len); _processedLength += len; _parent.AsyncSetProgressValue((int)_processedLength); _retryCount = 0; } else { //_debugStream.Close(); if (++_retryCount == 3) { //もうあきらめる Fail(XZModemPlugin.Instance.Strings.GetString("Message.XModem.CheckSumError")); } else { SendByte(NAK); } } } } }
public void Transmit(ByteDataFragment data) { _receiver.OnReception(data); }
public override void OnReception(ByteDataFragment fragment) { if (_timer != null) { _timer.Dispose(); _timer = null; } byte[] data = fragment.Buffer; int offset = fragment.Offset; int count = fragment.Length; if (_negotiating) { for (int i = 0; i < count; i++) { byte t = data[offset + i]; if (t == NAK || t == (byte)'C') { _crcEnabled = t == (byte)'C'; _negotiating = false; _sequenceNumber = 1; _offset = _nextOffset = 0; break; } } if (_negotiating) return; //あたまがきていない } else { byte t = data[offset]; if (t == ACK) { _sequenceNumber++; _retryCount = 0; if (_offset == _body.Length) { //successfully exit _site.MainWindow.Information(XZModemPlugin.Instance.Strings.GetString("Message.XModem.SendComplete")); Complete(); return; } _offset = _nextOffset; } else if (t != NAK || (++_retryCount == 3)) { Fail(XZModemPlugin.Instance.Strings.GetString("Message.XModem.BlockStartError")); return; } } if (_nextOffset >= _body.Length) { //last SendByte(EOT); _offset = _body.Length; } else { int len = 128; if (_crcEnabled && _offset + 1024 <= _body.Length) len = 1024; byte[] buf = new byte[3 + len + (_crcEnabled ? 2 : 1)]; buf[0] = len == 128 ? SOH : STX; buf[1] = (byte)_sequenceNumber; buf[2] = (byte)(255 - buf[1]); int body_len = Math.Min(len, _body.Length - _offset); Array.Copy(_body, _offset, buf, 3, body_len); for (int i = body_len; i < len; i++) buf[3 + i] = 26; //padding if (_crcEnabled) { ushort sum = CalcCRC(buf, 3, len); buf[3 + len] = (byte)(sum >> 8); buf[3 + len + 1] = (byte)(sum & 0xFF); } else { byte sum = 0; for (int i = 0; i < len; i++) sum += buf[3 + i]; buf[3 + len] = sum; } _nextOffset = _offset + len; _connection.Socket.Transmit(buf, 0, buf.Length); _parent.AsyncSetProgressValue(_nextOffset); //Debug.WriteLine("Transmitted "+_sequenceNumber+" " +_offset); } }
public override void OnReception(ByteDataFragment fragment) { Interlocked.Exchange(ref _lastReceptionTimeUtcTicks, DateTime.UtcNow.Ticks); if (_aborting) { return; } byte[] data = fragment.Buffer; int offset = fragment.Offset; int length = fragment.Length; BlockTypeInfo blockInfo; if (_recvLen > 0) { blockInfo = GetBlockTypeInfo(_recvBuff[0], Volatile.Read(ref _mode)); } else { blockInfo = new BlockTypeInfo(); // update later } for (int i = 0; i < length; i++) { byte c = data[offset + i]; if (_recvLen == 0) { if (c == EOT) { Trace("--> EOT"); FlushPendingBuffer(true); Trace("<-- ACK"); Send(ACK); Completed(false, true, XZModemPlugin.Instance.Strings.GetString("Message.XModem.ReceiveComplete")); return; } if (c != SOH && c != STX) { continue; // skip } // determine expected block type blockInfo = GetBlockTypeInfo(c, Volatile.Read(ref _mode)); } _recvBuff[_recvLen++] = c; if (_recvLen >= blockInfo.BlockSize) { goto BlockReceived; } } return; BlockReceived: // a block has been received Interlocked.Exchange(ref _lastBlockTimeUtcTicks, DateTime.UtcNow.Ticks); Trace("--> {0:X2} {1:X2} ...({2})", _recvBuff[0], _recvBuff[1], _recvLen); // check sequence number if (_recvBuff[1] != _nextSequenceNumber || _recvBuff[2] != (255 - _nextSequenceNumber)) { Trace("<-- NAK (bad seq)"); goto Error; } // check CRC or checksum if (blockInfo.HasCRC) { ushort crc = Crc16.Update(Crc16.InitialValue, _recvBuff, blockInfo.DataOffset, blockInfo.DataLength); int crcIndex = blockInfo.DataOffset + blockInfo.DataLength; if (_recvBuff[crcIndex] != (byte)(crc >> 8) || _recvBuff[crcIndex + 1] != (byte)crc) { // CRC error Trace("<-- NAK (CRC error)"); goto Error; } } else { byte checksum = 0; int index = blockInfo.DataOffset; for (int n = 0; n < blockInfo.DataLength; ++n) { checksum += _recvBuff[index++]; } if (_recvBuff[index] != checksum) { // checksum error Trace("<-- NAK (checksum error)"); goto Error; } } // ok _nextSequenceNumber++; FlushPendingBuffer(false); SaveToPendingBuffer(_recvBuff, blockInfo.DataOffset, blockInfo.DataLength); _errorCount = 0; _recvLen = 0; Send(ACK); return; Error: _recvLen = 0; _errorCount++; if (_errorCount > MAX_ERROR) { Abort(XZModemPlugin.Instance.Strings.GetString("Message.XModem.CouldNotReceiveCorrectData"), false); } else { Send(NAK); } }