入出力ストリームをStreamRelay.NET.exe のプラグインとして実装する方法について説明する
StreamRelay.NET.exe/StreamRelay.NET.x86.exeには、いくつかの機能をプラグインとして実装できるようにインターフェイスを公開している。
今回は、標準入出力(オプションだと「-[Local|Remote]Port 0」の場合)のリダイレクト先のストリームをプラグインのインターフェイスとして公開していて、そのプラグインを作成する方法を記述する。
既存のプラグイン
ファイルから入力/出力とか、マイクから音声入力とか、スピーカーへ音声出力とか、音声認識とか、音声合成とか、名前付きパイプとか、指定されたURLへ送信とかそういうところに使われている。
プラグイン的には、このあたり。
- Plugins\Win32\stdioFileC32.ddl
- Plugins\Win64\stdioFileC64.ddl
- Plugins\Win32\stdioSoundRecordMDX.ddl
- Plugins\Win32\stdioSoundRecordSlimDX.x86.ddl
- Plugins\Win64\stdioSoundRecordSlimDX.x64.ddl
- Plugins\stdioFile.ddl
- Plugins\stdioICMPTunnel.ddl
- Plugins\stdioNamedPipe.ddl
- Plugins\stdioSpeachRecognition.ddl
- Plugins\stdioTCP.ddl
- Plugins\stdioUrl.ddl
- Plugins\stdioUrlWS.ddl
実装したプラグインの呼び出され方
「-[Local|Remote]Port 0」が指定されて、ストリームの物理実体が標準入出力となっている状態で、プラグインで指定された引数が渡されると、標準入出力のリダイレクト先として、プラグインが呼ばれる。
という感じ。
実装するインターフェイス
以下のインターフェイスを継承したクラスを実装すればよい
- IPlugin.dll 中の jp.dip.rocketeer.Plugins.IPluginStdioout インターフェイス
このクラス一つだけ実装すればよい。
jp.dip.rocketeer.Plugins.IPluginStdioout インターフェイス
StreamRelay.NET.exeが、引数/オプションの解析処理中に呼び出して、引数の指定内容によって有効化していれば、
標準入力を置き換える(リダイレクト)する場合は、プロパティ「CanInputStream=true」とする。
標準出力を置き換える(リダイレクト)する場合は、プロパティ「CanOutputStream=true」とする。
そうすると、StreamRelay.NET.exeで、(標準入出力の代わりに)ストリームを開く際に、入力を置き換えた(リダイレクト)場合にはgetInputStream()、出力を置き換えた(リダイレクト)場合には**getOutputStream()**が呼ばれる。
という感じ。
具体的には、起動直後の引数/オプションの解析処理中に、
int Args(String iStr1, String iStr2, String iStr3);
を呼び出すので、自分の引数であれば、プロパティ「CanInputStream=true」または「CanOutputStream=true」にして、使った引数の数を返してくれればよい。
自分の引数でなければ、0を返す。
より、具体的には、
例えば、
c:\>StreamRelay.NET.exe a b c d e f
というコマンドラインで起動したら、
- iStr1=a, iStr2=b, iStr3=c, で、Args() を呼び出し、
- iStr1=b, iStr2=c, iStr3=d, で、Args() を呼び出し、
- iStr1=c, iStr2=d, iStr3=e, で、Args() を呼び出し、
- iStr1=d, iStr2=e, iStr3=f, で、Args() を呼び出し、
- iStr1=e, iStr2=f, iStr3=NULL, で、Args() を呼び出し、
という感じ・・・
例えば、iStr1=b, iStr2=c, iStr3=d, の時、自分の引数ということで、iStr1=b, iStr2=c, を Args() で使用したら、2を返す。すると次は iStr1=d, iStr2=e, iStr3=f, で、Args() が呼び出される。
ということになっている。
Args()の呼ばれ方の留意点
Args()の第一引数の先頭が「-Local」または「-Remote」の場合だけ、Args()は呼び出される。
しかも、先頭の「-Local」または「-Remote」は削られた形で呼び出されるので注意。
より、具体的には、
例えば、
c:\>StreamRelay.NET.exe -LocalStdinRedirect b c d e f
というコマンドラインで起動したら、
1番最初だけ、「StdinRedirect」というように「-Local」または「-Remote」が削られて、結局「StdinRedirect」「b」「c」という引数でArgs()が呼ばれる。
ということになる。
jp.dip.rocketeer.Plugins.IPluginStdioout インターフェイスで定義しているメソッド/プロパティ
実装する必要があるのは以下
jp.dip.rocketeer.Plugins.IPluginStdiooutインターフェイスで定義されているのは、以下のとおり
- String[] usage { get; }
- ヘルプに引数を表示する
- int Args(String iStr1, String iStr2, String iStr3)
- 引数を解析して、自分のものだったかどうかを返す(「名前」「 値」の二つを必要とするバージョン)
第一引数の「-Local」または「-Remote」は削られて渡される - String InputStreamName { get; }
- 現在の状態を表示する(設定を受け取っての状態(Verboseモード時や接続状態の表示時に呼び出される))(入力側)
- String OutputStreamName { get; }
- 現在の状態を表示する(設定を受け取っての状態(Verboseモード時や接続状態の表示時に呼び出される))(出力側)
- Stream getInputStream()
- ストリームを取得する(入力)
サーバ系統の場合(ローカル側で IsServer=True)は、接続ごとにこのメソッドが呼び出されるようなイメージ
よって、呼び出しごとに新規ストリームを返すというようなイメージ - Stream getOutputStream()
- ストリームを取得する(出力)
サーバ系統の場合(ローカル側で IsServer=True)は、接続ごとにこのメソッドが呼び出されるようなイメージ
よって、呼び出しごとに新規ストリームを返すというようなイメージ - Boolean CanInputStream { get; }
- InputStream が利用可能かどうかを示す
- Boolean CanOutputStream { get; }
- OutputStream が利用可能かどうかを示す
- Boolean IsLocal { get; set; }
- ローカルか、リモートか (StreamRelay.NET.exeがセットする)
- UInt32 SleepTime { get; set; }
- スレッドのインターバル(ms) (StreamRelay.NET.exeがセットする)
- UInt32 RecvBufSize { get; set; }
- バッファサイズ (StreamRelay.NET.exeがセットする)
- Encoding InputEncoding { get; set; }
- 文字コード(必要な場合) (StreamRelay.NET.exeがセットする)
- Encoding OutputEncoding { get; set; }
- 文字コード(必要な場合) (StreamRelay.NET.exeがセットする)
- Boolean IsSameStream { get; set; }
- ストリームは入力だけ、出力だけではなくて、入出力の時、True。
True の場合、output 系統のインスタンス側のメソッドは呼び出されない。 - Boolean IsServer { get; set; }
- サーバ(複数クライアントの多重接続)として動作させるかどうか
- Stop()
- サービスとして動作しているような場合の終了処理を記述する
例: ローカルで、TCPサーバとして起動している場合のサーバの停止処理
接続中のストリームの停止処理は、別途しているので、待ち受けサーバの停止処理だけ記述すればよい - void init(PluginManagePublicObj iObj)
- 他のプラグイン(乱数とか文字コードとか)も操作できるオブジェクトを渡す (引数はStreamRelay.NET.exeがセットして呼び出される)
jp.dip.rocketeer.Plugins.IPluginBaseインターフェイスで定義されている分については、インターフェイス IPluginBase についてを参照