netpipe -- サーバー同士をsocket接続できる自己修復型ネットワーク仮想ケーブル(ADSB用)

なんだその長い表題?! 以下の絵のようなものです。何もしないタダのソケット配線、です、特徴はタダ切れにくいだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/5214f409-97ef-abea-662c-b145412f27e2.png)
ADSBの人なら何に使うかわかるはず。
この記事には以下の内容が含まれています。

+ ADSBにかなり特化した信号処理系プログラムでのソケットの利用のお話
+ netpipe(上図)を ADSB用に作ったよという紹介、ダウンロード可能

# 信号処理プログラムにはソケット通信が便利
うんちくです。少し長いので絵だけ見てもらってもよいかも。
### OSのパイプ
OSをかじっていると、パイプという概念に出会います。処理Aの出力を処理Bにつなぐ。色んな種類の処理を部品(プログラム)として準備しておけば、プログラムを書き換えなくても処理をつなぎ変えると即座にやりたいことができる。というわけです。そもそも異なる専門分野のプログラムを一つにまとめるのはムリです。得意なプログラムに得意な分野を任せるというのは大変良い考え方です。

```shell
$ progA | progB
```
大抵の処理は順番に行うだけで済みます。ところが、出力が2つだったり、入力が2つだったりする処理もでてくると、パイプだけでは間に合わず、ネームドパイプというのを使います。でも使い勝手が悪すぎて、パイプの爽快感はもう無くなってしまいます。

### 信号処理とソケット通信
信号処理には通常終わり(EOF)がありません。多くのソフトは終わりのあるデータを扱うので逐次処理ができますが、信号処理の場合は電気回路の回路図のように、ブロック図で流れを描く必要があります。各処理部品は記号や箱で表現され複数の入力や出力があり、処理は網の目状につながりループ状に戻ることもあります。この部品間の「配線」をソケット接続でやりましょうという考え方があるのです。私も最近 SDR/ADSBの世界に入ってからこの考え方を知りました。ソケット接続は本来は別のPCとの通信などに使うものですが、信号処理に使う場合には同じPC内でソケット接続を使います。なんて贅沢なんでしょう、でも便利ですよ。

# ソケット通信
一番身近なソケット接続は Webです。Webサービスに、ブラウザのクライアントがソケット接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/5bbadfca-c84e-0c51-434e-b870c27eb64f.png)
ソケット接続はオーディオのプラグとジャックのような関係です。サーバーは自分の固有のジャック番号(port)を持っていて待ち受け(listen)しています。クライアントはプラグを持っていてジャックに挿す(connect)ことでソケット接続が完了します。
オーディオと異なるのは1個のジャックに複数のプラグを挿せることです。
\# BLMで業界用語も見直しを迫られてますが、プラグとジャックは大丈夫かな。

