// -------------------------------------------------------------------- // 接続開始 // -------------------------------------------------------------------- /// <summary> /// 非同期接続を開始します。 /// </summary> /// <remarks> /// 接続パラメータとターミナル設定を作成して、非同期接続を開始します。 /// 接続が成功するとSuccessfullyExit()が呼ばれ、失敗するとConnectionFailed()が呼ばれます。 /// </remarks> public void AsyncConnect() { State = LineState.Connecting; _settings = null; _session = null; _connector = null; // // ターミナルエミュレータサービスとプロトコルサービスを取得します。 // ITerminalEmulatorService terminalEmulatorService = (ITerminalEmulatorService)PoderosaAccessPoint.World.PluginManager.FindPlugin( "org.poderosa.terminalemulator", typeof(ITerminalEmulatorService)); IProtocolService protocolService = (IProtocolService)PoderosaAccessPoint.World.PluginManager.FindPlugin( "org.poderosa.protocols", typeof(IProtocolService)); // // 接続パラメータを作成します。 // ITCPParameter tcpParameter = null; ISSHLoginParameter sshLoginParameter = null; if (LoginProfile.ConnectionMethod == ConnectionParam.ConnectionMethod.Telnet) { // // Telnet接続パラメータの作成 // ※ tcpParameterの実体はTCPParameterクラスのインスタンスです。 // tcpParameter = protocolService.CreateDefaultTelnetParameter(); tcpParameter.Destination = LoginProfile.Host; tcpParameter.Port = LoginProfile.Port; } else { // // SSH接続パラメータの作成 // ※ sshLoginParameterの実体はSSHLoginParameterクラスのインスタンスであり、 // SSHLoginParameterクラスはTCPParameterクラスを継承しています。 // sshLoginParameter = protocolService.CreateDefaultSSHParameter(); sshLoginParameter.Account = LoginProfile.UserName; if (LoginProfile.Password != null && LoginProfile.Password.Length > 0) { IntPtr pswdBytes = Marshal.SecureStringToGlobalAllocAnsi(LoginProfile.Password); sshLoginParameter.PasswordOrPassphrase = Marshal.PtrToStringAnsi(pswdBytes); } if (!String.IsNullOrEmpty(LoginProfile.IdentityFile)) { sshLoginParameter.AuthenticationType = AuthenticationType.PublicKey; sshLoginParameter.IdentityFileName = LoginProfile.IdentityFile; } else { sshLoginParameter.AuthenticationType = AuthenticationType.Password; } sshLoginParameter.Method = (SSHProtocol)Enum.Parse( typeof(SSHProtocol), LoginProfile.ConnectionMethod.ToString("G")); tcpParameter = (ITCPParameter)sshLoginParameter.GetAdapter(typeof(ITCPParameter)); tcpParameter.Destination = LoginProfile.Host; tcpParameter.Port = LoginProfile.Port; } // // ターミナル設定のパラメータをセットします。 // terminalEmulatorService.TerminalEmulatorOptions.RightButtonAction = MouseButtonAction.Paste; _settings = terminalEmulatorService.CreateDefaultTerminalSettings( tcpParameter.Destination, null); _settings.BeginUpdate(); _settings.TerminalType = (ConnectionParam.TerminalType)Enum.Parse( typeof(ConnectionParam.TerminalType), LoginProfile.TerminalType.ToString("G")); _settings.Encoding = LoginProfile.EncodingType; _settings.LocalEcho = LoginProfile.LocalEcho; _settings.TransmitNL = LoginProfile.TransmitNL; _settings.RenderProfile = LoginProfile.ExportRenderProfile(); _settings.EndUpdate(); ITerminalParameter param = (ITerminalParameter)tcpParameter.GetAdapter(typeof(ITerminalParameter)); param.SetTerminalName(_settings.TerminalType.ToString("G").ToLower()); // // 非同期接続開始処理を行います。 // if (LoginProfile.ConnectionMethod == ConnectionParam.ConnectionMethod.Telnet) { #if DEBUG WriteLog("Telnet非同期接続を開始します。"); #endif _connector = protocolService.AsyncTelnetConnect(this, tcpParameter); } else { #if DEBUG WriteLog("SSH非同期接続を開始します。"); #endif _connector = protocolService.AsyncSSHConnect(this, sshLoginParameter); } }
// -------------------------------------------------------------------- // 接続成功 (IInterruptableConnectorClient.SuccessfullyExit) // -------------------------------------------------------------------- /// <summary> /// IInterruptableConnectorClient.SuccessfullyExitのコールバック関数です。 /// </summary> /// <remarks> /// SSH接続もしくはTelnet接続が確立したときに呼ばれます。ターミナル画面を表示するために /// 以下の手順で処理を行います。<br/> /// (1) 新規にPoderosa.Forms.MainWindowを作成します。<br/> /// (2) MainWindow上にビューを作成します。<br/> /// (3) 作成したビュー上でターミナルセッションを開始します。<br/> /// (4) MainWindow上にあるメニューチップとツールチップを非表示にします。<br/> /// (5) ターミナル画面のみが表示されたMainWindowを本コントロール上に載せます。<br/> /// (6) TerminalConnectedイベントを発行します。 /// </remarks> /// <param name="result">Newly-created SSH connection.</param> public void SuccessfullyExit(ITerminalConnection result) { #if DEBUG WriteLog("SuccessfullyExit()が呼び出されました。"); #endif // // 返されたターミナルコネクションがICloseableTerminalConnectionであれば、 // コネクションが切断されたことを通知するイベントが利用できますので、ハンドラを // 設定します。 // ※ SSH接続時はICloseableTerminalConnectionが返されますが、Telnet接続時は返されません。 // ICloseableTerminalConnection closableConnection = result as ICloseableTerminalConnection; if (closableConnection != null) { _isCloseableConnection = true; closableConnection.ConnectionClosed += terminal_ConnectionClosed; closableConnection.ConnectionLost += terminal_ConnectionLost; } else { _isCloseableConnection = false; } // // ウィンドウマネージャを取得します。 // ICoreServices coreServices = (ICoreServices)PoderosaAccessPoint.World.GetAdapter(typeof(ICoreServices)); IWindowManager windowManager = coreServices.WindowManager; // // Invokeメソッドを用いてGUIスレッド上で処理実行させます。 // windowManager.MainWindows.First().AsForm().Invoke(new Action(() => { // // 返されたターミナルコネクションとターミナル設定から、ターミナルセッションを // 作成します。 // _session = new Sessions.TerminalSession(result, _settings); // // Poderosa.Forms.MainWindowを新規に生成し、ビューを作成します。 // IPoderosaMainWindow window = windowManager.CreateNewWindow( new MainWindowArgument(ClientRectangle, FormWindowState.Normal, "", "", 1)); IViewManager viewManager = window.ViewManager; IContentReplaceableView view = (IContentReplaceableView)viewManager.GetCandidateViewForNewDocument().GetAdapter( typeof(IContentReplaceableView)); // // セッションマネージャに新しいターミナルセッションを作成したビュー上で // 開始するように要求します。 // coreServices.SessionManager.StartNewSession(_session, view); // // ターミナルセッションの設定を調整します。 // - サイズチップは表示しません。 // _session.TerminalControl.HideSizeTip = true; // // ビューの親フォームはPoderosa.Forms.MainWindowです。 // MainWindow上にはメニューストリップやツールストリップが載せられていますので、 // ターミナル画面以外の全てを非表示にします。 // Form containerForm = view.ParentForm.AsForm(); foreach (Control control in containerForm.Controls) { if (control is MenuStrip || control.GetType().Name == "PoderosaStatusBar") { control.Visible = false; } else if (control.GetType().Name == "PoderosaToolStripContainer") { foreach (ToolStripPanel child in control.Controls.OfType<ToolStripPanel>()) { child.Visible = false; } foreach (ToolStripContentPanel child in control.Controls.OfType<ToolStripContentPanel>()) { foreach (Control grandChild in child.Controls) { if (grandChild.GetType().Name != "TerminalControl") { grandChild.Visible = false; } } } } } // // ターミナル画面のみが表示されるMainWindowを本コントロール上に載せます。 // containerForm.TopLevel = false; containerForm.FormBorderStyle = FormBorderStyle.None; containerForm.Width = Width; containerForm.Height = Height; containerForm.Dock = DockStyle.Fill; containerForm.Parent = this; // // ビューコントロールのBackColorChangedイベントを捕捉することで、 // Telnet接続時のCtrl-D入力やlogoutコマンドによる切断を検査する契機とします。 // ※ Ctrl-Dを送信した後、ビューコントロールのBackColorChangedイベントは // 2回発生します。1回目はBlackに変わっており、2回目はControlDarkです。 // これにより、表示プロファイルの背景色とかぶっても問題がないと言えます。 // view.AsControl().BackColorChanged += new EventHandler(view_BackColorChanged); view.AsControl().Focus(); })); // // TerminalConnectイベントを発行します。 // State = LineState.Connected; if (TerminalConnected != null) { TerminalConnected(this, new EventArgs()); } }
/// <summary> /// Called when <see cref="IProtocolService.AsyncSSHConnect"/> is able to successfully establish the SSH connection. Creates a new /// <see cref="IPoderosaMainWindow"/> instance and points the newly created connection to a new document instance within that window. We then steal /// the <see cref="IContentReplaceableView"/> terminal window from Poderosa and set its parent to ourself, thus displaying the terminal within this /// control. /// </summary> /// <param name="result">Newly-created SSH connection.</param> public void SuccessfullyExit(ITerminalConnection result) { ICoreServices coreServices = (ICoreServices)_poderosaWorld.GetAdapter(typeof(ICoreServices)); IWindowManager windowManager = coreServices.WindowManager; // Wire up the event handlers on the newly-created connection. (result as ICloseableTerminalConnection).ConnectionClosed += TerminalControl_ConnectionClosed; (result as ICloseableTerminalConnection).ConnectionLost += TerminalControl_ConnectionLost; // We run all of this logic within an Invoke() to avoid trying to do this on the wrong GUI thread windowManager.MainWindows.First().AsForm().Invoke( new Action( () => { // Create a new Poderosa window to contain the connection terminal IPoderosaMainWindow window = windowManager.CreateNewWindow(new MainWindowArgument(ClientRectangle, FormWindowState.Normal, "", "", 1)); IViewManager viewManager = window.ViewManager; Sessions.TerminalSession session = new Sessions.TerminalSession(result, _settings); // Create a new connection window within the Poderosa window, which we will later steal IContentReplaceableView view = (IContentReplaceableView)viewManager.GetCandidateViewForNewDocument().GetAdapter(typeof(IContentReplaceableView)); coreServices.SessionManager.StartNewSession(session, view); session.TerminalControl.HideSizeTip = true; Form containerForm = view.ParentForm.AsForm(); // Hide all of the toolbar and statusbar chrome in the connection window and display only the terminal itself (it's a little // clumsy, I know) foreach (Control control in containerForm.Controls) { if (control is MenuStrip || control.GetType().Name == "PoderosaStatusBar") { control.Visible = false; } else if (control.GetType().Name == "PoderosaToolStripContainer") { foreach (ToolStripPanel child in control.Controls.OfType <ToolStripPanel>()) { child.Visible = false; } foreach (ToolStripContentPanel child in control.Controls.OfType <ToolStripContentPanel>()) { foreach (Control grandChild in child.Controls) { if (grandChild.GetType().Name != "TerminalControl") { grandChild.Visible = false; } } } } } // Steal the terminal view and display it within this control containerForm.TopLevel = false; containerForm.FormBorderStyle = FormBorderStyle.None; containerForm.Width = Width; containerForm.Height = Height; containerForm.Dock = DockStyle.Fill; containerForm.Parent = this; view.AsControl().Focus(); })); // Invoke the Connected event if (Connected != null) { Connected(this, new EventArgs()); } }