From fff09a05212232ed52fce71c7fb26d6009c58303 Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 6 Aug 2025 11:24:36 +0200 Subject: [PATCH] Add support for dynamically regenerated web-pages. Limit to 1 concurrent TCP connection for now. --- Makefile | 12 +++- httpd/Makefile | 2 +- httpd/httpd.c | 157 ++++++++++++++++++++++++++++++++++++++++++------- httpd/httpd.h | 2 +- uip/uip-conf.h | 10 ++-- 5 files changed, 153 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 5f4c944..1cce738 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,15 @@ SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS)) all: $(SUBDIRS) rtlplayground.bin -SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c +SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c OBJS = ${SRCS:.c=.rel} -OBJS += uip/timer.rel uip/uip-fw.rel uip/uip-neighbor.rel uip/uip-split.rel uip/uip.rel uip/uip_arp.rel uip/uiplib.rel httpd/httpd.rel +OBJS += uip/timer.rel uip/uip-fw.rel uip/uip-neighbor.rel uip/uip-split.rel uip/uip.rel uip/uip_arp.rel uip/uiplib.rel httpd/httpd.rel httpd/page_impl.rel +html_data.c html_data.h: html tools + tools/fileadder -a -s -b BANK1 -d html -p html_data + +httpd: html_data.h + $(MAKE) -C $@ $(SUBDIRS): $(MAKE) -C $@ @@ -21,6 +26,7 @@ $(SUBDIRS): clean: -make -C uip clean -make -C httpd clean + -rm html_data.c html_data.c if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi if [ -e rtlplayground.asm ]; then rm rtlplayground.asm; fi -rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin @@ -45,6 +51,8 @@ rtlplayground.ihx: crtstart.rel $(OBJS) cat $< >> $@ truncate --size=16K $@ dd if=$< skip=80 bs=1024 >>$@ + tools/fileadder -s -d config.txt $@ + tools/fileadder -a -s -d html -p html_data $@ .PHONY: clean all $(SUBDIRS) .PRECIOUS: %.rel %.ihx .img diff --git a/httpd/Makefile b/httpd/Makefile index 7a30056..397f46c 100644 --- a/httpd/Makefile +++ b/httpd/Makefile @@ -3,7 +3,7 @@ CC_FLAGS = -mmcs51 -I. -I../uip ASM = sdas8051 AFLAGS= -plosgff -SRCS = httpd.c +SRCS = httpd.c page_impl.c OBJS = ${SRCS:.c=.rel} all: $(OBJS) diff --git a/httpd/httpd.c b/httpd/httpd.c index e99f35d..b7b3492 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -1,23 +1,29 @@ #include "httpd.h" #include "../rtl837x_common.h" +#include "../rtl837x_flash.h" #include "uip.h" +#include "../html_data.h" + +#define CMARK_S 6 #pragma codeseg BANK1 -static __code uint8_t page_main[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n" -"\r\n" -"" -" " -" FreeSwitchOS Main Page" -" " -" " -"

Port configuration:

" -"

TBD

