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

Fork of libMiMic by Ryo Iizuka

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

Who changed what in which revision?

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