00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <time.h>
00013 #include <u/libu.h>
00014 #include <klone/request.h>
00015 #include <klone/response.h>
00016 #include <klone/session.h>
00017 #include <klone/utils.h>
00018 #include <klone/io.h>
00019 #include <klone/codec.h>
00020 #include <klone/http.h>
00021 #include <klone/response.h>
00022 #include <klone/rsfilter.h>
00023 #include <klone/ses_prv.h>
00024
00025
00026
00027
00028
00029
00030 enum {
00031 RFS_BUFFERING,
00032 RFS_FLUSHING
00033 };
00034
00035 struct response_filter_s
00036 {
00037 codec_t codec;
00038 request_t *rq;
00039 response_t *rs;
00040 session_t *ss;
00041 int state;
00042 char buf[RFBUFSZ], *ptr;
00043 size_t off;
00044 io_t *iob;
00045 };
00046
00047 static int rf_init_iob(response_filter_t *rf)
00048 {
00049 char *h;
00050 size_t hsz, htell;
00051
00052 dbg_err_if (rf == NULL);
00053
00054 hsz = response_get_max_header_size(rf->rs) + rf->off;
00055
00056 h = (char *)u_zalloc(hsz);
00057 dbg_err_if(h == NULL);
00058
00059 dbg_err_if(io_mem_create(h, hsz, 0, &rf->iob));
00060
00061
00062 response_print_header_to_io(rf->rs, rf->iob);
00063
00064 if(response_get_method(rf->rs) != HM_HEAD)
00065 {
00066
00067 dbg_err_if(io_write(rf->iob, rf->buf, rf->off) < 0);
00068 }
00069 dbg_err_if(io_flush(rf->iob));
00070
00071 htell = io_tell(rf->iob);
00072
00073 dbg_if(io_free(rf->iob));
00074 rf->iob = NULL;
00075
00076
00077 dbg_err_if(io_mem_create(h, htell, IO_MEM_FREE_BUF, &rf->iob));
00078
00079 return 0;
00080 err:
00081 return ~0;
00082 }
00083
00084 static int rf_flush(codec_t *codec, char *dst, size_t *dcount)
00085 {
00086 response_filter_t *rf = (response_filter_t*)codec;
00087 ssize_t c;
00088
00089 dbg_err_if (codec == NULL);
00090 dbg_err_if (dst == NULL);
00091 dbg_err_if (dcount == NULL);
00092
00093 if(rf->state == RFS_BUFFERING)
00094 {
00095 rf->state = RFS_FLUSHING;
00096
00097
00098 dbg_err_if(rf_init_iob(rf));
00099 }
00100
00101 if(rf->iob)
00102 {
00103 dbg_err_if((c = io_read(rf->iob, dst, *dcount)) < 0);
00104 if(c == 0)
00105 {
00106 io_free(rf->iob);
00107 rf->iob = NULL;
00108 } else {
00109 *dcount = c;
00110 return CODEC_FLUSH_CHUNK;
00111 }
00112 }
00113
00114 return CODEC_FLUSH_COMPLETE;
00115 err:
00116 return -1;
00117 }
00118
00119 static ssize_t rf_transform(codec_t *codec,
00120 char *dst, size_t *dcount,
00121 const char *src, size_t src_sz)
00122 {
00123 response_filter_t *rf = (response_filter_t*)codec;
00124 size_t max;
00125 ssize_t c;
00126
00127 dbg_err_if (codec == NULL);
00128 dbg_err_if (dst == NULL);
00129 dbg_err_if (dcount == NULL);
00130 dbg_err_if (src == NULL);
00131
00132
00133 if(response_get_method(rf->rs) == HM_HEAD)
00134 {
00135 *dcount = 0;
00136 return src_sz;
00137 }
00138
00139 if(rf->state == RFS_BUFFERING)
00140 {
00141 if(rf->off + src_sz < RFBUFSZ)
00142 {
00143 memcpy(rf->buf + rf->off, src, src_sz);
00144 rf->off += src_sz;
00145 *dcount = 0;
00146 return src_sz;
00147 } else {
00148
00149 rf->state = RFS_FLUSHING;
00150
00151
00152
00153 if(rf->ss && strlen(rf->ss->id) == 0)
00154 dbg_err_if(session_priv_set_id(rf->ss, NULL));
00155
00156
00157 dbg_err_if(rf_init_iob(rf));
00158 }
00159 }
00160
00161 if(rf->iob)
00162 {
00163 dbg_err_if((c = io_read(rf->iob, dst, *dcount)) < 0);
00164 if(c == 0)
00165 {
00166 io_free(rf->iob);
00167 rf->iob = NULL;
00168 } else {
00169 *dcount = c;
00170 return 0;
00171 }
00172 }
00173
00174
00175 max = MIN(*dcount, src_sz);
00176 memcpy(dst, src, max);
00177 *dcount = max;
00178 return max;
00179 err:
00180 return -1;
00181 }
00182
00183 static int rf_free(codec_t *codec)
00184 {
00185 response_filter_t *rf;
00186
00187 dbg_return_if (codec == NULL, 0);
00188
00189 rf = (response_filter_t*)codec;
00190
00191 if(rf->iob)
00192 io_free(rf->iob);
00193
00194 U_FREE(rf);
00195
00196 return 0;
00197 }
00198
00199 int response_filter_create(request_t *rq, response_t *rs, session_t *ss,
00200 codec_t **prf)
00201 {
00202 response_filter_t *rf = NULL;
00203
00204 dbg_err_if (rs == NULL);
00205 dbg_err_if (prf == NULL);
00206
00207 rf = u_zalloc(sizeof(response_filter_t));
00208 dbg_err_if(rf == NULL);
00209
00210 rf->rq = rq;
00211 rf->rs = rs;
00212 rf->ss = ss;
00213 rf->codec.transform = rf_transform;
00214 rf->codec.flush = rf_flush;
00215 rf->codec.free = rf_free;
00216 rf->ptr = rf->buf;
00217 rf->iob = NULL;
00218
00219 *prf = (codec_t*)rf;
00220
00221 return 0;
00222 err:
00223 U_FREE(rf);
00224 return ~0;
00225 }