" -" " -"\r\n"; +extern __code struct f_data f_data[]; +extern __code fcall_ptr f_calls[]; __xdata uint8_t outbuf[2048]; +__xdata uint8_t entry; +__xdata uint16_t slen; +__xdata uint16_t o_idx; +__xdata uint16_t mpos; +__xdata uint16_t len_left; + +#define TSTATE_NONE 0 +#define TSTATE_TX 1 +#define TSTATE_ACKED 2 +#define TSTATE_CLOSED 3 + inline uint8_t is_space(uint8_t c) { @@ -27,8 +33,27 @@ inline uint8_t is_space(uint8_t c) void httpd_init(void) __banked { + __xdata struct httpd_state *s = &(uip_conn->appstate); // Start listening to port 80 uip_listen(HTONS(80)); + s->tstate = TSTATE_CLOSED; +} + + +uint8_t find_entry(uint8_t *e) +{ + register uint8_t i, j; + + for (i = 0; f_data[i].len; i++) { + j = 0; + while (f_data[i].file[j] && (f_data[i].file[j] == e[j])) { + j++; + } + if ((!f_data[i].file[j]) && (!e[j])) { + return i; + } + } + return 0xff; } @@ -37,19 +62,46 @@ void httpd_appcall(void) __xdata struct httpd_state *s = &(uip_conn->appstate); write_char('P'); - if(uip_connected()) { + if(uip_connected() && s->tstate == TSTATE_CLOSED) { print_string("Connected...\n"); - s->transmitted = 0; + s->tstate = TSTATE_NONE; } else if (uip_closed()) { print_string("Connection closed\n"); + s->tstate = TSTATE_CLOSED; } else if (uip_poll()) { uip_len = 0; - if (s->transmitted) + if (s->tstate == TSTATE_ACKED) { + print_string("Closing because everything has been transmitted\n"); uip_close(); + } // write_char('p'); - } else if (uip_newdata()) { + } else if (uip_acked() && s->tstate == TSTATE_TX) { + print_string("ACK\n"); + if (slen > uip_mss()) { + slen -= uip_mss(); + o_idx += uip_mss(); + } else { + slen = 0; + o_idx += slen; + } + + s->tstate = TSTATE_ACKED; + + if (slen > uip_mss()) { + print_string("Sending A: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, uip_mss()); + print_string("Sending A done\n"); + s->tstate = TSTATE_TX; + } else if (slen > 0) { + print_string("Sending B: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, slen); + print_string("Sending B done\n"); + s->tstate = TSTATE_TX; + } + } else if (uip_newdata() && s->tstate != TSTATE_TX) { write_char('<'); print_short(uip_len); write_char('\n'); __xdata uint8_t *p = uip_appdata; + p[uip_len] = 0; while (*p) write_char(*p++); write_char('\n'); @@ -63,13 +115,76 @@ void httpd_appcall(void) *p = '\0'; print_string_x(q); write_char('\n'); - // For now, we do not have anything to send... - uip_len = strlen(page_main); - strtox(outbuf, page_main); - s->transmitted = 1; - uip_send(outbuf, uip_len); + + s->tstate = TSTATE_NONE; + entry = find_entry(q); + print_string("Entry is: "); print_byte(entry); write_char('\n'); + if (entry == 0xff) { + print_string("Not found\n"); + slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n"); + print_string("slen: "); print_short(slen); write_char('\n'); + slen += strtox(outbuf + slen, "\n404 Not Found\n

Not Found

\n"); + } else { + print_string("Have entry\n"); + slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: "); + slen += strtox(outbuf + slen, f_data[entry].mime); + slen += strtox(outbuf + slen, "\r\n\r\n"); + len_left = f_data[entry].len; + if (f_data[entry].mime[0] == 't' && f_data[entry].mime[5] == 'h') { + print_string("MIME is html len is "); print_short(len_left); write_char('\n'); + mpos = 0; + flash_find_mark(f_data[entry].start, len_left, "#{"); + print_string("mpos: "); print_short(mpos); write_char('\n'); + while (mpos != 0xffff) { + print_string("Entry-len:"); print_short(len_left); write_char('\n'); + mpos = len_left - mpos; + print_string("l/pos: "); print_short(mpos); write_char('\n'); + flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, mpos + CMARK_S); // call marker is e.g. #{001} + slen += mpos; + write_char('@'); write_char(outbuf[slen + 2]); write_char(outbuf[slen + 3]); write_char(outbuf[slen + 4]); + fcall_ptr ptr = f_calls[(outbuf[slen + 2] - '0') * 100 + (outbuf[slen + 3]-'0') * 10 + outbuf[slen + 4] - '0']; + slen -= CMARK_S; // Overwrite marker with generated html + print_string("Call location is: "); print_short((uint16_t)ptr); write_char('\n'); +// f_calls[outbuf[slen + 2] * 100 + outbuf[slen + 3] * 10 + outbuf[slen + 4]](); + ptr(); + print_string("call done\n"); + mpos += CMARK_S; + len_left -= mpos; + flash_find_mark(f_data[entry].start + mpos, len_left, "#{"); + } + print_string("At end mpos: "); print_short(mpos); write_char('\n'); + flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, len_left); + slen += len_left; + } else { + print_string("MIME: "); print_string(f_data[entry].mime); write_char('\n'); + flash_read_bulk(outbuf + slen, f_data[entry].start, len_left); + slen += len_left; + } + } + print_string("slen: "); print_short(slen); write_char('\n'); + o_idx = 0; + if (slen > uip_mss()) { + print_string("Sending a: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, uip_mss()); + print_string("Sending a done\n"); + } else { + print_string("Sending b: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, slen); + print_string("Sending b done\n"); + } + s->tstate = TSTATE_TX; } else if (uip_rexmit()) { // Connection established, need to rexmit? - write_char('r'); + print_string("RETRANSMIT requested\n"); + if (slen > uip_mss()) { + print_string("Sending C: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, uip_mss()); + print_string("Sending C done\n"); + } else if (slen > 0) { + print_string("Sending D: "); print_short(slen); write_char('\n'); + uip_send(outbuf + o_idx, slen); + print_string("Sending D done\n"); + } + s->tstate = TSTATE_TX; uip_len = 0; } else { uip_len = 0; diff --git a/httpd/httpd.h b/httpd/httpd.h index 9365058..59ed289 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -11,7 +11,7 @@ allocated together with each TCP connection. One application state for each TCP connection. */ typedef struct httpd_state { - char transmitted; + uint8_t tstate; } uip_tcp_appstate_t; /* Finally we define the application function to be called by uIP. */ diff --git a/uip/uip-conf.h b/uip/uip-conf.h index 06908f8..08f7439 100644 --- a/uip/uip-conf.h +++ b/uip/uip-conf.h @@ -90,25 +90,25 @@ typedef uint16_t u16_t; typedef unsigned short uip_stats_t; /** - * Maximum number of TCP connections. + * Maximum number of TCP connections. TODO: Increase this, but also make the socket state/buffer per-connection. * * \hideinitializer */ -#define UIP_CONF_MAX_CONNECTIONS 40 +#define UIP_CONF_MAX_CONNECTIONS 1 /** - * Maximum number of listening TCP ports. + * Maximum number of listening TCP ports. TODO: increase this! * * \hideinitializer */ -#define UIP_CONF_MAX_LISTENPORTS 40 +#define UIP_CONF_MAX_LISTENPORTS 1 /** * uIP buffer size. * * \hideinitializer */ -#define UIP_CONF_BUFFER_SIZE 2000 +#define UIP_CONF_BUFFER_SIZE 2200 /** * CPU byte order.