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

NyLPC_cHttpHeaderWriter.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 <stdlib.h>
00027 
00028 #include "NyLPC_cHttpHeaderWriter.h"
00029 #include "NyLPC_cHttpdConfig.h"
00030 
00031 
00032 /**
00033  * Httpリクエストヘッダに対応したHttpヘッダライタを構築します。
00034  */
00035 NyLPC_TBool NyLPC_cHttpHeaderWriter_initialize(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TiHttpPtrStream_t* i_ref_stream,const struct NyLPC_THttpBasicHeader* i_req_header)
00036 {
00037     i_inst->_is_chunked=NyLPC_TUInt8_FALSE;
00038     i_inst->_content_length=0;
00039     i_inst->_ref_stream=i_ref_stream;
00040     i_inst->_is_error=NyLPC_TUInt8_FALSE;
00041     //書込エンコーディングをなしにセット
00042     NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);
00043     //必要に応じてリクエストの内容をパース
00044     if(i_req_header!=NULL){
00045         if(i_req_header->type!=NyLPC_THttpHeaderType_REQUEST){
00046             return NyLPC_TBool_FALSE;
00047         }
00048         //コネクションの持続性を決定
00049         if((i_req_header->connection==NyLPC_THttpMessgeHeader_Connection_CLOSE)||
00050             (i_req_header->startline.req.version!=NyLPC_THttpVersion_11))
00051         {
00052             i_inst->_is_close=NyLPC_TUInt8_TRUE;
00053         }else{
00054             i_inst->_is_close=NyLPC_TUInt8_FALSE;
00055         }
00056     }else{
00057         i_inst->_is_close=NyLPC_TUInt8_TRUE;
00058     }
00059     return NyLPC_TBool_TRUE;
00060 }
00061 
00062 #define NyLPC_cHttpHttpWriter_finalize(i)
00063 
00064 
00065 void NyLPC_cHttpHeaderWriter_setChunked(NyLPC_TcHttpHeaderWriter_t* i_inst)
00066 {
00067     i_inst->_is_chunked=NyLPC_TUInt8_TRUE;
00068     return;
00069 }
00070 void NyLPC_cHttpHeaderWriter_setContentLength(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt32 i_content_length)
00071 {
00072     i_inst->_content_length=i_content_length;
00073     return;
00074 }
00075 void NyLPC_cHttpHeaderWriter_setConnectionClose(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TBool i_is_close)
00076 {
00077     i_inst->_is_close=i_is_close;
00078     return;
00079 }
00080 
00081 
00082 
00083 const static struct{
00084     NyLPC_TUInt16 code;
00085     const NyLPC_TChar*  message;
00086 }status_line_tbl[]={
00087     {200,"OK"},
00088     {301,"Moved Permanently"},
00089     {302,"Moved Temporarily"},
00090     {400,"Bad Request"},
00091     {403,"Forbidden"},
00092     {404,"Not Found"},
00093     {405,"Method Not Allowed"},
00094     {500,"Internal Server Error"},
00095     {0,NULL}//これ最後にしてね。
00096 };
00097 const static char* getStatusMessage(NyLPC_TUInt16 i_status)
00098 {
00099     int i=0;
00100     while(status_line_tbl[i].code!=0){
00101         if(i_status==status_line_tbl[i].code){
00102             return status_line_tbl[i].message;
00103         }
00104         i++;
00105     }
00106     return NULL;
00107 }
00108 
00109 static NyLPC_TBool writeln(NyLPC_TiHttpPtrStream_t* i_inst,const void* i_data,NyLPC_TInt16 i_length)
00110 {
00111     if(NyLPC_iHttpPtrStream_write(i_inst,i_data,i_length)){
00112         if(NyLPC_iHttpPtrStream_write(i_inst,"\r\n",2)){
00113             return NyLPC_TBool_TRUE;
00114         }
00115     }
00116     return NyLPC_TBool_FALSE;
00117 }
00118 
00119 
00120 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRequestHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_THttpMethodType i_method,const struct NyLPC_TIPv4Addr* i_host,NyLPC_TUInt16 i_port,const NyLPC_TChar* i_path)
00121 {
00122     const NyLPC_TChar* t;
00123     NyLPC_TChar v[16];
00124     //エラー状態ならなにもしない。
00125     if(i_inst->_is_error){
00126         return NyLPC_TBool_FALSE;
00127     }
00128 
00129     t=NyLPC_THttpMethodType_toString(i_method);
00130     if(t==NULL){
00131         return NyLPC_TBool_FALSE;
00132     }
00133     //リクエストラインの記述
00134     //Method
00135     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,t,-1)){
00136         NyLPC_OnErrorGoto(Error);
00137     }
00138     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){
00139         NyLPC_OnErrorGoto(Error);
00140     }
00141     //Path
00142     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_path,-1)){
00143         NyLPC_OnErrorGoto(Error);
00144     }
00145     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," HTTP/1.1\r\n",11)){
00146         NyLPC_OnErrorGoto(Error);
00147     }
00148     //HOSTの記述
00149     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Host: ",6)){
00150         NyLPC_OnErrorGoto(Error);
00151     }
00152     NyLPC_TIPv4Addr_toString(i_host,v);
00153     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){
00154         NyLPC_OnErrorGoto(Error);
00155     }
00156     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,":",1)){
00157         NyLPC_OnErrorGoto(Error);
00158     }
00159     NyLPC_uitoa (i_port,v,10);
00160     if(!writeln(i_inst->_ref_stream,v,-1)){
00161         NyLPC_OnErrorGoto(Error);
00162     }
00163 
00164     //close
00165     if(i_inst->_is_close){
00166         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){
00167             NyLPC_OnErrorGoto(Error);
00168         }
00169     }
00170 
00171     //chunked
00172     if(i_inst->_is_chunked){
00173         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){
00174             NyLPC_OnErrorGoto(Error);
00175         }
00176     }else{
00177         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){
00178             NyLPC_OnErrorGoto(Error);
00179         }
00180         NyLPC_uitoa (i_inst->_content_length,v,10);
00181         if(!writeln(i_inst->_ref_stream,v,-1)){
00182             NyLPC_OnErrorGoto(Error);
00183         }
00184     }
00185     //送信サイズをリセット
00186     i_inst->_size_of_sent=0;
00187     return NyLPC_TBool_TRUE;
00188 Error:
00189     i_inst->_is_error=NyLPC_TUInt8_FALSE;
00190     return NyLPC_TBool_FALSE;
00191 
00192 }
00193 
00194 /**
00195  * ステータスラインと、標準メッセージヘッダを出力します。
00196  */
00197 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeResponseHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status)
00198 {
00199     NyLPC_TChar v[12];
00200     const char* m=getStatusMessage(i_status);
00201     //エラー状態ならなにもしない。
00202     if(i_inst->_is_error){
00203         return NyLPC_TBool_FALSE;
00204     }
00205     //検索に失敗したら500番に変更
00206     if(m==NULL){
00207         i_status=500;
00208         m=getStatusMessage(500);
00209     }
00210     //ステータスラインの記述
00211     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"HTTP/1.1 ",9)){
00212         NyLPC_OnErrorGoto(Error);
00213     }
00214     NyLPC_itoa(i_status,v,10);
00215     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){
00216         NyLPC_OnErrorGoto(Error);
00217     }
00218     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){
00219         NyLPC_OnErrorGoto(Error);
00220     }
00221     if(!writeln(i_inst->_ref_stream,m,-1)){
00222         NyLPC_OnErrorGoto(Error);
00223     }
00224     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Server: " NyLPC_cHttpdConfig_SERVER "\r\n",-1)){
00225         NyLPC_OnErrorGoto(Error);
00226     }
00227     if(i_inst->_is_close){
00228         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){
00229             NyLPC_OnErrorGoto(Error);
00230         }
00231     }
00232     //ヘッダの記述
00233     if(i_inst->_is_chunked){
00234         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){
00235             NyLPC_OnErrorGoto(Error);
00236         }
00237     }else{
00238         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){
00239             NyLPC_OnErrorGoto(Error);
00240         }
00241         NyLPC_uitoa (i_inst->_content_length,v,10);
00242         if(!writeln(i_inst->_ref_stream,v,-1)){
00243             NyLPC_OnErrorGoto(Error);
00244         }
00245     }
00246     //送信サイズをリセット
00247     i_inst->_size_of_sent=0;
00248     return NyLPC_TBool_TRUE;
00249 Error:
00250     i_inst->_is_error=NyLPC_TUInt8_FALSE;
00251     return NyLPC_TBool_FALSE;
00252 }
00253 
00254 /**
00255  * 独自定義のメッセージヘッダを記述します。
00256  */
00257 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_name,const NyLPC_TChar* i_field)
00258 {
00259     //エラー状態ならなにもしない。
00260     if(i_inst->_is_error){
00261         return NyLPC_TBool_FALSE;
00262     }
00263     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_name,-1)){
00264         NyLPC_OnErrorGoto(Error);
00265     }
00266     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,": ",2)){
00267         NyLPC_OnErrorGoto(Error);
00268     }
00269     if(!writeln(i_inst->_ref_stream,i_field,-1)){
00270         NyLPC_OnErrorGoto(Error);
00271     }
00272     return NyLPC_TBool_TRUE;
00273 Error:
00274     i_inst->_is_error=NyLPC_TUInt8_FALSE;
00275     return NyLPC_TBool_FALSE;
00276 }
00277 
00278 
00279 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRawMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_additional_header)
00280 {
00281     //エラー状態ならなにもしない。
00282     if(i_inst->_is_error){
00283         return NyLPC_TBool_FALSE;
00284     }
00285     if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_additional_header,strlen(i_additional_header))){
00286         NyLPC_OnErrorGoto(Error);
00287     }
00288     return NyLPC_TBool_TRUE;
00289 Error:
00290     i_inst->_is_error=NyLPC_TUInt8_FALSE;
00291     return NyLPC_TBool_FALSE;
00292 }
00293 
00294 /**
00295  * Httpヘッダの書き込みを完了します。
00296  * 続けてbody転送が可能な場合は、必要に応じてエンコーディングモードを更新します。
00297  * @return
00298  * 現在のストリームのステータスを返します。
00299  */
00300 NyLPC_TBool NyLPC_cHttpHeaderWriter_close(NyLPC_TcHttpHeaderWriter_t* i_inst)
00301 {
00302     //エラー状態ならなにもしない。
00303     if(i_inst->_is_error){
00304         return NyLPC_TBool_FALSE;
00305     }
00306     if(NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"\r\n",2)){
00307         if( NyLPC_iHttpPtrStream_flush(i_inst->_ref_stream)){
00308             return NyLPC_TBool_TRUE;
00309         }
00310     }
00311     return NyLPC_TBool_FALSE;
00312 }
00313 
00314 
00315