X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fdrivers%2Fnp%2Fcache.c;fp=src%2Fdrivers%2Fnp%2Fcache.c;h=81133d0fa12682791f647827094279307955caec;hb=99340c43f64ab2633f2f0203f4ce6609fdc5ee82;hp=0000000000000000000000000000000000000000;hpb=59090e31c4348a072dde272eeb04de0df66745e6;p=cilux diff --git a/src/drivers/np/cache.c b/src/drivers/np/cache.c new file mode 100644 index 0000000..81133d0 --- /dev/null +++ b/src/drivers/np/cache.c @@ -0,0 +1,182 @@ + +/* -}{----------------------------------------------------------------------- */ + +#include +#include + +/* -}{----------------------------------------------------------------------- */ + +extern void ensure_self_sub(ni_event* evq); + +/* -}{----------------------------------------------------------------------- */ + +#define TMPBUFSIZE 4096 +static char tmpbuf[TMPBUFSIZE]; + +/* -}{----------------------------------------------------------------------- */ + +static void cache_read(char*, char*, char*, int, k_stat, void*); +static void entity_written(char*, char*, char*, int, k_stat, void*); +static void write_headers(char* path, ni_resource* res); +static void headers_written(char*, char*, char*, int, k_stat, void*); + + +/* -}{----------------------------------------------------------------------- */ + +char* make_cache_path(char* uri) +{ + char* path; + size_t l=strlen(uri); + if(l>100){ k_log_out("URI too long to save: %s", uri); return 0; } + if(*(uri+l-1)!='/'){ + path=k_strdup(uri); + } + else{ + path=k_malloc(l+1+10); + sprintf(path, "%sindex.html", uri); + } + return path; +} + +void look_in_file_cache(ni_event* evq) +{ + k_hashtable* sub=evq->ent_head; + char* uri=k_hashtable_get(sub, "Sub-To:"); + size_t l=strlen(uri); + + if(l>100){ ensure_self_sub(evq); return; } + + char hdr[128]; + if(*(uri+l-1)!='/') sprintf(hdr, "%s.hdr", uri); + else sprintf(hdr, "%sindex.html.hdr", uri); + + if(strstr(hdr, "..")){ ensure_self_sub(evq); return; } + if(strchr(hdr, '?' )){ ensure_self_sub(evq); return; } + + char* c=strchr(hdr, ':'); + char* e=strchr(hdr, '/'); + if(c && c< e) *c='-'; + + k_file_read(".", k_strdup(hdr), USE_MALL, 0, cache_read, evq); +} + +void save_in_file_cache(ni_resource* res) +{ + char* uri =res->uri; + char* path =make_cache_path(uri); if(!path) return; + k_hashtable* ent_head=res->ent_head; + void* data =res->entity; + int partial =k_hashtable_is( ent_head, "Status:", "206"); + size_t size =k_hashtable_get_int(ent_head, "Content-Length:"); + char* conrange=k_hashtable_get( ent_head, "Content-Range:"); + int constant=k_hashtable_is( ent_head, "CUX:", "C"); + + if(!data){ + write_headers(path, res); + } + else + if(constant){ + int ok=k_file_sync(data, size); + if(!ok){ + k_log_err("Failed to write (sync mmap): %s", uri); + k_free(path); + return; + } + write_headers(path, res); + } + else{ + if(partial){ + k_log_out("save_in_file_cache partial %s", conrange); + if(!conrange || strncmp(conrange, "0-", 2)){ + k_log_err("not saving partial"); + k_free(path); + return; + } + size=atoi(conrange+2); + } + k_log_out("save_in_file_cache updateable: %d bytes", size); + k_file_write(".", path, data, size, entity_written, res); + } +} + +/* -}{----------------------------------------------------------------------- */ + +void entity_written(char* basedir, + char* path, + char* data, + int usedmmap, + k_stat kstat, + void* context) +{ + if(data) k_log_out("File cache entity written: %s", path); + else{ + k_log_err("Failed to write entity: %s", path); + k_free(path); + return; + } + ni_resource* res=context; + write_headers(path, res); +} + +void write_headers(char* path, ni_resource* res) +{ + snprintf(tmpbuf, TMPBUFSIZE, "%s.hdr", path); + k_free(path); path=k_strdup(tmpbuf); + k_hashtable_snprintf(res->ent_head, tmpbuf, TMPBUFSIZE); + k_file_write(".", path, tmpbuf, strlen(tmpbuf), headers_written, 0); +} + +void headers_written(char* basedir, + char* path, + char* data, + int usedmmap, + k_stat kstat, + void* context) +{ + if(data) k_log_out("File cache headers written: %s", path); + else k_log_err("Failed to write headers: %s", path); + k_free(path); +} + +void cache_read(char* basedir, + char* path, + char* data, + int usedmmap, + k_stat kstat, + void* context) +{ + if(!data) k_log_out("no cache of %s", path); + else k_log_out("file cache read: %d %s", kstat.size, path); + char* e=strstr(path, ".hdr"); + if(e){ + ni_event* evq=context; + if(!data){ k_free(path); ensure_self_sub(evq); return; } + + char* header=data; + *(header+kstat.size-2)=0; + k_hashtable* ent_head=k_hashtable_new("nHeaders/cache_read", 1); + k_hashtable_put(ent_head, "", header); + if(!ni_get_headers(header, 0, ent_head)){ + k_hashtable_delete(ent_head); + k_free(path); + ensure_self_sub(evq); + return; + } + ni_event_delete(evq); + *e=0; + ni_event* evt=ni_event_new(0, 0, ent_head, 0); + int constant=k_hashtable_is(ent_head, "CUX:", "C"); + size_t m=constant? USE_MMAP: USE_MALL; + k_file_read(".", path, m, 0, cache_read, evt); + return; + } + ni_event* evt=context; + k_free(path); + evt->entity=data; + ni_event_show(evt, "File Cache Found:"); + k_event_post("ni", evt); +} + +/* -}{----------------------------------------------------------------------- */ + +