Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of libMiMic by
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 16:22:57 by
1.7.2
