-
Notifications
You must be signed in to change notification settings - Fork 18
JSON RPC API メモ
PeerCastStation の HTML UI では Ajax を使用しており、ページ全体のリロー ドや遷移をさせずにブラウザに表示されるページの情報を更新したり、チャン ネル操作や設定の変更などができる。
具体的には、ブラウザで動いている JavaScript が JSON RPC プロトコル に従って作 成されたリモートプロシージャコールを表す JSON [RFC4627] テキストを所定 の URL に POST し、それに対する応答がサーバーから POST の応答本文とし て返ってくる。
この API を使うと、別のプログラム(別のマシンで動いていても良い)が PeerCastStation から情報を取得したり、PeerCastStation を操作することが できる。
JSON は構造化データをテキストで表わすフォーマットだということは知って いると思う。セキュリティの問題を無視して、やろうと思えば JavaScript パー サーでパースすることができるが、許されている値の種類は JavaScript のサ ブセットになる。
数値 1.0
、文字列 "abc"
、配列 [A, B, C, ...]
、オブジェクト {A:B, ...}
。その他の値として false
, true
, null
が使える。「オブジェク
ト」というのは、JavaScript の用語から来ていて、波括弧で囲まれたキー・
値の組が並んだ「オブジェクト記法」のデータのことだ。
JSON RPC では JSON で要求・応答が行なわれる。
リモートプロシージャ(JSON RPC では「メソッド」と言う)の呼び出しは、以 下のような形式で行なわれる(要求オブジェクト)。
{
"jsonrpc": "2.0",
"id": 6412,
"method": "getVersionInfo",
"params": []
}
method
が呼び出したいメソッドの名前、params
はメソッドに対する引数
だ。
引数を取らないメソッドに対しては、params
キーは省略できるが、存
在する場合は配列かオブジェクトでなければならない。
引数は配列で順番に指定することもできるし、個々の引数にも名前が付いてい
るので、オブジェクトで指定することもできる。f(x)
というメソッドに対
して [1.0]
と 引数を指定するのと {"x": 1.0}
と引数を指定するのは、
同じことだ。
id
は個々の呼び出しを区別するための数値で、対応する応答オブジェクト
に同じ id
が入っている。我々の場合では、複数の要求に対する応答が同じ
経路で順不同で返ってくるような状況は想定していないので、ID の唯一性に
気を配る必要はない。(…と思う。どうなん?)
応答オブジェクトは、成功時には "result"
というキーを含み、値がメソッ
ドの返り値になっている。失敗時には "error"
というキーを含む。詳しく
は JSON RPC の仕様書などを見てください。
PeerCastStation が JSON RPC を受け付ける URL は、
http://localhost:7144/api/1
だ。ここに要求を POST する。
curl
コマンドで getVersionInfo
メソッドを呼び出してみる。
$ curl -H "X-Requested-With: XMLHttpRequest" -H "Content-Type: application/json" -X POST -d '{"jsonrpc": "2.0","id": 6412,"method":"getVersionInfo"}' http://localhost:7144/api/1
{
"jsonrpc": "2.0",
"id": 6412,
"result": {
"agentName": "PeerCastStation/2.3.6.0",
"apiVersion": "1.0.0",
"jsonrpc": "2.0"
}
}
-H
オプションはヘッダーを、-d
は POST の本文データを指定している。
このマシンでは バージョン 2.3.6 の PeerCastStation が動いていることが
わかる。
X-Requested-With
ヘッダーを指定する必要があったことに注意して欲しい。
このヘッダーは、本来ブラウザが Ajax リクエストを発行する時に付くものだ。
PeerCastStation バージョン 1.9 から、JSON RPC の呼び出しにはこのヘッダー
が必要になった。
ローカルマシン以外の PeerCastStation に要求を送る場合には、HTTP Basic 認証で認証する必要が(普通は)ある。
認証が必要であることは、/api/1
への POST に対して 401 Unauthorized
応答が返ってくることでわかる。
HTTP Basic 認証は user:pass
のようなログイン情報を Base64 でエンコー
ドしたものを HTTP ヘッダーで送る方式である。(盗聴されたら簡単にログイ
ン情報を復元できるので一般に推奨されない)
認証情報は Authorization ヘッダーで次のように送る。
Authorization: Basic dXNlcjpwYXNz
dXNlcjpwYXNz
は user:pass
を Base64 エンコードしたもの。Linux では
以下のようにすればコマンドラインから文字列を Base64 エンコードすること
ができる。
$ echo -n "user:pass" | base64
dXNlcjpwYXNz
もちろん暗号ではないので簡単にデコードできる。
$ echo -n "dXNlcjpwYXNz" | base64 -d
user:pass
こんなものを読むよりソースに当たるのが確実(ぉぃ。
APIHost.cs
で定義されている APIContext
クラスのメソッドのうち、
[RPCMethod("getVersionInfo")]
のように RPCMethod 属性が付与されている
ものが、リフレクション魔法により JSON RPC で利用できるようになっている。
C# 風の記法でメソッドのシグネチャを示す。型名 void は値 null だけから なる型。bool は true あるいは false。number? 等は number あるいは null であることを表わす。
ところどころサンプルデータが Ruby 表記でごめんなさい。
チャンネル作成時の詳細を履歴に保存。
object addListener(string address, number port, number localAccepts, number globalAccepts, bool localAuthorizationRequired=false, bool globalAuthorizationRequired=true)
新しく待ち受けポートを追加。
object addYellowPage(string protocol, string name, string uri=null, string announceUri=null, string channelsUri=null)
イエローページを追加。YPビューアの機能が追加されたバージョン 1.9.2 からは、addYellowPage(protocol, name, uri, announceUri, channelsUri)
。(uri は null で良い?)
string broadcastChannel(number? yellowPageId, string sourceUri, string contentReader, object info, object track, string sourceStream=null)
チャンネルを開始。チャンネルIDを返す。contentReader は getContentReaders メソッドで得られる名前を指定する。
チャンネルに再接続。
帯域測定をして帯域幅を Kbps 単位で返す。測定に失敗した場合は null を返す。
466
ポート開放状態をチェックする。
[7144]
新バージョンのチェックを開始する。
ログをクリア。
パスワードを入力せずに設定画面を開いたり、ダイレクト接続で視聴する為に URL に auth=... の形で付与される認証トークン文字列(ユーザー名とパスワー ドをハッシュ化したもの)を取得する。
(ポートごとにパスワードが違うはずだけど、JSON-RPC リクエストを受けとっ たポートの認証トークンになるのかな?)
チャンネル作成フォームに入れた内容の履歴。
[{"streamType"=>"RTMP Source",
"streamUrl"=>"rtmp://localhost/live/livestream",
"bitrate"=>0,
"contentType"=>"Flash Video (FLV)",
"yellowPage"=>"SP",
"channelName"=>"予定地",
"genre"=>"spプログラミング",
"description"=>"ラムダ電卓",
"comment"=>"短時間マイク無し",
"contactUrl"=>
"http://jbbs.shitaraba.net/bbs/read.cgi/game/48538/1391100125/",
"trackTitle"=>"",
"trackAlbum"=>"",
"trackArtist"=>"",
"trackGenre"=>"",
"trackUrl"=>"",
"favorite"=>false},
... ]
チャンネルの接続情報。
[{"connectionId"=>1351461736,
"type"=>"source",
"status"=>"Connected",
"sendRate"=>0.0,
"recvRate"=>64698.2266,
"protocolName"=>"RTMP Source",
"localRelays"=>nil,
"localDirects"=>nil,
"contentPosition"=>345423,
"agentName"=>"FMLE/3.0 (compatible; FMSc/1.0)",
"remoteEndPoint"=>"127.0.0.1:64329",
"remoteHostStatus"=>["local"],
"remoteName"=>"rtmp://localhost/live/livestream"},
{"connectionId"=>1724473770,
"type"=>"direct",
"status"=>"Connected",
"sendRate"=>0.0,
"recvRate"=>0.0,
"protocolName"=>"HTTP Direct",
"localRelays"=>nil,
"localDirects"=>nil,
"contentPosition"=>330616,
"agentName"=>"VLC/2.1.5 LibVLC/2.1.5",
"remoteEndPoint"=>"192.168.0.6:64320",
"remoteHostStatus"=>["local"],
"remoteName"=>"192.168.0.6:64320"},
{"connectionId"=>919361550,
"type"=>"relay",
"status"=>"Connected",
"sendRate"=>60694.1758,
"recvRate"=>16.5836468,
"protocolName"=>"PCP Relay",
"localRelays"=>0,
"localDirects"=>1,
"contentPosition"=>135065042,
"agentName"=>nil,
"remoteEndPoint"=>"***.***.***.***:50475",
"remoteHostStatus"=>["relayFull"],
"remoteName"=>"***.***.***.***:50475"}]
{"info"=>
{"name"=>"テストch",
"url"=>"",
"genre"=>"",
"desc"=>"",
"comment"=>"",
"bitrate"=>512,
"contentType"=>"FLV",
"mimeType"=>"video/x-flv"},
"track"=>{"name"=>"", "genre"=>"", "album"=>"", "creator"=>"", "url"=>""},
"yellowPages"=>[]}
動画プレーヤー接続の情報。
[{"outputId"=>1835339218,
"name"=>"HTTP Direct 127.0.0.1:64191 (NSPlayer/12.0.7601.17514) 472kbps", "type"=>1}]
リレーツリー情報。ルートは自分自身。
[{"sessionId"=>"F46190087E454DE6977B957D2D74D599",
"address"=>"110.4.130.220",
"port"=>7144,
"isFirewalled"=>false,
"localRelays"=>1,
"localDirects"=>0,
"isTracker"=>false,
"isRelayFull"=>true,
"isDirectFull"=>true,
"isReceiving"=>true,
"isControlFull"=>false,
"version"=>nil,
"versionVP"=>nil,
"children"=>
[{"sessionId"=>"0078CC0C7CF28A909E3AF7C5A30FAED6",
"address"=>"***.***.***.***",
"port"=>7144,
"isFirewalled"=>false,
"localRelays"=>0,
"localDirects"=>1,
"isTracker"=>false,
"isRelayFull"=>false,
"isDirectFull"=>true,
"isReceiving"=>true,
"isControlFull"=>false,
"version"=>1218,
"versionVP"=>27,
"versionEX"=>"IM45",
"children"=>[]}]}]
特定のチャンネルの情報。
{"status"=>"Searching",
"source"=>"rtmp://localhost/live/livestream",
"uptime"=>166,
"localRelays"=>0,
"localDirects"=>0,
"totalRelays"=>0,
"totalDirects"=>0,
"isBroadcasting"=>true,
"isRelayFull"=>false,
"isDirectFull"=>false,
"isReceiving"=>false}
すべてのチャンネルの情報。
[{"channelId"=>"A0B184CC8F166FD0BCB9618B74A2CD80",
"status"=>
{"status"=>"Searching",
"source"=>"rtmp://localhost/live/livestream",
"uptime"=>3,
"localRelays"=>0,
"localDirects"=>0,
"totalRelays"=>0,
"totalDirects"=>0,
"isBroadcasting"=>true,
"isRelayFull"=>false,
"isDirectFull"=>false,
"isReceiving"=>false},
"info"=>
{"name"=>"テストch",
"url"=>"",
"genre"=>"",
"desc"=>"",
"comment"=>"",
"bitrate"=>0,
"contentType"=>nil,
"mimeType"=>"application/octet-stream"},
"track"=>{"name"=>"", "genre"=>"", "album"=>"", "creator"=>"", "url"=>""},
"yellowPages"=>[]}]
コンテント解析器の情報。
[{"name"=>"ASF(WMV or WMA)", "desc"=>"ASF(WMV or WMA)"},
{"name"=>"RAW", "desc"=>"RAW"},
{"name"=>"Flash Video (FLV)", "desc"=>"Flash Video (FLV)"},
{"name"=>"Matroska (MKV or WebM)", "desc"=>"Matroska (MKV or WebM)"}]
ここで得られた名前を broadcastChannel の contentReader に指定する。
ネットワークのルーターから UPnP 等で得られた外部IPアドレスを取得する。 返り値は文字列の配列。
PeerCast の接続を受け付けるIPアドレスとポートの情報。
[{"listenerId"=>546346459,
"address"=>"0.0.0.0",
"port"=>7144,
"localAccepts"=>2147483647,
"globalAccepts"=>7,
"localAuthorizationRequired"=>false,
"globalAuthorizationRequired"=>false,
"authenticationId"=>"-!FO;Zsk(atStMKU",
"authenticationPassword"=>"ZVdf_xQqQ,vhDIKk",
"isOpened"=>nil}]
ログバッファーの内容の取得。from は取得を開始する行番号で、null の場合は 0 と同様にログバッファーの先頭から。maxLines は最大何行取得するかで、null の場合制限はなく、ログバッファーの最後まで取得される。
ログバッファーは、最終行としてまだコミットされていない作りかけの行がある。(空行にしかならない?) log キーのテキストは、最終行以外は "\n" で終端される。したがって、ログバッファーが空の場合(コミットされた行が無い場合)は以下のような応答になる。
{"from"=>0, "lines"=>1, "log"=>""}
一方、ログバッファーにコミットされた行が1行ある場合は lines キーは 2 になる。
{"from"=>0,
"lines"=>2,
"log"=>
"OutputListener: 2015-01-18T10:19:31 [OutputListenerThread:0.0.0.0:7144] INFO - Client connected 192.168.0.7:56442\n"}
ログレベルの取得。0
「ログの記録なし」、2
「エラー」、3
「警告」、4
「付加的な情報」、5
「デバッグ用の情報」。1
「致命的なエラー」は欠番。
{"level"=>2}
新バージョン情報の取得。返り値はオブジェクトの配列。
[
{
"title": "Version 2.3.8 (2017年06月02日開発版)",
"publishDate": "2017-06-02T00:00:00+09:00",
"link": "http://www.pecastation.org/files/PeerCastStation-2.3.8.zip",
"description": "<h1>Version 2.3.8 (2017年06月02日開発版)</h1><p>バグ修正とマイナーな機能追加をしました。</p><ul><li>GUIの設定で通知を出さないよう設定できるようにしました。</li><li>GUIでの起動中 のアップデートチェック間隔を2時間から24時間にしました。</li><li>アップデートチェック時の転送量を減らしました。</li><li>チャンネル情報を取得できないチャンネルを視聴しようとした時に接続が切れずに残って いたのを修正しました。</li><li>起動時のポート開放確認で、ポート開放確認自体に失敗した時に未開放扱い になってしまっていたのを開放状態不明のままになるようにしました。</li><li>配信開始時のビットレートに 負数や空文字を設定するとビットレートが正しく設定されないのを修正しました。</li><li>YPからのチャンネ ル情報取得を設定している場合に http://localhost:7144/ypchannels/index.txt でindex.txtの再配信がされ るようにしました。</li><li>RTMPの送信パケットサイズを1536に変更しました。RTMP視聴時に通信のオーバー ヘッドが削減されます。</li><li>zip版でunblock.batで一部DLLのブロックが解除されなかったのを修正しました。</li><li>zip版にデバッグ用のpdbを追加しました。</li></ul>",
"enclosures": [
{
"title": "",
"url": "http://www.pecastation.org/files/PeerCastStation-2.3.8.zip",
"length": 2160689,
"installerType": "archive",
"type": "application/octet-stream"
},
{
"title": "",
"url": "http://www.pecastation.org/files/PeerCastStation-2.3.8.exe",
"length": 2323939,
"installerType": "installer",
"type": "application/octet-stream"
},
{
"title": "",
"url": "http://www.pecastation.org/files/PecaStationd-2.3.8.msi",
"length": 2032488,
"installerType": "serviceinstaller",
"type": "application/octet-stream"
}
]
}, ...
]
ポップアップ用通知メッセージの取得。
[{"type"=>"error", "title"=>"テストch", "message"=>"チャンネルに接続できませんでした"},
{"type"=>"info", "title"=>"テストch", "message"=>"チャンネルが終了しました"},
...]
プラグイン情報の取得。
[{"name"=>"ASF Content Reader",
"isUsable"=>true,
"assembly"=>
{"name"=>"PeerCastStation.ASF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a441b7b23e9d2fd0",
"path"=>"PeerCastStation.ASF.dll",
"version"=>"1.7.9.1",
"copyright"=>" "}},
... ]
リレーに関する設定の取得。
{"maxRelays"=>2,
"maxRelaysPerChannel"=>1,
"maxDirects"=>2,
"maxDirectsPerChannel"=>0,
"maxUpstreamRate"=>600,
"maxUpstreamRatePerChannel"=>0,
"channelCleaner"=>{"mode"=>3, "inactiveLimit"=>60000}}
対応しているソースストリームプロトコルの情報を取得。
[{"name"=>"RTMP Source",
"desc"=>"RTMP Source",
"scheme"=>"rtmp",
"type"=>1,
"defaultUri"=>"rtmp://localhost/live/livestream"},
{"name"=>"http",
"desc"=>"http",
"scheme"=>"http",
"type"=>1,
"defaultUri"=>"http://localhost:8080/"},
{"name"=>"pcp",
"desc"=>"pcp",
"scheme"=>"pcp",
"type"=>2,
"defaultUri"=>""}]
type
は用途を表す。1
は「配信用入力ストリーム」、
2
は「リレー用入力ストリーム」。
{"uptime"=>58541,
"isFirewalled"=>false,
"globalRelayEndPoint"=>["110.*.*.*", 7144],
"globalDirectEndPoint"=>["110.*.*.*", 7144],
"localRelayEndPoint"=>["192.168.0.6", 7144],
"localDirectEndPoint"=>["192.168.0.6", 7144]}
稼働時間、ポート開放状態、IPアドレスなどの情報の取得。
組込み YP ブラウザなどのユーザー設定などを取得する。今のところ user は
"default"
固定?
{"agentName"=>"PeerCastStation/1.7.9.1",
"apiVersion"=>"1.0.0",
"jsonrpc"=>"2.0"}
バージョン情報の取得。
外部サイトの index.txt から取得されたチャンネル一覧。YP ブラウザでの表 示用。オブジェクトの配列。
[
...,
{
"yellowPage": "SP",
"name": "SP ※お知らせ 3/30",
"channelId": "00000000000000000000000000000000",
"tracker": "",
"contactUrl": "http://bayonet.ddo.jp/sp/xgame.html",
"genre": "",
"description": "【重要】配信コンテンツの自粛願いについて。昨今、配信ガイドラインが掲示されるケースが増えてきました。その都度お知らせするにしてもSPとしては限界がありますので、各配信者の方々は配信前にガイドラインの有無のご確認をよろしくお願いいたします。",
"comment": "",
"bitrate": 0,
"contentType": "RAW",
"trackTitle": "",
"album": "",
"creator": "",
"trackUrl": "",
"listeners": -9,
"relays": -9,
"uptime": 0
}]
[{"name"=>"PCP", "protocol"=>"pcp"}]
[{"yellowPageId"=>1901542310,
"name"=>"SP",
"uri"=>"pcp://bayonet.ddo.jp:7146/",
"protocol"=>"pcp",
"channels"=>[]}, # [{channelId, status}...]
... ]
登録されているイエローページの取得。status は配信中のチャンネルとルー トサーバーとの接続状態で、"Idle", "Connecting", "Connected", "Error" のいずれか。
ポートリスナーを削除。
イエローページを削除。
ポートリスナーのユーザー名/パスワードを変える。
YP への接続をはりなおす。
チャンネル詳細を変更。
ポートリスナーのアクセス許可設定を変更。以下の値の論理和である整数。
None: 0
Play: 1
Relay: 2
Metadata: 4
Interface: 8
All: 0x7FFFFFFF
void setListenerAuthorizationRequired(number listenerId, bool localAuthorizationRequired, bool globalAuthorizationRequired)
パスワードによる認証が必要であるかどうかの設定を変更する。
settings は { "level" : 0 }
のようなオブジェクト。数値の意味については getLogSettings の項を参照。ログレベル 1 は 2 と同じものとして扱われる。
リレーに関する設定を変更。settings の形式については getSettings の項を 参照。
イエローページへの掲載を停止する。
チャンネルを停止する。
チャンネルに関して特定の接続を停止する。成功すれば true
、失敗すれば
false
を返す。
YP から index.txt を取得する。