From 633d206d652087e0b170535a6e7fd0b33c8dc816 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 19 Mar 2009 21:17:39 +0000 Subject: [PATCH] Big renaming --- makefile | 46 +-- src/drivers/np/cache.c | 182 ---------- src/drivers/np/np.c | 562 ---------------------------- src/drivers/np/uri2chan.c | 294 --------------- src/drivers/nt/mid/mid.c | 408 --------------------- src/drivers/nt/test/testni.c | 149 -------- src/drivers/op/cache.c | 182 ++++++++++ src/drivers/op/protocol.c | 562 ++++++++++++++++++++++++++++ src/drivers/op/uri2chan.c | 294 +++++++++++++++ src/drivers/ot/mid/mid.c | 408 +++++++++++++++++++++ src/drivers/ot/test/teston.c | 149 ++++++++ src/include/ni.h | 93 ----- src/include/notification.h | 93 +++++ src/ni/headers.c | 523 --------------------------- src/ni/ni.c | 824 ------------------------------------------ src/on/headers.c | 523 +++++++++++++++++++++++++++ src/on/notification.c | 824 ++++++++++++++++++++++++++++++++++++++++++ src/platform/kernelapi.c | 6 +- 18 files changed, 3061 insertions(+), 3061 deletions(-) delete mode 100644 src/drivers/np/cache.c delete mode 100644 src/drivers/np/np.c delete mode 100644 src/drivers/np/uri2chan.c delete mode 100644 src/drivers/nt/mid/mid.c delete mode 100644 src/drivers/nt/test/testni.c create mode 100644 src/drivers/op/cache.c create mode 100644 src/drivers/op/protocol.c create mode 100644 src/drivers/op/uri2chan.c create mode 100644 src/drivers/ot/mid/mid.c create mode 100644 src/drivers/ot/test/teston.c delete mode 100644 src/include/ni.h create mode 100644 src/include/notification.h delete mode 100644 src/ni/headers.c delete mode 100644 src/ni/ni.c create mode 100644 src/on/headers.c create mode 100644 src/on/notification.c diff --git a/makefile b/makefile index b972b60..271ab7f 100644 --- a/makefile +++ b/makefile @@ -19,7 +19,7 @@ linux: INCLUDES=-I/usr/local/include -I. -I../include -I../../include -I../../.. linux: LIBRARIES=-L/usr/local/lib -lnsl -ldl -lm -lX11 -lEGL -lGLESv2 linux: linux-all -linux-all: cilux mod-ni.so mod-np.so mod-mid.so mod-testni.so install-lin +linux-all: cilux mod-on.so mod-op.so mod-mid.so mod-teston.so install-lin # ---------------------------------------------------------------------------- # @@ -31,7 +31,7 @@ version-lin: @echo -n " Linux (Built " >> src/platform/linux/version.h @date | tr '\012' ')' >> src/platform/linux/version.h @echo "\";" >> src/platform/linux/version.h - @echo "static char* cilux_ciux=\"np\";" >> src/platform/linux/version.h + @echo "static char* cilux_ciux=\"op\";" >> src/platform/linux/version.h cilux: version-lin src/platform/linux/cilux.c src/platform/linux/kernelplat.h src/platform/linux/kernelplat.c src/platform/kernelapi.c src/include/kernelapi.h src/platform/linux/platform.h (cd src/platform/linux; $(CC) $(CCOPTIONS) -c cilux.c -o cilux.o $(COMPILEOPTIONS) $(INCLUDES)) @@ -40,40 +40,40 @@ cilux: version-lin src/platform/linux/cilux.c src/platform/linux/kernelplat.h sr $(STRIP) cilux @echo '--------------------' -mod-ni.so: src/ni/ni.c src/ni/headers.c src/include/ni.h src/include/kernelapi.h src/platform/linux/platform.h - (cd src/ni; $(CC) $(CCOPTIONS) -c headers.c -o headers.o $(COMPILEOPTIONS) $(INCLUDES)) - (cd src/ni; $(CC) $(CCOPTIONS) -c ni.c -o ni.o $(COMPILEOPTIONS) $(INCLUDES)) - $(CCLIB),mod-ni.so -o mod-ni.so src/ni/headers.o src/ni/ni.o - $(STRIP) mod-ni.so +mod-on.so: src/on/notification.c src/on/headers.c src/include/notification.h src/include/kernelapi.h src/platform/linux/platform.h + (cd src/on; $(CC) $(CCOPTIONS) -c headers.c -o headers.o $(COMPILEOPTIONS) $(INCLUDES)) + (cd src/on; $(CC) $(CCOPTIONS) -c notification.c -o notification.o $(COMPILEOPTIONS) $(INCLUDES)) + $(CCLIB),mod-on.so -o mod-on.so src/on/headers.o src/on/notification.o + $(STRIP) mod-on.so @echo '--------------------' -mod-np.so: src/drivers/np/np.c src/drivers/np/uri2chan.c src/include/kernelapi.h src/platform/linux/platform.h - (cd src/drivers/np; $(CC) $(CCOPTIONS) -c np.c -o np.o $(COMPILEOPTIONS) $(INCLUDES)) - (cd src/drivers/np; $(CC) $(CCOPTIONS) -c uri2chan.c -o uri2chan.o $(COMPILEOPTIONS) $(INCLUDES)) - (cd src/drivers/np; $(CC) $(CCOPTIONS) -c cache.c -o cache.o $(COMPILEOPTIONS) $(INCLUDES)) - $(CCLIB),mod-np.so -o mod-np.so src/drivers/np/np.o src/drivers/np/uri2chan.o src/drivers/np/cache.o - $(STRIP) mod-np.so +mod-op.so: src/drivers/op/protocol.c src/drivers/op/uri2chan.c src/include/kernelapi.h src/platform/linux/platform.h + (cd src/drivers/op; $(CC) $(CCOPTIONS) -c protocol.c -o protocol.o $(COMPILEOPTIONS) $(INCLUDES)) + (cd src/drivers/op; $(CC) $(CCOPTIONS) -c uri2chan.c -o uri2chan.o $(COMPILEOPTIONS) $(INCLUDES)) + (cd src/drivers/op; $(CC) $(CCOPTIONS) -c cache.c -o cache.o $(COMPILEOPTIONS) $(INCLUDES)) + $(CCLIB),mod-op.so -o mod-op.so src/drivers/op/protocol.o src/drivers/op/uri2chan.o src/drivers/op/cache.o + $(STRIP) mod-op.so @echo '--------------------' -mod-mid.so: src/drivers/nt/mid/mid.c src/include/kernelapi.h src/platform/linux/platform.h - (cd src/drivers/nt/mid; $(CC) $(CCOPTIONS) -c mid.c -o mid.o $(COMPILEOPTIONS) $(INCLUDES)) - $(CCLIB),mod-mid.so -o mod-mid.so src/drivers/nt/mid/mid.o +mod-mid.so: src/drivers/ot/mid/mid.c src/include/kernelapi.h src/platform/linux/platform.h + (cd src/drivers/ot/mid; $(CC) $(CCOPTIONS) -c mid.c -o mid.o $(COMPILEOPTIONS) $(INCLUDES)) + $(CCLIB),mod-mid.so -o mod-mid.so src/drivers/ot/mid/mid.o $(STRIP) mod-mid.so @echo '--------------------' -mod-testni.so: src/drivers/nt/test/testni.c src/include/kernelapi.h src/platform/linux/platform.h - (cd src/drivers/nt/test; $(CC) $(CCOPTIONS) -c testni.c -o testni.o $(COMPILEOPTIONS) $(INCLUDES)) - $(CCLIB),mod-testni.so -o mod-testni.so src/drivers/nt/test/testni.o - $(STRIP) mod-testni.so +mod-teston.so: src/drivers/ot/test/teston.c src/include/kernelapi.h src/platform/linux/platform.h + (cd src/drivers/ot/test; $(CC) $(CCOPTIONS) -c teston.c -o teston.o $(COMPILEOPTIONS) $(INCLUDES)) + $(CCLIB),mod-teston.so -o mod-teston.so src/drivers/ot/test/teston.o + $(STRIP) mod-teston.so @echo '--------------------' install-lin: mv cilux /usr/local/bin - mv mod-ni.so mod-np.so /usr/local/lib + mv mod-on.so mod-op.so /usr/local/lib mkdir -p modules/mid mv mod-mid.so modules/mid - mkdir -p modules/testni - mv mod-testni.so modules/testni + mkdir -p modules/teston + mv mod-teston.so modules/teston @echo '--------------------' # ---------------------------------------------------------------------------- # diff --git a/src/drivers/np/cache.c b/src/drivers/np/cache.c deleted file mode 100644 index 81133d0..0000000 --- a/src/drivers/np/cache.c +++ /dev/null @@ -1,182 +0,0 @@ - -/* -}{----------------------------------------------------------------------- */ - -#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); -} - -/* -}{----------------------------------------------------------------------- */ - - diff --git a/src/drivers/np/np.c b/src/drivers/np/np.c deleted file mode 100644 index b33dc10..0000000 --- a/src/drivers/np/np.c +++ /dev/null @@ -1,562 +0,0 @@ - -/* -}{----------------------------------------------------------------------- */ - -#include -#include - -/* -}{----------------------------------------------------------------------- */ - -#define TMPBUFSIZE 4096 -static char tmpbuf[TMPBUFSIZE]; -static k_hashtable* own_resources; - -/* -}{----------------------------------------------------------------------- */ - -extern void run_tests(void); - -extern char* make_cache_path(char* uri); -extern void look_in_file_cache(ni_event* evq); -extern void save_in_file_cache(ni_resource* res); - -extern void init_uri2chan(void); -extern char* get_host_for(char* uri); -extern char* get_channel_for(char* host); -extern char* use_ping_info(k_hashtable*, k_channel*); -extern void use_from_info(k_hashtable*, k_channel*); -extern void ping_tunnels(void); -extern void send_ping(k_channel* chan, char* firstline, char* to); - -/* -}{----------------------------------------------------------------------- */ - -static int handles_resource(char* name); -static void sync_resource(ni_resource* res); - int connection_writable(k_channel* chan, int bufpos, int len); - int connection_readable(k_channel* chan, int bufpos, int len); -static int recv_next_event( k_channel* chan); -static void recv_request( k_channel* chan, char* header); -static void recv_response( k_channel* chan, char* header); -static void got_mmap(char*, char*, char*, int, k_stat, void*); -static void set_read_buffer(k_channel*, char*, size_t, ni_event*); -static int recv_entity( k_channel* chan, int bufpos, int eof); -static int expecting_response(char* pub, ni_event* evt, k_channel*); -static void do_request( ni_event* evq); - void ensure_self_sub(ni_event* evq); -static void ping_resource_subs(void* arg, char* key, void* val); -static void ping_sub(ni_resource* res, k_hashtable* sub); -static ni_resource* own_resource(char* uri); -static void send_request(ni_event* evq); -static void send_response(ni_event* evt); -static k_channel* ensure_chan(char* chanm); - -/* -}{----------------------------------------------------------------------- */ - -EXPORT int np_module_loaded(void) -{ - ni_register_driver("np", handles_resource, sync_resource); - - if(strstr(k_version, "test")){ - //run_tests(); - } - - init_uri2chan(); - - own_resources=k_hashtable_new("Own Resources", 0); - - k_log_out("NP Driver initialised"); - - return 0; -} - -EXPORT void np_module_tick(void) -{ - static long tix; - tix++; - if(!(tix % 1000)){ - k_hashtable_apply(own_resources, ping_resource_subs, 0); - } - if(!(tix % 3000)){ - ping_tunnels(); - } -} - -EXPORT int np_module_event(void* data) -{ - ni_event* evt=data; - if(!k_hashtable_get(evt->ent_head, "Status:")){ - do_request(evt); - } - else{ - send_response(evt); - } - return 0; -} - -/* -}{----------------------------------------------------------------------- */ - -int handles_resource(char* name) -{ - return 0; -} - -void sync_resource(ni_resource* res) -{ - save_in_file_cache(res); -} - -/* -}{----------------------------------------------------------------------- */ - -int connection_readable(k_channel* chan, int bufpos, int len) -{ - if(0) k_log_out("connection_readable %s %p %d %d %p", - chan->name, chan, bufpos, len, chan->context); - int sof=(len== 0); - int eof=(len== -1); - - if(sof) return 0; - - do{ - ni_event* evt=chan->context; - if(!evt){ - int n=recv_next_event(chan); - if(n<0) break; - bufpos-=n; - } - else{ - int n=recv_entity(chan, bufpos, eof); - if(n<0) break; - bufpos-=n; - } - - } while(1); - - if(eof && chan->context){ - ni_event* evt=chan->context; - evt->entity=0; - ni_event_delete(evt); - chan->context=0; - } - - return 0; -} - -int connection_writable(k_channel* chan, int bufpos, int len) -{ - if(0) k_log_out("connection_writable %p %d %d %p", - chan, bufpos, len, chan->context); -//if(len>20000) exit(1); - int sof=(len== 0); - int eof=(len== -1); - - if(sof){ - send_ping(chan, "PING ni/0.5", 0); - return 0; - } - - if(eof && chan->context){ - ni_event* evt=chan->context; - evt->entity=0; - ni_event_delete(evt); - chan->context=0; - } - - return 0; -} - -/* -}{---- Receiving -------------------------------------------------------- */ - -int recv_next_event(k_channel* chan) -{ - char* header=k_channel_chop_div(chan, CRLF CRLF); - if(!header) return -1; - int n=strlen(header)+strlen(CRLF CRLF); - - if(!strncmp(header, "GET", 3) || - !strncmp(header, "SUB", 3) || - !strncmp(header, "UNSUB",5) || - !strncmp(header, "HEAD", 4) || - !strncmp(header, "PING", 4) ){ - - recv_request(chan, header); - return n; - } - if(!strncmp(header, "ni/", 4) ){ - - recv_response(chan, header); - return n; - } - k_free(header); - k_log_err("Failed reading request or response - closing connection"); - k_channel_close(chan); - return n; -} - -void recv_request(k_channel* chan, char* header) -{ - ni_event* evq; - evq=ni_get_request_headers(header); - if(!evq){ - k_log_err("Failed reading request headers - closing connection"); - k_channel_close(chan); - return; - } - if(!k_hashtable_isn(evq->evt_head, "Protocol:", "ni/", 4)){ - ni_event_delete(evq); - k_log_err("Failed reading request not ni - closing connection"); - k_channel_close(chan); - return; - } - - k_hashtable* ent_head=evq->ent_head; - int ping=k_hashtable_is(ent_head, "Method:", "PING"); - - if(!evq->uri && !ping){ - evq->uri=k_strdup(chan->name); - k_hashtable_put_dup(ent_head, "URI:", chan->name); - } - - ni_event_show(evq, "ni Protocol Request"); - - if(k_hashtable_isi(evq->evt_head, "Connection:", "Keep-Alive")){ - chan->linger=1; - if(k_hashtable_isn(ent_head, "Sub-To:", "./test", 6)){ - chan->linger=0; - } - } - if(ping){ - char* from=use_ping_info(ent_head, chan); - if(from) send_ping(chan, "ni/0.5 270 PING", from); - ni_event_delete(evq); - return; - } - //use_from_info(ent_head, chan); - - ni_event* evp=ni_event_new(evq->uri, 0, k_hashtable_dup(ent_head), 0); - - ni_event_delete(evq); - - k_event_post("ni", evp); -} - -void recv_response(k_channel* chan, char* header) -{ - ni_event* evt=ni_get_response_headers(header); - if(!evt){ - k_log_err("recv_response: headers failed but doing nothing!"); - return; - } - char* pub= evt->uri; - k_hashtable* ent_head=evt->ent_head; - - if(!expecting_response(pub, evt, chan)) return; - - ni_event_show(evt, "Response"); - - int head=k_hashtable_is( ent_head, "Status:", "260"); - int nmod=k_hashtable_is( ent_head, "Status:", "304"); - int ping=k_hashtable_is( ent_head, "Status:", "270"); - int cl =k_hashtable_get_int(ent_head, "Content-Length:"); - int entity=!(head || nmod || ping || cl==0); - - if(ping){ - use_ping_info(ent_head, chan); - ni_event_delete(evt); - return; - } - use_from_info(ent_head, chan); - - if(entity){ - k_hashtable_set(ent_head, "Status:", "260"); - k_hashtable_set(ent_head, "Status-Text:", "Headers Only"); - } - k_event_post("ni", evt); - - if(entity){ - - k_hashtable* eh=k_hashtable_new("nHeaders/recv_response", 1); - char* from =k_hashtable_get(ent_head, "From:"); - char* contlen =k_hashtable_get(ent_head, "Content-Length:"); - char* cux =k_hashtable_get(ent_head, "CUX:"); - k_hashtable_set(eh, "Status:", "206"); - k_hashtable_set(eh, "Status-Text:", "Partial Content"); - k_hashtable_put_dup(eh, "From:", from); - k_hashtable_put_dup(eh, "Content-Length:", contlen); - k_hashtable_put_dup(eh, "CUX:", cux); - ni_event* evc=ni_event_new(pub, 0, eh, 0); - chan->context=evc; - - int constant=k_hashtable_is(ent_head, "CUX:", "C"); - if(constant){ - char* path=make_cache_path(pub); if(!path) return; - k_file_read(".", path, USE_MMAP, cl, got_mmap, chan); - } - else{ - char* data=k_malloc(cl); - set_read_buffer(chan, data, cl, evc); - } - } -} - -void got_mmap(char* basedir, - char* path, - char* data, - int usedmmap, - k_stat kstat, - void* context){ - - k_free(path); - k_channel* chan=context; - ni_event* evt=chan->context; - if(!evt){ k_log_err("got_mmap: evt=0"); return; } - if(!data || !usedmmap){ k_log_err("got_mmap: mmap failed"); return; } - - size_t cl=k_hashtable_get_int(evt->ent_head, "Content-Length:"); - set_read_buffer(chan, data, cl, evt); -} - -void set_read_buffer(k_channel* chan, char* data, size_t cl, ni_event* evt) -{ - evt->entity=data; - int r=k_channel_setbuf(chan, data, cl); - if(0) k_log_out("k_channel_setbuf %d", r); - if(r==BUFFER_ALREADY_SET){ - k_log_err("oops! k_channel_setbuf BUFFER_ALREADY_SET"); - return; - } - if(r==BUFFER_FILLED){ - k_hashtable_set(evt->ent_head, "Status:", "200"); - k_hashtable_set(evt->ent_head, "Status-Text:", "OK"); - chan->context=0; - k_event_post("ni", evt); - } -} - -int recv_entity(k_channel* chan, int bufpos, int eof) -{ - ni_event* evt=chan->context; - k_hashtable* ent_head=evt->ent_head; - - char* cls=k_hashtable_get( ent_head, "Content-Length:"); - int cl =k_hashtable_get_int(ent_head, "Content-Length:"); - - if(!cls && !eof) return -1; - - int partial=0; - int eofcontlen=eof && (!cls || bufpos < cl); - if(eofcontlen){ - if(cls){ - char* clg=k_strdup(cls); - k_hashtable_put(ent_head, "Content-Length-Given:", clg); - partial=1; - } - cl=bufpos; - char b[32]; snprintf(b, 32, "%d", cl); - k_hashtable_put_dup(ent_head, "Content-Length:", b); - } - - if(bufpos < cl){ - if(bufpos){ - ni_event* evp=ni_event_dup(evt); - snprintf(tmpbuf, TMPBUFSIZE, "0-%d", bufpos); - char* cr=k_strdup(tmpbuf); - k_hashtable_put(evp->ent_head, "Content-Range:", cr); - k_event_post("ni", evp); - } - return -1; - } - - static char dummy_empty_entity[0]; - if(!k_channel_getbuf(chan)){ - int cn=k_hashtable_is(ent_head, "CUX:", "C"); - if(cl) evt->entity=k_channel_chop_len(chan, cl); - else evt->entity=cn? dummy_empty_entity: k_malloc(1); - } - - if(!partial){ - k_hashtable_set(ent_head, "Status:", "200"); - k_hashtable_set(ent_head, "Status-Text:", "OK"); - } - chan->context=0; - k_event_post("ni", evt); - - return cl; -} - -int expecting_response(char* pub, ni_event* evt, k_channel* chan) -{ - if(pub && 0){ - k_log_err("unwanted response: %s", pub); - ni_event_delete(evt); - k_channel_close(chan); - return 0; - } - return 1; -} - -/* -}{---- Sending ---------------------------------------------------------- */ - -void do_request(ni_event* evq) -{ - k_hashtable* sub=evq->ent_head; - int tc=k_hashtable_isi(sub, "Sub-Type:", "Cache"); - int to=k_hashtable_isi(sub, "Sub-Type:", "Original"); - - if(tc){ - char* ims=k_hashtable_get(sub, "If-Modified-Since:"); - if(ims) ensure_self_sub(evq); - else look_in_file_cache(evq); - } - else - if(to){ - send_request(evq); - } -} - -void ensure_self_sub(ni_event* evq) -{ - k_hashtable* sub=evq->ent_head; - char* pub=k_hashtable_get(sub, "Sub-To:"); - - ni_resource* res=own_resource(pub); - k_hashtable* enh=res->ent_head; - k_hashtable* selfsub=k_hashtable_get(enh, "Sub-To:"); - if(selfsub && !k_hashtable_is(selfsub, "Status-Cache:", "OK")){ - k_log_err("cancel selfsub as new one needed"); - } - - k_hashtable* ss=k_hashtable_dup(sub); - k_hashtable_remove( ss, "From:"); - k_hashtable_put_dup(ss, "URI:", pub); - k_hashtable_set( ss, "Sub-Type:", "Original"); - k_hashtable_put_dup(ss, "Via:", get_host_for(pub)); - if(k_hashtable_get( ss, "If-Modified-Since:")){ - char* lm=k_hashtable_get(enh, "Last-Modified:"); - if(!res->entity) lm=0; - k_hashtable_set(ss, "If-Modified-Since:", lm? lm: "0"); - } - ni_event* evs=ni_event_new(0, 0, ss, 0); - k_event_post("ni", evs); - - ni_event_delete(evq); -} - -void ping_resource_subs(void* arg, char* key, void* val) -{ - ni_resource* res=val; - k_hashtable* pubcache=k_hashtable_get(res->ent_head, "Pub-Cache:"); - if(!pubcache || !k_hashtable_get(pubcache, "Method:")) return; - k_hashtable* subs=k_hashtable_get(res->ent_head, "Sub-To:"); - k_hashtable* sub; - for(sub=subs; sub; sub=sub->next){ - if(!k_hashtable_is(sub, "Status-Cache:", "OK")){ - if(!k_hashtable_get(sub, "Status:")){ - ping_sub(res, sub); - } - else{ - int ts=k_hashtable_get_int(sub, "Timestamp:"); - if(0) k_log_out("check dried-up request: %d", ts); - } - } - } -} - -void ping_sub(ni_resource* res, k_hashtable* sub) -{ - ni_resource_show(res, "ping_resource_subs"); - - k_hashtable* ss=k_hashtable_dup(sub); - - char* subto=k_hashtable_extract(ss, "URI:"); - k_hashtable_put_dup(ss, "URI:", res->uri); - k_hashtable_put( ss, "Sub-To:", subto); - k_hashtable_set( ss, "Sub-Type:", "Original"); - k_hashtable_put_dup(ss, "Via:", get_host_for(res->uri)); - - ni_event* evs=ni_event_new(0, 0, ss, 0); - k_event_post("ni", evs); -} - -ni_resource* own_resource(char* uri) -{ - ni_resource* res=k_hashtable_get(own_resources, uri); - if(!res){ - res=ni_resource_get(uri); - k_hashtable_set(own_resources, uri, res); - } - return res; -} - -void send_request(ni_event* evt) -{ - k_hashtable* eh=evt->ent_head; - char* method=k_strdup(k_hashtable_get(eh, "Method:")); - char* to =k_strdup(k_hashtable_get(eh, "Sub-To:")); - char* via =k_strdup(k_hashtable_get(eh, "Via:")); - - char* chanm=get_channel_for(via); - if(!chanm) goto free_and_return; - - k_channel* chan=ensure_chan(chanm); - if(!chan) goto free_and_return; - - ni_fix_ni_headers(eh, 0); - ni_request(evt, to, method, chan); - - free_and_return: - k_free(method); k_free(to); k_free(via); - ni_event_delete(evt); -} - -void send_response(ni_event* evt) -{ - ni_event_show(evt, "send_response"); - - k_hashtable* eh=evt->ent_head; - - k_hashtable* sub=k_hashtable_get(eh, "Pub-To:"); - char* uri =k_hashtable_get(sub, "URI:"); - char* from =k_hashtable_get(sub, "From:"); - char* method =k_hashtable_get(sub, "Method:"); - int methead =k_hashtable_is( sub, "Method:", "HEAD"); - - char* to=from? from: uri; - - char* host=from? from: get_host_for(uri); - char* chanm=get_channel_for(host); - if(!chanm){ - if(0) k_log_out("no ni protocol channel %s", to); - ni_event_delete(evt); - return; - } - - k_channel* chan=ensure_chan(chanm); - if(!chan){ - if(0) k_log_out("no ni protocol channel %s", to); - ni_event_delete(evt); - return; - } - - k_hashtable_extract(eh, "Pub-To:"); - - char* protocol="ni/0.5"; - - ni_fix_ni_headers(eh, methead); - ni_response(evt, to, method, protocol, 0, chan); - - k_hashtable_delete(sub); - evt->entity=0; - ni_event_delete(evt); -} - -k_channel* ensure_chan(char* chanm) -{ - k_channel* chan=k_channel_get_name(chanm); - if(!chan){ - k_log_err("Cannot find current channel for %s", chanm); - k_channel_connect_name(chanm, connection_readable, - connection_writable); - } - return chan; -} - -/* -}{----------------------------------------------------------------------- */ - diff --git a/src/drivers/np/uri2chan.c b/src/drivers/np/uri2chan.c deleted file mode 100644 index 26b05f2..0000000 --- a/src/drivers/np/uri2chan.c +++ /dev/null @@ -1,294 +0,0 @@ - -/* -}{----------------------------------------------------------------------- */ - -#include -#include - -/* -}{----------------------------------------------------------------------- */ - -extern int connection_writable(k_channel* chan, int bufpos, int len); -extern int connection_readable(k_channel* chan, int bufpos, int len); - -/* -}{----------------------------------------------------------------------- */ - -#define TMPBUFSIZE 4096 -static char tmpbuf[TMPBUFSIZE]; -static int is_np; -static char* nexus_channel; -static k_hashtable* chans_for_host; - -/* -}{----------------------------------------------------------------------- */ - -static void nexus_file_read(char*, char*, char*, int, k_stat, void*); -static void write_nexus(char* hostname); -static void nexus_file_written(char*, char*, char*, int, k_stat, void*); -static int root_nexus(void); -static void listen_http(void); -static void listen_nexus(void); -static void connect_to_nexus(void); -static void ping_this(void* arg, char* key, void* val); -static char* generate_new_hostname(k_hashtable* ent_head, k_channel* chan); -static void set_channel_for(char* host, char* chanm); -static void show_np(void); -static void show_list(void* arg, char* key, void* val); - -/* -}{----------------------------------------------------------------------- */ - -void init_uri2chan(void) -{ - chans_for_host =k_hashtable_new("Channels for Host", 0); - - k_file_read(".", "nexus.txt", USE_MALL, 0, nexus_file_read, 0); - - is_np=!strcmp(k_ciux, "np"); - if(is_np) listen_nexus(); - if(root_nexus()){ - k_log_out("root nexus - but listening on http"); - listen_http(); - } - else{ - k_log_out("connecting to nexus %s", nexus_channel); - connect_to_nexus(); - } -} - -char* get_host_for(char* uri) -{ - if(0) k_log_out("get_host_for %s", uri); - char* host=0; - if(0) k_log_out("host for %s=%s", uri, host); - return host; -} - -char* get_channel_for(char* host) -{ - if(0) k_log_out("get_channel_for %s", host); - char* chanm=k_hashtable_get(chans_for_host, host); - if(!chanm){ - } - if(0) k_log_out("channel for %s=%s", host, chanm); - return chanm; -} - -char* use_ping_info(k_hashtable* ent_head, k_channel* chan) -{ - char* from=k_hashtable_get(ent_head, "From:"); - char* to =k_hashtable_get(ent_head, "To:"); - - if(!from) return 0; - if(!strcmp(from, "-")) from=generate_new_hostname(ent_head, chan); - if(!from) return 0; - if(!ni_hostname() && to) write_nexus(to); - - set_channel_for(from, chan->name); - - if(0) k_log_out("%s PING %s", chan->name, from); - if(0) show_np(); - - return from; -} - -void use_from_info(k_hashtable* ent_head, k_channel* chan) -{ - char* from=k_hashtable_get(ent_head, "From:"); - - if(!from) return; - - set_channel_for(from, chan->name); - - if(0) show_np(); -} - -void ping_tunnels(void) -{ - k_hashtable* channelspinged=k_hashtable_new("channelspinged", 0); - k_hashtable_apply(chans_for_host, ping_this, channelspinged); - k_hashtable_delete(channelspinged); -} - -void send_ping(k_channel* chan, char* firstline, char* to) -{ - char* from=ni_hostname(); - if(!from) from="-"; - - int ln=0; - int bufsize=TMPBUFSIZE; - - ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s" CRLF, firstline); - if(ln>=bufsize) return; - ln+=snprintf(tmpbuf+ln, bufsize-ln, "From: %s" CRLF, from); - if(ln>=bufsize) return; - if(to){ - ln+=snprintf(tmpbuf+ln, bufsize-ln, "To: %s" CRLF, to); - if(ln>=bufsize) return; - } - ln+=snprintf(tmpbuf+ln, bufsize-ln, "Server: %s" CRLF, k_version); - if(ln>=bufsize) return; - ln+=snprintf(tmpbuf+ln, bufsize-ln, "Channels: %s" CRLF, "-"); - if(ln>=bufsize) return; - ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF); - if(ln>=bufsize) return; - - char* head=k_strdup(tmpbuf); - k_channel_send(chan, head, ln, FREE_ON_SENT); -} - -/* -}{----------------------------------------------------------------------- */ - -void nexus_file_read(char* basedir, - char* filepath, - char* data, - int usedmmap, - k_stat kstat, - void* context) -{ - int L=0; - if(data) data[kstat.size-1]=0; - else data=k_strdup(""); - k_hashtable* nex=k_hashtable_new("nexus", 1); - if(!ni_get_headers(data, nex, 0)){ - k_log_err("Corrupt nexus.txt file"); - k_hashtable_delete(nex); - k_free(data); - data=k_strdup(""); - nex=k_hashtable_new("nexus", 1); - ni_get_headers(data, nex, 0); - } - - char* hostname; - nexus_channel=k_hashtable_get_dup(nex, "Nexus-Channel:"); - hostname =k_hashtable_get( nex, "Hostname:"); - - if(hostname) ni_hostname_set(hostname); - - if(L) if(nexus_channel) k_log_out("Nexus-Channel: %s", nexus_channel); - if(L) if(hostname) k_log_out("Hostname: %s", hostname); - - k_hashtable_delete(nex); - k_free(data); -} - -void write_nexus(char* hostname) -{ - ni_hostname_set(hostname); - - snprintf(tmpbuf, TMPBUFSIZE, "Nexus-Channel: %s\r\n" - "Hostname: %s\r\n", nexus_channel, - hostname); - - k_file_write(".", "nexus.txt", tmpbuf, strlen(tmpbuf), - nexus_file_written, 0); -} - -void nexus_file_written(char* basedir, - char* filepath, - char* data, - int usedmmap, - k_stat kstat, - void* context) -{ - if(!data) k_fatal("Failed to write nexus.txt"); - else k_log_out("New nexus.txt written:\n%s", data); -} - -int root_nexus(void) -{ - char* hostname=ni_hostname(); - if(!hostname || strchr(hostname, '-')) return 0; - return 1; -} - -void listen_http(void) -{ - char* chanm="|nip-server|-|8081|-|"; - k_channel_connect_name(chanm, connection_readable, - connection_writable); -} - -void listen_nexus(void) -{ - char* chanm="|nip-server|-|7747|-|"; - k_channel_connect_name(chanm, connection_readable, - connection_writable); -} - -void connect_to_nexus(void) -{ - if(nexus_channel){ - k_channel_connect_name(nexus_channel, connection_readable, - connection_writable); - } - else k_log_out("discovery of nexus not implemented yet!"); -} - -void ping_this(void* arg, char* key, void* val) -{ - k_hashtable* channelspinged=arg; - char* chanm=val; - - if(strncmp(chanm, "nip-client", 11) ) return; - if(k_hashtable_get(channelspinged, chanm)) return; - k_hashtable_set(channelspinged, chanm, chanm); - - k_channel* chan=k_channel_get_name(chanm); - //k_log_out("ping_this: host %s channel %s got=%p", key, chanm, chan); - - if(!chan) k_channel_connect_name(chanm, connection_readable, - connection_writable); - - int pingtodeath=0; - if(chan && pingtodeath) send_ping(chan, "PING ni/0.5", 0); -} - -char* generate_new_hostname(k_hashtable* ent_head, k_channel* chan) -{ - if(!ni_hostname()) return 0; - unsigned long a=chan->clientip.s_addr; - #define IPQUAD(a) \ - ((unsigned char *)&a)[0], \ - ((unsigned char *)&a)[1], \ - ((unsigned char *)&a)[2], \ - ((unsigned char *)&a)[3] - snprintf(tmpbuf, TMPBUFSIZE, "%s-%02x%02x%02x%02x.%d", - ni_hostname(), IPQUAD(a), 7747); - if(0) k_log_out("generated new hostname: %s\n", tmpbuf); - return k_strdup(tmpbuf); -} - -/* -}{----------------------------------------------------------------------- */ - -void set_channel_for(char* host, char* chanm) -{ - k_hashtable_put_dup(chans_for_host, host, chanm); -} - -void show_np(void) -{ - k_log_out("-------- channel for host ---------------"); - k_hashtable_apply(chans_for_host, show_list, 0); - k_channel_show_all(); -} - -void show_list(void* arg, char* key, void* val) -{ - char* chanm=val; - k_log_out("%s %s", key, chanm); -} - -void generate_random(void) -{ - time_t t=time(0); - short r; - k_random_bytes((char*)&r, sizeof(r)); - unsigned char r1=(t >>24) & 255; - unsigned char r2=(t >>16) & 255; - unsigned char r3=(t >> 8) & 255; - unsigned char r4=(t ) & 255; - unsigned char r5=(r >> 8) & 255; - unsigned char r6=(r ) & 255; - snprintf(tmpbuf, TMPBUFSIZE, "%02x-%02x-%02x-%02x-%02x-%02x", - r1, r2, r3, r4, r5, r6); -} - -/* -}{----------------------------------------------------------------------- */ - diff --git a/src/drivers/nt/mid/mid.c b/src/drivers/nt/mid/mid.c deleted file mode 100644 index a684d80..0000000 --- a/src/drivers/nt/mid/mid.c +++ /dev/null @@ -1,408 +0,0 @@ - -/* -------------------------------------------------------------------------- */ - -#include -#include - -/* -------------------------------------------------------------------------- */ - -#define WINDOW_WIDTH 640 -#define WINDOW_HEIGHT 480 - -#define POS_ARRAY 0 -#define NORMAL_ARRAY 1 -#define TEXCOORD_ARRAY 2 - -#define TEX_SIZE 128 - -/* -------------------------------------------------------------------------- */ - -static GLfloat xco= 0; -static GLfloat yco= 1; -static GLfloat zco= -35; -static GLfloat view_rotx=0.0, view_roty=0.0, view_rotz=0.0; -static int shift=0; - -GLuint program; -GLuint texture; -GLuint vbo; -unsigned int numberOfVertices; -unsigned int posStep; -unsigned int normStep; -unsigned int tcStep; -unsigned int stride; -float angle=0.0; -float viewAngle = 0.0; - -/* -------------------------------------------------------------------------- */ - -static int handles_resource(char* name); -static void sync_resource(ni_resource* res); -static void init_gl(void); -static void reshape(int width, int height); -static void draw(void); -static void key(unsigned char k, int down); - -static int useTheProgram(); -static int setUpTnL(); -static int drawStuff(int width, int height); - -/* -------------------------------------------------------------------------- */ - -EXPORT int mid_module_loaded(void) -{ - ni_register_driver("mid", handles_resource, sync_resource); - - init_gl(); - - k_gl_register_reshape(reshape); - k_gl_register_draw(draw); - k_gl_register_key(key); - - k_log_out("MID Driver initialised"); - - return 1; -} - -EXPORT int mid_module_event(void* data) -{ - k_log_out("MID got event: %p", data); - ni_event* evt=data; - ni_event_delete(evt); - return 1; -} - -EXPORT int mid_module_tick(void) -{ - if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end(); - return 1; -} - -/* -------------------------------------------------------------------------- */ - -int handles_resource(char* name) -{ - return 0; -} - -void sync_resource(ni_resource* res) -{ -} - -/* -------------------------------------------------------------------------- */ - -void init_gl(void) -{ - if(!useTheProgram()) k_gl_end(); - if(!setUpTnL()) k_gl_end(); -} - -void reshape(int width, int height) -{ -} - -void draw(void) -{ - if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end(); -} - -#define SHIFT 0 -void key(unsigned char k, int down) -{ - if(k == 113) viewAngle += 0.1; - if(k == 114) viewAngle -= 0.1; - - if(k==SHIFT && down){ shift=1; return; } - if(k==SHIFT && !down){ shift=0; return; } - if(!down) return; - - if(shift) k-=('a'-'A'); - - float speed=0.25; - switch (k) { - case 'H': - xco-=speed*(float)sin((view_roty-90)*3.14/180); - zco+=speed*(float)cos((view_roty-90)*3.14/180); - if(xco< -35) xco= -35; - if(xco> 35) xco= 35; - if(zco< -35) zco= -35; - if(zco> 35) zco= 35; - break; - case 'L': - xco+=speed*(float)sin((view_roty-90)*3.14/180); - zco-=speed*(float)cos((view_roty-90)*3.14/180); - if(xco< -35) xco= -35; - if(xco> 35) xco= 35; - if(zco< -35) zco= -35; - if(zco> 35) zco= 35; - break; - case 'i': - xco-=speed*(float)sin(view_roty*3.14/180); - zco+=speed*(float)cos(view_roty*3.14/180); - if(xco< -35) xco= -35; - if(xco> 35) xco= 35; - if(zco< -35) zco= -35; - if(zco> 35) zco= 35; - break; - case 'o': - xco+=speed*(float)sin(view_roty*3.14/180); - zco-=speed*(float)cos(view_roty*3.14/180); - if(xco< -35) xco= -35; - if(xco> 35) xco= 35; - if(zco< -35) zco= -35; - if(zco> 35) zco= 35; - break; - case 'j': - yco-=speed; - if(yco< 0.2) yco= 0.2; - break; - case 'k': - yco+=speed; - break; - case 'l': - view_roty += speed*20; - break; - case 'h': - view_roty -= speed*20; - break; - case 'J': - view_rotx += 2.0; - break; - case 'K': - view_rotx -= 2.0; - break; - case 'z': - view_rotz += 2.0; - break; - case 'Z': - view_rotz -= 2.0; - break; - default: - return; - } - draw(); -} - -/* ------------------------------------------------------------- */ - -GLuint isShaderError(GLuint thing) -{ - GLint isShader = glIsShader(thing); - - GLint ok; - if(isShader){ - glGetShaderiv(thing, GL_COMPILE_STATUS, &ok); - }else{ - glGetProgramiv(thing, GL_LINK_STATUS, &ok); - } - if(ok) return 0; - - GLint infoLen=0; - if(isShader){ - glGetShaderiv(thing, GL_INFO_LOG_LENGTH, &infoLen); - }else{ - glGetProgramiv(thing, GL_INFO_LOG_LENGTH, &infoLen); - } - if(infoLen){ - char* infoLog = malloc(sizeof(char)*infoLen); - if(isShader){ - glGetShaderInfoLog(thing, infoLen, NULL, infoLog); - }else{ - glGetProgramInfoLog(thing, infoLen, NULL, infoLog); - } - printf("%s: %s\n", isShader? "Shader compile": "Program link", infoLog); - free(infoLog); - } - return 1; -} - -char* file2string(const char *path) -{ - FILE *fd; - long len, r; - char *str; - - if(!(fd=fopen(path, "r"))) { - fprintf(stderr, "Can't open file '%s' for reading\n", path); - return NULL; - } - - fseek(fd, 0, SEEK_END); - len = ftell(fd); - fseek(fd, 0, SEEK_SET); - - if(!(str=malloc(len*sizeof(char)))) { - fprintf(stderr, "Can't malloc space for '%s'\n", path); - return NULL; - } - - r = fread(str, sizeof(char), len, fd); - - str[r-1] = '\0'; - - fclose(fd); - - return str; -} - -/* ------------------------------------------------------------- */ - -int useTheProgram() -{ - const char *vsSource = file2string("tnl.vert"); - const char *fsSource = file2string("tnl.frag"); - - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vs, 1, &vsSource, NULL); - glCompileShader(vs); - if(isShaderError(vs)) return 0; - - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fs, 1, &fsSource, NULL); - glCompileShader(fs); - if(isShaderError(fs)) return 0; - - free((void*)vsSource); - free((void*)fsSource); - - program = glCreateProgram(); - glAttachShader(program, vs); - glAttachShader(program, fs); - - glBindAttribLocation(program, POS_ARRAY, "vertPos"); - glBindAttribLocation(program, NORMAL_ARRAY, "vertNormal"); - /* vertNormal and vertTexCoord don't need to be bound here.. ? */ - glBindAttribLocation(program, TEXCOORD_ARRAY, "vertTexCoord"); - - glLinkProgram(program); - if(isShaderError(program)) return 0; - - glUseProgram(program); - - glUniform3f(glGetUniformLocation(program, "frameLightDirection"), 1.0, 0.0, 1.0); - glUniform1i(glGetUniformLocation(program, "texture"), 0); /* 0 ?? */ - - return 1; -} - -int setUpTnL() -{ - glClearColor(1.0f, 1.0f, 0.0f, 0.0f); - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - - GLuint* td = malloc(sizeof(GLuint)*TEX_SIZE*TEX_SIZE); - int i,j; - for(i=0; i -#include - -/* -------------------------------------------------------------------------- */ - -static int handles_resource(char* name); -static void sync_resource(ni_resource* res); - -static void start_tests(void); -static void running_tests(ni_event* evt); - -static void test_state(n_object* o, char* os, char* uid, char* cont); - -/* -------------------------------------------------------------------------- */ - -EXPORT int testni_module_loaded(void) -{ - ni_register_driver("testni", handles_resource, sync_resource); - - k_log_out("Test NI Driver initialised"); - - start_tests(); - - return 1; -} - -EXPORT int testni_module_event(void* data) -{ - ni_event* evt=data; - - running_tests(evt); - - ni_event_delete(evt); - return 1; -} - -EXPORT int testni_module_tick(void) -{ - return 1; -} - -/* -------------------------------------------------------------------------- */ - -int handles_resource(char* name) -{ - return 1; -} - -void sync_resource(ni_resource* res) -{ -} - -/* -------------------------------------------------------------------------- */ - -/* - - object.create .update .commit .rollback (auto inc version #?) - - object.see - may return empty so wait for .. - - seestate(object) - state asked for /or/ object is subscribing - */ -void start_tests(void) -{ - k_log_out("Creating o11111"); - - char* o11111s = "UID: 11111-4141a\n" - "\n" - "This: is one content\n"; - - n_object* o11111 = n_object_new(o11111s); - - test_state(o11111, o11111s, "11111-4141a", "is one content"); - - k_log_out("Committing o11111"); - - n_commit(o11111); - - k_log_out("Creating o22222"); - - char* o22222s = "UID: 22222-ef990\n" - "\n" - "This: is two content\n"; - - n_object* o22222 = n_object_new(o22222s); - - test_state(o22222, o22222s, "22222-ef990", "is two content"); - - n_object* o2 = n_see(o11111, "22222-ef990"); - - k_assert(!o2, "Object 2 has not been committed yet, but Object 1 can see it:\n%s\n", n_to_string(o2)); - - n_commit(o22222); - - o2 = n_see(o11111, "22222-ef990"); - - k_assert(o2!=0, "Object 2 has been committed, but can't be seen by Object 1"); - - test_state(o2, o22222s, "22222-ef990", "is two content"); - - n_object* o3 = n_see(o22222, "33333-18bbc"); - - k_assert(!o3, "Object 3 has not been created yet, but Object 2 can see it:\n%s", n_to_string(o3)); -} - -void running_tests(ni_event* evt) -{ - char* o33333s = - "UID: 33333-18bbc\n" - "\n" - "This: is three content\n"; - - n_object* o33333 = n_object_new(o33333s); - - n_commit(o33333); - -} - -/* -------------------------------------------------------------------------- */ - -void test_state(n_object* o, char* os, char* uid, char* cont) -{ - char* c; - - k_log_out("Checking %s", uid); - - c=n_to_string(o); - k_assert(c && !strcmp(c, os), "To-string was\n%s", c? c: "null"); - - c=n_uid(o); - k_assert(c && !strcmp(c, uid), "UID was %s in n_uid", c? c: "null"); - - c=n_header(o, "UID"); - k_assert(c && !strcmp(c, uid), "UID was %s in n_header", c? c: "null"); - - c=k_hashtable_get(n_headers(o), "UID"); - k_assert(c && !strcmp(c, uid), "UID was %s in hash get", c? c: "null"); - - c=k_hashtable_get(n_content(o), "This"); - k_assert(c && !strcmp(c, cont), "Content was %s", c? c: "null"); - - c=n_to_string(o); - k_assert(c && !strcmp(c, os), "To-string was\n%s", c? c: "null"); -} - -/* -------------------------------------------------------------------------- */ - - - diff --git a/src/drivers/op/cache.c b/src/drivers/op/cache.c new file mode 100644 index 0000000..fcc7f5b --- /dev/null +++ b/src/drivers/op/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("on", evt); +} + +/* -}{----------------------------------------------------------------------- */ + + diff --git a/src/drivers/op/protocol.c b/src/drivers/op/protocol.c new file mode 100644 index 0000000..ce964a9 --- /dev/null +++ b/src/drivers/op/protocol.c @@ -0,0 +1,562 @@ + +/* -}{----------------------------------------------------------------------- */ + +#include +#include + +/* -}{----------------------------------------------------------------------- */ + +#define TMPBUFSIZE 4096 +static char tmpbuf[TMPBUFSIZE]; +static k_hashtable* own_resources; + +/* -}{----------------------------------------------------------------------- */ + +extern void run_tests(void); + +extern char* make_cache_path(char* uri); +extern void look_in_file_cache(ni_event* evq); +extern void save_in_file_cache(ni_resource* res); + +extern void init_uri2chan(void); +extern char* get_host_for(char* uri); +extern char* get_channel_for(char* host); +extern char* use_ping_info(k_hashtable*, k_channel*); +extern void use_from_info(k_hashtable*, k_channel*); +extern void ping_tunnels(void); +extern void send_ping(k_channel* chan, char* firstline, char* to); + +/* -}{----------------------------------------------------------------------- */ + +static int handles_resource(char* name); +static void sync_resource(ni_resource* res); + int connection_writable(k_channel* chan, int bufpos, int len); + int connection_readable(k_channel* chan, int bufpos, int len); +static int recv_next_event( k_channel* chan); +static void recv_request( k_channel* chan, char* header); +static void recv_response( k_channel* chan, char* header); +static void got_mmap(char*, char*, char*, int, k_stat, void*); +static void set_read_buffer(k_channel*, char*, size_t, ni_event*); +static int recv_entity( k_channel* chan, int bufpos, int eof); +static int expecting_response(char* pub, ni_event* evt, k_channel*); +static void do_request( ni_event* evq); + void ensure_self_sub(ni_event* evq); +static void ping_resource_subs(void* arg, char* key, void* val); +static void ping_sub(ni_resource* res, k_hashtable* sub); +static ni_resource* own_resource(char* uri); +static void send_request(ni_event* evq); +static void send_response(ni_event* evt); +static k_channel* ensure_chan(char* chanm); + +/* -}{----------------------------------------------------------------------- */ + +EXPORT int op_module_loaded(void) +{ + ni_register_driver("op", handles_resource, sync_resource); + + if(strstr(k_version, "test")){ + //run_tests(); + } + + init_uri2chan(); + + own_resources=k_hashtable_new("Own Resources", 0); + + k_log_out("OP Driver initialised"); + + return 0; +} + +EXPORT void op_module_tick(void) +{ + static long tix; + tix++; + if(!(tix % 1000)){ + k_hashtable_apply(own_resources, ping_resource_subs, 0); + } + if(!(tix % 3000)){ + ping_tunnels(); + } +} + +EXPORT int op_module_event(void* data) +{ + ni_event* evt=data; + if(!k_hashtable_get(evt->ent_head, "Status:")){ + do_request(evt); + } + else{ + send_response(evt); + } + return 0; +} + +/* -}{----------------------------------------------------------------------- */ + +int handles_resource(char* name) +{ + return 0; +} + +void sync_resource(ni_resource* res) +{ + save_in_file_cache(res); +} + +/* -}{----------------------------------------------------------------------- */ + +int connection_readable(k_channel* chan, int bufpos, int len) +{ + if(0) k_log_out("connection_readable %s %p %d %d %p", + chan->name, chan, bufpos, len, chan->context); + int sof=(len== 0); + int eof=(len== -1); + + if(sof) return 0; + + do{ + ni_event* evt=chan->context; + if(!evt){ + int n=recv_next_event(chan); + if(n<0) break; + bufpos-=n; + } + else{ + int n=recv_entity(chan, bufpos, eof); + if(n<0) break; + bufpos-=n; + } + + } while(1); + + if(eof && chan->context){ + ni_event* evt=chan->context; + evt->entity=0; + ni_event_delete(evt); + chan->context=0; + } + + return 0; +} + +int connection_writable(k_channel* chan, int bufpos, int len) +{ + if(0) k_log_out("connection_writable %p %d %d %p", + chan, bufpos, len, chan->context); +//if(len>20000) exit(1); + int sof=(len== 0); + int eof=(len== -1); + + if(sof){ + send_ping(chan, "PING OP/0.5", 0); + return 0; + } + + if(eof && chan->context){ + ni_event* evt=chan->context; + evt->entity=0; + ni_event_delete(evt); + chan->context=0; + } + + return 0; +} + +/* -}{---- Receiving -------------------------------------------------------- */ + +int recv_next_event(k_channel* chan) +{ + char* header=k_channel_chop_div(chan, CRLF CRLF); + if(!header) return -1; + int n=strlen(header)+strlen(CRLF CRLF); + + if(!strncmp(header, "GET", 3) || + !strncmp(header, "SUB", 3) || + !strncmp(header, "UNSUB",5) || + !strncmp(header, "HEAD", 4) || + !strncmp(header, "PING", 4) ){ + + recv_request(chan, header); + return n; + } + if(!strncmp(header, "OP/", 4) ){ + + recv_response(chan, header); + return n; + } + k_free(header); + k_log_err("Failed reading request or response - closing connection"); + k_channel_close(chan); + return n; +} + +void recv_request(k_channel* chan, char* header) +{ + ni_event* evq; + evq=ni_get_request_headers(header); + if(!evq){ + k_log_err("Failed reading request headers - closing connection"); + k_channel_close(chan); + return; + } + if(!k_hashtable_isn(evq->evt_head, "Protocol:", "OP/", 4)){ + ni_event_delete(evq); + k_log_err("Failed reading request not OP - closing connection"); + k_channel_close(chan); + return; + } + + k_hashtable* ent_head=evq->ent_head; + int ping=k_hashtable_is(ent_head, "Method:", "PING"); + + if(!evq->uri && !ping){ + evq->uri=k_strdup(chan->name); + k_hashtable_put_dup(ent_head, "URI:", chan->name); + } + + ni_event_show(evq, "OP Protocol Request"); + + if(k_hashtable_isi(evq->evt_head, "Connection:", "Keep-Alive")){ + chan->linger=1; + if(k_hashtable_isn(ent_head, "Sub-To:", "./test", 6)){ + chan->linger=0; + } + } + if(ping){ + char* from=use_ping_info(ent_head, chan); + if(from) send_ping(chan, "OP/0.5 270 PING", from); + ni_event_delete(evq); + return; + } + //use_from_info(ent_head, chan); + + ni_event* evp=ni_event_new(evq->uri, 0, k_hashtable_dup(ent_head), 0); + + ni_event_delete(evq); + + k_event_post("on", evp); +} + +void recv_response(k_channel* chan, char* header) +{ + ni_event* evt=ni_get_response_headers(header); + if(!evt){ + k_log_err("recv_response: headers failed but doing nothing!"); + return; + } + char* pub= evt->uri; + k_hashtable* ent_head=evt->ent_head; + + if(!expecting_response(pub, evt, chan)) return; + + ni_event_show(evt, "Response"); + + int head=k_hashtable_is( ent_head, "Status:", "260"); + int nmod=k_hashtable_is( ent_head, "Status:", "304"); + int ping=k_hashtable_is( ent_head, "Status:", "270"); + int cl =k_hashtable_get_int(ent_head, "Content-Length:"); + int entity=!(head || nmod || ping || cl==0); + + if(ping){ + use_ping_info(ent_head, chan); + ni_event_delete(evt); + return; + } + use_from_info(ent_head, chan); + + if(entity){ + k_hashtable_set(ent_head, "Status:", "260"); + k_hashtable_set(ent_head, "Status-Text:", "Headers Only"); + } + k_event_post("on", evt); + + if(entity){ + + k_hashtable* eh=k_hashtable_new("nHeaders/recv_response", 1); + char* from =k_hashtable_get(ent_head, "From:"); + char* contlen =k_hashtable_get(ent_head, "Content-Length:"); + char* cux =k_hashtable_get(ent_head, "CUX:"); + k_hashtable_set(eh, "Status:", "206"); + k_hashtable_set(eh, "Status-Text:", "Partial Content"); + k_hashtable_put_dup(eh, "From:", from); + k_hashtable_put_dup(eh, "Content-Length:", contlen); + k_hashtable_put_dup(eh, "CUX:", cux); + ni_event* evc=ni_event_new(pub, 0, eh, 0); + chan->context=evc; + + int constant=k_hashtable_is(ent_head, "CUX:", "C"); + if(constant){ + char* path=make_cache_path(pub); if(!path) return; + k_file_read(".", path, USE_MMAP, cl, got_mmap, chan); + } + else{ + char* data=k_malloc(cl); + set_read_buffer(chan, data, cl, evc); + } + } +} + +void got_mmap(char* basedir, + char* path, + char* data, + int usedmmap, + k_stat kstat, + void* context){ + + k_free(path); + k_channel* chan=context; + ni_event* evt=chan->context; + if(!evt){ k_log_err("got_mmap: evt=0"); return; } + if(!data || !usedmmap){ k_log_err("got_mmap: mmap failed"); return; } + + size_t cl=k_hashtable_get_int(evt->ent_head, "Content-Length:"); + set_read_buffer(chan, data, cl, evt); +} + +void set_read_buffer(k_channel* chan, char* data, size_t cl, ni_event* evt) +{ + evt->entity=data; + int r=k_channel_setbuf(chan, data, cl); + if(0) k_log_out("k_channel_setbuf %d", r); + if(r==BUFFER_ALREADY_SET){ + k_log_err("oops! k_channel_setbuf BUFFER_ALREADY_SET"); + return; + } + if(r==BUFFER_FILLED){ + k_hashtable_set(evt->ent_head, "Status:", "200"); + k_hashtable_set(evt->ent_head, "Status-Text:", "OK"); + chan->context=0; + k_event_post("on", evt); + } +} + +int recv_entity(k_channel* chan, int bufpos, int eof) +{ + ni_event* evt=chan->context; + k_hashtable* ent_head=evt->ent_head; + + char* cls=k_hashtable_get( ent_head, "Content-Length:"); + int cl =k_hashtable_get_int(ent_head, "Content-Length:"); + + if(!cls && !eof) return -1; + + int partial=0; + int eofcontlen=eof && (!cls || bufpos < cl); + if(eofcontlen){ + if(cls){ + char* clg=k_strdup(cls); + k_hashtable_put(ent_head, "Content-Length-Given:", clg); + partial=1; + } + cl=bufpos; + char b[32]; snprintf(b, 32, "%d", cl); + k_hashtable_put_dup(ent_head, "Content-Length:", b); + } + + if(bufpos < cl){ + if(bufpos){ + ni_event* evp=ni_event_dup(evt); + snprintf(tmpbuf, TMPBUFSIZE, "0-%d", bufpos); + char* cr=k_strdup(tmpbuf); + k_hashtable_put(evp->ent_head, "Content-Range:", cr); + k_event_post("on", evp); + } + return -1; + } + + static char dummy_empty_entity[0]; + if(!k_channel_getbuf(chan)){ + int cn=k_hashtable_is(ent_head, "CUX:", "C"); + if(cl) evt->entity=k_channel_chop_len(chan, cl); + else evt->entity=cn? dummy_empty_entity: k_malloc(1); + } + + if(!partial){ + k_hashtable_set(ent_head, "Status:", "200"); + k_hashtable_set(ent_head, "Status-Text:", "OK"); + } + chan->context=0; + k_event_post("on", evt); + + return cl; +} + +int expecting_response(char* pub, ni_event* evt, k_channel* chan) +{ + if(pub && 0){ + k_log_err("unwanted response: %s", pub); + ni_event_delete(evt); + k_channel_close(chan); + return 0; + } + return 1; +} + +/* -}{---- Sending ---------------------------------------------------------- */ + +void do_request(ni_event* evq) +{ + k_hashtable* sub=evq->ent_head; + int tc=k_hashtable_isi(sub, "Sub-Type:", "Cache"); + int to=k_hashtable_isi(sub, "Sub-Type:", "Original"); + + if(tc){ + char* ims=k_hashtable_get(sub, "If-Modified-Since:"); + if(ims) ensure_self_sub(evq); + else look_in_file_cache(evq); + } + else + if(to){ + send_request(evq); + } +} + +void ensure_self_sub(ni_event* evq) +{ + k_hashtable* sub=evq->ent_head; + char* pub=k_hashtable_get(sub, "Sub-To:"); + + ni_resource* res=own_resource(pub); + k_hashtable* enh=res->ent_head; + k_hashtable* selfsub=k_hashtable_get(enh, "Sub-To:"); + if(selfsub && !k_hashtable_is(selfsub, "Status-Cache:", "OK")){ + k_log_err("cancel selfsub as new one needed"); + } + + k_hashtable* ss=k_hashtable_dup(sub); + k_hashtable_remove( ss, "From:"); + k_hashtable_put_dup(ss, "URI:", pub); + k_hashtable_set( ss, "Sub-Type:", "Original"); + k_hashtable_put_dup(ss, "Via:", get_host_for(pub)); + if(k_hashtable_get( ss, "If-Modified-Since:")){ + char* lm=k_hashtable_get(enh, "Last-Modified:"); + if(!res->entity) lm=0; + k_hashtable_set(ss, "If-Modified-Since:", lm? lm: "0"); + } + ni_event* evs=ni_event_new(0, 0, ss, 0); + k_event_post("on", evs); + + ni_event_delete(evq); +} + +void ping_resource_subs(void* arg, char* key, void* val) +{ + ni_resource* res=val; + k_hashtable* pubcache=k_hashtable_get(res->ent_head, "Pub-Cache:"); + if(!pubcache || !k_hashtable_get(pubcache, "Method:")) return; + k_hashtable* subs=k_hashtable_get(res->ent_head, "Sub-To:"); + k_hashtable* sub; + for(sub=subs; sub; sub=sub->next){ + if(!k_hashtable_is(sub, "Status-Cache:", "OK")){ + if(!k_hashtable_get(sub, "Status:")){ + ping_sub(res, sub); + } + else{ + int ts=k_hashtable_get_int(sub, "Timestamp:"); + if(0) k_log_out("check dried-up request: %d", ts); + } + } + } +} + +void ping_sub(ni_resource* res, k_hashtable* sub) +{ + ni_resource_show(res, "ping_resource_subs"); + + k_hashtable* ss=k_hashtable_dup(sub); + + char* subto=k_hashtable_extract(ss, "URI:"); + k_hashtable_put_dup(ss, "URI:", res->uri); + k_hashtable_put( ss, "Sub-To:", subto); + k_hashtable_set( ss, "Sub-Type:", "Original"); + k_hashtable_put_dup(ss, "Via:", get_host_for(res->uri)); + + ni_event* evs=ni_event_new(0, 0, ss, 0); + k_event_post("on", evs); +} + +ni_resource* own_resource(char* uri) +{ + ni_resource* res=k_hashtable_get(own_resources, uri); + if(!res){ + res=ni_resource_get(uri); + k_hashtable_set(own_resources, uri, res); + } + return res; +} + +void send_request(ni_event* evt) +{ + k_hashtable* eh=evt->ent_head; + char* method=k_strdup(k_hashtable_get(eh, "Method:")); + char* to =k_strdup(k_hashtable_get(eh, "Sub-To:")); + char* via =k_strdup(k_hashtable_get(eh, "Via:")); + + char* chanm=get_channel_for(via); + if(!chanm) goto free_and_return; + + k_channel* chan=ensure_chan(chanm); + if(!chan) goto free_and_return; + + ni_fix_ni_headers(eh, 0); + ni_request(evt, to, method, chan); + + free_and_return: + k_free(method); k_free(to); k_free(via); + ni_event_delete(evt); +} + +void send_response(ni_event* evt) +{ + ni_event_show(evt, "send_response"); + + k_hashtable* eh=evt->ent_head; + + k_hashtable* sub=k_hashtable_get(eh, "Pub-To:"); + char* uri =k_hashtable_get(sub, "URI:"); + char* from =k_hashtable_get(sub, "From:"); + char* method =k_hashtable_get(sub, "Method:"); + int methead =k_hashtable_is( sub, "Method:", "HEAD"); + + char* to=from? from: uri; + + char* host=from? from: get_host_for(uri); + char* chanm=get_channel_for(host); + if(!chanm){ + if(0) k_log_out("no OP protocol channel %s", to); + ni_event_delete(evt); + return; + } + + k_channel* chan=ensure_chan(chanm); + if(!chan){ + if(0) k_log_out("no OP protocol channel %s", to); + ni_event_delete(evt); + return; + } + + k_hashtable_extract(eh, "Pub-To:"); + + char* protocol="OP/0.5"; + + ni_fix_ni_headers(eh, methead); + ni_response(evt, to, method, protocol, 0, chan); + + k_hashtable_delete(sub); + evt->entity=0; + ni_event_delete(evt); +} + +k_channel* ensure_chan(char* chanm) +{ + k_channel* chan=k_channel_get_name(chanm); + if(!chan){ + k_log_err("Cannot find current channel for %s", chanm); + k_channel_connect_name(chanm, connection_readable, + connection_writable); + } + return chan; +} + +/* -}{----------------------------------------------------------------------- */ + diff --git a/src/drivers/op/uri2chan.c b/src/drivers/op/uri2chan.c new file mode 100644 index 0000000..8586433 --- /dev/null +++ b/src/drivers/op/uri2chan.c @@ -0,0 +1,294 @@ + +/* -}{----------------------------------------------------------------------- */ + +#include +#include + +/* -}{----------------------------------------------------------------------- */ + +extern int connection_writable(k_channel* chan, int bufpos, int len); +extern int connection_readable(k_channel* chan, int bufpos, int len); + +/* -}{----------------------------------------------------------------------- */ + +#define TMPBUFSIZE 4096 +static char tmpbuf[TMPBUFSIZE]; +static int is_np; +static char* nexus_channel; +static k_hashtable* chans_for_host; + +/* -}{----------------------------------------------------------------------- */ + +static void nexus_file_read(char*, char*, char*, int, k_stat, void*); +static void write_nexus(char* hostname); +static void nexus_file_written(char*, char*, char*, int, k_stat, void*); +static int root_nexus(void); +static void listen_http(void); +static void listen_nexus(void); +static void connect_to_nexus(void); +static void ping_this(void* arg, char* key, void* val); +static char* generate_new_hostname(k_hashtable* ent_head, k_channel* chan); +static void set_channel_for(char* host, char* chanm); +static void show_np(void); +static void show_list(void* arg, char* key, void* val); + +/* -}{----------------------------------------------------------------------- */ + +void init_uri2chan(void) +{ + chans_for_host =k_hashtable_new("Channels for Host", 0); + + k_file_read(".", "nexus.txt", USE_MALL, 0, nexus_file_read, 0); + + is_np=!strcmp(k_ciux, "op"); + if(is_np) listen_nexus(); + if(root_nexus()){ + k_log_out("root nexus - but listening on http"); + listen_http(); + } + else{ + k_log_out("connecting to nexus %s", nexus_channel); + connect_to_nexus(); + } +} + +char* get_host_for(char* uri) +{ + if(0) k_log_out("get_host_for %s", uri); + char* host=0; + if(0) k_log_out("host for %s=%s", uri, host); + return host; +} + +char* get_channel_for(char* host) +{ + if(0) k_log_out("get_channel_for %s", host); + char* chanm=k_hashtable_get(chans_for_host, host); + if(!chanm){ + } + if(0) k_log_out("channel for %s=%s", host, chanm); + return chanm; +} + +char* use_ping_info(k_hashtable* ent_head, k_channel* chan) +{ + char* from=k_hashtable_get(ent_head, "From:"); + char* to =k_hashtable_get(ent_head, "To:"); + + if(!from) return 0; + if(!strcmp(from, "-")) from=generate_new_hostname(ent_head, chan); + if(!from) return 0; + if(!ni_hostname() && to) write_nexus(to); + + set_channel_for(from, chan->name); + + if(0) k_log_out("%s PING %s", chan->name, from); + if(0) show_np(); + + return from; +} + +void use_from_info(k_hashtable* ent_head, k_channel* chan) +{ + char* from=k_hashtable_get(ent_head, "From:"); + + if(!from) return; + + set_channel_for(from, chan->name); + + if(0) show_np(); +} + +void ping_tunnels(void) +{ + k_hashtable* channelspinged=k_hashtable_new("channelspinged", 0); + k_hashtable_apply(chans_for_host, ping_this, channelspinged); + k_hashtable_delete(channelspinged); +} + +void send_ping(k_channel* chan, char* firstline, char* to) +{ + char* from=ni_hostname(); + if(!from) from="-"; + + int ln=0; + int bufsize=TMPBUFSIZE; + + ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s" CRLF, firstline); + if(ln>=bufsize) return; + ln+=snprintf(tmpbuf+ln, bufsize-ln, "From: %s" CRLF, from); + if(ln>=bufsize) return; + if(to){ + ln+=snprintf(tmpbuf+ln, bufsize-ln, "To: %s" CRLF, to); + if(ln>=bufsize) return; + } + ln+=snprintf(tmpbuf+ln, bufsize-ln, "Server: %s" CRLF, k_version); + if(ln>=bufsize) return; + ln+=snprintf(tmpbuf+ln, bufsize-ln, "Channels: %s" CRLF, "-"); + if(ln>=bufsize) return; + ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF); + if(ln>=bufsize) return; + + char* head=k_strdup(tmpbuf); + k_channel_send(chan, head, ln, FREE_ON_SENT); +} + +/* -}{----------------------------------------------------------------------- */ + +void nexus_file_read(char* basedir, + char* filepath, + char* data, + int usedmmap, + k_stat kstat, + void* context) +{ + int L=0; + if(data) data[kstat.size-1]=0; + else data=k_strdup(""); + k_hashtable* nex=k_hashtable_new("nexus", 1); + if(!ni_get_headers(data, nex, 0)){ + k_log_err("Corrupt nexus.txt file"); + k_hashtable_delete(nex); + k_free(data); + data=k_strdup(""); + nex=k_hashtable_new("nexus", 1); + ni_get_headers(data, nex, 0); + } + + char* hostname; + nexus_channel=k_hashtable_get_dup(nex, "Nexus-Channel:"); + hostname =k_hashtable_get( nex, "Hostname:"); + + if(hostname) ni_hostname_set(hostname); + + if(L) if(nexus_channel) k_log_out("Nexus-Channel: %s", nexus_channel); + if(L) if(hostname) k_log_out("Hostname: %s", hostname); + + k_hashtable_delete(nex); + k_free(data); +} + +void write_nexus(char* hostname) +{ + ni_hostname_set(hostname); + + snprintf(tmpbuf, TMPBUFSIZE, "Nexus-Channel: %s\r\n" + "Hostname: %s\r\n", nexus_channel, + hostname); + + k_file_write(".", "nexus.txt", tmpbuf, strlen(tmpbuf), + nexus_file_written, 0); +} + +void nexus_file_written(char* basedir, + char* filepath, + char* data, + int usedmmap, + k_stat kstat, + void* context) +{ + if(!data) k_fatal("Failed to write nexus.txt"); + else k_log_out("New nexus.txt written:\n%s", data); +} + +int root_nexus(void) +{ + char* hostname=ni_hostname(); + if(!hostname || strchr(hostname, '-')) return 0; + return 1; +} + +void listen_http(void) +{ + char* chanm="|nip-server|-|8081|-|"; + k_channel_connect_name(chanm, connection_readable, + connection_writable); +} + +void listen_nexus(void) +{ + char* chanm="|nip-server|-|7747|-|"; + k_channel_connect_name(chanm, connection_readable, + connection_writable); +} + +void connect_to_nexus(void) +{ + if(nexus_channel){ + k_channel_connect_name(nexus_channel, connection_readable, + connection_writable); + } + else k_log_out("discovery of nexus not implemented yet!"); +} + +void ping_this(void* arg, char* key, void* val) +{ + k_hashtable* channelspinged=arg; + char* chanm=val; + + if(strncmp(chanm, "nip-client", 11) ) return; + if(k_hashtable_get(channelspinged, chanm)) return; + k_hashtable_set(channelspinged, chanm, chanm); + + k_channel* chan=k_channel_get_name(chanm); + //k_log_out("ping_this: host %s channel %s got=%p", key, chanm, chan); + + if(!chan) k_channel_connect_name(chanm, connection_readable, + connection_writable); + + int pingtodeath=0; + if(chan && pingtodeath) send_ping(chan, "PING OP/0.5", 0); +} + +char* generate_new_hostname(k_hashtable* ent_head, k_channel* chan) +{ + if(!ni_hostname()) return 0; + unsigned long a=chan->clientip.s_addr; + #define IPQUAD(a) \ + ((unsigned char *)&a)[0], \ + ((unsigned char *)&a)[1], \ + ((unsigned char *)&a)[2], \ + ((unsigned char *)&a)[3] + snprintf(tmpbuf, TMPBUFSIZE, "%s-%02x%02x%02x%02x.%d", + ni_hostname(), IPQUAD(a), 7747); + if(0) k_log_out("generated new hostname: %s\n", tmpbuf); + return k_strdup(tmpbuf); +} + +/* -}{----------------------------------------------------------------------- */ + +void set_channel_for(char* host, char* chanm) +{ + k_hashtable_put_dup(chans_for_host, host, chanm); +} + +void show_np(void) +{ + k_log_out("-------- channel for host ---------------"); + k_hashtable_apply(chans_for_host, show_list, 0); + k_channel_show_all(); +} + +void show_list(void* arg, char* key, void* val) +{ + char* chanm=val; + k_log_out("%s %s", key, chanm); +} + +void generate_random(void) +{ + time_t t=time(0); + short r; + k_random_bytes((char*)&r, sizeof(r)); + unsigned char r1=(t >>24) & 255; + unsigned char r2=(t >>16) & 255; + unsigned char r3=(t >> 8) & 255; + unsigned char r4=(t ) & 255; + unsigned char r5=(r >> 8) & 255; + unsigned char r6=(r ) & 255; + snprintf(tmpbuf, TMPBUFSIZE, "%02x-%02x-%02x-%02x-%02x-%02x", + r1, r2, r3, r4, r5, r6); +} + +/* -}{----------------------------------------------------------------------- */ + diff --git a/src/drivers/ot/mid/mid.c b/src/drivers/ot/mid/mid.c new file mode 100644 index 0000000..b27b24a --- /dev/null +++ b/src/drivers/ot/mid/mid.c @@ -0,0 +1,408 @@ + +/* -------------------------------------------------------------------------- */ + +#include +#include + +/* -------------------------------------------------------------------------- */ + +#define WINDOW_WIDTH 640 +#define WINDOW_HEIGHT 480 + +#define POS_ARRAY 0 +#define NORMAL_ARRAY 1 +#define TEXCOORD_ARRAY 2 + +#define TEX_SIZE 128 + +/* -------------------------------------------------------------------------- */ + +static GLfloat xco= 0; +static GLfloat yco= 1; +static GLfloat zco= -35; +static GLfloat view_rotx=0.0, view_roty=0.0, view_rotz=0.0; +static int shift=0; + +GLuint program; +GLuint texture; +GLuint vbo; +unsigned int numberOfVertices; +unsigned int posStep; +unsigned int normStep; +unsigned int tcStep; +unsigned int stride; +float angle=0.0; +float viewAngle = 0.0; + +/* -------------------------------------------------------------------------- */ + +static int handles_resource(char* name); +static void sync_resource(ni_resource* res); +static void init_gl(void); +static void reshape(int width, int height); +static void draw(void); +static void key(unsigned char k, int down); + +static int useTheProgram(); +static int setUpTnL(); +static int drawStuff(int width, int height); + +/* -------------------------------------------------------------------------- */ + +EXPORT int mid_module_loaded(void) +{ + ni_register_driver("mid", handles_resource, sync_resource); + + init_gl(); + + k_gl_register_reshape(reshape); + k_gl_register_draw(draw); + k_gl_register_key(key); + + k_log_out("MID Driver initialised"); + + return 1; +} + +EXPORT int mid_module_event(void* data) +{ + k_log_out("MID got event: %p", data); + ni_event* evt=data; + ni_event_delete(evt); + return 1; +} + +EXPORT int mid_module_tick(void) +{ + if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end(); + return 1; +} + +/* -------------------------------------------------------------------------- */ + +int handles_resource(char* name) +{ + return 0; +} + +void sync_resource(ni_resource* res) +{ +} + +/* -------------------------------------------------------------------------- */ + +void init_gl(void) +{ + if(!useTheProgram()) k_gl_end(); + if(!setUpTnL()) k_gl_end(); +} + +void reshape(int width, int height) +{ +} + +void draw(void) +{ + if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end(); +} + +#define SHIFT 0 +void key(unsigned char k, int down) +{ + if(k == 113) viewAngle += 0.1; + if(k == 114) viewAngle -= 0.1; + + if(k==SHIFT && down){ shift=1; return; } + if(k==SHIFT && !down){ shift=0; return; } + if(!down) return; + + if(shift) k-=('a'-'A'); + + float speed=0.25; + switch (k) { + case 'H': + xco-=speed*(float)sin((view_roty-90)*3.14/180); + zco+=speed*(float)cos((view_roty-90)*3.14/180); + if(xco< -35) xco= -35; + if(xco> 35) xco= 35; + if(zco< -35) zco= -35; + if(zco> 35) zco= 35; + break; + case 'L': + xco+=speed*(float)sin((view_roty-90)*3.14/180); + zco-=speed*(float)cos((view_roty-90)*3.14/180); + if(xco< -35) xco= -35; + if(xco> 35) xco= 35; + if(zco< -35) zco= -35; + if(zco> 35) zco= 35; + break; + case 'i': + xco-=speed*(float)sin(view_roty*3.14/180); + zco+=speed*(float)cos(view_roty*3.14/180); + if(xco< -35) xco= -35; + if(xco> 35) xco= 35; + if(zco< -35) zco= -35; + if(zco> 35) zco= 35; + break; + case 'o': + xco+=speed*(float)sin(view_roty*3.14/180); + zco-=speed*(float)cos(view_roty*3.14/180); + if(xco< -35) xco= -35; + if(xco> 35) xco= 35; + if(zco< -35) zco= -35; + if(zco> 35) zco= 35; + break; + case 'j': + yco-=speed; + if(yco< 0.2) yco= 0.2; + break; + case 'k': + yco+=speed; + break; + case 'l': + view_roty += speed*20; + break; + case 'h': + view_roty -= speed*20; + break; + case 'J': + view_rotx += 2.0; + break; + case 'K': + view_rotx -= 2.0; + break; + case 'z': + view_rotz += 2.0; + break; + case 'Z': + view_rotz -= 2.0; + break; + default: + return; + } + draw(); +} + +/* ------------------------------------------------------------- */ + +GLuint isShaderError(GLuint thing) +{ + GLint isShader = glIsShader(thing); + + GLint ok; + if(isShader){ + glGetShaderiv(thing, GL_COMPILE_STATUS, &ok); + }else{ + glGetProgramiv(thing, GL_LINK_STATUS, &ok); + } + if(ok) return 0; + + GLint infoLen=0; + if(isShader){ + glGetShaderiv(thing, GL_INFO_LOG_LENGTH, &infoLen); + }else{ + glGetProgramiv(thing, GL_INFO_LOG_LENGTH, &infoLen); + } + if(infoLen){ + char* infoLog = malloc(sizeof(char)*infoLen); + if(isShader){ + glGetShaderInfoLog(thing, infoLen, NULL, infoLog); + }else{ + glGetProgramInfoLog(thing, infoLen, NULL, infoLog); + } + printf("%s: %s\n", isShader? "Shader compile": "Program link", infoLog); + free(infoLog); + } + return 1; +} + +char* file2string(const char *path) +{ + FILE *fd; + long len, r; + char *str; + + if(!(fd=fopen(path, "r"))) { + fprintf(stderr, "Can't open file '%s' for reading\n", path); + return NULL; + } + + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fseek(fd, 0, SEEK_SET); + + if(!(str=malloc(len*sizeof(char)))) { + fprintf(stderr, "Can't malloc space for '%s'\n", path); + return NULL; + } + + r = fread(str, sizeof(char), len, fd); + + str[r-1] = '\0'; + + fclose(fd); + + return str; +} + +/* ------------------------------------------------------------- */ + +int useTheProgram() +{ + const char *vsSource = file2string("tnl.vert"); + const char *fsSource = file2string("tnl.frag"); + + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vsSource, NULL); + glCompileShader(vs); + if(isShaderError(vs)) return 0; + + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fsSource, NULL); + glCompileShader(fs); + if(isShaderError(fs)) return 0; + + free((void*)vsSource); + free((void*)fsSource); + + program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, fs); + + glBindAttribLocation(program, POS_ARRAY, "vertPos"); + glBindAttribLocation(program, NORMAL_ARRAY, "vertNormal"); + /* vertNormal and vertTexCoord don't need to be bound here.. ? */ + glBindAttribLocation(program, TEXCOORD_ARRAY, "vertTexCoord"); + + glLinkProgram(program); + if(isShaderError(program)) return 0; + + glUseProgram(program); + + glUniform3f(glGetUniformLocation(program, "frameLightDirection"), 1.0, 0.0, 1.0); + glUniform1i(glGetUniformLocation(program, "texture"), 0); /* 0 ?? */ + + return 1; +} + +int setUpTnL() +{ + glClearColor(1.0f, 1.0f, 0.0f, 0.0f); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + GLuint* td = malloc(sizeof(GLuint)*TEX_SIZE*TEX_SIZE); + int i,j; + for(i=0; i +#include + +/* -------------------------------------------------------------------------- */ + +static int handles_resource(char* name); +static void sync_resource(ni_resource* res); + +static void start_tests(void); +static void running_tests(ni_event* evt); + +static void test_state(n_object* o, char* os, char* uid, char* cont); + +/* -------------------------------------------------------------------------- */ + +EXPORT int teston_module_loaded(void) +{ + ni_register_driver("teston", handles_resource, sync_resource); + + k_log_out("Test ON Driver initialised"); + + start_tests(); + + return 1; +} + +EXPORT int teston_module_event(void* data) +{ + ni_event* evt=data; + + running_tests(evt); + + ni_event_delete(evt); + return 1; +} + +EXPORT int teston_module_tick(void) +{ + return 1; +} + +/* -------------------------------------------------------------------------- */ + +int handles_resource(char* name) +{ + return 1; +} + +void sync_resource(ni_resource* res) +{ +} + +/* -------------------------------------------------------------------------- */ + +/* + - object.create .update .commit .rollback (auto inc version #?) + - object.see - may return empty so wait for .. + - seestate(object) - state asked for /or/ object is subscribing + */ +void start_tests(void) +{ + k_log_out("Creating o11111"); + + char* o11111s = "UID: 11111-4141a\n" + "\n" + "This: is one content\n"; + + n_object* o11111 = n_object_new(o11111s); + + test_state(o11111, o11111s, "11111-4141a", "is one content"); + + k_log_out("Committing o11111"); + + n_commit(o11111); + + k_log_out("Creating o22222"); + + char* o22222s = "UID: 22222-ef990\n" + "\n" + "This: is two content\n"; + + n_object* o22222 = n_object_new(o22222s); + + test_state(o22222, o22222s, "22222-ef990", "is two content"); + + n_object* o2 = n_see(o11111, "22222-ef990"); + + k_assert(!o2, "Object 2 has not been committed yet, but Object 1 can see it:\n%s\n", n_to_string(o2)); + + n_commit(o22222); + + o2 = n_see(o11111, "22222-ef990"); + + k_assert(o2!=0, "Object 2 has been committed, but can't be seen by Object 1"); + + test_state(o2, o22222s, "22222-ef990", "is two content"); + + n_object* o3 = n_see(o22222, "33333-18bbc"); + + k_assert(!o3, "Object 3 has not been created yet, but Object 2 can see it:\n%s", n_to_string(o3)); +} + +void running_tests(ni_event* evt) +{ + char* o33333s = + "UID: 33333-18bbc\n" + "\n" + "This: is three content\n"; + + n_object* o33333 = n_object_new(o33333s); + + n_commit(o33333); + +} + +/* -------------------------------------------------------------------------- */ + +void test_state(n_object* o, char* os, char* uid, char* cont) +{ + char* c; + + k_log_out("Checking %s", uid); + + c=n_to_string(o); + k_assert(c && !strcmp(c, os), "To-string was\n%s", c? c: "null"); + + c=n_uid(o); + k_assert(c && !strcmp(c, uid), "UID was %s in n_uid", c? c: "null"); + + c=n_header(o, "UID"); + k_assert(c && !strcmp(c, uid), "UID was %s in n_header", c? c: "null"); + + c=k_hashtable_get(n_headers(o), "UID"); + k_assert(c && !strcmp(c, uid), "UID was %s in hash get", c? c: "null"); + + c=k_hashtable_get(n_content(o), "This"); + k_assert(c && !strcmp(c, cont), "Content was %s", c? c: "null"); + + c=n_to_string(o); + k_assert(c && !strcmp(c, os), "To-string was\n%s", c? c: "null"); +} + +/* -------------------------------------------------------------------------- */ + + + diff --git a/src/include/ni.h b/src/include/ni.h deleted file mode 100644 index 7916190..0000000 --- a/src/include/ni.h +++ /dev/null @@ -1,93 +0,0 @@ - -#ifndef ni_H -#define ni_H - -/* -------------------------------------------------------------------------- */ - -typedef struct n_object{ - k_hashtable* headers; - k_hashtable* content; -} n_object; - -PUBLIC n_object* n_object_new(char* s); -PUBLIC void n_commit(n_object* o); -PUBLIC n_object* n_see(n_object* o, char* uid); -PUBLIC char* n_to_string(n_object* o); -PUBLIC char* n_uid(n_object* o); -PUBLIC char* n_header(n_object* o, char* name); -PUBLIC k_hashtable* n_headers(n_object* o); -PUBLIC k_hashtable* n_content(n_object* o); - -/* -------------------------------------------------------------------------- */ - -PUBLIC char* ni_hostname(void); -PUBLIC void ni_hostname_set(char* name); - -/* -------------------------------------------------------------------------- */ - -typedef struct ni_resource{ - char* uri; - k_hashtable* ent_head; - void* entity; -} ni_resource; - -PUBLIC ni_resource* ni_resource_new(char* uri, - k_hashtable* ent_head, - char* entity); -PUBLIC ni_resource* ni_resource_dup( ni_resource* res); -PUBLIC void ni_resource_delete(ni_resource* res); -PUBLIC void ni_resource_show( ni_resource* res, char* text); -PUBLIC ni_resource* ni_resource_get(char* uri); - -/* -------------------------------------------------------------------------- */ - -typedef struct ni_event{ - char* uri; - k_hashtable* evt_head; - k_hashtable* ent_head; - void* entity; -} ni_event; - -PUBLIC ni_event* ni_event_new(char* uri, - k_hashtable* evt_head, - k_hashtable* ent_head, - char* entity); -PUBLIC ni_event* ni_event_dup( ni_event* res); -PUBLIC void ni_event_delete(ni_event* res); -PUBLIC void ni_event_show( ni_event* res, char* text); - -/* -------------------------------------------------------------------------- */ - -PUBLIC ni_event* ni_res_to_evt(ni_resource* res); - -/* -------------------------------------------------------------------------- */ - -typedef int (*ni_handles_resource)(char*); -typedef void (*ni_sync_resource )(ni_resource*); - -PUBLIC void ni_register_driver(char* name, - ni_handles_resource handles_resource, - ni_sync_resource sync_resource); - -/* -------------------------------------------------------------------------- */ - -PUBLIC ni_event* ni_get_request_headers( char* header); -PUBLIC ni_event* ni_get_response_headers(char* header); -PUBLIC char* ni_get_headers( char* header, k_hashtable*, k_hashtable*); -PUBLIC void ni_fix_http_headers(k_hashtable* ent_head); -PUBLIC void ni_fix_ni_headers(k_hashtable* ent_head, int methead); -PUBLIC void ni_response(ni_event* evt, - char* to, - char* method, - char* protocol, - char* connection, - k_channel* chan); -PUBLIC void ni_request(ni_event* evt, - char* to, - char* method, - k_channel* chan); - -/* -------------------------------------------------------------------------- */ - -#endif - diff --git a/src/include/notification.h b/src/include/notification.h new file mode 100644 index 0000000..7916190 --- /dev/null +++ b/src/include/notification.h @@ -0,0 +1,93 @@ + +#ifndef ni_H +#define ni_H + +/* -------------------------------------------------------------------------- */ + +typedef struct n_object{ + k_hashtable* headers; + k_hashtable* content; +} n_object; + +PUBLIC n_object* n_object_new(char* s); +PUBLIC void n_commit(n_object* o); +PUBLIC n_object* n_see(n_object* o, char* uid); +PUBLIC char* n_to_string(n_object* o); +PUBLIC char* n_uid(n_object* o); +PUBLIC char* n_header(n_object* o, char* name); +PUBLIC k_hashtable* n_headers(n_object* o); +PUBLIC k_hashtable* n_content(n_object* o); + +/* -------------------------------------------------------------------------- */ + +PUBLIC char* ni_hostname(void); +PUBLIC void ni_hostname_set(char* name); + +/* -------------------------------------------------------------------------- */ + +typedef struct ni_resource{ + char* uri; + k_hashtable* ent_head; + void* entity; +} ni_resource; + +PUBLIC ni_resource* ni_resource_new(char* uri, + k_hashtable* ent_head, + char* entity); +PUBLIC ni_resource* ni_resource_dup( ni_resource* res); +PUBLIC void ni_resource_delete(ni_resource* res); +PUBLIC void ni_resource_show( ni_resource* res, char* text); +PUBLIC ni_resource* ni_resource_get(char* uri); + +/* -------------------------------------------------------------------------- */ + +typedef struct ni_event{ + char* uri; + k_hashtable* evt_head; + k_hashtable* ent_head; + void* entity; +} ni_event; + +PUBLIC ni_event* ni_event_new(char* uri, + k_hashtable* evt_head, + k_hashtable* ent_head, + char* entity); +PUBLIC ni_event* ni_event_dup( ni_event* res); +PUBLIC void ni_event_delete(ni_event* res); +PUBLIC void ni_event_show( ni_event* res, char* text); + +/* -------------------------------------------------------------------------- */ + +PUBLIC ni_event* ni_res_to_evt(ni_resource* res); + +/* -------------------------------------------------------------------------- */ + +typedef int (*ni_handles_resource)(char*); +typedef void (*ni_sync_resource )(ni_resource*); + +PUBLIC void ni_register_driver(char* name, + ni_handles_resource handles_resource, + ni_sync_resource sync_resource); + +/* -------------------------------------------------------------------------- */ + +PUBLIC ni_event* ni_get_request_headers( char* header); +PUBLIC ni_event* ni_get_response_headers(char* header); +PUBLIC char* ni_get_headers( char* header, k_hashtable*, k_hashtable*); +PUBLIC void ni_fix_http_headers(k_hashtable* ent_head); +PUBLIC void ni_fix_ni_headers(k_hashtable* ent_head, int methead); +PUBLIC void ni_response(ni_event* evt, + char* to, + char* method, + char* protocol, + char* connection, + k_channel* chan); +PUBLIC void ni_request(ni_event* evt, + char* to, + char* method, + k_channel* chan); + +/* -------------------------------------------------------------------------- */ + +#endif + diff --git a/src/ni/headers.c b/src/ni/headers.c deleted file mode 100644 index 391fcc2..0000000 --- a/src/ni/headers.c +++ /dev/null @@ -1,523 +0,0 @@ - -/* -}{----------------------------------------------------------------------- */ - -#include -#undef PUBLIC -#define PUBLIC EXPORT -#include - -/* -}{---- ------------------------------------------------------------------ */ - -static k_hashtable* entity_headers; - -/* -}{---- ------------------------------------------------------------------ */ - -#define TMPBUFSIZE 4096 -static char tmpbuf[TMPBUFSIZE]; - -/* -}{----------------------------------------------------------------------- */ - -static char* get_request( char* header, k_hashtable*, k_hashtable*); -static char* get_response(char* header, k_hashtable*, k_hashtable*); -static char* get_val(char** atp); -static char* end_of_val(char* at); -static void fix_keepalive(k_hashtable* evt_head); -static void fix_cache_control(k_hashtable* ent_head); -static void fix_uri(k_hashtable* ent_head); -static void fix_subscribe(k_hashtable*, k_hashtable*); - -/* -}{----------------------------------------------------------------------- */ - -#define WHITESPACEH " \t" -#define WHITESPACEV "\012\015" -#define WHITESPACE WHITESPACEH WHITESPACEV - -EXPORT ni_event* ni_get_request_headers(char* header) -{ - k_hashtable* evt_head=k_hashtable_new("vHeaders/get_req_hdrs", 1); - k_hashtable* ent_head=k_hashtable_new("nHeaders/get_req_hdrs", 1); - k_hashtable_put(ent_head, "", header); - - char* h=get_request(header, evt_head, ent_head); - if(!h){ - k_hashtable_delete(evt_head); - k_hashtable_delete(ent_head); - return 0; - } - - h=ni_get_headers(h, evt_head, ent_head); - if(!h){ - k_hashtable_delete(evt_head); - k_hashtable_delete(ent_head); - return 0; - } - - fix_keepalive(evt_head); - fix_cache_control(ent_head); - fix_uri(ent_head); - fix_subscribe(evt_head, ent_head); - - ni_event* evq=ni_event_new(0, evt_head, ent_head, 0); - - return evq; -} - -EXPORT ni_event* ni_get_response_headers(char* header) -{ - k_hashtable* evt_head=k_hashtable_new("vHeaders/get_resp_hdrs", 1); - k_hashtable* ent_head=k_hashtable_new("nHeaders/get_resp_hdrs", 1); - k_hashtable_put(ent_head, "", header); - - char* h=get_response(header, evt_head, ent_head); - if(!h){ - k_hashtable_delete(evt_head); - k_hashtable_delete(ent_head); - return 0; - } - - h=ni_get_headers(h, evt_head, ent_head); - if(!h){ - k_hashtable_delete(evt_head); - k_hashtable_delete(ent_head); - return 0; - } - - ni_event* evt=ni_event_new(0, evt_head, ent_head, 0); - - return evt; -} - -EXPORT char* ni_get_headers(char* header, - k_hashtable* evt_head, - k_hashtable* ent_head) -{ - char* at=header; - char* tag; - char* val; - while(*at){ - - tag=at; - at=strpbrk(at, WHITESPACE); - if(!at || at==tag) return 0; - char* e=at; - val=get_val(&at); - *e=0; - - if(strlen(val) > 2048) return 0; - - k_hashtable* h; - h=k_hashtable_get(entity_headers, tag)? ent_head: evt_head; - if(h){ - char* old=k_hashtable_get(h, tag); - if(!old) k_hashtable_set(h, tag, val); - } - } - return at; -} - -EXPORT void ni_fix_http_headers(k_hashtable* ent_head) -{ - if(k_hashtable_is(ent_head, "Status:", "260")){ - char* crn=k_hashtable_get(ent_head, "Content-Range:"); - char* clg=k_hashtable_get(ent_head, "Content-Length-Given:"); - if(crn || clg){ - k_hashtable_set(ent_head, "Status:", "206"); - k_hashtable_set(ent_head, "Status-Text:", "Partial Content"); - } - else{ - k_hashtable_set(ent_head, "Status:", "200"); - k_hashtable_set(ent_head, "Status-Text:", "OK"); - } - } - k_hashtable_remove(ent_head, "URI:"); - k_hashtable_remove(ent_head, "Method:"); - k_hashtable_remove(ent_head, "From:"); - k_hashtable_remove(ent_head, "Content-Length-Given:"); - k_hashtable_remove(ent_head, "Last-Modified-Epoch:"); - - char* cc=k_hashtable_get(ent_head, "Cache-Control:"); - if(cc && strstr(cc, "no-cache")){ - k_hashtable_set(ent_head, "Pragma:", "no-cache"); - } -} - -EXPORT void ni_fix_ni_headers(k_hashtable* ent_head, int methead) -{ - if(methead && (k_hashtable_is(ent_head, "Status:", "200") || - k_hashtable_is(ent_head, "Status:", "206") )){ - - k_hashtable_set(ent_head, "Status:", "260"); - k_hashtable_set(ent_head, "Status-Text:", "Headers Only"); - } - k_hashtable_remove(ent_head, "Method:"); - k_hashtable_remove(ent_head, "Sub-To:"); - k_hashtable_remove(ent_head, "Via:"); - k_hashtable_set( ent_head, "From:", ni_hostname()); - - char* uri=k_hashtable_get(ent_head, "URI:"); - if(*uri=='.'){ - snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", ni_hostname(), uri+2); - k_hashtable_put_dup(ent_head, "URI:", tmpbuf); - } -} - -EXPORT void ni_response(ni_event* evt, - char* to, - char* method, - char* protocol, - char* connection, - k_channel* chan) -{ - int L=0; - snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc_relative(0)); - k_hashtable_put_dup(evt->evt_head, "Date:", tmpbuf); - k_hashtable_set( evt->evt_head, "Server:", k_version); - if(connection) - k_hashtable_put_dup(evt->evt_head, "Connection:", connection); - - int status =k_hashtable_get_int(evt->ent_head, "Status:"); - char* statustext=k_hashtable_get( evt->ent_head, "Status-Text:"); - int datalength=k_hashtable_get_int(evt->ent_head, "Content-Length:"); - int constant =k_hashtable_is( evt->ent_head, "CUX:", "C"); - - char* buf =tmpbuf; - int bufsize=TMPBUFSIZE; - int ln=0; - - ln+=snprintf(buf+ln, bufsize-ln, "%s %d %s" CRLF, - protocol, status, statustext); - if(ln>=bufsize) return; - - static char* exheaders[]={ "Status:", "Status-Text:", - "Protocol:", "CUX:", 0 }; - - ln+=k_hashtable_snprintf_x(evt->evt_head, buf+ln,bufsize-ln, exheaders); - if(ln>=bufsize) return; - - ln+=k_hashtable_snprintf_x(evt->ent_head, buf+ln,bufsize-ln, exheaders); - if(ln>=bufsize) return; - - ln+=snprintf(buf+ln, bufsize-ln, CRLF); - if(ln>=bufsize) return; - - char* head=k_strdup(buf); - if(L) k_log_out("Actual response headers:\n%s", head); - k_channel_send(chan, head, ln, FREE_ON_SENT); - - if(evt->entity && datalength){ - k_channel_send(chan, evt->entity, datalength, !constant); - } - else{ - datalength=0; - if(!constant) k_free(evt->entity); - } - k_log_out("%s %s %s %d %d", to, method, evt->uri, status, datalength); -} - -EXPORT void ni_request(ni_event* evt, char* to, char* method, k_channel* chan) -{ - k_hashtable* sub=evt->ent_head; - - int ln=0; - int bufsize=TMPBUFSIZE; - - ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s //%s ni/0.5" CRLF, method, to); - if(ln>=bufsize) return; - - ln+=k_hashtable_snprintf(sub, tmpbuf+ln, bufsize-ln); - if(ln>=bufsize) return; - - ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF); - if(ln>=bufsize) return; - - char* head=k_strdup(tmpbuf); - if(0) k_log_out("Actual request headers:\n%s", head); - k_channel_send(chan, head, ln, FREE_ON_SENT); -} - -/* -}{----------------------------------------------------------------------- */ - -char* get_request(char* header, k_hashtable* evt_head, k_hashtable* ent_head) -{ - char* at=header; - char* method=at; - at=strpbrk(at, WHITESPACEH); - if(!at) return 0; - *at++=0; - - k_hashtable_set(ent_head, "Method:", method); - - char* file=0; - char* host=0; - if(strcmp(method, "PING")){ - - at+=strspn(at, WHITESPACEH); - file=at; - at=strpbrk(at, WHITESPACEH); - if(!at) return 0; - *at++=0; - if(strlen(file) > 1024 ) return 0; - - if(!strncmp(file, "http://", 7)){ - char* s=file+7; - if(!*s || *s=='/') return 0; - char* e=strchr(s, '/'); - if(!e) return 0; - host=s; - *e++=0; - file=e; - } - else - if(*file=='/') file++; - else return 0; - - if(*file=='/'){ - char* s=file+1; - if(!*s || *s=='/') return 0; - char* e=strchr(s, '/'); - if(!e) return 0; - host=s; - *e++=0; - file=e; - } - } - if(file) k_hashtable_set(evt_head, "File:", file); - if(host) k_hashtable_set(evt_head, "Host:", host); - - at+=strspn(at, WHITESPACEH); - char* protocol=at; - at=strpbrk(at, WHITESPACE); - if(!at) at=protocol+strlen(protocol); - else *at++=0; - - k_hashtable_set(evt_head, "Protocol:", protocol); - - at+=strspn(at, WHITESPACE); - return at; -} - -char* get_response(char* header, k_hashtable* evt_head, k_hashtable* ent_head) -{ - char* at=header; - char* protocol=at; - at=strpbrk(at, WHITESPACEH); - if(!at) return 0; - *at++=0; - - k_hashtable_set(evt_head, "Protocol:", protocol); - - at+=strspn(at, WHITESPACEH); - char* status=at; - at=strpbrk(at, WHITESPACEH); - if(!at) return 0; - *at++=0; - - at+=strspn(at, WHITESPACEH); - char* statustext=at; - at=strpbrk(at, WHITESPACEV); - if(!at) return 0; - *at++=0; - - k_hashtable_set(ent_head, "Status:", status); - k_hashtable_set(ent_head, "Status-Text:", statustext); - - at+=strspn(at, WHITESPACE); - return at; -} - -char* get_val(char** atp) -{ - char* at=*atp; - char* val=at; - - val+=strspn(val, WHITESPACEH); - val+=strspn(val, WHITESPACEV); - - char* eov=end_of_val(at); - if(eov0; - if(localhostdns || localhostni || dotdotnumber){ - host="."; - } - } - else{ - host="."; - } - if(file){ - k_string_url_decode(file); - snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", host, file); - k_hashtable_put_dup(ent_head, "Sub-To:", tmpbuf); - k_hashtable_set( ent_head, "Sub-Type:", "Original"); - } -} - -void init_headers(void) -{ - entity_headers =k_hashtable_new("Entity Headers", 1); - - k_hashtable_set(entity_headers, "URI:", (void*)1); - k_hashtable_set(entity_headers, "From:", (void*)1); - k_hashtable_set(entity_headers, "To:", (void*)1); - k_hashtable_set(entity_headers, "Via:", (void*)1); - k_hashtable_set(entity_headers, "Sub-To:", (void*)1); - k_hashtable_set(entity_headers, "Sub-Type:", (void*)1); - k_hashtable_set(entity_headers, "Method:", (void*)1); - k_hashtable_set(entity_headers, "Status:", (void*)1); - k_hashtable_set(entity_headers, "Status-Text:", (void*)1); - k_hashtable_set(entity_headers, "Last-Modified-Epoch:", (void*)1); - k_hashtable_set(entity_headers, "CUX:", (void*)1); - - k_hashtable_set(entity_headers, "Range:", (void*)1); - k_hashtable_set(entity_headers, "If-Modified-Since:", (void*)1); - k_hashtable_set(entity_headers, "If-None-Match:", (void*)1); - k_hashtable_set(entity_headers, "Cache-Control:", (void*)1); - k_hashtable_set(entity_headers, "Pragma:", (void*)1); - - k_hashtable_set(entity_headers, "Content-Length:", (void*)1); - k_hashtable_set(entity_headers, "Content-Type:", (void*)1); - k_hashtable_set(entity_headers, "Content-Encoding:", (void*)1); - k_hashtable_set(entity_headers, "Content-Location:", (void*)1); - k_hashtable_set(entity_headers, "Content-MD5:", (void*)1); - k_hashtable_set(entity_headers, "Content-Language:", (void*)1); - k_hashtable_set(entity_headers, "Content-Range:", (void*)1); - k_hashtable_set(entity_headers, "Last-Modified:", (void*)1); - k_hashtable_set(entity_headers, "ETag:", (void*)1); - k_hashtable_set(entity_headers, "Expires:", (void*)1); - - k_hashtable_set(entity_headers, "Allow:", (void*)1); -} - -void drop_entity_headers(k_hashtable* ent_head) -{ - k_hashtable_remove(ent_head, "Content-Length:"); - k_hashtable_remove(ent_head, "Content-Range:"); - k_hashtable_remove(ent_head, "Content-Type:"); - k_hashtable_remove(ent_head, "Content-Encoding:"); - k_hashtable_remove(ent_head, "Content-Location:"); - k_hashtable_remove(ent_head, "Last-Modified:"); -#ifdef DO_THESE_ONES_TOO - k_hashtable_remove(ent_head, "Allow:"); - k_hashtable_remove(ent_head, "Content-Language:"); - k_hashtable_remove(ent_head, "Content-MD5:"); - k_hashtable_remove(ent_head, "Expires:"); -#endif -} - -void fill_headers(k_hashtable* ent_head, - char* status, - char* statustext, - char* uri, - time_t modifitime, - int datalength, - char* mimetype, - char* encoding, - int nocache) -{ - if(status){ - k_hashtable_put_dup(ent_head, "Status:", status); - k_hashtable_put_dup(ent_head, "Status-Text:", statustext); - } - if(uri){ - k_hashtable_put_dup(ent_head, "URI:", uri); - } - if(modifitime>=0){ - snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc(modifitime)); - k_hashtable_put_dup(ent_head, "Last-Modified:", tmpbuf); - } - if(datalength>=0){ - snprintf(tmpbuf, TMPBUFSIZE, "%d", datalength); - k_hashtable_put_dup(ent_head, "Content-Length:", tmpbuf); - } - if(mimetype){ - k_hashtable_put_dup(ent_head, "Content-Type:", mimetype); - } - if(encoding){ - k_hashtable_put_dup(ent_head, "Content-Encoding:", encoding); - } - if(nocache==1){ - k_hashtable_put_dup(ent_head, "Cache-Control:", - "no-cache,no-store"); - } - else - if(nocache==0){ - long maxage=31449600; - snprintf(tmpbuf, TMPBUFSIZE, "max-age=%ld", maxage); - char* maxages=k_time_to_rfc_relative(maxage); - k_hashtable_put_dup(ent_head, "Cache-Control:", tmpbuf); - k_hashtable_put_dup(ent_head, "Expires:", maxages); - } - else - if(nocache== -1){ - k_hashtable_remove(ent_head, "Cache-Control:"); - k_hashtable_remove(ent_head, "Expires:"); - } -} - -/* -}{---- ------------------------------------------------------------------ */ - diff --git a/src/ni/ni.c b/src/ni/ni.c deleted file mode 100644 index fae4db1..0000000 --- a/src/ni/ni.c +++ /dev/null @@ -1,824 +0,0 @@ - -/* -}{----------------------------------------------------------------------- */ - -#include -#undef PUBLIC -#define PUBLIC EXPORT -#include - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT n_object* n_object_new(char* s) -{ - return 0; -} - -EXPORT void n_commit(n_object* o) -{ -} - -EXPORT n_object* n_see(n_object* o, char* uid) -{ - return 0; -} - -EXPORT char* n_to_string(n_object* o) -{ - return 0; -} - -EXPORT char* n_uid(n_object* o) -{ - return 0; -} - -EXPORT char* n_header(n_object* o, char* name) -{ - return 0; -} - -EXPORT k_hashtable* n_headers(n_object* o) -{ - return 0; -} - -EXPORT k_hashtable* n_content(n_object* o) -{ - return 0; -} - -/* -}{---- ------------------------------------------------------------------ */ - -#define TMPBUFSIZE 4096 -static char tmpbuf[TMPBUFSIZE]; -static char* hostname; -static k_hashtable* resources; - -/* -}{---- ------------------------------------------------------------------ */ - -typedef struct ni_driver{ - char* name; - ni_handles_resource handles_resource; - ni_sync_resource sync_resource; -} ni_driver; - -/* -}{---- From headers.c --------------------------------------------------- */ - -extern void init_headers(void); -extern void drop_entity_headers(k_hashtable* ent_head); -extern void fill_headers(k_hashtable* ent_head, - char* status, - char* statustext, - char* uri, - time_t modifitime, - int datalength, - char* mimetype, - char* encoding, - int nocache); - -/* -}{---- ------------------------------------------------------------------ */ - -static void incoming_request(ni_event* evq); -static ni_resource* ensure_res(char* pub); -static void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub); -static void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub); -static k_hashtable* get_this(k_hashtable*, char*, k_hashtable*); -static k_hashtable* get_using(k_hashtable* curr, char* tag, char* val); -static void post_to_driver(char* pub, ni_event* evq); -static void incoming_resource(ni_event* evt); -static void test_pub_tos(ni_resource* res, ni_event* evt, int entityok); -static int satisfiable(k_hashtable*, ni_resource*, ni_event*, int); -static void update_pubcache(int, k_hashtable**, k_hashtable*, k_hashtable*); -static int sub_less(k_hashtable* sub1, k_hashtable* sub2); -static void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh); -static int sub_ok(k_hashtable* sub); -static int range_ok(char* range, char* conrange); -static void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh); -static void merge_entity_range(ni_resource* res, ni_event* evt); -static void respond( k_hashtable* sub, ni_resource* res, ni_event* evt); -static void respond_ok(k_hashtable* sub, ni_event* evv); -static void respond_nf(k_hashtable* sub, ni_event* evv); -static void* entity_to_octets(k_hashtable* ent_head, void* entity); -static char* handled_by(char* pub); -static void call_sync_resource(ni_resource* res); -static ni_driver* ni_driver_new(char* name, - ni_handles_resource handles_resource, - ni_sync_resource sync_resource); - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT int ni_module_loaded(void) -{ - resources=k_hashtable_new("Resources", 0); - - init_headers(); - - k_log_out("NI initialised"); - return 1; -} - -EXPORT void ni_module_tick(void) -{ -} - -EXPORT int ni_module_event(void* data) -{ - ni_event* evt=data; - - if(!k_hashtable_get(evt->ent_head, "Status:")){ - - incoming_request(evt); - } - else{ - incoming_resource(evt); - } - return 1; -} - -/* -}{---- ------------------------------------------------------------------ */ - -void incoming_request(ni_event* evq) -{ - int L=1; - if(L) ni_event_show(evq, "NI got request event"); - - k_hashtable* sub=evq->ent_head; - char* uri =k_hashtable_get(sub, "URI:"); - char* pub =k_hashtable_get(sub, "Sub-To:"); if(!pub) return; - int styor=k_hashtable_isi(sub, "Sub-Type:", "Original"); - char* via =k_hashtable_get(sub, "Via:"); - char* from =k_hashtable_get(sub, "From:"); - if(L) k_log_out("------------------ %s", pub); - - int nocache=k_hashtable_isi(sub, "Cache-Control:", "no-cache"); - if(nocache){ - k_hashtable_remove( sub, "Cache-Control:"); - k_hashtable_set( sub, "If-Modified-Since:", "0"); - } - - if(!from){ - ni_resource* ses=k_hashtable_get(resources, uri); - if(ses) ensure_sub_entry(ses->ent_head, sub); - if(ses) if(L) ni_resource_show(ses, "Subscribing Resource:"); - if(styor && via){ - post_to_driver(pub, evq); - return; - } - } - - ni_resource* res=ensure_res(pub); - if(L) ni_resource_show(res, "Publishing Resource:"); - - k_hashtable* pubcache=0; - int sat=satisfiable(sub, res, 0, 0); - update_pubcache(sat, &pubcache, res->ent_head, sub); - if(sat){ - if(L) k_log_out("Memory cache hit for %s", pub); - respond(k_hashtable_dup(sub), res, 0); - ni_event_delete(evq); - } - else{ - ensure_pub_entry(res->ent_head, sub); - if(L) ni_resource_show(res, "Pending Resource:"); - if(pubcache){ - evq->ent_head=pubcache; - post_to_driver(pub, evq); - k_hashtable_delete(sub); - } - else{ - if(L) k_log_out("In-progress Pub-Cache sufficient"); - ni_event_delete(evq); - } - } -} - -ni_resource* ensure_res(char* pub) -{ - ni_resource* res=k_hashtable_get(resources, pub); - if(!res){ - res=ni_resource_new(pub, k_hashtable_new("resHeaders", 1), 0); - k_hashtable_set(resources, pub, res); - } - return res; -} - -void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub) -{ - char* tag="Sub-To:"; - k_hashtable* sup=get_this(ent_head, tag, sub); - if(!sup){ - k_hashtable* sup=k_hashtable_dup(sub); - char* uri=k_hashtable_extract(sup, "Sub-To:"); - k_hashtable_put( sup, "URI:", uri); - k_hashtable_remove( sup, "Sub-Type:"); - k_hashtable_sub(ent_head, tag, sup); - } - else{ - k_hashtable_remove(sup, "Range:"); - k_hashtable_remove(sup, "Content-Range:"); - k_hashtable_remove(sup, "Status:"); - k_hashtable_remove(sup, "Status-Cache:"); - char* mth=k_strdup(k_hashtable_get(sub, "Method:")); - char* via=k_strdup(k_hashtable_get(sub, "Via:")); - char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:")); - char* rng=k_strdup(k_hashtable_get(sub, "Range:")); - if(mth) k_hashtable_put(sup, "Method:", mth); - if(via) k_hashtable_put(sup, "Via:", via); - if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims); - if(rng) k_hashtable_put(sup, "Range:", rng); - } -} - -void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub) -{ - char* tag="Pub-To:"; - k_hashtable* sup=get_this(ent_head, tag, sub); - if(!sup){ - k_hashtable* sup=k_hashtable_dup(sub); - k_hashtable_remove(sup, "Sub-To:"); - k_hashtable_remove(sup, "Sub-Type:"); - k_hashtable_sub(ent_head, tag, sup); - } - else { - k_hashtable_remove(sup, "Method:"); - k_hashtable_remove(sup, "If-Modified-Since:"); - k_hashtable_remove(sup, "Cache-Control:"); - k_hashtable_remove(sup, "Update:"); - char* mth=k_strdup(k_hashtable_get(sub, "Method:")); - char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:")); - char* ccn=k_strdup(k_hashtable_get(sub, "Cache-Control:")); - char* upd=k_strdup(k_hashtable_get(sub, "Update:")); - if(mth) k_hashtable_put(sup, "Method:", mth); - if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims); - if(ccn) k_hashtable_put(sup, "Cache-Control:", ccn); - if(upd) k_hashtable_put(sup, "Update:", upd); - } -} - -k_hashtable* get_this(k_hashtable* ent_head, char* pubsub, k_hashtable* try) -{ - k_hashtable* curr=k_hashtable_get(ent_head, pubsub); - if(!curr) return 0; - - char* tag; - char* val; - - tag="From:"; - val=k_hashtable_get(try, tag); - if(val) return get_using(curr, tag, val); - - tag="URI:"; - val=k_hashtable_get(try, tag); - if(val) return get_using(curr, tag, val); - - return 0; -} - -k_hashtable* get_using(k_hashtable* curr, char* tag, char* val) -{ - k_hashtable* c; - for(c=curr; c; c=c->next) if(k_hashtable_is(c, tag, val)) return c; - return c; -} - -/* -}{---- ------------------------------------------------------------------ */ - -void incoming_resource(ni_event* evt) -{ - int L=0; - if(L) ni_event_show(evt, "ni got resource incoming event"); - - ni_resource* res=k_hashtable_get(resources, evt->uri); - int fullconst=res && k_hashtable_is(res->ent_head, "Status:", "200") && - k_hashtable_is(res->ent_head, "CUX:", "C"); - - if(fullconst){ - k_log_err("Resource is complete and Constant"); - ni_event_delete(evt); - return; - } - if(!res) res=ensure_res(evt->uri); - - k_hashtable* reseh=res->ent_head; - k_hashtable* evteh=evt->ent_head; - int okfull =k_hashtable_is(evteh, "Status:", "200"); - int partial =k_hashtable_is(evteh, "Status:", "206"); - int headonly=k_hashtable_is(evteh, "Status:", "260");/* - int updated =k_hashtable_is(evteh, "Status:", "266");*/ - int notmod =k_hashtable_is(evteh, "Status:", "304"); - int notfound=k_hashtable_is(evteh, "Status:", "404"); - - int entityok= (okfull || partial || notmod); - int entityev=!(headonly || notmod || notfound); - int entityin=!!evt->entity; - int entityon=!!res->entity; - - if(!entityev){ - } - if(okfull || !entityon){ - k_hashtable_merge(reseh, evteh); - if(okfull) k_hashtable_remove(reseh, "Content-Range:"); - } - else{ - merge_non_entity_headers(reseh, evteh); - } - - fix_via_subs(evteh, reseh); - - if(entityin){ - if(okfull || (partial && !entityon)){ - if(res->entity!=evt->entity){ - if(!k_hashtable_is(reseh, "CUX:", "C")){ - k_free(res->entity); - } - res->entity=evt->entity; - } - } - else - if(partial && entityon){ - merge_entity_range(res, evt); - } - } - - if(L) ni_resource_show(res, "updated resource - sync and try pubs:"); - - call_sync_resource(res); - - test_pub_tos(res, evt, entityok); - - evt->entity=0; - ni_event_delete(evt); - - if(L) ni_resource_show(res, "resource after ni:"); -} - -void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh) -{ - char* from=k_hashtable_get(evteh, "From:"); - if(!from) return; - k_hashtable* subs=k_hashtable_get(reseh, "Sub-To:"); - k_hashtable* sub; - for(sub=subs; sub; sub=sub->next){ - if(!k_hashtable_is(sub, "Via:", from)) continue; - int st=k_hashtable_get_int(evteh, "Status:"); - char* cr=k_hashtable_get_dup(evteh, "Content-Range:"); - if(st!=304) k_hashtable_put_int(sub, "Status:", st); - if(st==200) k_hashtable_remove( sub, "Content-Range:"); - else - if(cr) k_hashtable_put(sub, "Content-Range:", cr); - if(sub_ok(sub)) k_hashtable_set(sub, "Status-Cache:", "OK"); - } -} - -void test_pub_tos(ni_resource* res, ni_event* evt, int entityok) -{ - k_hashtable* keeps=0; - k_hashtable* sub=k_hashtable_extract(res->ent_head, "Pub-To:"); - while(sub){ - k_hashtable* subnext=sub->next; - sub->next=0; - int keep=1; - int sat=satisfiable(sub, res, evt, entityok); - update_pubcache(sat, 0, res->ent_head, sub); - if(sat){ - respond(k_hashtable_dup(sub), res, evt); - if(!k_hashtable_get(sub, "Update:")) keep=0; - } - if(keep){ - sub->next=keeps; - keeps=sub; - } - else{ - k_hashtable_delete(sub); - } - sub=subnext; - } - sub=keeps; - while(sub){ - k_hashtable* subnext=sub->next; - k_hashtable_sub(res->ent_head, "Pub-To:", sub); - sub=subnext; - } -} - -int satisfiable(k_hashtable* sub, - ni_resource* res, - ni_event* evt, - int entityok) -{ - int L=0; - int get =k_hashtable_is( sub, "Method:", "GET"); - int head =k_hashtable_is( sub, "Method:", "HEAD"); - int dosub=k_hashtable_is( sub, "Method:", "SUB"); - int unsub=k_hashtable_is( sub, "Method:", "UNSUB"); - int full=!k_hashtable_isi(sub, "Cache-Control:", "no-full"); - int updt =k_hashtable_isi(sub, "Update:", "changes"); - char* ims =k_hashtable_get(sub, "If-Modified-Since:"); - char* range=k_hashtable_get(sub, "Range:"); - - int getsub =get || dosub; - int getrange=getsub && range; - - k_hashtable* reseh=res->ent_head; - int gotall= k_hashtable_is( reseh, "Status:", "200"); - int gotrange= k_hashtable_is( reseh, "Status:", "206"); - int gothead= k_hashtable_is( reseh, "Status:", "260"); - int gotupdated=evt && - k_hashtable_is(evt->ent_head, "Status:", "266"); - int notfound= k_hashtable_is( reseh, "Status:", "404"); - int constant= k_hashtable_is( reseh, "CUX:", "C" ); - char* conrange= k_hashtable_get(reseh, "Content-Range:"); - - if(unsub) return 0; - if(notfound) return 1; - - int gotany=(gothead || gotrange || gotall); - int snapok=(constant || !ims || entityok); - - int sat= - (full && - ((getsub && gotall && snapok) || - (getrange && gotrange && range_ok(range, conrange) && snapok) || - (head && gotany ) )) - || - (updt && - ((dosub && gotupdated))); - - if(L) k_log_out("satisfiable %d", sat); - return sat; -} - -void update_pubcache(int sat, - k_hashtable** pubcachep, - k_hashtable* reseh, - k_hashtable* sub) -{ - if(!sat){ if(pubcachep){ - k_hashtable* pubcache; - pubcache=k_hashtable_get(reseh, "Pub-Cache:"); - if(!pubcache || sub_less(pubcache, sub)){ - if(!pubcache){ - pubcache=k_hashtable_dup(sub); - k_hashtable_sub(reseh, "Pub-Cache:", pubcache); - } - else{ - k_hashtable_merge(pubcache, sub); - } - k_hashtable_remove(pubcache, "URI:"); - k_hashtable_remove(pubcache, "Sub-Type:"); - *pubcachep=k_hashtable_dup(pubcache); - k_hashtable_set(*pubcachep, "Sub-Type:", "Cache"); - } - }} - else{ if(!pubcachep){ - k_hashtable* pubcache; - pubcache=k_hashtable_get(reseh, "Pub-Cache:"); - if(!sub_less(sub, pubcache)){ - k_hashtable_remove(pubcache, "Method:"); - k_hashtable_remove(pubcache, "If-Modified-Since:"); - } - }} -} - -int sub_ok(k_hashtable* sub) -{ - char* gotresp =k_hashtable_get(sub, "Status:"); - if(!gotresp) return 0; - int notfound=k_hashtable_is( sub, "Status:", "404"); - if(notfound) return 0; - int gotall =k_hashtable_is( sub, "Status:", "200"); - int gotrange=k_hashtable_is( sub, "Status:", "206"); - int gothead= k_hashtable_is( sub, "Status:", "260"); - int doget =k_hashtable_is( sub, "Method:", "GET"); - int dohead =k_hashtable_is( sub, "Method:", "HEAD"); - int dosub =k_hashtable_is( sub, "Method:", "SUB"); - char* range =k_hashtable_get(sub, "Range:"); - char* conrange=k_hashtable_get(sub, "Content-Range:"); - - int dogetsub=doget || dosub; - int dogetrange=dogetsub && range; - int gotany =(gothead || gotrange || gotall); - - return (dogetsub && gotall ) || - (dogetrange && gotrange && range_ok(range, conrange)) || - (dohead && gotany ); -} - -int sub_less(k_hashtable* sub1, k_hashtable* sub2) -{ - int L=0; - if(L) k_log_out("sub_less sub1:"); - if(L) k_hashtable_show_chars(sub1); - if(L) k_log_out("sub_less sub2:"); - if(L) k_hashtable_show_chars(sub2); - char* mth1 =k_hashtable_get(sub1, "Method:"); - int head1=k_hashtable_is( sub1, "Method:", "HEAD"); - int get2 =k_hashtable_is( sub2, "Method:", "GET"); - char* ims1 =k_hashtable_get(sub1, "If-Modified-Since:"); - char* ims2 =k_hashtable_get(sub2, "If-Modified-Since:"); - int full=!k_hashtable_isi(sub2, "Cache-Control:", "no-full"); - return full && ((!mth1) || (head1 && get2) || (!ims1 && ims2)); -} - -int range_ok(char* range, char* conrange) -{ - k_log_out("range_ok not implemented: %s vs %s", range, conrange); - return 0; -} - -void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh) -{ -} - -void merge_entity_range(ni_resource* res, ni_event* evt) -{ - k_log_out("merge_entity_range not implemented yet"); -} - -/* -}{---- ------------------------------------------------------------------ */ - -void respond(k_hashtable* sub, ni_resource* res, ni_event* evt) -{ - int updated=evt && k_hashtable_is(evt->ent_head, "Status:", "266"); - ni_event* evv=updated? ni_event_dup(evt): - ni_res_to_evt(res); - int L=0; - if(L) ni_event_show(evv, "respond"); - - k_hashtable_remove(evv->ent_head, "Permit:"); - k_hashtable_remove(evv->ent_head, "Sub-To:"); - k_hashtable_remove(evv->ent_head, "Pub-To:"); - k_hashtable_remove(evv->ent_head, "Pub-Cache:"); - k_hashtable_sub( evv->ent_head, "Pub-To:", sub); - - int nf; - nf=k_hashtable_is( evv->ent_head, "Status:", "404"); - if(!nf) respond_ok(sub, evv); - else respond_nf(sub, evv); -} - -void respond_ok(k_hashtable* sub, ni_event* evv) -{ - char* status=0; - char* statustext=0; - int datalength= -1; - int nocache=0; - k_hashtable* ent_head=evv->ent_head; - - time_t modifitime=k_hashtable_get_int(ent_head, "Last-Modified-Epoch:"); - char* modistring=k_hashtable_get( ent_head, "Last-Modified:"); - if(!modifitime){ - modifitime=k_time_from_rfc(modistring); - } - char* imss=k_hashtable_get(sub, "If-Modified-Since:"); - time_t imst=k_time_from_rfc(imss); - - if(modifitime== -1 || imst== -1 || modifitime > imst){ - if(k_hashtable_is(sub, "Method:", "HEAD")){ - evv->entity=0; - } - if(!k_hashtable_is(ent_head, "CUX:", "C")){ - evv->entity=entity_to_octets(ent_head, evv->entity); - nocache=1; - } - } - else{ - status="304"; - statustext="Not Modified"; - modifitime= -1; - nocache= -1; - evv->entity=0; - drop_entity_headers(ent_head); - } - - fill_headers(ent_head, status, statustext, 0, - modistring? -1: modifitime, - datalength, 0, 0, nocache); - - char* pub =k_hashtable_get(sub, "URI:"); - int L=0; - if(L) ni_event_show(evv, "respond_ok"); - post_to_driver(pub, evv); -} - -void respond_nf(k_hashtable* sub, ni_event* evv) -{ - fill_headers(evv->ent_head, "404", "File Not Found", 0, -1, 0, 0, 0, 1); - char* pub =k_hashtable_get(sub, "URI:"); - post_to_driver(pub, evv); -} - -void post_to_driver(char* pub, ni_event* evq) -{ - char* driver=handled_by(pub); - if(0) k_log_out("Passing %s on to %s", pub, driver); - if(0) ni_event_show(evq, "Post to Driver:"); - k_event_post(driver, evq); -} - -void* entity_to_octets(k_hashtable* ent_head, void* entity) -{ - if(!entity) return 0; - size_t size=k_hashtable_get_int(ent_head, "Content-Length:"); - return k_memdup(entity, size); -} - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT char* ni_hostname() -{ - return hostname? hostname: "not set"; -} - -EXPORT void ni_hostname_set(char* name) -{ - k_free(hostname); - hostname=k_strdup(name); -} - -/* -}{---- ------------------------------------------------------------------ */ - -static ni_driver* npdriver; -static ni_driver* moddriver; - -char* handled_by(char* pub) -{ - if(moddriver->handles_resource(pub)) return moddriver->name; - return "np"; -} - -void call_sync_resource(ni_resource* res) -{ - if(moddriver->handles_resource(res->uri)) moddriver->sync_resource(res); - else npdriver->sync_resource(res); -} - -ni_driver* ni_driver_new(char* name, - ni_handles_resource handles_resource, - ni_sync_resource sync_resource) -{ - ni_driver* driver=k_malloc(sizeof(ni_driver)); - driver->name =name; - driver->handles_resource=handles_resource; - driver->sync_resource =sync_resource; - return driver; -} - -EXPORT void ni_register_driver(char* name, - ni_handles_resource handles_resource, - ni_sync_resource sync_resource) -{ - ni_driver* d=ni_driver_new(name, handles_resource, sync_resource); - if(!strcmp(name, "np")) npdriver=d; - else moddriver=d; -} - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT ni_resource* ni_resource_new(char* uri, - k_hashtable* ent_head, - char* entity) -{ - char* urih=k_hashtable_get(ent_head, "URI:"); - if(urih) uri=urih; - else - if(uri) k_hashtable_put_dup(ent_head, "URI:", uri); - - ni_resource* res=k_malloc(sizeof(ni_resource)); - res->uri =(uri? k_strdup(uri): 0); - res->ent_head=ent_head; - res->entity =entity; - return res; -} - -EXPORT ni_resource* ni_resource_dup(ni_resource* res) -{ - ni_resource* rep=k_malloc(sizeof(ni_resource)); - rep->uri =k_strdup( res->uri); - rep->ent_head=k_hashtable_dup(res->ent_head); - rep->entity = res->entity; - return rep; -} - -EXPORT void ni_resource_delete(ni_resource* res) -{ - if(!res) return; - if(res->entity && res->ent_head){ - int constant=k_hashtable_is(res->ent_head, "CUX:", "C"); - if(!constant) k_free(res->entity); - } - k_hashtable_delete(res->ent_head); - k_free( res->uri); - k_free( res); -} - -static char* excto[]={ "Permit:", "Sub-To:", "Pub-To:", 0 }; -static char* perto[]={ "Permit:", 0 }; -static char* subto[]={ "Sub-To:", 0 }; -static char* pubto[]={ "Pub-To:", 0 }; - -EXPORT void ni_resource_show(ni_resource* res, char* text) -{ - if(!res){ - k_log_out("\n---%s--------\n------------\n\n----------", - text); - } - else{ - char* b=tmpbuf; - size_t s=TMPBUFSIZE; - size_t l=0; - l+=k_hashtable_snprintf_x(res->ent_head, b+l, s-l, excto); - l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, perto); - l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, subto); - l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, pubto); - k_log_out("\n---%s----%s--\n%s----------\n%p\n----------", - text, res->uri, tmpbuf, res->entity); - } -} - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT ni_resource* ni_resource_get(char* uri) -{ - return k_hashtable_get(resources, uri); -} - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT ni_event* ni_res_to_evt(ni_resource* res) -{ - ni_event* evp=k_malloc(sizeof(ni_event)); - evp->uri =k_strdup( res->uri); - evp->evt_head=k_hashtable_new("vHeaders/ni_res_to_evt", 1); - evp->ent_head=k_hashtable_dup(res->ent_head); - evp->entity = res->entity; - return evp; -} - -/* -}{---- ------------------------------------------------------------------ */ - -EXPORT ni_event* ni_event_new(char* uri, - k_hashtable* evt_head, - k_hashtable* ent_head, - char* entity) -{ - char* urih=k_hashtable_get(ent_head, "URI:"); - if(urih) uri=urih; - else - if(uri) k_hashtable_put_dup(ent_head, "URI:", uri); - - ni_event* evt=k_malloc(sizeof(ni_event)); - evt->uri =(uri? k_strdup(uri): 0); - evt->evt_head=evt_head; - evt->ent_head=ent_head; - evt->entity =entity; - return evt; -} - -EXPORT ni_event* ni_event_dup(ni_event* evt) -{ - ni_event* evp=k_malloc(sizeof(ni_event)); - evp->uri =k_strdup( evt->uri); - evp->evt_head=k_hashtable_dup(evt->evt_head); - evp->ent_head=k_hashtable_dup(evt->ent_head); - evp->entity = evt->entity; - return evp; -} - -EXPORT void ni_event_delete(ni_event* evt) -{ - if(!evt) return; - if(evt->entity && evt->ent_head){ - int constant=k_hashtable_is(evt->ent_head, "CUX:", "C"); - if(!constant) k_free(evt->entity); - } - k_hashtable_delete(evt->evt_head); - k_hashtable_delete(evt->ent_head); - k_free( evt->uri); - k_free( evt); -} - -EXPORT void ni_event_show(ni_event* evt, char* text) -{ - if(!evt){ - k_log_out("\n---%s--------\n------------\n\n----------", - text); - } - else{ - char* buf=tmpbuf; - int siz=TMPBUFSIZE; - int n=k_hashtable_snprintf(evt->evt_head, buf, siz)+1; - ; k_hashtable_snprintf(evt->ent_head, buf+n, siz-n); - k_log_out("\n---%s----%s--\n" - "%s----------\n" - "%s----------\n" - "%p\n----------", - text, evt->uri, buf, buf+n, evt->entity); - } -} - -/* -}{----------------------------------------------------------------------- */ - - - - diff --git a/src/on/headers.c b/src/on/headers.c new file mode 100644 index 0000000..13fc3e0 --- /dev/null +++ b/src/on/headers.c @@ -0,0 +1,523 @@ + +/* -}{----------------------------------------------------------------------- */ + +#include +#undef PUBLIC +#define PUBLIC EXPORT +#include + +/* -}{---- ------------------------------------------------------------------ */ + +static k_hashtable* entity_headers; + +/* -}{---- ------------------------------------------------------------------ */ + +#define TMPBUFSIZE 4096 +static char tmpbuf[TMPBUFSIZE]; + +/* -}{----------------------------------------------------------------------- */ + +static char* get_request( char* header, k_hashtable*, k_hashtable*); +static char* get_response(char* header, k_hashtable*, k_hashtable*); +static char* get_val(char** atp); +static char* end_of_val(char* at); +static void fix_keepalive(k_hashtable* evt_head); +static void fix_cache_control(k_hashtable* ent_head); +static void fix_uri(k_hashtable* ent_head); +static void fix_subscribe(k_hashtable*, k_hashtable*); + +/* -}{----------------------------------------------------------------------- */ + +#define WHITESPACEH " \t" +#define WHITESPACEV "\012\015" +#define WHITESPACE WHITESPACEH WHITESPACEV + +EXPORT ni_event* ni_get_request_headers(char* header) +{ + k_hashtable* evt_head=k_hashtable_new("vHeaders/get_req_hdrs", 1); + k_hashtable* ent_head=k_hashtable_new("nHeaders/get_req_hdrs", 1); + k_hashtable_put(ent_head, "", header); + + char* h=get_request(header, evt_head, ent_head); + if(!h){ + k_hashtable_delete(evt_head); + k_hashtable_delete(ent_head); + return 0; + } + + h=ni_get_headers(h, evt_head, ent_head); + if(!h){ + k_hashtable_delete(evt_head); + k_hashtable_delete(ent_head); + return 0; + } + + fix_keepalive(evt_head); + fix_cache_control(ent_head); + fix_uri(ent_head); + fix_subscribe(evt_head, ent_head); + + ni_event* evq=ni_event_new(0, evt_head, ent_head, 0); + + return evq; +} + +EXPORT ni_event* ni_get_response_headers(char* header) +{ + k_hashtable* evt_head=k_hashtable_new("vHeaders/get_resp_hdrs", 1); + k_hashtable* ent_head=k_hashtable_new("nHeaders/get_resp_hdrs", 1); + k_hashtable_put(ent_head, "", header); + + char* h=get_response(header, evt_head, ent_head); + if(!h){ + k_hashtable_delete(evt_head); + k_hashtable_delete(ent_head); + return 0; + } + + h=ni_get_headers(h, evt_head, ent_head); + if(!h){ + k_hashtable_delete(evt_head); + k_hashtable_delete(ent_head); + return 0; + } + + ni_event* evt=ni_event_new(0, evt_head, ent_head, 0); + + return evt; +} + +EXPORT char* ni_get_headers(char* header, + k_hashtable* evt_head, + k_hashtable* ent_head) +{ + char* at=header; + char* tag; + char* val; + while(*at){ + + tag=at; + at=strpbrk(at, WHITESPACE); + if(!at || at==tag) return 0; + char* e=at; + val=get_val(&at); + *e=0; + + if(strlen(val) > 2048) return 0; + + k_hashtable* h; + h=k_hashtable_get(entity_headers, tag)? ent_head: evt_head; + if(h){ + char* old=k_hashtable_get(h, tag); + if(!old) k_hashtable_set(h, tag, val); + } + } + return at; +} + +EXPORT void ni_fix_http_headers(k_hashtable* ent_head) +{ + if(k_hashtable_is(ent_head, "Status:", "260")){ + char* crn=k_hashtable_get(ent_head, "Content-Range:"); + char* clg=k_hashtable_get(ent_head, "Content-Length-Given:"); + if(crn || clg){ + k_hashtable_set(ent_head, "Status:", "206"); + k_hashtable_set(ent_head, "Status-Text:", "Partial Content"); + } + else{ + k_hashtable_set(ent_head, "Status:", "200"); + k_hashtable_set(ent_head, "Status-Text:", "OK"); + } + } + k_hashtable_remove(ent_head, "URI:"); + k_hashtable_remove(ent_head, "Method:"); + k_hashtable_remove(ent_head, "From:"); + k_hashtable_remove(ent_head, "Content-Length-Given:"); + k_hashtable_remove(ent_head, "Last-Modified-Epoch:"); + + char* cc=k_hashtable_get(ent_head, "Cache-Control:"); + if(cc && strstr(cc, "no-cache")){ + k_hashtable_set(ent_head, "Pragma:", "no-cache"); + } +} + +EXPORT void ni_fix_ni_headers(k_hashtable* ent_head, int methead) +{ + if(methead && (k_hashtable_is(ent_head, "Status:", "200") || + k_hashtable_is(ent_head, "Status:", "206") )){ + + k_hashtable_set(ent_head, "Status:", "260"); + k_hashtable_set(ent_head, "Status-Text:", "Headers Only"); + } + k_hashtable_remove(ent_head, "Method:"); + k_hashtable_remove(ent_head, "Sub-To:"); + k_hashtable_remove(ent_head, "Via:"); + k_hashtable_set( ent_head, "From:", ni_hostname()); + + char* uri=k_hashtable_get(ent_head, "URI:"); + if(*uri=='.'){ + snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", ni_hostname(), uri+2); + k_hashtable_put_dup(ent_head, "URI:", tmpbuf); + } +} + +EXPORT void ni_response(ni_event* evt, + char* to, + char* method, + char* protocol, + char* connection, + k_channel* chan) +{ + int L=0; + snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc_relative(0)); + k_hashtable_put_dup(evt->evt_head, "Date:", tmpbuf); + k_hashtable_set( evt->evt_head, "Server:", k_version); + if(connection) + k_hashtable_put_dup(evt->evt_head, "Connection:", connection); + + int status =k_hashtable_get_int(evt->ent_head, "Status:"); + char* statustext=k_hashtable_get( evt->ent_head, "Status-Text:"); + int datalength=k_hashtable_get_int(evt->ent_head, "Content-Length:"); + int constant =k_hashtable_is( evt->ent_head, "CUX:", "C"); + + char* buf =tmpbuf; + int bufsize=TMPBUFSIZE; + int ln=0; + + ln+=snprintf(buf+ln, bufsize-ln, "%s %d %s" CRLF, + protocol, status, statustext); + if(ln>=bufsize) return; + + static char* exheaders[]={ "Status:", "Status-Text:", + "Protocol:", "CUX:", 0 }; + + ln+=k_hashtable_snprintf_x(evt->evt_head, buf+ln,bufsize-ln, exheaders); + if(ln>=bufsize) return; + + ln+=k_hashtable_snprintf_x(evt->ent_head, buf+ln,bufsize-ln, exheaders); + if(ln>=bufsize) return; + + ln+=snprintf(buf+ln, bufsize-ln, CRLF); + if(ln>=bufsize) return; + + char* head=k_strdup(buf); + if(L) k_log_out("Actual response headers:\n%s", head); + k_channel_send(chan, head, ln, FREE_ON_SENT); + + if(evt->entity && datalength){ + k_channel_send(chan, evt->entity, datalength, !constant); + } + else{ + datalength=0; + if(!constant) k_free(evt->entity); + } + k_log_out("%s %s %s %d %d", to, method, evt->uri, status, datalength); +} + +EXPORT void ni_request(ni_event* evt, char* to, char* method, k_channel* chan) +{ + k_hashtable* sub=evt->ent_head; + + int ln=0; + int bufsize=TMPBUFSIZE; + + ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s //%s OP/0.5" CRLF, method, to); + if(ln>=bufsize) return; + + ln+=k_hashtable_snprintf(sub, tmpbuf+ln, bufsize-ln); + if(ln>=bufsize) return; + + ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF); + if(ln>=bufsize) return; + + char* head=k_strdup(tmpbuf); + if(0) k_log_out("Actual request headers:\n%s", head); + k_channel_send(chan, head, ln, FREE_ON_SENT); +} + +/* -}{----------------------------------------------------------------------- */ + +char* get_request(char* header, k_hashtable* evt_head, k_hashtable* ent_head) +{ + char* at=header; + char* method=at; + at=strpbrk(at, WHITESPACEH); + if(!at) return 0; + *at++=0; + + k_hashtable_set(ent_head, "Method:", method); + + char* file=0; + char* host=0; + if(strcmp(method, "PING")){ + + at+=strspn(at, WHITESPACEH); + file=at; + at=strpbrk(at, WHITESPACEH); + if(!at) return 0; + *at++=0; + if(strlen(file) > 1024 ) return 0; + + if(!strncmp(file, "http://", 7)){ + char* s=file+7; + if(!*s || *s=='/') return 0; + char* e=strchr(s, '/'); + if(!e) return 0; + host=s; + *e++=0; + file=e; + } + else + if(*file=='/') file++; + else return 0; + + if(*file=='/'){ + char* s=file+1; + if(!*s || *s=='/') return 0; + char* e=strchr(s, '/'); + if(!e) return 0; + host=s; + *e++=0; + file=e; + } + } + if(file) k_hashtable_set(evt_head, "File:", file); + if(host) k_hashtable_set(evt_head, "Host:", host); + + at+=strspn(at, WHITESPACEH); + char* protocol=at; + at=strpbrk(at, WHITESPACE); + if(!at) at=protocol+strlen(protocol); + else *at++=0; + + k_hashtable_set(evt_head, "Protocol:", protocol); + + at+=strspn(at, WHITESPACE); + return at; +} + +char* get_response(char* header, k_hashtable* evt_head, k_hashtable* ent_head) +{ + char* at=header; + char* protocol=at; + at=strpbrk(at, WHITESPACEH); + if(!at) return 0; + *at++=0; + + k_hashtable_set(evt_head, "Protocol:", protocol); + + at+=strspn(at, WHITESPACEH); + char* status=at; + at=strpbrk(at, WHITESPACEH); + if(!at) return 0; + *at++=0; + + at+=strspn(at, WHITESPACEH); + char* statustext=at; + at=strpbrk(at, WHITESPACEV); + if(!at) return 0; + *at++=0; + + k_hashtable_set(ent_head, "Status:", status); + k_hashtable_set(ent_head, "Status-Text:", statustext); + + at+=strspn(at, WHITESPACE); + return at; +} + +char* get_val(char** atp) +{ + char* at=*atp; + char* val=at; + + val+=strspn(val, WHITESPACEH); + val+=strspn(val, WHITESPACEV); + + char* eov=end_of_val(at); + if(eov0; + if(localhostdns || localhostni || dotdotnumber){ + host="."; + } + } + else{ + host="."; + } + if(file){ + k_string_url_decode(file); + snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", host, file); + k_hashtable_put_dup(ent_head, "Sub-To:", tmpbuf); + k_hashtable_set( ent_head, "Sub-Type:", "Original"); + } +} + +void init_headers(void) +{ + entity_headers =k_hashtable_new("Entity Headers", 1); + + k_hashtable_set(entity_headers, "URI:", (void*)1); + k_hashtable_set(entity_headers, "From:", (void*)1); + k_hashtable_set(entity_headers, "To:", (void*)1); + k_hashtable_set(entity_headers, "Via:", (void*)1); + k_hashtable_set(entity_headers, "Sub-To:", (void*)1); + k_hashtable_set(entity_headers, "Sub-Type:", (void*)1); + k_hashtable_set(entity_headers, "Method:", (void*)1); + k_hashtable_set(entity_headers, "Status:", (void*)1); + k_hashtable_set(entity_headers, "Status-Text:", (void*)1); + k_hashtable_set(entity_headers, "Last-Modified-Epoch:", (void*)1); + k_hashtable_set(entity_headers, "CUX:", (void*)1); + + k_hashtable_set(entity_headers, "Range:", (void*)1); + k_hashtable_set(entity_headers, "If-Modified-Since:", (void*)1); + k_hashtable_set(entity_headers, "If-None-Match:", (void*)1); + k_hashtable_set(entity_headers, "Cache-Control:", (void*)1); + k_hashtable_set(entity_headers, "Pragma:", (void*)1); + + k_hashtable_set(entity_headers, "Content-Length:", (void*)1); + k_hashtable_set(entity_headers, "Content-Type:", (void*)1); + k_hashtable_set(entity_headers, "Content-Encoding:", (void*)1); + k_hashtable_set(entity_headers, "Content-Location:", (void*)1); + k_hashtable_set(entity_headers, "Content-MD5:", (void*)1); + k_hashtable_set(entity_headers, "Content-Language:", (void*)1); + k_hashtable_set(entity_headers, "Content-Range:", (void*)1); + k_hashtable_set(entity_headers, "Last-Modified:", (void*)1); + k_hashtable_set(entity_headers, "ETag:", (void*)1); + k_hashtable_set(entity_headers, "Expires:", (void*)1); + + k_hashtable_set(entity_headers, "Allow:", (void*)1); +} + +void drop_entity_headers(k_hashtable* ent_head) +{ + k_hashtable_remove(ent_head, "Content-Length:"); + k_hashtable_remove(ent_head, "Content-Range:"); + k_hashtable_remove(ent_head, "Content-Type:"); + k_hashtable_remove(ent_head, "Content-Encoding:"); + k_hashtable_remove(ent_head, "Content-Location:"); + k_hashtable_remove(ent_head, "Last-Modified:"); +#ifdef DO_THESE_ONES_TOO + k_hashtable_remove(ent_head, "Allow:"); + k_hashtable_remove(ent_head, "Content-Language:"); + k_hashtable_remove(ent_head, "Content-MD5:"); + k_hashtable_remove(ent_head, "Expires:"); +#endif +} + +void fill_headers(k_hashtable* ent_head, + char* status, + char* statustext, + char* uri, + time_t modifitime, + int datalength, + char* mimetype, + char* encoding, + int nocache) +{ + if(status){ + k_hashtable_put_dup(ent_head, "Status:", status); + k_hashtable_put_dup(ent_head, "Status-Text:", statustext); + } + if(uri){ + k_hashtable_put_dup(ent_head, "URI:", uri); + } + if(modifitime>=0){ + snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc(modifitime)); + k_hashtable_put_dup(ent_head, "Last-Modified:", tmpbuf); + } + if(datalength>=0){ + snprintf(tmpbuf, TMPBUFSIZE, "%d", datalength); + k_hashtable_put_dup(ent_head, "Content-Length:", tmpbuf); + } + if(mimetype){ + k_hashtable_put_dup(ent_head, "Content-Type:", mimetype); + } + if(encoding){ + k_hashtable_put_dup(ent_head, "Content-Encoding:", encoding); + } + if(nocache==1){ + k_hashtable_put_dup(ent_head, "Cache-Control:", + "no-cache,no-store"); + } + else + if(nocache==0){ + long maxage=31449600; + snprintf(tmpbuf, TMPBUFSIZE, "max-age=%ld", maxage); + char* maxages=k_time_to_rfc_relative(maxage); + k_hashtable_put_dup(ent_head, "Cache-Control:", tmpbuf); + k_hashtable_put_dup(ent_head, "Expires:", maxages); + } + else + if(nocache== -1){ + k_hashtable_remove(ent_head, "Cache-Control:"); + k_hashtable_remove(ent_head, "Expires:"); + } +} + +/* -}{---- ------------------------------------------------------------------ */ + diff --git a/src/on/notification.c b/src/on/notification.c new file mode 100644 index 0000000..970b1cb --- /dev/null +++ b/src/on/notification.c @@ -0,0 +1,824 @@ + +/* -}{----------------------------------------------------------------------- */ + +#include +#undef PUBLIC +#define PUBLIC EXPORT +#include + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT n_object* n_object_new(char* s) +{ + return 0; +} + +EXPORT void n_commit(n_object* o) +{ +} + +EXPORT n_object* n_see(n_object* o, char* uid) +{ + return 0; +} + +EXPORT char* n_to_string(n_object* o) +{ + return 0; +} + +EXPORT char* n_uid(n_object* o) +{ + return 0; +} + +EXPORT char* n_header(n_object* o, char* name) +{ + return 0; +} + +EXPORT k_hashtable* n_headers(n_object* o) +{ + return 0; +} + +EXPORT k_hashtable* n_content(n_object* o) +{ + return 0; +} + +/* -}{---- ------------------------------------------------------------------ */ + +#define TMPBUFSIZE 4096 +static char tmpbuf[TMPBUFSIZE]; +static char* hostname; +static k_hashtable* resources; + +/* -}{---- ------------------------------------------------------------------ */ + +typedef struct ni_driver{ + char* name; + ni_handles_resource handles_resource; + ni_sync_resource sync_resource; +} ni_driver; + +/* -}{---- From headers.c --------------------------------------------------- */ + +extern void init_headers(void); +extern void drop_entity_headers(k_hashtable* ent_head); +extern void fill_headers(k_hashtable* ent_head, + char* status, + char* statustext, + char* uri, + time_t modifitime, + int datalength, + char* mimetype, + char* encoding, + int nocache); + +/* -}{---- ------------------------------------------------------------------ */ + +static void incoming_request(ni_event* evq); +static ni_resource* ensure_res(char* pub); +static void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub); +static void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub); +static k_hashtable* get_this(k_hashtable*, char*, k_hashtable*); +static k_hashtable* get_using(k_hashtable* curr, char* tag, char* val); +static void post_to_driver(char* pub, ni_event* evq); +static void incoming_resource(ni_event* evt); +static void test_pub_tos(ni_resource* res, ni_event* evt, int entityok); +static int satisfiable(k_hashtable*, ni_resource*, ni_event*, int); +static void update_pubcache(int, k_hashtable**, k_hashtable*, k_hashtable*); +static int sub_less(k_hashtable* sub1, k_hashtable* sub2); +static void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh); +static int sub_ok(k_hashtable* sub); +static int range_ok(char* range, char* conrange); +static void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh); +static void merge_entity_range(ni_resource* res, ni_event* evt); +static void respond( k_hashtable* sub, ni_resource* res, ni_event* evt); +static void respond_ok(k_hashtable* sub, ni_event* evv); +static void respond_nf(k_hashtable* sub, ni_event* evv); +static void* entity_to_octets(k_hashtable* ent_head, void* entity); +static char* handled_by(char* pub); +static void call_sync_resource(ni_resource* res); +static ni_driver* ni_driver_new(char* name, + ni_handles_resource handles_resource, + ni_sync_resource sync_resource); + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT int on_module_loaded(void) +{ + resources=k_hashtable_new("Resources", 0); + + init_headers(); + + k_log_out("ON initialised"); + return 1; +} + +EXPORT void on_module_tick(void) +{ +} + +EXPORT int on_module_event(void* data) +{ + ni_event* evt=data; + + if(!k_hashtable_get(evt->ent_head, "Status:")){ + + incoming_request(evt); + } + else{ + incoming_resource(evt); + } + return 1; +} + +/* -}{---- ------------------------------------------------------------------ */ + +void incoming_request(ni_event* evq) +{ + int L=1; + if(L) ni_event_show(evq, "ON got request event"); + + k_hashtable* sub=evq->ent_head; + char* uri =k_hashtable_get(sub, "URI:"); + char* pub =k_hashtable_get(sub, "Sub-To:"); if(!pub) return; + int styor=k_hashtable_isi(sub, "Sub-Type:", "Original"); + char* via =k_hashtable_get(sub, "Via:"); + char* from =k_hashtable_get(sub, "From:"); + if(L) k_log_out("------------------ %s", pub); + + int nocache=k_hashtable_isi(sub, "Cache-Control:", "no-cache"); + if(nocache){ + k_hashtable_remove( sub, "Cache-Control:"); + k_hashtable_set( sub, "If-Modified-Since:", "0"); + } + + if(!from){ + ni_resource* ses=k_hashtable_get(resources, uri); + if(ses) ensure_sub_entry(ses->ent_head, sub); + if(ses) if(L) ni_resource_show(ses, "Subscribing Resource:"); + if(styor && via){ + post_to_driver(pub, evq); + return; + } + } + + ni_resource* res=ensure_res(pub); + if(L) ni_resource_show(res, "Publishing Resource:"); + + k_hashtable* pubcache=0; + int sat=satisfiable(sub, res, 0, 0); + update_pubcache(sat, &pubcache, res->ent_head, sub); + if(sat){ + if(L) k_log_out("Memory cache hit for %s", pub); + respond(k_hashtable_dup(sub), res, 0); + ni_event_delete(evq); + } + else{ + ensure_pub_entry(res->ent_head, sub); + if(L) ni_resource_show(res, "Pending Resource:"); + if(pubcache){ + evq->ent_head=pubcache; + post_to_driver(pub, evq); + k_hashtable_delete(sub); + } + else{ + if(L) k_log_out("In-progress Pub-Cache sufficient"); + ni_event_delete(evq); + } + } +} + +ni_resource* ensure_res(char* pub) +{ + ni_resource* res=k_hashtable_get(resources, pub); + if(!res){ + res=ni_resource_new(pub, k_hashtable_new("resHeaders", 1), 0); + k_hashtable_set(resources, pub, res); + } + return res; +} + +void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub) +{ + char* tag="Sub-To:"; + k_hashtable* sup=get_this(ent_head, tag, sub); + if(!sup){ + k_hashtable* sup=k_hashtable_dup(sub); + char* uri=k_hashtable_extract(sup, "Sub-To:"); + k_hashtable_put( sup, "URI:", uri); + k_hashtable_remove( sup, "Sub-Type:"); + k_hashtable_sub(ent_head, tag, sup); + } + else{ + k_hashtable_remove(sup, "Range:"); + k_hashtable_remove(sup, "Content-Range:"); + k_hashtable_remove(sup, "Status:"); + k_hashtable_remove(sup, "Status-Cache:"); + char* mth=k_strdup(k_hashtable_get(sub, "Method:")); + char* via=k_strdup(k_hashtable_get(sub, "Via:")); + char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:")); + char* rng=k_strdup(k_hashtable_get(sub, "Range:")); + if(mth) k_hashtable_put(sup, "Method:", mth); + if(via) k_hashtable_put(sup, "Via:", via); + if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims); + if(rng) k_hashtable_put(sup, "Range:", rng); + } +} + +void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub) +{ + char* tag="Pub-To:"; + k_hashtable* sup=get_this(ent_head, tag, sub); + if(!sup){ + k_hashtable* sup=k_hashtable_dup(sub); + k_hashtable_remove(sup, "Sub-To:"); + k_hashtable_remove(sup, "Sub-Type:"); + k_hashtable_sub(ent_head, tag, sup); + } + else { + k_hashtable_remove(sup, "Method:"); + k_hashtable_remove(sup, "If-Modified-Since:"); + k_hashtable_remove(sup, "Cache-Control:"); + k_hashtable_remove(sup, "Update:"); + char* mth=k_strdup(k_hashtable_get(sub, "Method:")); + char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:")); + char* ccn=k_strdup(k_hashtable_get(sub, "Cache-Control:")); + char* upd=k_strdup(k_hashtable_get(sub, "Update:")); + if(mth) k_hashtable_put(sup, "Method:", mth); + if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims); + if(ccn) k_hashtable_put(sup, "Cache-Control:", ccn); + if(upd) k_hashtable_put(sup, "Update:", upd); + } +} + +k_hashtable* get_this(k_hashtable* ent_head, char* pubsub, k_hashtable* try) +{ + k_hashtable* curr=k_hashtable_get(ent_head, pubsub); + if(!curr) return 0; + + char* tag; + char* val; + + tag="From:"; + val=k_hashtable_get(try, tag); + if(val) return get_using(curr, tag, val); + + tag="URI:"; + val=k_hashtable_get(try, tag); + if(val) return get_using(curr, tag, val); + + return 0; +} + +k_hashtable* get_using(k_hashtable* curr, char* tag, char* val) +{ + k_hashtable* c; + for(c=curr; c; c=c->next) if(k_hashtable_is(c, tag, val)) return c; + return c; +} + +/* -}{---- ------------------------------------------------------------------ */ + +void incoming_resource(ni_event* evt) +{ + int L=0; + if(L) ni_event_show(evt, "ON got resource incoming event"); + + ni_resource* res=k_hashtable_get(resources, evt->uri); + int fullconst=res && k_hashtable_is(res->ent_head, "Status:", "200") && + k_hashtable_is(res->ent_head, "CUX:", "C"); + + if(fullconst){ + k_log_err("Resource is complete and Constant"); + ni_event_delete(evt); + return; + } + if(!res) res=ensure_res(evt->uri); + + k_hashtable* reseh=res->ent_head; + k_hashtable* evteh=evt->ent_head; + int okfull =k_hashtable_is(evteh, "Status:", "200"); + int partial =k_hashtable_is(evteh, "Status:", "206"); + int headonly=k_hashtable_is(evteh, "Status:", "260");/* + int updated =k_hashtable_is(evteh, "Status:", "266");*/ + int notmod =k_hashtable_is(evteh, "Status:", "304"); + int notfound=k_hashtable_is(evteh, "Status:", "404"); + + int entityok= (okfull || partial || notmod); + int entityev=!(headonly || notmod || notfound); + int entityin=!!evt->entity; + int entityon=!!res->entity; + + if(!entityev){ + } + if(okfull || !entityon){ + k_hashtable_merge(reseh, evteh); + if(okfull) k_hashtable_remove(reseh, "Content-Range:"); + } + else{ + merge_non_entity_headers(reseh, evteh); + } + + fix_via_subs(evteh, reseh); + + if(entityin){ + if(okfull || (partial && !entityon)){ + if(res->entity!=evt->entity){ + if(!k_hashtable_is(reseh, "CUX:", "C")){ + k_free(res->entity); + } + res->entity=evt->entity; + } + } + else + if(partial && entityon){ + merge_entity_range(res, evt); + } + } + + if(L) ni_resource_show(res, "updated resource - sync and try pubs:"); + + call_sync_resource(res); + + test_pub_tos(res, evt, entityok); + + evt->entity=0; + ni_event_delete(evt); + + if(L) ni_resource_show(res, "resource after ON:"); +} + +void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh) +{ + char* from=k_hashtable_get(evteh, "From:"); + if(!from) return; + k_hashtable* subs=k_hashtable_get(reseh, "Sub-To:"); + k_hashtable* sub; + for(sub=subs; sub; sub=sub->next){ + if(!k_hashtable_is(sub, "Via:", from)) continue; + int st=k_hashtable_get_int(evteh, "Status:"); + char* cr=k_hashtable_get_dup(evteh, "Content-Range:"); + if(st!=304) k_hashtable_put_int(sub, "Status:", st); + if(st==200) k_hashtable_remove( sub, "Content-Range:"); + else + if(cr) k_hashtable_put(sub, "Content-Range:", cr); + if(sub_ok(sub)) k_hashtable_set(sub, "Status-Cache:", "OK"); + } +} + +void test_pub_tos(ni_resource* res, ni_event* evt, int entityok) +{ + k_hashtable* keeps=0; + k_hashtable* sub=k_hashtable_extract(res->ent_head, "Pub-To:"); + while(sub){ + k_hashtable* subnext=sub->next; + sub->next=0; + int keep=1; + int sat=satisfiable(sub, res, evt, entityok); + update_pubcache(sat, 0, res->ent_head, sub); + if(sat){ + respond(k_hashtable_dup(sub), res, evt); + if(!k_hashtable_get(sub, "Update:")) keep=0; + } + if(keep){ + sub->next=keeps; + keeps=sub; + } + else{ + k_hashtable_delete(sub); + } + sub=subnext; + } + sub=keeps; + while(sub){ + k_hashtable* subnext=sub->next; + k_hashtable_sub(res->ent_head, "Pub-To:", sub); + sub=subnext; + } +} + +int satisfiable(k_hashtable* sub, + ni_resource* res, + ni_event* evt, + int entityok) +{ + int L=0; + int get =k_hashtable_is( sub, "Method:", "GET"); + int head =k_hashtable_is( sub, "Method:", "HEAD"); + int dosub=k_hashtable_is( sub, "Method:", "SUB"); + int unsub=k_hashtable_is( sub, "Method:", "UNSUB"); + int full=!k_hashtable_isi(sub, "Cache-Control:", "no-full"); + int updt =k_hashtable_isi(sub, "Update:", "changes"); + char* ims =k_hashtable_get(sub, "If-Modified-Since:"); + char* range=k_hashtable_get(sub, "Range:"); + + int getsub =get || dosub; + int getrange=getsub && range; + + k_hashtable* reseh=res->ent_head; + int gotall= k_hashtable_is( reseh, "Status:", "200"); + int gotrange= k_hashtable_is( reseh, "Status:", "206"); + int gothead= k_hashtable_is( reseh, "Status:", "260"); + int gotupdated=evt && + k_hashtable_is(evt->ent_head, "Status:", "266"); + int notfound= k_hashtable_is( reseh, "Status:", "404"); + int constant= k_hashtable_is( reseh, "CUX:", "C" ); + char* conrange= k_hashtable_get(reseh, "Content-Range:"); + + if(unsub) return 0; + if(notfound) return 1; + + int gotany=(gothead || gotrange || gotall); + int snapok=(constant || !ims || entityok); + + int sat= + (full && + ((getsub && gotall && snapok) || + (getrange && gotrange && range_ok(range, conrange) && snapok) || + (head && gotany ) )) + || + (updt && + ((dosub && gotupdated))); + + if(L) k_log_out("satisfiable %d", sat); + return sat; +} + +void update_pubcache(int sat, + k_hashtable** pubcachep, + k_hashtable* reseh, + k_hashtable* sub) +{ + if(!sat){ if(pubcachep){ + k_hashtable* pubcache; + pubcache=k_hashtable_get(reseh, "Pub-Cache:"); + if(!pubcache || sub_less(pubcache, sub)){ + if(!pubcache){ + pubcache=k_hashtable_dup(sub); + k_hashtable_sub(reseh, "Pub-Cache:", pubcache); + } + else{ + k_hashtable_merge(pubcache, sub); + } + k_hashtable_remove(pubcache, "URI:"); + k_hashtable_remove(pubcache, "Sub-Type:"); + *pubcachep=k_hashtable_dup(pubcache); + k_hashtable_set(*pubcachep, "Sub-Type:", "Cache"); + } + }} + else{ if(!pubcachep){ + k_hashtable* pubcache; + pubcache=k_hashtable_get(reseh, "Pub-Cache:"); + if(!sub_less(sub, pubcache)){ + k_hashtable_remove(pubcache, "Method:"); + k_hashtable_remove(pubcache, "If-Modified-Since:"); + } + }} +} + +int sub_ok(k_hashtable* sub) +{ + char* gotresp =k_hashtable_get(sub, "Status:"); + if(!gotresp) return 0; + int notfound=k_hashtable_is( sub, "Status:", "404"); + if(notfound) return 0; + int gotall =k_hashtable_is( sub, "Status:", "200"); + int gotrange=k_hashtable_is( sub, "Status:", "206"); + int gothead= k_hashtable_is( sub, "Status:", "260"); + int doget =k_hashtable_is( sub, "Method:", "GET"); + int dohead =k_hashtable_is( sub, "Method:", "HEAD"); + int dosub =k_hashtable_is( sub, "Method:", "SUB"); + char* range =k_hashtable_get(sub, "Range:"); + char* conrange=k_hashtable_get(sub, "Content-Range:"); + + int dogetsub=doget || dosub; + int dogetrange=dogetsub && range; + int gotany =(gothead || gotrange || gotall); + + return (dogetsub && gotall ) || + (dogetrange && gotrange && range_ok(range, conrange)) || + (dohead && gotany ); +} + +int sub_less(k_hashtable* sub1, k_hashtable* sub2) +{ + int L=0; + if(L) k_log_out("sub_less sub1:"); + if(L) k_hashtable_show_chars(sub1); + if(L) k_log_out("sub_less sub2:"); + if(L) k_hashtable_show_chars(sub2); + char* mth1 =k_hashtable_get(sub1, "Method:"); + int head1=k_hashtable_is( sub1, "Method:", "HEAD"); + int get2 =k_hashtable_is( sub2, "Method:", "GET"); + char* ims1 =k_hashtable_get(sub1, "If-Modified-Since:"); + char* ims2 =k_hashtable_get(sub2, "If-Modified-Since:"); + int full=!k_hashtable_isi(sub2, "Cache-Control:", "no-full"); + return full && ((!mth1) || (head1 && get2) || (!ims1 && ims2)); +} + +int range_ok(char* range, char* conrange) +{ + k_log_out("range_ok not implemented: %s vs %s", range, conrange); + return 0; +} + +void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh) +{ +} + +void merge_entity_range(ni_resource* res, ni_event* evt) +{ + k_log_out("merge_entity_range not implemented yet"); +} + +/* -}{---- ------------------------------------------------------------------ */ + +void respond(k_hashtable* sub, ni_resource* res, ni_event* evt) +{ + int updated=evt && k_hashtable_is(evt->ent_head, "Status:", "266"); + ni_event* evv=updated? ni_event_dup(evt): + ni_res_to_evt(res); + int L=0; + if(L) ni_event_show(evv, "respond"); + + k_hashtable_remove(evv->ent_head, "Permit:"); + k_hashtable_remove(evv->ent_head, "Sub-To:"); + k_hashtable_remove(evv->ent_head, "Pub-To:"); + k_hashtable_remove(evv->ent_head, "Pub-Cache:"); + k_hashtable_sub( evv->ent_head, "Pub-To:", sub); + + int nf; + nf=k_hashtable_is( evv->ent_head, "Status:", "404"); + if(!nf) respond_ok(sub, evv); + else respond_nf(sub, evv); +} + +void respond_ok(k_hashtable* sub, ni_event* evv) +{ + char* status=0; + char* statustext=0; + int datalength= -1; + int nocache=0; + k_hashtable* ent_head=evv->ent_head; + + time_t modifitime=k_hashtable_get_int(ent_head, "Last-Modified-Epoch:"); + char* modistring=k_hashtable_get( ent_head, "Last-Modified:"); + if(!modifitime){ + modifitime=k_time_from_rfc(modistring); + } + char* imss=k_hashtable_get(sub, "If-Modified-Since:"); + time_t imst=k_time_from_rfc(imss); + + if(modifitime== -1 || imst== -1 || modifitime > imst){ + if(k_hashtable_is(sub, "Method:", "HEAD")){ + evv->entity=0; + } + if(!k_hashtable_is(ent_head, "CUX:", "C")){ + evv->entity=entity_to_octets(ent_head, evv->entity); + nocache=1; + } + } + else{ + status="304"; + statustext="Not Modified"; + modifitime= -1; + nocache= -1; + evv->entity=0; + drop_entity_headers(ent_head); + } + + fill_headers(ent_head, status, statustext, 0, + modistring? -1: modifitime, + datalength, 0, 0, nocache); + + char* pub =k_hashtable_get(sub, "URI:"); + int L=0; + if(L) ni_event_show(evv, "respond_ok"); + post_to_driver(pub, evv); +} + +void respond_nf(k_hashtable* sub, ni_event* evv) +{ + fill_headers(evv->ent_head, "404", "File Not Found", 0, -1, 0, 0, 0, 1); + char* pub =k_hashtable_get(sub, "URI:"); + post_to_driver(pub, evv); +} + +void post_to_driver(char* pub, ni_event* evq) +{ + char* driver=handled_by(pub); + if(0) k_log_out("Passing %s on to %s", pub, driver); + if(0) ni_event_show(evq, "Post to Driver:"); + k_event_post(driver, evq); +} + +void* entity_to_octets(k_hashtable* ent_head, void* entity) +{ + if(!entity) return 0; + size_t size=k_hashtable_get_int(ent_head, "Content-Length:"); + return k_memdup(entity, size); +} + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT char* ni_hostname() +{ + return hostname? hostname: "not set"; +} + +EXPORT void ni_hostname_set(char* name) +{ + k_free(hostname); + hostname=k_strdup(name); +} + +/* -}{---- ------------------------------------------------------------------ */ + +static ni_driver* opdriver; +static ni_driver* moddriver; + +char* handled_by(char* pub) +{ + if(moddriver->handles_resource(pub)) return moddriver->name; + return "op"; +} + +void call_sync_resource(ni_resource* res) +{ + if(moddriver->handles_resource(res->uri)) moddriver->sync_resource(res); + else opdriver->sync_resource(res); +} + +ni_driver* ni_driver_new(char* name, + ni_handles_resource handles_resource, + ni_sync_resource sync_resource) +{ + ni_driver* driver=k_malloc(sizeof(ni_driver)); + driver->name =name; + driver->handles_resource=handles_resource; + driver->sync_resource =sync_resource; + return driver; +} + +EXPORT void ni_register_driver(char* name, + ni_handles_resource handles_resource, + ni_sync_resource sync_resource) +{ + ni_driver* d=ni_driver_new(name, handles_resource, sync_resource); + if(!strcmp(name, "op")) opdriver=d; + else moddriver=d; +} + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT ni_resource* ni_resource_new(char* uri, + k_hashtable* ent_head, + char* entity) +{ + char* urih=k_hashtable_get(ent_head, "URI:"); + if(urih) uri=urih; + else + if(uri) k_hashtable_put_dup(ent_head, "URI:", uri); + + ni_resource* res=k_malloc(sizeof(ni_resource)); + res->uri =(uri? k_strdup(uri): 0); + res->ent_head=ent_head; + res->entity =entity; + return res; +} + +EXPORT ni_resource* ni_resource_dup(ni_resource* res) +{ + ni_resource* rep=k_malloc(sizeof(ni_resource)); + rep->uri =k_strdup( res->uri); + rep->ent_head=k_hashtable_dup(res->ent_head); + rep->entity = res->entity; + return rep; +} + +EXPORT void ni_resource_delete(ni_resource* res) +{ + if(!res) return; + if(res->entity && res->ent_head){ + int constant=k_hashtable_is(res->ent_head, "CUX:", "C"); + if(!constant) k_free(res->entity); + } + k_hashtable_delete(res->ent_head); + k_free( res->uri); + k_free( res); +} + +static char* excto[]={ "Permit:", "Sub-To:", "Pub-To:", 0 }; +static char* perto[]={ "Permit:", 0 }; +static char* subto[]={ "Sub-To:", 0 }; +static char* pubto[]={ "Pub-To:", 0 }; + +EXPORT void ni_resource_show(ni_resource* res, char* text) +{ + if(!res){ + k_log_out("\n---%s--------\n------------\n\n----------", + text); + } + else{ + char* b=tmpbuf; + size_t s=TMPBUFSIZE; + size_t l=0; + l+=k_hashtable_snprintf_x(res->ent_head, b+l, s-l, excto); + l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, perto); + l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, subto); + l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, pubto); + k_log_out("\n---%s----%s--\n%s----------\n%p\n----------", + text, res->uri, tmpbuf, res->entity); + } +} + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT ni_resource* ni_resource_get(char* uri) +{ + return k_hashtable_get(resources, uri); +} + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT ni_event* ni_res_to_evt(ni_resource* res) +{ + ni_event* evp=k_malloc(sizeof(ni_event)); + evp->uri =k_strdup( res->uri); + evp->evt_head=k_hashtable_new("vHeaders/ni_res_to_evt", 1); + evp->ent_head=k_hashtable_dup(res->ent_head); + evp->entity = res->entity; + return evp; +} + +/* -}{---- ------------------------------------------------------------------ */ + +EXPORT ni_event* ni_event_new(char* uri, + k_hashtable* evt_head, + k_hashtable* ent_head, + char* entity) +{ + char* urih=k_hashtable_get(ent_head, "URI:"); + if(urih) uri=urih; + else + if(uri) k_hashtable_put_dup(ent_head, "URI:", uri); + + ni_event* evt=k_malloc(sizeof(ni_event)); + evt->uri =(uri? k_strdup(uri): 0); + evt->evt_head=evt_head; + evt->ent_head=ent_head; + evt->entity =entity; + return evt; +} + +EXPORT ni_event* ni_event_dup(ni_event* evt) +{ + ni_event* evp=k_malloc(sizeof(ni_event)); + evp->uri =k_strdup( evt->uri); + evp->evt_head=k_hashtable_dup(evt->evt_head); + evp->ent_head=k_hashtable_dup(evt->ent_head); + evp->entity = evt->entity; + return evp; +} + +EXPORT void ni_event_delete(ni_event* evt) +{ + if(!evt) return; + if(evt->entity && evt->ent_head){ + int constant=k_hashtable_is(evt->ent_head, "CUX:", "C"); + if(!constant) k_free(evt->entity); + } + k_hashtable_delete(evt->evt_head); + k_hashtable_delete(evt->ent_head); + k_free( evt->uri); + k_free( evt); +} + +EXPORT void ni_event_show(ni_event* evt, char* text) +{ + if(!evt){ + k_log_out("\n---%s--------\n------------\n\n----------", + text); + } + else{ + char* buf=tmpbuf; + int siz=TMPBUFSIZE; + int n=k_hashtable_snprintf(evt->evt_head, buf, siz)+1; + ; k_hashtable_snprintf(evt->ent_head, buf+n, siz-n); + k_log_out("\n---%s----%s--\n" + "%s----------\n" + "%s----------\n" + "%p\n----------", + text, evt->uri, buf, buf+n, evt->entity); + } +} + +/* -}{----------------------------------------------------------------------- */ + + + + diff --git a/src/platform/kernelapi.c b/src/platform/kernelapi.c index e8e2854..e32c1b5 100644 --- a/src/platform/kernelapi.c +++ b/src/platform/kernelapi.c @@ -285,7 +285,7 @@ void dir_read(char* basedir, } else{ is_np=1; - k_ciux="np"; + k_ciux="op"; } k_free(data); } @@ -294,8 +294,8 @@ void dir_read(char* basedir, k_log_out("========================================"); - load_module("ni", 0); - load_module("np", 0); + load_module("on", 0); + load_module("op", 0); if(!is_np) load_module(k_ciux, 1); k_log_out("========================================"); -- 1.7.9.5