This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

libMiMic(MiMic library for mbed)は、WebService機能を提供するSDKです。 mbedでWebAPIに対応したネットワークデバイスを簡単に作ることが出来ます。

libMiMicはMiMic projectで開発しています。MiMic projectについてはこちらをご覧ください。 http://nyatla.jp/mimic/wp/

構成

libMiMicはmbedRTOS上で動作し、ユーザアプリケーションにAPIを提供します。コアAPIはC言語で記述されていますが、使用頻度の高いものについてはmbed向けのC++APIが準備されています。

/media/uploads/nyatla/libmimic-sdk.png

※libMiMicはmbedの標準イーサネットドライバをしようしていません。

標準イーサネットドライバと同時に使用することはできません。

  • MiMicIP - IPv4スタックです。レテンシとメモリ消費量を抑えたuipベースのライブラリです。
  • ARP/ICMP/UDP/TCP - 基礎的なソケットAPIを提供します。APIは独自です。
  • HTTP/1.1 Server - HTTP/1.1に対応したサーバです。マルチセッション・Chunked・持続性接続に対応しています。
  • HTTP Modules - HTTP/1.1の機能モジュールです。以下のモジュールがあります。
    • ROM file provider - ROMに格納したファイルイメージを公開します。
    • File system provider - mbedファイルシステムを公開します。
    • Onchip configuration - プログラムフラッシュを利用して設定を保存します。
    • MiMicVM processor - RPCリクエスト(MiMicVM)を処理します。
    • FileUpload - ファイルアップロードを受け取ります。
    • URL decoder - HTTPリクエストを解析します。
    • UPnP handler -UPnPメッセージを処理します。
    • WebSocket - Websocketサーバです。
  • mDNS - マルチキャストDNSサービスです。
  • UPnP - UPnP/1.0の機能を提供します。UPnP handlerと協調して動作します。(現在はデバイス探索(SSDP)・デスクリプション(Description)のみ実装してあります。)
  • DHCP/APIPA - ゼロコンフィギュレーション用のモジュールです。
  • HTTP/1.1 Client
  • mbed C++ class library - mbed向けのC++CPIです。C言語のものより簡単です。

対応機種

  • mbed(mbed LPC1768)
  • LPCXpresso1769

プログラム

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

サンプル

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

チュートリアル

English

libMiMic(MiMic library for mbed) is SDK which provides Webservice functions. It can be created networking device easily using mbed.

See more MiMic information, See MiMic project website. http://nyatla.jp/mimic/wp/

Structure

libMiMic run on mbed RTOS and provides networking API to user application. This library has C++ class API for the mbed, and low-level C language API.

/media/uploads/nyatla/libmimic-sdk.png

For WebService general, it can be written in a simple C + + API.

libMiMic does not have the standard Ethernet driver of mbed. It is not possible that will be used with the standard Ethernet driver.

  • MiMicIP - IPv4 protocol stack. This is based uip which is reduced memory and latency.
  • ARP / ICMP / UDP / TCP - Those are provide basic IP protocols.
  • HTTP/1.1 Server - The Http server compatible HTTP/1.1. It supports multi-session, chunked transport, persistent connection.
  • HTTP Modules - There are addon-module for HTTP server. The following modules.
    • ROM file module - Publish the file images in ROM.
    • File system module - Publish thefiles in mbed file system.
    • Onchip configuration module - To save the network settings to the program flash via REST.
    • MiMicVM module - To handle the (MiMicVM) RPC request.
    • FileUpload module - Accept a file via HTTP POST.
    • URL dedoce module - A versatility URL decoder.
    • UPnP handle module - To handle UPnP messages.
    • UPnP - This provides UPnP/1.0 device functions. It works together with UPnP handler.
    • Websocket - websocket (version13) server
  • mDNS Service - DNS-SD protocol server.
  • UPnP - This provides UPnP/1.0 device functions which works with UPnP handler. (You have been implemented (SSDP) ? description only (Description) device search now.) It is a module zero configuration for - DHCP / APIPA. mbed C + + class library - C of mbed for + + is the CPI. It is simple than that of the C language.
  • DHCP/APIPA - It support zero-cpnfigulation.
  • mbed C++ class library. Almost APIs for Web applications are available.
  • HTTP/1.1 Client

Supported target

  • mbed(mbed LPC1768)
  • LPCXpresso1769

Application

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

Sample

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

Tutorial

