Skip to content

PCPプロトコルメモ

Philmist edited this page May 22, 2017 · 1 revision

Memo

用語

トラッカー
配信元
Root
YP

オリジナルソースファイル概要

リクエスト・レスポンス用のHTTPヘッダ(もどき)

HTTP_HS_SERVER "Server:"
レスポンスのみ。サーバー名。User-Agentと同じ
HTTP_HS_AGENT "User-Agent:"
リクエストのみ(?)。ユーザーエージェント名。PeerCast/0.1218(VP0027-1)とか。
HTTP_HS_CONTENT "Content-Type:"
レスポンスのみ。コンテントタイプ。PCPの場合"application/x-peercast-pcp"
HTTP_HS_CONNECTION "Connection:"
いずれも。"close"を指定。HTTP 1.1で持続的接続をサポートしないことを示す。
PCX_HS_PCP "x-peercast-pcp:"
いずれも。値に"1"を指定。PCPプロトコルでの通信をすることを示す
PCX_HS_POS "x-peercast-pos:"
いずれも。リクエスト時は値に要求を始めるストリーム位置を指定。 レスポンス時はリクエストにストリーム位置指定があればそれに一番近い保持しているコンテンツ位置 ストリーム位置指定がなければ保持している最後のコンテンツ位置
PCX_HS_CHANNELID "x-peercast-channelid:"
プログレッシブダウンロードのレスポンス時のみ。再生チャンネルID
PCX_HS_OS "x-peercast-os:
旧PeerCastプロトコル用
PCX_HS_DL "x-peercast-download:"
旧PeerCastプロトコル用
PCX_HS_ID "x-peercast-id:"
旧PeerCastプロトコル用
PCX_HS_NETWORKID "x-peercast-networkid:"
旧PeerCastプロトコル用
PCX_HS_MSG "x-peercast-msg:"
旧PeerCastプロトコル用
tCX_HS_SUBNET "x-peercast-subnet:"
未使用
PCX_HS_FULLHIT "x-peercast-fullhit:"
未使用
PCX_HS_MINBCTTL "x-peercast-minbcttl:"
旧PeerCastプロトコル用
PCX_HS_MAXBCTTL "x-peercast-maxbcttl:"
旧PeerCastプロトコル用
PCX_HS_RELAYBC "x-peercast-relaybc:"
旧PeerCastプロトコル用
PCX_HS_PRIORITY "x-peercast-priority:"
旧PeerCastプロトコル用
PCX_HS_FLOWCTL "x-peercast-flowctl:"
旧PeerCastプロトコル用
PCX_HS_PINGME "x-peercast-pingme:"
未使用
tCX_HS_PORT "x-peercast-port:"
未使用
PCX_HS_REMOTEIP "x-peercast-remoteip:"
旧PeerCastプロトコル用
PCX_HS_SESSIONID "x-peercast-sessionid:"
未使用

PCPコマンド

PCP_CONNECT "pcp\n"
バージョン : int = 1
PCP_OK "ok\0\0"
: int = 0

PCP_HELO "helo" 子持ち(PCP_HELO_*)

PCP_HELO_AGENT "agnt"
ユーザーエージェント : string
PCP_HELO_OSTYPE "ostp"
OS種別? : int 内容不明。未使用
PCP_HELO_SESSIONID "sid"
セッションID : byte[16] クライアント毎にランダムで生成
PCP_HELO_PORT "port"
ポート番号 : short listenしてるポート番号
PCP_HELO_PING "ping"
指定したポートへのping要求 : short ポートが開いてるか確認する
PCP_HELO_PONG "pong"
内容不明。未使用
PCP_HELO_REMOTEIP "rip"
リモートIP : int OLEHにつける。自分のグローバルIP
PCP_HELO_VERSION "ver"
クライアントバージョン : int クライアントのバージョン。1218以降を使う
PCP_HELO_BCID "bcid"
配信ID : byte[16] 不明
PCP_HELO_DISABLE "dis"
拒否 : int = 1 OLEHにくっつく。これがあったら接続拒否された。
PCP_OLEH "oleh" 子持ち(PCP_HELO_*)
HELOへの返事
static const ID4 PCP_MODE			= "mode";
static const ID4 PCP_MODE_GNUT06	= "gn06";

static const ID4 PCP_ROOT			= "root";
static const ID4 PCP_ROOT_UPDINT	= "uint";
static const ID4 PCP_ROOT_CHECKVER	= "chkv";
static const ID4 PCP_ROOT_URL		= "url";
static const ID4 PCP_ROOT_UPDATE	= "upd";
static const ID4 PCP_ROOT_NEXT		= "next";


static const ID4 PCP_OS_LINUX		= "lnux";
static const ID4 PCP_OS_WINDOWS		= "w32";
static const ID4 PCP_OS_OSX			= "osx";
static const ID4 PCP_OS_WINAMP		= "wamp";
static const ID4 PCP_OS_ZAURUS		= "zaur";

