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_cHttpdConnection.c Source File

NyLPC_cHttpdConnection.c

00001 #include "NyLPC_cHttpdConnection_protected.h"
00002 #include "NyLPC_http.h"
00003 #include "NyLPC_netif.h"
00004 #include "NyLPC_cHttpdUtils.h"
00005 #include "./NyLPC_cHttpd_protected.h"
00006 
00007 
00008 
00009 NyLPC_TBool NyLPC_cHttpdConnection_initialize(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TcHttpd_t* i_parent_httpd)
00010 {
00011     i_inst->_socket=NyLPC_cNet_createTcpSocketEx(NyLPC_TSocketType_TCP_HTTP);
00012     if(i_inst->_socket==NULL){
00013         return NyLPC_TBool_FALSE;
00014     }
00015     NyLPC_cHttpRequestPrefixParser_initialize(&(i_inst->_pparser));
00016     i_inst->_parent_httpd=i_parent_httpd;
00017     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_CLOSED;
00018     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_LISTEN;
00019     return NyLPC_TBool_TRUE;
00020 }
00021 
00022 void NyLPC_cHttpdConnection_finalize(NyLPC_TcHttpdConnection_t* i_inst)
00023 {
00024     NyLPC_cHttpdConnection_closeResponse(i_inst);
00025     NyLPC_cHttpdConnection_closeSocket(i_inst);
00026     NyLPC_cHttpRequestPrefixParser_finalize(i_inst);
00027     NyLPC_iTcpSocket_finalize(i_inst->_socket);
00028 }
00029 
00030 const NyLPC_TChar* NyLPC_cHttpdConnection_getUrlPrefix(const NyLPC_TcHttpdConnection_t* i_inst)
00031 {
00032     return NyLPC_cHttpRequestPrefixParser_getUrlPrefix(&i_inst->_pparser);
00033 }
00034 void NyLPC_cHttpdConnection_setReqStatusParsed(NyLPC_TcHttpdConnection_t* i_inst)
00035 {
00036     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_END;
00037 }
00038 
00039 #define NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED 0xFFFFFFFF
00040 
00041 
00042 NyLPC_TBool NyLPC_cHttpdConnection_send100Continue(NyLPC_TcHttpdConnection_t* i_inst)
00043 {
00044     //状態の確認
00045     if(i_inst->_res_status!=NyLPC_cHttpdConnection_ResStatus_HEAD)
00046     {
00047         NyLPC_OnErrorGoto(Error_Status);
00048     }
00049     //ステータスラインの記述
00050     if(!NyLPC_iHttpPtrStream_write(&(i_inst->_in_stream.super),"HTTP/1.1 100 Continue\r\n\r\n",25)){
00051         NyLPC_OnErrorGoto(Error);
00052     }
00053     return NyLPC_TBool_TRUE;
00054 Error:
00055 Error_Status:
00056     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_ERROR;
00057     return NyLPC_TBool_FALSE;
00058 }
00059 
00060 /**
00061  * レスポンスヘッダを送信します。
00062  */
00063 NyLPC_TBool NyLPC_cHttpdConnection_sendResponseHeader(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TUInt16 i_response_code,const NyLPC_TChar* i_content_type,const NyLPC_TChar* i_additional_header)
00064 {
00065     return NyLPC_cHttpdConnection_sendResponseHeader2(i_inst,i_response_code,i_content_type,NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED,i_additional_header);
00066 }
00067 
00068 NyLPC_TBool NyLPC_cHttpdConnection_sendResponseHeader2(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TUInt16 i_response_code,const NyLPC_TChar* i_content_type,NyLPC_TUInt32 i_content_length,const NyLPC_TChar* i_additional_header)
00069 {
00070     NyLPC_TcHttpHeaderWriter_t* h=&(i_inst->_head_writer);
00071     //状態の確認
00072     if(i_inst->_res_status!=NyLPC_cHttpdConnection_ResStatus_HEAD)
00073     {
00074         NyLPC_OnErrorGoto(Error_Status);
00075     }
00076     //ヘッダ送信
00077     if(!NyLPC_cHttpHeaderWriter_initialize(h,&(i_inst->_in_stream.super),NULL)){
00078         NyLPC_OnErrorGoto(ERROR_SEND);
00079     }
00080     //Headerの転送モードセット
00081     if(i_content_length==NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED){
00082         NyLPC_cHttpHeaderWriter_setChunked(h);
00083     }else{
00084         NyLPC_cHttpHeaderWriter_setContentLength(h,i_content_length);
00085     }
00086     //continueにセットされていたらcloseをFALSEに
00087     NyLPC_cHttpHeaderWriter_setConnectionClose(h,(i_inst->_connection_message_mode!=NyLPC_TcHttpdConnection_CONNECTION_MODE_CONTINUE));
00088 
00089     if(!NyLPC_cHttpHeaderWriter_writeResponseHeader(h,i_response_code)){
00090         NyLPC_OnErrorGoto(ERROR_SEND);
00091     }
00092     if(!NyLPC_cHttpHeaderWriter_writeMessage(h,"Content-type",i_content_type)){
00093         NyLPC_OnErrorGoto(ERROR_SEND);
00094     }
00095     if(i_additional_header!=NULL){
00096         if(!NyLPC_cHttpHeaderWriter_writeRawMessage(h,i_additional_header)){
00097             NyLPC_OnErrorGoto(ERROR_SEND);
00098         }
00099     }
00100     NyLPC_cHttpHeaderWriter_close(h);
00101     NyLPC_cHttpHeaderWriter_finalize(h);
00102     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_BODY;
00103     //BodyWriter生成
00104     NyLPC_cHttpBodyWriter_initialize(&(i_inst->_body_writer),&(i_inst->_in_stream));
00105     //bodyのchunkedもセット
00106     if(i_content_length==NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED){
00107         NyLPC_cHttpBodyWriter_setChunked(&(i_inst->_body_writer));
00108     }else{
00109         NyLPC_cHttpBodyWriter_setContentLength(&(i_inst->_body_writer),i_content_length);
00110     }
00111     return NyLPC_TBool_TRUE;
00112 ERROR_SEND:
00113     NyLPC_cHttpHeaderWriter_finalize(&(i_inst->_head_writer));
00114 Error_Status:
00115     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_ERROR;
00116     return NyLPC_TBool_FALSE;
00117 }
00118 
00119 
00120 /**
00121  * レスポンスBodyを送信します。
00122  * 関数を実行後、_res_statusはBODYかERRORに遷移します。
00123  */
00124 NyLPC_TBool NyLPC_cHttpdConnection_sendResponseBody(NyLPC_TcHttpdConnection_t* i_inst,const void* i_data,NyLPC_TUInt32 i_size)
00125 {
00126     if(i_inst->_res_status!=NyLPC_cHttpdConnection_ResStatus_BODY)
00127     {
00128         NyLPC_OnErrorGoto(Error);
00129     }
00130     //Bodyの書込み
00131     if(!NyLPC_cHttpBodyWriter_write(&(i_inst->_body_writer),i_data,i_size)){
00132         NyLPC_OnErrorGoto(Error_Send);
00133     }
00134     return NyLPC_TBool_TRUE;
00135 Error_Send:
00136     NyLPC_cHttpBodyWriter_finalize(&(i_inst->_in_stream));
00137 Error:
00138     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_ERROR;
00139     return NyLPC_TBool_FALSE;
00140 }
00141 /**
00142  * レスポンスBodyを書式出力して送信します。
00143  * 関数を実行後、_res_statusはBODYかERRORに遷移します。
00144  */
00145 NyLPC_TBool NyLPC_cHttpdConnection_sendResponseBodyF(NyLPC_TcHttpdConnection_t* i_inst,const char* i_fmt,...)
00146 {
00147     va_list a;
00148     if(i_inst->_res_status!=NyLPC_cHttpdConnection_ResStatus_BODY)
00149     {
00150         NyLPC_OnErrorGoto(Error);
00151     }
00152     //Bodyの書込み
00153     va_start(a,i_fmt);
00154     if(!NyLPC_cHttpBodyWriter_formatV(&(i_inst->_body_writer),i_fmt,a)){
00155         NyLPC_OnErrorGoto(Error_Send);
00156     }
00157     va_end(a);
00158     return NyLPC_TBool_TRUE;
00159 Error_Send:
00160     va_end(a);
00161     NyLPC_cHttpBodyWriter_finalize(&(i_inst->_in_stream));
00162 Error:
00163     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_ERROR;
00164     return NyLPC_TBool_FALSE;
00165 }
00166 
00167 /**
00168  * ヘッダのみのErrorレスポンスを送信する。
00169  * この関数はワーク用のHeaderWriterを使います。
00170  */
00171 static void sendErrorResponse(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TInt16 i_status)
00172 {
00173     NyLPC_TcHttpHeaderWriter_t* h=&(i_inst->_head_writer);
00174     if(NyLPC_cHttpHeaderWriter_initialize(h,&i_inst->_in_stream.super,NULL)){
00175         //ヘッダを送信
00176         NyLPC_cHttpHeaderWriter_setConnectionClose(h,NyLPC_TBool_TRUE);
00177         NyLPC_cHttpHeaderWriter_writeResponseHeader(h,i_status);
00178         NyLPC_cHttpHeaderWriter_close(h);
00179         NyLPC_cHttpHeaderWriter_finalize(h);
00180     }
00181 }
00182 /**
00183  * 関数を実行後、_res_statusはCLOSEDかHEADかERRORに遷移する。
00184  */
00185 NyLPC_TBool NyLPC_cHttpdConnection_closeResponse(NyLPC_TcHttpdConnection_t* i_inst)
00186 {
00187     NyLPC_TcHttpBodyWriter_t* b;
00188     switch(i_inst->_res_status){
00189     case NyLPC_cHttpdConnection_ResStatus_CLOSED:
00190     case NyLPC_cHttpdConnection_ResStatus_ERROR:
00191         //何もせずにコネクションをクローズする。
00192         return NyLPC_TBool_FALSE;
00193     case NyLPC_cHttpdConnection_ResStatus_HEAD:
00194         //エラー500を送信してクローズする。
00195         sendErrorResponse(i_inst,500);
00196         i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_CLOSED;
00197         return NyLPC_TBool_FALSE;
00198     case NyLPC_cHttpdConnection_ResStatus_BODY:
00199         //正常終了。BODYをクローズし、終了する。
00200         b=&(i_inst->_body_writer);
00201         NyLPC_cHttpBodyWriter_close(b);
00202         NyLPC_cHttpBodyWriter_finalize(&b);
00203         i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_HEAD;
00204         if(i_inst->_connection_message_mode!=NyLPC_TcHttpdConnection_CONNECTION_MODE_CONTINUE)
00205         {
00206             i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_CLOSED;
00207             return NyLPC_TBool_FALSE;
00208         }
00209         return NyLPC_TBool_TRUE;
00210     default:
00211         NyLPC_Abort();
00212     }
00213     return NyLPC_TBool_TRUE;
00214 }
00215 
00216 /**
00217  * コネクションのプリフェッチデータをヘッダパーサへpushします。
00218  */
00219 NyLPC_TBool NyLPC_cHttpdConnection_pushPrefetchInfo(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TcHttpBasicHeaderParser_t* i_header_parser,struct NyLPC_THttpBasicHeader* o_out)
00220 {
00221     const char* method=NyLPC_THttpMethodType_toString(i_inst->_pparser.method);
00222     if(NyLPC_cHttpBasicHeaderParser_parseChar(i_header_parser,method,strlen(method),o_out)<0){
00223         NyLPC_OnErrorGoto(Error);
00224     }
00225     if(NyLPC_cHttpBasicHeaderParser_parseChar(i_header_parser," ",1,o_out)<0){
00226         NyLPC_OnErrorGoto(Error);
00227     }
00228     if(NyLPC_cHttpBasicHeaderParser_parseChar(i_header_parser,i_inst->_pparser._url,strlen(i_inst->_pparser._url),o_out)<0){
00229         NyLPC_OnErrorGoto(Error);
00230     }
00231     return NyLPC_TBool_TRUE;
00232 Error:
00233     return NyLPC_TBool_FALSE;
00234 }
00235 
00236 #define NyLPC_cHttpdConnection_TIMEOUT_ACCEPT   3000
00237 #define NyLPC_cHttpdConnection_TIMEOUT_CLOSE    5000
00238 #define NyLPC_cHttpdConnection_TIMEOUT_LISTEN   5000
00239 
00240 
00241 /**
00242  * listenerでConnectionのソケットに接続を待ちます。
00243  */
00244 NyLPC_TBool NyLPC_cHttpdConnection_listenSocket(NyLPC_TcHttpdConnection_t* i_inst,NyLPC_TiTcpListener_t* i_listener)
00245 {
00246     NyLPC_Assert(i_inst->_req_status==NyLPC_cHttpdConnection_ReqStatus_LISTEN);
00247     //リスニング
00248     if(!NyLPC_iTcpListener_listen(i_listener,i_inst->_socket,NyLPC_cHttpdConnection_TIMEOUT_LISTEN)){
00249         return NyLPC_TBool_FALSE;
00250     }
00251     //成功したらステータス遷移
00252     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_ACCEPT;
00253     return NyLPC_TBool_TRUE;
00254 }
00255 
00256 /**
00257  * コネクションのソケットをacceptします。
00258  */
00259 NyLPC_TBool NyLPC_cHttpdConnection_acceptSocket(NyLPC_TcHttpdConnection_t* i_inst)
00260 {
00261     NyLPC_Assert(i_inst->_req_status==NyLPC_cHttpdConnection_ReqStatus_ACCEPT);
00262 
00263     if(!NyLPC_iTcpSocket_accept(i_inst->_socket,NyLPC_cHttpdConnection_TIMEOUT_ACCEPT)){
00264         NyLPC_OnErrorGoto(Error);
00265     }
00266     //HttpStreamの生成
00267     if(!NyLPC_cHttpStream_initialize(&i_inst->_in_stream,i_inst->_socket)){
00268         NyLPC_OnErrorGoto(Error_Connected);
00269     }
00270     //初回だけHEADに遷移
00271     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_HEAD;
00272     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_PREFETCH;
00273     i_inst->_connection_message_mode=NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE;
00274     return NyLPC_TBool_TRUE;
00275 Error_Connected:
00276     NyLPC_iTcpSocket_close(i_inst->_socket,NyLPC_cHttpdConnection_TIMEOUT_CLOSE);
00277     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_LISTEN;
00278 Error:
00279     return NyLPC_TBool_FALSE;
00280 }
00281 
00282 NyLPC_TBool NyLPC_cHttpdConnection_prefetch(NyLPC_TcHttpdConnection_t* i_inst)
00283 {
00284     NyLPC_Assert(i_inst->_req_status==NyLPC_cHttpdConnection_ReqStatus_PREFETCH);
00285 
00286     //Prefetchを実行
00287     if(!NyLPC_cHttpRequestPrefixParser_parse(&i_inst->_pparser,&i_inst->_in_stream.super)){
00288         //400エラー
00289         sendErrorResponse(i_inst,400);
00290         NyLPC_OnErrorGoto(Error_Prefetch);
00291     }
00292     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_REQPARSE;
00293     return NyLPC_TBool_TRUE;
00294 Error_Prefetch:
00295     NyLPC_iTcpSocket_close(i_inst->_socket,NyLPC_cHttpdConnection_TIMEOUT_CLOSE);
00296     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_LISTEN;
00297     return NyLPC_TBool_FALSE;
00298 }
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 NyLPC_TBool NyLPC_cHttpdConnection_prevNextPrefetch(NyLPC_TcHttpdConnection_t* i_inst)
00307 {
00308     NyLPC_TcHttpNullRequestHeaderParser_t parser;
00309     switch(i_inst->_req_status)
00310     {
00311     case NyLPC_cHttpdConnection_ReqStatus_REQPARSE:
00312         //リクエストパース待ちなら前段のリクエストを吸収しておく。
00313         NyLPC_cHttpNullRequestHeaderParser_initialize(&parser);
00314         //プリフェッチしたデータを流す
00315         NyLPC_cHttpNullRequestHeaderParser_parseInit(&parser);
00316         NyLPC_cHttpNullRequestHeaderParser_parseChar(&parser,"GET ",4);//決め打ち
00317         NyLPC_cHttpNullRequestHeaderParser_parseChar(&parser,i_inst->_pparser._url,strlen(i_inst->_pparser._url));
00318         //後続をストリームから取り込む
00319         if(NyLPC_cHttpNullRequestHeaderParser_parseStream(&parser,&(i_inst->_in_stream.super))){
00320             if(NyLPC_cHttpNullRequestHeaderParser_parseFinish(&parser)){
00321                 NyLPC_cHttpNullRequestHeaderParser_finalize(&parser);
00322                 //OK:403
00323                 sendErrorResponse(i_inst,403);
00324                 break;//OK
00325             }
00326         }
00327 
00328         NyLPC_cHttpNullRequestHeaderParser_finalize(&parser);
00329         //NG:400 Bad Request
00330         sendErrorResponse(i_inst,400);
00331         return NyLPC_TBool_FALSE;//吸収失敗
00332     case NyLPC_cHttpdConnection_ReqStatus_END:
00333         //リクエストがパース済みならprefetchに戻す。
00334         i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_PREFETCH;
00335     default:
00336         NyLPC_Abort();
00337     }
00338     //吸収成功
00339     return NyLPC_TBool_TRUE;
00340 }
00341 
00342 void NyLPC_cHttpdConnection_closeSocket(NyLPC_TcHttpdConnection_t* i_inst)
00343 {
00344     switch(i_inst->_req_status)
00345     {
00346     case NyLPC_cHttpdConnection_ReqStatus_LISTEN:
00347         //何も出来ない。
00348         break;
00349     case NyLPC_cHttpdConnection_ReqStatus_END:
00350     case NyLPC_cHttpdConnection_ReqStatus_REQPARSE:
00351     case NyLPC_cHttpdConnection_ReqStatus_PREFETCH:
00352         NyLPC_cHttpStream_finalize(&i_inst->_in_stream);
00353     case NyLPC_cHttpdConnection_ReqStatus_ACCEPT:
00354         NyLPC_iTcpSocket_close(i_inst->_socket,NyLPC_cHttpdConnection_TIMEOUT_CLOSE);
00355     default:
00356         break;
00357     }
00358     i_inst->_req_status=NyLPC_cHttpdConnection_ReqStatus_LISTEN;
00359     i_inst->_res_status=NyLPC_cHttpdConnection_ResStatus_CLOSED;
00360 }
00361 
00362 /**
00363  * Httpd全体で唯一のロックを取得する。
00364  */
00365 void NyLPC_cHttpdConnection_lock(NyLPC_TcHttpdConnection_t* i_inst)
00366 {
00367     NyLPC_cHttpd_lock((NyLPC_TcHttpd_t*)(i_inst->_parent_httpd));
00368 }
00369 /**
00370  * Httpd全体で唯一のロックを開放する。
00371  */
00372 void NyLPC_cHttpdConnection_unlock(NyLPC_TcHttpdConnection_t* i_inst)
00373 {
00374     NyLPC_cHttpd_unlock((NyLPC_TcHttpd_t*)(i_inst->_parent_httpd));
00375 }