年末年始の休みがそんなに長くないうえに、年末が微妙に忙しい。
29日にはPeerCastStationをリリースして飲み会、30日は空いてたんだがコミケ行くかーとちょっとだけ行ってきて帰って洗濯だのしてた。31日はコミケ行って急いで帰ってきてすぐに帰省だ。
UPnPとNAT-PMPでのポート開けを作り直した。とりあえず入れた状態でリリースしてみたもののやっぱりだめみたいだなぁ。
いろいろだめな人が居たので試してもらったところ、いろんなダメパターンが集まってきて困ったことになってしまった。
まずはデバイスが見つからないパターン。SSDPというデバイス探すパケットをUDPでブロードキャストするんだが、UDPソケットをバインドせずに1回だけぶん投げて返事を待つということをやると、思ったのと違うアドレスに勝手にバインドされちゃって、ちゃんとルータに対してブロードキャストできてないというわけだった。でもポート番号指定しないとバインドできないしどうすんだ?とMono.Natを調べたらポート0を指定してた。なるほどそれでよかったのか。UDPとか普段使わないので分からんことだらけだ。
とりあえずIPv4のUnicastアドレス全部に対してSSDPの探索をぶん投げたらちゃんと取れるようになったようだ。よかったよかった。
デバイスというかサービスが見つかったら詳細情報を取得するんだが、上手くいかない場合がある模様。どうも一つのサービスについて4つもコントロールURLがあるデバイスがあるっぽい。よくわからんがそのうち1つだけ選択するようにして解決したっぽい。しかしUSNが全部同じだった気がするのは気のせいだろうか。いやサービスとしては一つなのか?4つはどうやって使い分けるのかわかりませんね。
他にルータのWAN側アドレスが取得できないデバイスがある模様。一つはエラーを返してくるんだが、UPnPのエラーが-111で詳細はInvalid Action。しかし仕様のどこを見ても-111なんてエラーコードは書いてないし1、サービスのWANPPPConnection:1はGetExternalIPAddressアクションを実装してないといけないはず。WANIPConnectionサービスも実装してないみたいだしこれはお手上げだ。なんだこのクソデバイス……。
もう一つWAN側アドレスが取得できないものがあるが、これは0.0.0.0を返してきてしまうもの。WANPPPConnectionとWANIPConnectionの両方を公開してるがどっちも0.0.0.0を返してくるみたい。うちで試してたUPnP対応のルータも0.0.0.0を返すんだが、これはWAN側に線つなげてないので当然だ。しかしみんなから貰ったデータは普通に使ってるルータぽいけど? 普通にポート開けは対応してるような気がするし、エラーが返ってきてるわけでもないのでデバイスがWAN側のアドレス取得に対応してないのかな?と予想。なんでだかはわからないが。とにかくこっちでなんとかなりそうな気はしなかったので気にしないことにした。
あと関係ないけどとりあえず全デバイスの詳細情報取得に行ったらURLは返してくれるけどいざそのアドレスを見に行くと接続をぶち切っちゃうやつも居るようだ。ルータではないから気にしなくていいんだけどいったいなんなんだ……。
とりあえずデバイスの列挙がちゃんとできるように各UnicastアドレスからSSDPぶん投げるようにしないとな。 NAT-PMPはデフォルトゲートウェイのアドレスにぶん投げるようになってるんだけど、デフォルトゲートウェイ持ってるインターフェースのアドレスだけ使ってSSDPぶん投げるのもありかなぁ?まあ仕様的には全部探索するのが正しそうだしちゃんと全部ぶん投げるでいいか。
あとUPnPの情報見たりポート開け試したりできるツール作ってみんなに試してもらうしかないなぁ。思ったよりいろんな実装あるな!
Invalid Actionは401だし、そもそも標準で負値のエラーコード定義されてないみたいなんですけど ↩