static const ID4 PCP_GET			= "get";
static const ID4 PCP_GET_ID			= "id";
static const ID4 PCP_GET_NAME		= "name";
PCP_QUIT "quit"
終了コード : int
  • PCP_ERROR_QUIT + 0 通常終了。エラーコード無しまたは不明
  • PCP_ERROR_QUIT + PCP_ERROR_OFFAIR 上流切断、みつからない
  • PCP_ERROR_QUIT + PCP_ERROR_SHUTDOWN PeerCast終了
PCP_ERROR_QUIT    = 1000
PCP_ERROR_BCST    = 2000
PCP_ERROR_READ    = 3000
PCP_ERROR_WRITE   = 4000
PCP_ERROR_GENERAL = 5000
PCP_ERROR_SKIP             = 1
PCP_ERROR_ALREADYCONNECTED = 2
PCP_ERROR_UNAVAILABLE      = 3
PCP_ERROR_LOOPBACK         = 4
PCP_ERROR_NOTIDENTIFIED    = 5
PCP_ERROR_BADRESPONSE      = 6
PCP_ERROR_BADAGENT         = 7
PCP_ERROR_OFFAIR           = 8
PCP_ERROR_SHUTDOWN         = 9
PCP_ERROR_NOROOT           = 10
PCP_ERROR_BANNED           = 11

PCP_CHAN "chan" 子持ち(PCP_CHAN_*) チャンネルデータ PCP_CHAN_ID "id"

チャンネルIDID : byte[16]
PCP_CHAN_BCID "bcid"
配信者ID : byte[16]

PCP_CHAN_KEY "key" depriciated

PCP_CHAN_PKT "pkt"
チャンネルのストリームデータ: 子持ち(PCP_CHAN_PKT_*)
PCP_CHAN_PKT_TYPE "type"
このパケットの種別 : char[4] 以下のいずれか
  • PCP_CHAN_PKT_HEAD = "head"
  • PCP_CHAN_PKT_DATA = "data"
  • PCP_CHAN_PKT_META = "meta" (未使用)
PCP_CHAN_PKT_POS "pos"
パケットのストリーム位置 : int
PCP_CHAN_PKT_DATA "data"
パケットのデータ本体 : byte[len]
PCP_CHAN_INFO "info"
チャンネル情報 : 子持ち(PCP_CHAN_INFO_*)
PCP_CHAN_INFO_TYPE "type"
フォーマット : string オリジナルで対応してるのは以下のどれか "MP3", "OGG", "OGM", "RAW", "NSV", "WMA", "WMV", "PLS", "M3U", "ASX"
PCP_CHAN_INFO_BITRATE "bitr"
ビットレート : int
PCP_CHAN_INFO_GENRE "gnre"
ジャンル : string
PCP_CHAN_INFO_NAME "name"
チャンネル名 : string
PCP_CHAN_INFO_URL "url"
URL : string
PCP_CHAN_INFO_DESC "desc"
詳細 : string
PCP_CHAN_INFO_COMMENT "cmnt"
配信者から : string
PCP_CHAN_INFO_PPFLAGS "pflg"
PPフラグ? : int
PCP_CHAN_TRACK "trck"
トラック情報 : 子持ち(PCP_CHAN_TRACK_*)
PCP_CHAN_TRACK_TITLE "titl"
タイトル : string
PCP_CHAN_TRACK_CREATOR "crea"
アーティスト : string
PCP_CHAN_TRACK_URL "url"
連絡先 : string
PCP_CHAN_TRACK_ALBUM "albm"
アルバム : string
PCP_BCST "bcst"
みんなに回してねパケット : 子持ち(PCP_BCST_*、PCP_HOST)
PCP_BCST_TTL "ttl"
TTL(初期値11、回していくごとに-1) : byte
PCP_BCST_HOPS "hops"
ホップ数(初期値0、回していくごとに+1) : byte
PCP_BCST_FROM "from"
送信元のセッションID : byte[16]
PCP_BCST_DEST "dest"
送信先のセッションID : byte[16] 無ければTTLが無くなるまで回す
PCP_BCST_GROUP "grp"
ブロードキャスト先グループ : byte 以下をORで組み合わせ
  • PCP_BCST_GROUP_ALL 0xff 全部
  • PCP_BCST_GROUP_ROOT 1 未使用
  • PCP_BCST_GROUP_TRACKERS 2 CIN、COUT、上流方向のみ
  • PCP_BCST_GROUP_RELAYS 4 CIN、COUT、RELAY、上流方向(実質全部)
