shairport-sync-metadata-reader が、重かったので何とかしたお話

# CPU負荷対策的な
以下の記事の続きですー。
https://qiita.com/eucalyhome/items/731d38655fdb3f3cad91
https://qiita.com/eucalyhome/items/b2e2374db6e580186987

無事実装を終え。
なんとなしにtopしたら。
![npi_sht.png](https://qiita-image-store.s3.amazonaws.com/0/216885/e1a5f533-b351-1286-14fe-c546d1d865f1.png)

なんですって！？。
CPU、貼り付けてますやん・・・。

なのでまあ、どうにかしようかと。

# 解析
まず、shairport-syncのパイプを観察。
catで見てみましょうか。

```
root@nanopineo:/data/airplay_control#cat /ramdisk/shairport-sync-metadata
<item><type>73736e63</type><code>666c7372</code><length>10</length>
<data encoding="base64">
MzExMDc2MzExMg==</data></item>
<item><type>73736e63</type><code>70666c73</code><length>0</length></item>
<item><type>73736e63</type><code>70656e64</code><length>0</length></item>
<item><type>73736e63</type><code>636c6970</code><length>14</length>
<data encoding="base64">
MTkyLjE2OC4yNC4yMjE=</data></item>
<item><type>73736e63</type><code>73766970</code><length>14</length>
<data encoding="base64">
MTkyLjE2OC4yNC4xMDI=</data></item>
<item><type>73736e63</type><code>736e7561</code><length>89</length>
<data encoding="base64">
aVR1bmVzLzEyLjcuMSAoV2luZG93czsgTWljcm9zb2Z0IFdpbmRvd3MgMTAgeDY0IFByb2Zlc3Npb25hbCBFZGl0aW9uIChCdWlsZCAxNjI5OSk7IHg2NCk=</data></item>
<item><type>73736e63</type><code>61637265</code><length>10</length>
<data encoding="base64">
MzUwMDE0NDAxMw==</data></item>
<item><type>73736e63</type><code>64616964</code><length>16</length>
<data encoding="base64">
REFBQkRBNDlDQTBFRkE4Ng==</data></item>
<item><type>73736e63</type><code>70626567</code><length>0</length></item>
<item><type>73736e63</type><code>70666c73</code><length>0</length></item>
<item><type>73736e63</type><code>70766f6c</code><length>21</length>
<data encoding="base64">
MC4wMCwwLjAwLC05Ni4zMCwwLjAw</data></item>
<item><type>73736e63</type><code>70766f6c</code><length>21</length>
<data encoding="base64">
MC4wMCwwLjAwLC05Ni4zMCwwLjAw</data></item>
<item><type>73736e63</type><code>70766f6c</code><length>21</length>
<data encoding="base64">
MC4wMCwwLjAwLC05Ni4zMCwwLjAw</data></item>
<item><type>73736e63</type><code>6461706f</code><length>4</length>
<data encoding="base64">
MzY4OQ==</data></item>
<item><type>73736e63</type><code>6d647374</code><length>9</length>
<data encoding="base64">
NzgzMjczNjMx</data></item>
<item><type>636f7265</type><code>6d696b64</code><length>1</length>
<data encoding="base64">
Ag==</data></item>
```

ふむ、xmlチックに流れてくるようです。

なんとなく、typeとcodeが、reader出力のタイトルに割当たってる気がします。

こいつをファイルに保存し、shairport-sync-metadata-readerに食わせてみましょう。

```
root@nanopineo:/data/airplay_control# shairport-sync-metadata-reader </ramdisk/testmeta.txt
"ssnc" "flsr": "3110763112".
"ssnc" "pfls": "".
"ssnc" "pend": "".
Client's IP: "192.168.24.221".
"ssnc" "svip": "192.168.24.102".
"ssnc" "snua": "iTunes/12.7.1 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 16299); x64)".
"ssnc" "acre": "3500144013".
"ssnc" "daid": "DAABDA49CA0EFA86".
"ssnc" "pbeg": "".
"ssnc" "pfls": "".
"ssnc" "pvol": "0.00,0.00,-96.30,0.00".
"ssnc" "pvol": "0.00,0.00,-96.30,0.00".
"ssnc" "pvol": "0.00,0.00,-96.30,0.00".
"ssnc" "dapo": "3689".
"ssnc" "mdst": "783273631".
```

お、どんぴしゃっぽい。

よっしゃーとソース見てみると。

```c:shairport-sync-metadata-reader.c
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                '4', '5', '6', '7', '8', '9', '+', '/'};
```

あら、不穏な雰囲気。

もう面倒なので、上から追ってみましょう。
まあ、BASE64ベースで、キーはUser-Agent。
明らかに「Length:89」がそれっぽいので。
その下がRemote-accessだろうなと予測。

# perl実装
まあ、BASE64にそのまま入ってるべ、多分、と。
perlでサクっとデコーダを作ってみたり。

```perl:getactiveremote.pl
#!/usr/bin/perl

use MIME::Base64 ();

$activeremotefile = "/ramdisk/airplay_activeremote";
$metadatafile = "/ramdisk/shairport-sync-metadata";
$| = 1;
$datacount = 0;

open (PIPEFILE,$metadatafile);

while (<PIPEFILE>){
 if ($_ =~ /<type>73736e63<\/type><code>61637265<\/code>/){
  $datacount = 1;
  next;
 }
 if ($datacount == 1){
  $datacount = 2;
  next;
 }
 if ($datacount == 2){
  if ($_ =~ /^(.+?)<\/data>/){
   $adata = MIME::Base64::decode($1);
#   print "$_ $adata\n";
   open (OUTPUTFILE,">$activeremotefile");
   print OUTPUTFILE $adata;
   close (OUTPUTFILE);
  }
 $datacount = 0;
 }
}
```

xmlパーサとかかっこいいことせず、単純に「61637265」な行の２行下を取り出して整形、BASE64デコードしてるだけ。

ま、こんなんでも、いけました。

```txt:
root@nanopineo:/data/airplay_control# perl ./getactiveremote.pl
ODQ1NDkzOTcz</data></item>
 845493973
```

あとはまあ、systemdな設定書き換えて、終了。

```txt:/etc/systemd/system/getactiveremote.service

[Unit]
Description = getactiveremote
After = shairport-sync.service

[Service]
ExecStart=/usr/bin/perl /data/airplay_control/getactiveremote.pl
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target
```

ま、同名ファイル書き換えたので、そりゃデーモンの再起動要りますわな・・・。

```txt
root@nanopineo:/data/airplay_control# systemctl start getactiveremote
Warning: getactiveremote.service changed on disk. Run 'systemctl daemon-reload' to reload units.
root@nanopineo:/data/airplay_control# systemctl daemon-reload
root@nanopineo:/data/airplay_control# systemctl start getactiveremote
```

# 無事解決
やったー！。
![npi_sht2.png](https://qiita-image-store.s3.amazonaws.com/0/216885/b759c1cb-6a98-0c83-475a-76cb40b28725.png)