ITRON TCP/IP API
仕様の概要

Embedded TCP/IP 技術委員会

なぜITRONでTCP/IP なのか
インターネットにつながる組み込みシステム
ＰＤＡ / インターネット・テレビ / イントラネット用端末/ カーナビゲーションシステム / 携帯電話 …

パソコン、ワークステーションとの接続
コピー機、ＦＡＸをブラウザから設定する、など
工作機械のユーザーインターフェースをＰＣで持たせる（ブラウザなど）

組み込みシステムへの適応
組み込みシステムにおける要求項目
プログラムが小さい（プログラムサイズ・データサイズ）
ＣＰＵの性能をフルに活用
信頼性の確保動的なメモリ管理をもたない
ファイルシステムをもたないソケットインターフェースの問題点
ソケット
動的なメモリ管理を前提としている
設定などの情報をファイルシステムに保存することを前提としているシステムによって差異があり、標準と呼べるものが存在しない

互換性
各社とも独自のインターフェースを持っている
１つのアプリケーションを複数のプラットフォーム上に実装する場合、実装モデルを変更する必要が生ずることもある

仕様作成にあたって
Embedded TCP/IP 技術委員会
ITRON専門委員会の呼び掛けによって1997年3月に発足
成果をITRON専門委員会が承認 → ITRON TCP/IP API 仕様

方針
ソケットインターフェースから大きくははずさない
本APIにライブラリを被せることでソケットインターフェースを実現できるものにする
ITRON上での利用を想定するが、他のＲＴＯＳにも載るよう配慮する
静的な設定を活用する

ITRON TCP/IP API の特徴
TCPと、UDPのAPIを別々に定義「ソケット」に代えて「端点(end point)」を採用
TCP接続要求を受け付ける端点と、TCP接続の端点とは別のオブジェクト。UDP通信端点も別として扱う
ITRON カーネル仕様と同様、明示的に生成・削除を行う
オブジェクト種類毎にシステム内で一意なID番号で識別

コールバックによる非同期インターフェースを用意
UDPの受信はコールバック関数内で行うTCP用の省コピーAPIを用意

ITRON TCP/IP のモデル(１)
待ち受け手順(1)tcp̲cre̲rep();↓tcp̲cre̲cep();↓↑tcp̲acp̲cep();

ITRON TCP/IP のモデル(2)
待ち受け手順(2)↓tcp̲del̲rep();

ITRON TCP/IP のモデル(3)
待ち受け手順(3) 〜 ソケットとの比較
ソケットの場合接続要求が到着する度に、ソケットが１つ新設される。
待ち受け用ソケットは、接続が確立しない。
ITRON TCP/IP の場合
CEP, REPは、明示的に生成される。
接続要求が到着しても、待ち受けに入っているCEPがなければ要求は捨てられる。

TCPのAPI(1)tcp̲cre̲cep：TCP通信端点の生成
ER tcp̲cre̲cep(ID cepid, T̲TCP̲CCEP *pk̲ccep);指定したIDのTCP通信端点を生成する。
パラメータ:
生成するTCP通信端点ID
送信用・受信用、各ウィンドウバッファ送信・受信で個別に指定する
実装によって、サイズのみの指定も許す

コールバックルーチンのアドレス
補足
静的生成が標準でサポートされている。

TCPのAPI(2)tcp̲cre̲rep：TCP受付口の生成ER tcp̲cre̲rep(ID repid, T̲TCP̲CREP *pk̲crep);
指定したIDのTCP通信端点を生成する。
パラメータ:
生成するTCP受付口ID
自分側のIPアドレス
自分側のポート番号補足
一つのシステムで複数のIPアドレスを持つ場合を考慮に入れてある。
IPV4̲ADDRANY(=0)で、すべてのアドレスを指定可能。

TCPのAPI(3)tcp̲con̲cep：接続要求（能動オープン）
ER tcp̲con̲cep(ID cepid,T̲IPV4EP *p̲myaddr, T̲IPV4EP*p̲dstaddr, TMO tmout);
指定したIDのCEPを用いて、指定した相手IPアドレス/ポート番号に対して接続を行う。
パラメータ:
TCP通信端点 ID
自分側のポート番号 (自動割付あり)
相手側のIPアドレスとポート番号
タイムアウト指定 (TMO̲POL, TMO̲FEVR, TMO̲NBLK)
自分側のアドレスの自動割りつけは３通りで行う。

