OSDN Git Service

update libMiMic
[mimic/MiMicSDK.git] / lib / src / http / NyLPC_cHttpBodyWriter.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 \r
27 \r
28 #include <stdlib.h>\r
29 #include "NyLPC_utils.h"\r
30 #include "NyLPC_cHttpBodyWriter.h"\r
31 \r
32 \r
33 \r
34 \r
35 \r
36 \r
37 /**\r
38  * PrintHandler\r
39  */\r
40 static NyLPC_TBool printHandler(void* i_inst,const void* i_buf,NyLPC_TUInt32 i_len)\r
41 {\r
42     //エラー状態ならFALSE\r
43     if(((NyLPC_TcHttpBodyWriter_t*)i_inst)->_is_error){\r
44         return NyLPC_TBool_FALSE;\r
45     }\r
46     ((NyLPC_TcHttpBodyWriter_t*)i_inst)->_size_of_sent+=i_len;\r
47     if(!NyLPC_iHttpPtrStream_write(((NyLPC_TcHttpBodyWriter_t*)i_inst)->_ref_stream,i_buf,i_len)){\r
48         ((NyLPC_TcHttpBodyWriter_t*)i_inst)->_is_error=NyLPC_TUInt8_TRUE;\r
49         return NyLPC_TBool_FALSE;\r
50     }\r
51     return NyLPC_TBool_TRUE;\r
52 }\r
53 \r
54 \r
55 \r
56 void NyLPC_cHttpBodyWriter_initialize(NyLPC_TcHttpBodyWriter_t* i_inst,NyLPC_TcHttpStream_t* i_stream)\r
57 {\r
58     i_inst->_ref_stream=&(i_stream->super);\r
59     i_inst->_is_chunked=NyLPC_TUInt8_FALSE;\r
60     i_inst->_is_error=NyLPC_TUInt8_FALSE;\r
61     i_inst->_size_of_sent=0;\r
62     i_inst->_content_length=0;\r
63     NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);\r
64 }\r
65 \r
66 void NyLPC_cHttpBodyWriter_setChunked(NyLPC_TcHttpBodyWriter_t* i_inst)\r
67 {\r
68     i_inst->_is_chunked=NyLPC_TUInt8_TRUE;\r
69     NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_CHUNKED);\r
70 }\r
71 void NyLPC_cHttpBodyWriter_setContentLength(NyLPC_TcHttpBodyWriter_t* i_inst,NyLPC_TUInt32 i_content_length)\r
72 {\r
73     i_inst->_is_chunked=NyLPC_TUInt8_FALSE;\r
74     i_inst->_content_length=i_content_length;\r
75     NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);\r
76 }\r
77 \r
78 \r
79 /**\r
80  * HttpBodyを書き込みます。\r
81  * @return\r
82  * 偽を返した場合は、コネクションを切断してください。\r
83  */\r
84 NyLPC_TBool NyLPC_cHttpBodyWriter_write(NyLPC_TcHttpBodyWriter_t* i_inst,const void* i_buf,NyLPC_TUInt32 i_len)\r
85 {\r
86     return printHandler(i_inst,i_buf,i_len);\r
87 }\r
88 \r
89 /**\r
90  * HttpBodyの書き込みを完了します。\r
91  * @return\r
92  */\r
93 NyLPC_TBool NyLPC_cHttpBodyWriter_close(NyLPC_TcHttpBodyWriter_t* i_inst)\r
94 {\r
95     //エラー状態ならFALSE\r
96     if(i_inst->_is_error){\r
97         return NyLPC_TBool_FALSE;\r
98     }\r
99     //chunkedの場合、フッタを書き込む\r
100     if(i_inst->_is_chunked){\r
101         //エンコーディングを戻す。\r
102         NyLPC_iHttpPtrStream_setWriteEncoding(i_inst->_ref_stream,NyLPC_TiHttpPtrStream_ET_NONE);\r
103         //フッタを書き込む。\r
104         if(!NyLPC_iHttpPtrStream_write(i_inst->_ref_stream,"0\r\n\r\n",5)){\r
105             i_inst->_is_error=NyLPC_TUInt8_TRUE;\r
106             return NyLPC_TBool_FALSE;\r
107         }\r
108     }\r
109     //エラーでないときはストリームをフラッシュ\r
110     NyLPC_iHttpPtrStream_flush(i_inst->_ref_stream);\r
111     //クローズのステータスで状態を変える。\r
112     return NyLPC_TBool_TRUE;\r
113 }\r
114 \r
115 /**\r
116  * printfライクな書式出力を提供します。\r
117  * @i_fmt\r
118  * 書式文字列です。%d,%x,%s,%c,%%をサポートします。\r
119  */\r
120 NyLPC_TBool NyLPC_cHttpBodyWriter_format(NyLPC_TcHttpBodyWriter_t* i_inst,const NyLPC_TChar* i_fmt,...)\r
121 {\r
122     NyLPC_TBool ret;\r
123     va_list a;\r
124     //エラー状態ならFALSE\r
125     if(i_inst->_is_error){\r
126         return NyLPC_TBool_FALSE;\r
127     }\r
128     va_start(a,i_fmt);\r
129     ret=   NyLPC_cFormatWriter_print(printHandler,i_inst,i_fmt,a);\r
130     va_end(a);\r
131     return ret;\r
132 }\r
133 \r
134 NyLPC_TBool NyLPC_cHttpBodyWriter_formatV(NyLPC_TcHttpBodyWriter_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args)\r
135 {\r
136     NyLPC_TBool ret;\r
137     //エラー状態ならFALSE\r
138     if(i_inst->_is_error){\r
139         return NyLPC_TBool_FALSE;\r
140     }\r
141     ret=NyLPC_cFormatWriter_print(printHandler,i_inst,i_fmt,i_args);\r
142     return ret;\r
143 }\r
144 \r
145 /**\r
146  * テスト用のコード。\r
147  */\r
148 #define TEST\r
149 #ifndef TEST\r
150 //テスト\r
151 #include "NyLPC_cHttpHeaderWriter.h"\r
152 \r
153 const char* TP1=\r
154         "HTTP/0.9 200 OK\r\n"\r
155         "HOST: 127.0.0.0.0.0.1\r\n"\r
156         "CONTENt-LENGTH: 1285\r\n"\r
157         "CONNECTION: CloSe\r\n"\r
158         "ETAG: nyatla.jp\r\n"\r
159         "ETAG: nyatla.jp\r\n"\r
160         "Transfer-Encoding:chunked\r\n"\r
161         "\r\n";\r
162 const char* TP2=\r
163         "GET /nyanyanya!/nyoronnnnnnnnnnnn?m,fpeofjregnoegnr HTTP/1.1\r\n"\r
164         "HOST: 127.0.0.0.0.0.1\r\n"\r
165         "CONTENt-LENGTH: 1285\r\n"\r
166         "CONNECTION: Keep\r\n"\r
167         "ETAG: nyatla.jp\r\n"\r
168         "ETAG: nyatla.jp\r\n"\r
169         "\r\n";\r
170 const char* DT="0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";\r
171 \r
172 \r
173 \r
174 \r
175 \r
176 \r
177 void main()\r
178 {\r
179     NyLPC_TcHttpStream_t st;\r
180     NyLPC_TcHttpBasicHeaderParser_t hp;\r
181     struct NyLPC_THttpBasicHeader reqheader;\r
182     NyLPC_TcHttpHeaderWriter_t hw;\r
183     NyLPC_TcHttpBodyWriter_t bw;\r
184     NyLPC_TcTcpSocket_t ts;\r
185     int body_len;\r
186     NyLPC_cTcpSocket_initialized(NULL,TP2,strlen(TP2));\r
187 \r
188     //TCPのオープン\r
189     if(!NyLPC_cHttpStream_initialize(&st,&ts)){\r
190         //エラー\r
191     }\r
192     for(;;){\r
193         //ヘッダ解析\r
194         NyLPC_cHttpBasicHeaderParser_initialize(&hp);\r
195         if(!NyLPC_cHttpShortRequestHeaderParser_parse(&hp,&st,&reqheader)){\r
196             //エラー\r
197             puts("Error");\r
198         }\r
199         //ヘッダの内容確認\r
200         if(reqheader.type!=NyLPC_THttpHeaderType_REQUEST){\r
201             //BadRequest\r
202             puts("Error");\r
203         }\r
204         if(reqheader.startline.req.method!=NyLPC_THttpMethodType_GET){\r
205             //リクエストサポートしてない\r
206             puts("Error");\r
207         }\r
208         //\r
209         NyLPC_cHttpHeaderWriter_initialize(&hw,&st,&reqheader);\r
210 //      NyLPC_cHttpResponseWriter_setClose(&hw);\r
211         body_len=100;\r
212         NyLPC_cHttpHeaderWriter_setContentLength(&hw,body_len);\r
213         NyLPC_cHttpHeaderWriter_writeResponseHeader(&hw,500);\r
214         NyLPC_cHttpHeaderWriter_close(&hw);\r
215 \r
216         NyLPC_cHttpBodyWriter_initialize(&bw,&st);\r
217         NyLPC_cHttpBodyWriter_setChunked(&bw);\r
218         NyLPC_cHttpBodyWriter_write(&bw,"TEST",4);\r
219         NyLPC_cHttpBodyWriter_printf(&bw,"TEST");\r
220         NyLPC_cHttpBodyWriter_printf(&bw,"TEST[%s][%d][%c],%%,[%x]","abcde",123,'s',0xff0011);\r
221         NyLPC_cHttpBodyWriter_close(&bw);\r
222         NyLPC_cHttpHttpWriter_finalize(&hw);\r
223     }\r
224     NyLPC_cHttpStream_finalize(&st);\r
225     //TCPのクローズ\r
226     return;\r
227 }\r
228 #endif\r