LoginSignup
17
16

More than 3 years have passed since last update.

iOSでNode.jsを動かしたい(ついでにWebRTCシグナリングサーバーも)

Last updated at Posted at 2020-12-21

はじめに

これは Node.jsアドベントカレンダー2020の記事です。実用性皆無のネタ記事ですが、リラックスしてお楽しみください。

twitterで「iPadでLinuxが動く」というツイートを見たことがきっかけで、iPad/iPhone上でNode.jsを動かしてみました。内容は次の通りです。

  • iSH Shell で Node.jsを動かす
  • Node.jsでWebサーバーを動かし、Safariでアクセスする
  • オマケ:WebRTCのシグナリングサーバーを動かして、iPadとiPhoneで通信する

iSH Shell

iSH Shellとは

利用するアプリは、「iSH Shell」(App Store)というアプリです。私は知りませんでいたが、以前からあるアプリのようです。
名前は「Shell」とありますが、実際にはアプリケーションレイヤーでlinuxをエミュレーションしています。利用されているディストリビューションは、Alpine Linuxです。

ちなみに使用するには、Bluetoothキーボードがあった方が便利です。

iSH Shellのインストール

普通にApp Storeからインストールします。

中身の確認

  • デフォルトのユーザーは root
  • /etc/issue をみると、Alpine Linux 3.12
  • CPUアーキテクチャーは、i686(インテル系32ビット)
シェルで操作
~# whoami
root

~# cat /etc/issue
Welcome to Alpine Linux 3.12
Kernel \r on an \m (\l)

~# uname -m
i686

[iPadの画面キャプチャー]
iSH_info.png

パッケージマネージャーの追加

アプリをインストールした状態では、Alpineのパッケージマネージャー apk はインストールされていません。どうやらApp Storeの規約上、取り除く必要があったようです。
(※2020.12.15現在、App Store版でもapkがインストール済みになったようです)

こちらの手順に従い、apkをインストールします。

シェルで操作
~# wget -qO- http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86/apk-tools-static-2.10.5-r1.apk | tar -xz sbin/apk.static && ./sbin/apk.static add apk-tools && rm sbin/apk.static && rmdir sbin 2> /dev/null

~# apk --version
apk-tools 2.10.5, compiled for x86.

[apkインストールまでのキャプチャー]
iSH_apk.png

Node.js を動かす

Node.jsのインストール

iSHとapkが用意できたら、念願のNode.jsをインストールします。

~# apk add nodejs
~# apk add npm

~# node -v
v12.18.4
~# npm -v
6.14.6

2020/12/5現在、node v12.18と、npm 6.14がインストールされました。(※npmは応答が返ってくるまで、時間がかかります。何かのタイムアウトが発生している?)

[node, npmインストールまで]
iSH_node_npm.png

REPLの利用

さっそくREPL(対話モード)を動かしてみます。

~# node
Welcome to Node.js v12.18.4.
Type ".help" for more information.
> 1+2+3
6
> console.log('Hello Node.js')
Hello Node.js
undefined
> .exit
~#

[Node.js REPLの様子]
iSH_node_repl.png

Webサーバーを動かす

次はNode.jsを使って、簡単なWebサーバーを動かしてみます。

server.js
const http = require('http');

const server = http.createServer((req, res) => {
  res.end('<html><h1>Hello World!</h1></html>');
});
server.listen(8000);

シェルから起動します。

~# node server.js

iPadの場合

iSHがバックグラウンドに回ってしまうと、内部のプロセスの実行が停止してしまいます。そのためiPadの場合はSplit View(Appleの説明)を使って、iSHとSafariを横に並べて使います。

iPadなら、そこそこ実用的にNode.jsを動かすことができます。

[iSHでWeサーバーを起動、Safariでアクセス]
iSH_web_server.png

iPhoneの場合

iPhoneでは、Split Viewが使えず、同時に2つのアプリを動かすことができません。そこで次の手順で無理やり実行します。

  • iSH上で、サーバーを起動
  • Safarを起動し、http://localhost:8000/にアクセス
    • ロード待ちになる
  • iSHに切り替えると、サーバーがリクエストを処理する
  • 再びSafariに切り替えると、Safari上でページが表示される

リクエストが飛ぶたびに、iSHとSafariを切り替えてやる必要があります。iPhoneではかなり厳しいです。

iSH Shellの制約

iSH Shellではx86をエミュレーとしてLinuxが動いていますが、一部デバイスに近い部分では使えない機能があるようです。具体的には、ネットワーク周りの機能では動かないものがありました。
例えば、Node.jsで次のコードを実行しようとすると、エラーが発生します。

コードの抜粋
  const os = require('os');
  const interfaces = os.networkInterfaces();
エラー
Uncaught:
SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_interface_addresses returned Unknown system error 22 (Unknown system error 22)

ネットワークスインターフェイスの情報が取れていないようです。

オマケ:WebRTCのシグナリングサーバーを動かす

ここからは、完全に個人の興味によるオマケです。

WebRTC とシグナリング