TCPのAPI(4)tcp̲acp̲cep：接続要求待ち(受動オープン)
ER tcp̲acp̲cep(ID cepid, ID repid, T̲IPV4EP *p̲dstaddr,TMO tmout);
指定したTCP受付口に対する接続要求を待つ。
パラメータ:
接続要求を待つTCP受付口ID接続に使うTCP通信端点ID
タイムアウト指定 (TMO̲POL, TMO̲FEVR, TMO̲NBLK)
補足
一つのTCP受付口に対して、同時に複数のtcp̲acp̲cepを発行することが可能。

TCPのAPI(5)tcp̲snd̲dat：データの送信
ER tcp̲snd̲dat(ID cepid, VP data, INT len, TMO tmout);tcp̲rcv̲cep：データの受信
ER tcp̲rcv̲cep(ID cepid, VP data, INT len, TMO tmout);

パラメータ:
コネクションポートID
バッファの先頭と長さ
タイムアウト指定 (TMO̲POL, TMO̲FEVR, TMO̲NBLKTCPのAPI(6)
省コピー送受信ER tcp̲get̲buf(ID cepid, VP *p̲buf, TMO tmout);
次に送信するデータを入れるべきバッファを取り出す。
tcp̲snd̲buf(ID cepid, INT len);tcp̲get̲buf で取り出したバッファに書き込んだデータの送信を手配する。
tcp̲rcv̲buf(ID cepid, VP *p̲buf, TMO tmout);
受信したデータが入っているエリアを取り出す。
tcp̲rel̲buf(ID cepid, INT len);tcp̲rcv̲buf で取り出したバッファ中のデータを捨てる。

TCPのAPI(7)コールバック関数
ER callback(ID cepid, FN fncd, VP p̲parblk);
パラメータ
TCP通信端点ID
事象の種類
事象の種類に固有なパラメータブロックへのアドレス

ノンブロッキングコールの完了通知
fncd = 完了した API の機能コード(例：TFN̲TCP̲SND̲DAT)
p̲parablk -> ercd

緊急データの受信
fncd = TEV̲TCP̲RCV̲OOB ( = 0x0201)
p̲parablk -> ercd

TCPのAPI(8)エラーコードエラーは負の値。０または正の値で正常終了
メインエラーコードとサブエラーコードとで構成される。
ER mainercd(ercd);
ER subercd(ercd);

ITRONカーネルと同一のエラーコード
E̲OK
E̲OBJ

=0= -63

追加したエラーコード
E̲WBLK ( = -83)
E̲CLS ( = -87)
E̲BOVR ( = -89)

ノンブロッキングコール受付
接続が異常切断された
バッファオーバーフロー

使用例(1)
クライアントの場合
void main(void){
ercd = tcp̲cre̲cep(cepid,pk̲ccep);
while (stat) {ercd = tcp̲con̲cep(cepid,p̲myaddr,p̲dstaddr,tmoout);
while (stat) {ercd = tcp̲snd̲cep(cepid, data, len, TMO̲FEVR);
ercd = tcp̲rcv̲cep(cepid, data, len, TMO̲NBLK);}
ercd = tcp̲cls̲cep(cepid, TMO̲FEVR);}
ercd = tcp̲del̲cep(cepid);}使用例(2)
シングルタスク・サーバーの場合
void main(void){
ercd = tcp̲cre̲cep(cepid,pk̲ccep);
ercd = tcp̲cre̲rep(repid,pk̲crep);while (true) {ercd = tcp̲acp̲cep(cepid,repid,dstaddr,tmout);
while (true) {ercd = tcp̲snd̲cep(cepid, data, len, TMO̲FEVR);
ercd = tcp̲rcv̲cep(cepid, data, len, TMO̲NBLK);}
ercd = tcp̲cls̲cep(cepid, TMO̲FEVR);}}

使用例(3)
マルチタスク・サーバーの場合(1)まず、サーバータスクを用意する。
void server(ID repid){
ercd = tcp̲cre̲cep(cepid,pk̲ccep);
while (true) {ercd = tcp̲acp̲cep(cepid,repid,dstaddr,tmout);
while (true) {ercd = tcp̲snd̲cep(cepid, data, len, TMO̲FEVR);
ercd = tcp̲rcv̲cep(cepid, data, len, TMO̲NBLK);}ercd = tcp̲cls̲cep(cepid, TMO̲FEVR);}}

使用例(4)
マルチタスク・サーバーの場合(2)リッスンポートを用意し、サーバータスクを起動する。
静的設定を利用する場合は生成不要。
void main(void){
int i, start̲code;
ercd = tcp̲cre̲rep(repid,pk̲crep);
start̲code = repid;for (i=0; i<SERVER̲NUM; i++) {create & start̲task(server, start̲code);}
sleep̲task(SELF);}

使用例(5)
マルチタスク・サーバーの場合(3)メインタスクサーバータスクサーバータスクサーバータスクサーバータスク

起動
生成

リッスンポート

Accept