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 Sep 27 12:47:51 2013 +0000
Revision:
58:03b89038b21a
Parent:
57:bc4330dfa62f
Child:
71:855020258513
add classes; checked:modwebsocket; unchecked:tcpsocket,udpsocket,httpclient.;

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 58:03b89038b21a 470 /**
nyatla 58:03b89038b21a 471 * @return
nyatla 58:03b89038b21a 472 * n>0:データ受信
nyatla 58:03b89038b21a 473 * 0 :タイムアウト。コネクションの状態は変化しない。
nyatla 58:03b89038b21a 474 * -1 :エラー コネクションはNyLPC_TcModWebSocket_ST_CLOSEDへ遷移する。
nyatla 58:03b89038b21a 475 */
nyatla 58:03b89038b21a 476 NyLPC_TInt16 NyLPC_cModWebSocket_read(NyLPC_TcModWebSocket_t* i_inst,void* i_buf,NyLPC_TInt16 i_buf_len)
nyatla 58:03b89038b21a 477 {
nyatla 58:03b89038b21a 478 const NyLPC_TUInt8* rx;
nyatla 58:03b89038b21a 479 NyLPC_TInt32 rs,i;
nyatla 58:03b89038b21a 480 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 481 NyLPC_cModWebSocket_update(i_inst,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 482
nyatla 58:03b89038b21a 483 switch(i_inst->_payload_st)
nyatla 58:03b89038b21a 484 {
nyatla 57:bc4330dfa62f 485 case NyLPC_TcModWebSocket_ST_READ_PAYLOAD:
nyatla 58:03b89038b21a 486 break;//処理継続
nyatla 58:03b89038b21a 487 case NyLPC_TcModWebSocket_ST_START_PAYLOAD:
nyatla 58:03b89038b21a 488 //タイムアウト扱い
nyatla 58:03b89038b21a 489 return 0;
nyatla 58:03b89038b21a 490 default:
nyatla 58:03b89038b21a 491 return -1;
nyatla 58:03b89038b21a 492 }
nyatla 58:03b89038b21a 493 //読み出し可能なデータをパース
nyatla 58:03b89038b21a 494 rs=NyLPC_iHttpPtrStream_pread(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),(const void**)&rx,HTTP_TIMEOUT);
nyatla 58:03b89038b21a 495 if(rs<=0){
nyatla 58:03b89038b21a 496 if(rs<0){
nyatla 58:03b89038b21a 497 //Error
nyatla 58:03b89038b21a 498 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 499 }
nyatla 58:03b89038b21a 500 //Timeout
nyatla 58:03b89038b21a 501 goto Timeout;
nyatla 58:03b89038b21a 502 }
nyatla 58:03b89038b21a 503 //読み込みサイズを決定
nyatla 58:03b89038b21a 504 rs=(rs<i_buf_len)?rs:i_buf_len;
nyatla 58:03b89038b21a 505 //アンマスク
nyatla 58:03b89038b21a 506 if(NyLPC_TUInt8_isBitOn(i_inst->_frame_flags_bits,FLAGS_MASK_BIT)){
nyatla 58:03b89038b21a 507 for(i=0;i<rs;i++){
nyatla 58:03b89038b21a 508 *(((NyLPC_TUInt8*)i_buf)+i)=rx[i]^i_inst->_frame_mask[(i_inst->payload_ptr+i)%4];
nyatla 57:bc4330dfa62f 509 }
nyatla 58:03b89038b21a 510 }else{
nyatla 58:03b89038b21a 511 memcpy(i_buf,rx,rs);
nyatla 57:bc4330dfa62f 512 }
nyatla 58:03b89038b21a 513 //読取位置を移動
nyatla 58:03b89038b21a 514 NyLPC_iHttpPtrStream_rseek(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),rs);
nyatla 58:03b89038b21a 515 i_inst->payload_ptr+=rs;
nyatla 58:03b89038b21a 516 if(i_inst->payload_size==i_inst->payload_ptr){
nyatla 58:03b89038b21a 517 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_START_PAYLOAD;
nyatla 58:03b89038b21a 518 }
nyatla 58:03b89038b21a 519 return rs;
nyatla 57:bc4330dfa62f 520 //処理されなければエラー
nyatla 57:bc4330dfa62f 521 Error:
nyatla 57:bc4330dfa62f 522 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 523 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 524 return -1;
nyatla 57:bc4330dfa62f 525 Timeout:
nyatla 57:bc4330dfa62f 526 return 0;
nyatla 57:bc4330dfa62f 527 }
nyatla 57:bc4330dfa62f 528
nyatla 58:03b89038b21a 529
nyatla 58:03b89038b21a 530
nyatla 58:03b89038b21a 531
nyatla 57:bc4330dfa62f 532 static NyLPC_TBool fmt_handler(void* i_inst,const void* i_buf,NyLPC_TUInt32 i_len)
nyatla 57:bc4330dfa62f 533 {
nyatla 57:bc4330dfa62f 534 return NyLPC_iHttpPtrStream_write((NyLPC_TiHttpPtrStream_t*)i_inst,i_buf,i_len);
nyatla 57:bc4330dfa62f 535 }
nyatla 57:bc4330dfa62f 536
nyatla 58:03b89038b21a 537
nyatla 58:03b89038b21a 538 /**
nyatla 58:03b89038b21a 539 * Payloadヘッダを書く。
nyatla 58:03b89038b21a 540 */
nyatla 58:03b89038b21a 541 NyLPC_TBool NyLPC_cModWebSocket_writePayloadHeader(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TInt16 i_len)
nyatla 57:bc4330dfa62f 542 {
nyatla 57:bc4330dfa62f 543 NyLPC_TUInt16 s;
nyatla 57:bc4330dfa62f 544 NyLPC_TChar w[4];
nyatla 58:03b89038b21a 545 //CLOSED,CONNECTの時は使用不可
nyatla 58:03b89038b21a 546 switch(i_inst->_payload_st){
nyatla 58:03b89038b21a 547 case NyLPC_TcModWebSocket_ST_CLOSED:
nyatla 57:bc4330dfa62f 548 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 549 default:
nyatla 57:bc4330dfa62f 550 break;
nyatla 57:bc4330dfa62f 551 }
nyatla 57:bc4330dfa62f 552 //データサイズで切り分け
nyatla 57:bc4330dfa62f 553 switch(i_inst->_frame_type)
nyatla 57:bc4330dfa62f 554 {
nyatla 57:bc4330dfa62f 555 case NyLPC_TcModWebSocket_FRAME_TYPE_TXT:
nyatla 57:bc4330dfa62f 556 w[0]=0x80|0x01;
nyatla 57:bc4330dfa62f 557 break;
nyatla 57:bc4330dfa62f 558 case NyLPC_TcModWebSocket_FRAME_TYPE_BIN:
nyatla 57:bc4330dfa62f 559 w[0]=0x80|0x02;
nyatla 57:bc4330dfa62f 560 break;
nyatla 57:bc4330dfa62f 561 default:
nyatla 57:bc4330dfa62f 562 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 563 }
nyatla 57:bc4330dfa62f 564 if(i_len<126){
nyatla 57:bc4330dfa62f 565 w[1]=(NyLPC_TUInt8)i_len;
nyatla 57:bc4330dfa62f 566 s=2;
nyatla 57:bc4330dfa62f 567 }else{
nyatla 57:bc4330dfa62f 568 w[1]=126;
nyatla 57:bc4330dfa62f 569 s=3;
nyatla 57:bc4330dfa62f 570 *((NyLPC_TUInt16*)(&(w[2])))=NyLPC_htons(i_len);
nyatla 57:bc4330dfa62f 571 }
nyatla 57:bc4330dfa62f 572 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),w,s)){
nyatla 57:bc4330dfa62f 573 //CLOSE
nyatla 57:bc4330dfa62f 574 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 575 }
nyatla 58:03b89038b21a 576 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 577 Error:
nyatla 58:03b89038b21a 578 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 579 }
nyatla 58:03b89038b21a 580
nyatla 58:03b89038b21a 581
nyatla 58:03b89038b21a 582
nyatla 58:03b89038b21a 583
nyatla 58:03b89038b21a 584 NyLPC_TBool NyLPC_cModWebSocket_writeFormat(NyLPC_TcModWebSocket_t* i_inst,const NyLPC_TChar* i_fmt,...)
nyatla 58:03b89038b21a 585 {
nyatla 58:03b89038b21a 586 NyLPC_TInt16 l;
nyatla 58:03b89038b21a 587 va_list a;
nyatla 58:03b89038b21a 588 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 589 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 590
nyatla 58:03b89038b21a 591 //書式文字列の長さを計算
nyatla 58:03b89038b21a 592 va_start(a,i_fmt);
nyatla 58:03b89038b21a 593 l=NyLPC_cFormatWriter_length(i_fmt,a);
nyatla 58:03b89038b21a 594 va_end(a);
nyatla 58:03b89038b21a 595 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,l)){
nyatla 58:03b89038b21a 596 //CLOSE
nyatla 58:03b89038b21a 597 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 598 }
nyatla 58:03b89038b21a 599 va_start(a,i_fmt);
nyatla 58:03b89038b21a 600 if(!NyLPC_cFormatWriter_print(fmt_handler,NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_fmt,a)){
nyatla 58:03b89038b21a 601 va_end(a);
nyatla 58:03b89038b21a 602 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 603 }
nyatla 58:03b89038b21a 604 va_end(a);
nyatla 58:03b89038b21a 605 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 58:03b89038b21a 606 return NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 607 Error:
nyatla 58:03b89038b21a 608 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 58:03b89038b21a 609 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 58:03b89038b21a 610 return NyLPC_TBool_FALSE;
nyatla 58:03b89038b21a 611 }
nyatla 58:03b89038b21a 612
nyatla 58:03b89038b21a 613
nyatla 58:03b89038b21a 614
nyatla 58:03b89038b21a 615
nyatla 58:03b89038b21a 616 NyLPC_TBool NyLPC_cModWebSocket_write(NyLPC_TcModWebSocket_t* i_inst,const void* i_buf,NyLPC_TInt16 i_len)
nyatla 58:03b89038b21a 617 {
nyatla 58:03b89038b21a 618 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 619 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 620 if(!NyLPC_cModWebSocket_writePayloadHeader(i_inst,i_len)){
nyatla 58:03b89038b21a 621 //CLOSE
nyatla 58:03b89038b21a 622 NyLPC_OnErrorGoto(Error);
nyatla 58:03b89038b21a 623 }
nyatla 57:bc4330dfa62f 624 if(!NyLPC_iHttpPtrStream_write(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection),i_buf,i_len)){
nyatla 57:bc4330dfa62f 625 //CLOSE
nyatla 57:bc4330dfa62f 626 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 627 }
nyatla 57:bc4330dfa62f 628 NyLPC_iHttpPtrStream_flush(NyLPC_cHttpdConnection_refStream(i_inst->_ref_connection));
nyatla 57:bc4330dfa62f 629 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 630 Error:
nyatla 57:bc4330dfa62f 631 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 632 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 633 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 634 }
nyatla 57:bc4330dfa62f 635
nyatla 57:bc4330dfa62f 636 void NyLPC_cModWebSocket_close(NyLPC_TcModWebSocket_t* i_inst,NyLPC_TUInt16 i_code)
nyatla 57:bc4330dfa62f 637 {
nyatla 58:03b89038b21a 638 //ストリームの状態を更新する。
nyatla 58:03b89038b21a 639 NyLPC_cModWebSocket_update(i_inst,0);
nyatla 58:03b89038b21a 640
nyatla 57:bc4330dfa62f 641 if(i_inst->_payload_st==NyLPC_TcModWebSocket_ST_CLOSED){
nyatla 57:bc4330dfa62f 642 return;
nyatla 57:bc4330dfa62f 643 }
nyatla 57:bc4330dfa62f 644 //CLOSE送信
nyatla 57:bc4330dfa62f 645 writeClosePacket(i_inst,i_code);
nyatla 57:bc4330dfa62f 646 i_inst->_payload_st=NyLPC_TcModWebSocket_ST_CLOSED;
nyatla 57:bc4330dfa62f 647 //切断
nyatla 57:bc4330dfa62f 648 NyLPC_cHttpdConnection_closeSocket(i_inst->_ref_connection);
nyatla 57:bc4330dfa62f 649 }