0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

フィルタストリームをプラグインとして実装する方法

Last updated at Posted at 2021-04-23

フィルタストリームをStreamRelay.NET.exe のプラグインとして実装する方法について説明する

StreamRelay.NET.exe/StreamRelay.NET.x86.exeには、いくつかの機能をプラグインとして実装できるようにインターフェイスを公開している。

今回は、フィルタストリーム(ストリームを受け取ってストリームを返すストリーム)をStreamRelay.NET.exeから呼び出させるインターフェイスを使って、プラグインを作成する方法を記述する。


既存のプラグイン

圧縮ストリームとか、BASExx系の変換ストリームとか、そういうものを既存として作った。

プラグイン的には、このあたり。

  • Plugins\Plugin.7zip.dll
  • Plugins\Plugin.BaseFilterStream.dll
  • Plugins\Plugin.BouncyCastle.Crypto.dll
  • Plugins\Plugin.Brotli.dll
  • Plugins\Plugin.CSharpCode.SharpZipLib.dll
  • Plugins\Plugin.LZ4.dll
  • Plugins\Plugin.sEncoding.dll
  • Plugins\Plugin.Snappy.dll
  • Plugins\Plugin.xz.dll
  • Plugins\Plugin.zlib.NET.dll
  • Plugins\Win32\Plugin.Zopfli.x86.dll
  • Plugins\Win64\Plugin.Zopfli.x64.dll
  • Plugins\Plugin.ZstdNet.dll

実装したプラグインの呼び出され方

-[Local/Remote]Proxy オプションのnetstreamスキームの引数として渡された引数に応じて、ストリームを包んだりする

という感じ。


実装するインターフェイス

以下のインターフェイスを継承したクラスを実装すればよい

  • IPlugin.dll 中の jp.dip.rocketeer.Plugins.IPluginFilterStreamEntity インターフェイス
  • IPlugin.dll 中の jp.dip.rocketeer.Plugins.IPluginFilterStream インターフェイス

このクラス一つだけ実装すればよい。


jp.dip.rocketeer.Plugins.IPluginFilterStreamEntity インターフェイス

StreamRelay.NET.exeから、引数/オプションの解析処理中に呼び出して、引数の指定内容によって、IPluginFilterStreamEntityを返す。
すると、IPluginFilterStreamEntityから、Streamを包んでStreamを返すものを呼び出したりする。

という感じ。

例えば

-RemoteProxy netstream:///?GzipCompress=lv1&GzipDeCompress

という引数の「GzipCompress」とか「GzipDeCompress」というのが、IPluginFilterStreamEntity CreateFilterStreamEntity(String name, String value, PluginManagePublicObj iObj, ref String errMsg) の「name」に渡されるので、自分の引数であれば、IPluginFilterStreamEntityオブジェクトを返してほしい。

ちなみに「value」には「name=GzipCompress」時には「lv1」が、「name=GzipDeCompress」時には「null」が渡される感じ。

そしてストリームの生成時に、IPluginFilterStreamEntity#CreateStream(Stream)
が呼ばれるので、ストリームを包んでくれればよい。


jp.dip.rocketeer.Plugins.IPluginFilterStreamEntity インターフェイスで定義しているメソッド/プロパティ

実装する必要があるのは以下

jp.dip.rocketeer.Plugins.IPluginFilterStreamEntityインターフェイスで定義されているのは、以下のとおり

Boolean IsInput { get; set; }
実装内容が InputStream なのか OutputStream なのか
InOutStream CreateStream(Stream baseStream)
フィルタストリームを返す(マルチスレッドを考慮した実装をしてほしい)
String ArgorithmName()
フィルタ内容(圧縮アルゴリズム名とか)を返す

jp.dip.rocketeer.Plugins.IPluginFilterStream インターフェイスで定義しているメソッド/プロパティ

実装する必要があるのは以下

jp.dip.rocketeer.Plugins.IPluginFilterStreamインターフェイスで定義されているのは、以下のとおり

Dictionary ListDescription()
引数文字列などを返す
IPluginFilterStreamEntity CreateFilterStreamEntity(String name, String value, PluginManagePublicObj iObj, ref String errMsg)
名称から FilterStream オブジェクトの実体を作成する。不適切な名称(他のプラグイン呼び出しとかなので)ならnullを返す

jp.dip.rocketeer.Plugins.IPluginBaseインターフェイスで定義されている分については、インターフェイス IPluginBase についてを参照


jp.dip.rocketeer.Plugins.InOutStream クラス

jp.dip.rocketeer.Plugins.InOutStream クラスは、既存の圧縮ストリームとか、暗号ストリームが双方向ストリームではないので、双方向化するためにラップされたストリーム。

例えば、インプットとして設定された圧縮ストリームに、アウトプット(Write)しようとするとエラーとなるので、そういうのをスルーして上位ストリームへ渡したりしてくれるストリーム。
(StreamRelay.NET.exeは、双方向ストリームを前提としているので)

なんとなくのなんちゃってコードだとこんな感じ

public class exampleFilter : IPluginFilterStreamEntity{
// 例えば、何か圧縮するストリームだとする。
CompressStream compressStream;

InOutStream CreateStream(Stream baseStream){
	// baseStreamストリームを包む
	// 例えば、何かを圧縮するストリームを生成する
        compressStream = new CompressStream(baseStream);

	// 何かを圧縮するストリームを包んだInOutStream(System.IO.Stream)を返す
	// 入力側は圧縮するのでcompressStreamだけど、
	// 出力側は圧縮しないのでbaseStreamそのままを引数に与える
	return new InOutStream(compressStream, baseStream);
}}

みたいな感じで InOutStreamを生成して、返してほしい。


目次へ戻る

目次というか最初の一歩

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?