This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
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 }
Generated on Tue Jul 12 2022 15:46:15 by 1.7.2