マイクラの RCON パケットにおけるリクエストとレスポンス
マイクラの RCON は TCP/IP ベースになっており、サーバへの接続認証を行ったあとでコマンドを受け付けるので、コマンドを送信するたびに認証処理が必要になる。
パケット構造
フィールド | 型 | パケットサイズ |
---|---|---|
Packet Size | Int32, リトルエンディアン | 10 ~ 4096Byte |
Packet ID | Int32, リトルエンディアン | 4Byte |
Packet Type | Int32, リトルエンディアン | 4Byte |
Packet Body | null終端, ASCII 文字列 | 少なくとも1Byte |
Empty String | null終端, ASCII 文字列 | 1Byte |
パケットサイズ
コマンドのパケットサイズを byte 単位で表す。ただし、この「サイズ」自体のパケットは含まれないので、実際のパケットサイズは 4 Byte 小さい。
Size = ID + Type + Body + EmpStr - 4[Byte]
パケットID
任意の正の整数値をとることができ、リクエストへのレスポンスをする際に使用する。リクエスト処理中に別のリクエストが来た場合、別のIDが割り振られる。
パケットタイプ
サーバに対してどのリクエストを実行するかを指定するためのフィールド。
値 | 記述子 |
---|---|
3 | SERVERDATA_AUTH |
2 | SERVERDATA_AUTH_RESPONSE |
2 | SERVERDATA_EXECCOMMAND |
0 | SERVERDATA_RESPONSE_VALUE |
パケットボディ
エンコードされたnull終端文字列。パケットタイプによって認証、コマンドの実行、レスポンスのいずれかが記述される。
空文字列
パケットの終端に記述されるnull文字で、8ビットの0で構成される。ただし、null終端文字列にならないような場合は 16 ビットの 0 で埋める(おそらく Body 本体の null 終端文字とパケット本体の null 終端文字の 2 Byte 分かも?)
パケット構成
以上を踏まえてのパケット構成はこんな感じ?
+----------+------------+--------------+---------------+-----------+
| Size(int) | ID(4Byte) | Type(4Byte) | Body(NByte) | NULL文字 |
+----------+------------+--------------+---------------+-----------+
リクエストとレスポンスについて
認証用パケットとコマンド用パケットを別で送信することで、認証後にコマンドを実行できるようになる。
Type | IDの割当 | 概要 | Body |
---|---|---|---|
SERVERDATA_AUTH (Type=3) | 任意のID | 接続認証リクエストに使用するパケット | RCON 接続用パスワードが格納される |
SERVERDATA_AUTH_RESPONSE (Type=2) | SERVERDATA_AUTHと同じID※ | 接続認証レスポンスに使用するパケット | 空の文字列 (0x00) が格納される |
SERVERDATA_EXECCOMMAND (Type=2) | 任意のID | コマンド実行リクエストに使用するパケット | サーバで実行されるコマンドが格納される |
SERVERDATA_RESPONSE_VALUE (Type=0) | SERVERDATA_EXECCOMMANDと同じID | コマンド実行に対するレスポンスに使用するパケット | コマンドの実行結果が格納される(空の文字列が格納される可能性もある。) |
通常、RCON パスワードがなし(空文字列)になっている場合は SERVERDATA_AUTH リクエストは拒否されて接続はできない。
もしかすると、コマンド実行後のレスポンスを受け取れなかった場合、SERVERDATA_RESPONSE_VALUE にてリクエスト ID と同じ ID でリクエストすればレスポンスの再取得が可能になる?のかもしれない
※ SERVERDATA_AUTH にて認証が完了するとこのID当てに空の文字列となってレスポンスが返ってくるが、認証に失敗した場合は ID が -1 (0xFF FF FF FF) として返ってくる。通常、リクエスト ID 自体は正の整数値しかとらないので、異常値として検出可能。
RCON コマンドは ASCII コードなので日本語表示できないと思っていたが、どうやら CoreRCON では UTF8 を使用して日本語や中国語といった文字も表示できるようにしている。
もしかしたら UTF8 にすればいけるかもと思っていたが、例外がスローされる。
どうやら、レスポンスのパケットが null なためにパケットサイズが 0 になっており、範囲外参照しようとした結果このような状況になっている。
ちなみに現段階ではこんな感じ。
NetworkStream クラスで書き込みをしようとするとダメっぽい?
CoreRCON のほうでは Socket クラスを使用しているが、結構低レベルな感じなので TcpClient クラスよりも実装が大変かもしれない。
解決した~!
どうやら、一度メモリストリームに格納しないといけないみたい。とりあえず RCON のソースコードをなんとなく眺めていたら気づいた。(やっぱり UTF8 形式でコマンドが実行できるじゃないですかぁ)