reworked to single Makefile, fix conversion warnings

master
Ondřej Hruška 2 years ago
parent 59e2223ef7
commit c9b6fd5491
  1. 5
      .gitignore
  2. 179
      Makefile
  3. 7
      demo/.gitignore
  4. 36
      demo/Makefile
  5. 27
      demo/server_demo.c
  6. 9913
      demo/staticfiles.embed.c
  7. 4
      espfsbuilder/.gitignore
  8. 20
      espfsbuilder/Makefile
  9. 0
      fstool/README.md
  10. 0
      fstool/httpd-logging.h
  11. 28
      fstool/main.c
  12. 24
      fstool/parsing.c
  13. 0
      fstool/parsing.h
  14. 0
      fstool/testfiles/LIMECURD.TXT
  15. 0
      fstool/testfiles/mouse.jpg
  16. 0
      fstool/testout/.gitignore
  17. 5
      spritehttpd/.gitignore
  18. 49
      spritehttpd/Makefile
  19. 2
      spritehttpd/include/cgi-espfs.h
  20. 10
      spritehttpd/include/httpd-platform.h
  21. 8
      spritehttpd/include/httpd-utils.h
  22. 10
      spritehttpd/include/httpd.h
  23. 20
      spritehttpd/lib/espfs/espfs.c
  24. 2
      spritehttpd/lib/espfs/espfs.h
  25. 198
      spritehttpd/lib/heatshrink/heatshrink_decoder.c
  26. 263
      spritehttpd/lib/heatshrink/heatshrink_encoder.c
  27. 23
      spritehttpd/src/cgi-espfs.c
  28. 33
      spritehttpd/src/cgi-websocket.c
  29. 12
      spritehttpd/src/httpd-loop.c
  30. 14
      spritehttpd/src/httpd-utils.c
  31. 75
      spritehttpd/src/httpd.c
  32. 2
      spritehttpd/src/utils/base64.c
  33. 10
      spritehttpd/src/utils/sha1.c

5
.gitignore vendored

@ -5,3 +5,8 @@
*.map
*.d
*~
*.a
spritehttpd-demo
staticfiles-embed.c
staticfiles.bin
espfstool

@ -1,14 +1,173 @@
.PHONY: all clean espfsbuilder demo lib
.PHONY: clean all lib demo fstool
all: demo espfsbuilder
# -*- Settings -*-
clean:
make -C ./spritehttpd clean
make -C ./demo clean
make -C ./espfsbuilder clean
DEBUG = 1
PLATFORM ?= POSIX # POSIX or ARM
# -*- Target names -*-
LIB_TARGET = ./libspritehttpd.a
DEMO_TARGET = ./spritehttpd-demo
FSTOOL_TARGET = ./espfstool # Note: keep ./ here so it can be called when building demo
# Handy targets
all: demo lib fstool
demo: $(DEMO_TARGET)
lib: $(LIB_TARGET)
fstool: $(FSTOOL_TARGET)
# -*- Tools -*-
# hex dump tool
XXD ?= xxd
HOST_CC = gcc
ifeq ($(PLATFORM),ARM)
CC = arm-none-eabi-gcc
AR = arm-none-eabi-ar
else
# Probably posix
CC = gcc
AR = ar
endif
# -*- CFLAGS -*-
# Common variables
GIT_HASH = $(shell git rev-parse --short HEAD)
# These flags are used by all targets
COMMON_CFLAGS = -Wall -Wextra -Werror \
-Wshadow -Wfloat-equal -Wundef -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wwrite-strings -Wunreachable-code -Wconversion -Winit-self \
-std=gnu99 -DGIT_HASH='"$(GIT_HASH)"' -ffunction-sections -fdata-sections
# The final binary linker should use -Wl,--gc-sections to take advantage of -ffunction-sections and -fdata-sections
LIB_CFLAGS = $(COMMON_CFLAGS) -c -fPIC
FSTOOL_CFLAGS = $(COMMON_CFLAGS) -DZLIB_CONST -lz
DEMO_CFLAGS = $(COMMON_CFLAGS)
ifeq ($(DEBUG), 1)
COMMON_CFLAGS += -DDEBUG -Og -ggdb
else
FSTOOL_CFLAGS += -O2
DEMO_CFLAGS += -O2
LIB_CFLAGS += -DNDEBUG -Os
endif
# -*- Library -*-
LIB_DIR = spritehttpd
LIB_SOURCES = \
lib/espfs/espfs.c \
lib/heatshrink/heatshrink_decoder.c \
src/utils/base64.c \
src/utils/sha1.c \
src/httpd.c \
src/httpd-auth.c \
src/httpd-utils.c \
src/httpd-loop.c \
src/cgi-espfs.c \
src/cgi-redirects.c \
src/cgi-websocket.c
LIB_INCLUDE_DIRS = \
src \
include \
lib/heatshrink \
lib/espfs
ifeq ($(PLATFORM),ARM)
LIB_SOURCES += src/port/httpd-freertos.c
else
LIB_SOURCES += src/port/httpd-posix.c
endif
espfsbuilder:
make -C ./espfsbuilder
LIB_SOURCES := $(addprefix $(LIB_DIR)/, $(LIB_SOURCES))
LIB_OBJS = $(LIB_SOURCES:.c=.o)
LIB_CFLAGS += $(addprefix -I$(LIB_DIR)/, $(LIB_INCLUDE_DIRS))
demo:
make -C ./demo
# This is only used for the library files. TODO restrict it somehow
%.o: %.c
$(CC) $(LIB_CFLAGS) -o $@ $<
$(LIB_TARGET): $(LIB_OBJS)
$(AR) rcs $@ $^
# -*- Demo -*-
DEMO_DIR = demo
# these won't have dir prefix added - they can refer to other dirs
DEMO_SOURCES = \
$(DEMO_DIR)/server_demo.c \
$(DEMO_DIR)/staticfiles.embed.c
DEMO_INCLUDE_DIRS = \
$(DEMO_DIR) \
$(LIB_DIR)/include
DEMO_STATIC_FILES = \
index.html \
kocour.jpg \
template.tpl.txt
DEMO_OBJS = $(DEMO_SOURCES:.c=.o)
DEMO_STATIC_FILES := $(addprefix $(DEMO_DIR)/staticfiles/, $(DEMO_STATIC_FILES))
DEMO_CFLAGS += $(addprefix -I, $(DEMO_INCLUDE_DIRS))
demo/staticfiles.bin: $(FSTOOL_TARGET) $(DEMO_STATIC_FILES)
# Create the FS image
$(FSTOOL_TARGET) -c1 -g jpg --strip-path demo/staticfiles -o $@ $(DEMO_STATIC_FILES)
# Show content of the image
$(FSTOOL_TARGET) -p $@
demo/staticfiles.embed.c: demo/staticfiles.bin
# Dump the FS image to a C file
$(XXD) -i -n espfs_image $< $@
$(DEMO_TARGET): $(DEMO_SOURCES) $(LIB_TARGET)
$(CC) $(DEMO_CFLAGS) $(DEMO_SOURCES) \
-o $@ \
-lspritehttpd -L.
# FS builder
FSTOOL_DIR = fstool
FSTOOL_SOURCES = \
$(FSTOOL_DIR)/main.c \
$(FSTOOL_DIR)/parsing.c \
$(LIB_DIR)/lib/heatshrink/heatshrink_encoder.c \
$(LIB_DIR)/lib/heatshrink/heatshrink_decoder.c \
$(LIB_DIR)/lib/espfs/espfs.c
FSTOOL_INCLUDE_DIRS = \
$(FSTOOL_DIR) \
$(LIB_DIR)/lib/heatshrink/ \
$(LIB_DIR)/lib/espfs/
FSTOOL_CFLAGS += $(addprefix -I, $(FSTOOL_INCLUDE_DIRS))
$(FSTOOL_TARGET): $(FSTOOL_SOURCES)
$(HOST_CC) $(FSTOOL_CFLAGS) $^ -o $@
# -*- Clean -*-
clean:
rm -f $(FSTOOL_TARGET) $(DEMO_TARGET) $(LIB_TARGET)
find . -type f \( \
-name '*.o' \
-o -name '*.embed.c' \
-o -name '*.d' \
-o -name '*.a' \
-o -name '*.elf' \
-o -name '*.bin' \
\) -delete

7
demo/.gitignore vendored

@ -1,7 +0,0 @@
demo
*.o
.idea/
*.bin
*.a
staticfiles-embed.c
staticfiles.bin

@ -1,36 +0,0 @@
DEMO_SOURCES = server_demo.c staticfiles-embed.c
FSBUILDER = ../espfsbuilder/mkespfsimage
LIBFILE = ../spritehttpd/libspritehttpd.a
STATIC_FILES = \
staticfiles/index.html \
staticfiles/kocour.jpg \
staticfiles/template.tpl.txt
all: demo
$(FSBUILDER):
make -C ../espfsbuilder
staticfiles.bin: $(FSBUILDER) ${STATIC_FILES}
$(FSBUILDER) -c1 -g jpg --strip-path staticfiles -o $@ ${STATIC_FILES}
$(FSBUILDER) -p $@
staticfiles-embed.c: staticfiles.bin
xxd -i -n espfs_image $< $@
clean:
rm -f demo staticfiles.bin staticfiles-embed.c
make -C ../spritehttpd clean
$(LIBFILE):
make -C ../spritehttpd PLATFORM=posix CFLAGS="-Og -g"
demo: ${DEMO_SOURCES} $(LIBFILE)
cc -Og -g -Wall ${DEMO_SOURCES} \
-o $@ \
-I../spritehttpd/include \
-lspritehttpd \
-L../spritehttpd/