Committer:
nyatla
Date:
Fri Jun 13 11:06:33 2014 +0000
Revision:
72:c118a7aa37a3
Parent:
71:855020258513
Child:
82:03c645af0bb1
mbedAPI???????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nyatla 57:bc4330dfa62f 1 /*********************************************************************************
nyatla 57:bc4330dfa62f 2 * PROJECT: MiMic
nyatla 57:bc4330dfa62f 3 * --------------------------------------------------------------------------------
nyatla 57:bc4330dfa62f 4 *
nyatla 57:bc4330dfa62f 5 * This file is part of MiMic
nyatla 57:bc4330dfa62f 6 * Copyright (C)2011 Ryo Iizuka
nyatla 57:bc4330dfa62f 7 *
nyatla 57:bc4330dfa62f 8 * MiMic is free software: you can redistribute it and/or modify
nyatla 57:bc4330dfa62f 9 * it under the terms of the GNU Lesser General Public License as published
nyatla 57:bc4330dfa62f 10 * by the Free Software Foundation, either version 3 of the License, or
nyatla 57:bc4330dfa62f 11 * (at your option) any later version.
nyatla 57:bc4330dfa62f 12 *
nyatla 57:bc4330dfa62f 13 * This program is distributed in the hope that it will be useful,
nyatla 57:bc4330dfa62f 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nyatla 57:bc4330dfa62f 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nyatla 57:bc4330dfa62f 16 * GNU General Public License for more details.
nyatla 57:bc4330dfa62f 17 *
nyatla 57:bc4330dfa62f 18 * You should have received a copy of the GNU Lesser General Public License
nyatla 57:bc4330dfa62f 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
nyatla 57:bc4330dfa62f 20 *
nyatla 57:bc4330dfa62f 21 * For further information please contact.
nyatla 57:bc4330dfa62f 22 * http://nyatla.jp/
nyatla 57:bc4330dfa62f 23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
nyatla 57:bc4330dfa62f 24 *
nyatla 57:bc4330dfa62f 25 *********************************************************************************/
nyatla 58:03b89038b21a 26 #include "NyLPC_cModWebSocket_protected.h"
nyatla 57:bc4330dfa62f 27 #include "NyLPC_utils.h"
nyatla 57:bc4330dfa62f 28
nyatla 58:03b89038b21a 29 #define HTTP_TIMEOUT NyLPC_TiHttpPtrStream_DEFAULT_HTTP_TIMEOUT
nyatla 57:bc4330dfa62f 30
nyatla 57:bc4330dfa62f 31 #define NyLPC_TcModWebSocket_FRAME_TYPE_BIN 0x01
nyatla 57:bc4330dfa62f 32 #define NyLPC_TcModWebSocket_FRAME_TYPE_TXT 0x02
nyatla 57:bc4330dfa62f 33
nyatla 57:bc4330dfa62f 34
nyatla 57:bc4330dfa62f 35
nyatla 57:bc4330dfa62f 36 #define STRBUF_MAX 32
nyatla 57:bc4330dfa62f 37 struct TModWebSocketHeader
nyatla 57:bc4330dfa62f 38 {
nyatla 57:bc4330dfa62f 39 struct NyLPC_THttpBasicHeader super;
nyatla 57:bc4330dfa62f 40 NyLPC_TcStr_t _tstr;
nyatla 57:bc4330dfa62f 41 NyLPC_TChar _tstr_buf[STRBUF_MAX];
nyatla 57:bc4330dfa62f 42 NyLPC_TChar key[24+4];
nyatla 57:bc4330dfa62f 43 NyLPC_TInt16 version;
nyatla 57:bc4330dfa62f 44 NyLPC_TUInt8 sub_protocol_id;
nyatla 57:bc4330dfa62f 45 NyLPC_TUInt8 message_id;
nyatla 57:bc4330dfa62f 46 const NyLPC_TChar* _ref_sub_protocol;
nyatla 57:bc4330dfa62f 47 };
nyatla 57:bc4330dfa62f 48
nyatla 57:bc4330dfa62f 49
nyatla 57:bc4330dfa62f 50
nyatla 57:bc4330dfa62f 51 #define MESSAGE_ID_UNKNOWN 0x00
nyatla 57:bc4330dfa62f 52 #define MESSAGE_ID_UPGRADE 0x01
nyatla 57:bc4330dfa62f 53 #define MESSAGE_ID_SEC_WEBSOCKET_KEY 0x02
nyatla 57:bc4330dfa62f 54 #define MESSAGE_ID_ORIGIN 0x03
nyatla 57:bc4330dfa62f 55 #define MESSAGE_ID_SEC_WEBSOCKET_PROTOCL 0x04
nyatla 57:bc4330dfa62f 56 #define MESSAGE_ID_SEC_WEBSOCKET_VERSION 0x05
nyatla 57:bc4330dfa62f 57
nyatla 57:bc4330dfa62f 58 static const struct NyLPC_TTextIdTbl msg_tbl[]=
nyatla 57:bc4330dfa62f 59 {
nyatla 57:bc4330dfa62f 60 {"Upgrade",MESSAGE_ID_UPGRADE},
nyatla 57:bc4330dfa62f 61 {"Sec-WebSocket-Key",MESSAGE_ID_SEC_WEBSOCKET_KEY},
nyatla 57:bc4330dfa62f 62 {"Origin",MESSAGE_ID_ORIGIN},
nyatla 57:bc4330dfa62f 63 {"Sec-WebSocket-Protocol",MESSAGE_ID_SEC_WEBSOCKET_PROTOCL},
nyatla 57:bc4330dfa62f 64 {"Sec-WebSocket-Version",MESSAGE_ID_SEC_WEBSOCKET_VERSION},
nyatla 57:bc4330dfa62f 65 {NULL,MESSAGE_ID_UNKNOWN}
nyatla 57:bc4330dfa62f 66 };
nyatla 57:bc4330dfa62f 67
nyatla 57:bc4330dfa62f 68 static NyLPC_TBool messageHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const NyLPC_TChar* i_name,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
nyatla 57:bc4330dfa62f 69 {
nyatla 57:bc4330dfa62f 70 struct TModWebSocketHeader* out=(struct TModWebSocketHeader*)o_out;
nyatla 57:bc4330dfa62f 71 if(i_name!=NULL){
nyatla 57:bc4330dfa62f 72 out->message_id=NyLPC_TTextIdTbl_getMatchIdIgnoreCase(i_name,msg_tbl);
nyatla 57:bc4330dfa62f 73 NyLPC_cStr_clear(&(out->_tstr));
nyatla 57:bc4330dfa62f 74 }else{
nyatla 57:bc4330dfa62f 75 switch(out->message_id)
nyatla 57:bc4330dfa62f 76 {
nyatla 57:bc4330dfa62f 77 case MESSAGE_ID_UPGRADE:
nyatla 57:bc4330dfa62f 78 if(i_c!='\0'){
nyatla 57:bc4330dfa62f 79 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
nyatla 57:bc4330dfa62f 80 NyLPC_OnErrorGoto(ERROR);
nyatla 57:bc4330dfa62f 81 }
nyatla 57:bc4330dfa62f 82 }else{
nyatla 57:bc4330dfa62f 83 //websocketかチェック
nyatla 57:bc4330dfa62f 84 if(!NyLPC_cStr_isEqualIgnoreCase(&out->_tstr,"websocket")){
nyatla 57:bc4330dfa62f 85 return NyLPC_TBool_FALSE;//不一致
nyatla 57:bc4330dfa62f 86 }
nyatla 57:bc4330dfa62f 87 }
nyatla 57:bc4330dfa62f 88 break;
nyatla 57:bc4330dfa62f 89 case MESSAGE_ID_SEC_WEBSOCKET_KEY:
nyatla 57:bc4330dfa62f 90 if(i_c!='\0'){
nyatla 57:bc4330dfa62f 91 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
nyatla 57:bc4330dfa62f 92 NyLPC_OnErrorGoto(ERROR);
nyatla 57:bc4330dfa62f 93 }
nyatla 57:bc4330dfa62f 94 }else{
nyatla 57:bc4330dfa62f 95 //HASH値をコピー
nyatla 57:bc4330dfa62f 96 strcpy(out->key,NyLPC_cStr_str(&out->_tstr));
nyatla 57:bc4330dfa62f 97 }
nyatla 57:bc4330dfa62f 98 break;
nyatla 57:bc4330dfa62f 99 case MESSAGE_ID_SEC_WEBSOCKET_PROTOCL:
nyatla 57:bc4330dfa62f 100 if(i_c!='\0' && i_c!=','){
nyatla 57:bc4330dfa62f 101 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
nyatla 57:bc4330dfa62f 102 NyLPC_OnErrorGoto(ERROR);
nyatla 57:bc4330dfa62f 103 }
nyatla 57:bc4330dfa62f 104 }else{
nyatla 57:bc4330dfa62f 105 //トークン終端
nyatla 57:bc4330dfa62f 106 if(out->_ref_sub_protocol!=NULL){
nyatla 57:bc4330dfa62f 107 //サブプロトコルが指定されている場合はチェック
nyatla 57:bc4330dfa62f 108 if(NyLPC_stricmp(NyLPC_cStr_str(&out->_tstr),out->_ref_sub_protocol)==0){
nyatla 57:bc4330dfa62f 109 out->sub_protocol_id=1;//SubProtocol一致
nyatla 57:bc4330dfa62f 110 }
nyatla 57:bc4330dfa62f 111 }
nyatla 57:bc4330dfa62f 112 //','の時はリセット
nyatla 57:bc4330dfa62f 113 if(i_c!=','){
nyatla 57:bc4330dfa62f 114 NyLPC_cStr_clear(&(out->_tstr));
nyatla 57:bc4330dfa62f 115 }
nyatla 57:bc4330dfa62f 116 }
nyatla 57:bc4330dfa62f 117 break;
nyatla 57:bc4330dfa62f 118 case MESSAGE_ID_SEC_WEBSOCKET_VERSION:
nyatla 57:bc4330dfa62f 119 if(i_c!='\0'){
nyatla 57:bc4330dfa62f 120 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
nyatla 57:bc4330dfa62f 121 NyLPC_OnErrorGoto(ERROR);
nyatla 57:bc4330dfa62f 122 }
nyatla 57:bc4330dfa62f 123 }else{
nyatla 57:bc4330dfa62f 124 //VERSION
nyatla 57:bc4330dfa62f 125 out->version=atoi(NyLPC_cStr_str(&out->_tstr));
nyatla 57:bc4330dfa62f 126 if(out->version<0){
nyatla 57:bc4330dfa62f 127 NyLPC_OnErrorGoto(ERROR);
nyatla 57:bc4330dfa62f 128 }
nyatla 57:bc4330dfa62f 129 }
nyatla 57:bc4330dfa62f 130 }
nyatla 57:bc4330dfa62f 131 }
nyatla 57:bc4330dfa62f 132 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 133 ERROR:
nyatla 57:bc4330dfa62f 134 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 135 }
nyatla 57:bc4330dfa62f 136
nyatla 57:bc4330dfa62f 137
nyatla 57:bc4330dfa62f 138
nyatla 57:bc4330dfa62f 139
nyatla 57:bc4330dfa62f 140 /**
nyatla 57:bc4330dfa62f 141 * デフォルトハンドラ
nyatla 57:bc4330dfa62f 142 */
nyatla 57:bc4330dfa62f 143 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler=
nyatla 57:bc4330dfa62f 144 {
nyatla 57:bc4330dfa62f 145 messageHandler,
nyatla 57:bc4330dfa62f 146 NULL
nyatla 57:bc4330dfa62f 147 };
nyatla 58:03b89038b21a 148
nyatla 57:bc4330dfa62f 149
nyatla 57:bc4330dfa62f 150
nyatla 57:bc4330dfa62f 151 /**
nyatla 57:bc4330dfa62f 152 * コンストラクタ。
nyatla 57:bc4330dfa62f 153 */
nyatla 57:bc4330dfa62f 154 void NyLPC_cModWebSocket_initialize(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_ref_root_path)
nyatla 57:bc4330dfa62f 155 {
nyatla 57:bc4330dfa62f 156 NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_root_path,NULL,0);
nyatla 57:bc4330dfa62f 157 i_inst->_frame_type=NyLPC_TcModWebSocket_FRAME_TYPE_TXT;
nyatla 57:bc4330dfa62f 158 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 159 }
nyatla 57:bc4330dfa62f 160 void NyLPC_cModWebSocket_finalize(NyLPC_TcModWebSocket_t* i_inst)
nyatla 57:bc4330dfa62f 161 {
nyatla 57:bc4330dfa62f 162 NyLPC_cModRomFiles_finalize(&i_inst->super);
nyatla 57:bc4330dfa62f 163 }
nyatla 57:bc4330dfa62f 164 /**
nyatla 57:bc4330dfa62f 165 * モジュールがコネクションをハンドリングできるかを返します。
nyatla 57:bc4330dfa62f 166 */
nyatla 57:bc4330dfa62f 167 NyLPC_TBool NyLPC_cModWebSocket_canHandle(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
nyatla 57:bc4330dfa62f 168 {
nyatla 57:bc4330dfa62f 169 return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection);
nyatla 57:bc4330dfa62f 170 }
nyatla 57:bc4330dfa62f 171
nyatla 57:bc4330dfa62f 172 static union{
nyatla 57:bc4330dfa62f 173 struct TModWebSocketHeader header;
nyatla 57:bc4330dfa62f 174 }work;
nyatla 57:bc4330dfa62f 175
nyatla 57:bc4330dfa62f 176
nyatla 57:bc4330dfa62f 177
nyatla 57:bc4330dfa62f 178 /**
nyatla 57:bc4330dfa62f 179 * モジュールを実行します。
nyatla 57:bc4330dfa62f 180 */
nyatla 57:bc4330dfa62f 181 NyLPC_TBool NyLPC_cModWebSocket_execute(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
nyatla 57:bc4330dfa62f 182 {
nyatla 57:bc4330dfa62f 183 union{
nyatla 57:bc4330dfa62f 184 NyLPC_TcHttpBasicHeaderParser_t parser;
nyatla 57:bc4330dfa62f 185 SHA1_CTX sh1;
nyatla 57:bc4330dfa62f 186 }sh;
nyatla 57:bc4330dfa62f 187
nyatla 57:bc4330dfa62f 188 //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却)
nyatla 57:bc4330dfa62f 189 NyLPC_cHttpdConnection_setReqStatusParsed(i_connection);
nyatla 57:bc4330dfa62f 190
nyatla 57:bc4330dfa62f 191
nyatla 57:bc4330dfa62f 192
nyatla 57:bc4330dfa62f 193 //排他ロック
nyatla 57:bc4330dfa62f 194 NyLPC_cHttpdConnection_lock(i_connection);
nyatla 57:bc4330dfa62f 195 {//parser
nyatla 57:bc4330dfa62f 196
nyatla 57:bc4330dfa62f 197 //初期化
nyatla 57:bc4330dfa62f 198 work.header.version=0;
nyatla 57:bc4330dfa62f 199 work.header.sub_protocol_id=0;
nyatla 57:bc4330dfa62f 200 NyLPC_cStr_initialize(&work.header._tstr,work.header._tstr_buf,STRBUF_MAX);
nyatla 57:bc4330dfa62f 201
nyatla 57:bc4330dfa62f 202 NyLPC_cHttpBasicHeaderParser_initialize(&sh.parser,&handler);
nyatla 57:bc4330dfa62f 203
nyatla 57:bc4330dfa62f 204 //プリフェッチしたデータを流す
nyatla 57:bc4330dfa62f 205 NyLPC_cHttpBasicHeaderParser_parseInit(&sh.parser,&(work.header.super));
nyatla 57:bc4330dfa62f 206 NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&sh.parser,&work.header.super);
nyatla 57:bc4330dfa62f 207 //後続をストリームから取り込む
nyatla 57:bc4330dfa62f 208 if(!NyLPC_cHttpBasicHeaderParser_parseStream(&sh.parser,NyLPC_cHttpdConnection_refStream(i_connection),&(work.header.super))){
nyatla 57:bc4330dfa62f 209 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
nyatla 57:bc4330dfa62f 210 NyLPC_OnErrorGoto(Error1);
nyatla 57:bc4330dfa62f 211 }
nyatla 57:bc4330dfa62f 212 if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&sh.parser,&(work.header.super))){
nyatla 57:bc4330dfa62f 213 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
nyatla 57:bc4330dfa62f 214 NyLPC_OnErrorGoto(Error1);
nyatla 57:bc4330dfa62f 215 }
nyatla 57:bc4330dfa62f 216 //HeaderParserはここで破棄(URLEncode,cSTRも)
nyatla 57:bc4330dfa62f 217 NyLPC_cHttpBasicHeaderParser_finalize(&sh.parser);
nyatla 57:bc4330dfa62f 218
nyatla 57:bc4330dfa62f 219 NyLPC_cStr_finalize(&single_header._tstr);
nyatla 57:bc4330dfa62f 220
nyatla 57:bc4330dfa62f 221
nyatla 57:bc4330dfa62f 222 //HTTP/1.1であること。Connection:Upgradeはチェックしない。
nyatla 57:bc4330dfa62f 223 if(work.header.super.startline.req.version!=NyLPC_THttpVersion_11)
nyatla 57:bc4330dfa62f 224 {
nyatla 57:bc4330dfa62f 225 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400);
nyatla 57:bc4330dfa62f 226 NyLPC_OnErrorGoto(Error2);
nyatla 57:bc4330dfa62f 227 }
nyatla 57:bc4330dfa62f 228 if(NyLPC_cHttpdConnection_getMethod(i_connection)!=NyLPC_THttpMethodType_GET){
nyatla 57:bc4330dfa62f 229 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400);
nyatla 57:bc4330dfa62f 230 NyLPC_OnErrorGoto(Error2);
nyatla 57:bc4330dfa62f 231 }
nyatla 57:bc4330dfa62f 232 //WebSocket version 13であること
nyatla 57:bc4330dfa62f 233 if(work.header.version!=13){
nyatla 57:bc4330dfa62f 234 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400);
nyatla 57:bc4330dfa62f 235 NyLPC_OnErrorGoto(Error2);
nyatla 57:bc4330dfa62f 236 }
nyatla 57:bc4330dfa62f 237
nyatla 57:bc4330dfa62f 238 //レスポンスの生成(生データを直接ストリームへ書きこむ)
nyatla 57:bc4330dfa62f 239 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection),
nyatla 57:bc4330dfa62f 240 "HTTP/1.1 101 Switching Protocols\r\n" //32+2
nyatla 57:bc4330dfa62f 241 "Upgrade: websocket\r\n" //18+2
nyatla 57:bc4330dfa62f 242 "Connection: Upgrade\r\n" //19+2
nyatla 57:bc4330dfa62f 243 "Sec-WebSocket-Accept: " //22
nyatla 57:bc4330dfa62f 244 ,32+2+18+2+19+2+22)){
nyatla 57:bc4330dfa62f 245 NyLPC_OnErrorGoto(Error3);
nyatla 57:bc4330dfa62f 246 }
nyatla 57:bc4330dfa62f 247 //SH1キーの生成
nyatla 57:bc4330dfa62f 248 SHA1Init(&sh.sh1);
nyatla 57:bc4330dfa62f 249 SHA1Update(&sh.sh1,(const unsigned char*)work.header.key,strlen(work.header.key));
nyatla 57:bc4330dfa62f 250 SHA1Update(&sh.sh1,(const unsigned char*)"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",36);
nyatla 57:bc4330dfa62f 251 //ワークメモリ32バイトはstrの使いまわし
nyatla 57:bc4330dfa62f 252 SHA1Final((unsigned char*)(work.header._tstr_buf),&sh.sh1);
nyatla 57:bc4330dfa62f 253 //BASE64化(single_header.keyへ出力)
nyatla 57:bc4330dfa62f 254 NyLPC_cBase64_encode(work.header._tstr_buf,20,work.header.key);
nyatla 57:bc4330dfa62f 255 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection),work.header.key,28)){
nyatla 57:bc4330dfa62f 256 NyLPC_OnErrorGoto(Error3);
nyatla 57:bc4330dfa62f 257 }
nyatla 57:bc4330dfa62f 258 //SubProtocolの認証が有る場合
nyatla 57:bc4330dfa62f 259 if(work.header.sub_protocol_id!=0){
nyatla 57:bc4330dfa62f 260 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection)
nyatla 57:bc4330dfa62f 261 ,"\r\nSec-WebSocket-Protocol: " //24
nyatla 57:bc4330dfa62f 262 ,24)){
nyatla 57:bc4330dfa62f 263 NyLPC_OnErrorGoto(Error3);
nyatla 57:bc4330dfa62f 264 }
nyatla 57:bc4330dfa62f 265 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection)
nyatla 57:bc4330dfa62f 266 ,work.header._ref_sub_protocol
nyatla 57:bc4330dfa62f 267 ,strlen(work.header._ref_sub_protocol)))
nyatla 57:bc4330dfa62f 268 {
nyatla 57:bc4330dfa62f 269 NyLPC_OnErrorGoto(Error3);
nyatla 57:bc4330dfa62f 270 }
nyatla 57:bc4330dfa62f 271 }
nyatla 57:bc4330dfa62f 272 //Sec-WebSocket-Protocol
nyatla 57:bc4330dfa62f 273 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_connection),"\r\n\r\n",4)){
nyatla 57:bc4330dfa62f 274 NyLPC_OnErrorGoto(Error3);
nyatla 57:bc4330dfa62f 275 }
nyatla 58:03b89038b21a 276 //connection phase
nyatla 57:bc4330dfa62f 277 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 57:bc4330dfa62f 278 }
nyatla 57:bc4330dfa62f 279 //占有解除
nyatla 57:bc4330dfa62f 280 NyLPC_cHttpdConnection_unlock(i_connection);
nyatla 57:bc4330dfa62f 281 //参照コネクションの設定
nyatla 57:bc4330dfa62f 282 i_inst->_ref_connection=i_connection;
nyatla 57:bc4330dfa62f 283 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 284 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 285 Error3:
nyatla 57:bc4330dfa62f 286 Error2:
nyatla 57:bc4330dfa62f 287 //VM排他ロックの解除
nyatla 57:bc4330dfa62f 288 NyLPC_cHttpdConnection_unlock(i_connection);
nyatla 57:bc4330dfa62f 289 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 290 Error1:
nyatla 57:bc4330dfa62f 291 NyLPC_cHttpBasicHeaderParser_finalize(&parser);
nyatla 57:bc4330dfa62f 292 NyLPC_cStr_finalize(&single_header._tstr);
nyatla 57:bc4330dfa62f 293 //VM排他ロックの解除
nyatla 57:bc4330dfa62f 294 NyLPC_cHttpdConnection_unlock(i_connection);
nyatla 57:bc4330dfa62f 295 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 296 }
nyatla 57:bc4330dfa62f 297
nyatla 57:bc4330dfa62f 298
nyatla 57:bc4330dfa62f 299
nyatla 57:bc4330dfa62f 300 static void writeClosePacket(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code)
nyatla 57:bc4330dfa62f 301 {
nyatla 57:bc4330dfa62f 302 char w[4];
nyatla 57:bc4330dfa62f 303 w[0]=0x88;
nyatla 57:bc4330dfa62f 304 w[1]=0x02;
nyatla 57:bc4330dfa62f 305 *((NyLPC_TUInt16*)(&w[2]))=NyLPC_htons(i_code); //REASON
nyatla 57:bc4330dfa62f 306 //CloseFrame送信
nyatla 57:bc4330dfa62f 307 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,4);
nyatla 57:bc4330dfa62f 308 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 309 }
nyatla 57:bc4330dfa62f 310
nyatla 57:bc4330dfa62f 311
nyatla 58:03b89038b21a 312 NyLPC_TBool NyLPC_cModWebSocket_canRead(const NyLPC_TcModWebSocket_t* i_inst)
nyatla 57:bc4330dfa62f 313 {
nyatla 57:bc4330dfa62f 314 const NyLPC_TUInt8* rx;
nyatla 58:03b89038b21a 315 return NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,0)>0;
nyatla 58:03b89038b21a 316 }
nyatla 58:03b89038b21a 317
nyatla 58:03b89038b21a 318 #define FLAGS_MASK_BIT 7
nyatla 58:03b89038b21a 319
nyatla 58:03b89038b21a 320 /**
nyatla 58:03b89038b21a 321 * Websocketの状態を更新します。
nyatla 58:03b89038b21a 322 * @return
nyatla 58:03b89038b21a 323 */
nyatla 58:03b89038b21a 324 void NyLPC_cModWebSocket_update(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt32 i_time_out)
nyatla 58:03b89038b21a 325 {
nyatla 58:03b89038b21a 326 const NyLPC_TUInt8* rx;
nyatla 58:03b89038b21a 327 NyLPC_TInt32 rs;
nyatla 57:bc4330dfa62f 328 NyLPC_TUInt16 header_size;
nyatla 57:bc4330dfa62f 329 NyLPC_TUInt8 w8[2];
nyatla 57:bc4330dfa62f 330 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 58:03b89038b21a 331 return;
nyatla 57:bc4330dfa62f 332 }
nyatla 57:bc4330dfa62f 333 START:
nyatla 58:03b89038b21a 334 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,i_time_out);
nyatla 58:03b89038b21a 335
nyatla 57:bc4330dfa62f 336 //Error?
nyatla 57:bc4330dfa62f 337 if(rs<0){
nyatla 57:bc4330dfa62f 338 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 339 }
nyatla 57:bc4330dfa62f 340 //Timeout?
nyatla 57:bc4330dfa62f 341 if(rs==0){
nyatla 57:bc4330dfa62f 342 goto Timeout;
nyatla 57:bc4330dfa62f 343 }
nyatla 57:bc4330dfa62f 344 switch(i_inst->_payload_st){
nyatla 58:03b89038b21a 345 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 58:03b89038b21a 346 //ペイロード読み出し中破何もしない
nyatla 58:03b89038b21a 347 return;
nyatla 57:bc4330dfa62f 348 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 57:bc4330dfa62f 349 //ペイロード
nyatla 57:bc4330dfa62f 350 //2バイト溜まるまで待つ
nyatla 57:bc4330dfa62f 351 if(rs<2){
nyatla 57:bc4330dfa62f 352 //Timeout?
nyatla 57:bc4330dfa62f 353 goto Timeout;
nyatla 57:bc4330dfa62f 354 }
nyatla 57:bc4330dfa62f 355 //ペイロードサイズの分析
nyatla 57:bc4330dfa62f 356 if((0x7f&rx[1])<=125){
nyatla 57:bc4330dfa62f 357 header_size=2+(((rx[1]&0x80)==0x80)?4:0);
nyatla 57:bc4330dfa62f 358 i_inst->payload_size=(0x7f&rx[1]);
nyatla 57:bc4330dfa62f 359 }else if((0x7f&rx[1])==126){
nyatla 57:bc4330dfa62f 360 if(rs<4){
nyatla 57:bc4330dfa62f 361 //Timeout?
nyatla 57:bc4330dfa62f 362 goto Timeout;
nyatla 57:bc4330dfa62f 363 }
nyatla 57:bc4330dfa62f 364 header_size=2+2+(((rx[1]&0x80)==0x80)?4:0);
nyatla 57:bc4330dfa62f 365 i_inst->payload_size=(rx[2]<<8)|rx[3];
nyatla 57:bc4330dfa62f 366 }else{
nyatla 57:bc4330dfa62f 367 //CLOSEの送信
nyatla 57:bc4330dfa62f 368 writeClosePacket(i_inst,1009);
nyatla 57:bc4330dfa62f 369 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 370 }
nyatla 57:bc4330dfa62f 371 //十分なヘッダが集まったかチェック
nyatla 57:bc4330dfa62f 372 if(rs<header_size){
nyatla 57:bc4330dfa62f 373 goto Timeout;
nyatla 57:bc4330dfa62f 374 }
nyatla 57:bc4330dfa62f 375 i_inst->_frame_flags_bits=0;
nyatla 57:bc4330dfa62f 376 //FINがセットされていること.断片化禁止!
nyatla 57:bc4330dfa62f 377 if((rx[0]&0x80)!=0x80){
nyatla 57:bc4330dfa62f 378 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 379 }
nyatla 57:bc4330dfa62f 380 //必要ならMaskをコピー
nyatla 57:bc4330dfa62f 381 if((rx[1]&0x80)==0x80){
nyatla 57:bc4330dfa62f 382 memcpy(i_inst->_frame_mask,(rx+header_size-4),4);
nyatla 57:bc4330dfa62f 383 NyLPC_TUInt8_setBit(i_inst->_frame_flags_bits,FLAGS_MASK_BIT);
nyatla 57:bc4330dfa62f 384 }
nyatla 57:bc4330dfa62f 385 i_inst->payload_ptr=0;
nyatla 57:bc4330dfa62f 386
nyatla 57:bc4330dfa62f 387 //パケットサイズの確定(基本ヘッダ+マスク)
nyatla 57:bc4330dfa62f 388 switch(rx[0]&0x0f){
nyatla 57:bc4330dfa62f 389 case 0x00:
nyatla 57:bc4330dfa62f 390 //継続パケットは扱わない
nyatla 57:bc4330dfa62f 391 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 392 case 0x01:
nyatla 57:bc4330dfa62f 393 if(i_inst->_frame_type!=NyLPC_TcModWebSocket_FRAME_TYPE_TXT){
nyatla 57:bc4330dfa62f 394 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 395 }
nyatla 57:bc4330dfa62f 396 break;
nyatla 57:bc4330dfa62f 397 case 0x02:
nyatla 57:bc4330dfa62f 398 if(i_inst->_frame_type==NyLPC_TcModWebSocket_FRAME_TYPE_BIN){
nyatla 57:bc4330dfa62f 399 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 400 }
nyatla 57:bc4330dfa62f 401 break;
nyatla 57:bc4330dfa62f 402 case 0x08://close(非断片)
nyatla 57:bc4330dfa62f 403 //CloseFrame送信
nyatla 57:bc4330dfa62f 404 writeClosePacket(i_inst,1009);
nyatla 57:bc4330dfa62f 405 //Errorとして処理
nyatla 57:bc4330dfa62f 406 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 407 case 0x09://ping(非断片)
nyatla 57:bc4330dfa62f 408 //PONGを送信
nyatla 57:bc4330dfa62f 409 w8[0]=0x0a;
nyatla 57:bc4330dfa62f 410 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w8,1);
nyatla 57:bc4330dfa62f 411 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx+1,header_size-1);
nyatla 57:bc4330dfa62f 412 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 413 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 414 while(i_inst->payload_size!=i_inst->payload_ptr){
nyatla 58:03b89038b21a 415 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 57:bc4330dfa62f 416 if(rs<=0){
nyatla 57:bc4330dfa62f 417 if(rs<0){
nyatla 57:bc4330dfa62f 418 //Error
nyatla 57:bc4330dfa62f 419 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 420 }
nyatla 57:bc4330dfa62f 421 //Timeout
nyatla 57:bc4330dfa62f 422 goto Timeout;
nyatla 57:bc4330dfa62f 423 }
nyatla 57:bc4330dfa62f 424 //読み込みサイズを決定
nyatla 57:bc4330dfa62f 425 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx,rs);
nyatla 57:bc4330dfa62f 426 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 57:bc4330dfa62f 427 i_inst->payload_ptr+=rs;
nyatla 57:bc4330dfa62f 428 }
nyatla 57:bc4330dfa62f 429 //Timeout(パケットスタートに戻る?)
nyatla 57:bc4330dfa62f 430 goto START;
nyatla 57:bc4330dfa62f 431 case 0x0a://pong(非断片)
nyatla 57:bc4330dfa62f 432 //パケットの読み捨て
nyatla 57:bc4330dfa62f 433 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 434 while(i_inst->payload_size!=i_inst->payload_ptr){
nyatla 58:03b89038b21a 435 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 57:bc4330dfa62f 436 if(rs<=0){
nyatla 57:bc4330dfa62f 437 if(rs<0){
nyatla 57:bc4330dfa62f 438 //Error
nyatla 57:bc4330dfa62f 439 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 440 }
nyatla 57:bc4330dfa62f 441 //Timeout
nyatla 57:bc4330dfa62f 442 goto Timeout;
nyatla 57:bc4330dfa62f 443 }
nyatla 57:bc4330dfa62f 444 //読み込みサイズを決定
nyatla 57:bc4330dfa62f 445 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 57:bc4330dfa62f 446 i_inst->payload_ptr+=rs;
nyatla 57:bc4330dfa62f 447 }
nyatla 57:bc4330dfa62f 448 //Timeout(パケットスタートに戻る?)
nyatla 57:bc4330dfa62f 449 goto START;
nyatla 57:bc4330dfa62f 450 default:
nyatla 57:bc4330dfa62f 451 //知らないコードはエラー
nyatla 57:bc4330dfa62f 452 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 453 }
nyatla 57:bc4330dfa62f 454 //読み出し位置のシーク(Header部)
nyatla 57:bc4330dfa62f 455 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 456 //ペイロード読み出しへ
nyatla 57:bc4330dfa62f 457 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_READ_PAYLOAD;
nyatla 57:bc4330dfa62f 458 //継続してペイロード受信処理
nyatla 58:03b89038b21a 459 return;
nyatla 58:03b89038b21a 460 }
nyatla 58:03b89038b21a 461 //処理されなければエラー
nyatla 58:03b89038b21a 462 Error:
nyatla 58:03b89038b21a 463 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 58:03b89038b21a 464 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 58:03b89038b21a 465 return;
nyatla 58:03b89038b21a 466 Timeout:
nyatla 58:03b89038b21a 467 return;
nyatla 58:03b89038b21a 468 }
nyatla 58:03b89038b21a 469
nyatla 71:855020258513 470
nyatla 71:855020258513 471 /**
nyatla 71:855020258513 472 * 受信データをコールバック関数に通知するNyLPC_cModWebSocket_readです。
nyatla 71:855020258513 473 * @return
nyatla 71:855020258513 474 * n>0:データ受信
nyatla 71:855020258513 475 * 0 :タイムアウト。コネクションの状態は変化しない。
nyatla 71:855020258513 476 * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。
nyatla 71:855020258513 477 */
nyatla 71:855020258513 478 NyLPC_TInt16 NyLPC_cModWebSocket_readCB(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcModWebSocket_onRreadCB i_cb,void* i_cb_param)
nyatla 71:855020258513 479 {
nyatla 71:855020258513 480 const NyLPC_TUInt8* rx;
nyatla 71:855020258513 481 NyLPC_TInt32 rs,rd,i;
nyatla 71:855020258513 482 //ストリームの状態を更新する。
nyatla 71:855020258513 483 NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);
nyatla 71:855020258513 484
nyatla 71:855020258513 485 switch(i_inst->_payload_st)
nyatla 71:855020258513 486 {
nyatla 71:855020258513 487 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 71:855020258513 488 break;//処理継続
nyatla 71:855020258513 489 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 71:855020258513 490 //タイムアウト扱い
nyatla 71:855020258513 491 return 0;
nyatla 71:855020258513 492 default:
nyatla 71:855020258513 493 return -1;
nyatla 71:855020258513 494 }
nyatla 71:855020258513 495 //読み出し可能なデータをパース
nyatla 71:855020258513 496 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 71:855020258513 497 if(rs<=0){
nyatla 71:855020258513 498 if(rs<0){
nyatla 71:855020258513 499 //Error
nyatla 71:855020258513 500 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 501 }
nyatla 71:855020258513 502 //Timeout
nyatla 71:855020258513 503 goto Timeout;
nyatla 71:855020258513 504 }
nyatla 71:855020258513 505 rd=0;//読みだしたバイト数
nyatla 71:855020258513 506 //アンマスク
nyatla 71:855020258513 507 if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){
nyatla 71:855020258513 508 //マスク有の時
nyatla 71:855020258513 509 for(i=0;i<rs;i++){
nyatla 71:855020258513 510 rd++;
nyatla 71:855020258513 511 switch(i_cb(i_cb_param,rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4])){
nyatla 71:855020258513 512 case 1:
nyatla 71:855020258513 513 continue;
nyatla 71:855020258513 514 case 0:
nyatla 71:855020258513 515 break;
nyatla 71:855020258513 516 default:
nyatla 71:855020258513 517 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 518 }
nyatla 71:855020258513 519 }
nyatla 71:855020258513 520 }else{
nyatla 71:855020258513 521 //マスクなしの時
nyatla 71:855020258513 522 for(i=0;i<rs;i++){
nyatla 71:855020258513 523 rd++;
nyatla 71:855020258513 524 switch(i_cb(i_cb_param,rx[i])){
nyatla 71:855020258513 525 case 1:
nyatla 71:855020258513 526 continue;
nyatla 71:855020258513 527 case 0:
nyatla 71:855020258513 528 break;
nyatla 71:855020258513 529 default:
nyatla 71:855020258513 530 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 531 }
nyatla 71:855020258513 532 }
nyatla 71:855020258513 533 }
nyatla 71:855020258513 534 //読取位置を移動
nyatla 71:855020258513 535 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rd);
nyatla 71:855020258513 536 i_inst->payload_ptr+=rd;
nyatla 71:855020258513 537 if(i_inst->payload_size==i_inst->payload_ptr){
nyatla 71:855020258513 538 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 71:855020258513 539 }
nyatla 71:855020258513 540 return rd;
nyatla 71:855020258513 541 //処理されなければエラー
nyatla 71:855020258513 542 Error:
nyatla 71:855020258513 543 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 544 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 545 return -1;
nyatla 71:855020258513 546 Timeout:
nyatla 71:855020258513 547 return 0;
nyatla 71:855020258513 548 }
nyatla 71:855020258513 549
nyatla 58:03b89038b21a 550 /**
nyatla 58:03b89038b21a 551 * @return
nyatla 58:03b89038b21a 552 * n>0:データ受信
nyatla 58:03b89038b21a 553 * 0 :タイムアウト。コネクションの状態は変化しない。
nyatla 58:03b89038b21a 554 * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。
nyatla 58:03b89038b21a 555 */
nyatla 58:03b89038b21a 556 NyLPC_TInt16 NyLPC_cModWebSocket_read(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_buf_len)
nyatla 58:03b89038b21a 557 {
nyatla 58:03b89038b21a 558 const NyLPC_TUInt8* rx;
nyatla 58:03b89038b21a 559 NyLPC_TInt32 rs,i;
nyatla 58:03b89038b21a 560 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 561 NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 562
nyatla 58:03b89038b21a 563 switch(i_inst->_payload_st)
nyatla 58:03b89038b21a 564 {
nyatla 57:bc4330dfa62f 565 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 58:03b89038b21a 566 break;//処理継続
nyatla 58:03b89038b21a 567 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 58:03b89038b21a 568 //タイムアウト扱い
nyatla 58:03b89038b21a 569 return 0;
nyatla 58:03b89038b21a 570 default:
nyatla 58:03b89038b21a 571 return -1;
nyatla 58:03b89038b21a 572 }
nyatla 58:03b89038b21a 573 //読み出し可能なデータをパース
nyatla 58:03b89038b21a 574 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 575 if(rs<=0){
nyatla 58:03b89038b21a 576 if(rs<0){
nyatla 58:03b89038b21a 577 //Error
nyatla 58:03b89038b21a 578 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 579 }
nyatla 58:03b89038b21a 580 //Timeout
nyatla 58:03b89038b21a 581 goto Timeout;
nyatla 58:03b89038b21a 582 }
nyatla 58:03b89038b21a 583 //読み込みサイズを決定
nyatla 58:03b89038b21a 584 rs=(rs<i_buf_len)?rs:i_buf_len;
nyatla 58:03b89038b21a 585 //アンマスク
nyatla 58:03b89038b21a 586 if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){
nyatla 58:03b89038b21a 587 for(i=0;i<rs;i++){
nyatla 58:03b89038b21a 588 *(((NyLPC_TUInt8*)i_buf)+i)=rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4];
nyatla 57:bc4330dfa62f 589 }
nyatla 58:03b89038b21a 590 }else{
nyatla 58:03b89038b21a 591 memcpy(i_buf,rx,rs);
nyatla 57:bc4330dfa62f 592 }
nyatla 58:03b89038b21a 593 //読取位置を移動
nyatla 58:03b89038b21a 594 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 58:03b89038b21a 595 i_inst->payload_ptr+=rs;
nyatla 58:03b89038b21a 596 if(i_inst->payload_size==i_inst->payload_ptr){
nyatla 58:03b89038b21a 597 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 58:03b89038b21a 598 }
nyatla 58:03b89038b21a 599 return rs;
nyatla 57:bc4330dfa62f 600 //処理されなければエラー
nyatla 57:bc4330dfa62f 601 Error:
nyatla 57:bc4330dfa62f 602 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 603 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 604 return -1;
nyatla 57:bc4330dfa62f 605 Timeout:
nyatla 57:bc4330dfa62f 606 return 0;
nyatla 57:bc4330dfa62f 607 }
nyatla 57:bc4330dfa62f 608
nyatla 58:03b89038b21a 609
nyatla 58:03b89038b21a 610
nyatla 58:03b89038b21a 611
nyatla 57:bc4330dfa62f 612 static NyLPC_TBool fmt_handler(void* i_inst,const void* i_buf,NyLPC_TUInt32 i_len)
nyatla 57:bc4330dfa62f 613 {
nyatla 57:bc4330dfa62f 614 return NyLPC_iHttpPtrStream_write((NyLPC_TiHttpPtrStream_t*)i_inst,i_buf,i_len);
nyatla 57:bc4330dfa62f 615 }
nyatla 57:bc4330dfa62f 616
nyatla 58:03b89038b21a 617
nyatla 58:03b89038b21a 618 /**
nyatla 58:03b89038b21a 619 * Payloadヘッダを書く。
nyatla 58:03b89038b21a 620 */
nyatla 58:03b89038b21a 621 NyLPC_TBool NyLPC_cModWebSocket_writePayloadHeader(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)
nyatla 57:bc4330dfa62f 622 {
nyatla 57:bc4330dfa62f 623 NyLPC_TUInt16 s;
nyatla 57:bc4330dfa62f 624 NyLPC_TChar w[4];
nyatla 58:03b89038b21a 625 //CLOSED,CONNECTの時は使用不可
nyatla 58:03b89038b21a 626 switch(i_inst->_payload_st){
nyatla 58:03b89038b21a 627 case NyLPC_TcModWebSocket_ST_CLOSED:
nyatla 57:bc4330dfa62f 628 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 629 default:
nyatla 57:bc4330dfa62f 630 break;
nyatla 57:bc4330dfa62f 631 }
nyatla 57:bc4330dfa62f 632 //データサイズで切り分け
nyatla 57:bc4330dfa62f 633 switch(i_inst->_frame_type)
nyatla 57:bc4330dfa62f 634 {
nyatla 57:bc4330dfa62f 635 case NyLPC_TcModWebSocket_FRAME_TYPE_TXT:
nyatla 57:bc4330dfa62f 636 w[0]=0x80|0x01;
nyatla 57:bc4330dfa62f 637 break;
nyatla 57:bc4330dfa62f 638 case NyLPC_TcModWebSocket_FRAME_TYPE_BIN:
nyatla 57:bc4330dfa62f 639 w[0]=0x80|0x02;
nyatla 57:bc4330dfa62f 640 break;
nyatla 57:bc4330dfa62f 641 default:
nyatla 57:bc4330dfa62f 642 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 643 }
nyatla 57:bc4330dfa62f 644 if(i_len<126){
nyatla 57:bc4330dfa62f 645 w[1]=(NyLPC_TUInt8)i_len;
nyatla 57:bc4330dfa62f 646 s=2;
nyatla 57:bc4330dfa62f 647 }else{
nyatla 57:bc4330dfa62f 648 w[1]=126;
nyatla 57:bc4330dfa62f 649 s=3;
nyatla 57:bc4330dfa62f 650 *((NyLPC_TUInt16*)(&(w[2])))=NyLPC_htons(i_len);
nyatla 57:bc4330dfa62f 651 }
nyatla 57:bc4330dfa62f 652 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,s)){
nyatla 57:bc4330dfa62f 653 //CLOSE
nyatla 57:bc4330dfa62f 654 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 655 }
nyatla 58:03b89038b21a 656 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 657 Error:
nyatla 58:03b89038b21a 658 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 659 }
nyatla 58:03b89038b21a 660
nyatla 72:c118a7aa37a3 661
nyatla 58:03b89038b21a 662
nyatla 71:855020258513 663 NyLPC_TBool NyLPC_cModWebSocket_writeFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 58:03b89038b21a 664 {
nyatla 58:03b89038b21a 665 NyLPC_TInt16 l;
nyatla 58:03b89038b21a 666 va_list a;
nyatla 58:03b89038b21a 667 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 668 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 669
nyatla 58:03b89038b21a 670 //書式文字列の長さを計算
nyatla 72:c118a7aa37a3 671 NyLPC_va_copy(a,args);
nyatla 58:03b89038b21a 672 l=NyLPC_cFormatWriter_length(i_fmt,a);
nyatla 58:03b89038b21a 673 va_end(a);
nyatla 58:03b89038b21a 674 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,l)){
nyatla 58:03b89038b21a 675 //CLOSE
nyatla 58:03b89038b21a 676 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 677 }
nyatla 71:855020258513 678 if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){
nyatla 58:03b89038b21a 679 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 680 }
nyatla 58:03b89038b21a 681 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 58:03b89038b21a 682 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 683 Error:
nyatla 58:03b89038b21a 684 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 58:03b89038b21a 685 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 58:03b89038b21a 686 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 687 }
nyatla 58:03b89038b21a 688
nyatla 71:855020258513 689 NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 690 {
nyatla 71:855020258513 691 NyLPC_TBool r;
nyatla 71:855020258513 692 va_list a;
nyatla 71:855020258513 693 va_start(a,i_fmt);
nyatla 71:855020258513 694 r=NyLPC_cModWebSocket_writeFormatV(i_inst,i_fmt,a);
nyatla 71:855020258513 695 va_end(a);
nyatla 71:855020258513 696 return r;
nyatla 71:855020258513 697 }
nyatla 71:855020258513 698
nyatla 58:03b89038b21a 699
nyatla 58:03b89038b21a 700
nyatla 58:03b89038b21a 701
nyatla 58:03b89038b21a 702 NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,const void* i_buf,NyLPC_TInt16 i_len)
nyatla 58:03b89038b21a 703 {
nyatla 58:03b89038b21a 704 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 705 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 706 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){
nyatla 58:03b89038b21a 707 //CLOSE
nyatla 58:03b89038b21a 708 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 709 }
nyatla 57:bc4330dfa62f 710 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_buf,i_len)){
nyatla 57:bc4330dfa62f 711 //CLOSE
nyatla 57:bc4330dfa62f 712 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 713 }
nyatla 57:bc4330dfa62f 714 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 715 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 716 Error:
nyatla 57:bc4330dfa62f 717 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 718 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 719 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 720 }
nyatla 57:bc4330dfa62f 721
nyatla 57:bc4330dfa62f 722 void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code)
nyatla 57:bc4330dfa62f 723 {
nyatla 58:03b89038b21a 724 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 725 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 726
nyatla 57:bc4330dfa62f 727 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 57:bc4330dfa62f 728 return;
nyatla 57:bc4330dfa62f 729 }
nyatla 57:bc4330dfa62f 730 //CLOSE送信
nyatla 57:bc4330dfa62f 731 writeClosePacket(i_inst,i_code);
nyatla 57:bc4330dfa62f 732 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 733 //切断
nyatla 57:bc4330dfa62f 734 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 735 }
nyatla 71:855020258513 736
nyatla 71:855020258513 737
nyatla 71:855020258513 738 NyLPC_TInt16 NyLPC_cModWebSocket_testFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 71:855020258513 739 {
nyatla 71:855020258513 740 return NyLPC_cFormatWriter_length(i_fmt,args);
nyatla 71:855020258513 741 }
nyatla 71:855020258513 742 NyLPC_TInt16 NyLPC_cModWebSocket_testFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 743 {
nyatla 71:855020258513 744 NyLPC_TInt16 r;
nyatla 71:855020258513 745 va_list a;
nyatla 71:855020258513 746 va_start(a,i_fmt);
nyatla 71:855020258513 747 r=NyLPC_cFormatWriter_length(i_fmt,a);
nyatla 71:855020258513 748 va_end(a);
nyatla 71:855020258513 749 return r;
nyatla 71:855020258513 750 }
nyatla 71:855020258513 751
nyatla 71:855020258513 752
nyatla 71:855020258513 753 NyLPC_TBool NyLPC_cModWebSocket_startBulkWrite(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)
nyatla 71:855020258513 754 {
nyatla 71:855020258513 755 //ストリームの状態を更新する。
nyatla 71:855020258513 756 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 71:855020258513 757 //ペイロードヘッダの出力
nyatla 71:855020258513 758 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){
nyatla 71:855020258513 759 //CLOSE
nyatla 71:855020258513 760 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 761 }
nyatla 71:855020258513 762 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 763 Error:
nyatla 71:855020258513 764 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 765 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 766 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 767 }
nyatla 71:855020258513 768 /**
nyatla 71:855020258513 769 * バルク書き込みを終了します。
nyatla 71:855020258513 770 * この関数をコールする前に、startBulkWrite関数のi_lenで指定した大きさのデータを入力し終えている必要があります。
nyatla 71:855020258513 771 * 過不足があった場合、関数は失敗するか、WebSocketセッションが破壊されます。
nyatla 71:855020258513 772 */
nyatla 71:855020258513 773 NyLPC_TBool NyLPC_cModWebSocket_endBulkWrite(NyLPC_TcModWebSocket_t* i_inst)
nyatla 71:855020258513 774 {
nyatla 71:855020258513 775 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 71:855020258513 776 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 777 }
nyatla 71:855020258513 778 //送信サイズ確認?
nyatla 71:855020258513 779 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 71:855020258513 780 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 781 }
nyatla 71:855020258513 782
nyatla 71:855020258513 783 NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 71:855020258513 784 {
nyatla 71:855020258513 785 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 71:855020258513 786 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 787 }
nyatla 71:855020258513 788 if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){
nyatla 71:855020258513 789 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 790 }
nyatla 71:855020258513 791 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 792 Error:
nyatla 71:855020258513 793 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 794 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 795 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 796 }
nyatla 71:855020258513 797 NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 798 {
nyatla 71:855020258513 799 NyLPC_TBool ret;
nyatla 71:855020258513 800 va_list a;
nyatla 71:855020258513 801 va_start(a,i_fmt);
nyatla 71:855020258513 802 ret=NyLPC_cModWebSocket_writeBulkFormatV(i_inst,i_fmt,a);
nyatla 71:855020258513 803 va_end(a);
nyatla 71:855020258513 804 return ret;
nyatla 71:855020258513 805 }