Node.js が動くなら、WebRTCのシグナリングを動かしたくなるのが性分です。

  • WebRTC ... Web Realtime Communitaion
    • Web上で、音声/映像/データをやり取りするための仕組み
    • P2Pでのユースケースを想定して規格が作られたが、いまはサーバー経由の利用が増えている
  • シグナリング
    • これから通信を始める2者が、通信開始に必要な情報を交換するための手続き
    • WebRTCではやり方は規定されていない
      • サーバー経由で、WebSocket等の双方向通信の仕組みでやり取りすることが多い

ここでは説明は省略します。興味がある方は(ちょっと古いですが)こちらをご参照ください。

シグナリングサーバーとWebサーバー

よくあるケース

通常はシグナリングのサーバーはローカルネットワーク内のPC上か、インターネット上で動かし、通信したい2つの端末で接続します。

[通常の構成図]
webrtc_signaling.png

iOSデバイスだけで動かしたい

今回はPC(Mac)やインターネット上のサーバーを利用せず、2台のiOSデバイスだけでシグナリングサーバーを動かし、WebRTC通信を行ってみます。

  • iPad と iPad
  • または、iPad と iPhone

(不自然ではありますが、そういう縛りのある状況でデモしなければならない、という設定をご想像ください汗)

また、ブラウザでメディア通信で使うカメラ/マイクにアクセスするには、セキュリティ上の制限により次の場所にあるWebページの必要があります。

そのため、2台のデバイスそれぞれでWebサーバーは動かします。

[今回の構成図]
webrtc_signaling_deviceonly.png

iSH でWebサーバー/シグナリングサーバーを動かしてみる

Webサーバー/シグナリングサーバは、Node.js + express + ws(WebSocket) で実装しています。

準備(セットアップ)

  • 2台のiOSデバイスを用意 (iPad + iPad, or iPad + iPhone)
  • それぞれに、iSH Shell をインストール、apk, node.js もインストール
  • それぞれに、gitもインストール
    • apk add git
  • それぞれに、コードを取得(ブランチを指定してください)
コードを取得
~# apk add git

~# git clone https://github.com/mganeko/webrtc_1to1.git
~# cd webrtc_1to1
~# npm install

準備(情報収集)

今回シグナリングサーバー役のデバイス1は、iPadを利用する必要があります。(iSHをバックグラウンドに回さないように)。一方、デバイス2側からは、デバイス1のIPアドレスを知っておく必要があります。

  • (A) 両方が、同じWiFi環境にいる場合
    • デバイス1側で、割り振られているIPアドレスを確認
    • 「設定」-「Wi-Fi」- 詳細情報(iボタン)で、ネットワークの情報を確認
      • IPV4アドレスの表から、自分のIPアドレスを取得
      • 192.168.0.xxx など

iOS_addr.jpg

  • (B) それ以外の場合
    • デバイス1側で、「インターネット共有」(テザリング)をオンに
    • デバイス2側で、デバイス1で共有したWiFiに接続
    • デバイス2側で、接続情報を確認
      • IPV4アドレスの表から、「ルーター」のアドレスを確認
      • 172.20.xxx.1 など
      • ※テザリングしているデバイス1でなく、そこのぶら下がるデバイス2側で確認します

iOS_router_addr.jpg

(A),(B)それぞれに応じた方法で取得したシグナリングサーバー(デバイス1)のIPアドレスを、次のステップで利用します。

実行

(1) サーバーの起動

デバイス1、2の両方で、サーバーを起動します。

起動
~# npm start

> webrtc_1to1@1.0.0 start /root/work/webrtc_1to1
> node server_1to1.js
websocket server start. port=8080
Web server start. http://localhost:8080/

(2) SafariでWebサーバーにアクセス

起動したらそれぞれのデバイスでWebサーバーにつなぎますが、デバイスごとにURLが異なります。

  • デバイス1(ローカルのシグナリングサーバーに接続する)
  • デバイス2(シグナリングサーバーのURLを別途指定する)
    • http://localhost:8080/sub.html
    • ※デバイス2がiPhoneの場合は、SahariとiSHを交互に切り替えながら、Webページをロードしてください

[デバイス1の画面(iPad)]
ipad_webrtc.png

[デバイス2の画面(iPhone)]
iphone_webrtc.png

※iOSデバイスがスリープしてしまうと、サーバーの実行が止まります。再度起動し直してください。

(3) カメラ映像の取得

  • デバイス1で、[Start Video]ボタンをタップ
    • アクセス許可を求められたら、[許可]をタップしてください
  • 同様にデバイス2でも、[Start Video]ボタンをタップ
    • アクセス許可を求められたら、[許可]をタップしてください

(4) 接続

接続はデバイス2 (sub.html)側から行います

  • デバイス2側で、テキストエリアにシグナリングサーバーのURLを入力
    • 例えば、「ws://192.168.0.10:8080」
    • ※ポート番号は 8080 です
  • デバイス2側で[Connect]ボタンをタップ
    • 接続情報が交換され、通信が開始します。

ios_webrtc_connected2.jpg

(5) 切断

  • デバイス1,2 どちらでも良いので、[Hang Up]ボタンをタップします
    • ※この状態で[Connect]ボタンをタップすると、再接続できます

コード

https://github.com/mganeko/webrtc_1to1.git にあります。

おわりに

「iOSでNode.jsを動かしたい」という何の実用性もない記事でした。もし不幸にも(?)そういう状況に陥ったら思い出してみてください。

17
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16