@ -74,6 +74,21 @@ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token)
return HTTPD_CGI_DONE;
}
//
//int httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen)
//{
// httpdGetHeader(conn, "Cookie", )
//}
//
//httpd_cgi_state cgiStartSession(HttpdConnData *conn)
//{
//
//
// return HTTPD_CGI_NOTFOUND;
//}
/**
@ -81,6 +96,7 @@ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token)
*/
const HttpdBuiltInUrl routes[] = {
// TODO password lock ...
// ROUTE_CGI("*", cgiStartSession),
// --- Web pages ---
// ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"),
@ -91,17 +107,20 @@ const HttpdBuiltInUrl routes[] = {
ROUTE_END(),
};
void sigpipe_handler(int unused)
void sigpipe_handler(int signum)
{
(void) signum;
}
void handle_sigint(int signum)
{
(void) signum;
fprintf(stderr, " SIGINT detected, shutting down HTTPD\n");
httpdShutdown(s_serverHandle);
}
int main()
int main(void)
{
struct sigaction action;
memset(&action, 0, sizeof(action));
@ -109,7 +128,7 @@ int main()
sigaction(SIGINT, &action, NULL);
// prevent abort on sigpipe
sigaction(SIGPIPE, &(struct sigaction) {{sigpipe_handler}}, NULL);
sigaction(SIGPIPE, &(struct sigaction) {{sigpipe_handler},.sa_mask={}}, NULL);
struct httpd_options opts = {
.port = 8080,
@ -122,7 +141,7 @@ int main()
return 0;
}
int httpdPlatEspfsRead(void *dest, uint32_t offset, size_t len)
int httpdPlatEspfsRead(void *dest, size_t offset, size_t len)
{
if (offset + len > espfs_image_len) {
return -1;

File diff suppressed because it is too large Load Diff

@ -1,4 +0,0 @@
mkespfsimage
*.o
.idea/
*.bin

@ -1,20 +0,0 @@
TARGET=mkespfsimage
SOURCES = main.c parsing.c \
../spritehttpd/lib/heatshrink/heatshrink_encoder.c \
../spritehttpd/lib/heatshrink/heatshrink_decoder.c \
../spritehttpd/lib/espfs/espfs.c
CFLAGS = -I. \
-I../spritehttpd/lib/heatshrink/ \
-I../spritehttpd/lib/espfs/ \
-DZLIB_CONST
all: $(TARGET)
$(TARGET): ${SOURCES}
#cc -O3 -lz $^ -o $@ ${CFLAGS}
cc -Og -g -Wall -Wextra -lz $^ -o $@ ${CFLAGS}
clean:
rm $(TARGET)

@ -60,8 +60,8 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t
const uint8_t *inp = in;
uint8_t *outp = out;
size_t len;
int ws[] = {5, 6, 8, 11, 13};
int ls[] = {3, 3, 4, 4, 4};
uint8_t ws[] = {5, 6, 8, 11, 13};
uint8_t ls[] = {3, 3, 4, 4, 4};
HSE_poll_res pres = 0;
HSE_sink_res sres = 0;
size_t r;
@ -73,7 +73,7 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t
exit(1);
}
//Save encoder parms as first byte
*outp = (ws[level] << 4) | ls[level];
*outp = (uint8_t) ((ws[level] << 4) | ls[level]);
outp++;
outcap--;
@ -123,9 +123,9 @@ size_t compressGzip(const uint8_t *in, size_t insize, uint8_t *out, size_t outca
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.next_in = in;
stream.avail_in = insize;
stream.avail_in = (uInt) insize;
stream.next_out = out;
stream.avail_out = outcap;
stream.avail_out = (uInt) outcap;
// 31 -> 15 window bits + 16 for gzip
zresult = deflateInit2(&stream, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
if (zresult != Z_OK) {
@ -190,7 +190,7 @@ void parseGzipExtensions(char *input)
{
char *token;
char *extList = input;
int count = 2; // one for first element, second for terminator
size_t count = 2; // one for first element, second for terminator
// count elements
while (*extList != 0) {
@ -224,11 +224,11 @@ void parseGzipExtensions(char *input)
int handleFile(int fd, const char *name, int compression_mode, int level, const char **compName)
{
uint8_t *fdat = NULL, *cdat = NULL, *cdatbuf = NULL;
uint32_t size, csize;
size_t size, csize;
EspFsHeader h;
uint16_t realNameLen;
uint8_t flags = 0;
size = lseek(fd, 0, SEEK_END);
size = (size_t) lseek(fd, 0, SEEK_END);
fdat = malloc(size);
lseek(fd, 0, SEEK_SET);
read(fd, fdat, size);
@ -265,17 +265,17 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const
//Fill header data
h.magic = htole32(ESPFS_MAGIC); // ('E' << 0) + ('S' << 8) + ('f' << 16) + ('s' << 24);
h.flags = flags;
h.compression = (int8_t) compression_mode;
h.nameLen = realNameLen = strlen(name) + 1; // zero terminator
uint32_t padbytes = 0;
h.compression = (uint8_t) compression_mode;
h.nameLen = realNameLen = (uint16_t) strlen(name) + 1; // zero terminator
uint16_t padbytes = 0;
if (h.nameLen & 3) {
//Round to next 32bit boundary
padbytes = 4 - (h.nameLen & 3);
h.nameLen += padbytes; // include the bytes in "name" to make parsing easier - these will be zeroed out, so the c-string remains the same.
}
h.nameLen = htole16(h.nameLen);
h.fileLenComp = htole32(csize);
h.fileLenDecomp = htole32(size);
h.fileLenComp = htole32((uint32_t) csize);
h.fileLenDecomp = htole32((uint32_t) size);
write(s_outFd, &h, sizeof(EspFsHeader));
write(s_outFd, name, realNameLen);
@ -319,7 +319,7 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const
/**
* Write final dummy header with FLAG_LASTFILE set.
*/
void finishArchive()
void finishArchive(void)
{
EspFsHeader h;
h.magic = htole32(ESPFS_MAGIC);

@ -7,7 +7,7 @@
#include "parsing.h"
#include "espfs.h"
static size_t espfs_parse_filesize = -1;
static off_t espfs_parse_filesize = -1;
static int espfs_parse_fd = -1;
size_t decompressGzip(const uint8_t *in, size_t insize, int outfd)
@ -22,7 +22,7 @@ size_t decompressGzip(const uint8_t *in, size_t insize, int outfd)
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.next_in = in;
stream.avail_in = insize;
stream.avail_in = (uInt) insize;
stream.next_out = outbuf;
stream.avail_out = OUTBUF_LEN;
// 31 -> 15 window bits + 16 for gzip
@ -40,9 +40,9 @@ size_t decompressGzip(const uint8_t *in, size_t insize, int outfd)
zresult = inflate(&stream, Z_FINISH);
if (zresult == Z_BUF_ERROR || zresult == Z_OK || zresult == Z_STREAM_END) {
int have = OUTBUF_LEN - stream.avail_out;
fprintf(stderr, "inflated: %d\n", have);
if (have != write(outfd, outbuf, have)) {
size_t have = OUTBUF_LEN - stream.avail_out;
fprintf(stderr, "inflated: %d\n", (int) have);
if ((ssize_t)have != write(outfd, outbuf, have)) {
perror("Write output");
exit(1);
}
@ -98,7 +98,7 @@ void parseEspfsImage(const char *imagefile, const char *extractfile, int outfd)
}
if (extractfile) {
EspFsFile * efile = espFsOpen(extractfile);
EspFsFile *efile = espFsOpen(extractfile);
EspFsHeader hdr;
if (!efile) {
@ -117,9 +117,9 @@ void parseEspfsImage(const char *imagefile, const char *extractfile, int outfd)
size_t expected_readlen = isGzip ? hdr.fileLenComp : hdr.fileLenDecomp;
uint8_t *buff = malloc(expected_readlen);
int lenRead = espFsRead(efile, buff, expected_readlen);
if (lenRead != (int) expected_readlen) {
fprintf(stderr, "Fail to read raw file from espfs image - read len %d", lenRead);
size_t lenRead = espFsRead(efile, buff, expected_readlen);
if (lenRead != expected_readlen) {
fprintf(stderr, "Fail to read raw file from espfs image - read len %d", (int) lenRead);
exit(1);
}
@ -152,14 +152,14 @@ void parseEspfsImage(const char *imagefile, const char *extractfile, int outfd)
}
int httpdPlatEspfsRead(void *dest, uint32_t offset, size_t len)
int httpdPlatEspfsRead(void *dest, size_t offset, size_t len)
{
// fprintf(stderr, "FS read @ %d, len %d\n", offset, (int) len);
if (offset + len > espfs_parse_filesize) {
if ((off_t) (offset + len) > espfs_parse_filesize) {
fprintf(stderr, "Read out fo range!\n");
return -1;
}
lseek(espfs_parse_fd, offset, SEEK_SET);
lseek(espfs_parse_fd, (off_t) offset, SEEK_SET);
read(espfs_parse_fd, dest, len);
return 0;
}

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@ -1,5 +0,0 @@
mkespfsimage
*.o
.idea/
*.bin
*.a

@ -1,49 +0,0 @@
# If building for posix:
ifeq ($(PLATFORM),arm-freertos)
CC ?= arm-none-eabi-gcc
AR ?= arm-none-eabi-ar
PORT_SOURCES = src/port/httpd-freertos.c
else
# Probably posix
CC ?= cc
AR ?= ar
PORT_SOURCES = src/port/httpd-posix.c
endif
# additional C flags can be specified via the CFLAGS variable
LIB_FILE = libspritehttpd.a
LIB_SOURCES = ${PORT_SOURCES} \
lib/espfs/espfs.c \
lib/heatshrink/heatshrink_decoder.c \
src/utils/base64.c \
src/utils/sha1.c \
src/httpd.c \
src/httpd-auth.c \
src/httpd-utils.c \
src/httpd-loop.c \
src/cgi-espfs.c \
src/cgi-redirects.c \
src/cgi-websocket.c
LIB_OBJS = $(LIB_SOURCES:.c=.o)
LIB_INCLUDES = -Iinclude -Ilib/heatshrink -Ilib/espfs
LIB_CFLAGS = -fPIC -Wall -Wextra -c -Os -ggdb -std=gnu99 -DGIT_HASH='"$(shell git rev-parse --short HEAD)"'
all: $(LIB_FILE)
%.o: %.c
$(CC) -c $(LIB_INCLUDES) $(CFLAGS) $(LIB_CFLAGS) -o $@ $<
$(LIB_FILE): $(LIB_OBJS)
$(AR) rcs $@ $^
clean:
find . -type f -name '*.o' -delete
find . -type f -name '*.d' -delete
find . -type f -name '*.a' -delete
find . -type f -name '*.elf' -delete

@ -39,7 +39,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn);
* @param len - string len
* @return 1 = OK
*/
int tplSendN(HttpdConnData *conn, const char *str, int len);
int tplSendN(HttpdConnData *conn, const char *str, size_t len);
/**
* Send template substitution string (use strlen)

@ -14,12 +14,12 @@
/**
* Lock the server mutex
*/
void httpdPlatLock();
void httpdPlatLock(void);
/**
* Unlock the server mutex
*/
void httpdPlatUnlock();
void httpdPlatUnlock(void);
/**
* Allocate memory
@ -46,7 +46,7 @@ void httpdPlatDelayMs(uint32_t ms);
/**
* Platform-specific way of terminating the current task
*/
void httpdPlatTaskEnd();
void httpdPlatTaskEnd(void);
/**
* Low-level send data to a socket
@ -75,7 +75,7 @@ void httpdPlatDisableTimeout(ConnTypePtr conn);
/**
* Init platform specific stuff for the http server
*/
void httpdPlatInit();
void httpdPlatInit(void);
/**
* Start the HTTPD server loop
@ -100,7 +100,7 @@ void httpdPlatJoin(httpd_thread_handle_t *handle);
* @param len read length
* @return 0 on success
*/
int httpdPlatEspfsRead(void *dest, uint32_t offset, size_t len);
int httpdPlatEspfsRead(void *dest, size_t offset, size_t len);
/**
* Server task function, called by httpdPlatStart inside a thread.

@ -11,7 +11,7 @@
// Custom helpers
#define streq(a, b) (strcmp((const char*)(a), (const char*)(b)) == 0)
#define strneq(a, b, n) (strncmp((const char*)(a), (const char*)(b), (n)) == 0)
#define strstarts(a, b) strneq((a), (b), (int)strlen((b)))
#define strstarts(a, b) strneq((a), (b), strlen((b)))
#define last_char_n(str, n) ((str))[strlen((str)) - (n)]
#define last_char(str) last_char_n((str), 1)
@ -49,9 +49,9 @@ uint8_t httpdHexVal(char c);
* @param valLen - length of the encoded value field
* @param buff - output buffer, the string will be zero-terminated
* @param buffLen - output buffer size
* @return
* @return Decoded len
*/
int httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen);
size_t httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen);
/**
* Find a specific arg in a string of get- or post-data.
@ -64,7 +64,7 @@ int httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen);
* @param arg - name of the argument to retrieve
* @param[out] buff - output buffer, the string will be zero-terminated
* @param buffLen - output buffer size
* @return
* @return length of the result, or -1
*/
int httpdFindArg(const char *line, const char *arg, char *buff, size_t buffLen);

@ -272,7 +272,7 @@ void httdResponseOptions(HttpdConnData *conn, int cors);
* @param remIp - remote IP (4 bytes)
* @param remPort - remote port
*/
void httpdSentCb(ConnTypePtr conn, const char *remIp, int remPort);
void httpdSentCb(ConnTypePtr conn, const uint8_t *remIp, uint16_t remPort);
/**
* Callback called when there's data available on a socket.
@ -283,7 +283,7 @@ void httpdSentCb(ConnTypePtr conn, const char *remIp, int remPort);
* @param data - data received. This is a mutable buffer
* @param len - data len
*/
void httpdRecvCb(ConnTypePtr conn, const char *remIp, int remPort, uint8_t *data, unsigned short len);
void httpdRecvCb(ConnTypePtr conn, const uint8_t *remIp, uint16_t remPort, uint8_t *data, size_t len);
/**
* The platform layer should ALWAYS call this function, regardless if the connection is closed by the server
@ -293,7 +293,7 @@ void httpdRecvCb(ConnTypePtr conn, const char *remIp, int remPort, uint8_t *data
* @param remIp - remote IP (4 bytes)
* @param remPort - remote port
*/
void httpdDisconCb(ConnTypePtr conn, const char *remIp, int remPort);
void httpdDisconCb(ConnTypePtr conn, const uint8_t *remIp, uint16_t remPort);
/**
* Connect callback - a client connected
@ -303,7 +303,7 @@ void httpdDisconCb(ConnTypePtr conn, const char *remIp, int remPort);
* @param remPort - remote port
* @return 1 = OK, 0 = client couldn't be served
*/
int httpdConnectCb(ConnTypePtr conn, const char *remIp, int remPort);
int httpdConnectCb(ConnTypePtr conn, const uint8_t *remIp, uint16_t remPort);
/**
* Low level function to close & release a connection
@ -318,4 +318,4 @@ void httpdConnRelease(ConnTypePtr conn);
*
* @internal
*/
void httpdInternalCloseAllSockets();
void httpdInternalCloseAllSockets(void);

@ -27,17 +27,17 @@ It's written for use with httpd, but doesn't need to be used as such.
// internal fields
struct EspFsFile {
/// Header pointer
uint32_t headerPos;
size_t headerPos;
/// Decompressor type
uint8_t decompressor;
uint32_t posDecomp;
uint32_t posStart;
uint32_t posComp;
size_t posDecomp;
size_t posStart;
size_t posComp;
heatshrink_decoder *decompData;
};
// forward declaration for use in the stand-alone espfs tool
int httpdPlatEspfsRead(void *dest, uint32_t offset, size_t len);
int httpdPlatEspfsRead(void *dest, size_t offset, size_t len);
EspFsInitResult espFsInit()
@ -113,7 +113,7 @@ bool espFsWalkNext(EspFsWalk *walk, EspFsHeader *header, char *namebuf, size_t n
*filepos = walk->hpos;
}
walk->hpos += sizeof(EspFsHeader) + header->nameLen + header->fileLenComp;
walk->hpos += (uint32_t) (sizeof(EspFsHeader) + header->nameLen + header->fileLenComp);
// Align
while(walk->hpos & 3) {
walk->hpos++;
@ -267,7 +267,7 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
if (fh->decompressor == COMPRESS_NONE) {
int toRead = (int) binary_len - (int) (fh->posComp - fh->posStart);
if (toRead < 0) { toRead = 0; }
if ((int) buf_cap > toRead) { buf_cap = toRead; }
if ((int) buf_cap > toRead) { buf_cap = (size_t) toRead; }
espfs_dbg("[EspFS] Plain data, read chunk @%d: %d", (int)fh->posComp, (int) buf_cap);
rv = httpdPlatEspfsRead(buff, fh->posComp, buf_cap);
if (rv != 0) {
@ -276,7 +276,7 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
fh->posDecomp += buf_cap;
fh->posComp += buf_cap;
return (int) buf_cap;
return buf_cap;
} else if (fh->decompressor == COMPRESS_HEATSHRINK) {
rv = httpdPlatEspfsRead(&decompressed_len, fh->headerPos + offsetof(EspFsHeader, fileLenDecomp), 4);
if (rv != 0) {
@ -323,10 +323,10 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
if (fh->posDecomp == decompressed_len) {
heatshrink_decoder_finish(dec);
}
return (int) decoded_bytes;
return decoded_bytes;
}
}
return (int) buf_cap;
return buf_cap;
}
return 0;
}

@ -52,7 +52,7 @@ EspFsFile *espFsOpenFromHeader(EspFsHeader *h, uint32_t hpos);
*
* @return
*/
EspFsInitResult espFsInit();
EspFsInitResult espFsInit(void);
/**
* Open a file

@ -5,13 +5,13 @@
/* States for the polling state machine. */
typedef enum {
HSDS_TAG_BIT, /* tag bit */
HSDS_YIELD_LITERAL, /* ready to yield literal byte */
HSDS_BACKREF_INDEX_MSB, /* most significant byte of index */
HSDS_BACKREF_INDEX_LSB, /* least significant byte of index */
HSDS_BACKREF_COUNT_MSB, /* most significant byte of count */
HSDS_BACKREF_COUNT_LSB, /* least significant byte of count */
HSDS_YIELD_BACKREF, /* ready to yield back-reference */
HSDS_TAG_BIT, /* tag bit */
HSDS_YIELD_LITERAL, /* ready to yield literal byte */
HSDS_BACKREF_INDEX_MSB, /* most significant byte of index */
HSDS_BACKREF_INDEX_LSB, /* least significant byte of index */
HSDS_BACKREF_COUNT_MSB, /* most significant byte of count */
HSDS_BACKREF_COUNT_LSB, /* least significant byte of count */
HSDS_YIELD_BACKREF, /* ready to yield back-reference */
} HSD_state;
#if HEATSHRINK_DEBUGGING_LOGS
@ -35,21 +35,24 @@ static const char *state_names[] = {
#endif
typedef struct {
uint8_t *buf; /* output buffer */
size_t buf_size; /* buffer size */
size_t *output_size; /* bytes pushed to buffer, so far */
uint8_t *buf; /* output buffer */
size_t buf_size; /* buffer size */
size_t *output_size; /* bytes pushed to buffer, so far */
} output_info;
#define NO_BITS ((uint16_t)-1)
/* Forward references. */
static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count);
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte);
#if HEATSHRINK_DYNAMIC_ALLOC
heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
uint8_t window_sz2,
uint8_t lookahead_sz2) {
uint8_t lookahead_sz2)
{
if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
(window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
(input_buffer_size == 0) ||
@ -57,7 +60,7 @@ heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
(lookahead_sz2 >= window_sz2)) {
return NULL;
}
size_t buffers_sz = (1 << window_sz2) + input_buffer_size;
size_t buffers_sz = ((size_t) 1 << window_sz2) + input_buffer_size;
size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz);
if (hsd == NULL) { return NULL; }
@ -70,15 +73,18 @@ heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
return hsd;
}
void heatshrink_decoder_free(heatshrink_decoder *hsd) {
size_t buffers_sz = (1 << hsd->window_sz2) + hsd->input_buffer_size;
void heatshrink_decoder_free(heatshrink_decoder *hsd)
{
size_t buffers_sz = ((size_t) 1 << hsd->window_sz2) + hsd->input_buffer_size;
size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
HEATSHRINK_FREE(hsd, sz);
(void)sz; /* may not be used by free */
(void) sz; /* may not be used by free */
}
#endif
void heatshrink_decoder_reset(heatshrink_decoder *hsd) {
void heatshrink_decoder_reset(heatshrink_decoder *hsd)
{
size_t buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd);
size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd);
memset(hsd->buffers, 0, buf_sz + input_sz);
@ -94,7 +100,8 @@ void heatshrink_decoder_reset(heatshrink_decoder *hsd) {
/* Copy SIZE bytes into the decoder's input buffer, if it will fit. */
HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd,
uint8_t *in_buf, size_t size, size_t *input_size) {
uint8_t *in_buf, size_t size, size_t *input_size)
{
if ((hsd == NULL) || (in_buf == NULL) || (input_size == NULL)) {
return HSDR_SINK_ERROR_NULL;
}
@ -109,7 +116,7 @@ HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd,
LOG("-- sinking %zd bytes\n", size);
/* copy into input buffer (at head of buffers) */
memcpy(&hsd->buffers[hsd->input_size], in_buf, size);
hsd->input_size += (uint16_t)size;
hsd->input_size += (uint16_t) size;
*input_size = size;
return HSDR_SINK_OK;
}
@ -124,17 +131,24 @@ HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd,
// States
static HSD_state st_tag_bit(heatshrink_decoder *hsd);
static HSD_state st_yield_literal(heatshrink_decoder *hsd,
output_info *oi);
output_info *oi);
static HSD_state st_backref_index_msb(heatshrink_decoder *hsd);
static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd);
static HSD_state st_backref_count_msb(heatshrink_decoder *hsd);
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd);
static HSD_state st_yield_backref(heatshrink_decoder *hsd,
output_info *oi);
output_info *oi);
HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd,
uint8_t *out_buf, size_t out_buf_size, size_t *output_size) {
uint8_t *out_buf, size_t out_buf_size, size_t *output_size)
{
if ((hsd == NULL) || (out_buf == NULL) || (output_size == NULL)) {
return HSDR_POLL_ERROR_NULL;
}
@ -151,31 +165,31 @@ HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd,
uint8_t in_state = hsd->state;
HSD_state next_state;
switch (in_state) {
case HSDS_TAG_BIT:
next_state = st_tag_bit(hsd);
break;
case HSDS_YIELD_LITERAL:
next_state = st_yield_literal(hsd, &oi);
break;
case HSDS_BACKREF_INDEX_MSB:
next_state = st_backref_index_msb(hsd);
break;
case HSDS_BACKREF_INDEX_LSB:
next_state = st_backref_index_lsb(hsd);
break;
case HSDS_BACKREF_COUNT_MSB:
next_state = st_backref_count_msb(hsd);
break;
case HSDS_BACKREF_COUNT_LSB:
next_state = st_backref_count_lsb(hsd);
break;
case HSDS_YIELD_BACKREF:
next_state = st_yield_backref(hsd, &oi);
break;
default:
return HSDR_POLL_ERROR_UNKNOWN;
case HSDS_TAG_BIT:
next_state = st_tag_bit(hsd);
break;
case HSDS_YIELD_LITERAL:
next_state = st_yield_literal(hsd, &oi);
break;
case HSDS_BACKREF_INDEX_MSB:
next_state = st_backref_index_msb(hsd);
break;
case HSDS_BACKREF_INDEX_LSB:
next_state = st_backref_index_lsb(hsd);
break;
case HSDS_BACKREF_COUNT_MSB:
next_state = st_backref_count_msb(hsd);
break;
case HSDS_BACKREF_COUNT_LSB:
next_state = st_backref_count_lsb(hsd);
break;
case HSDS_YIELD_BACKREF:
next_state = st_yield_backref(hsd, &oi);
break;
default:
return HSDR_POLL_ERROR_UNKNOWN;
}
hsd->state = (uint8_t)next_state;
hsd->state = (uint8_t) next_state;
/* If the current state cannot advance, check if input or output
* buffer are exhausted. */
@ -186,7 +200,8 @@ HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd,
}
}
static HSD_state st_tag_bit(heatshrink_decoder *hsd) {
static HSD_state st_tag_bit(heatshrink_decoder *hsd)
{
const uint32_t bits = get_bits(hsd, 1); // get tag bit
if (bits == NO_BITS) {
return HSDS_TAG_BIT;
@ -205,7 +220,8 @@ static HSD_state st_tag_bit(heatshrink_decoder *hsd) {
}
static HSD_state st_yield_literal(heatshrink_decoder *hsd,
output_info *oi) {
output_info *oi)
{
/* Emit a repeated section from the window buffer, and add it (again)
* to the window buffer. (Note that the repetition can include
* itself.)*/
@ -213,8 +229,8 @@ static HSD_state st_yield_literal(heatshrink_decoder *hsd,
uint16_t byte = get_bits(hsd, 8);
if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */
uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)];
uint16_t mask = (uint16_t)(1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
uint8_t c = byte & 0xFF;
uint16_t mask = (uint16_t) (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
uint8_t c = (uint8_t) (byte & 0xFF);
LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.');
buf[hsd->head_index++ & mask] = c;
push_byte(hsd, oi, c);
@ -224,17 +240,19 @@ static HSD_state st_yield_literal(heatshrink_decoder *hsd,
}
}
static HSD_state st_backref_index_msb(heatshrink_decoder *hsd) {
static HSD_state st_backref_index_msb(heatshrink_decoder *hsd)
{
uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
ASSERT(bit_ct > 8);
uint16_t bits = get_bits(hsd, bit_ct - 8);
LOG("-- backref index (msb), got 0x%04x (+1)\n", bits);
if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_MSB; }
hsd->output_index = (uint16_t)(bits << 8);
hsd->output_index = (uint16_t) (bits << 8);
return HSDS_BACKREF_INDEX_LSB;
}
static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd) {
static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd)
{
uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
uint16_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8);
LOG("-- backref index (lsb), got 0x%04x (+1)\n", bits);
@ -246,17 +264,19 @@ static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd) {
return (br_bit_ct > 8) ? HSDS_BACKREF_COUNT_MSB : HSDS_BACKREF_COUNT_LSB;
}
static HSD_state st_backref_count_msb(heatshrink_decoder *hsd) {
static HSD_state st_backref_count_msb(heatshrink_decoder *hsd)
{
uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
ASSERT(br_bit_ct > 8);
uint16_t bits = get_bits(hsd, br_bit_ct - 8);
LOG("-- backref count (msb), got 0x%04x (+1)\n", bits);
if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_MSB; }
hsd->output_count = (uint16_t)(bits << 8);
hsd->output_count = (uint16_t) (bits << 8);
return HSDS_BACKREF_COUNT_LSB;
}
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd) {
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd)
{
uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
uint16_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8);
LOG("-- backref count (lsb), got 0x%04x (+1)\n", bits);
@ -267,26 +287,27 @@ static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd) {
}
static HSD_state st_yield_backref(heatshrink_decoder *hsd,
output_info *oi) {
output_info *oi)
{
size_t count = oi->buf_size - *oi->output_size;
if (count > 0) {
size_t i = 0;
if (hsd->output_count < count) count = hsd->output_count;
if (hsd->output_count < count) { count = hsd->output_count; }
uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)];
uint16_t mask = (uint16_t)((1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1);
uint16_t mask = (uint16_t) ((1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1);
uint16_t neg_offset = hsd->output_index;
LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset);
ASSERT(neg_offset <= mask + 1);
ASSERT(count <= (size_t)(1 << BACKREF_COUNT_BITS(hsd)));
ASSERT(count <= (size_t) (1 << BACKREF_COUNT_BITS(hsd)));
for (i=0; i<count; i++) {
for (i = 0; i < count; i++) {
uint8_t c = buf[(hsd->head_index - neg_offset) & mask];
push_byte(hsd, oi, c);
buf[hsd->head_index & mask] = c;
hsd->head_index++;
LOG(" -- ++ 0x%02x\n", c);
}
hsd->output_count -= (uint16_t)count;
hsd->output_count -= (uint16_t) count;
if (hsd->output_count == 0) { return HSDS_TAG_BIT; }
}
return HSDS_YIELD_BACKREF;
@ -294,7 +315,8 @@ static HSD_state st_yield_backref(heatshrink_decoder *hsd,
/* Get the next COUNT bits from the input buffer, saving incremental progress.
* Returns NO_BITS on end of input, or if more than 15 bits are requested. */
static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count) {
static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count)
{
uint16_t accumulator = 0;
int i = 0;
if (count > 15) { return NO_BITS; }
@ -326,12 +348,12 @@ static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count) {
accumulator |= 0x01;
if (0) {
LOG(" -- got 1, accumulator 0x%04x, bit_index 0x%02x\n",
accumulator, hsd->bit_index);
accumulator, hsd->bit_index);
}
} else {
if (0) {
LOG(" -- got 0, accumulator 0x%04x, bit_index 0x%02x\n",
accumulator, hsd->bit_index);
accumulator, hsd->bit_index);
}
}
hsd->bit_index >>= 1;
@ -341,34 +363,36 @@ static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count) {
return accumulator;
}
HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd) {
HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd)
{
if (hsd == NULL) { return HSDR_FINISH_ERROR_NULL; }
switch (hsd->state) {
case HSDS_TAG_BIT:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
/* If we want to finish with no input, but are in these states, it's
* because the 0-bit padding to the last byte looks like a backref
* marker bit followed by all 0s for index and count bits. */
case HSDS_BACKREF_INDEX_LSB:
case HSDS_BACKREF_INDEX_MSB:
case HSDS_BACKREF_COUNT_LSB:
case HSDS_BACKREF_COUNT_MSB:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
/* If the output stream is padded with 0xFFs (possibly due to being in
* flash memory), also explicitly check the input size rather than
* uselessly returning MORE but yielding 0 bytes when polling. */
case HSDS_YIELD_LITERAL:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
default:
return HSDR_FINISH_MORE;
case HSDS_TAG_BIT:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
/* If we want to finish with no input, but are in these states, it's
* because the 0-bit padding to the last byte looks like a backref
* marker bit followed by all 0s for index and count bits. */
case HSDS_BACKREF_INDEX_LSB:
case HSDS_BACKREF_INDEX_MSB:
case HSDS_BACKREF_COUNT_LSB:
case HSDS_BACKREF_COUNT_MSB:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
/* If the output stream is padded with 0xFFs (possibly due to being in
* flash memory), also explicitly check the input size rather than
* uselessly returning MORE but yielding 0 bytes when polling. */
case HSDS_YIELD_LITERAL:
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
default:
return HSDR_FINISH_MORE;
}
}
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte) {
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
{
LOG(" -- pushing byte: 0x%02x ('%c')\n", byte, isprint(byte) ? byte : '.');
oi->buf[(*oi->output_size)++] = byte;
(void)hsd;
(void) hsd;
}

@ -4,16 +4,16 @@
#include "heatshrink_encoder.h"
typedef enum {
HSES_NOT_FULL, /* input buffer not full enough */
HSES_FILLED, /* buffer is full */
HSES_SEARCH, /* searching for patterns */
HSES_YIELD_TAG_BIT, /* yield tag bit */
HSES_YIELD_LITERAL, /* emit literal byte */
HSES_YIELD_BR_INDEX, /* yielding backref index */
HSES_YIELD_BR_LENGTH, /* yielding backref length */
HSES_SAVE_BACKLOG, /* copying buffer to backlog */
HSES_FLUSH_BITS, /* flush bit buffer */
HSES_DONE, /* done */
HSES_NOT_FULL, /* input buffer not full enough */
HSES_FILLED, /* buffer is full */
HSES_SEARCH, /* searching for patterns */
HSES_YIELD_TAG_BIT, /* yield tag bit */
HSES_YIELD_LITERAL, /* emit literal byte */
HSES_YIELD_BR_INDEX, /* yielding backref index */
HSES_YIELD_BR_LENGTH, /* yielding backref length */
HSES_SAVE_BACKLOG, /* copying buffer to backlog */
HSES_FLUSH_BITS, /* flush bit buffer */
HSES_DONE, /* done */
} HSE_state;
#if HEATSHRINK_DEBUGGING_LOGS
@ -41,34 +41,44 @@ static const char *state_names[] = {
// Encoder flags
enum {
FLAG_IS_FINISHING = 0x01,
FLAG_IS_FINISHING = 0x01,
};
typedef struct {
uint8_t *buf; /* output buffer */
size_t buf_size; /* buffer size */
size_t *output_size; /* bytes pushed to buffer, so far */
uint8_t *buf; /* output buffer */
size_t buf_size; /* buffer size */
size_t *output_size; /* bytes pushed to buffer, so far */
} output_info;
#define MATCH_NOT_FOUND ((uint16_t)-1)
static uint16_t get_input_offset(heatshrink_encoder *hse);
static uint16_t get_input_buffer_size(heatshrink_encoder *hse);
static uint16_t get_lookahead_size(heatshrink_encoder *hse);
static void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag);
static int can_take_byte(output_info *oi);
static int is_finishing(heatshrink_encoder *hse);
static void save_backlog(heatshrink_encoder *hse);
/* Push COUNT (max 8) bits to the output buffer, which has room. */
static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits,
output_info *oi);
output_info *oi);
static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi);
static void push_literal_byte(heatshrink_encoder *hse, output_info *oi);
#if HEATSHRINK_DYNAMIC_ALLOC
heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
uint8_t lookahead_sz2) {
uint8_t lookahead_sz2)
{
if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
(window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
(lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) ||
@ -89,13 +99,13 @@ heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
heatshrink_encoder_reset(hse);
#if HEATSHRINK_USE_INDEX
size_t index_sz = buf_sz*sizeof(uint16_t);
size_t index_sz = buf_sz * sizeof(uint16_t);
hse->search_index = HEATSHRINK_MALLOC(index_sz + sizeof(struct hs_index));
if (hse->search_index == NULL) {
HEATSHRINK_FREE(hse, sizeof(*hse) + buf_sz);
return NULL;
}
hse->search_index->size = (uint16_t)index_sz;
hse->search_index->size = (uint16_t) index_sz;
#endif
LOG("-- allocated encoder with buffer size of %zu (%u byte input size)\n",
@ -103,19 +113,22 @@ heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
return hse;
}
void heatshrink_encoder_free(heatshrink_encoder *hse) {
void heatshrink_encoder_free(heatshrink_encoder *hse)
{
size_t buf_sz = (2U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
#if HEATSHRINK_USE_INDEX
size_t index_sz = sizeof(struct hs_index) + hse->search_index->size;
HEATSHRINK_FREE(hse->search_index, index_sz);
(void)index_sz;
(void) index_sz;
#endif
HEATSHRINK_FREE(hse, sizeof(heatshrink_encoder) + buf_sz);
(void)buf_sz;
(void) buf_sz;
}
#endif
void heatshrink_encoder_reset(heatshrink_encoder *hse) {
void heatshrink_encoder_reset(heatshrink_encoder *hse)
{
size_t buf_sz = (2U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
memset(hse->buffer, 0, buf_sz);
hse->input_size = 0;
@ -129,13 +142,14 @@ void heatshrink_encoder_reset(heatshrink_encoder *hse) {
hse->outgoing_bits = 0x0000;
hse->outgoing_bits_count = 0;
#ifdef LOOP_DETECT
#ifdef LOOP_DETECT
hse->loop_detect = (uint32_t)-1;
#endif
#endif
}
HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse,
const uint8_t *in_buf, size_t size, size_t *input_size) {
const uint8_t *in_buf, size_t size, size_t *input_size)
{
if ((hse == NULL) || (in_buf == NULL) || (input_size == NULL)) {
return HSER_SINK_ERROR_NULL;
}
@ -149,7 +163,7 @@ HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse,
uint16_t write_offset = get_input_offset(hse) + hse->input_size;
uint16_t ibs = get_input_buffer_size(hse);
uint16_t rem = ibs - hse->input_size;
uint16_t cp_sz = rem < size ? rem : (uint16_t)size;
uint16_t cp_sz = rem < size ? rem : (uint16_t) size;
memcpy(&hse->buffer[write_offset], in_buf, cp_sz);
*input_size = cp_sz;
@ -171,24 +185,32 @@ HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse,
***************/
static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
uint16_t end, const uint16_t maxlen, uint16_t *match_length);
uint16_t end, const uint16_t maxlen, uint16_t *match_length);
static void do_indexing(heatshrink_encoder *hse);
static HSE_state st_step_search(heatshrink_encoder *hse);
static HSE_state st_yield_tag_bit(heatshrink_encoder *hse,
output_info *oi);
output_info *oi);
static HSE_state st_yield_literal(heatshrink_encoder *hse,
output_info *oi);
output_info *oi);
static HSE_state st_yield_br_index(heatshrink_encoder *hse,
output_info *oi);
output_info *oi);
static HSE_state st_yield_br_length(heatshrink_encoder *hse,
output_info *oi);
output_info *oi);
static HSE_state st_save_backlog(heatshrink_encoder *hse);
static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse,
output_info *oi);
output_info *oi);
HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse,
uint8_t *out_buf, size_t out_buf_size, size_t *output_size) {
uint8_t *out_buf, size_t out_buf_size, size_t *output_size)
{
if ((hse == NULL) || (out_buf == NULL) || (output_size == NULL)) {
return HSER_POLL_ERROR_NULL;
}
@ -211,49 +233,50 @@ HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse,
HSE_state next_state;
switch (in_state) {
case HSES_NOT_FULL:
return HSER_POLL_EMPTY;
case HSES_FILLED:
do_indexing(hse);
next_state = HSES_SEARCH;
break;
case HSES_SEARCH:
next_state = st_step_search(hse);
break;
case HSES_YIELD_TAG_BIT:
next_state = st_yield_tag_bit(hse, &oi);
break;
case HSES_YIELD_LITERAL:
next_state = st_yield_literal(hse, &oi);
break;
case HSES_YIELD_BR_INDEX:
next_state = st_yield_br_index(hse, &oi);
break;
case HSES_YIELD_BR_LENGTH:
next_state = st_yield_br_length(hse, &oi);
break;
case HSES_SAVE_BACKLOG:
next_state = st_save_backlog(hse);
break;
case HSES_FLUSH_BITS:
hse->state = (uint8_t)st_flush_bit_buffer(hse, &oi);
return HSER_POLL_EMPTY;
case HSES_DONE:
return HSER_POLL_EMPTY;
default:
LOG("-- bad state %s\n", state_names[hse->state]);
return HSER_POLL_ERROR_MISUSE;
case HSES_NOT_FULL:
return HSER_POLL_EMPTY;
case HSES_FILLED:
do_indexing(hse);
next_state = HSES_SEARCH;
break;
case HSES_SEARCH:
next_state = st_step_search(hse);
break;
case HSES_YIELD_TAG_BIT:
next_state = st_yield_tag_bit(hse, &oi);
break;
case HSES_YIELD_LITERAL:
next_state = st_yield_literal(hse, &oi);
break;
case HSES_YIELD_BR_INDEX:
next_state = st_yield_br_index(hse, &oi);
break;
case HSES_YIELD_BR_LENGTH:
next_state = st_yield_br_length(hse, &oi);
break;
case HSES_SAVE_BACKLOG:
next_state = st_save_backlog(hse);
break;
case HSES_FLUSH_BITS:
hse->state = (uint8_t) st_flush_bit_buffer(hse, &oi);
return HSER_POLL_EMPTY;
case HSES_DONE:
return HSER_POLL_EMPTY;
default:
LOG("-- bad state %s\n", state_names[hse->state]);
return HSER_POLL_ERROR_MISUSE;
}
hse->state = (uint8_t)next_state;
hse->state = (uint8_t) next_state;
if (hse->state == in_state) {
/* Check if output buffer is exhausted. */
if (*output_size == out_buf_size) return HSER_POLL_MORE;
if (*output_size == out_buf_size) { return HSER_POLL_MORE; }
}
}
}
HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse) {
HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse)
{
if (hse == NULL) { return HSER_FINISH_ERROR_NULL; }
LOG("-- setting is_finishing flag\n");
hse->flags |= FLAG_IS_FINISHING;
@ -261,12 +284,13 @@ HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse) {
return hse->state == HSES_DONE ? HSER_FINISH_DONE : HSER_FINISH_MORE;
}
static HSE_state st_step_search(heatshrink_encoder *hse) {
static HSE_state st_step_search(heatshrink_encoder *hse)
{
uint16_t window_length = get_input_buffer_size(hse);
uint16_t lookahead_sz = get_lookahead_size(hse);
uint16_t msi = hse->match_scan_index;
LOG("## step_search, scan @ +%d (%d/%d), input size %d\n",
msi, hse->input_size + msi, 2*window_length, hse->input_size);
msi, hse->input_size + msi, 2 * window_length, hse->input_size);
bool fin = is_finishing(hse);
if (msi > hse->input_size - (fin ? 1 : lookahead_sz)) {
@ -287,7 +311,7 @@ static HSE_state st_step_search(heatshrink_encoder *hse) {
uint16_t match_length = 0;
uint16_t match_pos = find_longest_match(hse,
start, end, max_possible, &match_length);
start, end, max_possible, &match_length);
if (match_pos == MATCH_NOT_FOUND) {
LOG("ss Match not found\n");
@ -305,7 +329,8 @@ static HSE_state st_step_search(heatshrink_encoder *hse) {
}
static HSE_state st_yield_tag_bit(heatshrink_encoder *hse,
output_info *oi) {
output_info *oi)
{
if (can_take_byte(oi)) {
if (hse->match_length == 0) {
add_tag_bit(hse, oi, HEATSHRINK_LITERAL_MARKER);
@ -322,7 +347,8 @@ static HSE_state st_yield_tag_bit(heatshrink_encoder *hse,
}
static HSE_state st_yield_literal(heatshrink_encoder *hse,
output_info *oi) {
output_info *oi)
{
if (can_take_byte(oi)) {
push_literal_byte(hse, oi);
return HSES_SEARCH;
@ -332,7 +358,8 @@ static HSE_state st_yield_literal(heatshrink_encoder *hse,
}
static HSE_state st_yield_br_index(heatshrink_encoder *hse,
output_info *oi) {
output_info *oi)
{
if (can_take_byte(oi)) {
LOG("-- yielding backref index %u\n", hse->match_pos);
if (push_outgoing_bits(hse, oi) > 0) {
@ -348,7 +375,8 @@ static HSE_state st_yield_br_index(heatshrink_encoder *hse,
}
static HSE_state st_yield_br_length(heatshrink_encoder *hse,
output_info *oi) {
output_info *oi)
{
if (can_take_byte(oi)) {
LOG("-- yielding backref length %u\n", hse->match_length);
if (push_outgoing_bits(hse, oi) > 0) {
@ -363,14 +391,16 @@ static HSE_state st_yield_br_length(heatshrink_encoder *hse,
}
}
static HSE_state st_save_backlog(heatshrink_encoder *hse) {
static HSE_state st_save_backlog(heatshrink_encoder *hse)
{
LOG("-- saving backlog\n");
save_backlog(hse);
return HSES_NOT_FULL;
}
static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse,
output_info *oi) {
output_info *oi)
{
if (hse->bit_index == 0x80) {
LOG("-- done!\n");
return HSES_DONE;
@ -384,26 +414,31 @@ static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse,
}
}
static void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag) {
static void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag)
{
LOG("-- adding tag bit: %d\n", tag);
push_bits(hse, 1, tag, oi);
}
static uint16_t get_input_offset(heatshrink_encoder *hse) {
static uint16_t get_input_offset(heatshrink_encoder *hse)
{
return get_input_buffer_size(hse);
}
static uint16_t get_input_buffer_size(heatshrink_encoder *hse) {
(void)hse;
return (uint16_t)(1U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
static uint16_t get_input_buffer_size(heatshrink_encoder *hse)
{
(void) hse;
return (uint16_t) (1U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
}
static uint16_t get_lookahead_size(heatshrink_encoder *hse) {
(void)hse;
return (uint16_t)(1U << HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
static uint16_t get_lookahead_size(heatshrink_encoder *hse)
{
(void) hse;
return (uint16_t) (1U << HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
}
static void do_indexing(heatshrink_encoder *hse) {
static void do_indexing(heatshrink_encoder *hse)
{
#if HEATSHRINK_USE_INDEX
/* Build an index array I that contains flattened linked lists
* for the previous instances of every byte in the buffer.
@ -425,8 +460,8 @@ static void do_indexing(heatshrink_encoder *hse) {
int16_t last[256];
memset(last, 0xFF, sizeof(last));
uint8_t * const data = hse->buffer;
int16_t * const index = hsi->index;
uint8_t *const data = hse->buffer;
int16_t *const index = hsi->index;
const uint16_t input_offset = get_input_offset(hse);
const uint16_t end = input_offset + hse->input_size;
@ -442,18 +477,21 @@ static void do_indexing(heatshrink_encoder *hse) {
#endif
}
static int is_finishing(heatshrink_encoder *hse) {
static int is_finishing(heatshrink_encoder *hse)
{
return hse->flags & FLAG_IS_FINISHING;
}
static int can_take_byte(output_info *oi) {
static int can_take_byte(output_info *oi)
{
return *oi->output_size < oi->buf_size;
}
/* Return the longest match for the bytes at buf[end:end+maxlen] between
* buf[start] and buf[end-1]. If no match is found, return -1. */
static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
uint16_t end, const uint16_t maxlen, uint16_t *match_length) {
uint16_t end, const uint16_t maxlen, uint16_t *match_length)
{
LOG("-- scanning for match of buf[%u:%u] between buf[%u:%u] (max %u bytes)\n",
end, end + maxlen, start, end + maxlen - 1, maxlen);
uint8_t *buf = hse->buffer;
@ -462,13 +500,13 @@ static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
uint16_t match_index = MATCH_NOT_FOUND;
uint16_t len = 0;
uint8_t * const needlepoint = &buf[end];
uint8_t *const needlepoint = &buf[end];
#if HEATSHRINK_USE_INDEX
struct hs_index *hsi = HEATSHRINK_ENCODER_INDEX(hse);
int16_t pos = hsi->index[end];
while (pos - (int16_t)start >= 0) {
uint8_t * const pospoint = &buf[pos];
while (pos - (int16_t) start >= 0) {
uint8_t *const pospoint = &buf[pos];
/* Only check matches that will potentially beat the current maxlen.
* This is redundant with the index if match_maxlen is 0, but the
@ -479,12 +517,12 @@ static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
}
for (len = 1; len < maxlen; len++) {
if (pospoint[len] != needlepoint[len]) break;
if (pospoint[len] != needlepoint[len]) { break; }
}
if (len > match_maxlen) {
match_maxlen = len;
match_index = (uint16_t)pos;
match_index = (uint16_t) pos;
if (len == maxlen) { break; } /* won't find better */
}
pos = hsi->index[pos];
@ -510,9 +548,8 @@ static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
}
#endif
const size_t break_even_point =
(1 + HEATSHRINK_ENCODER_WINDOW_BITS(hse) +
HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
const size_t break_even_point = (size_t) (1 + HEATSHRINK_ENCODER_WINDOW_BITS(hse)
+ HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
/* Instead of comparing break_even_point against 8*match_maxlen,
* compare match_maxlen against break_even_point/8 to avoid
@ -528,15 +565,16 @@ static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
return MATCH_NOT_FOUND;
}
static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi) {
static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi)
{
uint8_t count = 0;
uint8_t bits = 0;
if (hse->outgoing_bits_count > 8) {
count = 8;
bits = (uint8_t)(hse->outgoing_bits >> (hse->outgoing_bits_count - 8));
bits = (uint8_t) (hse->outgoing_bits >> (hse->outgoing_bits_count - 8));
} else {
count = hse->outgoing_bits_count;
bits = (uint8_t)hse->outgoing_bits;
bits = (uint8_t) hse->outgoing_bits;
}
if (count > 0) {
@ -550,7 +588,8 @@ static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi) {
/* Push COUNT (max 8) bits to the output buffer, which has room.
* Bytes are set from the lowest bits, up. */
static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits,
output_info *oi) {
output_info *oi)
{
ASSERT(count <= 8);
LOG("++ push_bits: %d bits, input of 0x%02x\n", count, bits);
@ -559,7 +598,7 @@ static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits,
if (count == 8 && hse->bit_index == 0x80) {
oi->buf[(*oi->output_size)++] = bits;
} else {
for (int i=count - 1; i>=0; i--) {
for (int i = count - 1; i >= 0; i--) {
bool bit = bits & (1 << i);
if (bit) { hse->current_byte |= hse->bit_index; }
if (0) {
@ -577,7 +616,8 @@ static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits,
}
}
static void push_literal_byte(heatshrink_encoder *hse, output_info *oi) {
static void push_literal_byte(heatshrink_encoder *hse, output_info *oi)
{
uint16_t processed_offset = hse->match_scan_index - 1;
uint16_t input_offset = get_input_offset(hse) + processed_offset;
uint8_t c = hse->buffer[input_offset];
@ -586,7 +626,8 @@ static void push_literal_byte(heatshrink_encoder *hse, output_info *oi) {
push_bits(hse, 8, c, oi);
}
static void save_backlog(heatshrink_encoder *hse) {
static void save_backlog(heatshrink_encoder *hse)
{
size_t input_buf_sz = get_input_buffer_size(hse);
uint16_t msi = hse->match_scan_index;
@ -595,13 +636,13 @@ static void save_backlog(heatshrink_encoder *hse) {
* used for future matches. Don't bother checking whether the
* input is less than the maximum size, because if it isn't,
* we're done anyway. */
uint16_t rem = (uint16_t)input_buf_sz - msi; // unprocessed bytes
uint16_t shift_sz = (uint16_t)input_buf_sz + rem;
uint16_t rem = (uint16_t) input_buf_sz - msi; // unprocessed bytes
uint16_t shift_sz = (uint16_t) input_buf_sz + rem;
memmove(&hse->buffer[0],
&hse->buffer[input_buf_sz - rem],
shift_sz);
&hse->buffer[input_buf_sz - rem],
shift_sz);
hse->match_scan_index = 0;
hse->input_size -= (uint16_t)input_buf_sz - rem;
hse->input_size -= (uint16_t) (input_buf_sz - rem);
}

@ -85,7 +85,7 @@ EspFsFile *tryOpenIndex(const char *path)
static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepath)
{
EspFsFile *file = hconn->cgiData;
int len;
size_t len;
uint8_t buff[FILE_CHUNK_LEN + 1];
char acceptEncodingBuffer[64 + 1];
int isGzip;
@ -182,21 +182,21 @@ typedef enum {
typedef struct {
EspFsFile *file;
int tokenPos;
ssize_t tokenPos;
char buff[FILE_CHUNK_LEN + 1];
char token[HTTPD_ESPFS_TOKEN_LEN];
char *pToken;
bool chunk_resume;
int buff_len;
int buff_x;
int buff_sp;
size_t buff_len;
size_t buff_x;
size_t buff_sp;
char *buff_e;
TplEncode tokEncode;
} TplDataInternal;
int tplSendN(HttpdConnData *conn, const char *str, int len)
int tplSendN(HttpdConnData *conn, const char *str, size_t len)
{
if (conn == NULL) { return 0; }
@ -206,9 +206,9 @@ int tplSendN(HttpdConnData *conn, const char *str, int len)
if (tdi->tokEncode == ENCODE_PLAIN) {
return httpdSendStrN(conn, str, len);
} else if (tdi->tokEncode == ENCODE_HTML) {
return httpdSend_html(conn, str, len);
return httpdSend_html(conn, str, (ssize_t) len);
} else if (tdi->tokEncode == ENCODE_JS) {
return httpdSend_js(conn, str, len);
return httpdSend_js(conn, str, (ssize_t) len);
}
return 0;
}
@ -218,8 +218,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
{
TplDataInternal *tdi = conn->cgiData;
int len;
int x, sp = 0;
size_t len, x, sp;
char *e = NULL;
if (conn->conn == NULL) {
@ -383,7 +382,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
// looks like we collected some garbage, put it back
httpdSendStrN(conn, "%", 1);
if (tdi->tokenPos > 0) {
httpdSendStrN(conn, tdi->token, tdi->tokenPos);
httpdSendStrN(conn, tdi->token, (size_t) tdi->tokenPos);
}
// the bad char
httpdSendStrN(conn, &c, 1);
@ -406,7 +405,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
//Send remaining bit.
if (sp != 0) {
httpdSendStrN(conn, e, sp);
httpdSendStrN(conn, e, (size_t) sp);
}
if (len != FILE_CHUNK_LEN) {

@ -96,10 +96,10 @@ struct WebsockPriv {
static Websock *llStart = NULL;
static int sendFrameHead(Websock *ws, int opcode, size_t len)
static int sendFrameHead(Websock *ws, uint8_t opcode, size_t len)
{
uint8_t buf[14];
int i = 0;
size_t i = 0;
buf[i++] = opcode;
if (len > 65535) {
buf[i++] = 127;
@ -107,16 +107,16 @@ static int sendFrameHead(Websock *ws, int opcode, size_t len)
buf[i++] = 0;
buf[i++] = 0;
buf[i++] = 0;
buf[i++] = len >> 24;
buf[i++] = len >> 16;
buf[i++] = len >> 8;
buf[i++] = len;
buf[i++] = (uint8_t) (len >> 24);
buf[i++] = (uint8_t) (len >> 16);
buf[i++] = (uint8_t) (len >> 8);
buf[i++] = (uint8_t) (len);
} else if (len > 125) {
buf[i++] = 126;
buf[i++] = len >> 8;
buf[i++] = len;
buf[i++] = (uint8_t) (len >> 8);
buf[i++] = (uint8_t) (len & 0xFF);
} else {
buf[i++] = len;
buf[i++] = (uint8_t) len;
}
// ws_dbg("WS: Sent frame head for payload of %d bytes.", len);
return httpdSend(ws->conn, buf, i);
@ -125,7 +125,7 @@ static int sendFrameHead(Websock *ws, int opcode, size_t len)
int cgiWebsocketSend(Websock *ws, const uint8_t *data, size_t len, int flags)
{
int r = 0;
int fl = 0;
uint8_t fl = 0;
// Continuation frame has opcode 0
if (!(flags & WEBSOCK_FLAG_CONT)) {
if (flags & WEBSOCK_FLAG_BIN) {
@ -197,7 +197,7 @@ void cgiWebsockMeasureBacklog(const char *resource, size_t *total, size_t *max)
void cgiWebsocketClose(Websock *ws, websock_close_reason reason)
{
uint8_t rs[2] = {reason >> 8, reason & 0xff};
uint8_t rs[2] = {(uint8_t) (reason >> 8), reason & 0xff};
sendFrameHead(ws, FLAG_FIN | OPCODE_CLOSE, 2);
httpdSend(ws->conn, rs, 2);
ws->priv->closedHere = 1;
@ -234,7 +234,7 @@ static void websockFree(Websock *ws)
httpd_cgi_state cgiWebSocketRecv(HttpdConnData *connData, uint8_t *data, size_t len)
{
int j, sl;
size_t j, sl;
httpd_cgi_state r = HTTPD_CGI_MORE;
int wasHeaderByte;
Websock *ws = (Websock *) connData->cgiData;
@ -286,7 +286,7 @@ httpd_cgi_state cgiWebSocketRecv(HttpdConnData *connData, uint8_t *data, size_t
// ws_dbg("Ws: Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags);
if ((uint64_t) sl > ws->priv->fr.len) {
sl = (int) ws->priv->fr.len;
sl = ws->priv->fr.len;
}
for (j = 0; j < sl; j++) {
@ -348,8 +348,9 @@ httpd_cgi_state cgiWebSocketRecv(HttpdConnData *connData, uint8_t *data, size_t
// ws_dbg("WS: Got close frame");
if (!ws->priv->closedHere) {
// ws_dbg("WS: Sending response close frame, %x %x (i=%d, len=%d)", data[i], data[i+1], i, len);
int cause = WS_CLOSE_OK;
websock_close_reason cause = WS_CLOSE_OK;
if (i <= len - 2) {
// TODO why?
cause = ((data[i] << 8) & 0xff00) + (data[i + 1] & 0xff);
}
cgiWebsocketClose(ws, cause);
@ -362,8 +363,8 @@ httpd_cgi_state cgiWebSocketRecv(HttpdConnData *connData, uint8_t *data, size_t
}
}
i += sl - 1;
ws->priv->fr.len -= sl;
i += (size_t) (sl - 1);
ws->priv->fr.len -= (uint64_t) sl;
if (ws->priv->fr.len == 0) {
ws->priv->wsStatus = ST_FLAGS; //go receive next frame

@ -17,10 +17,10 @@ Thanks to my collague at Espressif for writing the foundations of this code.
struct HttpdConnType {
int fd;
int needWriteDoneNotif;
int needsClose;
int port;
char ip[4];
bool needWriteDoneNotif;
bool needsClose;
uint16_t port;
uint8_t ip[4];
};
static HttpdConnType s_rconn[HTTPD_MAX_CONNECTIONS];
@ -56,7 +56,7 @@ void httpdServerTask(void *pvParameters)
fd_set readset, writeset;
struct sockaddr_in server_addr;
struct sockaddr_in remote_addr;
int httpPort;
uint16_t httpPort;
s_shutdown_requested = false;
@ -226,7 +226,7 @@ void httpdServerTask(void *pvParameters)
ret = (int) recv(s_rconn[i].fd, s_recv_buf, HTTPD_RECV_BUF_LEN, 0);
if (ret > 0) {
//Data received. Pass to httpd.
httpdRecvCb(&s_rconn[i], s_rconn[i].ip, s_rconn[i].port, s_recv_buf, ret);
httpdRecvCb(&s_rconn[i], s_rconn[i].ip, s_rconn[i].port, s_recv_buf, (size_t) ret);
} else {
//recv error,connection close
httpdDisconCb(&s_rconn[i], s_rconn[i].ip, s_rconn[i].port);

@ -11,25 +11,25 @@ char httpdHexNibble(uint8_t val)
uint8_t httpdHexVal(char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
if (c >= '0' && c <= '9') { return (uint8_t) (c - '0'); }
if (c >= 'A' && c <= 'F') { return (uint8_t) (c - 'A' + 10); }
if (c >= 'a' && c <= 'f') { return (uint8_t) (c - 'a' + 10); }
return 0;
}
int httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen)
size_t httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen)
{
size_t s = 0, d = 0;
int esced = 0;
char escVal = 0;
uint8_t escVal = 0;
while (s < valLen && d < buffLen) {
if (esced == 1) {
escVal = httpdHexVal(val[s]) << 4;
esced = 2;
} else if (esced == 2) {
escVal |= httpdHexVal(val[s]);
buff[d++] = escVal;
buff[d++] = (char) escVal;
esced = 0;
} else if (val[s] == '%') {
esced = 1;
@ -58,7 +58,7 @@ int httpdFindArg(const char *line, const char *arg, char *buff, size_t buffLen)
e = strstr(p, "&");
if (e == NULL) { e = p + strlen(p); }
router_dbg("findArg: val %s len %d", p, (int) (e - p));
return httpdUrlDecode(p, (int)(e - p), buff, buffLen);
return (int) httpdUrlDecode(p, (size_t)(e - p), buff, buffLen);
}
p = strstr(p, "&");
if (p != NULL) { p += 1; }

@ -21,6 +21,8 @@ Esp8266 http server - core routines
static void cleanupCgiAndUserData(HttpdConnData *hconn);
static void httpdRetireConn(HttpdConnData *hconn);
_Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at most 255");
//This gets set at init time.
static const HttpdBuiltInUrl *s_builtInUrls;
static const char *s_serverName = HTTPD_SERVERNAME;
@ -28,12 +30,12 @@ static const char *s_serverName = HTTPD_SERVERNAME;
typedef struct HttpSendBacklogItem HttpSendBacklogItem;
struct HttpSendBacklogItem {
int len;
size_t len;
HttpSendBacklogItem *next;
char data[];
uint8_t data[];
};
//Flags
//Flags (1 byte)
#define HFL_HTTP11 (1<<0)
#define HFL_CHUNKED (1<<1)
#define HFL_SENDINGBODY (1<<2)
@ -45,13 +47,13 @@ struct HttpSendBacklogItem {
struct HttpdPriv {
char head[HTTPD_MAX_HEAD_LEN];
char corsToken[HTTPD_MAX_CORS_TOKEN_LEN];
int headPos;
size_t headPos;
uint8_t *sendBuff;
int sendBuffLen;
size_t sendBuffLen;
char *chunkHdr;
HttpSendBacklogItem *sendBacklog;
int sendBacklogSize;
int flags;
size_t sendBacklogSize;
uint8_t flags;
};
@ -104,7 +106,7 @@ size_t httpGetBacklogSize(const HttpdConnData *conn)
{
HttpSendBacklogItem *bl = conn->priv->sendBacklog;
if (!bl) { return 0; }
int bytes = 0;
size_t bytes = 0;
while (bl != NULL) {
bytes += bl->len;
bl = bl->next;
@ -113,7 +115,7 @@ size_t httpGetBacklogSize(const HttpdConnData *conn)
}
//Looks up the connData info for a specific connection
static HttpdConnData *httpdFindConnData(ConnTypePtr conn, const char *remIp, int remPort)
static HttpdConnData *httpdFindConnData(ConnTypePtr conn, const uint8_t *remIp, int remPort)
{
for (int i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
if (s_connData[i] && s_connData[i]->remote_port == remPort &&
@ -192,13 +194,13 @@ int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t b
void httdSetTransferMode(HttpdConnData *conn, httpd_transfer_opt mode)
{
if (mode == HTTPD_TRANSFER_CLOSE) {
conn->priv->flags &= ~HFL_CHUNKED;
conn->priv->flags &= ~HFL_NOCONNECTIONSTR;
conn->priv->flags &= (uint8_t) ~HFL_CHUNKED;
conn->priv->flags &= (uint8_t) ~HFL_NOCONNECTIONSTR;
} else if (mode == HTTPD_TRANSFER_CHUNKED) {
conn->priv->flags |= HFL_CHUNKED;
conn->priv->flags &= ~HFL_NOCONNECTIONSTR;
conn->priv->flags &= (uint8_t) ~HFL_NOCONNECTIONSTR;
} else if (mode == HTTPD_TRANSFER_NONE) {
conn->priv->flags &= ~HFL_CHUNKED;
conn->priv->flags &= (uint8_t) ~HFL_CHUNKED;
conn->priv->flags |= HFL_NOCONNECTIONSTR;
}
}
@ -212,7 +214,6 @@ void httdResponseOptions(HttpdConnData *conn, int cors)
void httpdStartResponse(HttpdConnData *conn, int code)
{
char buff[256];
size_t l;
const char *connStr = "";
if (!(conn->priv->flags & HFL_NOCONNECTIONSTR)) {
@ -223,8 +224,8 @@ void httpdStartResponse(HttpdConnData *conn, int code)
}
}
l = sprintf(buff, "HTTP/1.%d %d %s\r\nServer: %s\r\n%s",
(conn->priv->flags & HFL_HTTP11) ? 1 : 0,
size_t l = (size_t)sprintf(buff, "HTTP/1.%d %d %s\r\nServer: %s\r\n%s",
((conn->priv->flags & HFL_HTTP11) ? 1 : 0),
code,
httpdStatusName(code),
s_serverName,
@ -287,7 +288,7 @@ int httpdSend(HttpdConnData *conn, const uint8_t *data, size_t len)
return 1;
}
#define httpdSend_orDie(conn, data, len) do { if (!httpdSend((conn), (const uint8_t *)(data), (len))) return false; } while (0)
#define httpdSend_orDie(conn, data, len) do { if (!httpdSend((conn), (const uint8_t *)(data), (size_t)(len))) return false; } while (0)
#define httpdSendStr_orDie(conn, data) do { if (!httpdSendStr((conn), (data))) return false; } while (0)
@ -295,7 +296,7 @@ int httpdSend(HttpdConnData *conn, const uint8_t *data, size_t len)
int httpdSend_html(HttpdConnData *conn, const char *data, ssize_t len)
{
int start = 0, end = 0;
uint8_t c;
char c;
if (conn->conn == NULL) { return 0; }
if (len < 0) { len = (int) strlen((const char *) data); }
if (len == 0) { return 0; }
@ -326,7 +327,7 @@ int httpdSend_html(HttpdConnData *conn, const char *data, ssize_t len)
int httpdSend_js(HttpdConnData *conn, const char *data, ssize_t len)
{
int start = 0, end = 0;
uint8_t c;
char c;
if (conn->conn == NULL) { return 0; }
if (len < 0) { len = (int) strlen((const char *) data); }
if (len == 0) { return 0; }
@ -362,19 +363,20 @@ int httpdSend_js(HttpdConnData *conn, const char *data, ssize_t len)
//Returns false if data could not be sent nor put in backlog.
bool httpdFlushSendBuffer(HttpdConnData *conn)
{
int r, len;
int r;
size_t len;
if (conn->conn == NULL) { return false; }
if (conn->priv->chunkHdr != NULL) {
//We're sending chunked data, and the chunk needs fixing up.
//Finish chunk with cr/lf
httpdSendStr(conn, "\r\n");
//Calculate length of chunk
len = ((char *)(&conn->priv->sendBuff[conn->priv->sendBuffLen]) - conn->priv->chunkHdr) - 8;
len = (size_t) ((char *)(&conn->priv->sendBuff[conn->priv->sendBuffLen]) - conn->priv->chunkHdr) - 8;
//Fix up chunk header to correct value
conn->priv->chunkHdr[0] = httpdHexNibble(len >> 12);
conn->priv->chunkHdr[1] = httpdHexNibble(len >> 8);
conn->priv->chunkHdr[2] = httpdHexNibble(len >> 4);
conn->priv->chunkHdr[3] = httpdHexNibble(len >> 0);
conn->priv->chunkHdr[0] = httpdHexNibble((uint8_t) (len >> 12));
conn->priv->chunkHdr[1] = httpdHexNibble((uint8_t) (len >> 8));
conn->priv->chunkHdr[2] = httpdHexNibble((uint8_t) (len >> 4));
conn->priv->chunkHdr[3] = httpdHexNibble((uint8_t) (len >> 0));
//Reset chunk hdr for next call
conn->priv->chunkHdr = NULL;
}
@ -388,7 +390,7 @@ bool httpdFlushSendBuffer(HttpdConnData *conn)
if (!r) {
//Can't send this for some reason. Dump packet in backlog, we can send it later.
if (conn->priv->sendBacklogSize + conn->priv->sendBuffLen > HTTPD_MAX_BACKLOG_SIZE) {
http_error("Httpd: Backlog overrun, dropped %dB", conn->priv->sendBuffLen);
http_error("Httpd: Backlog overrun, dropped %dB", (int) conn->priv->sendBuffLen);
conn->priv->sendBuffLen = 0;
return false;
}
@ -437,7 +439,7 @@ void httpdCgiIsDone(HttpdConnData *conn)
//Callback called when the data on a socket has been successfully
//sent.
void httpdSentCb(ConnTypePtr rconn, const char *remIp, int remPort)
void httpdSentCb(ConnTypePtr rconn, const uint8_t *remIp, uint16_t remPort)
{
HttpdConnData *conn = httpdFindConnData(rconn, remIp, remPort);
httpdContinue(conn);
@ -647,7 +649,7 @@ static void httpdParseHeader(char *h, HttpdConnData *conn)
i = 11;
//Skip trailing spaces
while (h[i] == ' ') { i++; }
if (strstarts(&h[i], "close")) { conn->priv->flags &= ~HFL_CHUNKED; } //Don't use chunked conn
if (strstarts(&h[i], "close")) { conn->priv->flags &= (uint8_t) ~HFL_CHUNKED; } //Don't use chunked conn
} else if (strstarts(h, "Content-Length:")) {
i = 15;
//Skip trailing spaces
@ -660,7 +662,7 @@ static void httpdParseHeader(char *h, HttpdConnData *conn)
// we'll stream this in in chunks
conn->post->buffSize = HTTPD_MAX_POST_LEN;
} else {
conn->post->buffSize = conn->post->len;
conn->post->buffSize = (size_t) conn->post->len;
}
http_dbg("Mallocced buffer for %d + 1 bytes of post data.", (int) conn->post->buffSize);
conn->post->buff = (char *) httpdPlatMalloc(conn->post->buffSize + 1);
@ -713,9 +715,10 @@ void httpdConnSendFinish(HttpdConnData *conn)
}
//Callback called when there's data available on a socket.
void httpdRecvCb(ConnTypePtr rconn, const char *remIp, int remPort, uint8_t *data, unsigned short len)
void httpdRecvCb(ConnTypePtr rconn, const uint8_t *remIp, uint16_t remPort, uint8_t *data, size_t len)
{
int x, r;
httpd_cgi_state r;
size_t x;
char *p, *e;
httpdPlatLock();
@ -752,7 +755,7 @@ void httpdRecvCb(ConnTypePtr rconn, const char *remIp, int remPort, uint8_t *dat
}
}
//ToDo: return http error code 431 (request header too long) if this happens
if (conn->priv->headPos != HTTPD_MAX_HEAD_LEN) { conn->priv->head[conn->priv->headPos++] = data[x]; }
if (conn->priv->headPos != HTTPD_MAX_HEAD_LEN) { conn->priv->head[conn->priv->headPos++] = (char) data[x]; }
conn->priv->head[conn->priv->headPos] = 0;
//Scan for /r/n/r/n. Receiving this indicates the headers end.
if (data[x] == '\n' && strstr(conn->priv->head, "\r\n\r\n") != NULL) {
@ -776,7 +779,7 @@ void httpdRecvCb(ConnTypePtr rconn, const char *remIp, int remPort, uint8_t *dat
}
} else if (conn->post->len != 0) {
//This byte is a POST byte.
conn->post->buff[conn->post->buffLen++] = data[x];
conn->post->buff[conn->post->buffLen++] = (char) data[x];
conn->post->received++;
conn->hostName = NULL;
if (conn->post->buffLen >= conn->post->buffSize || (int) conn->post->received == conn->post->len) {
@ -820,7 +823,7 @@ void httpdRecvCb(ConnTypePtr rconn, const char *remIp, int remPort, uint8_t *dat
//The platform layer should ALWAYS call this function, regardless if the connection is closed by the server
//or by the client.
void httpdDisconCb(ConnTypePtr rconn, const char *remIp, int remPort)
void httpdDisconCb(ConnTypePtr rconn, const uint8_t *remIp, uint16_t remPort)
{
httpdPlatLock();
HttpdConnData *hconn = httpdFindConnData(rconn, remIp, remPort);
@ -853,9 +856,9 @@ static void cleanupCgiAndUserData(HttpdConnData *hconn)
}
int httpdConnectCb(ConnTypePtr conn, const char *remIp, int remPort)
int httpdConnectCb(ConnTypePtr conn, const uint8_t *remIp, uint16_t remPort)
{
int i;
uint8_t i;
httpdPlatLock();
//Find empty conndata in pool
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {

@ -4,7 +4,7 @@
#include <stdint.h>
#include <ctype.h>
static const int base64dec_tab[256] = {
static const uint8_t base64dec_tab[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,

@ -113,11 +113,11 @@ static void sha1_pad(httpd_sha1nfo *s)
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
sha1_addUncounted(s, 0); // So zero pad the top bits
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, s->byteCount >> 13); // byte.
sha1_addUncounted(s, s->byteCount >> 5);
sha1_addUncounted(s, s->byteCount << 3);
sha1_addUncounted(s, (uint8_t)(s->byteCount >> 29)); // Shifting to multiply by 8
sha1_addUncounted(s, (uint8_t)(s->byteCount >> 21)); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, (uint8_t)(s->byteCount >> 13)); // byte.
sha1_addUncounted(s, (uint8_t)(s->byteCount >> 5));
sha1_addUncounted(s, (uint8_t)(s->byteCount << 3));
}
uint8_t *httpd_sha1_result(httpd_sha1nfo *s)

Loading…
Cancel
Save