CTIPは、アプリケーションからドキュメント変換サーバーCopper PDFの機能を利用するための、ソケット通信プロトコルとして開発されました。 ライブラリのリンクという方法ではなく、ソケット通信により連携することにより、プログラミング言語に依存しない、2つのプログラムが物理的に離れていても連携できるというメリットがあります。
前バージョンのCTIP 1.0は2005年に開発されました。 CTIP 2.0はその後継版で、次の新しい機能を備えています。
新たに、複数の変換結果を結合する機能が追加されました。
CTIPはバイナリデータによって情報をやりとりします。 2バイト以上のデータの固まりは、必ず上位のバイトから送られます。 データの基本単位は次の4通りです。
文字列は次の形式で表します。
ただし
文字列のキャラクタ・エンコーディングは、接続の際にクライアントが決定します。
クライアント-サーバー間でやり取りされるデータは適当な大きさのパケットを単位として 送られます。各パケットは次の形式のバイト列です。
ただし
ドライバがサーバーにTCP接続した後、 プロトコルのバージョンとキャラクタ・エンコーディングをサーバーに知らせるために、 次のメッセージを送ります。
"CTIP/2.0" " " ENCODING "\n"
ENCODINGは以降の通信でstringに使うキャラクタ・エンコーディング名です。
例) UTF-8キャラクタ・エンコーディングを用いる場合、ドライバは次のメッセージを送ります。
"CTIP/2.0 UTF-8\n"
サーバーがプロトコルをサポートしない場合は、直ちに接続が切断されます。 プロトコルをサポートする 場合は、認証状態になります。
接続後、クライアントはサーバーに認証情報を送る必要があります。 認証情報は以下の形式です。
"PLAIN:" USER " " PASSWORD "\n"
USERはユーザー名で、PASSWORDはパスワードです。例えばユーザー名"user"、 パスワード"password"で認証する場合は次の1行を送ります。
PLAIN: user password
認証に成功した場合は、サーバーは"OK \n"を返します。 失敗した場合は"NG \n"を返し、直ちに接続を切断します。
認証の完了後、クライアントからバイナリ形式のパケットを送出することにより、 サーバー側に各種操作を要求することが出来ます。
以下は各パケットの概要と、状態遷移表です。 クライアントから送るパケットには"cXX"、 サーバーから送るパケットには"sXX"、 という名前を付けています。 XXはTYPEの部分の16進数表記です。
TYPE | SPECIFIC | 処理 |
---|---|---|
c01 | NAME(string) VALUE(string) | プロパティの送信 |
c02 | URI(string) MIME_TYPE(string) ENCODING(string) LENGTH(long) | メインドキュメントの開始を通知 |
c03 | URI(string) | メインドキュメントの変換を要求 |
c04 | MODE(byte) | サーバーからリソースを要求するモードに切り替え |
c05 | MODE(byte) | 複数の変換結果を後で結合するモードに切り替え |
c11 | DATA(data) | データ |
c21 | URI(string) MIME_TYPE(string) ENCODING(string) LENGTH(long) | リソースの開始を通知 |
c22 | URI(string) | リソースの不存在を通知 |
c31 | なし | データの終了 |
c32 | MODE(byte) | 中断 |
c33 | なし | 結合 |
c41 | なし | リセット |
c42 | なし | 切断 |
c51 | URI(string) | サーバー情報の問い合わせ |
TYPE | SPECIFIC | 処理 |
---|---|---|
s01 | URI(string) MIME_TYPE(string) ENCODING(string) LENGTH(long) | データの開始 |
s11 | BLOCK_ID(int) DATA(data) | ブロックデータ |
s12 | なし | ブロックの追加 |
s13 | ANCHOR_ID(int) | ブロックの挿入 |
s14 | CODE(short) MESSAGE(string) ARGn(string) | メッセージ |
s15 | LENGTH(long) | メインドキュメントのバイト数 |
s16 | READ(long) | メインドキュメントの読み込み済みバイト数 |
s17 | DATA(data) | データ |
s18 | BLOCK_ID(int) | ブロックのクローズ |
s21 | URI(string) | リソースの要求 |
s31 | なし | データの終了 |
s32 | MODE(byte) CODE(short) MESSAGE(string) ARGn(string) | 処理の中断 |
横軸はパケットの種類、縦軸は状態、各マス目の数値は遷移先の状態です。 空欄の部分では、パケットが無視され、状態の変化はありません。
↓状態 | パケット→ | c01 | c02 | c03 | c04 | c05 | c11 | c21 | c22 | c31 | c32 | c33 | c41 | c42 | c51 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 初期状態 | 0 | 3/8*1 | 4 | 0 | 0 | 2 | 0 | 切断 | 1 | |||||
1 | サーバー情報取得 | ||||||||||||||
2 | リソース送信 | 2 | 0 | ||||||||||||
3 | メインドキュメント送信 | 2 | 4 | ||||||||||||
4 | サーバーからのリソース要求受信 | 4 | |||||||||||||
5 | 要求されたリソース存否判定 | 6 | 4 | ||||||||||||
6 | 要求されたリソース送信 | 6 | 4 | ||||||||||||
7 | メインドキュメント変換結果受信 | 7 | 7 | ||||||||||||
8 | メインドキュメントのパイプライン変換 | 8 | 7 | 7 |
↓状態 | パケット→ | s01 | s11 | s12 | s13 | s14 | s15 | s16 | s17 | s18 | s21 | s31 | s32 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 初期状態 | ||||||||||||
1 | サーバー情報取得 | 1 | 0 | ||||||||||
2 | リソース送信 | ||||||||||||
3 | メインドキュメント送信 | ||||||||||||
4 | サーバーからのリソース要求受信 | 4*2 | 4*2 | 4*2 | 4*2 | 4 | 4 | 4 | 4*2 | 4*2 | 5 | 0 | 0 |
5 | 要求されたリソース存否判定 | ||||||||||||
6 | 要求されたリソース送信 | ||||||||||||
7 | メインドキュメント変換結果受信 | 7*2 | 7*2 | 7*2 | 7*2 | 7 | 7 | 7 | 7*2 | 7*2 | 0 | 0 | |
8 | メインドキュメントのパイプライン変換 | 8*2 | 8*2 | 8*2 | 8*2 | 8 | 8 | 8 | 8*2 | 8*2 | 0 | 0 |
*1 c04によりサーバーからリソースを要求するモードになっている場合は3, それ以外は8に遷移します。
*2 これらのパケットには送られる順序があります。 クライアント側でのデータの構築を参照してください。
初期状態では、次のいずれかの操作を行うことが出来ます。
プロパティを送信(c01)することで、メインドキュメントの変換処理等の、以降のサーバーの動作を変える事が出来ます。 プロパティは名前と値の文字列のペアで、名前と値の組み合わせの意味はサーバーに依存します。
リソースの開始を通知(c21)することで、リソース送信状態に切り替わり、クライアント側からサーバーにデータを送ることが出来ます。 リソースは、メインドキュメントから参照されるデータです。例えば、HTML文書中のIMG要素から参照する画像等です。
サーバーからリソースを要求するモードに切り替える(c04)ことで、ドキュメントから参照されているリソースの送信要求をサーバーから受けられるようになります。 このモードは、ドキュメントの内容を解析しなければ必要なリソースが分からないような状況で有効です。
変換対象となるメインのドキュメントは、クライアントから送信する方法(c02)と、 サーバー側から取得する方法(c03)の2種類があります。 前者の方法では、ドキュメントの送信と変換を並行して行うことが出来、後者の方法ではクライアントが指定したアドレスにサーバーがアクセスします。 後者の方法ではメインのドキュメントをリソースとして事前に送り、後でそのリソースをメインドキュメントとして使用することも出来ます。
ただし、サーバーからリソースを要求するモードでは、必要なリソースの要求とドキュメントの変換処理はクライアントから送られるドキュメントの全体を受信した後に始まります。 従って、ドキュメントの送信と変換は並行しては行われません。
通常は、メインドキュメントの開始(c02)から終了(c31)、あるいはメインドキュメントの変換を要求(c03)した時点で、 変換結果が最後までクライアントに送信されますが、複数の変換結果を結合するモードに切り替える(c05)ことで、 明示的に結合が要求(c33)されるまで最終的な変換結果を出さず、複数の変換があれば、その結果を結合するようにします。
例えば、PDFへの変換であれば通常は別のソースは別のPDFとして返されるのに対し、 結果を結合すると、複数のソースが連結された1つのPDFとして返されます。
サーバー側でメインドキュメントを取得する場合、クライアントはドキュメントのURIを送るだけです(c03)。
ドキュメントの変換を同じ接続で続けて行うと、設定したプロパティと、送信したリソース(事前に送信したものと、サーバーの要求により送信したものも含む)は再利用されます。 そのため、同じ設定やリソースを共有する複数のドキュメントの変換が高速に行えます。 サーバーからリソースを要求するモードに切り替えていた場合は、そのモードも維持されます。
リセット(c41)を行うと、接続を維持したまま、全ての状態がクリアされ、接続直後と同じ状態に戻ります。
クライアントが切断(c42)を要求すると、サーバー側からソケットが切断されます。
サーバー情報の問い合わせ(c51)により、サーバー側のソフトウェアの種類やバージョンを知ることができます。
受け取ることができるデータの詳細はサーバー情報のURIと内容¶を参照してください。
サーバー情報の取得を要求した場合、サーバーからのデータは複数のデータパケット(s17)によって送られ、 データの終了パケット(s31)によって終了します。クライアント側でデータパケットのDATAを連結したものがサーバー情報です。
リソースの送信は、リソースの開始パケット(c21)によって開始し、 クライアントからのデータは複数のデータパケット(c11)によって送られ、 データの終了パケット(c31)によって終了します。 データパケットのDATAを連結したものがサーバー側に記録されるリソースとなります。
クライアントからメインドキュメントのデータを送る場合は、メインドキュメントの開始を通知(c02)し、データの送信を開始します。 複数のデータパケット(c11)によって送り、 データの終了パケット(c31)により終了します。 サーバーからリソースを要求するモードでない場合は、クライアントからのメインドキュメントのデータを送信している最中に、 サーバーがクライアントにデータを送ることがあります。
クライアントは、常にサーバー側に処理を中断するように要求することができます。 処理の中断(c32)は生成済みのデータを出力して中断する方法と、即時中断する方法の2種類があります。 前者ではサーバー側はなるべくきりのよいところまで処理を続けます。 即時中断する場合は、文字どおり強制的にサーバー側の処理を中断します。 どちらの場合も、途中までのページまでしか読み込めないような中途半端なデータや、 そもそも見ることが出来ない不正なデータが生成されてしまう可能性がありますが、 その可能性は後者の方がずっと高くなります。 どの状態かは、サーバーからデータの終了(s31)が通知されるか、処理の中断(s32)のパケットのMODEにより判別することができます。
サーバーからリソースを要求するモードでは、クライアントがメインドキュメントのURIを送った後、 またはメインドキュメントのデータを送り終わった後に、サーバーがリソースの送信をクライアントに要求します(s21)。 リソースの要求はサーバー側の処理結果の送信に混じって行われますが、サーバーがリソースを要求して、 クライアントが要求したリソースを送り終えるまでは、サーバーが処理結果を送ることはありません。 クライアント側のリソース送信の手順は、リソース不存在の通知(c22)を除いては、事前にリソースを送る場合と同じです。
サーバーからリソースが要求された場合は、リソースを送信するか(c21)、リソースが存在しないことを通知(c22)することができます。
サーバーから要求されたリソースを送信する場合の手順は、事前にリソースを送信する場合と同じです。
サーバーがクライアントにデータを送信する方法は2通りあります。 1つ目はデータパケット(s17)による単純な方法で、クライアントはデータパケットのDATAを連結するだけです。
2つ目は断片化されたデータを構築する方法で、 サーバーはブロックの追加パケット、ブロックの挿入パケット、メッセージパケット、ブロックデータパケットを繰り返しクライアントに送ります。 サーバー側からのデータの送信は、サーバ側からのデータの終了(s31), 処理の中断(s32)のいずれかのパケットの送信をもって終了します。
どちらの方法かは、最初にクライアントに送られるパケットがデータパケット(s17)であるか、 ブロックの追加パケット(s12)であるかどうかで判別できます。
後者の場合、クライアントはサーバーの指示に従って、クライアント側のディスク上あるいはメモリ空間にIDが割り付けられた「ブロック」の列を生成します。 データパケットはデータと一緒にブロックのID(BLOCK_ID)を含んでおり、クライアントはそのブロックにデータを追加します。
ブロックのIDは、最初の値が0であるカウンタをクライアント側に持つことにより連番で生成します。
断片化されたデータをサーバーから送る場合は、最初に必ずブロックの追加パケットが送られます。 追加パケットはクライアント側で現在のカウンタのIDを値とするブロックを列の末尾に生成します。 その後、カウンタの値を1つ増加させます。
ブロックの挿入パケットはクライアント側で現在のカウンタのIDを値とするブロックを、 ANCHOR_IDで示されるブロックの直前に生成します。 その後、カウンタの値を1つ増加させます。
ブロックデータパケットを受け取ったクライアントはBLOCK_IDで示されるブロックの末尾にDATAを追加します。
処理中の各種情報やエラーメッセージが送られます。 詳細はメッセージコードの説明を参照してください。
処理の進行状況を確認しやすくするため、メインドキュメントのサイズ(s15)と読み込み済みバイト数(s16)がクライアントに通知されます。 これらは通知されないこともありますし、通知のタイミングも不定期です。
サーバーとの通信が終了した後、クライアントはブロックの列を順に結合し、完成されたデータとします。
クライアントからメインドキュメントを送信(c02)する場合、サーバーからリソースを要求するモードでなければ、ドキュメントの送信と構築が並行して行われます。 このとき、クライアントはメインドキュメントの送信とメインドキュメント変換結果受信を同時に行う必要があります。 そのため、クライアントはノンブロッキングI/Oか、マルチスレッドのいずれかの手段で実装される必要があります。
サーバーの処理方法を指定するために、名前と値のペアで表現されるプロパティです。
ただし
メインドキュメントの本体の開始を通知します。
ただし
サーバー側でメインドキュメントを取得して変換する処理を開始します。
ただし
サーバーからリソースを要求するモードを変更します。
だたし
複数の出力結果を結合するモードを変更します。
だたし
クライアントから送るデータの断片です。
だたし
DATAの大きさには制限があり、最大で8192バイトです。従ってパケット全体の 大きさは最大8193バイトです。
要求されたリソースの開始を通知します。
ただし
要求されたリソースのが存在しなかったことを通知します。
ただし
データの終了です。
だたし
処理を中断することを要求します。
だたし
結果を結合します。
設定済みのプロパティ、サーバーに送信済みのリソースをクリアします。
接続を切断します。
サーバー情報の送信を要求します。
ただし
データの開始をクライアントに通知します。
ただし
クライアント側のブロックにデータを追加します。
だたし
クライアント側にブロックを追加します。
クライアント側にブロックを挿入します。
だたし
サーバーからクライアントに送られるエラー情報等のメッセージです。
だたし
だたし
だたし
クライアント側にデータを送ります。
だたし
クライアントにリソースの送信を要求します。
だたし
結果の送信を終了します。
処理を中断します。
だたし
16ビットのメッセージコードは、次の16進数表記によりクラス分けします。 Xの部分には0~Fの任意の値が入ります。
CTIPインターフェースのメッセージコードは次のとおりです。
コード | 値 | 説明 |
---|---|---|
1001 | abort等により、正常に処理が中断された。 | |
2001 | リソースのURI(string) | ドキュメントから参照されたリソースURIの形式の不正。 |
2002 | ベースURI(string) | 文書のベースURIの形式に不正がある。 |
3001 | ドキュメントのURI(string) | メインドキュメントのURIの形式に不正がある。 |
3002 | エラーメッセージ(string) | 通信エラー。 |
4001 | エラーメッセージ(string) | 予期しないエラー。 |