mirror of
https://github.com/webui-dev/webui.git
synced 2024-09-17 17:27:54 +03:00
WebUI 2.0.1
This commit is contained in:
parent
efa10711a5
commit
937ab1cda5
@ -4,32 +4,39 @@
|
||||
SHELL=CMD
|
||||
SOURCE=../../../src
|
||||
INCLUDE=../../../include
|
||||
EXAMPLES=../../../examples
|
||||
|
||||
all: release
|
||||
|
||||
debug:
|
||||
@echo Build WebUI (Debug Static)...
|
||||
@gcc -g -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
# Static with Debug info
|
||||
@echo Build WebUI Library (Debug Static)...
|
||||
@gcc -g -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c" -Wno-stringop-overread
|
||||
@gcc -g -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@ar rc libwebui-2-static-x64.a webui.o mongoose.o
|
||||
@ranlib libwebui-2-static-x64.a
|
||||
@echo Build WebUI (Debug Dynamic)...
|
||||
@gcc -g -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
# Dynamic with Debug info
|
||||
@echo Build WebUI Library (Debug Dynamic)...
|
||||
@gcc -g -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c" -Wno-stringop-overread
|
||||
@gcc -g -fPIC -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@gcc -g -shared -o webui-2-x64.dll webui.o mongoose.o -lws2_32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
release:
|
||||
@echo Build WebUI (Release Static)...
|
||||
@gcc -Os -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
# Static Release
|
||||
@echo Build WebUI Library (Release Static)...
|
||||
@gcc -Os -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c" -Wno-stringop-overread
|
||||
@gcc -Os -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@ar rc libwebui-2-static-x64.a webui.o mongoose.o
|
||||
@ranlib libwebui-2-static-x64.a
|
||||
@echo Build WebUI (Release Dynamic)...
|
||||
@gcc -O3 -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
# Dynamic Release
|
||||
@echo Build WebUI Library (Release Dynamic)...
|
||||
@gcc -O3 -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c" -Wno-stringop-overread
|
||||
@gcc -O3 -fPIC -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@gcc -shared -o webui-2-x64.dll webui.o mongoose.o -lws2_32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
|
@ -4,25 +4,36 @@
|
||||
all: release
|
||||
|
||||
debug:
|
||||
@echo Build WebUI (Debug Static)...
|
||||
# Static with Debug info
|
||||
@echo Build WebUI Library (Debug Static)...
|
||||
@cl /Zi /Fomongoose.obj /c /EHsc "../../../src/mongoose.c" /I "../../../include" 1>NUL 2>&1
|
||||
@cl /Zi /Fowebui.obj /c /EHsc "../../../src/webui.c" /I "../../../include" 1>NUL 2>&1
|
||||
@lib /OUT:webui-2-static-x64.lib webui.obj mongoose.obj 1>NUL 2>&1
|
||||
@echo Build WebUI (Debug Dynamic)...
|
||||
# Dynamic with Debug info
|
||||
@echo Build WebUI Library (Debug Dynamic)...
|
||||
@cl /Zi /Fomongoose.obj /c /EHsc "../../../src/mongoose.c" /I "../../../include" 1>NUL 2>&1
|
||||
@cl /Zi /Fowebui.obj /c /EHsc "../../../src/webui.c" /I "../../../include" 1>NUL 2>&1
|
||||
@link /DLL /OUT:webui-2-x64.dll webui.obj mongoose.obj 1>NUL 2>&1
|
||||
# Clean
|
||||
@- del *.obj >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
release:
|
||||
@echo Build WebUI (Release Static)...
|
||||
# Static Release
|
||||
@echo Build WebUI Library (Release Static)...
|
||||
@cl /Fomongoose.obj /c /EHsc "../../../src/mongoose.c" /I "../../../include" 1>NUL 2>&1
|
||||
@cl /Fowebui.obj /c /EHsc "../../../src/webui.c" /I "../../../include" 1>NUL 2>&1
|
||||
@lib /OUT:webui-2-static-x64.lib webui.obj mongoose.obj 1>NUL 2>&1
|
||||
@echo Build WebUI (Release Dynamic)...
|
||||
# Dynamic Release
|
||||
@echo Build WebUI Library (Release Dynamic)...
|
||||
@cl /Fomongoose.obj /c /EHsc "../../../src/mongoose.c" /I "../../../include" 1>NUL 2>&1
|
||||
@cl /Fowebui.obj /c /EHsc "../../../src/webui.c" /I "../../../include" 1>NUL 2>&1
|
||||
@link /DLL /OUT:webui-2-x64.dll webui.obj mongoose.obj 1>NUL 2>&1
|
||||
# Clean
|
||||
@- del *.obj >nul 2>&1
|
||||
@- del *.ilk >nul 2>&1
|
||||
@- del *.pdb >nul 2>&1
|
||||
@- del *.exp >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
|
@ -4,30 +4,37 @@
|
||||
SHELL=CMD
|
||||
SOURCE=../../../src
|
||||
INCLUDE=../../../include
|
||||
EXAMPLES=../../../examples
|
||||
|
||||
all: release
|
||||
|
||||
debug:
|
||||
@echo Build WebUI (Debug Static)...
|
||||
# Static with Debug info
|
||||
@echo Build WebUI Library (Debug Static)...
|
||||
@tcc -g -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
@tcc -g -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@tcc -m64 -ar rcs libwebui-2-static-x64.a webui.o mongoose.o
|
||||
@echo Build WebUI (Debug Dynamic)...
|
||||
# Dynamic with Debug info
|
||||
@echo Build WebUI Library (Debug Dynamic)...
|
||||
@tcc -g -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
@tcc -g -fPIC -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@tcc -g -shared -o webui-2-x64.dll webui.o mongoose.o -lws2_32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
release:
|
||||
@echo Build WebUI (Release Static)...
|
||||
# Static Release
|
||||
@echo Build WebUI Library (Release Static)...
|
||||
@tcc -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
@tcc -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@tcc -m64 -ar rcs libwebui-2-static-x64.a webui.o mongoose.o
|
||||
@echo Build WebUI (Release Dynamic)...
|
||||
# Dynamic Release
|
||||
@echo Build WebUI Library (Release Dynamic)...
|
||||
@tcc -fPIC -m64 -o mongoose.o -I "$(INCLUDE)" -c "$(SOURCE)/mongoose.c"
|
||||
@tcc -fPIC -m64 -o webui.o -I "$(INCLUDE)" -c "$(SOURCE)/webui.c"
|
||||
@tcc -shared -o webui-2-x64.dll webui.o mongoose.o -lws2_32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
|
@ -9,7 +9,7 @@ To build a C WebUI application, you will need to [build](https://github.com/alif
|
||||
```sh
|
||||
copy ..\..\build\Windows\MSVC\webui-2-static-x64.lib webui-2-static-x64.lib
|
||||
rc win.rc
|
||||
cl "example.c" /I "../../include" /link /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-static-x64.lib /OUT:example.exe
|
||||
cl "main.c" /I "../../include" /link /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-static-x64.lib /OUT:main.exe
|
||||
```
|
||||
|
||||
- **Build Tools for Microsoft Visual Studio - Dynamic**
|
||||
@ -17,34 +17,34 @@ cl "example.c" /I "../../include" /link /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res
|
||||
copy ..\..\build\Windows\MSVC\webui-2-x64.dll webui-2-x64.dll
|
||||
copy ..\..\build\Windows\MSVC\webui-2-x64.lib webui-2-x64.lib
|
||||
rc win.rc
|
||||
cl "example.c" /I "../../include" /link /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-x64.lib /OUT:example.exe
|
||||
cl "main.c" /I "../../include" /link /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-x64.lib /OUT:main.exe
|
||||
```
|
||||
|
||||
- **MinGW - Static**
|
||||
```sh
|
||||
copy ..\..\build\Windows\GCC\libwebui-2-static-x64.a libwebui-2-static-x64.a
|
||||
windres win.rc -O coff -o win.res
|
||||
gcc -static -Os -m64 -o example.exe "example.c" -I "../../include" -L. win.res -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
strip --strip-all example.exe
|
||||
gcc -static -Os -m64 -o main.exe "main.c" -I "../../include" -L. win.res -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
strip --strip-all main.exe
|
||||
```
|
||||
|
||||
- **MinGW - Dynamic**
|
||||
```sh
|
||||
copy ..\..\build\Windows\GCC\webui-2-x64.dll webui-2-x64.dll
|
||||
windres win.rc -O coff -o win.res
|
||||
gcc -m64 -o example.exe "example.c" -I "../../include" -L. win.res webui-2-x64.dll -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
gcc -m64 -o main.exe "main.c" -I "../../include" -L. win.res webui-2-x64.dll -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
strip --strip-all example_dynamic.exe
|
||||
```
|
||||
|
||||
- **TCC - Static**
|
||||
```sh
|
||||
copy ..\..\build\Windows\TCC\libwebui-2-static-x64.a libwebui-2-static-x64.a
|
||||
tcc -m64 -o example.exe "example.c" -I "../../include" -L. -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
tcc -m64 -o main.exe "main.c" -I "../../include" -L. -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
```
|
||||
|
||||
- **TCC - Dynamic**
|
||||
```sh
|
||||
copy ..\..\build\Windows\TCC\webui-2-x64.dll webui-2-x64.dll
|
||||
tcc -impdef webui-2-x64.dll -o webui-2-x64.def
|
||||
tcc -m64 -o example_dynamic.exe "example.c" -I "../../include" -L. webui-2-x64.def -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
tcc -m64 -o example_dynamic.exe "main.c" -I "../../include" -L. webui-2-x64.def -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
```
|
||||
|
51
examples/C/Windows/GCC/Makefile
Normal file
51
examples/C/Windows/GCC/Makefile
Normal file
@ -0,0 +1,51 @@
|
||||
# WebUI Library 2.x
|
||||
# C99 Example
|
||||
# Windows - GCC
|
||||
|
||||
SHELL=CMD
|
||||
LIB=../../../../build/Windows/GCC
|
||||
INCLUDE=../../../../include
|
||||
SOURCE=../..
|
||||
|
||||
all: release
|
||||
|
||||
debug:
|
||||
# Build Lib
|
||||
@cd "$(LIB)" && $(MAKE) debug
|
||||
# Static with Debug info
|
||||
@echo Build C99 Example (Debug Static)...
|
||||
@windres win.rc -O coff -o win.res
|
||||
@gcc -g -static -m64 -o main.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" win.res -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=console -luser32
|
||||
# Dynamic with Debug info
|
||||
@echo Build C99 Example (Debug Dynamic)...
|
||||
@windres win.rc -O coff -o win.res
|
||||
@gcc -g -m64 -o main-dyn.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" win.res "$(LIB)/webui-2-x64.dll" -lws2_32 -Wall -Wl,-subsystem=console -luser32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@- del *.res >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
release:
|
||||
# Build Lib
|
||||
@cd "$(LIB)" && $(MAKE)
|
||||
# Static Release
|
||||
@echo Build C99 Example (Release Static)...
|
||||
@windres win.rc -O coff -o win.res
|
||||
@gcc -static -Os -m64 -o main.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" win.res -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
@strip --strip-all main.exe
|
||||
# Dynamic Release
|
||||
@echo Build C99 Example (Release Dynamic)...
|
||||
@windres win.rc -O coff -o win.res
|
||||
@gcc -m64 -o main-dyn.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" win.res "$(LIB)/webui-2-x64.dll" -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
@strip --strip-all main-dyn.exe
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@- del *.res >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
- del *.o >nul 2>&1
|
||||
- del *.dll >nul 2>&1
|
||||
- del *.a >nul 2>&1
|
||||
- del *.exe >nul 2>&1
|
||||
- del *.res >nul 2>&1
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
49
examples/C/Windows/MSVC/Makefile
Normal file
49
examples/C/Windows/MSVC/Makefile
Normal file
@ -0,0 +1,49 @@
|
||||
# WebUI Library 2.x
|
||||
# C99 Example
|
||||
# Windows - Microsoft Visual C
|
||||
|
||||
SHELL=CMD
|
||||
_LIB=../../../../build/Windows/MSVC/
|
||||
_INCLUDE=../../../../include/
|
||||
_SOURCE=../../
|
||||
|
||||
all: release
|
||||
|
||||
debug:
|
||||
# Build Lib
|
||||
@cd "$(_LIB)" && $(MAKE) debug
|
||||
# Static with Debug info
|
||||
@echo Build C99 Example (Debug Static)...
|
||||
@rc win.rc
|
||||
@cl /Zi "$(_SOURCE)/main.c" /I "$(_INCLUDE)" /link /LIBPATH:"$(_LIB)" /MACHINE:X64 /SUBSYSTEM:CONSOLE win.res webui-2-static-x64.lib /OUT:main.exe
|
||||
# Dynamic with Debug info
|
||||
@echo Build C99 Example (Debug Dynamic)...
|
||||
@rc win.rc
|
||||
@cl /Zi "$(_SOURCE)/main.c" /I "$(_INCLUDE)" /link /LIBPATH:"$(_LIB)" /MACHINE:X64 /SUBSYSTEM:CONSOLE win.res webui-2-x64.lib /OUT:main-dyn.exe
|
||||
|
||||
release:
|
||||
# Build Lib
|
||||
@cd "$(_LIB)" && $(MAKE)
|
||||
# Static Release
|
||||
@echo Build C99 Example (Release Static)...
|
||||
@rc win.rc
|
||||
@cl "$(_SOURCE)/main.c" /I "$(_INCLUDE)" /link /LIBPATH:"$(_LIB)" /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-static-x64.lib /OUT:main.exe
|
||||
# Dynamic Release
|
||||
@echo Build C99 Example (Release Dynamic)...
|
||||
@rc win.rc
|
||||
@cl "$(_SOURCE)/main.c" /I "$(_INCLUDE)" /link /LIBPATH:"$(_LIB)" /MACHINE:X64 /SUBSYSTEM:WINDOWS win.res webui-2-x64.lib /OUT:main-dyn.exe
|
||||
# Clean
|
||||
@- del *.res >nul 2>&1
|
||||
@- del *.obj >nul 2>&1
|
||||
@- del *.exp >nul 2>&1
|
||||
@- del *.lib >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
- del *.obj >nul 2>&1
|
||||
- del *.ilk >nul 2>&1
|
||||
- del *.pdb >nul 2>&1
|
||||
- del *.exp >nul 2>&1
|
||||
- del *.exe >nul 2>&1
|
||||
- del *.lib >nul 2>&1
|
||||
- del *.res >nul 2>&1
|
BIN
examples/C/Windows/MSVC/win.ico
Normal file
BIN
examples/C/Windows/MSVC/win.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
24
examples/C/Windows/MSVC/win.rc
Normal file
24
examples/C/Windows/MSVC/win.rc
Normal file
@ -0,0 +1,24 @@
|
||||
id ICON "win.ico"
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "My Business Name"
|
||||
VALUE "LegalCopyright", "My Business Name"
|
||||
VALUE "FileDescription", "My WebUI Application"
|
||||
VALUE "InternalName", "MyApplication"
|
||||
VALUE "ProductName", "My Application"
|
||||
VALUE "FileVersion", "1.0"
|
||||
VALUE "OriginalFilename", "webui.exe"
|
||||
VALUE "ProductVersion", "1.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
43
examples/C/Windows/TCC/Makefile
Normal file
43
examples/C/Windows/TCC/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
# WebUI Library 2.x
|
||||
# C99 Example
|
||||
# Windows - Tiny C Compiler
|
||||
|
||||
SHELL=CMD
|
||||
LIB=../../../../build/Windows/TCC/
|
||||
INCLUDE=../../../../include/
|
||||
SOURCE=../../
|
||||
|
||||
all: release
|
||||
|
||||
debug:
|
||||
# Build Lib
|
||||
@cd "$(LIB)" && $(MAKE) debug
|
||||
# Static with Debug info
|
||||
@echo Build C99 Example (Debug Static)...
|
||||
@tcc -g -m64 -o main.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=console -luser32
|
||||
# Dynamic with Debug info
|
||||
@echo Build C99 Example (Debug Dynamic)...
|
||||
@tcc -g -m64 -o main-dyn.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" "$(LIB)/webui-2-x64.def" -lws2_32 -Wall -Wl,-subsystem=console -luser32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@- del *.def >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
release:
|
||||
# Build Lib
|
||||
@cd "$(LIB)" && $(MAKE)
|
||||
# Static Release
|
||||
@echo Build C99 Example (Release Static)...
|
||||
@tcc -m64 -o main.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" -lwebui-2-static-x64 -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
# Dynamic Release
|
||||
@echo Build C99 Example (Release Dynamic)...
|
||||
@tcc -m64 -o main-dyn.exe "$(SOURCE)/main.c" -I "$(INCLUDE)" -L "$(LIB)" "$(LIB)/webui-2-x64.def" -lws2_32 -Wall -Wl,-subsystem=windows -luser32
|
||||
# Clean
|
||||
@- del *.o >nul 2>&1
|
||||
@- del *.def >nul 2>&1
|
||||
@echo Done.
|
||||
|
||||
clean:
|
||||
- del *.o >nul 2>&1
|
||||
- del *.def >nul 2>&1
|
||||
- del *.exe >nul 2>&1
|
Binary file not shown.
Before Width: | Height: | Size: 108 KiB |
@ -1,7 +1,7 @@
|
||||
|
||||
/*
|
||||
WebUI Library 2.x
|
||||
|
||||
C99 Example
|
||||
|
||||
http://webui.me
|
||||
https://github.com/alifcommunity/webui
|
||||
|
||||
@ -16,18 +16,18 @@ webui_window_t* my_window;
|
||||
|
||||
// UI HTML
|
||||
const char* my_html = "<!DOCTYPE html>"
|
||||
"<html><head><title>WebUI 2.0 Example</title>"
|
||||
"<html><head><title>WebUI 2 - C99 Example</title>"
|
||||
"<style>body{color: white; background: #0F2027;"
|
||||
"background: -webkit-linear-gradient(to right, #2C5364, #203A43, #0F2027);"
|
||||
"background: linear-gradient(to right, #2C5364, #203A43, #0F2027);"
|
||||
"text-align:center; font-size: 18px; font-family: sans-serif;}</style></head><body>"
|
||||
"<h1>WebUI 2.0 Example</h1><br>"
|
||||
"<h1>WebUI 2 - C99 Example</h1><br>"
|
||||
"<input type=\"password\" id=\"MyInput\"><br><br>"
|
||||
"<button id=\"MyButton1\">Check Password</button> - <button id=\"MyButton2\">Exit</button>"
|
||||
"</body></html>";
|
||||
|
||||
// Check the password function
|
||||
void check_the_password(const webui_event_t e) {
|
||||
void check_the_password(webui_event_t* e) {
|
||||
|
||||
// This function get called every time the user click on "MyButton1"
|
||||
|
||||
@ -64,10 +64,11 @@ void check_the_password(const webui_event_t e) {
|
||||
webui_run_js(my_window, &js);
|
||||
}
|
||||
|
||||
// Free data resources
|
||||
webui_free_js(&js);
|
||||
}
|
||||
|
||||
void close_the_application(const webui_event_t e){
|
||||
void close_the_application(webui_event_t* e){
|
||||
|
||||
// Close all opened windows
|
||||
webui_exit();
|
@ -1,99 +0,0 @@
|
||||
// WebUI Library 2.0.0
|
||||
//
|
||||
// http://webui.me
|
||||
// https://github.com/alifcommunity/webui
|
||||
//
|
||||
// Licensed under GNU General Public License v3.0.
|
||||
// Copyright (C)2022 Hassan DRAGA <https://github.com/hassandraga>.
|
||||
|
||||
package main
|
||||
|
||||
//--[WebUI]-------------------------------------
|
||||
import (
|
||||
"C"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
dll_webui, _ = syscall.LoadLibrary("webui-2-x64.dll")
|
||||
|
||||
//webui_window_t* webui_new_window();
|
||||
dll_webui_new_window, _ = syscall.GetProcAddress(dll_webui, "webui_new_window")
|
||||
|
||||
// bool webui_show(webui_window_t* win, const char* html, unsigned int browser);
|
||||
dll_webui_show, _ = syscall.GetProcAddress(dll_webui, "webui_show")
|
||||
|
||||
// void webui_loop();
|
||||
dll_webui_loop, _ = syscall.GetProcAddress(dll_webui, "webui_loop")
|
||||
)
|
||||
|
||||
func webui_new_window() (result uintptr) {
|
||||
var arg uintptr = 0
|
||||
ret, _, _ := syscall.Syscall(uintptr(dll_webui_new_window), arg, 0, 0, 0)
|
||||
result = ret
|
||||
return
|
||||
}
|
||||
func webui_show(win uintptr, html string, browser uint) (result bool) {
|
||||
chtml := C.CString(html)
|
||||
var arg uintptr = 3
|
||||
ret, _, _ := syscall.Syscall(uintptr(dll_webui_show), arg, win, uintptr(unsafe.Pointer((chtml))), uintptr(browser))
|
||||
if ret == 0x00 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
func webui_loop() {
|
||||
var arg uintptr = 0
|
||||
syscall.Syscall(uintptr(dll_webui_loop), arg, 0, 0, 0)
|
||||
}
|
||||
func ini() {
|
||||
|
||||
defer syscall.FreeLibrary(dll_webui)
|
||||
}
|
||||
func webui_test() (res int) {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
|
||||
// Application Example
|
||||
|
||||
const my_html string = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebUI 2.0 Example</title>
|
||||
<style>
|
||||
body {
|
||||
color: white;
|
||||
background: #0F2027;
|
||||
background: -webkit-linear-gradient(to right, #2C5364, #203A43, #0F2027);
|
||||
background: linear-gradient(to right, #2C5364, #203A43, #0F2027);
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebUI 2.0 Example</h1>
|
||||
<br>
|
||||
<input type="password" id="MyInput">
|
||||
<br>
|
||||
<br>
|
||||
<button id="MyButton1">Check Password</button> - <button id="MyButton2">Exit</button>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
func main() {
|
||||
|
||||
var my_window = webui_new_window()
|
||||
|
||||
webui_show(my_window, my_html, 0)
|
||||
|
||||
webui_loop()
|
||||
|
||||
fmt.Print("Bye.")
|
||||
}
|
3
examples/Go/go.mod
Normal file
3
examples/Go/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/alifcommunity/webui
|
||||
|
||||
go 1.19
|
92
examples/Go/main.go
Normal file
92
examples/Go/main.go
Normal file
@ -0,0 +1,92 @@
|
||||
// WebUI Go Example
|
||||
// https://github.com/alifcommunity/webui
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/alifcommunity/webui/webui"
|
||||
)
|
||||
|
||||
const my_html string = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebUI 2 - Go Example</title>
|
||||
<style>
|
||||
body {
|
||||
color: white;
|
||||
background: #0F2027;
|
||||
background: -webkit-linear-gradient(to right, #2C5364, #203A43, #0F2027);
|
||||
background: linear-gradient(to right, #2C5364, #203A43, #0F2027);
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebUI 2 - Go Example</h1>
|
||||
<br>
|
||||
<input type="password" id="MyInput">
|
||||
<br>
|
||||
<br>
|
||||
<button id="CheckPassword">Check Password</button> - <button id="Exit">Exit</button>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
func Exit(e webui.Event) {
|
||||
|
||||
webui.Exit()
|
||||
}
|
||||
|
||||
func Check(e webui.Event) {
|
||||
|
||||
// Script to get the text value
|
||||
js := webui.JavaScript{
|
||||
Timeout: 10,
|
||||
Script: "return document.getElementById(\"MyInput\").value;",
|
||||
}
|
||||
|
||||
// Run the script
|
||||
webui.RunJavaScript(e.Window, &js)
|
||||
|
||||
// Check if any error
|
||||
if !js.Error {
|
||||
|
||||
fmt.Printf("Password: %s\n", js.Data)
|
||||
|
||||
// Check the password
|
||||
if js.Data == "123456" {
|
||||
|
||||
js.Script = "alert('Good. Password is correct.')"
|
||||
webui.RunJavaScript(e.Window, &js)
|
||||
} else {
|
||||
|
||||
js.Script = "alert('Sorry. Wrong password.')"
|
||||
webui.RunJavaScript(e.Window, &js)
|
||||
}
|
||||
} else {
|
||||
|
||||
// There is an error in our script
|
||||
fmt.Printf("JavaScript Error: %s\n", js.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// New window
|
||||
var my_window = webui.NewWindow()
|
||||
|
||||
// Bind
|
||||
webui.Bind(my_window, "CheckPassword", Check)
|
||||
webui.Bind(my_window, "Exit", Exit)
|
||||
|
||||
// Show window
|
||||
webui.Show(my_window, my_html, 0)
|
||||
|
||||
// Loop
|
||||
webui.Loop()
|
||||
|
||||
fmt.Println("Bye.")
|
||||
}
|
111
examples/Go/webui/webui.go
Normal file
111
examples/Go/webui/webui.go
Normal file
@ -0,0 +1,111 @@
|
||||
package webui
|
||||
|
||||
// WebUI Library 2.0.1
|
||||
//
|
||||
// http://webui.me
|
||||
// https://github.com/alifcommunity/webui
|
||||
//
|
||||
// Licensed under GNU General Public License v3.0.
|
||||
// Copyright (C)2022 Hassan DRAGA <https://github.com/hassandraga>.
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -I ./ -I ../../../include
|
||||
#cgo windows LDFLAGS: -L ./ -L ../../../build/Windows/GCC/ -lwebui-2-static-x64 -lws2_32
|
||||
#cgo darwin LDFLAGS: -L ./ -L ../../../build/macOS/Clang/ -lwebui-2-static-x64
|
||||
#cgo linux LDFLAGS: -L ./ -L ../../../build/Linux/GCC/ -lwebui-2-static-x64
|
||||
#include <webui.h>
|
||||
extern void webui_go_handler(webui_window_t* _window, unsigned int _element_id, unsigned int _window_id, char* _element_name);
|
||||
static void webui_bind_go_handler(webui_event_t* e) {
|
||||
webui_go_handler(e->window, e->element_id, e->window_id, e->element_name);
|
||||
}
|
||||
static unsigned int webui_bind_go(webui_window_t* win, const char* element) {
|
||||
return webui_bind(win, element, webui_bind_go_handler);
|
||||
}
|
||||
*/
|
||||
import (
|
||||
"C"
|
||||
)
|
||||
|
||||
// Event Struct
|
||||
type Event struct {
|
||||
Window *C.webui_window_t
|
||||
ElementID uint
|
||||
WindowID uint
|
||||
ElementName string
|
||||
}
|
||||
|
||||
// JavaScript Struct
|
||||
type JavaScript struct {
|
||||
Timeout uint
|
||||
Script string
|
||||
Error bool
|
||||
Length uint
|
||||
Data string
|
||||
}
|
||||
|
||||
// User Go Callback Functions list
|
||||
var fun_list [64][256]func(Event)
|
||||
|
||||
//export webui_go_handler
|
||||
func webui_go_handler(_window *C.webui_window_t, _element_id C.uint, _window_id C.uint, _element_name *C.char) {
|
||||
|
||||
var window *C.webui_window_t = (*C.webui_window_t)(_window)
|
||||
var element_id uint = uint(_element_id)
|
||||
var window_id uint = uint(_window_id)
|
||||
var element_name string = C.GoString(_element_name)
|
||||
|
||||
e := Event{
|
||||
Window: window,
|
||||
ElementID: element_id,
|
||||
WindowID: window_id,
|
||||
ElementName: element_name,
|
||||
}
|
||||
|
||||
fun_list[window_id][element_id](e)
|
||||
}
|
||||
|
||||
func RunJavaScript(window *C.webui_window_t, js *JavaScript) {
|
||||
|
||||
c_js := C.webui_javascript_py_t{
|
||||
script: C.CString(js.Script),
|
||||
timeout: 30, // uint(js.Timeout),
|
||||
error: C.bool(false),
|
||||
// length: uint(0),
|
||||
// data: C.CString(nil),
|
||||
}
|
||||
|
||||
C.webui_run_js_py(window, &c_js)
|
||||
|
||||
js.Error = bool(c_js.error)
|
||||
js.Data = C.GoString(c_js.data)
|
||||
}
|
||||
|
||||
func NewWindow() *C.webui_window_t {
|
||||
|
||||
return C.webui_new_window()
|
||||
}
|
||||
|
||||
func Exit() {
|
||||
|
||||
C.webui_exit()
|
||||
}
|
||||
|
||||
func Show(window *C.webui_window_t, html string, browser uint) {
|
||||
|
||||
c_html := C.CString(html)
|
||||
C.webui_show(window, c_html, C.uint(browser))
|
||||
}
|
||||
|
||||
func Loop() {
|
||||
|
||||
C.webui_loop()
|
||||
}
|
||||
|
||||
func Bind(window *C.webui_window_t, element string, callback func(Event)) {
|
||||
|
||||
c_element := C.CString(element)
|
||||
var window_id uint = uint(C._webui_window_get_number(window))
|
||||
var cb_index uint = uint(C.webui_bind_go(window, c_element))
|
||||
|
||||
fun_list[window_id][cb_index] = callback
|
||||
}
|
@ -3,11 +3,6 @@
|
||||
|
||||
To use WebUI in your Python script, you will need to [build](https://github.com/alifcommunity/webui/tree/main/build) the WebUI library first using your favorite C compiler, then copy into this folder the dynamic WebUI library, `webui-2-x64.dll` on Windows, or `webui-2-x64.so` on Linux.
|
||||
|
||||
**Requirement:**
|
||||
|
||||
- webui.py
|
||||
- WebUI Dynamic Library
|
||||
|
||||
```sh
|
||||
python example.py
|
||||
python main.py
|
||||
```
|
||||
|
@ -1,4 +1,6 @@
|
||||
# WebUI Library 2.0.0
|
||||
|
||||
# WebUI Library 2.x
|
||||
# Python Example
|
||||
#
|
||||
# http://webui.me
|
||||
# https://github.com/alifcommunity/webui
|
||||
@ -6,19 +8,21 @@
|
||||
# Licensed under GNU General Public License v3.0.
|
||||
# Copyright (C)2022 Hassan DRAGA <https://github.com/hassandraga>.
|
||||
|
||||
# [!] IMPORTANT
|
||||
# Please build a dynamic version of WebUI library using
|
||||
# your favorite C compiler, then copy file 'webui-2-x64'
|
||||
# into this folder.
|
||||
import webui
|
||||
|
||||
import webui # Importing 'webui.py' file
|
||||
# Set the WebUI dynamic library location (Optional)
|
||||
# Default is the same folder, otherwise use this option
|
||||
webui.set_library_path("../../build/Windows/MSVC")
|
||||
|
||||
# Create a global window object
|
||||
MyWindow = webui.window()
|
||||
|
||||
# HTML
|
||||
my_html = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebUI 2.0 Example</title>
|
||||
<title>WebUI 2 - Python Example</title>
|
||||
<style>
|
||||
body{
|
||||
color: white;
|
||||
@ -32,10 +36,11 @@ my_html = """
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebUI 2.0 Example</h1>
|
||||
<h1>WebUI 2 - Python Example</h1>
|
||||
<br>
|
||||
<input type="password" id="MyInput">
|
||||
<br><br>
|
||||
<br>
|
||||
<br>
|
||||
<button id="MyButton1">Check Password</button> - <button id="MyButton2">Exit</button>
|
||||
</body>
|
||||
</html>
|
||||
@ -68,17 +73,19 @@ def check_the_password(e : webui.event):
|
||||
def close_the_application(e : webui.event):
|
||||
webui.exit()
|
||||
|
||||
# Create a window object
|
||||
MyWindow = webui.window()
|
||||
def main():
|
||||
|
||||
# Bind am HTML element ID with a python function
|
||||
MyWindow.bind('MyButton1', check_the_password)
|
||||
MyWindow.bind('MyButton2', close_the_application)
|
||||
# Bind am HTML element ID with a python function
|
||||
MyWindow.bind('MyButton1', check_the_password)
|
||||
MyWindow.bind('MyButton2', close_the_application)
|
||||
|
||||
# Show the window
|
||||
MyWindow.show(my_html)
|
||||
# Show the window
|
||||
MyWindow.show(my_html)
|
||||
|
||||
# Wait until all windows are closed
|
||||
webui.loop()
|
||||
# Wait until all windows are closed
|
||||
webui.loop()
|
||||
|
||||
print('Bye.')
|
||||
print('Bye.')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,4 +1,4 @@
|
||||
# WebUI Library 2.0.0
|
||||
# WebUI Library 2.0.1
|
||||
#
|
||||
# http://webui.me
|
||||
# https://github.com/alifcommunity/webui
|
||||
@ -6,18 +6,15 @@
|
||||
# Licensed under GNU General Public License v3.0.
|
||||
# Copyright (C)2022 Hassan DRAGA <https://github.com/hassandraga>.
|
||||
|
||||
# [!] IMPORTANT
|
||||
# Please build a dynamic version of WebUI library using
|
||||
# your favorite C compiler, then copy file 'webui-2-x64'
|
||||
# into this folder.
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import ctypes
|
||||
from ctypes import *
|
||||
import shutil
|
||||
|
||||
lib = None
|
||||
WebUI = None
|
||||
WebUI_Path = os.getcwd()
|
||||
|
||||
# Event
|
||||
class event:
|
||||
@ -50,17 +47,17 @@ class window:
|
||||
cb_fun_list = [64]
|
||||
|
||||
def __init__(self):
|
||||
global lib
|
||||
global WebUI
|
||||
try:
|
||||
# Load WebUI Shared Library
|
||||
load_library()
|
||||
# Check library if correctly loaded
|
||||
if lib is None:
|
||||
if WebUI is None:
|
||||
print('Please download the latest library from https://webui.me')
|
||||
sys.exit(1)
|
||||
# Create new WebUI window
|
||||
webui_wrapper = None
|
||||
webui_wrapper = lib.webui_new_window
|
||||
webui_wrapper = WebUI.webui_new_window
|
||||
webui_wrapper.restype = c_void_p
|
||||
self.window = c_void_p(webui_wrapper())
|
||||
# Initializing events() to be called from WebUI Library
|
||||
@ -71,9 +68,9 @@ class window:
|
||||
sys.exit(1)
|
||||
|
||||
def __del__(self):
|
||||
global lib
|
||||
if self.window is not None and lib is not None:
|
||||
lib.webui_close(self.window)
|
||||
global WebUI
|
||||
if self.window is not None and WebUI is not None:
|
||||
WebUI.webui_close(self.window)
|
||||
|
||||
def events(self, element_id, window_id, element_name):
|
||||
if self.cb_fun_list[int(element_id)] is None:
|
||||
@ -86,39 +83,39 @@ class window:
|
||||
self.cb_fun_list[element_id](e)
|
||||
|
||||
def bind(self, element, func):
|
||||
global lib
|
||||
global WebUI
|
||||
if self.window is None:
|
||||
err_window_is_none('bind')
|
||||
return
|
||||
if lib is None:
|
||||
if WebUI is None:
|
||||
err_library_not_found('bind')
|
||||
return
|
||||
cb_index = int(lib.webui_bind_py(self.window, element.encode('utf-8'), self.c_events))
|
||||
cb_index = int(WebUI.webui_bind_py(self.window, element.encode('utf-8'), self.c_events))
|
||||
self.cb_fun_list.insert(cb_index, func)
|
||||
|
||||
def show(self, html):
|
||||
global lib
|
||||
global WebUI
|
||||
if self.window is None:
|
||||
err_window_is_none('show')
|
||||
return
|
||||
if lib is None:
|
||||
if WebUI is None:
|
||||
err_library_not_found('show')
|
||||
return
|
||||
lib.webui_show(self.window, html.encode('utf-8'))
|
||||
WebUI.webui_show(self.window, html.encode('utf-8'))
|
||||
|
||||
def close(self):
|
||||
global lib
|
||||
if lib is None:
|
||||
global WebUI
|
||||
if WebUI is None:
|
||||
err_library_not_found('close')
|
||||
return
|
||||
lib.webui_close(self.window)
|
||||
WebUI.webui_close(self.window)
|
||||
|
||||
def run_js(self, script, timeout = 0) -> javascript:
|
||||
global lib
|
||||
global WebUI
|
||||
if self.window is None:
|
||||
err_window_is_none('show')
|
||||
return
|
||||
if lib is None:
|
||||
if WebUI is None:
|
||||
err_library_not_found('show')
|
||||
return
|
||||
# Create Struct
|
||||
@ -137,56 +134,96 @@ class window:
|
||||
res.length = 7
|
||||
res.data = "UNKNOWN"
|
||||
# Run JavaScript
|
||||
lib.webui_run_js_py(self.window, ctypes.byref(js))
|
||||
WebUI.webui_run_js_py(self.window, ctypes.byref(js))
|
||||
res.length = int(js.length)
|
||||
res.data = js.data.decode('utf-8')
|
||||
res.error = js.error
|
||||
return res
|
||||
|
||||
# Exit app
|
||||
def load_library():
|
||||
global lib
|
||||
def get_library_path() -> str:
|
||||
global WebUI_Path
|
||||
if platform.system() == 'Darwin':
|
||||
lib = ctypes.CDLL('webui-2-x64.dylib')
|
||||
if lib is None:
|
||||
print("WebUI Error: Failed to load 'webui-2-x64.dylib' library.")
|
||||
file = '/webui-2-x64.dylib'
|
||||
path = os.getcwd() + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
path = WebUI_Path + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return path
|
||||
elif platform.system() == 'Windows':
|
||||
file = '\webui-2-x64.dll'
|
||||
path = os.getcwd() + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
path = WebUI_Path + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return path
|
||||
elif platform.system() == 'Linux':
|
||||
file = '/webui-2-x64.so'
|
||||
path = os.getcwd() + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
path = WebUI_Path + file
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return path
|
||||
else:
|
||||
return ""
|
||||
|
||||
# Load WebUI Dynamic Library
|
||||
def load_library():
|
||||
global WebUI
|
||||
global WebUI_Path
|
||||
if platform.system() == 'Darwin':
|
||||
WebUI = ctypes.CDLL(get_library_path())
|
||||
if WebUI is None:
|
||||
print("WebUI Error: Failed to load WebUI dynamic library.")
|
||||
elif platform.system() == 'Windows':
|
||||
if sys.version_info.major == 3 and sys.version_info.minor <= 8:
|
||||
os.chdir(os.getcwd())
|
||||
os.add_dll_directory(os.getcwd())
|
||||
lib = ctypes.CDLL('webui-2-x64.dll')
|
||||
WebUI = ctypes.CDLL(get_library_path())
|
||||
else:
|
||||
os.chdir(os.getcwd())
|
||||
os.add_dll_directory(os.getcwd())
|
||||
lib = cdll.LoadLibrary('webui-2-x64.dll')
|
||||
if lib is None:
|
||||
print("WebUI Error: Failed to load 'webui-2-x64.dll' library.")
|
||||
WebUI = cdll.LoadLibrary(get_library_path())
|
||||
if WebUI is None:
|
||||
print("WebUI Error: Failed to load WebUI dynamic library.")
|
||||
elif platform.system() == 'Linux':
|
||||
os.chdir(os.getcwd())
|
||||
lib = ctypes.CDLL(os.getcwd() + '/webui-2-x64.so')
|
||||
if lib is None:
|
||||
print("WebUI Error: Failed to load 'webui-2-x64.so' library.")
|
||||
WebUI = ctypes.CDLL(get_library_path())
|
||||
if WebUI is None:
|
||||
print("WebUI Error: Failed to load WebUI dynamic library.")
|
||||
else:
|
||||
print("WebUI Error: Unsupported OS")
|
||||
|
||||
# Exit app
|
||||
def exit():
|
||||
global lib
|
||||
if lib is None:
|
||||
global WebUI
|
||||
if WebUI is None:
|
||||
err_library_not_found('exit')
|
||||
return
|
||||
lib.webui_exit()
|
||||
WebUI.webui_exit()
|
||||
|
||||
# Wait until all windows get closed
|
||||
def loop():
|
||||
global lib
|
||||
if lib is None:
|
||||
global WebUI
|
||||
if WebUI is None:
|
||||
err_library_not_found('loop')
|
||||
return
|
||||
lib.webui_loop()
|
||||
WebUI.webui_loop()
|
||||
try:
|
||||
shutil.rmtree(os.getcwd() + '/__pycache__/')
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def err_library_not_found(f):
|
||||
print('WebUI ' + f + '(): Library Not Found.')
|
||||
|
||||
def err_window_is_none(f):
|
||||
print('WebUI ' + f + '(): Window is None.')
|
||||
|
||||
def set_library_path(Path):
|
||||
global WebUI_Path
|
||||
WebUI_Path = Path
|
||||
|
@ -15,7 +15,7 @@
|
||||
// Alternatively, you can license this software under a commercial
|
||||
// license, as set out in https://www.mongoose.ws/licensing/
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0 or commercial
|
||||
// SPDX-License-Identifier: GPL-2.0-only or commercial
|
||||
|
||||
#ifndef MONGOOSE_H
|
||||
#define MONGOOSE_H
|
||||
@ -70,6 +70,9 @@ extern "C" {
|
||||
#endif
|
||||
#endif // !defined(MG_ARCH)
|
||||
|
||||
// http://esr.ibiblio.org/?p=5095
|
||||
#define MG_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -98,10 +101,6 @@ extern "C" {
|
||||
#include <nx_port.h>
|
||||
#include <tx_port.h>
|
||||
|
||||
#ifdef __REDLIB__
|
||||
#define va_copy(d, s) __builtin_va_copy(d, s)
|
||||
#endif
|
||||
|
||||
#define PATH_MAX FX_MAXIMUM_PATH
|
||||
#define MG_DIRSEP '\\'
|
||||
|
||||
@ -294,6 +293,12 @@ struct timeval {
|
||||
#define EINTR pdFREERTOS_ERRNO_EINTR
|
||||
#endif
|
||||
|
||||
// FreeRTOS-TCP uses non-standard semantics for listen() backlog size. It is
|
||||
// not a backlog size for pending SYN connections, but a max socket number
|
||||
#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
|
||||
#define MG_SOCK_LISTEN_BACKLOG_SIZE 128
|
||||
#endif
|
||||
|
||||
#endif // MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||
|
||||
|
||||
@ -563,13 +568,6 @@ typedef int socklen_t;
|
||||
#define sleep(x) Sleep(x)
|
||||
#define mkdir(a, b) _mkdir(a)
|
||||
|
||||
#ifndef va_copy
|
||||
#ifdef __va_copy
|
||||
#define va_copy __va_copy
|
||||
#else
|
||||
#define va_copy(x, y) (x) = (y)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
||||
#endif
|
||||
@ -583,12 +581,12 @@ typedef int socklen_t;
|
||||
|
||||
#if MG_ARCH == MG_ARCH_ZEPHYR
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/socket.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@ -599,6 +597,9 @@ typedef int socklen_t;
|
||||
#include <time.h>
|
||||
|
||||
#define MG_PUTCHAR(x) printk("%c", x)
|
||||
#ifndef strdup
|
||||
#define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
|
||||
#endif
|
||||
#define strerror(x) zsock_gai_strerror(x)
|
||||
#define FD_CLOEXEC 0
|
||||
#define F_SETFD 0
|
||||
@ -655,7 +656,7 @@ int sscanf(const char *, const char *, ...);
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_MD5
|
||||
#define MG_ENABLE_MD5 0
|
||||
#define MG_ENABLE_MD5 1
|
||||
#endif
|
||||
|
||||
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
|
||||
@ -993,6 +994,7 @@ enum {
|
||||
MG_EV_RESOLVE, // Host name is resolved NULL
|
||||
MG_EV_CONNECT, // Connection established NULL
|
||||
MG_EV_ACCEPT, // Connection accepted NULL
|
||||
MG_EV_TLS_HS, // TLS handshake succeeded NULL
|
||||
MG_EV_READ, // Data received from socket long *bytes_read
|
||||
MG_EV_WRITE, // Data written to socket long *bytes_written
|
||||
MG_EV_CLOSE, // Connection closed NULL
|
||||
@ -1005,7 +1007,7 @@ enum {
|
||||
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
|
||||
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
|
||||
MG_EV_SNTP_TIME, // SNTP time received uint64_t *epoch_millis
|
||||
MG_EV_USER, // Starting ID for user events
|
||||
MG_EV_USER // Starting ID for user events
|
||||
};
|
||||
|
||||
|
||||
@ -1094,7 +1096,7 @@ struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
||||
void mg_connect_resolved(struct mg_connection *);
|
||||
bool mg_send(struct mg_connection *, const void *, size_t);
|
||||
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
|
||||
char *mg_straddr(struct mg_addr *, char *, size_t);
|
||||
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||||
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
WebUI Library 2.0.0
|
||||
WebUI Library 2.0.1
|
||||
|
||||
http://webui.me
|
||||
https://github.com/alifcommunity/webui
|
||||
@ -26,7 +26,7 @@
|
||||
#define WEBUI_MAX_ARRAY (32) // Max thread, servers, windows..
|
||||
#define WEBUI_MIN_PORT (8080) // Minimum socket port
|
||||
#define WEBUI_MAX_PORT (8335) // Should be less than 65535
|
||||
#define WEBUI_MAX_BUF (512000) // 512 Kb max dynamic memory
|
||||
#define WEBUI_MAX_BUF (512000) // 512 Kb max dynamic memory allocation
|
||||
#define WEBUI_DEFAULT_PATH "." // Default root path
|
||||
|
||||
// -- C STD -----------------------------------
|
||||
@ -73,11 +73,14 @@
|
||||
// -- macOS -----------------------------------
|
||||
// ...
|
||||
|
||||
struct webui_window_t;
|
||||
|
||||
typedef struct webui_event_t {
|
||||
|
||||
unsigned int window_id;
|
||||
unsigned int element_id;
|
||||
char* element_name;
|
||||
struct webui_window_t* window;
|
||||
|
||||
} webui_event_t;
|
||||
|
||||
@ -92,8 +95,9 @@ typedef struct webui_window_core_t {
|
||||
unsigned int server_port;
|
||||
bool is_bind_all;
|
||||
char* url;
|
||||
void (*cb_all[1]) (webui_event_t e);
|
||||
void (*cb_all[1]) (webui_event_t* e);
|
||||
const char* html;
|
||||
const char* html_cpy;
|
||||
const char* icon;
|
||||
const char* icon_type;
|
||||
unsigned int CurrentBrowser;
|
||||
@ -189,7 +193,7 @@ typedef struct webui_t {
|
||||
bool use_timeout;
|
||||
bool timeout_extra;
|
||||
bool exit_now;
|
||||
char* run_responses[WEBUI_MAX_ARRAY];
|
||||
const char* run_responses[WEBUI_MAX_ARRAY];
|
||||
bool run_done[WEBUI_MAX_ARRAY];
|
||||
bool run_error[WEBUI_MAX_ARRAY];
|
||||
unsigned int run_last_id;
|
||||
@ -198,7 +202,7 @@ typedef struct webui_t {
|
||||
webui_browser_t browser;
|
||||
webui_runtime_t runtime;
|
||||
bool initialized;
|
||||
void (*cb[WEBUI_MAX_ARRAY]) (webui_event_t e);
|
||||
void (*cb[WEBUI_MAX_ARRAY]) (webui_event_t* e);
|
||||
void (*cb_py[WEBUI_MAX_ARRAY])(unsigned int, unsigned int, char*);
|
||||
char* executable_path;
|
||||
|
||||
@ -228,6 +232,7 @@ EXPORT bool webui_any_window_is_open();
|
||||
EXPORT void webui_set_timeout(unsigned int second);
|
||||
EXPORT webui_window_t* webui_new_window();
|
||||
EXPORT bool webui_show(webui_window_t* win, const char* html, unsigned int browser);
|
||||
EXPORT bool webui_copy_show(webui_window_t* win, const char* html, unsigned int browser);
|
||||
EXPORT void webui_set_icon(webui_window_t* win, const char* icon_s, const char* type_s);
|
||||
EXPORT void webui_allow_multi_access(webui_window_t* win, bool status);
|
||||
EXPORT bool webui_set_root_folder(webui_window_t* win, const char* path);
|
||||
@ -235,8 +240,8 @@ EXPORT const char* webui_new_server(webui_window_t* win, const char* path, const
|
||||
EXPORT void webui_close(webui_window_t* win);
|
||||
EXPORT bool webui_is_show(webui_window_t* win);
|
||||
EXPORT void webui_run_js(webui_window_t* win, webui_javascript_t* javascript);
|
||||
EXPORT unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (webui_event_t e));
|
||||
EXPORT void webui_bind_all(webui_window_t* win, void (*func) (webui_event_t e));
|
||||
EXPORT unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (webui_event_t* e));
|
||||
EXPORT void webui_bind_all(webui_window_t* win, void (*func) (webui_event_t* e));
|
||||
EXPORT bool webui_open(webui_window_t* win, const char* url, unsigned int browser);
|
||||
EXPORT void webui_free_js(webui_javascript_t* javascript);
|
||||
EXPORT void webui_runtime(webui_window_t* win, unsigned int runtime);
|
||||
@ -259,14 +264,14 @@ EXPORT char* _webui_get_current_path();
|
||||
EXPORT void _webui_window_receive(webui_window_t* win, const char* packet, size_t len);
|
||||
EXPORT void _webui_window_send(webui_window_t* win, char* packet, size_t packets_size);
|
||||
EXPORT void _webui_window_event(webui_window_t* win, char* element_id, char* element);
|
||||
EXPORT unsigned int _webui_window_get_window_number(webui_window_t* win);
|
||||
EXPORT unsigned int _webui_window_get_number(webui_window_t* win);
|
||||
EXPORT void _webui_window_open(webui_window_t* win, char* link, unsigned int browser);
|
||||
EXPORT int _webui_cmd_sync(char* cmd);
|
||||
EXPORT int _webui_cmd_async(char* cmd);
|
||||
EXPORT int _webui_run_browser(webui_window_t* win, char* cmd);
|
||||
EXPORT void _webui_browser_clean();
|
||||
EXPORT bool _webui_browser_exist(webui_window_t* win, unsigned int browser);
|
||||
EXPORT char* _webui_browser_get_temp_path(unsigned int browser);
|
||||
EXPORT const char* _webui_browser_get_temp_path(unsigned int browser);
|
||||
EXPORT bool _webui_folder_exist(char* folder);
|
||||
EXPORT bool _webui_browser_create_profile_folder(webui_window_t* win, unsigned int browser);
|
||||
EXPORT bool _webui_browser_start_edge(webui_window_t* win, const char* address);
|
||||
|
283
src/mongoose.c
283
src/mongoose.c
@ -15,7 +15,7 @@
|
||||
// Alternatively, you can license this software under a commercial
|
||||
// license, as set out in https://www.mongoose.ws/licensing/
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0 or commercial
|
||||
// SPDX-License-Identifier: GPL-2.0-only or commercial
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
@ -90,9 +90,9 @@ int mg_base64_encode(const unsigned char *p, int n, char *to) {
|
||||
}
|
||||
|
||||
int mg_base64_decode(const char *src, int n, char *dst) {
|
||||
const char *end = src + n;
|
||||
const char *end = src == NULL ? NULL : src + n; // Cannot add to NULL
|
||||
int len = 0;
|
||||
while (src + 3 < end) {
|
||||
while (src != NULL && src + 3 < end) {
|
||||
int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
|
||||
d = mg_b64rev(src[3]);
|
||||
if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
|
||||
@ -559,7 +559,9 @@ static size_t mg_dtoa(char *dst, size_t dstlen, double d, int width) {
|
||||
}
|
||||
while (n > 0 && buf[s + n - 1] == '0') n--; // Trim trailing zeros
|
||||
if (n > 0 && buf[s + n - 1] == '.') n--; // Trim trailing dot
|
||||
buf[s + n] = '\0';
|
||||
n += s;
|
||||
if (n >= (int) sizeof(buf)) n = (int) sizeof(buf) - 1;
|
||||
buf[n] = '\0';
|
||||
return mg_snprintf(dst, dstlen, "%s", buf);
|
||||
}
|
||||
|
||||
@ -1540,7 +1542,7 @@ static void mg_http_parse_headers(const char *s, const char *end,
|
||||
|
||||
int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
|
||||
const char *end = s + req_len, *qs;
|
||||
const char *end = s == NULL ? NULL : s + req_len, *qs; // Cannot add to NULL
|
||||
struct mg_str *cl;
|
||||
|
||||
memset(hm, 0, sizeof(*hm));
|
||||
@ -1605,13 +1607,10 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
}
|
||||
|
||||
static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
||||
va_list ap) {
|
||||
va_list *ap) {
|
||||
size_t len = c->send.len;
|
||||
va_list tmp;
|
||||
mg_send(c, " \r\n", 10);
|
||||
va_copy(tmp, ap);
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp);
|
||||
va_end(tmp);
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
|
||||
if (c->send.len >= len + 10) {
|
||||
mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
|
||||
c->send.buf[len + 8] = '\r';
|
||||
@ -1623,7 +1622,7 @@ static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
||||
void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mg_http_vprintf_chunk(c, fmt, ap);
|
||||
mg_http_vprintf_chunk(c, fmt, &ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@ -1903,12 +1902,12 @@ static void printdirentry(const char *name, void *userdata) {
|
||||
}
|
||||
#if defined(MG_HTTP_DIRLIST_TIME)
|
||||
char time_str[30];
|
||||
struct tm * time_info = localtime(&t);
|
||||
struct tm *time_info = localtime(&t);
|
||||
strftime(time_str, sizeof time_str, "%Y/%m/%d %H:%M:%S", time_info);
|
||||
mg_snprintf(mod, sizeof(mod), "%s", time_str);
|
||||
#elif defined(MG_HTTP_DIRLIST_TIME_UTC)
|
||||
char time_str[30];
|
||||
struct tm * time_info = gmtime(&t);
|
||||
struct tm *time_info = gmtime(&t);
|
||||
strftime(time_str, sizeof time_str, "%Y/%m/%d %H:%M:%S", time_info);
|
||||
mg_snprintf(mod, sizeof(mod), "%s", time_str);
|
||||
#else
|
||||
@ -2238,7 +2237,7 @@ static void deliver_chunked_chunks(struct mg_connection *c, size_t hlen,
|
||||
ofs += pl + dl + 2, del += pl + 2; // 2 is for \r\n suffix
|
||||
processed += dl;
|
||||
if (c->recv.len != saved) processed -= dl, buf -= dl;
|
||||
mg_hexdump(c->recv.buf, hlen + processed);
|
||||
//mg_hexdump(c->recv.buf, hlen + processed);
|
||||
last = (dl == 0);
|
||||
}
|
||||
mg_iobuf_del(&c->recv, hlen + processed, del);
|
||||
@ -2358,7 +2357,7 @@ int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
|
||||
void *p = calloc(1, new_size);
|
||||
if (p != NULL) {
|
||||
size_t len = new_size < io->len ? new_size : io->len;
|
||||
if (len > 0) memmove(p, io->buf, len);
|
||||
if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
|
||||
zeromem(io->buf, io->size);
|
||||
free(io->buf);
|
||||
io->buf = (unsigned char *) p;
|
||||
@ -2801,29 +2800,18 @@ void mg_hexdump(const void *buf, size_t len) {
|
||||
|
||||
|
||||
#if defined(MG_ENABLE_MD5) && MG_ENABLE_MD5
|
||||
#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
|
||||
#define BYTE_ORDER __BYTE_ORDER
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* LITTLE_ENDIAN */
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* BIG_ENDIAN */
|
||||
#endif /* BYTE_ORDER */
|
||||
|
||||
static void mg_byte_reverse(unsigned char *buf, unsigned longs) {
|
||||
/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
do {
|
||||
uint32_t t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
#else
|
||||
(void) buf;
|
||||
(void) longs;
|
||||
#endif
|
||||
if (MG_BIG_ENDIAN) {
|
||||
do {
|
||||
uint32_t t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
} else {
|
||||
(void) buf, (void) longs; // Little endian. Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
@ -3275,11 +3263,9 @@ struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
||||
|
||||
|
||||
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
|
||||
size_t old = c->send.len;
|
||||
va_list tmp;
|
||||
va_copy(tmp, ap);
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp);
|
||||
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
|
||||
return c->send.len - old;
|
||||
}
|
||||
|
||||
@ -3287,7 +3273,7 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
|
||||
size_t len = 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vprintf(c, fmt, ap);
|
||||
len = mg_vprintf(c, fmt, &ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
@ -3494,8 +3480,10 @@ struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
||||
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
||||
unsigned flags, void (*fn)(void *), void *arg) {
|
||||
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
|
||||
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
|
||||
t->id = mgr->timerid++;
|
||||
if (t != NULL) {
|
||||
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
|
||||
t->id = mgr->timerid++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -3547,8 +3535,10 @@ void mg_mgr_init(struct mg_mgr *mgr) {
|
||||
void mg_rpc_add(struct mg_rpc **head, struct mg_str method,
|
||||
void (*fn)(struct mg_rpc_req *), void *fn_data) {
|
||||
struct mg_rpc *rpc = (struct mg_rpc *) calloc(1, sizeof(*rpc));
|
||||
rpc->method = mg_strdup(method), rpc->fn = fn, rpc->fn_data = fn_data;
|
||||
rpc->next = *head, *head = rpc;
|
||||
if (rpc != NULL) {
|
||||
rpc->method = mg_strdup(method), rpc->fn = fn, rpc->fn_data = fn_data;
|
||||
rpc->next = *head, *head = rpc;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_rpc_del(struct mg_rpc **head, void (*fn)(struct mg_rpc_req *)) {
|
||||
@ -3646,21 +3636,6 @@ void mg_rpc_list(struct mg_rpc_req *r) {
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* clang with std=-c99 uses __LITTLE_ENDIAN, by default
|
||||
* while for ex, RTOS gcc - LITTLE_ENDIAN, by default
|
||||
* it depends on __USE_BSD, but let's have everything
|
||||
*/
|
||||
#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
|
||||
#define BYTE_ORDER __BYTE_ORDER
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* LITTLE_ENDIAN */
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* BIG_ENDIAN */
|
||||
#endif /* BYTE_ORDER */
|
||||
|
||||
union char64long16 {
|
||||
unsigned char c[64];
|
||||
uint32_t l[16];
|
||||
@ -3669,11 +3644,11 @@ union char64long16 {
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
static uint32_t blk0(union char64long16 *block, int i) {
|
||||
/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
block->l[i] =
|
||||
(rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
|
||||
#endif
|
||||
if (MG_BIG_ENDIAN) {
|
||||
} else {
|
||||
block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |
|
||||
(rol(block->l[i], 8) & 0x00FF00FF);
|
||||
}
|
||||
return block->l[i];
|
||||
}
|
||||
|
||||
@ -5101,6 +5076,7 @@ void mg_tls_handshake(struct mg_connection *c) {
|
||||
if (rc == 0) { // Success
|
||||
MG_DEBUG(("%lu success", c->id));
|
||||
c->is_tls_hs = 0;
|
||||
mg_call(c, MG_EV_TLS_HS, NULL);
|
||||
} else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
rc == MBEDTLS_ERR_SSL_WANT_WRITE) { // Still pending
|
||||
MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
|
||||
@ -5238,7 +5214,8 @@ size_t mg_tls_pending(struct mg_connection *c) {
|
||||
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||
long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
|
||||
if (n == MBEDTLS_ERR_SSL_WANT_READ) return MG_IO_WAIT;
|
||||
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
return MG_IO_WAIT;
|
||||
if (n <= 0) return MG_IO_ERR;
|
||||
return n;
|
||||
}
|
||||
@ -5246,7 +5223,8 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||
long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
|
||||
if (n == MBEDTLS_ERR_SSL_WANT_WRITE) return MG_IO_WAIT;
|
||||
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
return MG_IO_WAIT;
|
||||
if (n <= 0) return MG_IO_ERR;
|
||||
return n;
|
||||
}
|
||||
@ -5373,6 +5351,7 @@ void mg_tls_handshake(struct mg_connection *c) {
|
||||
if (rc == 1) {
|
||||
MG_DEBUG(("%lu success", c->id));
|
||||
c->is_tls_hs = 0;
|
||||
mg_call(c, MG_EV_TLS_HS, NULL);
|
||||
} else {
|
||||
int code = mg_tls_err(tls, rc);
|
||||
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
|
||||
@ -5606,6 +5585,8 @@ uint64_t mg_millis(void) {
|
||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
#elif MG_ARCH == MG_ARCH_AZURERTOS
|
||||
return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
|
||||
#elif MG_ARCH == MG_ARCH_ZEPHYR
|
||||
return (uint64_t) k_uptime_get();
|
||||
#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
|
||||
// Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
|
||||
// Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
|
||||
@ -5633,6 +5614,7 @@ uint64_t mg_millis(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/ws.c"
|
||||
#endif
|
||||
@ -5830,9 +5812,10 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
if (final) mg_call(c, MG_EV_WS_MSG, &m);
|
||||
break;
|
||||
case WEBSOCKET_OP_CLOSE:
|
||||
MG_DEBUG(("%lu Got WS CLOSE", c->id));
|
||||
MG_DEBUG(("%lu WS CLOSE", c->id));
|
||||
mg_call(c, MG_EV_WS_CTL, &m);
|
||||
mg_ws_send(c, "", 0, WEBSOCKET_OP_CLOSE);
|
||||
// Echo the payload of the received CLOSE message back to the sender
|
||||
mg_ws_send(c, m.data.ptr, m.data.len, WEBSOCKET_OP_CLOSE);
|
||||
c->is_draining = 1;
|
||||
break;
|
||||
default:
|
||||
@ -5952,7 +5935,7 @@ static uint8_t rd(struct mip_spi *spi, uint8_t op, uint8_t addr) {
|
||||
|
||||
static bool mip_driver_enc28j60_init(uint8_t *mac, void *data) {
|
||||
(void) mac, (void) data;
|
||||
rd(data, OP_SRC, 0x1f);
|
||||
rd((struct mip_spi *) data, OP_SRC, 0x1f);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5971,10 +5954,9 @@ static bool mip_driver_enc28j60_up(void *data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mip_driver mip_driver_enc28j60 = {.init = mip_driver_enc28j60_init,
|
||||
.tx = mip_driver_enc28j60_tx,
|
||||
.rx = mip_driver_enc28j60_rx,
|
||||
.up = mip_driver_enc28j60_up};
|
||||
struct mip_driver mip_driver_enc28j60 = {
|
||||
mip_driver_enc28j60_init, mip_driver_enc28j60_tx, mip_driver_enc28j60_rx,
|
||||
mip_driver_enc28j60_up, NULL};
|
||||
#endif
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
@ -5982,7 +5964,7 @@ struct mip_driver mip_driver_enc28j60 = {.init = mip_driver_enc28j60_init,
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_MIP && defined(__arm__)
|
||||
#if MG_ENABLE_MIP
|
||||
struct stm32_eth {
|
||||
volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
|
||||
MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
|
||||
@ -6012,7 +5994,7 @@ static void *s_rxdata; // Recv callback data
|
||||
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; // PHY constants
|
||||
|
||||
static inline void spin(volatile uint32_t count) {
|
||||
while (count--) asm("nop");
|
||||
while (count--) (void) 0;
|
||||
}
|
||||
|
||||
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
@ -6050,7 +6032,7 @@ static uint32_t get_hclk(void) {
|
||||
} else {
|
||||
clk = hsi;
|
||||
}
|
||||
int hpre = (RCC->CFGR & (0x0F << 4)) >> 4;
|
||||
uint32_t hpre = (RCC->CFGR & (15 << 4)) >> 4;
|
||||
if (hpre < 8) return clk;
|
||||
|
||||
uint8_t ahbptab[8] = {1, 2, 3, 4, 6, 7, 8, 9}; // log2(div)
|
||||
@ -6108,7 +6090,7 @@ static bool mip_driver_stm32_init(uint8_t *mac, void *userdata) {
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
ETH->MACMIIAR = (cr & 3) << 2;
|
||||
ETH->MACMIIAR = ((uint32_t)cr & 3) << 2;
|
||||
|
||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
||||
@ -6183,10 +6165,9 @@ void ETH_IRQHandler(void) {
|
||||
ETH->DMASR = sr & ~(BIT(2) | BIT(7)); // Clear status
|
||||
}
|
||||
|
||||
struct mip_driver mip_driver_stm32 = {.init = mip_driver_stm32_init,
|
||||
.tx = mip_driver_stm32_tx,
|
||||
.setrx = mip_driver_stm32_setrx,
|
||||
.up = mip_driver_stm32_up};
|
||||
struct mip_driver mip_driver_stm32 = {
|
||||
mip_driver_stm32_init, mip_driver_stm32_tx, NULL, mip_driver_stm32_up,
|
||||
mip_driver_stm32_setrx};
|
||||
#endif
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
@ -6200,8 +6181,9 @@ enum { W5500_CR = 0, W5500_S0 = 1, W5500_TX0 = 2, W5500_RX0 = 3 };
|
||||
|
||||
static void w5500_txn(struct mip_spi *s, uint8_t block, uint16_t addr, bool wr,
|
||||
void *buf, size_t len) {
|
||||
uint8_t *p = buf, cmd[] = {(uint8_t) (addr >> 8), (uint8_t) (addr & 255),
|
||||
(uint8_t) ((block << 3) | (wr ? 4 : 0))};
|
||||
uint8_t *p = (uint8_t *) buf;
|
||||
uint8_t cmd[] = {(uint8_t) (addr >> 8), (uint8_t) (addr & 255),
|
||||
(uint8_t) ((block << 3) | (wr ? 4 : 0))};
|
||||
s->begin(s->spi);
|
||||
for (size_t i = 0; i < sizeof(cmd); i++) s->txn(s->spi, cmd[i]);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
@ -6278,8 +6260,8 @@ static bool w5500_up(void *data) {
|
||||
return phycfgr & 1; // Bit 0 of PHYCFGR is LNK (0 - down, 1 - up)
|
||||
}
|
||||
|
||||
struct mip_driver mip_driver_w5500 = {
|
||||
.init = w5500_init, .tx = w5500_tx, .rx = w5500_rx, .up = w5500_up};
|
||||
struct mip_driver mip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx, w5500_up,
|
||||
NULL};
|
||||
#endif
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
@ -6289,12 +6271,6 @@ struct mip_driver mip_driver_w5500 = {
|
||||
|
||||
#if MG_ENABLE_MIP
|
||||
|
||||
#if defined(_MSC_VER) || defined(ARDUINO)
|
||||
#define _Atomic
|
||||
#else
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#define MIP_ETHEMERAL_PORT 49152
|
||||
#define U16(ptr) ((((uint16_t) (ptr)[0]) << 8) | (ptr)[1])
|
||||
#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
|
||||
@ -6307,8 +6283,11 @@ struct mip_driver mip_driver_w5500 = {
|
||||
#define MIP_QSIZE (16 * 1024) // Queue size
|
||||
#endif
|
||||
|
||||
#ifndef MIP_TCP_KEEPALIVE_MS
|
||||
#define MIP_TCP_KEEPALIVE_MS 45000 // TCP keep-alive period, ms
|
||||
#endif
|
||||
|
||||
#define MIP_ARP_CS (2 + 12 * MIP_ARP_ENTRIES) // ARP cache size
|
||||
#define MIP_TCP_KEEPALIVE_MS 45000 // TCP keep-alive period, ms
|
||||
#define MIP_TCP_ACK_MS 150 // Timeout for ACKing
|
||||
|
||||
struct connstate {
|
||||
@ -6318,6 +6297,7 @@ struct connstate {
|
||||
uint8_t ttype; // Timer type. 0: ack, 1: keep-alive
|
||||
#define MIP_TTYPE_KEEPALIVE 0 // Connection is idle for long, send keepalive
|
||||
#define MIP_TTYPE_ACK 1 // Peer sent us data, we have to ack it soon
|
||||
uint8_t tmiss; // Number of keep-alive misses
|
||||
struct mg_iobuf raw; // For TLS only. Incoming raw data
|
||||
};
|
||||
|
||||
@ -6332,7 +6312,7 @@ struct str {
|
||||
struct queue {
|
||||
uint8_t *buf;
|
||||
size_t len;
|
||||
volatile _Atomic size_t tail, head;
|
||||
volatile size_t tail, head;
|
||||
};
|
||||
|
||||
// Network interface
|
||||
@ -6349,6 +6329,7 @@ struct mip_if {
|
||||
// Internal state, user can use it but should not change it
|
||||
uint64_t now; // Current time
|
||||
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
|
||||
uint64_t lease_expire; // Lease expiration time
|
||||
uint8_t arp_cache[MIP_ARP_CS]; // Each entry is 12 bytes
|
||||
uint16_t eport; // Next ephemeral port
|
||||
uint16_t dropped; // Number of dropped frames
|
||||
@ -6598,11 +6579,17 @@ static void arp_ask(struct mip_if *ifp, uint32_t ip) {
|
||||
ifp->driver->tx(eth, PDIFF(eth, arp + 1), ifp->driver_data);
|
||||
}
|
||||
|
||||
static size_t mg_print_ipv4(mg_pfn_t fn, void *fn_data, va_list *ap) {
|
||||
uint32_t ip = mg_ntohl(va_arg(*ap, uint32_t));
|
||||
return mg_xprintf(fn, fn_data, "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 255,
|
||||
(ip >> 8) & 255, ip & 255);
|
||||
}
|
||||
|
||||
static void onstatechange(struct mip_if *ifp) {
|
||||
if (ifp->state == MIP_STATE_READY) {
|
||||
char buf[40];
|
||||
struct mg_addr addr = {.ip = ifp->ip};
|
||||
MG_INFO(("READY, IP: %s", mg_ntoa(&addr, buf, sizeof(buf))));
|
||||
MG_INFO(("READY, IP: %M", mg_print_ipv4, ifp->ip));
|
||||
MG_INFO((" GW: %M", mg_print_ipv4, ifp->gw));
|
||||
MG_INFO((" Lease: %lld sec", (ifp->lease_expire - ifp->now) / 1000));
|
||||
arp_ask(ifp, ifp->gw);
|
||||
} else if (ifp->state == MIP_STATE_UP) {
|
||||
MG_ERROR(("Link up"));
|
||||
@ -6658,11 +6645,19 @@ static void tx_udp(struct mip_if *ifp, uint32_t ip_src, uint16_t sport,
|
||||
|
||||
static void tx_dhcp(struct mip_if *ifp, uint32_t src, uint32_t dst,
|
||||
uint8_t *opts, size_t optslen) {
|
||||
struct dhcp dhcp = {.op = 1,
|
||||
.htype = 1,
|
||||
.hlen = 6,
|
||||
.ciaddr = src,
|
||||
.magic = mg_htonl(0x63825363)};
|
||||
#if 0
|
||||
struct dhcp {
|
||||
uint8_t op, htype, hlen, hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs, flags;
|
||||
uint32_t ciaddr, yiaddr, siaddr, giaddr;
|
||||
uint8_t hwaddr[208];
|
||||
uint32_t magic;
|
||||
uint8_t options[32];
|
||||
};
|
||||
#endif
|
||||
struct dhcp dhcp = {1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
|
||||
dhcp.magic = mg_htonl(0x63825363);
|
||||
memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac));
|
||||
memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid));
|
||||
memcpy(&dhcp.options, opts, optslen);
|
||||
@ -6719,15 +6714,16 @@ static void rx_arp(struct mip_if *ifp, struct pkt *pkt) {
|
||||
|
||||
static void rx_icmp(struct mip_if *ifp, struct pkt *pkt) {
|
||||
// MG_DEBUG(("ICMP %d", (int) len));
|
||||
if (pkt->icmp->type == 8 && pkt->ip->dst == ifp->ip) {
|
||||
if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
|
||||
struct ip *ip = tx_ip(ifp, 1, ifp->ip, pkt->ip->src,
|
||||
sizeof(struct icmp) + pkt->pay.len);
|
||||
struct icmp *icmp = (struct icmp *) (ip + 1);
|
||||
memset(icmp, 0, sizeof(*icmp)); // Important - set csum to 0
|
||||
memcpy(icmp + 1, pkt->pay.buf, pkt->pay.len);
|
||||
icmp->csum = ipcsum(icmp, sizeof(*icmp) + pkt->pay.len);
|
||||
ifp->driver->tx(ifp->tx.buf, PDIFF(ifp->tx.buf, icmp + 1) + pkt->pay.len,
|
||||
ifp->driver_data);
|
||||
size_t len = PDIFF(ifp->tx.buf, icmp + 1), left = ifp->tx.len - len;
|
||||
if (left > pkt->pay.len) left = pkt->pay.len; // Don't overflow TX
|
||||
memset(icmp, 0, sizeof(*icmp)); // Set csum to 0
|
||||
memcpy(icmp + 1, pkt->pay.buf, left); // Copy RX payload to TX
|
||||
icmp->csum = ipcsum(icmp, sizeof(*icmp) + left);
|
||||
ifp->driver->tx(ifp->tx.buf, len + left, ifp->driver_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6735,21 +6731,20 @@ static void rx_dhcp(struct mip_if *ifp, struct pkt *pkt) {
|
||||
uint32_t ip = 0, gw = 0, mask = 0;
|
||||
uint8_t *p = pkt->dhcp->options, *end = &pkt->raw.buf[pkt->raw.len];
|
||||
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
|
||||
// MG_DEBUG(("DHCP %u", (unsigned) pkt->raw.len));
|
||||
while (p < end && p[0] != 255) {
|
||||
if (p[0] == 1 && p[1] == sizeof(ifp->mask)) {
|
||||
while (p + 1 < end && p[0] != 255) { // Parse options
|
||||
if (p[0] == 1 && p[1] == sizeof(ifp->mask) && p + 6 < end) { // Mask
|
||||
memcpy(&mask, p + 2, sizeof(mask));
|
||||
// MG_DEBUG(("MASK %x", mask));
|
||||
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw)) {
|
||||
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
|
||||
memcpy(&gw, p + 2, sizeof(gw));
|
||||
ip = pkt->dhcp->yiaddr;
|
||||
// MG_DEBUG(("IP %x GW %x", ip, gw));
|
||||
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
|
||||
uint32_t lease = 0;
|
||||
memcpy(&lease, p + 2, sizeof(lease));
|
||||
ifp->lease_expire = ifp->now + mg_ntohl(lease) * 1000;
|
||||
}
|
||||
p += p[1] + 2;
|
||||
}
|
||||
if (ip && mask && gw && ifp->ip == 0) {
|
||||
// MG_DEBUG(("DHCP offer ip %#08lx mask %#08lx gw %#08lx", (long) ip,
|
||||
// (long) mask, (long) gw));
|
||||
arp_cache_add(ifp, pkt->dhcp->siaddr, ((struct eth *) pkt->raw.buf)->src);
|
||||
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
|
||||
ifp->state = MIP_STATE_READY;
|
||||
@ -6936,7 +6931,8 @@ static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
|
||||
if (c != NULL && s->ttype == MIP_TTYPE_KEEPALIVE) {
|
||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||
s->tmiss = 0; // Reset missed keep-alive counter
|
||||
settmout(c, MIP_TTYPE_KEEPALIVE); // Advance keep-alive timer
|
||||
}
|
||||
#if 0
|
||||
MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len));
|
||||
@ -7009,7 +7005,7 @@ static void rx_ip6(struct mip_if *ifp, struct pkt *pkt) {
|
||||
if (pkt->pay.len < sizeof(*pkt->icmp)) return;
|
||||
mkpay(pkt, pkt->icmp + 1);
|
||||
rx_icmp(ifp, pkt);
|
||||
} else if (pkt->ip->proto == 17) {
|
||||
} else if (pkt->ip6->proto == 17) {
|
||||
pkt->udp = (struct udp *) (pkt->ip6 + 1);
|
||||
if (pkt->pay.len < sizeof(*pkt->udp)) return;
|
||||
// MG_DEBUG((" UDP %u %u -> %u", len, mg_htons(udp->sport),
|
||||
@ -7020,7 +7016,11 @@ static void rx_ip6(struct mip_if *ifp, struct pkt *pkt) {
|
||||
|
||||
static void mip_rx(struct mip_if *ifp, void *buf, size_t len) {
|
||||
const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
|
||||
struct pkt pkt = {.raw = {.buf = (uint8_t *) buf, .len = len}};
|
||||
// struct pkt pkt = {.raw = {.buf = (uint8_t *) buf, .len = len}};
|
||||
struct pkt pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.raw.buf = (uint8_t *) buf;
|
||||
pkt.raw.len = len;
|
||||
pkt.eth = (struct eth *) buf;
|
||||
if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt?
|
||||
if (memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
|
||||
@ -7099,6 +7099,7 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) {
|
||||
MG_DEBUG(("%lu keepalive", c->id));
|
||||
tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
|
||||
if (s->tmiss++ > 2) mg_error(c, "keepalive");
|
||||
}
|
||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||
}
|
||||
@ -7122,32 +7123,38 @@ static void on_rx(void *buf, size_t len, void *userdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void if_init(struct mip_if *ifp, struct mg_mgr *mgr,
|
||||
struct mip_cfg *ipcfg, struct mip_driver *driver,
|
||||
void *driver_data, size_t maxpktsize, size_t qlen) {
|
||||
memcpy(ifp->mac, ipcfg->mac, sizeof(ifp->mac));
|
||||
ifp->use_dhcp = ipcfg->ip == 0;
|
||||
ifp->ip = ipcfg->ip, ifp->mask = ipcfg->mask, ifp->gw = ipcfg->gw;
|
||||
ifp->rx.buf = (uint8_t *) (ifp + 1), ifp->rx.len = maxpktsize;
|
||||
ifp->tx.buf = ifp->rx.buf + maxpktsize, ifp->tx.len = maxpktsize;
|
||||
ifp->driver = driver;
|
||||
ifp->driver_data = driver_data;
|
||||
ifp->mgr = mgr;
|
||||
ifp->queue.buf = ifp->tx.buf + maxpktsize;
|
||||
ifp->queue.len = qlen;
|
||||
ifp->timer_1000ms = mg_millis();
|
||||
arp_cache_init(ifp->arp_cache, MIP_ARP_ENTRIES, 12);
|
||||
if (driver->setrx) driver->setrx(on_rx, ifp);
|
||||
mgr->priv = ifp;
|
||||
mgr->extraconnsize = sizeof(struct connstate);
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void mip_init(struct mg_mgr *mgr, struct mip_cfg *ipcfg,
|
||||
struct mip_driver *driver, void *driver_data) {
|
||||
if (driver->init && !driver->init(ipcfg->mac, driver_data)) {
|
||||
MG_ERROR(("driver init failed"));
|
||||
} else {
|
||||
size_t maxpktsize = 1518, qlen = driver->setrx ? MIP_QSIZE : 0;
|
||||
size_t maxpktsize = 1540, qlen = driver->setrx ? MIP_QSIZE : 0;
|
||||
struct mip_if *ifp =
|
||||
(struct mip_if *) calloc(1, sizeof(*ifp) + 2 * maxpktsize + qlen);
|
||||
memcpy(ifp->mac, ipcfg->mac, sizeof(ifp->mac));
|
||||
ifp->use_dhcp = ipcfg->ip == 0;
|
||||
ifp->ip = ipcfg->ip, ifp->mask = ipcfg->mask, ifp->gw = ipcfg->gw;
|
||||
ifp->rx.buf = (uint8_t *) (ifp + 1), ifp->rx.len = maxpktsize;
|
||||
ifp->tx.buf = ifp->rx.buf + maxpktsize, ifp->tx.len = maxpktsize;
|
||||
ifp->driver = driver;
|
||||
ifp->driver_data = driver_data;
|
||||
ifp->mgr = mgr;
|
||||
ifp->queue.buf = ifp->tx.buf + maxpktsize;
|
||||
ifp->queue.len = qlen;
|
||||
ifp->timer_1000ms = mg_millis();
|
||||
arp_cache_init(ifp->arp_cache, MIP_ARP_ENTRIES, 12);
|
||||
if (driver->setrx) driver->setrx(on_rx, ifp);
|
||||
mgr->priv = ifp;
|
||||
mgr->extraconnsize = sizeof(struct connstate);
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_init();
|
||||
#endif
|
||||
if_init(ifp, mgr, ipcfg, driver, driver_data, maxpktsize, qlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
126
src/webui.c
126
src/webui.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
WebUI Library 2.0.0
|
||||
WebUI Library 2.0.1
|
||||
|
||||
http://webui.me
|
||||
https://github.com/alifcommunity/webui
|
||||
@ -14,13 +14,15 @@
|
||||
// -- WebUI ---------------------------
|
||||
#include "webui.h"
|
||||
|
||||
// -- Log -----------------------------
|
||||
// #define WEBUI_LOG
|
||||
|
||||
// -- Heap ----------------------------
|
||||
#define WEBUI_LOG
|
||||
webui_t webui;
|
||||
|
||||
// -- JavaScript Bridge ---------------
|
||||
// Uncompressed version to allow debugging
|
||||
// in the browser using the builtin dev-tools
|
||||
// This is a uncompressed version to make the debugging
|
||||
// more easy in the browser using the builtin dev-tools
|
||||
static const char* webui_javascript_bridge =
|
||||
"var _webui_log = false; \n"
|
||||
"var _webui_ws; \n"
|
||||
@ -305,6 +307,7 @@ static const char* webui_def_icon = "<?xml version=\"1.0\" ?><svg height=\"24\"
|
||||
static const char* webui_def_icon_type = "image/svg+xml";
|
||||
static const char* webui_js_empty = "WEBUI_JS_EMPTY";
|
||||
static const char* webui_js_timeout = "WEBUI_JS_TIMEOUT";
|
||||
static const char* webui_empty_string = ""; // .text
|
||||
|
||||
#ifdef _WIN32
|
||||
static const char* webui_sep = "\\";
|
||||
@ -485,12 +488,12 @@ bool _webui_file_exist(char* file) {
|
||||
const char* _webui_get_extension(const char *f) {
|
||||
|
||||
if(f == NULL)
|
||||
return "";
|
||||
return webui_empty_string;
|
||||
|
||||
const char *ext = strrchr(f, '.');
|
||||
|
||||
if(ext == NULL || !ext || ext == f)
|
||||
return "";
|
||||
return webui_empty_string;
|
||||
return ext + 1;
|
||||
}
|
||||
|
||||
@ -1081,6 +1084,8 @@ static void _webui_server_event_handler(struct mg_connection *c, int ev, void *e
|
||||
|
||||
// Send main HTML
|
||||
|
||||
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[%d] _webui_server_event_handler()... HTML Main\n", win->core.window_number);
|
||||
#endif
|
||||
@ -1353,7 +1358,7 @@ bool _webui_browser_create_profile_folder(webui_window_t* win, unsigned int brow
|
||||
return true;
|
||||
}
|
||||
|
||||
char* temp = _webui_browser_get_temp_path(browser);
|
||||
const char* temp = _webui_browser_get_temp_path(browser);
|
||||
|
||||
// Chrome
|
||||
// No need to create a folder
|
||||
@ -1464,7 +1469,7 @@ bool _webui_folder_exist(char* folder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* _webui_browser_get_temp_path(unsigned int browser) {
|
||||
const char* _webui_browser_get_temp_path(unsigned int browser) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[0] _webui_browser_get_temp_path([%d])... \n", browser);
|
||||
@ -1476,11 +1481,11 @@ char* _webui_browser_get_temp_path(unsigned int browser) {
|
||||
char* WinUserProfile = NULL;
|
||||
size_t sz = 0;
|
||||
if(_dupenv_s(&WinUserProfile, &sz, "USERPROFILE") != 0 || WinUserProfile == NULL)
|
||||
return "";
|
||||
return webui_empty_string;
|
||||
#else
|
||||
char* WinUserProfile = getenv("USERPROFILE"); // _dupenv_s
|
||||
if(WinUserProfile == NULL)
|
||||
return "";
|
||||
return webui_empty_string;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1519,7 +1524,7 @@ char* _webui_browser_get_temp_path(unsigned int browser) {
|
||||
}
|
||||
|
||||
_webui_panic();
|
||||
return "";
|
||||
return webui_empty_string;
|
||||
}
|
||||
|
||||
bool _webui_browser_exist(webui_window_t* win, unsigned int browser) {
|
||||
@ -2179,10 +2184,10 @@ bool webui_any_window_is_open() {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int _webui_window_get_window_number(webui_window_t* win) {
|
||||
unsigned int _webui_window_get_number(webui_window_t* win) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[%d] _webui_window_get_window_number()... \n", win->core.window_number);
|
||||
printf("[%d] _webui_window_get_number()... \n", win->core.window_number);
|
||||
#endif
|
||||
|
||||
return win->core.window_number;
|
||||
@ -2257,6 +2262,8 @@ void webui_set_icon(webui_window_t* win, const char* icon_s, const char* type_s)
|
||||
|
||||
bool webui_show(webui_window_t* win, const char* html, unsigned int browser) {
|
||||
|
||||
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[%d] webui_show([%.*s..], [%d])... \n", win->core.window_number, 3, html, browser);
|
||||
#endif
|
||||
@ -2283,7 +2290,6 @@ bool webui_show(webui_window_t* win, const char* html, unsigned int browser) {
|
||||
CloseHandle(thread);
|
||||
|
||||
// Run browser
|
||||
|
||||
if(!_webui_browser_start(win, win->core.url, browser))
|
||||
return false;
|
||||
}
|
||||
@ -2308,7 +2314,28 @@ bool webui_show(webui_window_t* win, const char* html, unsigned int browser) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void webui_bind_all(webui_window_t* win, void (*func) (webui_event_t e)) {
|
||||
bool webui_copy_show(webui_window_t* win, const char* html, unsigned int browser) {
|
||||
|
||||
// Copy HTML, And show the window
|
||||
|
||||
// Free
|
||||
if(win->core.html_cpy != NULL)
|
||||
_webui_free_mem((void *) &win->core.html_cpy);
|
||||
|
||||
// Allocate
|
||||
char* cpy = (char*) webui_empty_string;
|
||||
size_t len = strlen(html);
|
||||
if(len > 1) {
|
||||
|
||||
char* cpy = _webui_malloc(len + 1);
|
||||
memcpy(cpy, html, len);
|
||||
}
|
||||
|
||||
// Show window
|
||||
return webui_show(win, cpy, browser);
|
||||
}
|
||||
|
||||
void webui_bind_all(webui_window_t* win, void (*func) (webui_event_t* e)) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[%d] webui_bind_all([*])... \n", win->core.window_number);
|
||||
@ -2318,10 +2345,10 @@ void webui_bind_all(webui_window_t* win, void (*func) (webui_event_t e)) {
|
||||
win->core.is_bind_all = true;
|
||||
}
|
||||
|
||||
unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (webui_event_t e)) {
|
||||
unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (webui_event_t* e)) {
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
printf("[%d] webui_bind([%s], [*])... \n", win->core.window_number, element);
|
||||
printf("[%d] webui_bind([%s], [%p])... \n", win->core.window_number, element, func);
|
||||
#endif
|
||||
|
||||
char* element_id = _webui_malloc(strlen(element));
|
||||
@ -2365,6 +2392,7 @@ unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (
|
||||
webui_event_t e;
|
||||
e.window_id = arg->win->core.window_number;
|
||||
e.element_name = arg->element_name;
|
||||
e.window = arg->win;
|
||||
|
||||
unsigned int cb_index = _webui_get_cb_index(arg->element_id);
|
||||
|
||||
@ -2373,14 +2401,14 @@ unsigned int webui_bind(webui_window_t* win, const char* element, void (*func) (
|
||||
|
||||
// User cb
|
||||
e.element_id = cb_index;
|
||||
webui.cb[cb_index](e);
|
||||
webui.cb[cb_index](&e);
|
||||
}
|
||||
|
||||
// General user cb
|
||||
if(arg->win->core.is_bind_all && arg->win->core.cb_all[0] != NULL) {
|
||||
|
||||
e.element_id = 0;
|
||||
arg->win->core.cb_all[0](e);
|
||||
arg->win->core.cb_all[0](&e);
|
||||
}
|
||||
|
||||
#ifdef WEBUI_LOG
|
||||
@ -2444,8 +2472,22 @@ bool _webui_get_data(const char* packet, size_t packet_len, unsigned int pos, si
|
||||
printf("[0] _webui_get_data()... \n");
|
||||
#endif
|
||||
|
||||
if((pos + 1) > packet_len) {
|
||||
|
||||
*data = NULL;
|
||||
data_len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = (char*) _webui_malloc((packet_len - pos) + 1);
|
||||
|
||||
// Check mem
|
||||
if(*data == NULL) {
|
||||
|
||||
data_len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy data part
|
||||
char* p = *data;
|
||||
for(unsigned int i = pos; i < packet_len; i++) {
|
||||
@ -2459,6 +2501,8 @@ bool _webui_get_data(const char* packet, size_t packet_len, unsigned int pos, si
|
||||
if(*data_len < 1) {
|
||||
|
||||
_webui_free_mem((void *) data);
|
||||
*data = NULL;
|
||||
data_len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2507,31 +2551,44 @@ void _webui_window_receive(webui_window_t* win, const char* packet, size_t len)
|
||||
// 3: [Error]
|
||||
// 4: [Data]
|
||||
|
||||
// Get data part
|
||||
char* data;
|
||||
size_t data_len;
|
||||
if(!_webui_get_data(packet, len, 4, &data_len, &data))
|
||||
return;
|
||||
|
||||
// Get pipe id
|
||||
unsigned char run_id = packet[2];
|
||||
if(run_id < 0x01) {
|
||||
|
||||
_webui_free_mem((void *) &data);
|
||||
// Fatal.
|
||||
// The pipe ID is not valid
|
||||
// we can't send the ready signal to webui_run_js()
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data part
|
||||
char* data;
|
||||
size_t data_len;
|
||||
bool data_status = _webui_get_data(packet, len, 4, &data_len, &data);
|
||||
|
||||
// Get js-error
|
||||
bool error = true;
|
||||
if((unsigned char) packet[3] == 0x00)
|
||||
error = false;
|
||||
|
||||
// Set pipe
|
||||
// Initialize pipe
|
||||
_webui_free_mem((void *) &webui.run_responses[run_id]);
|
||||
webui.run_error[run_id] = error;
|
||||
webui.run_responses[run_id] = data;
|
||||
|
||||
// Ready signal
|
||||
// Set pipe
|
||||
if(data_status && data_len > 0) {
|
||||
|
||||
webui.run_error[run_id] = error;
|
||||
webui.run_responses[run_id] = data;
|
||||
}
|
||||
else {
|
||||
|
||||
// Empty Result
|
||||
|
||||
webui.run_error[run_id] = error;
|
||||
webui.run_responses[run_id] = webui_empty_string;
|
||||
}
|
||||
|
||||
// Send ready signal to webui_run_js()
|
||||
webui.run_done[run_id] = true;
|
||||
}
|
||||
}
|
||||
@ -2544,6 +2601,7 @@ bool webui_open(webui_window_t* win, const char* url, unsigned int browser) {
|
||||
|
||||
// Just open an app-mode window using the link
|
||||
webui_set_timeout(0);
|
||||
webui_detect_process_close(win, true);
|
||||
return _webui_browser_start(win, url, browser);
|
||||
}
|
||||
|
||||
@ -2821,14 +2879,14 @@ unsigned int _webui_set_cb_index(char* element_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --[Python Wrapper]---------------
|
||||
// --[Python Interface]---------------
|
||||
|
||||
void webui_bind_py_handler(const webui_event_t e) {
|
||||
void webui_bind_py_handler(webui_event_t* e) {
|
||||
|
||||
unsigned int cb_index = e.element_id;
|
||||
unsigned int cb_index = e->element_id;
|
||||
|
||||
if(cb_index > 0 && webui.cb_py[cb_index] != NULL)
|
||||
webui.cb_py[cb_index](e.element_id, e.window_id, e.element_name);
|
||||
webui.cb_py[cb_index](e->element_id, e->window_id, e->element_name);
|
||||
}
|
||||
|
||||
unsigned int webui_bind_py(webui_window_t* win, const char* element, void (*func)(unsigned int, unsigned int, char*)) {
|
||||
|
Loading…
Reference in New Issue
Block a user