first import of old cilux linux platform code
[cilux] / src / drivers / np / uri2chan.c
diff --git a/src/drivers/np/uri2chan.c b/src/drivers/np/uri2chan.c
new file mode 100644 (file)
index 0000000..b4de726
--- /dev/null
@@ -0,0 +1,294 @@
+
+/* -}{----------------------------------------------------------------------- */
+
+#include <kernelapi.h>
+#include <ni.h>
+
+/* -}{----------------------------------------------------------------------- */
+
+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, 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" CRLF, 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);
+}
+
+/* -}{----------------------------------------------------------------------- */
+