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. 84
      spritehttpd/lib/heatshrink/heatshrink_decoder.c
  26. 153
      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 *.map
*.d *.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: DEBUG = 1
make -C ./spritehttpd clean PLATFORM ?= POSIX # POSIX or ARM
make -C ./demo clean
make -C ./espfsbuilder clean
# -*- 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: LIB_SOURCES := $(addprefix $(LIB_DIR)/, $(LIB_SOURCES))
make -C ./espfsbuilder LIB_OBJS = $(LIB_SOURCES:.c=.o)
LIB_CFLAGS += $(addprefix -I$(LIB_DIR)/, $(LIB_INCLUDE_DIRS))
demo: # This is only used for the library files. TODO restrict it somehow
make -C ./demo %.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; 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[] = { const HttpdBuiltInUrl routes[] = {
// TODO password lock ... // TODO password lock ...
// ROUTE_CGI("*", cgiStartSession),
// --- Web pages --- // --- Web pages ---
// ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"), // ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"),
@ -91,17 +107,20 @@ const HttpdBuiltInUrl routes[] = {
ROUTE_END(), ROUTE_END(),
}; };
void sigpipe_handler(int unused) void sigpipe_handler(int signum)
{ {
(void) signum;
} }
void handle_sigint(int signum) void handle_sigint(int signum)
{ {
(void) signum;
fprintf(stderr, " SIGINT detected, shutting down HTTPD\n"); fprintf(stderr, " SIGINT detected, shutting down HTTPD\n");
httpdShutdown(s_serverHandle); httpdShutdown(s_serverHandle);
} }
int main() int main(void)
{ {
struct sigaction action; struct sigaction action;
memset(&action, 0, sizeof(action)); memset(&action, 0, sizeof(action));
@ -109,7 +128,7 @@ int main()
sigaction(SIGINT, &action, NULL); sigaction(SIGINT, &action, NULL);
// prevent abort on sigpipe // prevent abort on sigpipe
sigaction(SIGPIPE, &(struct sigaction) {{sigpipe_handler}}, NULL); sigaction(SIGPIPE, &(struct sigaction) {{sigpipe_handler},.sa_mask={}}, NULL);
struct httpd_options opts = { struct httpd_options opts = {
.port = 8080, .port = 8080,
@ -122,7 +141,7 @@ int main()
return 0; 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) { if (offset + len > espfs_image_len) {
return -1; 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; const uint8_t *inp = in;
uint8_t *outp = out; uint8_t *outp = out;
size_t len; size_t len;
int ws[] = {5, 6, 8, 11, 13}; uint8_t ws[] = {5, 6, 8, 11, 13};
int ls[] = {3, 3, 4, 4, 4}; uint8_t ls[] = {3, 3, 4, 4, 4};
HSE_poll_res pres = 0; HSE_poll_res pres = 0;
HSE_sink_res sres = 0; HSE_sink_res sres = 0;
size_t r; size_t r;
@ -73,7 +73,7 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t
exit(1); exit(1);
} }
//Save encoder parms as first byte //Save encoder parms as first byte
*outp = (ws[level] << 4) | ls[level]; *outp = (uint8_t) ((ws[level] << 4) | ls[level]);
outp++; outp++;
outcap--; 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.zfree = Z_NULL;
stream.opaque = Z_NULL; stream.opaque = Z_NULL;
stream.next_in = in; stream.next_in = in;
stream.avail_in = insize; stream.avail_in = (uInt) insize;
stream.next_out = out; stream.next_out = out;
stream.avail_out = outcap; stream.avail_out = (uInt) outcap;
// 31 -> 15 window bits + 16 for gzip // 31 -> 15 window bits + 16 for gzip
zresult = deflateInit2(&stream, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); zresult = deflateInit2(&stream, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
if (zresult != Z_OK) { if (zresult != Z_OK) {
@ -190,7 +190,7 @@ void parseGzipExtensions(char *input)
{ {
char *token; char *token;
char *extList = input; 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 // count elements
while (*extList != 0) { 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) int handleFile(int fd, const char *name, int compression_mode, int level, const char **compName)
{ {
uint8_t *fdat = NULL, *cdat = NULL, *cdatbuf = NULL; uint8_t *fdat = NULL, *cdat = NULL, *cdatbuf = NULL;
uint32_t size, csize; size_t size, csize;
EspFsHeader h; EspFsHeader h;
uint16_t realNameLen; uint16_t realNameLen;
uint8_t flags = 0; uint8_t flags = 0;
size = lseek(fd, 0, SEEK_END); size = (size_t) lseek(fd, 0, SEEK_END);
fdat = malloc(size); fdat = malloc(size);
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
read(fd, fdat, size); read(fd, fdat, size);
@ -265,17 +265,17 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const
//Fill header data //Fill header data
h.magic = htole32(ESPFS_MAGIC); // ('E' << 0) + ('S' << 8) + ('f' << 16) + ('s' << 24); h.magic = htole32(ESPFS_MAGIC); // ('E' << 0) + ('S' << 8) + ('f' << 16) + ('s' << 24);
h.flags = flags; h.flags = flags;
h.compression = (int8_t) compression_mode; h.compression = (uint8_t) compression_mode;
h.nameLen = realNameLen = strlen(name) + 1; // zero terminator h.nameLen = realNameLen = (uint16_t) strlen(name) + 1; // zero terminator
uint32_t padbytes = 0; uint16_t padbytes = 0;
if (h.nameLen & 3) { if (h.nameLen & 3) {
//Round to next 32bit boundary //Round to next 32bit boundary
padbytes = 4 - (h.nameLen & 3); 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 += 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.nameLen = htole16(h.nameLen);
h.fileLenComp = htole32(csize); h.fileLenComp = htole32((uint32_t) csize);
h.fileLenDecomp = htole32(size); h.fileLenDecomp = htole32((uint32_t) size);
write(s_outFd, &h, sizeof(EspFsHeader)); write(s_outFd, &h, sizeof(EspFsHeader));
write(s_outFd, name, realNameLen); 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. * Write final dummy header with FLAG_LASTFILE set.
*/ */
void finishArchive() void finishArchive(void)
{ {
EspFsHeader h; EspFsHeader h;
h.magic = htole32(ESPFS_MAGIC); h.magic = htole32(ESPFS_MAGIC);

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

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

@ -11,7 +11,7 @@
// Custom helpers // Custom helpers
#define streq(a, b) (strcmp((const char*)(a), (const char*)(b)) == 0) #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 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_n(str, n) ((str))[strlen((str)) - (n)]
#define last_char(str) last_char_n((str), 1) #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 valLen - length of the encoded value field
* @param buff - output buffer, the string will be zero-terminated * @param buff - output buffer, the string will be zero-terminated
* @param buffLen - output buffer size * @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. * 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 arg - name of the argument to retrieve
* @param[out] buff - output buffer, the string will be zero-terminated * @param[out] buff - output buffer, the string will be zero-terminated
* @param buffLen - output buffer size * @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); 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 remIp - remote IP (4 bytes)
* @param remPort - remote port * @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. * 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 data - data received. This is a mutable buffer
* @param len - data len * @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 * 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 remIp - remote IP (4 bytes)
* @param remPort - remote port * @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 * Connect callback - a client connected
@ -303,7 +303,7 @@ void httpdDisconCb(ConnTypePtr conn, const char *remIp, int remPort);
* @param remPort - remote port * @param remPort - remote port
* @return 1 = OK, 0 = client couldn't be served * @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 * Low level function to close & release a connection
@ -318,4 +318,4 @@ void httpdConnRelease(ConnTypePtr conn);
* *
* @internal * @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 // internal fields
struct EspFsFile { struct EspFsFile {
/// Header pointer /// Header pointer
uint32_t headerPos; size_t headerPos;
/// Decompressor type /// Decompressor type
uint8_t decompressor; uint8_t decompressor;
uint32_t posDecomp; size_t posDecomp;
uint32_t posStart; size_t posStart;
uint32_t posComp; size_t posComp;
heatshrink_decoder *decompData; heatshrink_decoder *decompData;
}; };
// forward declaration for use in the stand-alone espfs tool // 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() EspFsInitResult espFsInit()
@ -113,7 +113,7 @@ bool espFsWalkNext(EspFsWalk *walk, EspFsHeader *header, char *namebuf, size_t n
*filepos = walk->hpos; *filepos = walk->hpos;
} }
walk->hpos += sizeof(EspFsHeader) + header->nameLen + header->fileLenComp; walk->hpos += (uint32_t) (sizeof(EspFsHeader) + header->nameLen + header->fileLenComp);
// Align // Align
while(walk->hpos & 3) { while(walk->hpos & 3) {
walk->hpos++; walk->hpos++;
@ -267,7 +267,7 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
if (fh->decompressor == COMPRESS_NONE) { if (fh->decompressor == COMPRESS_NONE) {
int toRead = (int) binary_len - (int) (fh->posComp - fh->posStart); int toRead = (int) binary_len - (int) (fh->posComp - fh->posStart);
if (toRead < 0) { toRead = 0; } 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); espfs_dbg("[EspFS] Plain data, read chunk @%d: %d", (int)fh->posComp, (int) buf_cap);
rv = httpdPlatEspfsRead(buff, fh->posComp, buf_cap); rv = httpdPlatEspfsRead(buff, fh->posComp, buf_cap);
if (rv != 0) { if (rv != 0) {
@ -276,7 +276,7 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
fh->posDecomp += buf_cap; fh->posDecomp += buf_cap;
fh->posComp += buf_cap; fh->posComp += buf_cap;
return (int) buf_cap; return buf_cap;
} else if (fh->decompressor == COMPRESS_HEATSHRINK) { } else if (fh->decompressor == COMPRESS_HEATSHRINK) {
rv = httpdPlatEspfsRead(&decompressed_len, fh->headerPos + offsetof(EspFsHeader, fileLenDecomp), 4); rv = httpdPlatEspfsRead(&decompressed_len, fh->headerPos + offsetof(EspFsHeader, fileLenDecomp), 4);
if (rv != 0) { if (rv != 0) {
@ -323,10 +323,10 @@ size_t espFsRead(EspFsFile *fh, uint8_t *buff, size_t buf_cap)
if (fh->posDecomp == decompressed_len) { if (fh->posDecomp == decompressed_len) {
heatshrink_decoder_finish(dec); heatshrink_decoder_finish(dec);
} }
return (int) decoded_bytes; return decoded_bytes;
} }
} }
return (int) buf_cap; return buf_cap;
} }
return 0; return 0;
} }

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

@ -44,12 +44,15 @@ typedef struct {
/* Forward references. */ /* Forward references. */
static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count); static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count);
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);
#if HEATSHRINK_DYNAMIC_ALLOC #if HEATSHRINK_DYNAMIC_ALLOC
heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
uint8_t window_sz2, uint8_t window_sz2,
uint8_t lookahead_sz2) { uint8_t lookahead_sz2)
{
if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) || if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
(window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) || (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
(input_buffer_size == 0) || (input_buffer_size == 0) ||
@ -57,7 +60,7 @@ heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
(lookahead_sz2 >= window_sz2)) { (lookahead_sz2 >= window_sz2)) {
return NULL; 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; size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz); heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz);
if (hsd == NULL) { return NULL; } if (hsd == NULL) { return NULL; }
@ -70,15 +73,18 @@ heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size,
return hsd; return hsd;
} }
void heatshrink_decoder_free(heatshrink_decoder *hsd) { void heatshrink_decoder_free(heatshrink_decoder *hsd)
size_t buffers_sz = (1 << hsd->window_sz2) + hsd->input_buffer_size; {
size_t buffers_sz = ((size_t) 1 << hsd->window_sz2) + hsd->input_buffer_size;
size_t sz = sizeof(heatshrink_decoder) + buffers_sz; size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
HEATSHRINK_FREE(hsd, sz); HEATSHRINK_FREE(hsd, sz);
(void)sz; /* may not be used by free */ (void) sz; /* may not be used by free */
} }
#endif #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 buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd);
size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd); size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd);
memset(hsd->buffers, 0, buf_sz + input_sz); 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. */ /* Copy SIZE bytes into the decoder's input buffer, if it will fit. */
HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd, 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)) { if ((hsd == NULL) || (in_buf == NULL) || (input_size == NULL)) {
return HSDR_SINK_ERROR_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); LOG("-- sinking %zd bytes\n", size);
/* copy into input buffer (at head of buffers) */ /* copy into input buffer (at head of buffers) */
memcpy(&hsd->buffers[hsd->input_size], in_buf, size); memcpy(&hsd->buffers[hsd->input_size], in_buf, size);
hsd->input_size += (uint16_t)size; hsd->input_size += (uint16_t) size;
*input_size = size; *input_size = size;
return HSDR_SINK_OK; return HSDR_SINK_OK;
} }
@ -124,17 +131,24 @@ HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd,
// States // States
static HSD_state st_tag_bit(heatshrink_decoder *hsd); static HSD_state st_tag_bit(heatshrink_decoder *hsd);
static HSD_state st_yield_literal(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_msb(heatshrink_decoder *hsd);
static HSD_state st_backref_index_lsb(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_msb(heatshrink_decoder *hsd);
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd); static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd);
static HSD_state st_yield_backref(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, 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)) { if ((hsd == NULL) || (out_buf == NULL) || (output_size == NULL)) {
return HSDR_POLL_ERROR_NULL; return HSDR_POLL_ERROR_NULL;
} }
@ -175,7 +189,7 @@ HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd,
default: default:
return HSDR_POLL_ERROR_UNKNOWN; 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 /* If the current state cannot advance, check if input or output
* buffer are exhausted. */ * 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 const uint32_t bits = get_bits(hsd, 1); // get tag bit
if (bits == NO_BITS) { if (bits == NO_BITS) {
return HSDS_TAG_BIT; 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, 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) /* Emit a repeated section from the window buffer, and add it (again)
* to the window buffer. (Note that the repetition can include * to the window buffer. (Note that the repetition can include
* itself.)*/ * itself.)*/
@ -213,8 +229,8 @@ static HSD_state st_yield_literal(heatshrink_decoder *hsd,
uint16_t byte = get_bits(hsd, 8); uint16_t byte = get_bits(hsd, 8);
if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */ if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */
uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)]; 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;
uint8_t c = byte & 0xFF; uint8_t c = (uint8_t) (byte & 0xFF);
LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.'); LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.');
buf[hsd->head_index++ & mask] = c; buf[hsd->head_index++ & mask] = c;
push_byte(hsd, oi, 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); uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
ASSERT(bit_ct > 8); ASSERT(bit_ct > 8);
uint16_t bits = get_bits(hsd, bit_ct - 8); uint16_t bits = get_bits(hsd, bit_ct - 8);
LOG("-- backref index (msb), got 0x%04x (+1)\n", bits); LOG("-- backref index (msb), got 0x%04x (+1)\n", bits);
if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_MSB; } 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; 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); uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
uint16_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8); uint16_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8);
LOG("-- backref index (lsb), got 0x%04x (+1)\n", bits); 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; 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); uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
ASSERT(br_bit_ct > 8); ASSERT(br_bit_ct > 8);
uint16_t bits = get_bits(hsd, br_bit_ct - 8); uint16_t bits = get_bits(hsd, br_bit_ct - 8);
LOG("-- backref count (msb), got 0x%04x (+1)\n", bits); LOG("-- backref count (msb), got 0x%04x (+1)\n", bits);
if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_MSB; } 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; 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); uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
uint16_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8); uint16_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8);
LOG("-- backref count (lsb), got 0x%04x (+1)\n", bits); 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, static HSD_state st_yield_backref(heatshrink_decoder *hsd,
output_info *oi) { output_info *oi)
{
size_t count = oi->buf_size - *oi->output_size; size_t count = oi->buf_size - *oi->output_size;
if (count > 0) { if (count > 0) {
size_t i = 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)]; 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; uint16_t neg_offset = hsd->output_index;
LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset); LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset);
ASSERT(neg_offset <= mask + 1); 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]; uint8_t c = buf[(hsd->head_index - neg_offset) & mask];
push_byte(hsd, oi, c); push_byte(hsd, oi, c);
buf[hsd->head_index & mask] = c; buf[hsd->head_index & mask] = c;
hsd->head_index++; hsd->head_index++;
LOG(" -- ++ 0x%02x\n", c); 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; } if (hsd->output_count == 0) { return HSDS_TAG_BIT; }
} }
return HSDS_YIELD_BACKREF; 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. /* 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. */ * 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; uint16_t accumulator = 0;
int i = 0; int i = 0;
if (count > 15) { return NO_BITS; } if (count > 15) { return NO_BITS; }
@ -341,7 +363,8 @@ static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count) {
return accumulator; 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; } if (hsd == NULL) { return HSDR_FINISH_ERROR_NULL; }
switch (hsd->state) { switch (hsd->state) {
case HSDS_TAG_BIT: case HSDS_TAG_BIT:
@ -367,8 +390,9 @@ HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd) {
} }
} }
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 : '.'); LOG(" -- pushing byte: 0x%02x ('%c')\n", byte, isprint(byte) ? byte : '.');
oi->buf[(*oi->output_size)++] = byte; oi->buf[(*oi->output_size)++] = byte;
(void)hsd; (void) hsd;
} }

