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_iTcpSocket_initialized(void* inst,const char* rb,int l)
\r
41 void* NyLPC_iIpTcpSocket_allocSendBuf(void* inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_len,NyLPC_TUInt32 i_to)
\r
46 NyLPC_TBool NyLPC_iTcpSocket_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_iTcpSocket_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_iTcpSocket_pseek(void* i_inst,NyLPC_TUInt16 i_seek)
\r
63 void* NyLPC_iTcpSocket_releaseSendBuf(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr)
\r
70 static NyLPC_TInt32 pread_func(void* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_timeout);
\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
81 #define HTTP_TX_BUF_HINT 1024
\r
84 const static struct NyLPC_TiHttpPtrStream_TInterface _interface=
\r
90 setReadEncoding_func,
\r
91 setWriteEncoding_func
\r
95 * i_bufに5バイトのchunkedヘッダを書きます。
\r
97 static void put_chunked_header(NyLPC_TUInt16 i_val,NyLPC_TUInt8* o_buf)
\r
99 const static char* D="0123456789ABCDEF";
\r
100 *(o_buf+0)=D[((i_val&0x0f00)>>8)];
\r
101 *(o_buf+1)=D[((i_val&0x00f0)>>4)];
\r
102 *(o_buf+2)=D[ (i_val&0x000f)];
\r
107 * 接続済のソケットをストリームに抽象化します。
\r
109 NyLPC_TBool NyLPC_cHttpStream_initialize(NyLPC_TcHttpStream_t* i_inst,NyLPC_TiTcpSocket_t* i_ref_sock)
\r
111 i_inst->super.absfunc=&_interface;
\r
112 i_inst->_ref_sock=i_ref_sock;
\r
113 i_inst->we_type=NyLPC_TiHttpPtrStream_ET_NONE;
\r
114 i_inst->re_type=NyLPC_TiHttpPtrStream_ET_NONE;
\r
116 return NyLPC_TBool_TRUE;
\r
119 void NyLPC_cHttpStream_finalize(NyLPC_TcHttpStream_t* i_inst)
\r
121 if(i_inst->txb!=NULL){
\r
122 NyLPC_iTcpSocket_releaseSendBuf(i_inst->_ref_sock,i_inst->txb);
\r
130 static NyLPC_TInt32 pread_func(void* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_timeout)
\r
132 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
133 return NyLPC_iTcpSocket_precv(inst->_ref_sock,o_buf_ptr,i_timeout);
\r
136 static NyLPC_TBool write_func(void* i_inst,const void* i_data,NyLPC_TInt32 i_length)
\r
138 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
139 NyLPC_TUInt16 s,free_size;
\r
141 const char* src=(const char*)i_data;
\r
142 l=((i_length<0)?strlen(src):i_length);
\r
144 //送信バッファがNULLなら、割り当て。
\r
145 if(inst->txb==NULL){
\r
146 inst->txb=(NyLPC_TUInt8*)NyLPC_iTcpSocket_allocSendBuf(inst->_ref_sock,HTTP_TX_BUF_HINT,&s,NyLPC_TiHttpPtrStream_DEFAULT_HTTP_TIMEOUT);
\r
147 if(inst->txb==NULL){
\r
148 return NyLPC_TBool_FALSE;
\r
150 //chunked encodingなら、先頭5バイト+末尾2バイトを予約する. 000
\r
151 if(inst->we_type==NyLPC_TiHttpPtrStream_ET_CHUNKED){
\r
153 inst->txb_size=s-7;
\r
160 free_size=inst->txb_size-inst->tx_len;
\r
161 if((NyLPC_TInt32)free_size>l){
\r
162 //書き込み可能サイズがi_length未満なら、バッファに貯めるだけ。
\r
163 memcpy(inst->txb+inst->tx_len,src,l);
\r
164 inst->tx_len+=(NyLPC_TUInt16)l;
\r
167 //バッファフルになるなら、送信する。
\r
168 memcpy(inst->txb+inst->tx_len,src,free_size);
\r
169 inst->tx_len+=free_size;
\r
171 if(!flush_func(i_inst)){
\r
173 return NyLPC_TBool_FALSE;
\r
179 return NyLPC_TBool_TRUE;
\r
183 static void pseek_func(void* i_inst,NyLPC_TUInt16 i_seek)
\r
185 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
187 NyLPC_iTcpSocket_pseek(inst->_ref_sock,i_seek);
\r
191 * キャッシュに保持してるデータを出力する。
\r
193 static NyLPC_TBool flush_func(void* i_inst)
\r
195 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
196 if(inst->txb==NULL){
\r
197 return NyLPC_TBool_TRUE;
\r
199 //chunkedの場合は、header/footerをセットする。
\r
200 if(inst->we_type==NyLPC_TiHttpPtrStream_ET_CHUNKED){
\r
202 put_chunked_header(inst->tx_len-5,inst->txb);
\r
203 *(inst->txb+inst->tx_len)=0x0d;
\r
204 *(inst->txb+inst->tx_len+1)=0x0a;
\r
208 if(!NyLPC_iTcpSocket_psend(inst->_ref_sock,inst->txb,inst->tx_len,NyLPC_TiHttpPtrStream_DEFAULT_HTTP_TIMEOUT)){
\r
210 NyLPC_iTcpSocket_releaseSendBuf(inst->_ref_sock,inst->txb);
\r
212 return NyLPC_TBool_FALSE;
\r
216 return NyLPC_TBool_TRUE;
\r
218 static void setReadEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et)
\r
224 static void setWriteEncoding_func(void* i_inst,NyLPC_TiHttpPtrStream_ET i_et)
\r
226 NyLPC_TcHttpStream_t* inst=(NyLPC_TcHttpStream_t*)i_inst;
\r
227 if(inst->we_type==i_et)
\r
231 //バッファがあるならフラッシュしてしまう。
\r
232 if(inst->txb!=NULL){
\r
233 if(!flush_func(i_inst)){
\r
238 inst->we_type=i_et;
\r