;============================================================ ; iron_webserver.hsp — HTTP / HTTPS / WebSocket サーバ ; ; hspwebsrv.dll (Windows HTTP Server API v2 = HTTP.sys 経由) を ; ラップした HSP 向け本格 HTTP サーバ。C# HttpListener と同じ ; backend なので HTTP/HTTPS/WebSocket が単一 DLL で扱える。 ; ; 特徴: ; - HTTP.sys (kernel-mode) backend で高性能 ; - http://localhost:port/ は admin 権限不要 ; - http://+:port/ 等は admin 必要 (netsh http add urlacl) ; - HTTPS は事前に netsh http add sslcert で証明書バインド必要 ; - WebSocket の handshake + フレーム parser も内包 ; ; API (HTTP / HTTPS): ; web_open port ; http://localhost:port/ ; web_open_url "https://localhost:8443/" ; web_accept method, path, body, is_ws [, timeout_ms] ; → stat = 1 (req) / 0 (timeout) / -1 (error) ; → is_ws = 1 なら WebSocket upgrade request ; web_respond status, "ctype", "body" ; web_close ; ; API (WebSocket): ; ws = web_accept_ws() upgrade 受諾 → ws ハンドル ; web_ws_send ws, "text" [, is_binary] ; web_ws_recv ws, buf [, timeout_ms] stat = bytes / 0 (timeout) / -1 (closed) ; web_ws_close ws ; ; 例 (HTTP): ; web_open 8080 ; repeat ; web_accept method, path, body, is_ws, 100 ; if stat = 1 : web_respond 200, "text/html", "

Hello

" ; stick k, 128 : if k & 128 : break ; loop ; web_close ; ; 例 (WebSocket echo): ; web_open 8080 ; repeat ; web_accept method, path, body, is_ws, 100 ; if stat = 1 { ; if is_ws = 1 { ; ws = web_accept_ws() ; repeat ; web_ws_recv ws, msg, 10000 ; if stat <= 0 : break ; web_ws_send ws, "echo: " + msg, 0 ; loop ; web_ws_close ws ; } else { ; web_respond 200, "text/html", "Hello" ; } ; } ; loop ; ; HTTPS を使う場合 (一度きり、admin で実行): ; netsh http add sslcert ipport=0.0.0.0:8443 \ ; certhash=<40桁thumbprint> \ ; appid={12345678-1234-1234-1234-123456789ABC} ;============================================================ #ifndef __iron_webserver_hsp__ #define __iron_webserver_hsp__ #module iron_webserver #uselib "hspwebsrv.dll" #cfunc _websrv_open "websrv_open" int #cfunc _websrv_open_url "websrv_open_url" str #cfunc _websrv_accept "websrv_accept" int, var, int, var, int, var, int, var, int #cfunc _websrv_respond "websrv_respond" int, int, str, str, int #cfunc _websrv_accept_ws "websrv_accept_ws" int #cfunc _websrv_ws_send "websrv_ws_send" int, str, int, int #cfunc _websrv_ws_recv "websrv_ws_recv" int, var, int, int #func _websrv_ws_close "websrv_ws_close" int #func _websrv_close "websrv_close" int #deffunc web_open int port if _web_handle >= 0 : web_close _web_handle = _websrv_open(port) return _web_handle #deffunc web_open_url str url if _web_handle >= 0 : web_close _web_handle = _websrv_open_url(url) return _web_handle #deffunc web_accept var out_method, var out_path, var out_body, var out_is_ws, int timeout_ms, local _to sdim out_method, 32 sdim out_path, 2048 sdim out_body, 16384 out_is_ws = 0 if _web_handle < 0 : return -1 _to = timeout_ms if _to = 0 : _to = 100 return _websrv_accept(_web_handle, out_method, 31, out_path, 2047, out_body, 16383, out_is_ws, _to) #deffunc web_respond int status, str content_type, str body if _web_handle < 0 : return -1 return _websrv_respond(_web_handle, status, content_type, body, 0) #defcfunc web_accept_ws if _web_handle < 0 : return -1 return _websrv_accept_ws(_web_handle) #deffunc web_ws_send int ws, str text, int is_binary return _websrv_ws_send(ws, text, 0, is_binary) #deffunc web_ws_recv int ws, var out_buf, int timeout_ms, local _to sdim out_buf, 16384 _to = timeout_ms if _to = 0 : _to = 1000 return _websrv_ws_recv(ws, out_buf, 16383, _to) #deffunc web_ws_close int ws _websrv_ws_close ws return #deffunc web_close if _web_handle < 0 : return _websrv_close _web_handle _web_handle = -1 return #global _web_handle@iron_webserver = -1 #endif