### ADSBでのソケット通信
やっと本題です。SDRはソフトウェアラジオですから、処理はソフトウェアです。一つのアプリにまとめるという考えもありますが、部品毎にプログラムが分かれていると前述のように組みなおしに便利です。[flightaware](https://flightaware.com/)とつないで RPiでADSB受信している人はソケットがこんな風に接続されています。サーバーから見ると世界規模で受信機と信号処理のネットワークが出来ていることになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/85b21c04-264e-5b7b-8fd1-e281790368d4.png)

機能毎にプログラムが別なので、以下の様な応用も簡単にできます。受信機と dump1090は共通で、[RadarBox](https://www.radarbox.com/)への配信用のフィーダーのみを追加しソケットで簡単に配線することができます。受信機を複数準備必要もなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/ec01fbd4-75d7-f874-428b-725ae09b11bc.png)

### ソケットとパイプの接続 netcat(nc)
netcatは、このソケット通信とパイプを相互に橋渡しできるプログラムです。nc とも言います。これを使うとパイプ処理を前提としたプログラムでも改造することなく簡単にソケット通信ネットワークに参加させることができます。最も簡単な、何もしないタダの配線の例を示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/972b03d0-2ae3-18c8-c904-59c2739dfb51.png)
[ADSBHub](https://www.adsbhub.org/) の場合、フィーダープログラムの中身はスクリプトになっていて、ncが上図の様に何も処理を挟まないで使われています。コードで書くと以下です。このパイプの間になにか処理を挟むこともできます。

```
nc localhost 30002 | nc data.adsbhub.org 5001
```

一見便利でうまく行きそうなのですが、私の場合、localhostそのものの再起動や、dump1090のみの再起動したり、そしてwifiの不調など原因はわからないですが、よく [ADSBHub](https://www.adsbhub.org/)への配信が止まってしまうことがありました。大手各社が自前でプログラムを提供しているのはこのあたりの理由もあるかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/bd97daba-6e6f-20fc-bba2-2c143414e320.png)
実際の詳細な記述は以下のようになっています。ncは接続が切れると終了します。スクリプトではこの文が終了すると一定時間後に再度呼ばれるように記載されています。

```
nc -w 60 -q 10 localhost 30002 | nc -w 60 -q 10 data.adsbhub.org 5001
```
オプションなどを指定して色々小細工されているのですが、おろらくこの文が終了することなく通信が途切れる条件があるんでしょう。また、入力側か出力側の片側が切断しただけでパイプが壊れて両側が切れるので、誘爆の如くどこかで発生した異常が他のプログラムにも伝搬して問題が起きるのかもしれません。

# netpipeの紹介
netpipeは 自己修復型パイプ(ソケット接続)です。要するにプラグ-プラグ型のオーディオケーブルですね。
試行錯誤の挙句、よい方法が思いつかなかったので、このプログラムを新規で作成することにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/773e02b6-f4be-d413-d747-06e17300d746.png)
もちろん自動再接続の機能つきです。両側のソケット接続それぞれに対して、切断を検知すると一定時間後に再接続します。異常の伝搬(誘爆?)を防ぐために、異常のない側のソケットは接続したままにします。また、起動時に接続先の準備がまだ出来てなくても待つようにしたので、起動順序の問題にも悩まされません。

```
$ sudo vi /usr/bin/adsbhub.sh
   :
cmd="netpipe -c 3 localhost 31002 data.adsbhub.org 5001"
#cmd="nc -w 60 -q 10 localhost 30002 | nc -w 60 -q 10 data.adsbhub.org 5001"
   :
```
ADSBHubのスクリプトは上記のように修正します。-c 3 は、3回リトライ後にプログラムを終了する意味です。グローバルIPアドレスが変わった場合の処理がこの後のスクリプトに記載されているので、適度に制御を回すためです。
-c 3 が無ければ、netpipeは 自己修復しながら永遠に動き続けます。

その一例として、VRS-Japanを紹介しておきます。
### VRS-Japanへのフィードでの使用
国内中心の VRS-Japanへのフィードも行っていますが、それは以下の記述一行のみです。すごくシンプル。

```
netpipe localhost 30005 (URL_of_VRS-Japan) (port)
```
(アドレス等は非公開なので伏字にしています。)
\# VRS-Japan は [Twitter @Aris_AirForce](https://twitter.com/Aris_AirForce) さんが運営されています。刻々とTweetされる情報と合わせて興味深い機体の情報が得られます。興味がある方はフォロー/コンタクトしてみてください。


# netpipeのインストールと使い方
欲しい人がいるのかどうかは不明ですが、debian packageの作り方にも興味があったのでバイナリーのみ公開してみました。armhfのバイナリーなので RPiならどれでも動くと思います。作成は buster で行いました。

```
$ wget https://github.com/y05s/netpipe/blob/master/netpipe_0.01-20200724_armhf.deb
$ sudo dpkg -i netpipe_0.01-20200724_armhf.deb
```
万が一他のアーキテクチャのバイナリーが欲しい方が居れば [twitter](https://twitter.com/4dso "4dso")などでご連絡ください。

使い方は以下です。countはプログラム終了までのリトライ回数でデフォルトが0で無限、timeoutは再接続までの秒数でデフォルトは60です。

```
$ netpipe {-c count} {-t timeout} host_in port_in host_out port_out
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651488/5214f409-97ef-abea-662c-b145412f27e2.png)