uIPに付属のWebサーバアプリケーション(apps/webserver)を利用して、TCP/IP上にHTTPを実装します。
Webサーバの動作
Webサーバは、HTTPクライアントからのリクエストを受け取ると、それに対するレスポンスを返します。リクエスト・メッセージを受信すると、GETメソッドからファイル名を獲得し、ファイルシステム中から目的のファイルを探してその内容をクライアントに返します。uIPでは、TCPパケット処理中にコールされるUIP_APP_CALL()内でHTTPの処理が行われます。
HTMLの準備
Webサーバアプリケーションには、Webサーバで使用するHTMLファイルをROM化するperlスクリプト(makefsdata)が付属しています。makefsdataを実行すると、httpd-fsディレクトリに格納されているファイルがunsigned char型の配列データに変換され、その結果がhttpd-fsdata.cという名前のファイルに格納されます。生成されたhttpd-fsdata.cは、その他のプログラムコードと共にコンパイルされて、最終的なプログラムデータに格納されます。
CGIの追加と変更
Webサーバアプリケーションでは、HTTPリクエスト・メッセージによって要求されたファイルの拡張子が.shtmlの場合にCGIの処理が行われます(handle_script())。ファイルの拡張子が.shtmlの場合、そのファイル中に”%!”が存在するかどうかをチェックし、存在すればそれに続く文字列からCGI関数を実行し、その結果をHTMLとして返します。
CGIの追加は、apps/webserver/httpd-cgi.cを変更する事で行います。
CGI追加例:CPUの設定を表示するCGI”cpu-stats”を追加する場合
1. shtml中に記述するCGIの定義
あらかじめ定義されているマクロ”HTTPD_CGI_CALL”を利用して新しいCGIを追加します。ここでは、cpu_statusという名前のCGIを追加しています。
HTTPD_CGI_CALL(cpu, "cpu-stats", cpu_stats);
2. httpd_cgi_call配列の変更
static const struct httpd_cgi_call *calls[] を変更し、1.で追加したcpuを配列に追加します。
static const struct httpd_cgi_call *calls[] = { &cpu, &file, &tcp, &net, NULL };
3. CGI用protothreadの追加
protosocketライブラリを使用して、CGI用の関数cpu_statsを追加します。protothreadは、uIPで提供されているスタックレスthreadであり、protosocketライブラリは、uIPで提供されているSocketインターフェースです。
static PT_THREAD(cpu_stats(struct httpd_state *s, char *ptr)) { PSOCK_BEGIN(&s->sout); PSOCK_GENERATOR_SEND(&s->sout, generate_cpu_stats, s); PSOCK_END(&s->sout); }
4.文字列生成関数の追加
HTML用文字列を生成する関数generate_cpu_statsを追加します。生成した文字列は、グローバル変数uip_appdataに格納します。また、格納した文字列の長さを関数の戻り値とします。
#define ADD_A_ROW(buf,str) do { \ l = strlen(SPACE2); \ strncpy(buf+len,SPACE2,l); \ len += l; \ l = strlen(str); \ strncpy(buf+len,str,l); \ len += l; \ l = strlen(BR); \ strncpy(buf+len,BR,l); \ len += l; \ } while (0) static unsigned short generate_cpu_stats(void *arg) { int l; struct st_cpg x; unsigned short len = 0; x.FRQCR.LONG = CPG.FRQCR.LONG; // SH4レジスタのリード if (x.FRQCR.LONG == 0x10244336) { ADD_A_ROW(buf,"x12"); ADD_A_ROW(buf,"x6"); ADD_A_ROW(buf,"x1"); ADD_A_ROW(buf,"x24/5"); ADD_A_ROW(buf,"x2"); } else { ADD_A_ROW(buf,"Wrong Configuration"); } strncpy((char *)uip_appdata,buf,len); return len; }