rsfilter.c
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, feeded;
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
00090 dbg_err_if (codec == NULL);
00091 dbg_err_if (dst == NULL);
00092 dbg_err_if (dcount == NULL);
00093
00094 if(rf->state == RFS_BUFFERING)
00095 {
00096 rf->state = RFS_FLUSHING;
00097
00098
00099 dbg_err_if(rf_init_iob(rf));
00100 }
00101
00102 if(rf->iob)
00103 {
00104 dbg_err_if((c = io_read(rf->iob, dst, *dcount)) < 0);
00105 if(c == 0)
00106 {
00107 io_free(rf->iob);
00108 rf->iob = NULL;
00109 } else {
00110 *dcount = c;
00111 return CODEC_FLUSH_CHUNK;
00112 }
00113 }
00114
00115 return CODEC_FLUSH_COMPLETE;
00116 err:
00117 return -1;
00118 }
00119
00120 static ssize_t rf_transform(codec_t *codec,
00121 char *dst, size_t *dcount,
00122 const char *src, size_t src_sz)
00123 {
00124 response_filter_t *rf = (response_filter_t*)codec;
00125 size_t max;
00126 ssize_t c;
00127
00128 dbg_err_if (codec == NULL);
00129 dbg_err_if (dst == NULL);
00130 dbg_err_if (dcount == NULL);
00131 dbg_err_if (src == NULL);
00132
00133 rf->feeded = 1;
00134
00135
00136 if(response_get_method(rf->rs) == HM_HEAD)
00137 {
00138 *dcount = 0;
00139 return src_sz;
00140 }
00141
00142 if(rf->state == RFS_BUFFERING)
00143 {
00144 if(rf->off + src_sz < RFBUFSZ)
00145 {
00146 memcpy(rf->buf + rf->off, src, src_sz);
00147 rf->off += src_sz;
00148 *dcount = 0;
00149 return src_sz;
00150 } else {
00151
00152 rf->state = RFS_FLUSHING;
00153
00154
00155
00156 if(rf->ss && strlen(rf->ss->id) == 0)
00157 dbg_err_if(session_priv_set_id(rf->ss, NULL));
00158
00159
00160 dbg_err_if(rf_init_iob(rf));
00161 }
00162 }
00163
00164 if(rf->iob)
00165 {
00166 dbg_err_if((c = io_read(rf->iob, dst, *dcount)) < 0);
00167 if(c == 0)
00168 {
00169 io_free(rf->iob);
00170 rf->iob = NULL;
00171 } else {
00172 *dcount = c;
00173 return 0;
00174 }
00175 }
00176
00177
00178 max = U_MIN(*dcount, src_sz);
00179 memcpy(dst, src, max);
00180 *dcount = max;
00181 return max;
00182 err:
00183 return -1;
00184 }
00185
00186 static int rf_free(codec_t *codec)
00187 {
00188 response_filter_t *rf;
00189
00190 dbg_return_if (codec == NULL, 0);
00191
00192 rf = (response_filter_t*)codec;
00193
00194 if(rf->iob)
00195 io_free(rf->iob);
00196
00197 U_FREE(rf);
00198
00199 return 0;
00200 }
00201
00202 int response_filter_feeded(codec_t *codec)
00203 {
00204 response_filter_t *rf;
00205
00206 dbg_return_if (codec == NULL, 0);
00207
00208 rf = (response_filter_t*)codec;
00209
00210 return rf->feeded;
00211 }
00212
00213 int response_filter_create(request_t *rq, response_t *rs, session_t *ss,
00214 codec_t **prf)
00215 {
00216 response_filter_t *rf = NULL;
00217
00218 dbg_err_if (rs == NULL);
00219 dbg_err_if (prf == NULL);
00220
00221 rf = u_zalloc(sizeof(response_filter_t));
00222 dbg_err_if(rf == NULL);
00223
00224 rf->rq = rq;
00225 rf->rs = rs;
00226 rf->ss = ss;
00227 rf->codec.transform = rf_transform;
00228 rf->codec.flush = rf_flush;
00229 rf->codec.free = rf_free;
00230 rf->ptr = rf->buf;
00231 rf->iob = NULL;
00232
00233 *prf = (codec_t*)rf;
00234
00235 return 0;
00236 err:
00237 U_FREE(rf);
00238 return ~0;
00239 }