当時の開発ログを見返しながらのメモ。
同じ機械の中ならつながるようになったので、次はスマホ。
ただスマホは携帯回線の NAT の向こうにいるので、外から直接は話しかけられない。
■小さな中継
みんなが話しかけられる場所に中継(relay)を1つ置く。
5/22 の最初の版は C で200行ちょっと。12バイトのヘッダに「誰から・誰へ」を書いて送ると、中継が転送するだけ。
相手は IP・ポートではなくノード番号で覚える。スマホが Wi-Fi から携帯回線に切り替わっても、次に何か送れば住所が勝手に更新される。つなぎ直しの処理が要らない。
最初のテストで、終了の合図を送っても中継が止まらずに固まった。signal() だと受信待ちが自動でやり直される設定になるのが原因。sigaction() に変更。
■認証をつける
5/26 に認証を追加。送る側と中継が同じ鍵を持って、パケットごとに HMAC-SHA256。同じパケットの再送も弾く。
SHA-256 は OpenSSL を使わずに自前。中継は「1ファイル置けば動く」ままにしたかったので。
気をつけたのは確認の順番。署名が正しいのを先に確認して、合っていたときだけ再送チェック用の記録を更新する。逆にすると、でたらめなパケットで記録を進められてしまう。
■カーネルをライブラリにする
Android アプリからはカーネルを共有ライブラリ(.so)として読み込む。5/22 に試したら起動途中で落ちた。
最初は切り替え処理のアセンブリを疑ったけど違った。原因はメモリの端を決める定数。組み込み向けの「メモリの終わりはこのへん」という値が、アドレスがランダムに散らばる環境では的外れになって、メモリの大きさの計算がおかしくなっていた。疑う場所が1段ずれていた。
■APK ができた
26日の最後に APK が1つできた。3.5MB。中に p-kernel と中継につなぐ部分。
標準では充電中だけ動く。アプリを閉じても止まらないように、通知を出したまま動く形(フォアグラウンドサービス)。
ビルド環境は aarch64 の Linux だったけど、Android の開発ツールは x86_64 用しかない。ツールの実行ファイルを1つずつ qemu-x86_64 越しに呼ぶスクリプトで包んで無理やり動かした。遅いけど動く。
ヘッダを探す順番を1つ間違えて、エラーの定義が丸ごと別物になり1時間溶かしたのもこの日…
この日はビルドして中身を確かめたところまで。実際にスマホで動かしたのはもう少しあと。
※リポジトリ: https://github.com/monyuonyu/p-kernel
※この記事は、p-kernel の開発を手伝ってもらっている AI(Claude)と一緒に書いています。