예제 #1
0
 public void Receive(byte[] data, int offset, int length)
 {
     if (_receiver != null)
     {
         _receiver.OnReception(new ByteDataFragment(data, offset, length));
     }
 }
예제 #2
0
        //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;
            }
        }
예제 #3
0
        //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);
            }
        }
예제 #4
0
        /// <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);
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
 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);
         }
     }
 }
예제 #7
0
        /// <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);
                }
            }
        }
예제 #8
0
 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;
         }
     }
 }
예제 #9
0
 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;
         }
     }
 }
 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;
         }
     }
 }
예제 #11
0
        /// <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);
                }
            }
        }
예제 #12
0
 public void Transmit(ByteDataFragment data)
 {
     _receiver.OnReception(data);
 }
예제 #13
0
 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;
         }
     }
 }
예제 #14
0
        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();
                }
            }
        }
예제 #15
0
        /// <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);
            }
        }
예제 #16
0
 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);
         }
     }
 }