Files
tlib/oversampling/WDL/eel2/scripts/httpd.eel
2024-05-24 13:28:31 +02:00

181 lines
4.2 KiB
Plaintext

// asynchronous HTTP server in EEL
function httpd.init(port, maxcon, table, stringoffs, wwwroot) global()
(
this.maxcon = maxcon;
this.tab = table;
this.port = port;
this.stringtab = stringoffs;
this.string_recsz = 2;
this.recsz = 3;
#this.wwwroot = wwwroot;
);
function httpd.getrecval(conid, parm) global()
(
conid >= 0 && conid < this.maxcon ? (
parm == 'sock' ? this.tab + conid*this.recsz + 0 : // socket
parm == 'st' ? this.tab + conid*this.recsz + 1 : // state
parm == 'fh' ? this.tab + conid*this.recsz + 2 : // file handle
0)
: 0
);
function httpd.set(conid, parm, value) local(x) global()
(
x = httpd.getrecval(conid,parm);
x>=0 ? x[]=value;
);
function httpd.get(conid, parm) local(x) global()
(
x=httpd.getrecval(conid,parm);
x>=0?x[];
);
function httpd.getbuf(conid, w) global()
(
conid >=0 && conid < this.maxcon ? this.stringtab + this.string_recsz*conid + w : -1;
);
function httpd.close(conid) global()
(
conid >=0 && conid < this.maxcon ?
(
tcp_close(httpd.get(conid,'sock'));
fclose(httpd.get(conid,'fh'));
httpd.set(conid,'sock',0);
httpd.set(conid,'fh',0);
);
);
function httpd.file_for_req(req, response) local(fn,fp) global() (
!strcmp(req,"") || !strcmp(req,"/") ? req = "/index.html";
str_getchar(req,0) == '/' &&
!match("*..*",req) &&
(fp=fopen(fn = strcat(#=#this.wwwroot,req),"rb")) > 0 ?
(
fseek(fp,0,1);
printf("GET %s -- 200: %s\n",req,fn);
strcat(response,sprintf(#, "HTTP/1.1 200 OK\r\n"
"Content-length: %d\r\n"
"Content-type: text/html\r\n"
"\r\n",
ftell(fp)));
fseek(fp,0,-1);
fp;
) : (
printf("GET %s -- 404\n",req);
fn = "The file specified could not be found.";
strcat(response,sprintf(#, "HTTP/1.1 404 NOT FOUND\r\n"
"Content-length: %d\r\n"
"Content-type: text/plain\r\n"
"\r\n"
"%s", strlen(fn),fn));
0;
);
);
// run input and output buffers
function httpd.runcon(idx) local(sock,x,str,rv,buffers) global() (
rv=0;
sock = httpd.get(idx,'sock');
sock > 0 ?
(
x=tcp_recv(sock,str=#);
x<0 ? (
httpd.close(idx);
) : (
buffers=httpd.getbuf(idx,0);
x>0 ? strcat(buffers,str);
rv+=x;
strlen(buffers+1)>0 ?
(
(x=tcp_send(sock,buffers+1)) > 0 ?
(
rv+=1;
str_delsub(buffers+1.1,0,x);
);
);
);
);
rv;
);
function httpd.run() local(sock, x, i, str, rv, t,hdrs,httpdver) global() (
str=#;
hdrs=#;
rv=0;
sock=tcp_listen(this.port,"",str);
sock > 0 ?
(
i=0;
while (i < this.maxcon && httpd.get(i,'sock')) ( i += 1; );
i < this.maxcon ? (
tcp_set_block(sock,0);
httpd.set(i,'sock',sock);
httpd.set(i,'st',0);
x=0;
loop(this.string_recsz, strcpy(httpd.getbuf(i,x), ""); x+=1; );
printf("httpd.run(): connection from '%s'\n",str);
rv+=1;
) : (
printf("httpd.run(): dropping connect from '%s', slots full\n",str);
tcp_close(x);
);
);
i=0;
while (i < this.maxcon)
(
this.httpd.runcon(i) ?
(
t = httpd.getbuf(i,0);
this.httpd.get(i,'st') == 0 ?
(
match("GET %S HTTP/1.%1d%S",t,str,httpdver,hdrs) &&
str_getchar(hdrs,0)=='\r' && str_getchar(hdrs,1)=='\n' &&
!strcmp(strcpy_substr(#,hdrs,-4),"\r\n\r\n")
?
(
httpd.set(i,'st',1 |
((httpdver==0 || matchi("\r\nConnection:*close\r\n",hdrs))?2:0)
);
httpd.set(i,'fh',httpd.file_for_req(str,t+1));
);
);
httpd.get(i,'fh') && !strlen(t+1) ? fread(httpd.get(i,'fh'),t+1,4096);
httpd.get(i,'st') == 3 ? (
strlen(t+1) == 0 ? (
httpd.close(i);
printf("sent data, closing\n");
);
);
rv+=1;
);
i+=1;
);
rv;
);
argc != 3 || strlen(argv[1])<1 || !match("%d",argv[2],port) ? (
printf("Usage: \n\t%s www_root port\n",argv[0]);
) : (
srv.httpd.init(port, 100, 100000, 10000, argv[1]);
// string [conidx] = send buffe
while(1)
(
srv.httpd.run() || Sleep(10);
);
);