投稿

R7800 OpenWrt(hnyman ビルド)のファイアーウォールの初期設定

イメージ
OpenWrt は fw3 を使っている。 fw3 では iptable を直接いじるのではなく、 設定ファイル (/etc/config/firewall 等)から一連の iptable を生成して、それを netfilter に渡す。netfilter に渡される iptable 自体はかなり複雑でユーザーが直接いじれるものではなくなっている。従って、fw3 に渡す設定ファイルの方を扱うことを考えればよく、UCI や LuCI で CUI/GUI を通じて操作するのも、設定ファイルの方である。 デフォルト設定 config defaults option syn_flood '1' option input 'ACCEPT' option output 'ACCEPT' option forward 'REJECT' グローバルに適用されるデフォルト設定(👉 Defaults )。 通信のルーター自身への出入は許可し、通過は拒絶する。syn_flood プロテクションを on。 lan ゾーン config zone option name 'lan' list network 'lan' option input 'ACCEPT' option output 'ACCEPT' option forward 'ACCEPT' lan のゾーン設定(👉 Zones )。 lan 側インターフェース(lan)をこのゾーン(lan)に割り当て、全ての通信を許可。 wan ゾーン config zone option name 'wan' list network 'wan' list network 'wan6' option input 'REJECT' option output 'ACCEPT' option forward 'REJECT' ...

SyntaxHighlighter から Prism へ移行

プログラムのサンプルコードの表示用のツールを SyntaxHighlighter から Prism へ移行した。 このサイト(blog.scaredeer.com)は Blogger で運用しており、Blogger の記事・ページとして生成されるファイル以外に、自分で任意のファイルを置けず、当然、Prism 用のファイル(prism.css と prism.js)も設置できない。 仕方ないので、サブドメイン www 用の別サーバーを用意し、そこに配置した Prism 用のファイル(css と js)をこの Blogger から指し示すようにして運用している(👉 Blogger と独自ドメインの設定 )。 Blogger のテーマの HTML のカスタム箇所 <head> ... <link href='https://www.scaredeer.com/prism/prism.css' rel='stylesheet'> </head> <body> ... <script src='https://www.scaredeer.com/prism/prism.js'></script> </body>

Favicon Generator

