golangでUPnPのポートフォワーディングをしてみる4−不定形のXMLをどうにかしたい [プログラミング]
これまでにGolangでXMLを細かく扱うには、UnmarshalXML()を定義すればいいと分かりました。
http://golang.rdy.jp/2015/11/08/anyxml/
不定形のXMLでもこれは使えると思っていたのですが、他のXMLにはそのままで使えないUnmarshalXML()であったのです。具体的にはxmlnsが邪魔してすんなりデータが取れないのです。というか、名前空間とか本来的にはデータを取ってくるだけのことではあんまり関係ないのですよね。面倒なことに定義されたあとすべてに絡んでくるので、無視するのにも手間がかかりそうですね。
サンプルとして提示されたもののXMLにはいちいちタグの属性として打ち込んでいるタイプだったので、それが問題にならなかったのでしょうけど、普通だったらいらないものとして抽出時に捨てられるものなんでしょう。
とりあえず実証コードを示します。ただ制限というか問題があります。
1. 最初のXMLを取りに行くSSDPの送受信は含まれず、コード内でURL決め打ちなので状況に合わせて書き直さないといけない。取ってくるコードは以下
https://miff.blog.so-net.ne.jp/2019-07-14-1
2. 特定のNECのAtermぐらいにしか使えないかもしれない。そして
SCPDURL
controlURL
eventSubURL
などのセットが複数ある場合は、最後のデータに上書きされる可能性がある(検証してないけど)
3. UnmarshalXMLに渡すデータ型がイマイチよくわからなかったので、SCPDURLなどを収納する変数をグローバルにして通しているので、ソースコードとして行儀が悪い。
さらにt *Tag を本質的に使っていない。本来ならこれを使ってSCPDURLなどを格納すればいいのだけれど、入れた後に使うことを考えると、特定の項目を検索したりするのが面倒だ。
1. の問題は自分がコードに落としていないだけでできないことはないのでしょうが、少々込み入ってしまう可能性があるので、目で見てLocation: ってところのURLを取ってきています。ここのところがSSDPの仕組みがどうなっているのかわからないので、別のクライアントが投げてくるメッセージをより分ける方法がわかってません。xmlUrlという変数を書き換えれば、任意の環境で動くかもしれません。
2, はルーターだと1組だけな場合が多そうなので気にする必要はないかもしれません。
3. はそもそもxmlパッケージの問題なのかもしれないので、UnmarshalXML()を使う限りは無理かもしれません。前提として不定形のXMLというものを前提としているので、そもそも定型なXMLを前提としているxmlパッケージの作りでは無理があるのかもしれません。
あと動作状況を知るためPrintfデバッグ的に埋め込んでいます。検証コードですので、最終的に得られる情報よりも過程が重要かと思われるので。
UnmarshalXMLが返してくるデータを手探りで抜き出しているので、先ほども言ったようにグローバル変数を関数の中に使うなど、Golangというかプログラミング言語的に悪手ではあるのは了解してください。その前にXMLの階層がまちまちというのが非常に問題なのだが、最近のルーターだとそういうこともないかもしれない。ただUPnPをサポートしているルーターで動かない例はそもそもXMLが腐っている可能性は高いので、対応アプリケーションに文句を言っても仕方ない可能性はある。
http://golang.rdy.jp/2015/11/08/anyxml/
不定形のXMLでもこれは使えると思っていたのですが、他のXMLにはそのままで使えないUnmarshalXML()であったのです。具体的にはxmlnsが邪魔してすんなりデータが取れないのです。というか、名前空間とか本来的にはデータを取ってくるだけのことではあんまり関係ないのですよね。面倒なことに定義されたあとすべてに絡んでくるので、無視するのにも手間がかかりそうですね。
サンプルとして提示されたもののXMLにはいちいちタグの属性として打ち込んでいるタイプだったので、それが問題にならなかったのでしょうけど、普通だったらいらないものとして抽出時に捨てられるものなんでしょう。
とりあえず実証コードを示します。ただ制限というか問題があります。
1. 最初のXMLを取りに行くSSDPの送受信は含まれず、コード内でURL決め打ちなので状況に合わせて書き直さないといけない。取ってくるコードは以下
https://miff.blog.so-net.ne.jp/2019-07-14-1
2. 特定のNECのAtermぐらいにしか使えないかもしれない。そして
SCPDURL
controlURL
eventSubURL
などのセットが複数ある場合は、最後のデータに上書きされる可能性がある(検証してないけど)
3. UnmarshalXMLに渡すデータ型がイマイチよくわからなかったので、SCPDURLなどを収納する変数をグローバルにして通しているので、ソースコードとして行儀が悪い。
さらにt *Tag を本質的に使っていない。本来ならこれを使ってSCPDURLなどを格納すればいいのだけれど、入れた後に使うことを考えると、特定の項目を検索したりするのが面倒だ。
1. の問題は自分がコードに落としていないだけでできないことはないのでしょうが、少々込み入ってしまう可能性があるので、目で見てLocation: ってところのURLを取ってきています。ここのところがSSDPの仕組みがどうなっているのかわからないので、別のクライアントが投げてくるメッセージをより分ける方法がわかってません。xmlUrlという変数を書き換えれば、任意の環境で動くかもしれません。
2, はルーターだと1組だけな場合が多そうなので気にする必要はないかもしれません。
3. はそもそもxmlパッケージの問題なのかもしれないので、UnmarshalXML()を使う限りは無理かもしれません。前提として不定形のXMLというものを前提としているので、そもそも定型なXMLを前提としているxmlパッケージの作りでは無理があるのかもしれません。
あと動作状況を知るためPrintfデバッグ的に埋め込んでいます。検証コードですので、最終的に得られる情報よりも過程が重要かと思われるので。
UnmarshalXMLが返してくるデータを手探りで抜き出しているので、先ほども言ったようにグローバル変数を関数の中に使うなど、Golangというかプログラミング言語的に悪手ではあるのは了解してください。その前にXMLの階層がまちまちというのが非常に問題なのだが、最近のルーターだとそういうこともないかもしれない。ただUPnPをサポートしているルーターで動かない例はそもそもXMLが腐っている可能性は高いので、対応アプリケーションに文句を言っても仕方ない可能性はある。
タグ:Golang
Twitterまとめ投稿 2019/07/23 [Twitter]
carbonhydrat『PS4のバックアップで受け側のSSDをMacでフォーマットしたらハマった話。』名前を変えようと思ったがいい案がなかった..|https://t.co/s0GMzWSYf207/22 12:08
2019-07-23 05:01
コメント(0)