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

Fork of libMiMic by Ryo Iizuka

Committer:
nyatla
Date:
Wed Jun 25 02:58:45 2014 +0000
Revision:
82:03c645af0bb1
Parent:
72:c118a7aa37a3
Child:
112:1853d747fcdf
bugfix; hsgw?????WebSocket????????????????????????????????????;

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 57:bc4330dfa62f 666 s=3;
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 }