@ -53,22 +53,32 @@ typedef struct {
#define MATCH_NOT_FOUND ((uint16_t)-1) #define MATCH_NOT_FOUND ((uint16_t)-1)
static uint16_t get_input_offset(heatshrink_encoder *hse); static uint16_t get_input_offset(heatshrink_encoder *hse);
static uint16_t get_input_buffer_size(heatshrink_encoder *hse); static uint16_t get_input_buffer_size(heatshrink_encoder *hse);
static uint16_t get_lookahead_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 void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag);
static int can_take_byte(output_info *oi); static int can_take_byte(output_info *oi);
static int is_finishing(heatshrink_encoder *hse); static int is_finishing(heatshrink_encoder *hse);
static void save_backlog(heatshrink_encoder *hse); static void save_backlog(heatshrink_encoder *hse);
/* Push COUNT (max 8) bits to the output buffer, which has room. */ /* 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, 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 uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi);
static void push_literal_byte(heatshrink_encoder *hse, output_info *oi); static void push_literal_byte(heatshrink_encoder *hse, output_info *oi);
#if HEATSHRINK_DYNAMIC_ALLOC #if HEATSHRINK_DYNAMIC_ALLOC
heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2, heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
uint8_t lookahead_sz2) { uint8_t lookahead_sz2)
{
if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) || if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
(window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) || (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
(lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) || (lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) ||
@ -89,13 +99,13 @@ heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
heatshrink_encoder_reset(hse); heatshrink_encoder_reset(hse);
#if HEATSHRINK_USE_INDEX #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)); hse->search_index = HEATSHRINK_MALLOC(index_sz + sizeof(struct hs_index));
if (hse->search_index == NULL) { if (hse->search_index == NULL) {
HEATSHRINK_FREE(hse, sizeof(*hse) + buf_sz); HEATSHRINK_FREE(hse, sizeof(*hse) + buf_sz);
return NULL; return NULL;
} }
hse->search_index->size = (uint16_t)index_sz; hse->search_index->size = (uint16_t) index_sz;
#endif #endif
LOG("-- allocated encoder with buffer size of %zu (%u byte input size)\n", 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; 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)); size_t buf_sz = (2U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
#if HEATSHRINK_USE_INDEX #if HEATSHRINK_USE_INDEX
size_t index_sz = sizeof(struct hs_index) + hse->search_index->size; size_t index_sz = sizeof(struct hs_index) + hse->search_index->size;
HEATSHRINK_FREE(hse->search_index, index_sz); HEATSHRINK_FREE(hse->search_index, index_sz);
(void)index_sz; (void) index_sz;
#endif #endif
HEATSHRINK_FREE(hse, sizeof(heatshrink_encoder) + buf_sz); HEATSHRINK_FREE(hse, sizeof(heatshrink_encoder) + buf_sz);
(void)buf_sz; (void) buf_sz;
} }
#endif #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)); size_t buf_sz = (2U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
memset(hse->buffer, 0, buf_sz); memset(hse->buffer, 0, buf_sz);
hse->input_size = 0; hse->input_size = 0;
@ -129,13 +142,14 @@ void heatshrink_encoder_reset(heatshrink_encoder *hse) {
hse->outgoing_bits = 0x0000; hse->outgoing_bits = 0x0000;
hse->outgoing_bits_count = 0; hse->outgoing_bits_count = 0;
#ifdef LOOP_DETECT #ifdef LOOP_DETECT
hse->loop_detect = (uint32_t)-1; hse->loop_detect = (uint32_t)-1;
#endif #endif
} }
HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse, 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)) { if ((hse == NULL) || (in_buf == NULL) || (input_size == NULL)) {
return HSER_SINK_ERROR_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 write_offset = get_input_offset(hse) + hse->input_size;
uint16_t ibs = get_input_buffer_size(hse); uint16_t ibs = get_input_buffer_size(hse);
uint16_t rem = ibs - hse->input_size; 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); memcpy(&hse->buffer[write_offset], in_buf, cp_sz);
*input_size = cp_sz; *input_size = cp_sz;
@ -172,23 +186,31 @@ HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse,
static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start, 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 void do_indexing(heatshrink_encoder *hse);
static HSE_state st_step_search(heatshrink_encoder *hse); static HSE_state st_step_search(heatshrink_encoder *hse);
static HSE_state st_yield_tag_bit(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, 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, 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, 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_save_backlog(heatshrink_encoder *hse);
static HSE_state st_flush_bit_buffer(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, 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)) { if ((hse == NULL) || (out_buf == NULL) || (output_size == NULL)) {
return HSER_POLL_ERROR_NULL; return HSER_POLL_ERROR_NULL;
} }
@ -236,7 +258,7 @@ HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse,
next_state = st_save_backlog(hse); next_state = st_save_backlog(hse);
break; break;
case HSES_FLUSH_BITS: case HSES_FLUSH_BITS:
hse->state = (uint8_t)st_flush_bit_buffer(hse, &oi); hse->state = (uint8_t) st_flush_bit_buffer(hse, &oi);
return HSER_POLL_EMPTY; return HSER_POLL_EMPTY;
case HSES_DONE: case HSES_DONE:
return HSER_POLL_EMPTY; return HSER_POLL_EMPTY;
@ -244,16 +266,17 @@ HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse,
LOG("-- bad state %s\n", state_names[hse->state]); LOG("-- bad state %s\n", state_names[hse->state]);
return HSER_POLL_ERROR_MISUSE; return HSER_POLL_ERROR_MISUSE;
} }
hse->state = (uint8_t)next_state; hse->state = (uint8_t) next_state;
if (hse->state == in_state) { if (hse->state == in_state) {
/* Check if output buffer is exhausted. */ /* 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; } if (hse == NULL) { return HSER_FINISH_ERROR_NULL; }
LOG("-- setting is_finishing flag\n"); LOG("-- setting is_finishing flag\n");
hse->flags |= FLAG_IS_FINISHING; 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; 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 window_length = get_input_buffer_size(hse);
uint16_t lookahead_sz = get_lookahead_size(hse); uint16_t lookahead_sz = get_lookahead_size(hse);
uint16_t msi = hse->match_scan_index; uint16_t msi = hse->match_scan_index;
LOG("## step_search, scan @ +%d (%d/%d), input size %d\n", 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); bool fin = is_finishing(hse);
if (msi > hse->input_size - (fin ? 1 : lookahead_sz)) { if (msi > hse->input_size - (fin ? 1 : lookahead_sz)) {
@ -305,7 +329,8 @@ static HSE_state st_step_search(heatshrink_encoder *hse) {
} }
static HSE_state st_yield_tag_bit(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 (can_take_byte(oi)) {
if (hse->match_length == 0) { if (hse->match_length == 0) {
add_tag_bit(hse, oi, HEATSHRINK_LITERAL_MARKER); 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, static HSE_state st_yield_literal(heatshrink_encoder *hse,
output_info *oi) { output_info *oi)
{
if (can_take_byte(oi)) { if (can_take_byte(oi)) {
push_literal_byte(hse, oi); push_literal_byte(hse, oi);
return HSES_SEARCH; 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, static HSE_state st_yield_br_index(heatshrink_encoder *hse,
output_info *oi) { output_info *oi)
{
if (can_take_byte(oi)) { if (can_take_byte(oi)) {
LOG("-- yielding backref index %u\n", hse->match_pos); LOG("-- yielding backref index %u\n", hse->match_pos);
if (push_outgoing_bits(hse, oi) > 0) { 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, static HSE_state st_yield_br_length(heatshrink_encoder *hse,
output_info *oi) { output_info *oi)
{
if (can_take_byte(oi)) { if (can_take_byte(oi)) {
LOG("-- yielding backref length %u\n", hse->match_length); LOG("-- yielding backref length %u\n", hse->match_length);
if (push_outgoing_bits(hse, oi) > 0) { 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"); LOG("-- saving backlog\n");
save_backlog(hse); save_backlog(hse);
return HSES_NOT_FULL; return HSES_NOT_FULL;
} }
static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse, static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse,
output_info *oi) { output_info *oi)
{
if (hse->bit_index == 0x80) { if (hse->bit_index == 0x80) {
LOG("-- done!\n"); LOG("-- done!\n");
return HSES_DONE; 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); LOG("-- adding tag bit: %d\n", tag);
push_bits(hse, 1, tag, oi); 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); return get_input_buffer_size(hse);
} }
static uint16_t get_input_buffer_size(heatshrink_encoder *hse) { static uint16_t get_input_buffer_size(heatshrink_encoder *hse)
(void)hse; {
return (uint16_t)(1U << HEATSHRINK_ENCODER_WINDOW_BITS(hse)); (void) hse;
return (uint16_t) (1U << HEATSHRINK_ENCODER_WINDOW_BITS(hse));
} }
static uint16_t get_lookahead_size(heatshrink_encoder *hse) { static uint16_t get_lookahead_size(heatshrink_encoder *hse)
(void)hse; {
return (uint16_t)(1U << HEATSHRINK_ENCODER_LOOKAHEAD_BITS(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 #if HEATSHRINK_USE_INDEX
/* Build an index array I that contains flattened linked lists /* Build an index array I that contains flattened linked lists
* for the previous instances of every byte in the buffer. * 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]; int16_t last[256];
memset(last, 0xFF, sizeof(last)); memset(last, 0xFF, sizeof(last));
uint8_t * const data = hse->buffer; uint8_t *const data = hse->buffer;
int16_t * const index = hsi->index; int16_t *const index = hsi->index;
const uint16_t input_offset = get_input_offset(hse); const uint16_t input_offset = get_input_offset(hse);
const uint16_t end = input_offset + hse->input_size; const uint16_t end = input_offset + hse->input_size;
@ -442,18 +477,21 @@ static void do_indexing(heatshrink_encoder *hse) {
#endif #endif
} }
static int is_finishing(heatshrink_encoder *hse) { static int is_finishing(heatshrink_encoder *hse)
{
return hse->flags & FLAG_IS_FINISHING; 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 *oi->output_size < oi->buf_size;
} }
/* Return the longest match for the bytes at buf[end:end+maxlen] between /* 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. */ * 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, 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", LOG("-- scanning for match of buf[%u:%u] between buf[%u:%u] (max %u bytes)\n",
end, end + maxlen, start, end + maxlen - 1, maxlen); end, end + maxlen, start, end + maxlen - 1, maxlen);
uint8_t *buf = hse->buffer; 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 match_index = MATCH_NOT_FOUND;
uint16_t len = 0; uint16_t len = 0;
uint8_t * const needlepoint = &buf[end]; uint8_t *const needlepoint = &buf[end];
#if HEATSHRINK_USE_INDEX #if HEATSHRINK_USE_INDEX
struct hs_index *hsi = HEATSHRINK_ENCODER_INDEX(hse); struct hs_index *hsi = HEATSHRINK_ENCODER_INDEX(hse);
int16_t pos = hsi->index[end]; int16_t pos = hsi->index[end];
while (pos - (int16_t)start >= 0) { while (pos - (int16_t) start >= 0) {
uint8_t * const pospoint = &buf[pos]; uint8_t *const pospoint = &buf[pos];
/* Only check matches that will potentially beat the current maxlen. /* Only check matches that will potentially beat the current maxlen.
* This is redundant with the index if match_maxlen is 0, but the * 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++) { for (len = 1; len < maxlen; len++) {
if (pospoint[len] != needlepoint[len]) break; if (pospoint[len] != needlepoint[len]) { break; }
} }
if (len > match_maxlen) { if (len > match_maxlen) {
match_maxlen = len; match_maxlen = len;
match_index = (uint16_t)pos; match_index = (uint16_t) pos;
if (len == maxlen) { break; } /* won't find better */ if (len == maxlen) { break; } /* won't find better */
} }
pos = hsi->index[pos]; pos = hsi->index[pos];
@ -510,9 +548,8 @@ static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start,
} }
#endif #endif
const size_t break_even_point = const size_t break_even_point = (size_t) (1 + HEATSHRINK_ENCODER_WINDOW_BITS(hse)
(1 + HEATSHRINK_ENCODER_WINDOW_BITS(hse) + + HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse));
/* Instead of comparing break_even_point against 8*match_maxlen, /* Instead of comparing break_even_point against 8*match_maxlen,
* compare match_maxlen against break_even_point/8 to avoid * 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; 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 count = 0;
uint8_t bits = 0; uint8_t bits = 0;
if (hse->outgoing_bits_count > 8) { if (hse->outgoing_bits_count > 8) {
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 { } else {
count = hse->outgoing_bits_count; count = hse->outgoing_bits_count;
bits = (uint8_t)hse->outgoing_bits; bits = (uint8_t) hse->outgoing_bits;
} }
if (count > 0) { 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. /* Push COUNT (max 8) bits to the output buffer, which has room.
* Bytes are set from the lowest bits, up. */ * Bytes are set from the lowest bits, up. */
static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits, static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits,
output_info *oi) { output_info *oi)
{
ASSERT(count <= 8); ASSERT(count <= 8);
LOG("++ push_bits: %d bits, input of 0x%02x\n", count, bits); 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) { if (count == 8 && hse->bit_index == 0x80) {
oi->buf[(*oi->output_size)++] = bits; oi->buf[(*oi->output_size)++] = bits;
} else { } else {
for (int i=count - 1; i>=0; i--) { for (int i = count - 1; i >= 0; i--) {
bool bit = bits & (1 << i); bool bit = bits & (1 << i);
if (bit) { hse->current_byte |= hse->bit_index; } if (bit) { hse->current_byte |= hse->bit_index; }
if (0) { 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 processed_offset = hse->match_scan_index - 1;
uint16_t input_offset = get_input_offset(hse) + processed_offset; uint16_t input_offset = get_input_offset(hse) + processed_offset;
uint8_t c = hse->buffer[input_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); 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); size_t input_buf_sz = get_input_buffer_size(hse);
uint16_t msi = hse->match_scan_index; 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 * used for future matches. Don't bother checking whether the
* input is less than the maximum size, because if it isn't, * input is less than the maximum size, because if it isn't,
* we're done anyway. */ * we're done anyway. */
uint16_t rem = (uint16_t)input_buf_sz - msi; // unprocessed bytes uint16_t rem = (uint16_t) input_buf_sz - msi; // unprocessed bytes
uint16_t shift_sz = (uint16_t)input_buf_sz + rem; uint16_t shift_sz = (uint16_t) input_buf_sz + rem;
memmove(&hse->buffer[0], memmove(&hse->buffer[0],
&hse->buffer[input_buf_sz - rem], &hse->buffer[input_buf_sz - rem],
shift_sz); shift_sz);
hse->match_scan_index = 0; 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) static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepath)
{ {
EspFsFile *file = hconn->cgiData; EspFsFile *file = hconn->cgiData;
int len; size_t len;
uint8_t buff[FILE_CHUNK_LEN + 1]; uint8_t buff[FILE_CHUNK_LEN + 1];
char acceptEncodingBuffer[64 + 1]; char acceptEncodingBuffer[64 + 1];
int isGzip; int isGzip;
@ -182,21 +182,21 @@ typedef enum {
typedef struct { typedef struct {
EspFsFile *file; EspFsFile *file;
int tokenPos; ssize_t tokenPos;
char buff[FILE_CHUNK_LEN + 1]; char buff[FILE_CHUNK_LEN + 1];
char token[HTTPD_ESPFS_TOKEN_LEN]; char token[HTTPD_ESPFS_TOKEN_LEN];
char *pToken; char *pToken;
bool chunk_resume; bool chunk_resume;
int buff_len; size_t buff_len;
int buff_x; size_t buff_x;
int buff_sp; size_t buff_sp;
char *buff_e; char *buff_e;
TplEncode tokEncode; TplEncode tokEncode;
} TplDataInternal; } 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; } if (conn == NULL) { return 0; }
@ -206,9 +206,9 @@ int tplSendN(HttpdConnData *conn, const char *str, int len)
if (tdi->tokEncode == ENCODE_PLAIN) { if (tdi->tokEncode == ENCODE_PLAIN) {
return httpdSendStrN(conn, str, len); return httpdSendStrN(conn, str, len);
} else if (tdi->tokEncode == ENCODE_HTML) { } 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) { } else if (tdi->tokEncode == ENCODE_JS) {
return httpdSend_js(conn, str, len); return httpdSend_js(conn, str, (ssize_t) len);
} }
return 0; return 0;
} }
@ -218,8 +218,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
{ {
TplDataInternal *tdi = conn->cgiData; TplDataInternal *tdi = conn->cgiData;
int len; size_t len, x, sp;
int x, sp = 0;
char *e = NULL; char *e = NULL;
if (conn->conn == NULL) { if (conn->conn == NULL) {
@ -383,7 +382,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
// looks like we collected some garbage, put it back // looks like we collected some garbage, put it back
httpdSendStrN(conn, "%", 1); httpdSendStrN(conn, "%", 1);
if (tdi->tokenPos > 0) { if (tdi->tokenPos > 0) {
httpdSendStrN(conn, tdi->token, tdi->tokenPos); httpdSendStrN(conn, tdi->token, (size_t) tdi->tokenPos);
} }
// the bad char // the bad char
httpdSendStrN(conn, &c, 1); httpdSendStrN(conn, &c, 1);
@ -406,7 +405,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
//Send remaining bit. //Send remaining bit.
if (sp != 0) { if (sp != 0) {
httpdSendStrN(conn, e, sp); httpdSendStrN(conn, e, (size_t) sp);
} }
if (len != FILE_CHUNK_LEN) { if (len != FILE_CHUNK_LEN) {

@ -96,10 +96,10 @@ struct WebsockPriv {
static Websock *llStart = NULL; 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]; uint8_t buf[14];
int i = 0; size_t i = 0;
buf[i++] = opcode; buf[i++] = opcode;
if (len > 65535) { if (len > 65535) {
buf[i++] = 127; 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++] = 0;
buf[i++] = 0; buf[i++] = 0;
buf[i++] = len >> 24; buf[i++] = (uint8_t) (len >> 24);
buf[i++] = len >> 16; buf[i++] = (uint8_t) (len >> 16);
buf[i++] = len >> 8; buf[i++] = (uint8_t) (len >> 8);
buf[i++] = len; buf[i++] = (uint8_t) (len);
} else if (len > 125) { } else if (len > 125) {
buf[i++] = 126; buf[i++] = 126;
buf[i++] = len >> 8; buf[i++] = (uint8_t) (len >> 8);
buf[i++] = len; buf[i++] = (uint8_t) (len & 0xFF);
} else { } else {
buf[i++] = len; buf[i++] = (uint8_t) len;
} }
// ws_dbg("WS: Sent frame head for payload of %d bytes.", len); // ws_dbg("WS: Sent frame head for payload of %d bytes.", len);
return httpdSend(ws->conn, buf, i); 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 cgiWebsocketSend(Websock *ws, const uint8_t *data, size_t len, int flags)
{ {
int r = 0; int r = 0;
int fl = 0; uint8_t fl = 0;
// Continuation frame has opcode 0 // Continuation frame has opcode 0
if (!(flags & WEBSOCK_FLAG_CONT)) { if (!(flags & WEBSOCK_FLAG_CONT)) {
if (flags & WEBSOCK_FLAG_BIN) { 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) 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); sendFrameHead(ws, FLAG_FIN | OPCODE_CLOSE, 2);
httpdSend(ws->conn, rs, 2); httpdSend(ws->conn, rs, 2);
ws->priv->closedHere = 1; 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) 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; httpd_cgi_state r = HTTPD_CGI_MORE;
int wasHeaderByte; int wasHeaderByte;
Websock *ws = (Websock *) connData->cgiData; 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); // 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) { 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++) { 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"); // ws_dbg("WS: Got close frame");
if (!ws->priv->closedHere) { if (!ws->priv->closedHere) {
// ws_dbg("WS: Sending response close frame, %x %x (i=%d, len=%d)", data[i], data[i+1], i, len); // 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) { if (i <= len - 2) {
// TODO why?
cause = ((data[i] << 8) & 0xff00) + (data[i + 1] & 0xff); cause = ((data[i] << 8) & 0xff00) + (data[i + 1] & 0xff);
} }
cgiWebsocketClose(ws, cause); cgiWebsocketClose(ws, cause);
@ -362,8 +363,8 @@ httpd_cgi_state cgiWebSocketRecv(HttpdConnData *connData, uint8_t *data, size_t
} }
} }
i += sl - 1; i += (size_t) (sl - 1);
ws->priv->fr.len -= sl; ws->priv->fr.len -= (uint64_t) sl;
if (ws->priv->fr.len == 0) { if (ws->priv->fr.len == 0) {
ws->priv->wsStatus = ST_FLAGS; //go receive next frame 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 { struct HttpdConnType {
int fd; int fd;
int needWriteDoneNotif; bool needWriteDoneNotif;
int needsClose; bool needsClose;
int port; uint16_t port;
char ip[4]; uint8_t ip[4];
}; };
static HttpdConnType s_rconn[HTTPD_MAX_CONNECTIONS]; static HttpdConnType s_rconn[HTTPD_MAX_CONNECTIONS];
@ -56,7 +56,7 @@ void httpdServerTask(void *pvParameters)
fd_set readset, writeset; fd_set readset, writeset;
struct sockaddr_in server_addr; struct sockaddr_in server_addr;
struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;
int httpPort; uint16_t httpPort;
s_shutdown_requested = false; 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); ret = (int) recv(s_rconn[i].fd, s_recv_buf, HTTPD_RECV_BUF_LEN, 0);
if (ret > 0) { if (ret > 0) {
//Data received. Pass to httpd. //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 { } else {
//recv error,connection close //recv error,connection close
httpdDisconCb(&s_rconn[i], s_rconn[i].ip, s_rconn[i].port); 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) uint8_t httpdHexVal(char c)
{ {
if (c >= '0' && c <= '9') { return c - '0'; } if (c >= '0' && c <= '9') { return (uint8_t) (c - '0'); }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; } if (c >= 'A' && c <= 'F') { return (uint8_t) (c - 'A' + 10); }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } if (c >= 'a' && c <= 'f') { return (uint8_t) (c - 'a' + 10); }
return 0; 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; size_t s = 0, d = 0;
int esced = 0; int esced = 0;
char escVal = 0; uint8_t escVal = 0;
while (s < valLen && d < buffLen) { while (s < valLen && d < buffLen) {
if (esced == 1) { if (esced == 1) {
escVal = httpdHexVal(val[s]) << 4; escVal = httpdHexVal(val[s]) << 4;
esced = 2; esced = 2;
} else if (esced == 2) { } else if (esced == 2) {
escVal |= httpdHexVal(val[s]); escVal |= httpdHexVal(val[s]);
buff[d++] = escVal; buff[d++] = (char) escVal;
esced = 0; esced = 0;
} else if (val[s] == '%') { } else if (val[s] == '%') {
esced = 1; esced = 1;
@ -58,7 +58,7 @@ int httpdFindArg(const char *line, const char *arg, char *buff, size_t buffLen)
e = strstr(p, "&"); e = strstr(p, "&");
if (e == NULL) { e = p + strlen(p); } if (e == NULL) { e = p + strlen(p); }
router_dbg("findArg: val %s len %d", p, (int) (e - 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, "&"); p = strstr(p, "&");
if (p != NULL) { p += 1; } if (p != NULL) { p += 1; }

@ -21,6 +21,8 @@ Esp8266 http server - core routines
static void cleanupCgiAndUserData(HttpdConnData *hconn); static void cleanupCgiAndUserData(HttpdConnData *hconn);
static void httpdRetireConn(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. //This gets set at init time.
static const HttpdBuiltInUrl *s_builtInUrls; static const HttpdBuiltInUrl *s_builtInUrls;
static const char *s_serverName = HTTPD_SERVERNAME; static const char *s_serverName = HTTPD_SERVERNAME;
@ -28,12 +30,12 @@ static const char *s_serverName = HTTPD_SERVERNAME;
typedef struct HttpSendBacklogItem HttpSendBacklogItem; typedef struct HttpSendBacklogItem HttpSendBacklogItem;
struct HttpSendBacklogItem { struct HttpSendBacklogItem {
int len; size_t len;
HttpSendBacklogItem *next; HttpSendBacklogItem *next;
char data[]; uint8_t data[];
}; };
//Flags //Flags (1 byte)
#define HFL_HTTP11 (1<<0) #define HFL_HTTP11 (1<<0)
#define HFL_CHUNKED (1<<1) #define HFL_CHUNKED (1<<1)
#define HFL_SENDINGBODY (1<<2) #define HFL_SENDINGBODY (1<<2)
@ -45,13 +47,13 @@ struct HttpSendBacklogItem {
struct HttpdPriv { struct HttpdPriv {
char head[HTTPD_MAX_HEAD_LEN]; char head[HTTPD_MAX_HEAD_LEN];
char corsToken[HTTPD_MAX_CORS_TOKEN_LEN]; char corsToken[HTTPD_MAX_CORS_TOKEN_LEN];
int headPos; size_t headPos;
uint8_t *sendBuff; uint8_t *sendBuff;
int sendBuffLen; size_t sendBuffLen;
char *chunkHdr; char *chunkHdr;
HttpSendBacklogItem *sendBacklog; HttpSendBacklogItem *sendBacklog;
int sendBacklogSize; size_t sendBacklogSize;
int flags; uint8_t flags;
}; };
@ -104,7 +106,7 @@ size_t httpGetBacklogSize(const HttpdConnData *conn)
{ {
HttpSendBacklogItem *bl = conn->priv->sendBacklog; HttpSendBacklogItem *bl = conn->priv->sendBacklog;
if (!bl) { return 0; } if (!bl) { return 0; }
int bytes = 0; size_t bytes = 0;
while (bl != NULL) { while (bl != NULL) {
bytes += bl->len; bytes += bl->len;
bl = bl->next; bl = bl->next;
@ -113,7 +115,7 @@ size_t httpGetBacklogSize(const HttpdConnData *conn)
} }
//Looks up the connData info for a specific connection //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++) { for (int i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
if (s_connData[i] && s_connData[i]->remote_port == remPort && 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) void httdSetTransferMode(HttpdConnData *conn, httpd_transfer_opt mode)
{ {
if (mode == HTTPD_TRANSFER_CLOSE) { if (mode == HTTPD_TRANSFER_CLOSE) {
conn->priv->flags &= ~HFL_CHUNKED; conn->priv->flags &= (uint8_t) ~HFL_CHUNKED;
conn->priv->flags &= ~HFL_NOCONNECTIONSTR; conn->priv->flags &= (uint8_t) ~HFL_NOCONNECTIONSTR;
} else if (mode == HTTPD_TRANSFER_CHUNKED) { } else if (mode == HTTPD_TRANSFER_CHUNKED) {
conn->priv->flags |= HFL_CHUNKED; conn->priv->flags |= HFL_CHUNKED;
conn->priv->flags &= ~HFL_NOCONNECTIONSTR; conn->priv->flags &= (uint8_t) ~HFL_NOCONNECTIONSTR;
} else if (mode == HTTPD_TRANSFER_NONE) { } else if (mode == HTTPD_TRANSFER_NONE) {
conn->priv->flags &= ~HFL_CHUNKED; conn->priv->flags &= (uint8_t) ~HFL_CHUNKED;
conn->priv->flags |= HFL_NOCONNECTIONSTR; conn->priv->flags |= HFL_NOCONNECTIONSTR;
} }
} }
@ -212,7 +214,6 @@ void httdResponseOptions(HttpdConnData *conn, int cors)
void httpdStartResponse(HttpdConnData *conn, int code) void httpdStartResponse(HttpdConnData *conn, int code)
{ {
char buff[256]; char buff[256];
size_t l;
const char *connStr = ""; const char *connStr = "";
if (!(conn->priv->flags & HFL_NOCONNECTIONSTR)) { 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", 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, ((conn->priv->flags & HFL_HTTP11) ? 1 : 0),
code, code,
httpdStatusName(code), httpdStatusName(code),
s_serverName, s_serverName,
@ -287,7 +288,7 @@ int httpdSend(HttpdConnData *conn, const uint8_t *data, size_t len)
return 1; 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) #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 httpdSend_html(HttpdConnData *conn, const char *data, ssize_t len)
{ {
int start = 0, end = 0; int start = 0, end = 0;
uint8_t c; char c;
if (conn->conn == NULL) { return 0; } if (conn->conn == NULL) { return 0; }
if (len < 0) { len = (int) strlen((const char *) data); } if (len < 0) { len = (int) strlen((const char *) data); }
if (len == 0) { return 0; } 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 httpdSend_js(HttpdConnData *conn, const char *data, ssize_t len)
{ {
int start = 0, end = 0; int start = 0, end = 0;
uint8_t c; char c;
if (conn->conn == NULL) { return 0; } if (conn->conn == NULL) { return 0; }
if (len < 0) { len = (int) strlen((const char *) data); } if (len < 0) { len = (int) strlen((const char *) data); }
if (len == 0) { return 0; } 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. //Returns false if data could not be sent nor put in backlog.
bool httpdFlushSendBuffer(HttpdConnData *conn) bool httpdFlushSendBuffer(HttpdConnData *conn)
{ {
int r, len; int r;
size_t len;
if (conn->conn == NULL) { return false; } if (conn->conn == NULL) { return false; }
if (conn->priv->chunkHdr != NULL) { if (conn->priv->chunkHdr != NULL) {
//We're sending chunked data, and the chunk needs fixing up. //We're sending chunked data, and the chunk needs fixing up.
//Finish chunk with cr/lf //Finish chunk with cr/lf
httpdSendStr(conn, "\r\n"); httpdSendStr(conn, "\r\n");
//Calculate length of chunk //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 //Fix up chunk header to correct value
conn->priv->chunkHdr[0] = httpdHexNibble(len >> 12); conn->priv->chunkHdr[0] = httpdHexNibble((uint8_t) (len >> 12));
conn->priv->chunkHdr[1] = httpdHexNibble(len >> 8); conn->priv->chunkHdr[1] = httpdHexNibble((uint8_t) (len >> 8));
conn->priv->chunkHdr[2] = httpdHexNibble(len >> 4); conn->priv->chunkHdr[2] = httpdHexNibble((uint8_t) (len >> 4));
conn->priv->chunkHdr[3] = httpdHexNibble(len >> 0); conn->priv->chunkHdr[3] = httpdHexNibble((uint8_t) (len >> 0));
//Reset chunk hdr for next call //Reset chunk hdr for next call
conn->priv->chunkHdr = NULL; conn->priv->chunkHdr = NULL;
} }
@ -388,7 +390,7 @@ bool httpdFlushSendBuffer(HttpdConnData *conn)
if (!r) { if (!r) {
//Can't send this for some reason. Dump packet in backlog, we can send it later. //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) { 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; conn->priv->sendBuffLen = 0;
return false; return false;
} }
@ -437,7 +439,7 @@ void httpdCgiIsDone(HttpdConnData *conn)
//Callback called when the data on a socket has been successfully //Callback called when the data on a socket has been successfully
//sent. //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); HttpdConnData *conn = httpdFindConnData(rconn, remIp, remPort);
httpdContinue(conn); httpdContinue(conn);
@ -647,7 +649,7 @@ static void httpdParseHeader(char *h, HttpdConnData *conn)
i = 11; i = 11;
//Skip trailing spaces //Skip trailing spaces
while (h[i] == ' ') { i++; } 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:")) { } else if (strstarts(h, "Content-Length:")) {
i = 15; i = 15;
//Skip trailing spaces //Skip trailing spaces
@ -660,7 +662,7 @@ static void httpdParseHeader(char *h, HttpdConnData *conn)
// we'll stream this in in chunks // we'll stream this in in chunks
conn->post->buffSize = HTTPD_MAX_POST_LEN; conn->post->buffSize = HTTPD_MAX_POST_LEN;
} else { } 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); http_dbg("Mallocced buffer for %d + 1 bytes of post data.", (int) conn->post->buffSize);
conn->post->buff = (char *) httpdPlatMalloc(conn->post->buffSize + 1); 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. //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; char *p, *e;
httpdPlatLock(); 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 //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; conn->priv->head[conn->priv->headPos] = 0;
//Scan for /r/n/r/n. Receiving this indicates the headers end. //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) { 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) { } else if (conn->post->len != 0) {
//This byte is a POST byte. //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->post->received++;
conn->hostName = NULL; conn->hostName = NULL;
if (conn->post->buffLen >= conn->post->buffSize || (int) conn->post->received == conn->post->len) { 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 //The platform layer should ALWAYS call this function, regardless if the connection is closed by the server
//or by the client. //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(); httpdPlatLock();
HttpdConnData *hconn = httpdFindConnData(rconn, remIp, remPort); 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(); httpdPlatLock();
//Find empty conndata in pool //Find empty conndata in pool
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) { for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <ctype.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, 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, 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); // We're only using 32 bit lengths
sha1_addUncounted(s, 0); // But SHA-1 supports 64 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, 0); // So zero pad the top bits
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 sha1_addUncounted(s, (uint8_t)(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, (uint8_t)(s->byteCount >> 21)); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, s->byteCount >> 13); // byte. sha1_addUncounted(s, (uint8_t)(s->byteCount >> 13)); // byte.
sha1_addUncounted(s, s->byteCount >> 5); sha1_addUncounted(s, (uint8_t)(s->byteCount >> 5));
sha1_addUncounted(s, s->byteCount << 3); sha1_addUncounted(s, (uint8_t)(s->byteCount << 3));
} }
uint8_t *httpd_sha1_result(httpd_sha1nfo *s) uint8_t *httpd_sha1_result(httpd_sha1nfo *s)

Loading…
Cancel
Save