イメージ
Favicon Generator ( realfavicongenerator.net ) を使って SVG 画像から各種 favicon とそれ用の head 内記述用タグを自動生成できる。 今回は、Blogger サイト用の favicon を生成して、Blogger の外部サイト(www2.scaredeer.com)を用意してそこに各種の favicon データを置いてみた(👉 Blogger と独自ドメインの設定 )。Blogger の favicon ガジェットを使うと、自動で 16x16 に圧縮された物凄く汚ないアイコン画像しか使えないからである。 以下、Blogger のテーマの HTML を修正するわけだが、その場合の注意点: 各タグが閉じられていないので、タグの最後の > の直前に / を入れて /> の形式にしておく必要がある。 head 内記述用タグの挿入する位置は CSS 定義よりも前にした方が良い(自分はテーマ HTML の viewport 定義と title の間にした)。そうしないと、meta theme-color が反映されなかった。cf. This value is used by the user agent to draw the background color of a shortcut when the manifest is available before the stylesheet has loaded. 生成される manifest のファイル名が web.manifest となっているが、これは json ファイルなので、manifest.json にファイル名を変更して Web サーバー側で .json ファイルとして適切に MIME が認識されるようにした。これに伴って、head 内記述用タグの manifest のリンク先も修正した。 ついでに manifest の中のエントリーとして description の情報も補っておいた。 head 内記述用タグ manifest.json { "name": "ししおどし", "short_name": "鹿威し...

Blogger と独自ドメインの設定

イメージ
SEO の観点からすると、サブドメインを無闇に乱立させずむしろ一箇所に集約させた方が良いようなので、一箇所に統合することにした。 従来 blog.scaredeer.com(@blogger):ブログ www.scaredeer.com(@nginx サーバー):コンテンツはほぼトップページのみ 統合後 www.scaredeer.com(@blogger):ブログ+ページ サブドメインなしの scaredeer.com は www.scaredeer.com にリダイレクトあれ、またプロトコル面でも、http を https にリダイレクトすることで、厳密に https://www.scaredeer.com へと集約 した。 Blogger での設定 カスタムドメイン:www.scaredeer.com カスタムドメインにリダイレクトする ✅ HTTPS の使用 ✅ HTTPS リダイレクト ✅ DNS(ムームー DNS で)の設定 Blogger でのサードパーティドメインの設定の過程において、DNS 側の一定の設定を行うことが求められる。自分は DNS そのものはあまり詳しくなく、ムームー DNS での設定しか実際に操作する機会がないので、下の設定で本当に良いのかはあまり自信がないが、大体こんなものだろうと思う: サブドメイン 種別 内容 備考 A 216.239.32.21 scaredeer.com 自体の IP アドレス(1/4) A 216.239.34.21 scaredeer.com 自体の IP アドレス(2/4) A 216.239.36.21 scaredeer.com 自体の IP アドレス(3/4) A 216.239.38.21 scaredeer.com 自体の IP アドレス(4/4) TXT google-site-verification=●●● Google にドメインオーナーであることを示す www CNAME ghs.google.com www.scaredeer.com → ghs.google.com ●●● CNAME gv-●●●.dv.googlehosted.com ●●●.scaredeer.com → gv-●●●.d...

Netgear R7800 の OpenWrt 化

イメージ
最新の OpenWrt R7800 用ファームウェア(hnyman ビルド)のインストール NetGear R7800 は一部のハードウェアチップ用ドライバーが非公開のためサポートされていないもの(ハードウェア NAT 機能)もあるが、全体としては Linux カーネルの更新に追従し続けているため、発売当時の OpenWrt ベースのままである純正 OEM ファームウェアよりもはるかに良くなっている(👉 Some notes on the current support in OpenWrt ) このルーターは 2016 年末頃から OpenWrt コミュニティによってサポートされ続けており、既に十分に安定化しているので、迷わず OpenWrt 化することを決意した。特に、R7800 についてはコミュニティの中心的人物である hnyman 氏が コミュニティビルド を用意しており、絶大な支持を集めているので、その通称 hnyman ビルドの stable 版を用いた。 OEM 版からの GUI のファームウェア更新機能を利用してファームウェアを乗せ換えるので、使ったのは *-factory.img である(*-sysupgrade.bin は OpenWrt 化済の場合に OpenWrt の GUI からアップデートする場合に使うもの)。もちろん、 TFTP から *-factory.img を書き込むことも可能(反対に純正 OEM 版に戻す場合も TFTP から R7800-V1.0.2.68.img を書き戻せばよい)。 ちなみに、コミュニティで hnyman 氏らが慎重に検証していたが、OpenWrt 化に先立って予め、何らかの失敗に備えるために純正版の mtd をバックアップしておくような作業をする必要はない。OEM 版ファームウェアを書き戻す際に、付随する設定値を格納するパーティションも初期化されて復活するようになっているようである。そういう意味でやはり Netgear はカスタムファームウェアに対しては非常に寛容で好感の持てるメーカーであり、チップのドライバーの公開・非公開次第では OpenWrt フレンドリーな製品となりやすいブランドだと思う。 Wi-Fi 設定の初期化 👉 OpenWrt での Wi-Fi 設定 (O...

アドレス帳データの iOS (iCloud) から Android (Google コンタクト) への移行

最近、楽天モバイルに乗り換え、スマートフォンの環境を徐々に iOS から Android に再び移行しつつある。逆の方向の移行の場合も似たようなものだが、アドレス帳については、基本的に、vCard 形式のデータでエクスポート&インポートができるので、特に難しくはない。 今回は、Mac 上で、連絡先アプリ(iCloud)から vCard をエクスポートし、Web で Google アカウントの Google コンタクト を開いて、インポート作業を行った。 Web の Google コンタクトでインポートする際に、vCard の拡張子を .vcf にしていないと、読み込めるファイルとして認識されなかった。 個別のアドレスデータは特に問題なくエクスポート&インポートできるが、グルーピング・タグ付けは、それぞれのアドレス帳アプリが行っていることなので、そこは改めてやり直す必要がある。 Google コンタクトインポート直後は、インポートの「月日」の名前を付けられたタグにまとめられている。そこから自分でタグを仕分けする。 少なくとも Web の Google コンタクトでは、デフォルトでは「名姓」の順番で表記されるので、設定で「姓名」に変更する必要があった。 Web の Google コンタクトを変更すれば、そのまま同じ Google アカウントに紐付いた Android のアドレス帳に反映されている。

LMVC (a.k.a. MVVM: ViewModel + DataBinding) と Fat View

LMVC(Android の MVVM)モデル や DataBinding について大体の感じはつかめてきたが、先日、一つ失敗して、学習したことがあった。 ViewModel + DataBinding を使うことによって、LifeCycle でグチャグチャに分断された Activity のあちこちに詰め込まれたコードを ViewModel や View に退避して、Activity をスッキリさせることには成功した。 一方、Activity から追い出したコードを、ViewModel に所属させるのか、View に所属させるのかという部分で間違いを犯した。DataBinding で View のプロパティを LiveData でリアルタイムに反映させることができるのだからと、ほとんどの部分を View に移植したのだ。これが失敗だった。 これは ViewModel が導入される以前の、Activity の肥大化に悩んだ当時の開発者たちが採った Fat View と呼ばれるアプローチと同じもので、Activity が一手に引き受けていた複雑な処理を、View が肩代りするだけの話に過ぎない。もちろん、通常は、Activity と View は一対多の関係だから、Activity に複数の View にまつわる処理が集結するよりはマシだが、単純に View の数に分割されただけで、全体としての複雑さの総量に変化はない。 今回は ViewModel を使っているにもかかわらず、単なる Fat View 的なアプローチと同じ罠に陥るという過ちを犯してしまったわけである。 Fat View の何がいけないかというと、View のプロパティにセットした値が、View で処理される順序が、何ら保証されていないという点である。今回は、ImageView を拡張して、Glide によるリモート画像の読み込みを行うようなことを実現したかったのだが、リモートのアドレスをバインドされた LiveData を通じてダイナミックに設定しようとした。ところが、リモートのアドレスをいくつかの諸条件から組み合わせて動的な生成を行う処理を View 内部に持たせ、バラバラの諸条件を View のプロパティとして入力しようとしたため、アドレスが null の段階で Glide で読み込もうと...

LMVC (a.k.a. MVVM) サンプル

前日の記事「 Android で MVVM ならぬ“LMVC” 」のサンプルコード build.gradle (:app): plugins { id 'com.android.application' } android { compileSdkVersion 30 buildToolsVersion '30.0.3' defaultConfig { applicationId 'com.scaredeer.lvmcsample' minSdkVersion 26 targetSdkVersion 30 versionCode 1 versionName '1.0' } compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } buildFeatures { dataBinding true } } dependencies { implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' // https://developer.android.com/jetpack/androidx/releases/lifecycle#java implementation 'androidx.li...

Android で MVVM ならぬ“LMVC”

イメージ
MVC と MVVM(参考: 2015年に備えて知っておきたいリアクティブアーキテクチャの潮流 )の比較: やはり、MVC の場合と MVVM の場合で、Model の意味合いが変っており、MVVM の方の M は基本的にもう Model と呼ぶべきものではないものとなっていると思う。 基本的にプレゼンテーション層とデータ・ビジネスロジック層を分けるという観点で全体を階層化させているわけだから、MVC のように、入力と出力を分けるという観点とは根本的に異っている。MVC の場合は、入力を抽象化して内部データ化するという処理の部分と、内部データを具象化して出力するという処理の部分を交錯させないで分離するという観点で、その抽象化された内部データの属する部分を Model と呼んでいるわけだ。 なので、MVC と MVVM で名称的に共通するのは View だけであり、Model 部分は紛らわしいので、別のネーミングにすべきではなかったかと思う。むしろ、ViewModel の部分の方が、View にとっての抽象化されたデータの参照元(Model of View となる部分)としての意味で ViewModel と呼ぶのは、まだ理解しうる。Model の方は Model と呼ばずに、Logic などと名付けて LVVM とでもすべきではなかったのだろうか(LVVM では別のタームと被ってしまうから、ViewModel の方をこそ Model と呼んで、LMV (Logic-Model-View) とか LMVC (Logic-Model-ViewControl) でもいいんじゃないかと思う)。 なので以下、敢えて LMVC の用語で行こうと思うが、Logic 層と ViewControl 層の両者の中間に Model 層(俗に言う ViewModel)を設ける意義は、処理の時系列的な連動性を断ち、時間的なバッファを設けることが可能となるからだと思う。ネットワークの非同期処理などを抱える Logic 層、Activity のライフサイクルなどによって頻繁にアプリ外の都合と要因で破棄・再生成されるライフサイクルを持つ ViewControl 層で、それぞれが所属する時間の流れ、ライフサイクルの様相が大きく食い違っており、この異なるフェイズが混じり合うことないように...

Application と ViewModel の使い分けはどうすればいいのか?

Activity か Fragment を基点として「ある程度安定して動けばいいや」的スタイルで Android プログラミングを続けてきたので、Application はたまに使用例に従って採用していただけで、主体的に判断して使用したことはない。それで最近、ボンヤリと、Android プログラミングに関する情報を調べていたら、Activity のライフサイクルに巻き込まれない、 モデル(ビジネスロジック)的なデータは Application で扱う(格納する)べし みたいな話があって、ちょっと気になっていた。 その辺りは特に他のアイデアがなく、自分は Activity や Fragment でそのままデータを持たせていたので、onSaveInstanceState / onRestoreInstanceState で Bundle を使って退避してライフサイクルの輪廻転生をくぐり抜けられるようにしたり、SharedPreferences を使って逐次 Persistent なデータとして退避するなどして、力技で対抗していた。 Application を使えば、もうちょっと楽にできたのかなと思って気にしていたところ、 ViewModel なんてものも存在することを(今さら)知り、Application と ViewModel の使い分けってどうなんだろう? と思った。もちろん、継承関係からしてそもそも存在意義が全然違うのだろうけど、「Activity のライフサイクルの輪廻転生をくぐり抜けて過去・現在・未来の三世を通じた一貫した記憶を保つ」という意味で、Application を使うか ViewModel を使うかということに、どういう違いがあるのだろうかということだ。 まあそもそも、Application の方は、ライフサイクルというよりは、スコープ的なグローバル性やシングルトン性の方がテーマとなるのだろうし、ViewModel の方はライフサイクルまで Activity に巻き添えを食らわないというだけで、あくまでも Activity / Fragment に従属したローカルなインスタンスなんだろうけど。 書いているうちに、全然違うよね〜、誰も疑問に思わないよね〜、という気持ちになってきた……。 Model とは言っても、ViewModel で扱う...