1 /*********************************************************************************
\r
3 * --------------------------------------------------------------------------------
\r
5 * This file is part of MiMic
\r
6 * Copyright (C)2011 Ryo Iizuka
\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
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
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
21 * For further information please contact.
\r
23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
25 *********************************************************************************/
\r
26 #include "NyLPC_cHttpStream.h"
\r
30 #if NyLPC_CONFIG_cHttpStream_DEBUG == 1
\r
35 void NyLPC_cTcpSocket_initialized(void* inst,const char* rb,int l)
\r
41 void* NyLPC_cTcpSocket_allocSendBuf(void* inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_len,NyLPC_TUInt32 i_to)
\r
46 NyLPC_TBool NyLPC_cTcpSocket_psend(void* inst,void* i_buf,NyLPC_TUInt16 i_len,NyLPC_TUInt32 i_to)
\r
48 printf("%.*s",i_len,i_buf);
\r
49 return NyLPC_TBool_TRUE;
\r
51 NyLPC_TInt32 NyLPC_cTcpSocket_precv(void* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
\r
53 int l=_rbuf_len>100?100:_rbuf_len;
\r
57 void NyLPC_cTcpSocket_pseek(void* i_inst,NyLPC_TUInt16 i_seek)
\r
63 void* NyLPC_cTcpSocket_releaseSendBuf(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr)
\r
70 static NyLPC_TInt32 pread_func(void* i_inst,const void** o_buf_ptr);
\r
71 static NyLPC_TBool write_func(void* i_inst,const void* i_data,NyLPC_TInt32 i_length);
\r
72 static void pseek_func(void* i_inst,NyLPC_TUInt16 i_seek);
\r
73 static NyLPC_TBool flush_func(void* i_inst);
\r
74 static void setReadEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et);
\r
75 static void setWriteEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et);
\r
80 #define HTTP_TIMEOUT 10*1000
\r
84 #define HTTP_TX_BUF_HINT 1024
\r
87 const static struct NyLPC_TiHttpPtrStream_TInterface _interface=
\r
93 setReadEncoding_func,
\r
94 setWriteEncoding_func
\r
98 * i_bufに5バイトのchunkedヘッダを書きます。
\r
100 static void put_chunked_header(NyLPC_TUInt16 i_val,NyLPC_TUInt8* o_buf)
\r
102 const static char* D="0123456789ABCDEF";
\r
103 *(o_buf+0)=D[((i_val&0x0f00)>>8)];
\r
104 *(o_buf+1)=D[((i_val&0x00f0)>>4)];
\r
105 *(o_buf+2)=D[ (i_val&0x000f)];
\r
110 * 接続済のソケットをストリームに抽象化します。
\r
112 NyLPC_TBool NyLPC_cHttpStream_initialize(NyLPC_TcHttpStream_t* i_inst,NyLPC_TcTcpSocket_t* i_ref_sock)
\r
114 i_inst->_interface_httpptrstream=&_interface;
\r
115 i_inst->_ref_sock=i_ref_sock;
\r
116 i_inst->we_type=NyLPC_TiHttpPtrStream_ET_NONE;
\r
117 i_inst->re_type=NyLPC_TiHttpPtrStream_ET_NONE;
\r
119 return NyLPC_TBool_TRUE;
\r
122 void NyLPC_cHttpStream_finalize(NyLPC_TcHttpStream_t* i_inst)
\r
124 if(i_inst->txb!=NULL){
\r
125 NyLPC_cTcpSocket_releaseSendBuf(i_inst->_ref_sock,i_inst->txb);
\r
133 static NyLPC_TInt32 pread_func(void* i_inst,const void** o_buf_ptr)
\r
135 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
136 return NyLPC_cTcpSocket_precv(inst->_ref_sock,o_buf_ptr,HTTP_TIMEOUT);
\r
139 static NyLPC_TBool write_func(void* i_inst,const void* i_data,NyLPC_TInt32 i_length)
\r
141 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
142 NyLPC_TUInt16 s,free_size;
\r
144 const char* src=i_data;
\r
145 l=(NyLPC_TUInt16)(i_length<0?strlen(src):i_length);
\r
146 if(l>=NyLPC_TUInt16_MAX){
\r
147 return NyLPC_TBool_FALSE;
\r
150 //送信バッファがNULLなら、割り当て。
\r
151 if(inst->txb==NULL){
\r
152 inst->txb=NyLPC_cTcpSocket_allocSendBuf(inst->_ref_sock,HTTP_TX_BUF_HINT,&s,HTTP_TIMEOUT);
\r
153 if(inst->txb==NULL){
\r
154 return NyLPC_TBool_FALSE;
\r
156 //chunked encodingなら、先頭5バイト+末尾2バイトを予約する. 000
\r
157 if(inst->we_type==NyLPC_TiHttpPtrStream_ET_CHUNKED){
\r
159 inst->txb_size=s-7;
\r
166 free_size=inst->txb_size-inst->tx_len;
\r
168 //書き込み可能サイズがi_length未満なら、バッファに貯めるだけ。
\r
169 memcpy(inst->txb+inst->tx_len,src,l);
\r
170 inst->tx_len+=(NyLPC_TUInt16)l;
\r
173 //バッファフルになるなら、送信する。
\r
174 memcpy(inst->txb+inst->tx_len,src,free_size);
\r
175 inst->tx_len+=free_size;
\r
177 flush_func(i_inst);
\r
182 return NyLPC_TBool_TRUE;
\r
186 static void pseek_func(void* i_inst,NyLPC_TUInt16 i_seek)
\r
188 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
190 NyLPC_cTcpSocket_pseek(inst->_ref_sock,i_seek);
\r
194 * キャッシュに保持してるデータを出力する。
\r
196 static NyLPC_TBool flush_func(void* i_inst)
\r
198 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
199 if(inst->txb==NULL){
\r
200 return NyLPC_TBool_TRUE;
\r
202 //chunkedの場合は、header/footerをセットする。
\r
203 if(inst->we_type==NyLPC_TiHttpPtrStream_ET_CHUNKED){
\r
205 put_chunked_header(inst->tx_len-5,inst->txb);
\r
206 *(inst->txb+inst->tx_len)=0x0d;
\r
207 *(inst->txb+inst->tx_len+1)=0x0a;
\r
211 if(!NyLPC_cTcpSocket_psend(inst->_ref_sock,inst->txb,inst->tx_len,HTTP_TIMEOUT)){
\r
213 NyLPC_cTcpSocket_releaseSendBuf(inst->_ref_sock,inst->txb);
\r
215 return NyLPC_TBool_FALSE;
\r
219 return NyLPC_TBool_TRUE;
\r
221 static void setReadEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et)
\r
227 static void setWriteEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et)
\r
229 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
230 if(inst->we_type==i_et)
\r
234 //バッファがあるならフラッシュしてしまう。
\r
235 if(inst->txb!=NULL){
\r
236 if(!flush_func(i_inst)){
\r
241 inst->we_type=i_et;
\r