So-net無料ブログ作成
プログラミング ブログトップ
前の10件 | -

Swiftの関数の引数のアンダーバー。 [プログラミング]

Swiftをやる時にいつも忘れているんだけど、わりとすぐに思い出せないので書いておく。

Swiftの関数で引数のところにアンダーバーが出てくるのが気になる。

override func draggingExited(_ sender: NSDraggingInfo?) {


例えば上のだと関数のところにsenderという引数があって、その型はNSDraggingInfoだということだけども、アンダーバーはなんだということになる。

答えはObjective-Cにあって、メソッドの引数に名前をつける習慣があって、C言語みたいに関数でやっている分には引数の順番で判別するのだが、クラスの中のメソッドの引数はキーバリューみたいに一揃えにしていかなければならない。だからそれを省略して書く時にアンダーバーが必要になってくる。

Objective-CのCocoaに対応するためにSwiftでも引数が順番だけじゃなくて名前で判別する仕組みを取っているというわけだ。引数が一つだけだとかは面倒だから省略するのが普通なわけだが、なんかいちいち省略しますよと宣言するというのが気持ち悪いがしょうがない。

なんでこんな事を毎回やっているのかというと、この事実を明示的に書いているところがあまりないからだ。Swiftをやっている人は大体Objective-Cのことを知っているし、僕みたいにいきなり思い立ってやり直すという人が少ないというのもあると思う。そもそも_で検索しても情報がなかなか出てこないしね。文法とかはやっぱり本とかがあったほうがいいに越したことはない。Swiftは一冊買ってあるからいいとして、Golangって持ってないんだよな。
これあたり欲しい。翻訳本で高いがな。

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

  • 作者: Alan A.A. Donovan
  • 出版社/メーカー: 丸善出版
  • 発売日: 2016/06/20
  • メディア: 単行本(ソフトカバー)



Swift本はこれを持っている。簡単すぎないから大体のことはよく読めば載っている。あまり親切とは言えないが、少なくともググってすぐ出てくる情報ばかりではない。

[改訂新版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

[改訂新版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

  • 作者: 石川 洋資
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/01/17
  • メディア: 単行本(ソフトカバー)



[改訂新版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 WEB+DB PRESS plus

[改訂新版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 WEB+DB PRESS plus

  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/11/14
  • メディア: Kindle版




それにしてもguard文は必ずしも必要な感じはしないなぁ。便利は便利だけれど、他の言語であまり見慣れないものを見ると一瞬ムムムと感じてしまう。まぁ書いてあることを読める程度にはなっているけれども…。Swiftはコンパイラで検知できるバグは文法的に取っていく方針にあるみたいなので、ある程度書き方を強制されるところはあるかも。

タグ:SWIFT
コメント(0) 

コマンドラインアプリをGUIアプリにする前の下調べ。 [プログラミング]

MacでWindowsのShellExecute()のようなことをしたい場合どうしたいか、調べたらすぐに出てきた。

https://codeday.me/jp/qa/20190508/790510.html

壊れたような日本語に翻訳されたサイトですが事足りるので別にいい。要するにopenコマンドをsystem()関数で呼び出せば済むだけなので、ファイルのパスを探してくるだけで、手間はShellExecute()と大して変わりません。面倒がなくていいね。というか、コマンドになっているからシェルスクリプトに書けるというメリットがありますね。

そういやsystem()関数とか呼ぶのは、Swiftではどうやってたかな。というか、Swiftあんまりやってないんだよなぁ。SwiftとC言語の関数とかどう互換性があったのかよくわからない。

http://moapp.hateblo.jp/entry/2017/01/04/221623

system()関数を呼び出そうとするとエラーになるそうで。Cocoa的にNSTaskを使えばいいっぽい。

https://qiita.com/kitanoow/items/8b551a2d121ff95ef553

細々なことをしようとすると面倒臭いっぽいが、コマンドを発行する程度ならそんなに面倒じゃなさそう。ただコマンドのフルパスを指定しないといけないとか、UNIXのお作法的に気持ち悪すぎる。普通パスが通っているところにフルパスを指定するとか謎仕様なんだけど、パスを指定する設定がないので仕方ないのかな。

まぁMacだけで使うのでパスが固定されていてもそれほど問題はないのかもしれないけど、なんらかの変更があった時には対応できないよな。というか、そういう仕様はUNIXとしてかなり腐っている感じがするのは私だけでしょうか。

コメント(0) 

golangで次なにしようかな〜 [プログラミング]

これまでルータを超えてアプリを晒すことをGolangでやってきました。UPnPではある程度やったんだけど、ルータの腐れ具合がそれを邪魔していました。まぁできないことはないんだけど、一般的に動きづらい困難さはある。

IPv6での操作も考えたんだけど、これもルータの設定が必要でUPnPよりか(手動操作的に)面倒な気がした。そもそもGolangでのIPv6対応がまだまだというところもあって、今すぐがっつり使うには足りていない気はした。


そんなわけでP2Pアプリみたいなことをしたい自分としては頓挫したわけですが、Webアプリ的なところはGolangでもできていた方がいいなと思ったのでちょっと探したらginが簡潔で良さそうな感じ。

https://qiita.com/Anharu/items/ce644c521a4d52fafb7e

フルスタックなものは求めていないし、覚えるにもコストがかかるのでリスクが大きい。HTMLファイルに埋め込めて、サクッとテンプレート作成できればそれでいい。元々Golang自体薄い言語なので、組み合わせてファットなものは使わないというのがセオリーな気がするのですが。

アプリとはいえ特にDBは必須ではないにしろ、今更使わないという選択肢はあまりないのだろうな。色々なものをストアするのに手動でやる方が面倒だって気もする。だけど、そこまでやるほど大掛かりにしたいわけでも、自分の窺い知れない操作をやってほしいわけでもないんだよね。

gormという名前は直球というか単純というか。goのorマッパーだからってことなんでしょうけど、golangはオブジェクト指向ではないよなと思ったり。SQL作るのしんどいので、使うことになるんだろうなぁ。sqlxというのでも良さそうな気はするけど、SQLが嫌いなのでねぇ。

ORマッパーでググると頭に百害あって一利なしとか出てくるのですが、SQLを書くのがしんどい人にとっては他の色々なことも気にしないで済むのも楽できていいのかなと。少し訳のわかった人がラッパーの重鈍さを嘆く・叩くというよくありがちな行動なのですが、みんなメリットがあるから使っているのだから何言っても、正論だけど主流と違うよねというところに落ち着くのでしょう。なんつーか、物知り顔のおじさんばっかでこの業界ウザいw。


Ajax的なこともできたらいいなと思っている。今更Ajaxかよと言われるかもしれないが、やればやったで面倒だったり使うときには便利だったりするのでやれておいた方がいい。というか、Webアプリでも面倒でやっていないと思われる場面もあるので、訳がわかっておいた方がいいんだろうなと思ったり。

ごちゃごちゃ言ってきたけど、P2Pで使えるような機能が実装できればいいので、あんまり長く書かずにサクッと終わらせられればいいとは思っています。GolangでWebアプリを作るのがいいのかどうかは微妙なところですが、まぁそこそこ用意されているし、できないことはないし、Webサーバ自体はお気楽に短い行で作れるし、やってみる価値はありそうです。


タグ:Golang
コメント(0) 

golangでUPnPのポートフォワーディングをしてみる6−最後 [プログラミング]

やっと実際のポートフォワーディングをUPnPでするまでに辿り着きました。というか、結論を言ってしまえば、UPnPでポートフォワーディングするのはあまりお勧めできません。恐らく、多くのルーターで動かないものができてしまいがちだからです。まぁルーターの実装が悪いからだからなんですが、一部でもできるものをできないと言うのも問題なので、一応最後までやってみようとしています。実際やろうとするならIPv6とかでやるべきなのかもしれないですね。どうやってやるかは調べてないので具体的にはわかりませんが…。

具体的なやり方としては、下のサイトにほとんどを頼った形になってます。それはグローバルアドレスを取るときも一緒でした。結局、具体的なPOSTデータを何を出せばいいかというのが、きっちりわかったので非常に有用でした。

http://manabu.quu.cc/up/6/e62532.htm

最終的には何のプログラミング言語を使うにしても、プロトコルとして何をしているのかがわかれば実装できるのですね。なのでこういうサイトはありがたいのであります。あとはどう自分の使う言語に落とし込むかって話なので、そこは各自にやればいいって話で。

ただ今回はやらないけれどもSSDPの改行文字は\r\nで\nじゃない気はするんですが、気になる人は両方やって見てください。UPnPはMSが言い出しっぺだと思ったので、\r\nでやるかと思ったんですがどうでしょうか。

やってる本体の部分は前回とあんまり変わらないんですけど、自分のIPを取ったりWebサーバを立ち上げたりしているので他に考えることは少し多い気はします。それと本当ならXMLの中身を見て、きちんとポートフォワーディングがサポートされているかどうか見ないといけないんだけど、どうせできないものはできないので確認作業はしなくてできるものとして考える。どうせできるものはできるし、できないものはエラーが出て転ぶんだろうし。



Access URL: http://xxx.xxx.xxx.xxx:8080/hello
と出てくると思うので、そのアドレスで自宅とは別回線でアクセスすれば、
This is an example server.
と表示されます。具体的にはWiFiを切った携帯で上のURLにアクセスするということです。晒しているサーバと同じネットワークからアクセスしても自分のネットワークには到達しません。まぁそれは何でポートフォワーディングしていても同じことですけどね。

最後にControl+CでWebサーバを終わるとき、ポートフォワーディングを削除したいんだけど、これではできていないっぽい。気になる人は単体で削除するコードを書いてもいいと思います。コードを切り離してあげれば動くと思います。

あとstringにしたり[]byteにしたり無意味なことをしていますが、ただ単に行きがかり上そうなっただけで深い意味はありません。もう直すのも面倒なので…。あと外に晒すポートとクライアントが開くポートは必ずしも同じにする必要はありません。面倒臭いので同じにしているだけで、違うものにする必要がないと思っただけです。

これでとりあえずポートフォワーディングの件は終わりです。というか、あまりにルーター側の不備が発覚したので呆れました。これじゃ、UPnPでポートフォワーディングを標榜しているソフトは、半分のルーターでは動作しないんじゃないかな。でも、できないというわけではないので、広くサポートしようとすると困難であるということなのでしょう。

IPv6でできるならやるべきなのかも。それもルーターが何かしら噛んできそうなので厳しいかもしれない。外にサーバ作って認識させるってのがP2Pでも使う方としてはお手軽なのでしょうね。

タグ:Golang
コメント(0) 

golangでUPnPのポートフォワーディングをしてみる5−グローバルアドレスを取ってみる。 [プログラミング]

今までルータのXMLが腐っているとかで、UPnPでポートフォワーディングするのが怪しくなってきているわけですが、続けていきますよ一応。まぁブツ切れの検証コードしか作れませんが、環境がまちまちなのでこっちで解決するには面倒臭すぎるというのはありますね。

ポートフォワーディングをしてみる前に、簡単にできそうなグローバルアドレスを取りに行くことをします。これは結構他でもやられているので、それをGolangに落とせばいいという話ですよね。

ともあれ、NECのルーターのUPnP用のポートのサービスが死にやすいということが発覚して、やる前にルーターを再起動しないといけないという体たらくで…。まぁNECのAtermは80番ポートを解放するだけで数日でルーターが死んでインターネットのアクセスができなくなるくらいですから、頑丈さからするとめっちゃ弱いと言わざるを得ません。ソフトの作りも悪いんだろうけど、多分スペックも足りてないんでしょうね。

あまり不満を言っていてもしょうがないので実際やってみますね。今回も事前に調べた体で、ルーターのIPとPOSTを食らわせるURLの一部を用意しておきます。それらを調べるコードは前回のコードでやっていますけど、繋げちゃうとどこがおかしくて動かないかどうかが分からなくなってしまうので、検証コードとしては短いほうがいいと思っています。



先にも言った通り、ルーターのローカルアドレスやらが分かっていないと動きません。具体的には
routerAddr
serviceType
controlURL
をルーターの設定に合わせて書き直さないと動きません。

それと返すXMLが腐っていなければ(同じフォーマットであれば)、問題なくグローバルアドレスが取れるかと思われます。大したことやってない割には苦労していますね。とりあえず苦労した点などは言っておきましょうか。


一番の問題はXMLを受けて解析するところなんですが、一応"encoding/xml"パッケージが解析してくれはします。ただ問題なのが解析の元となるXMLの構造をGolangの構造体で示してあげないといけない、という苦行が待ち構えているわけです。実際送られてきたXMLが下のようなものです。これも複数のルーターで調べたわけではないので、構造が違う可能性はあります。

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Body>
		<m:GetExternalIPAddressResponse xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">
			<NewExternalIPAddress>27.95.xxx.xxx
		</m:GetExternalIPAddressResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

これが洗練された方法があるわけでもなく、泥臭く構造体を定義するというクソッタレな仕様になっているわけです。どこかでXMLなんてタヒねばいいのにって書いてあったのですがその通りだと思います。かと言って情報交換するのにきちんと規定されたフォーマットってのは他にはあまりないわけで。

https://text.baldanders.info/golang/unmarshalling-xml/

今回は全体の構造体を定義せずに、そのパスだけを提示してグローバルアドレスだけを取ってきています。なので、正直言って全部の構造体を定義して全部入れ込むということは、今の自分にはできません。というかやりません。だってグローバルアドレスを取りたいだけなので、他の情報はいらないですから。そんなわけで構造体の定義は全体的にはしていません。

type root struct {
    NewExternalIPAddress string `xml:"Body>GetExternalIPAddressResponse>NewExternalIPAddress"`
}


でBody、GetExternalIPAddressResponse、NewExternalIPAddressと階層を示しているんですが、これで示せば他の構造は無視できるんですね。逆にいうとこの方法だと他の情報が取れない。

このやり方にしても、構造体の定義をするにしても、?xmlというタグとEnvelopeというタグは無視されているのはよくわかりません。?xmlは省略するのはわかるとして、次の階層になるEnvelopeというタグに関しては省略してしまうのはどうなのかなと思わなくはありません。でも、GolangのUnmarshal()がそういう仕組みになっているから仕方ありません。そうだからそうとしか言えないです。

とりあえず、これでルーターのグローバルアドレスを取ることはできるはずです。できなかったら変えるべき所を自分の環境に変えられていないか、ルーターの動作が死んでいるかですね。もしかするとルーターの再起動が必要かもしれません。XMLが返ってきているのに、構造体の中に入っていない場合は、XMLの構造がきちんとしていないということだと思います。


次はルータのポートフォワーディングをします。やる手順としては今回と大して違いがないはずです。今回と違う所を重点的に書いておこうと思います。

タグ:Golang
コメント(0) 

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が腐っている可能性は高いので、対応アプリケーションに文句を言っても仕方ない可能性はある。

タグ:Golang
コメント(0) 

golangでUPnPのポートフォワーディングをしてみる3−不定形のXMLをどうにかしたい [プログラミング]

前回、とりあえずXMLをパースする方針ができました。できたのですが、ルーターのXMLには数々の問題があり一筋縄にはいきません。問題を挙げておきます。

1. XMLが定型ではなく、ルーターによって構造がまちまち。
2. XMLがUTF-8でない場合があって読み込み時にエラーが出る。

というかなりクソッタレな状況になっていて、まともにUPnPを使ってポートフォワーディングができる状況ではありません。各メーカーが決まりを守っていれば問題ないのですが、やりたい放題でまともに動く状況になってはいません。

自分の状況を述べますと、無線LANルーターを二つ見ました。NECのAtermとIOデータのWN-G300Rです。AtermはXMLの構造がどうにも深くて、Golangでは構造体を規定してのデータ取り込みが困難でした。このネスト構造が本当にXMLのフォーマットとして規定されているものなのか疑問に思い、他のルーターを見てみました。

WN-G300Rを見てみると、ネストもそんなに深くなくシンプルだったので、Atermの深さがちょっと異常というのが何となく分かりました。その後のパースを比較的シンプルなXMLだったWN-G300Rに変えて検証してみていると、UTF-8以外のコードが含まれており、やり方によってはGolangで以下のようなエラーが出てしまうのでした。

panic: XML syntax error on line 15: illegal character code U+0018


そもそもXMLのURLをブラウザでアクセスしても、パーシングでエラーが出ていたのでおかしいなとは思ってはいたのです。

XML パースエラー: 整形式になっていません。
URL: http://192.168.1.202:49152/wps_device.xml
行番号: 11, 列番号: 18:bLy￿
-----------------^


IOデータの作った技術者が日本語エディタかなんかで編集してUTF-8の設定にしていなかったんですね、たぶん。そうじゃないとUTF-8外のデータが入り込むということは考えにくい。技術者だったら日本語の取り扱いぐらいは慎重にしておくべきですよね。ちょっと恥ずかしい。

XMLの形がちょっと独自すぎたり、そもそもXMLの体をなしていなかったりするので、正直言ってUPnPをポートフォワーディングで使うのは厳しい。問題を乗り越えるのにすべきことはいくつかあり、それを全部乗り越えるには正規の手続きではやりにくいと思われます。やれることとしては

・XMLにUTF-8以外のキャラクターが出てきても無視できるようにする。
・XMLの構造はあてにできないので、タグを一つ一つクロールして該当の部分だけ抜き出す。

ぐらいのものでしょうか。ポートフォワードが可能でなくても、決め打ちでメッセージを発行できるところはあるものの、ルーターごとに違う設定になっている部分はやっぱりXMLから抽出しないとできないので、パーシングは必要不可欠なのです。というか、完全に開発者のXMLの理解不足がアダとなっているなこりゃ。

そんなわけで、UPnPが可能としているルーターでも、UPnPをイネイブルにしたところでちっとも反応しないという状況が眼に浮かぶわけで。だから、あるソフトを使ってUPnPを有効にしたルーターで上手くいかないとしても何の疑いもなく動かないということはあり得るということをみなさんにも知っていただきたい。

とりあえずAtermのXMLはUTF-8ではあるので、それで動くかどうか確かめてみましょう。というか、こんな適当すぎる杜撰な仕様のソフトは一般的なんでしょうかね。まぁUPnPの成り立ちが微妙なのは否めませんけど。

タグ:Golang
コメント(0) 

golangでUPnPのポートフォワーディングをしてみる2−不定形のXMLをどうにかしようとする [プログラミング]

ルーターの持っているXMLが不定形なので、XMLとしては悪手なのではと思わざるを得ないのだけれども、DTDがあるわけでもなさそうなので、XMLの中を検索する他なさそうな気がします。構造化されているXMLをパースする例はいくらでもあるけど、不定形のXMLをどうにかするという記事がこれまたない。ググり方が悪いのかな?

一番雑音が少なさそうなコードがこれあたりで
https://hogesuke.hateblo.jp/entry/2014/08/25/012114
やっぱり構造体ときちんと定義しないといけないみたい。


Unmarshal()が出力するのはinterface{}で、具体的には構造体のようです。ふつう構造体自体は検索して使うものでもないので、XMLの型を作っておいてそこに当てはめるという方法は当然だったりします。実際、XMLからデータを引っ張ってくるサンプルはほぼ全部構造体を定義していますね。まぁXHTMLみたいな不定形なXMLも存在するので、そこのところを拾えない作りになっていると汎用性がない気がするんですがね。

Golangの構造体の検索を調べた方が良さそうな気がしますが、なんかなさそうな気がするんだよなぁ。LL言語あたりだと言語仕様か標準ライブラリのあたりにありそうな気はする。ググっていたらJSONをUnmarshalするということが書いてあって、JSONだと不定形なことも多いだろうと思って読んでみた。

https://www.kaoriya.net/blog/2016/06/25/

ゆるふわ、ねぇ。XMLでもできそうだなと思ったができなかった。

具体的には空のinterface{}にUnmarshal()で入れたんだけど、nilが返ってきました。よく読んだらきちんと構造体を作らないと空で返すよと書いてありました。形式は合っていてもvalに適合しないデータは破棄されます、って書いてあった。

http://golang.jp/pkg/xml

ううむ、一つずつ要素をクロールして行くような方法でいいからないのかな? でも、英語の文章を読んでいくのはしんどい。日本のリファレンスだってサンプルコードがない関数なんて暗闇の中で手探りしているようなもんだし。あんまり試行錯誤はしたくないんだよね。




不定形のXMLを扱う方法があった。

http://golang.rdy.jp/2015/11/08/anyxml/

UnmarshalXML()を独自に定義すればいいらしいんだが、サンプルではUnmarshalXML自体は呼んでない。Golangの仕組みとライブラリの問題なんだろうけど、いまいち細かくはよくわからない。

xml.Marshaler と xml.Unmarshaler interfaceを明示的に定義するっていうのがあったけど、別にこれはしなくてもいいってことなのかな。

https://qiita.com/ono_matope/items/70080cc33b75152c5c2a#xmlmarshaler-%E3%81%A8-xmlunmarshaler-interface

とにかく一つずつ拾っていく方法をとれるっぽいので、forで該当の情報を取れるまでぐるぐる回してみれば良さそうな気がする。そうなるとUnmarshalXMLは使わないでできるのかもしれない。使った方が楽かな? よくわからないけど実装できればいいや。

http://golang.rdy.jp/2015/11/08/anyxml/
のUnmarshalXML()だけをとって、情報を構造体にぶっこみたかったんだけど上手くいかず。
MarshalXML()もコピペして入れ込んだんだけど、内容が重複したり入れ子部分がざっくり無くなっていたり、まともに動いてくれていなかった。これは上のコードに自分が取ってきたXMLぶっ込んで試してみた方が良さそうだな。

やっぱり自分が取ってきたXMLを喰わせたら、階層を無視して途中でぶっちぎれて途中から続いた。汎用性がないらしい。あ〜自作かぁ。プログラミングするの面倒くさいなぁw。始めてしまえば楽しくなってきたりはしたりもするのだが、自分の用をなすものを作っても汎用性のあるコードは書きそうもないな。

とにかく、普通の正攻法ではできないとわかったので、地道にカスタマイズをかけるようにやるしかないかなと思ったり。なんとなくやり方の方針はわかったので、あとは似たようなコードとリファレンスを首っぴきにしてやるしかないかな。XMLだからもうちっとやり方が提供されていると思ったけど、薄っぺらなそこはGolangであるってことなんだろうな。

タグ:Golang
コメント(0) 

golangでUPnPのポートフォワーディングをしてみる1 [プログラミング]

P2Pのソフトを作る上でルーターに穴を開けないといけなくなった。その点でUPnPを使うのが楽かなと思い、そこらへんの調査をしてみた。

Golangで実際動くものをと思ってミニマムなコードをでっち上げた。参考にしたコードは以下。

https://qiita.com/KyojiOsada/items/bc381b3058715d4011d2
https://github.com/syncthing/syncthing/blob/master/lib/upnp/upnp.go



めんどうなのでコメントを入れなかったけど、短いので逐一調べてもそれほど時間はかからないと思う。とりあえずSSDPを発行して、ルータの情報が入っているXMLのパスが入っているので、それはこれで取れる。

メッセージを送って受けるだけのミニマムなコードなのでわかりにくいことはないとは思うのですが、やっぱりXMLをパースしてパスを抽出するところまで書けばよかったかな?

ただ受け側の問題があり、SSDPのメッセージが複数届くので、そこのところを勘案すると少し面倒なのかもしれない。それにルーターだけではなく別のクライアントからも来るのでそれを見分けないと。タイミング的に他のメッセージが来た時にそれをはじくべく内容で選別しないといけないのです。でも、単純にこれという文字列がよく分からないんだよなぁ。それもルーターから複数くるので面倒臭い。

結局、Location: のなんとか.xmlを取ってくればよくて、ルーターからのメッセージには必ず(?)入っているので、ルータとわかるメッセージであれば何でもいいんですがね。決定的なタグの文字列があればいいんだけど…。

その中に書いてあるXMLのパスのXMLに使えるアクションが書かれているので、あったらそれを使うという具合になっているようです。別にXMLをダウンロードしてきて調べなくても、あると思って決め打ちでも動きそうなので、XMLをパースする作業はここではしません。後で考えることにします。




グローバルアドレスを取ってくるとかならあったりするのだけれど、下のところほど情報がなくて実際にどうしたらいいのか分からなかった。

http://manabu.quu.cc/up/6/e62532.htm

ここまで詳しく書いてくれていたら誰でも分かって嬉しい。上のサイトでポートマッピングのやり方がわかったんだけど、とりあえずグローバルアドレスを得ないとピアのクライアントに教えることもできないので、とりあえずルーターのIPがわかっている体でGolangのソースを書いて実際に取得してみる。

ん?なんかXMLの階層がへんな感じがする。他の無線LANルーターのXMLを見てみる。全然構造が違うじゃねぇか。普通XMLを使う時には、構造が規定されているため、所定の手続きをすれば同じタイプのXMLであればアクセスできるのだが、構造が違ったら順にタグの名前を辿って行く方法が使えない。

しょうがないので
SCPDURL
controlURL
eventSubURL
のタグ名で検索して、中の文字列を取ってくるやり方しかなさそうだね。バッティングしなければいいのだけれど…。普通はそういう使い方をしないので、サンプルがそういうのがないみたい。リファレンスの内容からスクラッチしないといけないのはしんどいな。

パースした体でメッセージを送ろうとしたけど、結局XMLを解析しなくてはいけないので、やっぱパースを後にするのはやめた。そもそもルーターごとに全然違う状況になっているから、文字列を決め打ちでやっても動作確認しかできない。




思ったよりも面倒くさくて一回で終わらなかった。次でXMLをパースして、そこから送り場所を得て、グローバルIPを取りたいと思う。そこからのポート開けのスマホからの別回線の確認をしてみたいと思う。

タグ:Golang
コメント(0) 

GolangでP2Pをやろう、の下準備。 [プログラミング]

最終的に違法ファイルを流すP2Pを作るつもりではないので、それを目的にした人はどうもお疲れ様でした。

ともあれ、二点間でのP2Pを作ろうとしているわけですが、GUIをブラウザでやろうとしているので、基本的にWebサーバを作って情報をやり取りするということになっております。ホストとなるマシンがあるから正確にはP2Pではないのだけれど、直つなぎという点においては間違いはないかと。




GolangでUPnPで同じようなことをやっているソースがありそうなもんだなと探してみた。

https://github.com/syncthing/syncthing/blob/master/lib/upnp/upnp.go

syncthingというアプリがそのまま自分の実現したい用途に適合してそうだったけど、ここはお勉強も兼ねてやるので面倒臭くない程度で自分でやりたい。そしてライセンスが面倒なことになっていなければそのまま使えれば使っちゃおう。うぉ、8タブだよ、厳しいな。GitHubって8tabだったっけ?

ただ自分のグローバルIPを知って、ポートに穴開けて、ポートフォワーディングできればいいから、フルスタックなUPnPのライブラリを作るわけじゃないので、限られた動作ができればそれでいい。UPnPのプロトコルってどこにあるんだろ。RFCかな? とりあえずSOAPで送って云々というのはなんとなく見ているからそんなに難しいことをやっている気はしない。

グローバルアドレスはDHCPでも得られるみたいなことを書いてあったが、今回はUPnPができないと話にならないのでDHCPは使わない。

https://mdgw.hateblo.jp/entry/20080204/1202132356

SSDPを使うとあるが、HTTPリクエストをマルチキャストで投げればいいらしい。やっていることはそんなに難しいことではない。情報が入っているXMLのURLが送られるので、そこから取ると。そのあとのポートの開け方とかを知りたいんだけどな〜。

https://nazuna.sakura.ne.jp/software/upnp/get_device.html

古いドキュメントには標準化されていないと書いてあったが、そんなことはなかった。仕様は下記のどこかに埋まっているんだろうけど、探すの面倒だな。

https://openconnectivity.org/search/UPnP

これあたりかなぁ。

https://openconnectivity.org/developer/specifications/upnp-resources/upnp/internet-gateway-device-igd-v-2-0


どこぞでIPv6を使うとNAT越えも大丈夫とあるが、ようけわからんというか、IPv6から勉強しないといけないのと、IPv6の実装状況が一般的にどうなっているのかわからんというのが正直なところ。




とりあえず、グローバルIPと任意のポートを開けられたとしましょう。それを相手に教えるためにメールするわけだけど、SMTPをやるにも標準で用意されているからサンプルとかはたくさんあるでしょう。

https://www.write-ahead-log.net/entry/2017/08/02/233000

ASCIIなメールは送れるけど日本語はできないと書いてあるけど、まぁ当然ですよね。というか、それが当然と知っているのはメールクライアントをいじくったことがあるからで、基本的に歴史的にメールはASCII文字しか使えないということがあって、そのためにアルファベットなどにエンコーディングしないといけない。base64とかquoted-printableを使えばいいのだけれど、URLを送るだけだから面倒くさいからいいや。確かにGolangは標準ライブラリの作りが薄い…。

それでつなぎに行くところを伝えられたら、あとはWebサーバを立てられればOK。まぁそこからが何をするのかを考えるのが本体なのだが、メッセージングとファイルのやり取りはできればいいかなと思ったり。というか、それ以上のことは考えていません。双方向に情報を送れそうなので、やれることは多そうではある。HTTPだとファイルのやり取りはあまり効率的じゃなさそうですが、お手軽にやるにはそれで十分ですね。

コメント(0) 
前の10件 | - プログラミング ブログトップ