2 * NyLPC_cHttpClient.c
\r
4 * Created on: 2013/08/24
\r
7 #include "NyLPC_cHttpClient.h"
\r
8 typedef NyLPC_TUInt8 NyLPC_TcHttpClient_ST;
\r
9 #define NyLPC_TcHttpClient_ST_CLOSED 0x00 //ソケット切断
\r
10 #define NyLPC_TcHttpClient_ST_IDLE 0x01 //メソッド選択待ち
\r
12 #define NyLPC_TcHttpClient_ST_SEND_REQ_BODY 0x21 //POSTリクエスト送信中
\r
13 #define NyLPC_TcHttpClient_ST_RECV_RES_HEAD 0x23
\r
14 #define NyLPC_TcHttpClient_ST_RECV_RES_BODY 0x24
\r
18 NyLPC_TBool NyLPC_cHttpClient_initialize(NyLPC_TcHttpClient_t* i_inst,void* i_rx_buf,NyLPC_TUInt16 i_rx_size)
\r
20 i_inst->_sock=NyLPC_cNet_createTcpSocketEx(NyLPC_TSocketType_TCP_NORMAL);
\r
21 if(i_inst->_sock==NULL){
\r
22 return NyLPC_TBool_FALSE;
\r
24 i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED;
\r
25 return NyLPC_TBool_TRUE;
\r
27 void NyLPC_cHttpClient_finalize(NyLPC_TcHttpClient_t* i_inst)
\r
29 NyLPC_cHttpClient_close(i_inst);
\r
30 NyLPC_iTcpSocket_finalize(i_inst->_sock);
\r
33 void NyLPC_cHttpClient_close(NyLPC_TcHttpClient_t* i_inst)
\r
36 switch(i_inst->_state){
\r
37 case NyLPC_TcHttpClient_ST_RECV_RES_BODY:
\r
38 NyLPC_cHttpBodyParser_finalize(&i_inst->pw.body_parser);
\r
40 case NyLPC_TcHttpClient_ST_SEND_REQ_BODY:
\r
41 NyLPC_cHttpBodyWriter_finalize(&(i_inst->pw.body_writer));
\r
43 case NyLPC_TcHttpClient_ST_RECV_RES_HEAD:
\r
46 case NyLPC_TcHttpClient_ST_IDLE:
\r
48 case NyLPC_TcHttpClient_ST_CLOSED:
\r
51 NyLPC_iTcpSocket_close(i_inst->_sock,1000);
\r
52 i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED;
\r
57 * 関数はステータスをIDLEへ遷移する。
\r
58 * インスタンスのステータスは何でも構わない。
\r
60 * TRUE - ステータスはIDLEへ遷移する。
\r
61 * FALSE - ステータスはCLOSEDへ遷移する。
\r
63 NyLPC_TBool NyLPC_cHttpClient_connect(NyLPC_TcHttpClient_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port)
\r
66 NyLPC_cHttpClient_close(i_inst);
\r
68 if(!NyLPC_iTcpSocket_connect(i_inst->_sock,i_addr,i_port,3000)){
\r
69 return NyLPC_TBool_FALSE;
\r
72 if(!NyLPC_cHttpStream_initialize(&i_inst->_stream,i_inst->_sock)){
\r
73 NyLPC_OnErrorGoto(ERROR);
\r
76 i_inst->_state=NyLPC_TcHttpClient_ST_IDLE;
\r
77 return NyLPC_TBool_TRUE;
\r
79 return NyLPC_TBool_FALSE;
\r
89 NyLPC_TBool NyLPC_cHttpClient_sendMethod(
\r
90 NyLPC_TcHttpClient_t* i_inst,
\r
91 NyLPC_THttpMethodType i_method,
\r
92 const NyLPC_TChar* i_path,
\r
93 NyLPC_TUInt32 i_content_length,
\r
94 const NyLPC_TChar* i_mime_type,
\r
95 const NyLPC_TChar* i_additional_header)
\r
98 if(i_inst->_state!=NyLPC_TcHttpClient_ST_IDLE){
\r
99 NyLPC_OnErrorGoto(Error_0);
\r
102 if(!NyLPC_cHttpHeaderWriter_initialize(&i_inst->pw.head_writer,&i_inst->_stream.super,NULL)){
\r
103 NyLPC_OnErrorGoto(Error_0);
\r
106 NyLPC_cHttpHeaderWriter_setConnectionClose(&i_inst->pw.head_writer,NyLPC_TBool_TRUE);//Connection closeを強制
\r
107 if(i_content_length==NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED){
\r
108 NyLPC_cHttpHeaderWriter_setChunked(&i_inst->pw.head_writer);
\r
110 NyLPC_cHttpHeaderWriter_setContentLength(&i_inst->pw.head_writer,i_content_length);
\r
112 if(!NyLPC_cHttpHeaderWriter_writeRequestHeader(
\r
113 &i_inst->pw.head_writer,
\r
115 NyLPC_iTcpSocket_getPeerAddr((i_inst->_sock)),
\r
116 NyLPC_iTcpSocket_getPeerPort((i_inst->_sock)),i_path)){
\r
117 NyLPC_OnErrorGoto(Error_1);
\r
120 if(i_mime_type!=NULL){
\r
121 if(!NyLPC_cHttpHeaderWriter_writeMessage(&i_inst->pw.head_writer,"Content-type",i_mime_type)){
\r
122 NyLPC_OnErrorGoto(Error_1);
\r
125 if(i_additional_header!=NULL){
\r
126 if(!NyLPC_cHttpHeaderWriter_writeRawMessage(&i_inst->pw.head_writer,i_additional_header)){
\r
127 NyLPC_OnErrorGoto(Error_1);
\r
130 NyLPC_cHttpHeaderWriter_close(&i_inst->pw.head_writer);
\r
131 NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer);
\r
134 NyLPC_cHttpBodyWriter_initialize(&(i_inst->pw.body_writer),&(i_inst->_stream));
\r
136 if(i_content_length==0xffffffff){
\r
137 NyLPC_cHttpBodyWriter_setChunked(&(i_inst->pw.body_writer));
\r
139 NyLPC_cHttpBodyWriter_setContentLength(&(i_inst->pw.body_writer),i_content_length);
\r
141 i_inst->_state=NyLPC_TcHttpClient_ST_SEND_REQ_BODY;
\r
142 return NyLPC_TBool_TRUE;
\r
144 return NyLPC_TBool_FALSE;
\r
146 NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer);
\r
147 return NyLPC_TBool_FALSE;
\r
151 * POSTリクエストのデータを送信する。
\r
155 NyLPC_TBool NyLPC_cHttpClient_write(NyLPC_TcHttpClient_t* i_inst,const void* i_buf,NyLPC_TUInt32 i_buf_size)
\r
157 if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
\r
158 return NyLPC_TBool_FALSE;
\r
160 if(!NyLPC_cHttpBodyWriter_write(&i_inst->pw.body_writer,i_buf,i_buf_size)){
\r
162 NyLPC_cHttpClient_close(i_inst);
\r
163 NyLPC_OnErrorGoto(Error);
\r
165 return NyLPC_TBool_TRUE;
\r
167 return NyLPC_TBool_FALSE;
\r
170 NyLPC_TBool NyLPC_cHttpClient_writeFormat(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,...)
\r
174 if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
\r
175 return NyLPC_TBool_FALSE;
\r
178 ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,a);
\r
181 NyLPC_cHttpClient_close(i_inst);
\r
185 NyLPC_TBool NyLPC_cHttpClient_writeFormatV(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args)
\r
188 if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
\r
189 return NyLPC_TBool_FALSE;
\r
191 ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,i_args);
\r
193 NyLPC_cHttpClient_close(i_inst);
\r
204 NyLPC_TUInt16 NyLPC_cHttpClient_getStatus(NyLPC_TcHttpClient_t* i_inst)
\r
206 struct NyLPC_THttpBasicHeader header;
\r
207 if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
\r
211 if(!NyLPC_cHttpBodyWriter_close(&i_inst->pw.body_writer)){
\r
212 NyLPC_OnErrorGoto(Error_1);
\r
214 i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_HEAD;
\r
215 //100を無視してHTTPヘッダをパース
\r
216 //@todo POSTの時だけに制限したら?
\r
218 NyLPC_cHttpBasicHeaderParser_initialize(&i_inst->pw.head_parser,NULL);
\r
219 NyLPC_cHttpBasicHeaderParser_parseInit(&i_inst->pw.head_parser,&header);
\r
220 if(!NyLPC_cHttpBasicHeaderParser_parseStream(&i_inst->pw.head_parser,&i_inst->_stream.super,&header)){
\r
221 NyLPC_OnErrorGoto(Error_2);
\r
223 if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&i_inst->pw.head_parser,&header)){
\r
224 NyLPC_OnErrorGoto(Error_2);
\r
226 NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser);
\r
228 if(header.type!=NyLPC_THttpHeaderType_RESPONSE){
\r
229 NyLPC_OnErrorGoto(Error_1);
\r
231 }while(header.startline.res.status==100);
\r
233 NyLPC_cHttpBodyParser_initialize(&i_inst->pw.body_parser);
\r
234 NyLPC_cHttpBodyParser_parseInit(&i_inst->pw.body_parser,&header);
\r
235 i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_BODY;
\r
236 return header.startline.res.status;
\r
238 NyLPC_cHttpClient_close(i_inst);
\r
241 NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser);
\r
242 NyLPC_cHttpClient_close(i_inst);
\r
248 * GET/POSTリクエストで受信したデータを読み出す。
\r
249 * @param o_read_len
\r
253 * TRUE:正常読み出し。o_read_lenの値で終端判定
\r
254 * FALSE:失敗。コネクションはクローズされる。
\r
256 NyLPC_TBool NyLPC_cHttpClient_read(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size,NyLPC_TInt16* o_read_len)
\r
258 if(i_inst->_state!=NyLPC_TcHttpClient_ST_RECV_RES_BODY){
\r
259 return NyLPC_TBool_FALSE;
\r
261 if(!NyLPC_cHttpBodyParser_parseStream(&i_inst->pw.body_parser,&i_inst->_stream.super,i_buf,i_buf_size,o_read_len)){
\r
262 NyLPC_cHttpClient_close(i_inst);
\r
263 return NyLPC_TBool_FALSE;
\r
265 return NyLPC_TBool_TRUE;
\r