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

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NyLPC_cModFileIoBaseClass.c Source File

NyLPC_cModFileIoBaseClass.c

00001 /*********************************************************************************
00002  * PROJECT: MiMic
00003  * --------------------------------------------------------------------------------
00004  *
00005  * This file is part of MiMic
00006  * Copyright (C)2011 Ryo Iizuka
00007  *
00008  * MiMic is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License as published
00010  * by the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public License
00019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  * For further information please contact.
00022  *  http://nyatla.jp/
00023  *  <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
00024  *
00025  *********************************************************************************/
00026 #include "NyLPC_cModFileIoBaseClass.h"
00027 #include "NyLPC_stdlib.h"
00028 #include "NyLPC_http.h"
00029 #include "../NyLPC_cHttpdConnection_protected.h"
00030 #include "../NyLPC_cHttpdUtils.h"
00031 #include "NyLPC_net.h"
00032 
00033 #define FNAME_MAX   48
00034 #define STRBUF_MAX  48
00035 
00036 struct TModFileIoHeader
00037 {
00038     struct NyLPC_THttpBasicHeader super;
00039     NyLPC_TcUrlEncode_t urlencode;
00040     NyLPC_TUInt8 _content_id;
00041     //解析用
00042     NyLPC_TUInt8 _qery_name_id;
00043     NyLPC_TUInt8 _astate;
00044     NyLPC_TInt16 _prefix_len;
00045     NyLPC_TcStr_t _tstr;
00046     NyLPC_TChar _tstr_buf[STRBUF_MAX];
00047     /** 文字列のパーサ*/
00048     char fname[FNAME_MAX];//対象ファイル名の格納先
00049 };
00050 
00051 #define ST_PARSE_PATH 1
00052 #define ST_PARSE_QUERY_NAME 2
00053 #define ST_PARSE_QUERY_VALUE 3      //Query読み出し中
00054 #define ST_PARSE_QUERY_VALUE_NAME 4
00055 /**
00056  * コンテンツID定義(コンテンツ名に対応)
00057  */
00058 #define CONTENT_ID_UPLOAD  2
00059 #define CONTENT_ID_CREATE  3
00060 #define CONTENT_ID_REMOVE  4
00061 #define CONTENT_ID_UNKNOWN 0
00062 
00063 
00064 #define QNAME_ID_NAME    1
00065 #define QNAME_ID_UNKNOWN 0
00066 
00067 
00068 static const struct NyLPC_TTextIdTbl url_tbl[]=
00069 {
00070     {"upload.api",CONTENT_ID_UPLOAD},
00071     {"create.api",CONTENT_ID_CREATE},
00072     {"remove.api",CONTENT_ID_REMOVE},
00073     {NULL,CONTENT_ID_UNKNOWN}
00074 };
00075 
00076 static const struct NyLPC_TTextIdTbl qname_id_table[]=
00077 {
00078     {"name",QNAME_ID_NAME},
00079     {NULL,QNAME_ID_UNKNOWN}
00080 };
00081 
00082 
00083 
00084 static NyLPC_TBool urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out)
00085 {
00086     struct TModFileIoHeader* out=(struct TModFileIoHeader*)o_out;
00087     NyLPC_TChar c;
00088     //読み飛ばし
00089     if(out->_prefix_len<0){
00090         out->_prefix_len++;
00091         return NyLPC_TBool_TRUE;//読み飛ばし
00092     }
00093     //Path解析
00094     if(out->_astate==ST_PARSE_PATH){
00095         if(i_c!='\0' && i_c!='?'){
00096             if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
00097                 //ERROR
00098                 NyLPC_OnErrorGoto(ERROR);
00099             }
00100         }else{
00101             out->_content_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),url_tbl);
00102             switch(out->_content_id)
00103             {
00104             case CONTENT_ID_UPLOAD:
00105             case CONTENT_ID_CREATE:
00106             case CONTENT_ID_REMOVE:
00107                 break;
00108             default:
00109                 NyLPC_OnErrorGoto(ERROR);
00110             }
00111             NyLPC_cStr_clear(&(out->_tstr));
00112             out->_astate=ST_PARSE_QUERY_NAME;//クエリ名解析へ
00113         }
00114         return NyLPC_TBool_TRUE;
00115     }
00116     switch(out->_content_id)
00117     {
00118     case CONTENT_ID_UPLOAD:
00119     case CONTENT_ID_CREATE:
00120     case CONTENT_ID_REMOVE:
00121         switch(out->_astate){
00122         case ST_PARSE_QUERY_NAME:
00123             if(i_c!='\0' && i_c!='&' && i_c!='='){
00124                 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){
00125                     NyLPC_OnErrorGoto(ERROR);
00126                 }
00127             }else{
00128                 //Query確定。
00129                 out->_qery_name_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),qname_id_table);
00130                 NyLPC_cStr_clear(&(out->_tstr));
00131                 //クエリ値がある場合
00132                 switch(out->_qery_name_id){
00133                 case QNAME_ID_NAME:
00134                     NyLPC_cUrlEncode_reset(&out->urlencode);
00135                     out->_astate=ST_PARSE_QUERY_VALUE_NAME;
00136                     break;
00137                 default:
00138                     out->_astate=ST_PARSE_QUERY_VALUE;
00139                     break;
00140                 }
00141             }
00142             return NyLPC_TBool_TRUE;
00143         case ST_PARSE_QUERY_VALUE:
00144             //未知のクエリは無視
00145             if(i_c!='\0' && i_c!='&'){
00146             }else{
00147                 //クエリ値解析完了
00148                 out->_astate=ST_PARSE_QUERY_NAME;
00149             }
00150             return NyLPC_TBool_TRUE;
00151         case ST_PARSE_QUERY_VALUE_NAME:
00152             if(i_c!='\0' && i_c!='&'){
00153                 //URLデコードしながら蓄積
00154                 switch(NyLPC_cUrlEncode_decode(&out->urlencode,i_c,&c)){
00155                 case NyLPC_TcUrlEncode_ST_NEXT:
00156                     break;
00157                 case NyLPC_TcUrlEncode_ST_DONE:
00158                     if(!NyLPC_cStr_put(&(out->_tstr),c)){
00159                         NyLPC_OnErrorGoto(ERROR);
00160                     }
00161                     break;
00162                 default:
00163                     NyLPC_OnErrorGoto(ERROR);
00164                 }
00165                 return NyLPC_TBool_TRUE;
00166             }else{
00167                 if(NyLPC_cStr_len(&out->_tstr)<1){
00168                     //ファイル名短すぎ
00169                     NyLPC_OnErrorGoto(ERROR);
00170                 }
00171                 //ファイル名を保存
00172                 strcpy(out->fname,(const char*)NyLPC_cStr_str(&out->_tstr));
00173                 //終端しているなら、次のクエリへ
00174                 out->_astate=ST_PARSE_QUERY_NAME;
00175             }
00176             return NyLPC_TBool_TRUE;
00177         default:
00178             break;
00179         }
00180         NyLPC_OnErrorGoto(ERROR);
00181     default:
00182         NyLPC_OnErrorGoto(ERROR);
00183     }
00184     return NyLPC_TBool_TRUE;
00185 ERROR:
00186     return NyLPC_TBool_FALSE;
00187 }
00188 /**
00189  * デフォルトハンドラ
00190  */
00191 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler=
00192 {
00193     NULL,
00194     urlHandler
00195 };
00196 
00197 
00198 /**
00199  * コンストラクタ。
00200  */
00201 void NyLPC_cModFileIoBaseClass_initialize(NyLPC_TcModFileIoBaseClass_t* i_inst,const NyLPC_TChar* i_ref_root_path)
00202 {
00203     NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_root_path,NULL,0);
00204 }
00205 void NyLPC_cModFileIoBaseClass_finalize(NyLPC_TcModFileIoBaseClass_t* i_inst)
00206 {
00207     NyLPC_cModRomFiles_finalize(&i_inst->super);
00208 }
00209 /**
00210  * モジュールがコネクションをハンドリングできるかを返します。
00211  */
00212 NyLPC_TBool NyLPC_cModFileIoBaseClass_canHandle(NyLPC_TcModFileIoBaseClass_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
00213 {
00214     return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection);
00215 }
00216 
00217 static struct TModFileIoHeader single_header;
00218 
00219 
00220 /**
00221  * モジュールを実行します。
00222  */
00223 NyLPC_TBool NyLPC_cModFileIoBaseClass_execute(NyLPC_TcModFileIoBaseClass_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection)
00224 {
00225     union{
00226         NyLPC_TcHttpBasicHeaderParser_t parser;
00227         NyLPC_TcHttpBodyParser_t body_parser;
00228     }sh;
00229     NyLPC_TUInt8 method_type;
00230     //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却)
00231     NyLPC_cHttpdConnection_setReqStatusParsed(i_connection);
00232 
00233     //排他ロック
00234     NyLPC_cHttpdConnection_lock(i_connection);
00235     {//parser
00236 
00237         //URL解析の準備
00238         single_header._prefix_len=-((NyLPC_TInt16)strlen(i_inst->super._ref_root_path)+2);
00239         single_header._astate=ST_PARSE_PATH;
00240         single_header.fname[0]='\0';
00241         NyLPC_cUrlEncode_initialize(&single_header.urlencode);
00242         NyLPC_cStr_initialize(&single_header._tstr,single_header._tstr_buf,STRBUF_MAX);
00243 
00244         NyLPC_cHttpBasicHeaderParser_initialize(&sh.parser,&handler);
00245 
00246         //プリフェッチしたデータを流す
00247         NyLPC_cHttpBasicHeaderParser_parseInit(&sh.parser,&(single_header.super));
00248         NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&sh.parser,&single_header.super);
00249         //後続をストリームから取り込む
00250         if(!NyLPC_cHttpBasicHeaderParser_parseStream(&sh.parser,NyLPC_cHttpdConnection_refStream(i_connection),&(single_header.super))){
00251             NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
00252             NyLPC_OnErrorGoto(Error1);
00253         }
00254         if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&sh.parser,&(single_header.super))){
00255             NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500);
00256             NyLPC_OnErrorGoto(Error1);
00257         }
00258         //HeaderParserはここで破棄(URLEncode,cSTRも)
00259         NyLPC_cHttpBasicHeaderParser_finalize(&sh.parser);
00260         NyLPC_cUrlEncode_finalize(&single_header.urlencode);
00261         NyLPC_cStr_finalize(&single_header._tstr);
00262     }
00263     //Request::ConnectionがClose設定,又はHTTP1.1では無い場合,CLOSE
00264     if(single_header.super.connection==NyLPC_THttpMessgeHeader_Connection_CLOSE || single_header.super.startline.req.version!=NyLPC_THttpVersion_11)
00265     {
00266         NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE);
00267     }
00268     //返答フェーズ
00269     {
00270         method_type=NyLPC_cHttpdConnection_getMethod(i_connection);
00271 
00272         //CGIの実行
00273         switch(single_header._content_id)
00274         {
00275         case CONTENT_ID_UPLOAD:
00276             //ファイル名とBodyParserを通知
00277             if(method_type==NyLPC_THttpMethodType_POST)
00278             {
00279                 NyLPC_cHttpdConnection_send100Continue(i_connection);
00280                 NyLPC_cHttpBodyParser_initialize(&sh.body_parser);
00281                 NyLPC_cHttpBodyParser_parseInit(&sh.body_parser,&single_header.super);
00282                 //ハンドラ内ではparseStreamのみ実行
00283                 if(!i_inst->_abstruct_function.upload(i_connection,single_header.fname,&sh.body_parser)){
00284                     NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE);
00285                 }
00286                 if(NyLPC_cHttpBodyParser_parseFinish(&sh.body_parser)){
00287                     NyLPC_cHttpBodyParser_finalize(&sh.body_parser);
00288                     NyLPC_OnErrorGoto(Error2);//エラーメッセージはハンドラ内で送られていると仮定する。
00289                 }
00290                 NyLPC_cHttpBodyParser_finalize(&sh.body_parser);
00291             }else{
00292                 NyLPC_OnErrorGoto(Error2);
00293             }
00294             break;
00295         case CONTENT_ID_CREATE:
00296             if(method_type==NyLPC_THttpMethodType_GET || method_type==NyLPC_THttpMethodType_HEAD)
00297             {
00298                 //イベント起動
00299                 if(!i_inst->_abstruct_function.create(i_connection,single_header.fname)){
00300                     NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE);
00301                 }
00302                 break;
00303             }
00304             NyLPC_OnErrorGoto(Error2_405);
00305         case CONTENT_ID_REMOVE:
00306             //ファイル名を通知
00307             if(method_type==NyLPC_THttpMethodType_GET || method_type==NyLPC_THttpMethodType_HEAD)
00308             {
00309                 //イベント起動
00310                 if(!i_inst->_abstruct_function.remove(i_connection,single_header.fname)){
00311                     NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE);
00312                 }
00313                 break;
00314             }
00315             NyLPC_OnErrorGoto(Error2_405);
00316         default:
00317             NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400);
00318             NyLPC_OnErrorGoto(Error2);
00319         }
00320     }
00321 //占有解除
00322     NyLPC_cHttpdConnection_unlock(i_connection);
00323     return NyLPC_TBool_TRUE;
00324 Error2_405:
00325     NyLPC_cHttpdUtils_sendErrorResponse(i_connection,405);
00326 Error2:
00327     //VM排他ロックの解除
00328     NyLPC_cHttpdConnection_unlock(i_connection);
00329     return NyLPC_TBool_FALSE;
00330 Error1:
00331     NyLPC_cHttpBasicHeaderParser_finalize(&parser);
00332     NyLPC_cStr_finalize(&single_header._tstr);
00333     NyLPC_cUrlEncode_finalize(&single_header.urlencode);
00334     //VM排他ロックの解除
00335     NyLPC_cHttpdConnection_unlock(i_connection);
00336     return NyLPC_TBool_FALSE;
00337 }
00338 
00339