public void Receive(byte[] data, int offset, int length) { if (_receiver != null) { _receiver.OnReception(new ByteDataFragment(data, offset, length)); } }
//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; } }
//IByteAsyncInputStream‚̃nƒ“ƒhƒ‰‚Å—áŠO‚ª—ˆ‚é‚Æ‚¯‚Á‚±‚¤ŽSŽ–‚È‚Ì‚Å‚±‚Ì’†‚Å‚µ‚Á‚©‚èƒK[ƒh private GenericResult OnReceptionCore(ByteDataFragment data) { try { _callback.OnReception(_dataFragment); return(GenericResult.Succeeded); } catch (Exception ex) { RuntimeUtil.ReportException(ex); Close(); return(GenericResult.Failed); } }
/// <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 void OnData(DataFragment data) { lock (_outputSync) { if (_output == null) { if (_buffer != null) { _buffer.Write(data.Data, data.Offset, data.Length); } return; } _dataFragment.Set(data.Data, data.Offset, data.Length); _output.OnReception(_dataFragment); } }
public void SetReceptionHandler(IByteAsyncInputStream output) { lock (_outputSync) { if (_output != null) { return; } _output = output; if (_buffer != null && _buffer.Length > 0) { byte[] bytes = _buffer.ToArray(); _buffer.Dispose(); _buffer = null; _dataFragment.Set(bytes, 0, bytes.Length); _output.OnReception(_dataFragment); } } }
/// <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); } } }
public void RepeatAsyncRead(IByteAsyncInputStream cb) { _callback = cb; //バッファに何がしか溜まっている場合: //NOTE これは、IPoderosaSocket#StartAsyncReadを呼ぶシーケンスをなくし、接続を開始する瞬間(IProtocolServiceのメソッド系)から //データ本体を受信する口を提供させるようにすれば除去できる。しかしプログラマの側としては、接続成功を確認してからデータ受信口を用意したいので、 //(Poderosaでいえば、ログインボタンのOKを押す時点でAbstractTerminalまで準備せねばならないということ)、それよりはデータを保留しているほうがいいだろう if (_buffer != null) { lock (this) { _buffer.Close(); byte[] t = _buffer.ToArray(); _data.Set(t, 0, t.Length); if (t.Length > 0) { _callback.OnReception(_data); } _buffer = null; } } }
public void RepeatAsyncRead(IByteAsyncInputStream cb) { _callback = cb; //ƒoƒbƒtƒ@‚ɉ½‚ª‚µ‚©—‚Ü‚Á‚Ä‚¢‚éê‡F //NOTE ‚±‚ê‚ÍAIPoderosaSocket#StartAsyncRead‚ðŒÄ‚ÔƒV[ƒPƒ“ƒX‚ð‚È‚‚µAÚ‘±‚ðŠJŽn‚·‚éuŠÔ(IProtocolService‚̃ƒ\ƒbƒhŒn)‚©‚ç //ƒf[ƒ^–{‘Ì‚ðŽóM‚·‚éŒû‚ð’ñ‹Ÿ‚³‚¹‚é‚悤‚É‚·‚ê‚Îœ‹Ž‚Å‚«‚éB‚µ‚©‚µƒvƒƒOƒ‰ƒ}‚Ì‘¤‚Æ‚µ‚Ä‚ÍAÚ‘±¬Œ÷‚ðŠm”F‚µ‚Ä‚©‚çƒf[ƒ^ŽóMŒû‚ð—pˆÓ‚µ‚½‚¢‚Ì‚ÅA //iPoderosa‚Å‚¢‚¦‚ÎAƒƒOƒCƒ“ƒ{ƒ^ƒ“‚ÌOK‚ð‰Ÿ‚·Žž“_‚ÅAbstractTerminal‚Ü‚Å€”õ‚¹‚˂΂Ȃç‚È‚¢‚Æ‚¢‚¤‚±‚ÆjA‚»‚ê‚æ‚è‚̓f[ƒ^‚ð•Û—¯‚µ‚Ä‚¢‚é‚Ù‚¤‚ª‚¢‚¢‚¾‚낤 if (_buffer != null) { lock (this) { _buffer.Close(); byte[] t = _buffer.ToArray(); _data.Set(t, 0, t.Length); if (t.Length > 0) { _callback.OnReception(_data); } _buffer = null; } } }
public void RepeatAsyncRead(IByteAsyncInputStream cb) { _callback = cb; //�o�b�t�@�ɉ����������܂��Ă���ꍇ�F //NOTE ����́AIPoderosaSocket#StartAsyncRead��ĂԃV�[�P���X��Ȃ����A�ڑ���J�n����u��(IProtocolService�̃��\�b�h�n)���� //�f�[�^�{�̂��M������������悤�ɂ���Ώ����ł���B�������v���O���}�̑��Ƃ��ẮA�ڑ�������m�F���Ă���f�[�^��M����p�ӂ������̂ŁA //�iPoderosa�ł����A���O�C���{�^����OK��������_��AbstractTerminal�܂ŏ������˂Ȃ�Ȃ��Ƃ������Ɓj�A������̓f�[�^��ۗ����Ă���ق����������낤 if (_buffer != null) { lock (this) { _buffer.Close(); byte[] t = _buffer.ToArray(); _data.Set(t, 0, t.Length); if (t.Length > 0) _callback.OnReception(_data); _buffer = null; } } }
/// <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); } } }
public void Transmit(ByteDataFragment data) { _receiver.OnReception(data); }
public void RepeatAsyncRead(IByteAsyncInputStream cb) { _callback = cb; //バッファに何がしか溜まっている場合: //NOTE これは、IPoderosaSocket#StartAsyncReadを呼ぶシーケンスをなくし、接続を開始する瞬間(IProtocolServiceのメソッド系)から //データ本体を受信する口を提供させるようにすれば除去できる。しかしプログラマの側としては、接続成功を確認してからデータ受信口を用意したいので、 //(Poderosaでいえば、ログインボタンのOKを押す時点でAbstractTerminalまで準備せねばならないということ)、それよりはデータを保留しているほうがいいだろう if (_buffer != null) { lock (this) { _buffer.Close(); byte[] t = _buffer.ToArray(); _data.Set(t, 0, t.Length); if (t.Length > 0) _callback.OnReception(_data); _buffer = null; } } }
private void AsyncEntry() { const int EV_RXCHAR = 1; ManualResetEvent commEventOverlappedEvent = null; ManualResetEvent readOverlappedEvent = null; try { commEventOverlappedEvent = new ManualResetEvent(false); readOverlappedEvent = new ManualResetEvent(false); NativeOverlapped commEventOverlapped = new NativeOverlapped(); commEventOverlapped.EventHandle = commEventOverlappedEvent.SafeWaitHandle.DangerousGetHandle(); NativeOverlapped readOverlapped = new NativeOverlapped(); readOverlapped.EventHandle = readOverlappedEvent.SafeWaitHandle.DangerousGetHandle(); GCHandle commEventOverlappedPinned = GCHandle.Alloc(commEventOverlapped, GCHandleType.Pinned); // Pin a boxed NativeOverlapped GCHandle readOverlappedPinned = GCHandle.Alloc(readOverlapped, GCHandleType.Pinned); // Pin a boxed NativeOverlapped int commFlags = 0; GCHandle commFlagsPinned = GCHandle.Alloc(commFlags, GCHandleType.Pinned); // Pin a boxed Int32 int readLength = 0; GCHandle readLengthPinned = GCHandle.Alloc(readLength, GCHandleType.Pinned); // Pin a boxed Int32 int transferredLength = 0; GCHandle transferredLengthPinned = GCHandle.Alloc(transferredLength, GCHandleType.Pinned); // Pin a boxed Int32 byte[] buf = new byte[128]; GCHandle bufPinned = GCHandle.Alloc(buf, GCHandleType.Pinned); // Note: // GCHandle.Alloc(<struct>, GCHandleType.Pinned) makes a GCHandle for `Boxed' struct object. // So if you want to read a value of the struct, you have to read it from `Boxed' struct object // which is returned by GCHandle.Target. try { bool success = false; success = Win32Serial.ClearCommError(_fileHandle, IntPtr.Zero, IntPtr.Zero); if (!success) { throw new Exception("ClearCommError failed " + Marshal.GetLastWin32Error()); } //このSetCommMaskを実行しないとWaitCommEventが失敗してしまう success = Win32Serial.SetCommMask(_fileHandle, 0); if (!success) { throw new Exception("SetCommMask failed " + Marshal.GetLastWin32Error()); } success = Win32Serial.SetCommMask(_fileHandle, EV_RXCHAR); if (!success) { throw new Exception("SetCommMask failed " + Marshal.GetLastWin32Error()); } while (true) { commFlags = 0; commFlagsPinned.Target = commFlags; // Pin a new boxed Int32 transferredLength = 0; transferredLengthPinned.Target = transferredLength; // Pin a new boxed Int32 commEventOverlappedPinned.Target = commEventOverlapped; // Pin a new boxed NativeOverlapped success = Win32Serial.WaitCommEvent( _fileHandle, commFlagsPinned.AddrOfPinnedObject(), commEventOverlappedPinned.AddrOfPinnedObject()); if (!success) { int lastErr = Marshal.GetLastWin32Error(); if (lastErr == Win32.ERROR_INVALID_HANDLE) { goto CLOSED; // closed in another thread ? } if (lastErr != Win32.ERROR_IO_PENDING) { throw new Exception("WaitCommEvent failed " + lastErr); } success = Win32Serial.GetOverlappedResult( _fileHandle, commEventOverlappedPinned.AddrOfPinnedObject(), transferredLengthPinned.AddrOfPinnedObject(), true); if (!success) { lastErr = Marshal.GetLastWin32Error(); if (lastErr == Win32.ERROR_INVALID_HANDLE || lastErr == Win32.ERROR_OPERATION_ABORTED) { goto CLOSED; // closed in another thread ? } throw new Exception("GetOverlappedResult failed " + lastErr); } } if ((int)commFlagsPinned.Target != EV_RXCHAR) { goto CLOSED; } while (true) { readLength = 0; readLengthPinned.Target = readLength; // Pin a new boxed Int32 transferredLength = 0; transferredLengthPinned.Target = transferredLength; // Pin a new boxed Int32 readOverlappedPinned.Target = readOverlapped; // Pin a new boxed NativeOverlapped success = Win32Serial.ReadFile( _fileHandle, bufPinned.AddrOfPinnedObject(), buf.Length, readLengthPinned.AddrOfPinnedObject(), readOverlappedPinned.AddrOfPinnedObject()); if (!success) { int lastErr = Marshal.GetLastWin32Error(); if (lastErr == Win32.ERROR_INVALID_HANDLE) { goto CLOSED; // closed in another thread ? } if (lastErr != Win32.ERROR_IO_PENDING) { throw new Exception("ReadFile failed " + lastErr); } success = Win32Serial.GetOverlappedResult( _fileHandle, readOverlappedPinned.AddrOfPinnedObject(), transferredLengthPinned.AddrOfPinnedObject(), true); if (!success) { lastErr = Marshal.GetLastWin32Error(); if (lastErr == Win32.ERROR_INVALID_HANDLE || lastErr == Win32.ERROR_OPERATION_ABORTED) { goto CLOSED; // closed in another thread ? } throw new Exception("GetOverlappedResult failed " + lastErr); } readLength = (int)transferredLengthPinned.Target; // copy from pinned `boxed' Int32 } else { readLength = (int)readLengthPinned.Target; // copy from pinned `boxed' Int32 } if (readLength <= 0) { break; } _dataFragment.Set(buf, 0, readLength); _callback.OnReception(_dataFragment); } } } finally { commEventOverlappedPinned.Free(); readOverlappedPinned.Free(); commFlagsPinned.Free(); readLengthPinned.Free(); transferredLengthPinned.Free(); bufPinned.Free(); } CLOSED: ; } catch (Exception ex) { if (!_parent.IsClosed) { _callback.OnAbnormalTermination(ex.Message); } } finally { if (commEventOverlappedEvent != null) { commEventOverlappedEvent.Close(); } if (readOverlappedEvent != null) { readOverlappedEvent.Close(); } } }
/// <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 void SetReceptionHandler(IByteAsyncInputStream output) { lock (_outputSync) { if (_output != null) { return; } _output = output; if (_buffer != null && _buffer.Length > 0) { byte[] bytes = _buffer.ToArray(); _buffer.Dispose(); _buffer = null; _dataFragment.Set(bytes, 0, bytes.Length); _output.OnReception(_dataFragment); } } }