OSDN Git Service

git-svn-id: http://svn.osdn.jp/svnroot/mimic/trunk@198 47198e57-cb75-475f-84c4-a814cd...
[mimic/MiMicSDK.git] / lib / src / http / NyLPC_cHttpHeaderWriter.c
1 /*********************************************************************************\r
2  * PROJECT: MiMic\r
3  * --------------------------------------------------------------------------------\r
4  *\r
5  * This file is part of MiMic\r
6  * Copyright (C)2011 Ryo Iizuka\r
7  *\r
8  * MiMic is free software: you can redistribute it and/or modify\r
9  * it under the terms of the GNU Lesser General Public License as published\r
10  * by the Free Software Foundation, either version 3 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU Lesser General Public License\r
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
20  *\r
21  * For further information please contact.\r
22  *      http://nyatla.jp/\r
23  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
24  *\r
25  *********************************************************************************/\r
26 #include <stdlib.h>\r
27 \r
28 #include "NyLPC_cHttpHeaderWriter.h"\r
29 #include "NyLPC_cHttpdConfig.h"\r
30 \r
31 \r
32 /**\r
33  * Httpリクエストヘッダに対応したHttpヘッダライタを構築します。\r
34  */\r
35 NyLPC_TBool NyLPC_cHttpHeaderWriter_initialize(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TcHttpStream_t* i_ref_stream,const struct NyLPC_THttpBasicHeader* i_req_header)\r
36 {\r
37         i_inst->_is_chunked=NyLPC_TUInt8_FALSE;\r
38         i_inst->_content_length=0;\r
39         i_inst->_ref_stream=i_ref_stream;\r
40         i_inst->_is_error=NyLPC_TUInt8_FALSE;\r
41         //書込エンコーディングをなしにセット\r
42         NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);\r
43         //必要に応じてリクエストの内容をパース\r
44         if(i_req_header!=NULL){\r
45                 if(i_req_header->type!=NyLPC_THttpHeaderType_REQUEST){\r
46                         return NyLPC_TBool_FALSE;\r
47                 }\r
48                 //コネクションの持続性を決定\r
49                 if((i_req_header->connection==NyLPC_THttpMessgeHeader_Connection_CLOSE)||\r
50                         (i_req_header->startline.req.version!=NyLPC_THttpVersion_11))\r
51                 {\r
52                         i_inst->_is_close=NyLPC_TUInt8_TRUE;\r
53                 }else{\r
54                         i_inst->_is_close=NyLPC_TUInt8_FALSE;\r
55                 }\r
56         }else{\r
57                 i_inst->_is_close=NyLPC_TUInt8_TRUE;\r
58         }\r
59         return NyLPC_TBool_TRUE;\r
60 }\r
61 \r
62 #define NyLPC_cHttpHttpWriter_finalize(i)\r
63 \r
64 \r
65 void NyLPC_cHttpHeaderWriter_setChunked(NyLPC_TcHttpHeaderWriter_t* i_inst)\r
66 {\r
67         i_inst->_is_chunked=NyLPC_TUInt8_TRUE;\r
68         return;\r
69 }\r
70 void NyLPC_cHttpHeaderWriter_setContentLength(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt32 i_content_length)\r
71 {\r
72         i_inst->_content_length=i_content_length;\r
73         return;\r
74 }\r
75 void NyLPC_cHttpHeaderWriter_setClose(NyLPC_TcHttpHeaderWriter_t* i_inst)\r
76 {\r
77         i_inst->_is_close=NyLPC_TUInt8_TRUE;\r
78         return;\r
79 }\r
80 \r
81 \r
82 \r
83 const static struct{\r
84         NyLPC_TUInt16 code;\r
85         const NyLPC_TChar*  message;\r
86 }status_line_tbl[]={\r
87         {200,"OK"},\r
88         {400,"Bad Request"},\r
89         {403,"Forbidden"},\r
90         {404,"Not Found"},\r
91         {405,"Method Not Allowed"},\r
92         {500,"Internal Server Error"},\r
93         {0,NULL}//これ最後にしてね。\r
94 };\r
95 const static char* getStatusMessage(NyLPC_TUInt16 i_status)\r
96 {\r
97         int i=0;\r
98         while(status_line_tbl[i].code!=0){\r
99                 if(i_status==status_line_tbl[i].code){\r
100                         return status_line_tbl[i].message;\r
101                 }\r
102                 i++;\r
103         }\r
104         return NULL;\r
105 }\r
106 \r
107 static NyLPC_TBool writeln(NyLPC_TcHttpStream_t* i_inst,const void* i_data,NyLPC_TInt16 i_length)\r
108 {\r
109         if(NyLPC_iHttpPtrStream_write(i_inst,i_data,i_length)){\r
110                 if(NyLPC_iHttpPtrStream_write(i_inst,"\r\n",2)){\r
111                         return NyLPC_TBool_TRUE;\r
112                 }\r
113         }\r
114         return NyLPC_TBool_FALSE;\r
115 }\r
116 \r
117 \r
118 \r
119 #define TIMEOUT 10*1000\r
120 \r
121 /**\r
122  * ステータスラインと、標準メッセージヘッダを出力します。\r
123  */\r
124 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeHeader(NyLPC_TcHttpHeaderWriter_t* i_inst,NyLPC_TUInt16 i_status)\r
125 {\r
126         NyLPC_TChar v[12];\r
127         const char* m=getStatusMessage(i_status);\r
128         //エラー状態ならなにもしない。\r
129         if(i_inst->_is_error){\r
130                 return NyLPC_TBool_FALSE;\r
131         }\r
132         //検索に失敗したら500番に変更\r
133         if(m==NULL){\r
134                 i_status=500;\r
135                 m=getStatusMessage(500);\r
136         }\r
137         //ステータスラインの記述\r
138         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"HTTP/1.1 ",9)){\r
139                 NyLPC_OnErrorGoto(Error);\r
140         }\r
141         NyLPC_itoa(i_status,v,10);\r
142         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,v,-1)){\r
143                 NyLPC_OnErrorGoto(Error);\r
144         }\r
145         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream," ",1)){\r
146                 NyLPC_OnErrorGoto(Error);\r
147         }\r
148         if(!writeln(i_inst->_ref_stream,m,-1)){\r
149                 NyLPC_OnErrorGoto(Error);\r
150         }\r
151         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Server: " NyLPC_cHttpdConfig_SERVER "\r\n",-1)){\r
152                 NyLPC_OnErrorGoto(Error);\r
153         }\r
154         if(i_inst->_is_close){\r
155                 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Connection: CLOSE\r\n",-1)){\r
156                         NyLPC_OnErrorGoto(Error);\r
157                 }\r
158         }\r
159         //ヘッダの記述\r
160         if(i_inst->_is_chunked){\r
161                 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Transfer-Encoding: chunked\r\n",-1)){\r
162                         NyLPC_OnErrorGoto(Error);\r
163                 }\r
164         }else{\r
165                 if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"Content-Length: ",-1)){\r
166                         NyLPC_OnErrorGoto(Error);\r
167                 }\r
168                 NyLPC_itoa(i_inst->_content_length,v,10);\r
169                 if(!writeln(i_inst->_ref_stream,v,-1)){\r
170                         NyLPC_OnErrorGoto(Error);\r
171                 }\r
172         }\r
173         //送信サイズをリセット\r
174         i_inst->_size_of_sent=0;\r
175         return NyLPC_TBool_TRUE;\r
176 Error:\r
177         i_inst->_is_error=NyLPC_TUInt8_FALSE;\r
178         return NyLPC_TBool_FALSE;\r
179 }\r
180 \r
181 /**\r
182  * 独自定義のメッセージヘッダを記述します。\r
183  */\r
184 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_name,const NyLPC_TChar* i_field)\r
185 {\r
186         //エラー状態ならなにもしない。\r
187         if(i_inst->_is_error){\r
188                 return NyLPC_TBool_FALSE;\r
189         }\r
190         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_name,-1)){\r
191                 NyLPC_OnErrorGoto(Error);\r
192         }\r
193         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,": ",2)){\r
194                 NyLPC_OnErrorGoto(Error);\r
195         }\r
196         if(!writeln(i_inst->_ref_stream,i_field,-1)){\r
197                 NyLPC_OnErrorGoto(Error);\r
198         }\r
199         return NyLPC_TBool_TRUE;\r
200 Error:\r
201         i_inst->_is_error=NyLPC_TUInt8_FALSE;\r
202         return NyLPC_TBool_FALSE;\r
203 }\r
204 \r
205 \r
206 NyLPC_TBool NyLPC_cHttpHeaderWriter_writeRawMessage(NyLPC_TcHttpHeaderWriter_t* i_inst,const NyLPC_TChar* i_additional_header)\r
207 {\r
208         //エラー状態ならなにもしない。\r
209         if(i_inst->_is_error){\r
210                 return NyLPC_TBool_FALSE;\r
211         }\r
212         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,i_additional_header,strlen(i_additional_header))){\r
213                 NyLPC_OnErrorGoto(Error);\r
214         }\r
215         return NyLPC_TBool_TRUE;\r
216 Error:\r
217         i_inst->_is_error=NyLPC_TUInt8_FALSE;\r
218         return NyLPC_TBool_FALSE;\r
219 }\r
220 \r
221 /**\r
222  * Httpヘッダの書き込みを完了します。\r
223  * 続けてbody転送が可能な場合は、必要に応じてエンコーディングモードを更新します。\r
224  * @return\r
225  * 現在のストリームのステータスを返します。\r
226  */\r
227 NyLPC_TBool NyLPC_cHttpHeaderWriter_close(NyLPC_TcHttpHeaderWriter_t* i_inst)\r
228 {\r
229         //エラー状態ならなにもしない。\r
230         if(i_inst->_is_error){\r
231                 return NyLPC_TBool_FALSE;\r
232         }\r
233         if(NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"\r\n",2)){\r
234                 if(     NyLPC_iHttpPtrStream_flush(i_inst->_ref_stream)){\r
235                         return NyLPC_TBool_TRUE;\r
236                 }\r
237         }\r
238         return NyLPC_TBool_FALSE;\r
239 }\r
240 \r
241 \r
242 \r