PCP_BCST_CHANID "cid"
チャンネルID : byte[16]
PCP_BCST_VERSION "vers"
クライアントバージョン : int = 1218
PCP_BCST_VERSION_VP "vrvp"
クライアントバージョン(VP) : int = 27
PCP_BCST_VERSION_EX_PREFIX "vexp"
拡張クライアント名 : byte[2] = "PP"
PCP_BCST_VERSION_EX_NUMBER "vexn"
拡張クライアントバージョン : short = 23
PCP_HOST "host"
リレー数やリレー可能情報を流す。通常PCP_BCSTで流れてくる : 子持ち(PCP_HOST_*)
PCP_HOST_ID "id"
セッションID : byte[16]
PCP_HOST_IP "ip"
IPアドレス : int WAN側IPとLAN内IPの2つをつける
PCP_HOST_PORT "port"
ポート番号 : short WAN側ポートとLAN内ポートの2つをつける
PCP_HOST_CHANID "cid"
チャンネルID : byte[16] 省略可能、省略時は親PCP_BCSTのPCP_BCST_CHANIDを使用する
PCP_HOST_NUML "numl"
ローカルリスナー数 : int
PCP_HOST_NUMR "numr"
ローカルリレー数 : int
PCP_HOST_UPTIME "uptm"
アップタイム : int
PCP_HOST_TRACKER "trkr"
未使用。内容不明。
PCP_HOST_VERSION "ver"
クライアントバージョン : int = PCP_CLIENT_VERSION
PCP_HOST_VERSION_VP "vevp"
クライアントバージョン(VP) : int = PCP_CLIENT_VERSION_VP
PCP_HOST_VERSION_EX_PREFIX "vexp"
拡張クライアント名 : byte[2] = "PP"
PCP_HOST_VERSION_EX_NUMBER "vexn"
拡張クライアントバージョン : short = 23
PCP_HOST_CLAP_PP "clap"
拍手数 : int
PCP_HOST_OLDPOS "oldp"
持ってるストリームの一番古い位置 : int
PCP_HOST_NEWPOS "newp"
持ってるストリームの一番新しい位置 : int
PCP_HOST_FLAGS1 "flg1"
ストリームの状態 : byte 以下の値のOR組み合わせ
  • PCP_HOST_FLAGS1_TRACKER = 0x01 自分がトラッカーである
  • PCP_HOST_FLAGS1_RELAY = 0x02 リレー可能である(リレーが一杯でない)
  • PCP_HOST_FLAGS1_DIRECT = 0x04 直接続可能である(直接続が一杯でない)(誰も見ない?)
  • PCP_HOST_FLAGS1_PUSH = 0x08 ポト0である
  • PCP_HOST_FLAGS1_RECV = 0x10 再生中である
  • PCP_HOST_FLAGS1_CIN = 0x20 ControlIN接続が可能である(ControlIN接続が一杯でない)
  • PCP_HOST_FLAGS1_PRIVATE = 0x40 未使用(内容不明)
PCP_HOST_UPHOST_IP "upip"
一個上流のIP : int
PCP_HOST_UPHOST_PORT "uppt"
一個上流のポート : int
PCP_HOST_UPHOST_HOPS "uphp"
一個上流のホップ数 : int
static const ID4 PCP_MESG				= "mesg";
static const ID4 PCP_MESG_ASCII			= "asci";		// ascii/sjis to be depreciated.. utf8/unicode is the only supported format from now.
static const ID4 PCP_MESG_SJIS			= "sjis";
PCP_PUSH "push" 子持ち(PCP_PUSH_*) PCP_BCST_*の下にくっつく
指定のノードにリレーしろ命令
PCP_PUSH_IP "ip"
PUSH先のIPアドレス : int
PCP_PUSH_PORT "port"
PUSH先のポート : short
PCP_PUSH_CHANID "cid"
PUSHするチャンネルID : bytes[16]
static const ID4 PCP_SPKT				= "spkt";

static const ID4 PCP_ATOM				= "atom";	

static const ID4 PCP_SESSIONID			= "sid";

リレーのしかた

  1. 指定したアドレスのぴあきゃすに接続する(127.0.0.1:7144など)
  2. "GET /channel/チャンネルID HTTP/1.0\r\nx-peercast-pcp:1\r\n\r\n"を送る。
  3. HTTPのヘッダを受け取る
  4. HTTPのステータスが404の場合はチャンネル無し。接続終了。
  5. HTTPのステータスが503、200の場合はPCPのハンドシェイク接続をする
  6. HTTPのステータスが503の場合は次に接続すべきノードがPCP_HOSTで最大8個流れてきてPCP_QUITで終了
  7. HTTPのステータスが200の場合はPCP_OKが来て、その後PCP_CHAN_PKTでチャンネルの情報とストリームがだらだら来る
  8. あとは適当な間隔でPCP_HOSTをPCP_BCSTにつけて流してあげればよい

PCPハンドシェイクの仕方

  1. PCP_HELOを送る
  2. PCP_OLEHが帰ってくる

拡張ポイント(予定)

  • Core毎
    • チャンネル作成時(引数:チャンネル)
  • チャンネル毎
    • リレー接続HTTPリクエスト送信時(引数:チャンネル, HTTPヘッダ)
    • HTTPレスポンス受信時(引数:チャンネル, HTTPステータス, HTTPヘッダ)
    • PCPパケット送信時(引数:チャンネル, ATOM)
    • PCPパケット受信時(引数:チャンネル, ATOM)
    • 切断時(引数:チャンネル)
    • アイドル時(引数:チャンネル)
    • 再接続先選択時(引数:チャンネル, 候補リスト)
    • 他の人が接続してきた時の処理など…