From d66931acdfcd8447f78dfa44bb5b53a788e152a8 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 13 Jul 2025 12:03:40 +0200 Subject: [PATCH] Adding initial http daemon implementation --- Makefile | 7 +- hello-world/hello-world.c | 108 --------------------- {hello-world => httpd}/Makefile | 10 +- httpd/httpd.c | 77 +++++++++++++++ hello-world/hello-world.h => httpd/httpd.h | 39 ++------ httpd/treatasm.py | 25 +++++ rtl837x_common.h | 1 + rtlplayground.c | 11 +++ uip/Makefile | 4 +- uip/uip-conf.h | 2 +- uip/uip.c | 24 ++++- 11 files changed, 154 insertions(+), 154 deletions(-) delete mode 100644 hello-world/hello-world.c rename {hello-world => httpd}/Makefile (58%) create mode 100644 httpd/httpd.c rename hello-world/hello-world.h => httpd/httpd.h (50%) create mode 100755 httpd/treatasm.py diff --git a/Makefile b/Makefile index a44b92c..12bc4a7 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,18 @@ BOOTLOADER_ADDRESS=0x100 CC = sdcc -CC_FLAGS = -mmcs51 -Ihello-world -Iuip +CC_FLAGS = -mmcs51 -Ihttpd -Iuip ASM = sdas8051 AFLAGS= -plosgff -SUBDIRS := uip hello-world +SUBDIRS := uip httpd SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS)) all: $(SUBDIRS) rtlplayground.bin injector SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c OBJS = ${SRCS:.c=.rel} -OBJS += uip/psock.rel 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 hello-world/hello-world.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 $(SUBDIRS): @@ -20,6 +20,7 @@ $(SUBDIRS): clean: make -C uip clean + make -C httpd clean 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 diff --git a/hello-world/hello-world.c b/hello-world/hello-world.c deleted file mode 100644 index e09b436..0000000 --- a/hello-world/hello-world.c +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \addtogroup helloworld - * @{ - */ - -/** - * \file - * An example of how to write uIP applications - * with protosockets. - * \author - * Adam Dunkels - */ - -/* - * This is a short example of how to write uIP applications using - * protosockets. - */ - -/* - * We define the application state (struct hello_world_state) in the - * hello-world.h file, so we need to include it here. We also include - * uip.h (since this cannot be included in hello-world.h) and - * , since we use the memcpy() function in the code. - */ -#include "hello-world.h" -#include "../rtl837x_common.h" -#include "uip.h" - -#pragma codeseg BANK1 - -/* - * Declaration of the protosocket function that handles the connection - * (defined at the end of the code). - */ -static uint8_t handle_connection(__xdata struct hello_world_state *s); -/*---------------------------------------------------------------------------*/ -/* - * The initialization function. We must explicitly call this function - * from the system initialization code, some time after uip_init() is - * called. - */ -void -hello_world_init(void) -{ - /* We start to listen for connections on TCP port 1000. */ - uip_listen(HTONS(1000)); -} -/*---------------------------------------------------------------------------*/ -/* - * In hello-world.h we have defined the UIP_APPCALL macro to - * hello_world_appcall so that this funcion is uIP's application - * function. This function is called whenever an uIP event occurs - * (e.g. when a new connection is established, new data arrives, sent - * data is acknowledged, data needs to be retransmitted, etc.). - */ -void -hello_world_appcall(void) -{ - /* - * The uip_conn structure has a field called "appstate" that holds - * the application state of the connection. We make a pointer to - * this to access it easier. - */ - __xdata struct hello_world_state *s = &(uip_conn->appstate); - - /* - * If a new connection was just established, we should initialize - * the protosocket in our applications' state structure. - */ - if(uip_connected()) { - PSOCK_INIT(&s->p, s->inputbuffer, sizeof(s->inputbuffer)); - } - - /* - * Finally, we run the protosocket function that actually handles - * the communication. We pass it a pointer to the application state - * of the current connection. - */ - write_char('A'); - handle_connection(s); -} -/*---------------------------------------------------------------------------*/ -/* - * This is the protosocket function that handles the communication. A - * protosocket function must always return an int, but must never - * explicitly return - all return statements are hidden in the PSOCK - * macros. - */ -static uint8_t -handle_connection(__xdata struct hello_world_state *s) -{ - __xdata char buf[100]; - - PSOCK_BEGIN(&s->p); - - strtox(buf, "Hello. What is your name?\n"); -// PSOCK_SEND_STR(&s->p, &buf[0]); -// PSOCK_SEND_STR(&s->p, "Hello. What is your name?\n"); - PSOCK_READTO(&s->p, '\n'); -// strncpy(s->name, s->inputbuffer, sizeof(s->name)); - strtox(buf, "Name: "); -// PSOCK_SEND_STR(&s->p, &buf[0]); -// PSOCK_SEND_STR(&s->p, s->name); - PSOCK_CLOSE(&s->p); - - PSOCK_END(&s->p); -} -/*---------------------------------------------------------------------------*/ diff --git a/hello-world/Makefile b/httpd/Makefile similarity index 58% rename from hello-world/Makefile rename to httpd/Makefile index 8a2645e..7a30056 100644 --- a/hello-world/Makefile +++ b/httpd/Makefile @@ -3,19 +3,21 @@ CC_FLAGS = -mmcs51 -I. -I../uip ASM = sdas8051 AFLAGS= -plosgff -SRCS = hello-world.c +SRCS = httpd.c OBJS = ${SRCS:.c=.rel} all: $(OBJS) -%.rel: %.c - $(CC) $(CC_FLAGS) -c $< +%.asm: %.c + $(CC) $(CC_FLAGS) -c -S $< %.rel: %.asm + ./treatasm.py $^ >$^.new + mv $^.new $^ ${ASM} ${AFLAGS} $^ clean: - rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin + rm .asm *.lst *.rel *.rst *.sym .PHONY: all clean diff --git a/httpd/httpd.c b/httpd/httpd.c new file mode 100644 index 0000000..e99f35d --- /dev/null +++ b/httpd/httpd.c @@ -0,0 +1,77 @@ + +#include "httpd.h" +#include "../rtl837x_common.h" +#include "uip.h" + +#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"; + +__xdata uint8_t outbuf[2048]; + +inline uint8_t is_space(uint8_t c) +{ + return c == ' ' || c == '\t'; +} + + +void httpd_init(void) __banked +{ + // Start listening to port 80 + uip_listen(HTONS(80)); +} + + +void httpd_appcall(void) +{ + __xdata struct httpd_state *s = &(uip_conn->appstate); + + write_char('P'); + if(uip_connected()) { + print_string("Connected...\n"); + s->transmitted = 0; + } else if (uip_closed()) { + print_string("Connection closed\n"); + } else if (uip_poll()) { + uip_len = 0; + if (s->transmitted) + uip_close(); +// write_char('p'); + } else if (uip_newdata()) { + write_char('<'); print_short(uip_len); write_char('\n'); + __xdata uint8_t *p = uip_appdata; + while (*p) + write_char(*p++); + write_char('\n'); + p = uip_appdata; + if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ') + print_string("GET request "); + p += 4; + __xdata uint8_t *q = p; + while (!is_space(*p)) + p++; + *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); + } else if (uip_rexmit()) { // Connection established, need to rexmit? + write_char('r'); + uip_len = 0; + } else { + uip_len = 0; + } +} diff --git a/hello-world/hello-world.h b/httpd/httpd.h similarity index 50% rename from hello-world/hello-world.h rename to httpd/httpd.h index 5ef333b..9365058 100644 --- a/hello-world/hello-world.h +++ b/httpd/httpd.h @@ -1,24 +1,3 @@ -/** - * \addtogroup apps - * @{ - */ - -/** - * \defgroup helloworld Hello, world - * @{ - * - * A small example showing how to write applications with - * \ref psock "protosockets". - */ - -/** - * \file - * Header file for an example of how to write uIP applications - * with protosockets. - * \author - * Adam Dunkels - */ - #ifndef __HELLO_WORLD_H__ #define __HELLO_WORLD_H__ @@ -27,26 +6,20 @@ u16_t datatypes. */ #include "uipopt.h" -#include "psock.h" - /* Next, we define the uip_tcp_appstate_t datatype. This is the state of our application, and the memory required for this state is allocated together with each TCP connection. One application state for each TCP connection. */ -typedef struct hello_world_state { - struct psock p; - char inputbuffer[10]; - char name[40]; +typedef struct httpd_state { + char transmitted; } uip_tcp_appstate_t; /* Finally we define the application function to be called by uIP. */ -void hello_world_appcall(void); +void httpd_appcall(void); #ifndef UIP_APPCALL -#define UIP_APPCALL hello_world_appcall +#define UIP_APPCALL httpd_appcall #endif /* UIP_APPCALL */ -void hello_world_init(void); +void httpd_init(void) __banked; -#endif /* __HELLO_WORLD_H__ */ -/** @} */ -/** @} */ +#endif diff --git a/httpd/treatasm.py b/httpd/treatasm.py new file mode 100755 index 0000000..2940a3a --- /dev/null +++ b/httpd/treatasm.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +import re +import sys + +isBanked = False + +regex_bank = re.compile(r'^\s*\.area\s+BANK\d+\s*\(CODE\)') +regex_const = re.compile(r'^\s*\.area\s+CONST\s*\(CODE\)') +regex_area = re.compile(r'^\s*\.area\s+\(CODE\)') + +with open(sys.argv[1], "r") as file: + for line in file: + line = line.rstrip() + bmatch = re.search(regex_bank, line) + if bmatch: + isBanked = True + print(line) + else: + cmatch = re.search(regex_const, line) + if not isBanked or not cmatch: + print(line) + amatch = re.search(regex_area, line) + if amatch: + isBanked = False + print(line) diff --git a/rtl837x_common.h b/rtl837x_common.h index a520307..bd48a2f 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -59,5 +59,6 @@ uint16_t strlen(register __code const char *s); uint16_t strlen_x(register __xdata const char *s); void strtox(register __xdata uint8_t *dst, register __code const char *s); void tcpip_output(void); +void print_string_x(__xdata char *p); #endif diff --git a/rtlplayground.c b/rtlplayground.c index 37c636f..e4f9481 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -154,6 +154,12 @@ void print_string(__code char *p) write_char(*p++); } +void print_string_x(__xdata char *p) +{ + while (*p) + write_char(*p++); +} + void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len) { @@ -197,6 +203,9 @@ uint16_t strlen_x(register __xdata const char *s) uint16_t l = 0; while (s[l]) l++; + write_char(';'); + print_short(l); + write_char(';'); return l; } @@ -855,6 +864,7 @@ void handle_tx(void) for(uint8_t i = 0; i < UIP_CONNS; i++) { uip_periodic(i); if(uip_len > 0) { + write_char('.'); print_short(i); uip_arp_out(); tcpip_output(); } @@ -1588,6 +1598,7 @@ void bootloader(void) vlan_setup(); uip_init(); uip_arp_init(); + httpd_init(); was_offline = 1; diff --git a/uip/Makefile b/uip/Makefile index f190653..7a9ef28 100644 --- a/uip/Makefile +++ b/uip/Makefile @@ -1,9 +1,9 @@ CC = sdcc -CC_FLAGS = -mmcs51 -I. -I../hello-world +CC_FLAGS = -mmcs51 -I. -I../httpd ASM = sdas8051 AFLAGS= -plosgff -SRCS = psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c +SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c OBJS = ${SRCS:.c=.rel} all: $(OBJS) diff --git a/uip/uip-conf.h b/uip/uip-conf.h index 083836a..06908f8 100644 --- a/uip/uip-conf.h +++ b/uip/uip-conf.h @@ -148,7 +148,7 @@ typedef unsigned short uip_stats_t; /* Here we include the header file for the application(s) we use in our project. */ /*#include "smtp.h"*/ -#include "hello-world.h" +#include "httpd.h" /*#include "telnetd.h"*/ /*#include "webserver.h" */ /*#include "dhcpc.h"*/ diff --git a/uip/uip.c b/uip/uip.c index 470f3cb..949e1df 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -690,7 +690,9 @@ uip_process(u8_t flag) __banked if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr)) { uip_flags = UIP_POLL; + write_char('B'); UIP_APPCALL(); + write_char('b'); goto appsend; } goto drop; @@ -742,7 +744,9 @@ uip_process(u8_t flag) __banked UIP_TIMEDOUT to inform the application that the connection has timed out. */ uip_flags = UIP_TIMEDOUT; + write_char('C'); UIP_APPCALL(); + write_char('c'); /* We also send a reset packet to the remote host. */ BUF->flags = TCP_RST | TCP_ACK; @@ -781,6 +785,7 @@ uip_process(u8_t flag) __banked the code for sending out the packet (the apprexmit label). */ uip_flags = UIP_REXMIT; + write_char('R'); UIP_APPCALL(); goto apprexmit; @@ -993,8 +998,6 @@ uip_process(u8_t flag) __banked uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); -// ICMPBUF->proto = 0x06; //BUG: Only for testing... - UIP_STAT(++uip_stat.icmp.sent); goto send; @@ -1166,6 +1169,7 @@ uip_process(u8_t flag) __banked /* Start of TCP input header processing code. */ // BUG: We need to reimplement this with RTL837x TCP checksum checking +// i.e. figure out which bit in the RX-tag states the checksum is correct // if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP // checksum. */ // UIP_STAT(++uip_stat.tcp.drop); @@ -1381,7 +1385,9 @@ uip_process(u8_t flag) __banked uip_connr->tcpstateflags = UIP_CLOSED; UIP_LOG("tcp: got reset, aborting connection."); uip_flags = UIP_ABORT; + write_char('F'); UIP_APPCALL(); + write_char('f'); goto drop; } /* Calculated the length of the data, if the application has sent @@ -1470,7 +1476,7 @@ uip_process(u8_t flag) __banked uip_add_rcv_nxt(uip_len); } uip_slen = 0; - UIP_APPCALL(); + UIP_APPCALL(); // UIP_CONNECTED goto appsend; } goto drop; @@ -1525,12 +1531,16 @@ uip_process(u8_t flag) __banked uip_connr->len = 0; uip_len = 0; uip_slen = 0; + write_char('H'); UIP_APPCALL(); + write_char('h'); goto appsend; } /* Inform the application that the connection failed */ uip_flags = UIP_ABORT; + write_char('I'); UIP_APPCALL(); + write_char('I'); /* The connection is closed after we send the RST */ uip_conn->tcpstateflags = UIP_CLOSED; goto reset; @@ -1557,7 +1567,9 @@ uip_process(u8_t flag) __banked if(uip_len > 0) { uip_flags |= UIP_NEWDATA; } + write_char('J'); UIP_APPCALL(); + write_char('j'); uip_connr->len = 1; uip_connr->tcpstateflags = UIP_LAST_ACK; uip_connr->nrtx = 0; @@ -1715,7 +1727,9 @@ uip_process(u8_t flag) __banked if(uip_flags & UIP_ACKDATA) { uip_connr->tcpstateflags = UIP_CLOSED; uip_flags = UIP_CLOSE; + write_char('L'); UIP_APPCALL(); + write_char('l'); } break; @@ -1736,7 +1750,9 @@ uip_process(u8_t flag) __banked } uip_add_rcv_nxt(1); uip_flags = UIP_CLOSE; + write_char('M'); UIP_APPCALL(); + write_char('m'); goto tcp_send_ack; } else if(uip_flags & UIP_ACKDATA) { uip_connr->tcpstateflags = UIP_FIN_WAIT_2; @@ -1757,7 +1773,9 @@ uip_process(u8_t flag) __banked uip_connr->timer = 0; uip_add_rcv_nxt(1); uip_flags = UIP_CLOSE; + write_char('N'); UIP_APPCALL(); + write_char('n'); goto tcp_send_ack; } if(uip_len > 0) {