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:
Wed Jun 10 05:20:02 2015 +0000
Revision:
112:1853d747fcdf
Parent:
82:03c645af0bb1
fix issue; https://developer.mbed.org/users/nyatla/code/libMiMic/issues/3

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 82:03c645af0bb1 327 NyLPC_TInt32 rs,rt;
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 82:03c645af0bb1 385 //ペイロードポインターのリセット
nyatla 57:bc4330dfa62f 386 i_inst->payload_ptr=0;
nyatla 57:bc4330dfa62f 387
nyatla 57:bc4330dfa62f 388 //パケットサイズの確定(基本ヘッダ+マスク)
nyatla 57:bc4330dfa62f 389 switch(rx[0]&0x0f){
nyatla 57:bc4330dfa62f 390 case 0x00:
nyatla 57:bc4330dfa62f 391 //継続パケットは扱わない
nyatla 57:bc4330dfa62f 392 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 393 case 0x01:
nyatla 57:bc4330dfa62f 394 if(i_inst->_frame_type!=NyLPC_TcModWebSocket_FRAME_TYPE_TXT){
nyatla 57:bc4330dfa62f 395 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 396 }
nyatla 57:bc4330dfa62f 397 break;
nyatla 57:bc4330dfa62f 398 case 0x02:
nyatla 57:bc4330dfa62f 399 if(i_inst->_frame_type==NyLPC_TcModWebSocket_FRAME_TYPE_BIN){
nyatla 57:bc4330dfa62f 400 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 401 }
nyatla 57:bc4330dfa62f 402 break;
nyatla 57:bc4330dfa62f 403 case 0x08://close(非断片)
nyatla 57:bc4330dfa62f 404 //CloseFrame送信
nyatla 57:bc4330dfa62f 405 writeClosePacket(i_inst,1009);
nyatla 57:bc4330dfa62f 406 //Errorとして処理
nyatla 57:bc4330dfa62f 407 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 408 case 0x09://ping(非断片)
nyatla 57:bc4330dfa62f 409 //PONGを送信
nyatla 57:bc4330dfa62f 410 w8[0]=0x0a;
nyatla 57:bc4330dfa62f 411 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w8,1);
nyatla 57:bc4330dfa62f 412 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx+1,header_size-1);
nyatla 57:bc4330dfa62f 413 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 414 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 415 while(i_inst->payload_size!=i_inst->payload_ptr){
nyatla 58:03b89038b21a 416 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 57:bc4330dfa62f 417 if(rs<=0){
nyatla 57:bc4330dfa62f 418 if(rs<0){
nyatla 57:bc4330dfa62f 419 //Error
nyatla 57:bc4330dfa62f 420 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 421 }
nyatla 57:bc4330dfa62f 422 //Timeout
nyatla 57:bc4330dfa62f 423 goto Timeout;
nyatla 57:bc4330dfa62f 424 }
nyatla 82:03c645af0bb1 425 //読出し可能なサイズを決定
nyatla 82:03c645af0bb1 426 rt=i_inst->payload_size-i_inst->payload_ptr;
nyatla 82:03c645af0bb1 427 if(rs>rt){
nyatla 82:03c645af0bb1 428 rs=rt;
nyatla 82:03c645af0bb1 429 }
nyatla 82:03c645af0bb1 430 //パケットを破棄
nyatla 57:bc4330dfa62f 431 NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rx,rs);
nyatla 57:bc4330dfa62f 432 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 57:bc4330dfa62f 433 i_inst->payload_ptr+=rs;
nyatla 57:bc4330dfa62f 434 }
nyatla 57:bc4330dfa62f 435 //Timeout(パケットスタートに戻る?)
nyatla 57:bc4330dfa62f 436 goto START;
nyatla 57:bc4330dfa62f 437 case 0x0a://pong(非断片)
nyatla 57:bc4330dfa62f 438 //パケットの読み捨て
nyatla 57:bc4330dfa62f 439 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 440 while(i_inst->payload_size!=i_inst->payload_ptr){
nyatla 58:03b89038b21a 441 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 57:bc4330dfa62f 442 if(rs<=0){
nyatla 57:bc4330dfa62f 443 if(rs<0){
nyatla 57:bc4330dfa62f 444 //Error
nyatla 57:bc4330dfa62f 445 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 446 }
nyatla 57:bc4330dfa62f 447 //Timeout
nyatla 57:bc4330dfa62f 448 goto Timeout;
nyatla 57:bc4330dfa62f 449 }
nyatla 82:03c645af0bb1 450 //読出し可能なサイズを決定
nyatla 82:03c645af0bb1 451 rt=i_inst->payload_size-i_inst->payload_ptr;
nyatla 82:03c645af0bb1 452 if(rs>rt){
nyatla 82:03c645af0bb1 453 rs=rt;
nyatla 82:03c645af0bb1 454 }
nyatla 82:03c645af0bb1 455 //パケットを破棄
nyatla 57:bc4330dfa62f 456 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 57:bc4330dfa62f 457 i_inst->payload_ptr+=rs;
nyatla 57:bc4330dfa62f 458 }
nyatla 57:bc4330dfa62f 459 //Timeout(パケットスタートに戻る?)
nyatla 57:bc4330dfa62f 460 goto START;
nyatla 57:bc4330dfa62f 461 default:
nyatla 57:bc4330dfa62f 462 //知らないコードはエラー
nyatla 57:bc4330dfa62f 463 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 464 }
nyatla 57:bc4330dfa62f 465 //読み出し位置のシーク(Header部)
nyatla 57:bc4330dfa62f 466 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),header_size);
nyatla 57:bc4330dfa62f 467 //ペイロード読み出しへ
nyatla 57:bc4330dfa62f 468 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_READ_PAYLOAD;
nyatla 57:bc4330dfa62f 469 //継続してペイロード受信処理
nyatla 58:03b89038b21a 470 return;
nyatla 58:03b89038b21a 471 }
nyatla 58:03b89038b21a 472 //処理されなければエラー
nyatla 58:03b89038b21a 473 Error:
nyatla 58:03b89038b21a 474 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 58:03b89038b21a 475 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 58:03b89038b21a 476 return;
nyatla 58:03b89038b21a 477 Timeout:
nyatla 58:03b89038b21a 478 return;
nyatla 58:03b89038b21a 479 }
nyatla 58:03b89038b21a 480
nyatla 71:855020258513 481
nyatla 71:855020258513 482 /**
nyatla 71:855020258513 483 * 受信データをコールバック関数に通知するNyLPC_cModWebSocket_readです。
nyatla 71:855020258513 484 * @return
nyatla 71:855020258513 485 * n>0:データ受信
nyatla 71:855020258513 486 * 0 :タイムアウト。コネクションの状態は変化しない。
nyatla 71:855020258513 487 * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。
nyatla 71:855020258513 488 */
nyatla 71:855020258513 489 NyLPC_TInt16 NyLPC_cModWebSocket_readCB(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TcModWebSocket_onRreadCB i_cb,void* i_cb_param)
nyatla 71:855020258513 490 {
nyatla 71:855020258513 491 const NyLPC_TUInt8* rx;
nyatla 71:855020258513 492 NyLPC_TInt32 rs,rd,i;
nyatla 71:855020258513 493 //ストリームの状態を更新する。
nyatla 71:855020258513 494 NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);
nyatla 71:855020258513 495
nyatla 71:855020258513 496 switch(i_inst->_payload_st)
nyatla 71:855020258513 497 {
nyatla 71:855020258513 498 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 71:855020258513 499 break;//処理継続
nyatla 71:855020258513 500 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 71:855020258513 501 //タイムアウト扱い
nyatla 71:855020258513 502 return 0;
nyatla 71:855020258513 503 default:
nyatla 71:855020258513 504 return -1;
nyatla 71:855020258513 505 }
nyatla 71:855020258513 506 //読み出し可能なデータをパース
nyatla 71:855020258513 507 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 71:855020258513 508 if(rs<=0){
nyatla 71:855020258513 509 if(rs<0){
nyatla 71:855020258513 510 //Error
nyatla 71:855020258513 511 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 512 }
nyatla 71:855020258513 513 //Timeout
nyatla 71:855020258513 514 goto Timeout;
nyatla 71:855020258513 515 }
nyatla 82:03c645af0bb1 516 //読出し可能な残りサイズを計算して上書き
nyatla 82:03c645af0bb1 517 rd=i_inst->payload_size-i_inst->payload_ptr;
nyatla 82:03c645af0bb1 518 if(rs>rd){
nyatla 82:03c645af0bb1 519 rs=rd;
nyatla 82:03c645af0bb1 520 }
nyatla 82:03c645af0bb1 521 //読みだしたバイト数をリセット
nyatla 82:03c645af0bb1 522 rd=0;
nyatla 71:855020258513 523 //アンマスク
nyatla 71:855020258513 524 if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){
nyatla 71:855020258513 525 //マスク有の時
nyatla 71:855020258513 526 for(i=0;i<rs;i++){
nyatla 71:855020258513 527 rd++;
nyatla 71:855020258513 528 switch(i_cb(i_cb_param,rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4])){
nyatla 71:855020258513 529 case 1:
nyatla 71:855020258513 530 continue;
nyatla 71:855020258513 531 case 0:
nyatla 71:855020258513 532 break;
nyatla 71:855020258513 533 default:
nyatla 71:855020258513 534 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 535 }
nyatla 71:855020258513 536 }
nyatla 71:855020258513 537 }else{
nyatla 71:855020258513 538 //マスクなしの時
nyatla 71:855020258513 539 for(i=0;i<rs;i++){
nyatla 71:855020258513 540 rd++;
nyatla 71:855020258513 541 switch(i_cb(i_cb_param,rx[i])){
nyatla 71:855020258513 542 case 1:
nyatla 71:855020258513 543 continue;
nyatla 71:855020258513 544 case 0:
nyatla 71:855020258513 545 break;
nyatla 71:855020258513 546 default:
nyatla 71:855020258513 547 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 548 }
nyatla 71:855020258513 549 }
nyatla 71:855020258513 550 }
nyatla 71:855020258513 551 //読取位置を移動
nyatla 71:855020258513 552 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rd);
nyatla 71:855020258513 553 i_inst->payload_ptr+=rd;
nyatla 71:855020258513 554 if(i_inst->payload_size==i_inst->payload_ptr){
nyatla 71:855020258513 555 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 71:855020258513 556 }
nyatla 71:855020258513 557 return rd;
nyatla 71:855020258513 558 //処理されなければエラー
nyatla 71:855020258513 559 Error:
nyatla 71:855020258513 560 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 561 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 562 return -1;
nyatla 71:855020258513 563 Timeout:
nyatla 71:855020258513 564 return 0;
nyatla 71:855020258513 565 }
nyatla 71:855020258513 566
nyatla 58:03b89038b21a 567 /**
nyatla 58:03b89038b21a 568 * @return
nyatla 58:03b89038b21a 569 * n>0:データ受信
nyatla 58:03b89038b21a 570 * 0 :タイムアウト。コネクションの状態は変化しない。
nyatla 58:03b89038b21a 571 * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。
nyatla 58:03b89038b21a 572 */
nyatla 58:03b89038b21a 573 NyLPC_TInt16 NyLPC_cModWebSocket_read(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_buf_len)
nyatla 58:03b89038b21a 574 {
nyatla 58:03b89038b21a 575 const NyLPC_TUInt8* rx;
nyatla 58:03b89038b21a 576 NyLPC_TInt32 rs,i;
nyatla 58:03b89038b21a 577 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 578 NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 579
nyatla 58:03b89038b21a 580 switch(i_inst->_payload_st)
nyatla 58:03b89038b21a 581 {
nyatla 57:bc4330dfa62f 582 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 58:03b89038b21a 583 break;//処理継続
nyatla 58:03b89038b21a 584 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 58:03b89038b21a 585 //タイムアウト扱い
nyatla 58:03b89038b21a 586 return 0;
nyatla 58:03b89038b21a 587 default:
nyatla 58:03b89038b21a 588 return -1;
nyatla 58:03b89038b21a 589 }
nyatla 58:03b89038b21a 590 //読み出し可能なデータをパース
nyatla 58:03b89038b21a 591 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 592 if(rs<=0){
nyatla 58:03b89038b21a 593 if(rs<0){
nyatla 58:03b89038b21a 594 //Error
nyatla 58:03b89038b21a 595 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 596 }
nyatla 58:03b89038b21a 597 //Timeout
nyatla 58:03b89038b21a 598 goto Timeout;
nyatla 58:03b89038b21a 599 }
nyatla 58:03b89038b21a 600 //読み込みサイズを決定
nyatla 58:03b89038b21a 601 rs=(rs<i_buf_len)?rs:i_buf_len;
nyatla 58:03b89038b21a 602 //アンマスク
nyatla 58:03b89038b21a 603 if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){
nyatla 58:03b89038b21a 604 for(i=0;i<rs;i++){
nyatla 58:03b89038b21a 605 *(((NyLPC_TUInt8*)i_buf)+i)=rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4];
nyatla 57:bc4330dfa62f 606 }
nyatla 58:03b89038b21a 607 }else{
nyatla 58:03b89038b21a 608 memcpy(i_buf,rx,rs);
nyatla 57:bc4330dfa62f 609 }
nyatla 58:03b89038b21a 610 //読取位置を移動
nyatla 58:03b89038b21a 611 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 58:03b89038b21a 612 i_inst->payload_ptr+=rs;
nyatla 58:03b89038b21a 613 if(i_inst->payload_size==i_inst->payload_ptr){
nyatla 58:03b89038b21a 614 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 58:03b89038b21a 615 }
nyatla 58:03b89038b21a 616 return rs;
nyatla 57:bc4330dfa62f 617 //処理されなければエラー
nyatla 57:bc4330dfa62f 618 Error:
nyatla 57:bc4330dfa62f 619 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 620 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 621 return -1;
nyatla 57:bc4330dfa62f 622 Timeout:
nyatla 57:bc4330dfa62f 623 return 0;
nyatla 57:bc4330dfa62f 624 }
nyatla 57:bc4330dfa62f 625
nyatla 58:03b89038b21a 626
nyatla 58:03b89038b21a 627
nyatla 58:03b89038b21a 628
nyatla 57:bc4330dfa62f 629 static NyLPC_TBool fmt_handler(void* i_inst,const void* i_buf,NyLPC_TUInt32 i_len)
nyatla 57:bc4330dfa62f 630 {
nyatla 57:bc4330dfa62f 631 return NyLPC_iHttpPtrStream_write((NyLPC_TiHttpPtrStream_t*)i_inst,i_buf,i_len);
nyatla 57:bc4330dfa62f 632 }
nyatla 57:bc4330dfa62f 633
nyatla 58:03b89038b21a 634
nyatla 58:03b89038b21a 635 /**
nyatla 58:03b89038b21a 636 * Payloadヘッダを書く。
nyatla 58:03b89038b21a 637 */
nyatla 58:03b89038b21a 638 NyLPC_TBool NyLPC_cModWebSocket_writePayloadHeader(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)
nyatla 57:bc4330dfa62f 639 {
nyatla 57:bc4330dfa62f 640 NyLPC_TUInt16 s;
nyatla 57:bc4330dfa62f 641 NyLPC_TChar w[4];
nyatla 58:03b89038b21a 642 //CLOSED,CONNECTの時は使用不可
nyatla 58:03b89038b21a 643 switch(i_inst->_payload_st){
nyatla 58:03b89038b21a 644 case NyLPC_TcModWebSocket_ST_CLOSED:
nyatla 57:bc4330dfa62f 645 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 646 default:
nyatla 57:bc4330dfa62f 647 break;
nyatla 57:bc4330dfa62f 648 }
nyatla 57:bc4330dfa62f 649 //データサイズで切り分け
nyatla 57:bc4330dfa62f 650 switch(i_inst->_frame_type)
nyatla 57:bc4330dfa62f 651 {
nyatla 57:bc4330dfa62f 652 case NyLPC_TcModWebSocket_FRAME_TYPE_TXT:
nyatla 57:bc4330dfa62f 653 w[0]=0x80|0x01;
nyatla 57:bc4330dfa62f 654 break;
nyatla 57:bc4330dfa62f 655 case NyLPC_TcModWebSocket_FRAME_TYPE_BIN:
nyatla 57:bc4330dfa62f 656 w[0]=0x80|0x02;
nyatla 57:bc4330dfa62f 657 break;
nyatla 57:bc4330dfa62f 658 default:
nyatla 57:bc4330dfa62f 659 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 660 }
nyatla 57:bc4330dfa62f 661 if(i_len<126){
nyatla 57:bc4330dfa62f 662 w[1]=(NyLPC_TUInt8)i_len;
nyatla 57:bc4330dfa62f 663 s=2;
nyatla 57:bc4330dfa62f 664 }else{
nyatla 57:bc4330dfa62f 665 w[1]=126;
nyatla 112:1853d747fcdf 666 s=4;
nyatla 57:bc4330dfa62f 667 *((NyLPC_TUInt16*)(&(w[2])))=NyLPC_htons(i_len);
nyatla 57:bc4330dfa62f 668 }
nyatla 57:bc4330dfa62f 669 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,s)){
nyatla 57:bc4330dfa62f 670 //CLOSE
nyatla 57:bc4330dfa62f 671 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 672 }
nyatla 58:03b89038b21a 673 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 674 Error:
nyatla 58:03b89038b21a 675 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 676 }
nyatla 58:03b89038b21a 677
nyatla 72:c118a7aa37a3 678
nyatla 58:03b89038b21a 679
nyatla 71:855020258513 680 NyLPC_TBool NyLPC_cModWebSocket_writeFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 58:03b89038b21a 681 {
nyatla 58:03b89038b21a 682 NyLPC_TInt16 l;
nyatla 58:03b89038b21a 683 va_list a;
nyatla 58:03b89038b21a 684 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 685 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 686
nyatla 58:03b89038b21a 687 //書式文字列の長さを計算
nyatla 72:c118a7aa37a3 688 NyLPC_va_copy(a,args);
nyatla 58:03b89038b21a 689 l=NyLPC_cFormatWriter_length(i_fmt,a);
nyatla 58:03b89038b21a 690 va_end(a);
nyatla 58:03b89038b21a 691 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,l)){
nyatla 58:03b89038b21a 692 //CLOSE
nyatla 58:03b89038b21a 693 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 694 }
nyatla 71:855020258513 695 if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){
nyatla 58:03b89038b21a 696 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 697 }
nyatla 58:03b89038b21a 698 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 58:03b89038b21a 699 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 700 Error:
nyatla 58:03b89038b21a 701 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 58:03b89038b21a 702 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 58:03b89038b21a 703 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 704 }
nyatla 58:03b89038b21a 705
nyatla 71:855020258513 706 NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 707 {
nyatla 71:855020258513 708 NyLPC_TBool r;
nyatla 71:855020258513 709 va_list a;
nyatla 71:855020258513 710 va_start(a,i_fmt);
nyatla 71:855020258513 711 r=NyLPC_cModWebSocket_writeFormatV(i_inst,i_fmt,a);
nyatla 71:855020258513 712 va_end(a);
nyatla 71:855020258513 713 return r;
nyatla 71:855020258513 714 }
nyatla 71:855020258513 715
nyatla 58:03b89038b21a 716
nyatla 58:03b89038b21a 717
nyatla 58:03b89038b21a 718
nyatla 58:03b89038b21a 719 NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,const void* i_buf,NyLPC_TInt16 i_len)
nyatla 58:03b89038b21a 720 {
nyatla 58:03b89038b21a 721 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 722 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 723 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){
nyatla 58:03b89038b21a 724 //CLOSE
nyatla 58:03b89038b21a 725 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 726 }
nyatla 57:bc4330dfa62f 727 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_buf,i_len)){
nyatla 57:bc4330dfa62f 728 //CLOSE
nyatla 57:bc4330dfa62f 729 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 730 }
nyatla 57:bc4330dfa62f 731 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 732 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 733 Error:
nyatla 57:bc4330dfa62f 734 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 735 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 736 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 737 }
nyatla 57:bc4330dfa62f 738
nyatla 57:bc4330dfa62f 739 void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code)
nyatla 57:bc4330dfa62f 740 {
nyatla 58:03b89038b21a 741 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 742 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 743
nyatla 57:bc4330dfa62f 744 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 57:bc4330dfa62f 745 return;
nyatla 57:bc4330dfa62f 746 }
nyatla 57:bc4330dfa62f 747 //CLOSE送信
nyatla 57:bc4330dfa62f 748 writeClosePacket(i_inst,i_code);
nyatla 57:bc4330dfa62f 749 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 750 //切断
nyatla 57:bc4330dfa62f 751 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 752 }
nyatla 71:855020258513 753
nyatla 71:855020258513 754
nyatla 71:855020258513 755 NyLPC_TInt16 NyLPC_cModWebSocket_testFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 71:855020258513 756 {
nyatla 71:855020258513 757 return NyLPC_cFormatWriter_length(i_fmt,args);
nyatla 71:855020258513 758 }
nyatla 71:855020258513 759 NyLPC_TInt16 NyLPC_cModWebSocket_testFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 760 {
nyatla 71:855020258513 761 NyLPC_TInt16 r;
nyatla 71:855020258513 762 va_list a;
nyatla 71:855020258513 763 va_start(a,i_fmt);
nyatla 71:855020258513 764 r=NyLPC_cFormatWriter_length(i_fmt,a);
nyatla 71:855020258513 765 va_end(a);
nyatla 71:855020258513 766 return r;
nyatla 71:855020258513 767 }
nyatla 71:855020258513 768
nyatla 71:855020258513 769
nyatla 71:855020258513 770 NyLPC_TBool NyLPC_cModWebSocket_startBulkWrite(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)
nyatla 71:855020258513 771 {
nyatla 71:855020258513 772 //ストリームの状態を更新する。
nyatla 71:855020258513 773 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 71:855020258513 774 //ペイロードヘッダの出力
nyatla 71:855020258513 775 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){
nyatla 71:855020258513 776 //CLOSE
nyatla 71:855020258513 777 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 778 }
nyatla 71:855020258513 779 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 780 Error:
nyatla 71:855020258513 781 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 782 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 783 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 784 }
nyatla 71:855020258513 785 /**
nyatla 71:855020258513 786 * バルク書き込みを終了します。
nyatla 71:855020258513 787 * この関数をコールする前に、startBulkWrite関数のi_lenで指定した大きさのデータを入力し終えている必要があります。
nyatla 71:855020258513 788 * 過不足があった場合、関数は失敗するか、WebSocketセッションが破壊されます。
nyatla 71:855020258513 789 */
nyatla 71:855020258513 790 NyLPC_TBool NyLPC_cModWebSocket_endBulkWrite(NyLPC_TcModWebSocket_t* i_inst)
nyatla 71:855020258513 791 {
nyatla 71:855020258513 792 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 71:855020258513 793 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 794 }
nyatla 71:855020258513 795 //送信サイズ確認?
nyatla 71:855020258513 796 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 71:855020258513 797 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 798 }
nyatla 71:855020258513 799
nyatla 71:855020258513 800 NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormatV(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,va_list args)
nyatla 71:855020258513 801 {
nyatla 71:855020258513 802 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 71:855020258513 803 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 804 }
nyatla 71:855020258513 805 if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,args)){
nyatla 71:855020258513 806 NyLPC_OnErrorGoto(Error);
nyatla 71:855020258513 807 }
nyatla 71:855020258513 808 return NyLPC_TBool_TRUE;
nyatla 71:855020258513 809 Error:
nyatla 71:855020258513 810 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 71:855020258513 811 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 71:855020258513 812 return NyLPC_TBool_FALSE;
nyatla 71:855020258513 813 }
nyatla 71:855020258513 814 NyLPC_TBool NyLPC_cModWebSocket_writeBulkFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 71:855020258513 815 {
nyatla 71:855020258513 816 NyLPC_TBool ret;
nyatla 71:855020258513 817 va_list a;
nyatla 71:855020258513 818 va_start(a,i_fmt);
nyatla 71:855020258513 819 ret=NyLPC_cModWebSocket_writeBulkFormatV(i_inst,i_fmt,a);
nyatla 71:855020258513 820 va_end(a);
nyatla 71:855020258513 821 return ret;
nyatla 71:855020258513 822 }