180hfn=Sc{bWhXxgEh==
zW1rtwZ2$YO!$F%-$GrTbcHgUr??n3JEkO#40K@kZT!f`?1GCKBQVHtI|sTNg#D9Vi9twv#N4WrU3W=qXSW>WL{W
zA(+Z2l|A1yhMuneK2!OrlbSD(uQMGV#-sjcdATd}0vQouUdnIIEEQtZB}ELa<~v8L
z`raj)u1XfY(Hk`62XpTAv-?j|p2uUS(|h_}M|)c~2SY`5D
zjLN&tF1YoO{>>w6X?1#mh|gB|Z^zrM#KMs8tjnA-ijKprFMpz7DPx()kZ}G-!&n}b
zQWE}iomeo2GgZ(mQo{Kw&x``396eN%agslzu;deOa{@D{#mxIS-i?lq{OPjnQ6C|H
zNH>(Ce<2j_wts`n@c2mNTKr9^r;T$S-{BYSc&w>Z`arxx$zG)0K|6$(i`6lGQf;s&
z^0O78veq-6BqVRaL)&W%B(00y9qYS2(NRd{UO|)ODIOa%mHZ@uWIe1vX^BY1lW$baGchGIVLJVa?cgik%VPcR
zuym}9U1;~O?F^8FO3L~zBwztXxsbXL^A}PhL8kyV87~rIDmL;??7+kA;Q6*Bk#O>f
zfC%!5Wd)AJ%$F}0KKJx6_&lqvua_>eTeqmFbuCIpI(Q$EvXUp6_{#*7rd?&!|o6c?0@6O9+PO%MhsuH6bZKCKP6}D8#YM`
z7s&)vn|zOUmYNaAcR2()y!rl>kY6@-($MJdOHEBpQdz5xn(Het(ru#(MZ6tX?CdGe
z(Y+Q%&`7lTMKjx*BT;_5=-|mf2mGw%~*c_+G8VK-OWs6`P@E)D>6R!f!A;*
z&~4L0_Q>*nEZ)qdLo#}hU8_l;Rc-^)FgP1ah%O^O=iH`hY%+2wk!X&gbPYh3XEz)HO0uY`pJyVUm@&a8V8N`E8v=bK!zclKsbClvmroF3}57U*@s2=w+
z8sA3m$J(E+bZCZDj^p*o#W%*ytN#sncj>N_*>TN;MJEtGXy{s)2A*9a!~=$E
zQ0m#|!5j)3bti-1Te{}+)S{hRMqDC~*i9%>qGTAu%SIgPAba;4a+|tw90~WQreZq0!k((>7sIS&%R9^%{^z&FDiPdKHaK@`|qxx)^&nW
z&xg5Q*3!$Lvk-`Yosp{!;!FYCnNzxGG!cgZj}Ypdm8$lzxt{TClf9*DY3!}t%EDGn
z=B4=JqKj}+8)}wRJzA4;{wm?Qq+W`C_UoAKMU76KRj-^+;R%4WuN2IlVi8p
zR$}NI$a{F&=fWEUt09EAIUzgS#l%5e$-uOU#`!~la?>jtMr@1_SrxJr2m{G!X$f`r
zZ!?x}b#-<1bJiQC@pS+Y2PBR?M3q^{Ub~aubw_s9*EQwhM=5NLh33S6&Ep+LaMi7)
zuFut+9cm?K`hwmyOU7H>Ck-I#MB8sFPuSVneCV_~6?hsQKlM?tP$i3*PknfNBTgxD
zg(sK*hzoJolE&jsoC)xLfyRO&pQk*Zhwm{|KiAF+*U%bvi0#C$p3EASyw8|r5Vo?=
zy*xOfR4O?;c>DCq=O1e{C`-&;hQXz})6_=MmVXy_@#DvF4~n{Q4F=@g9d@--)-|T|
zre$9b!9!eYUgxIhd3LhDFGBA5Wyx!eX!s_B$%zCMa1vj?7Syj%d2oSphhh
z10`lBGvifg*BMt;7#rgtaKDCzYg@P@I^nj$O#0>Xa#=z@sV;3>rN9o+W%4500=wT<
z=uPth%Z5ut`Z4}M3K{zwn7dJi!jHr#-&%rN
z&H!?~btzr@?Hv>i5(2{1u_Jbyn2
zNs**pb!tLLJK7#r=arX#HnX%8uAgyHc{7r=dwg=-{@9L%K!6{E+#fw563`l>R^HsL
zq`v;!OJ*_P^lfpczV=ZVQci<#$LrZ>RpB@Mf9C~^q(mb9>dA?o!n
zkNQ6&J?_fQ&efCo%f9D@HXyvkm;hG8rax8ijePE$Z5=?o%BQRChXCX$1!&PJ6EwPL
zu)lvHlHUqWytv8EWF)V82}rGu42l_8O_Fqn+>_N;koh$=bnJl#bCotFg@s(k`uYpb
z&dy`*EEC+Q(LC5=bZNQhZ}8KQ6CL*~>xm|VMb>$xZ*Omp-yuVYVeJ@d)dDCzO*A(b
z@Am-i%Tjwqob?Jj*Z6glABb5zx|s=?*uh&GC4Q}Zo1o{FH86;#qfhIqBo)eZ?J
z-f~y`s9v1;8JFcaTs04gTw%qugYKNQIIK7aYe14}mBz5W$
zuacjjU*Z+A&i5E>6agPV=nrSa=m^iK{k
z^XD{}x#cV|T!w?RP{joE4czkjBEP4R!Hcgl6oRkEXc_&JkUSU!Dv}oHfz6i++_V!3
zEs|TwIQbkh+LCzb0~=oX!2@NdWF
zlCbI`@dP#Q^p7eS%MY{D&TbOVZC#+5y-*x!bX!sV>k}ad$>GxIsNQ{RYwNr5&Zb`PR$4;yOUiicT`s8z
zl7*#SxN%`kv^!j&)*y@s&mws2a_|_lj-XIF_En&0>8HO}zTb<~pii2^O+K0c+p|mM
z><*(kT1okfi4VVU4<0hr2#_FH$6i&cVF(p5iR}_0
zC3c0Jb4iY0+lsa1$JxSCBY04My!_t2Gg1iVMBOcUgc-%jJlzvm-#)a>c*qc$F5!H|
z5Zqmrb`rfLp$HE>io8py$Ou&TRi3EI#*?x2Q;e;_lW$(tSm;wcy2;GM%p8%+88PEj
zGm3CvYP|+qwS$9$PDUo9Kz}(EQ5YG-bFNj!;qaus?0nD$&P~NqPBM4tmCtHpVK!f$
zzI6H0&Q4CJdaw2=_U|Q3Pb%HeHV_kKv1opPsW*Yn1~g~MDsSFh?05Gje`q52;|ylT
zoEJP4bF;J;vtC}mmpbwFt2P;9`I3|FpxTXKn=ko)NpSi*Qa_ho`An`wJDE^$b&t1r
zlcO*pd7op6g28PJZ03Gf@Xs3yT!EK01OWDG7=u2y^zTzsY5cZzLiQ%9nzW4Nj;aO-
z4}HV@c!CL`57J
z>H^vvZB3FyYq91+^i0gpT_wjyMnaB`j$n%~Ybh(!DotGYo{-2gF**0EF1hoZ;~jPM
zsQqGk$4TnF=ay%5+?BAxzS6C(t{MR&*y|+{mEN&>2UGAs;jyJSx`44}*x7*0N6Pk<
z_r?M1Skd5%QCy7S!1CY8YQ6K(0VL?3$~i-|k^T7AhZsdN6q|BjZ_ri=^>
z4rs3NmM`Ilr7Fi{>kEHU3(JH>@HPL9FVinen!5uw(7SA3+&+YDUE}RPi;@J-`H(_h
z+YImJ2nN9_=WmX4e3$iYO*+ZAcPS$yxc(#PiD4f_=AT~YHXfG`8CFkQzL7A(D(*Nk
zy`&kSk(7l&+=6jBRgU40We{2E0FL>^n2@ilu70`a
z_rRt|m6aGzjZ_7_#4X5RDiPIf69-Eo>&M--Fy&8KSeVlTa~Pl_Y{BNljKU00PQC*m
z*B1gRSvNkG#ta?Cat+Q>(LQ&Im1;21YXHV1Q6^s{II_@s^qqUjChS5eHyox2$?FA`
zNWjT-t0{FRnU~lB+vvACqfn$ZHQnbVQ+*Byt@UR&Q+HAFf54LS4w17*!eq71!7+f-%OH{*b#)PiH--
zF`a;hzL2Yf12qff^Z(Ww*D3EZU%8tIxV(=pGcu2+>vT^QO2?Jpd@cIj!DJY&rJxzi
zoc-`iNomk!l4^^Wl_slw7dRc6kPR4QG{|3RX=$xaj&@BEZjCcg``=QSX$iW$w>m}d
zK>)i7+(pdJNZdN}=TTa6r_`hHP#c~~@d$)4a=MzSiAhRs8w=RR9sj0(wc7MCGp5ZgV#klSa6{O93`Q)qVtrm;)4qvYu=R=j)NetS5`J*3i
zr2ie;Wx&lU6R((0;Tuy#Ys&<^Zza-IJNW0fWxfu#Q
z9^mq;NL+dJ_%X%iC1u@;9J!}xPY8Q{`-+_eo^i%6gu~#DcUY{ZrLl1ojG76j4~0G&
zp<+*4ub(FYDZW#K5_z6_nii{HwknM8fGro$)YGtohYu~jk%~XYS7`Jwi^&go&p~3z
zoS#Pfd(-bfNcc)V78U&mS#8DE@kuIJ5bl8&$Ow(@;?5^G3X&B0f&W(~9xu;7Sd^f2
zk0|!tI3RSx8yXs{3=LCi3k#L+VG3RrEhT)kSZ53WT_>B}#y{wYurj&AGC@CV$3O(Z
zlM=Kw(qV$tjT`o#1Co#^0|Ntw#)gI~?9v{#tGzF;*B+dldPG|Hm{dO`g-RdzPb(k&
zYY-(=3`U~rn^ZnZ{L~+#d+^BdGND5Zp)j(mFN4-QYx7p=ZrTFGIdn5Fl7sH%WlHfY
zVX!dP9zgXSG6LW)+{~o7sQB>UBoJs&)FzK7adrlJ=CG2r5zpHzEb)QW5K-9B;IDP(
zP6yrb-s;P;3Rs+#z?U_L+XQ1>6h9@^E9fTwz1(f4SGVgB;
zjRz92K8Qdg*91BQ|43^YJeHlq0QLy!g-qGgZp7y)mdMZ2n)_a43!3+~j#Abu
zMxwyV#{pz#slPtrT2D<<<32WVV0=xvTxFO4HA)3Wpn|wDLXJ9UBRFo1fn<3?Y6%
zH#INc_eY;-OqQf1zTGmkP2th`AfEqV_=Tuu)DOt3cwO}~lShkiyYwPH`<$i762EndaW;KQTDme{{A&5IKNwzlGYGYikFm}A60|$(#
z-e{qXm|Y!r1QwXHVl>N>&FXJP9u@I8<#CW)`x^gA>|x=*cYak^hDdxA0@KG@Rf|R{
z^ox;fogT>R;8RC5e{B6zUi(r4O`?V=z#Enet(^~=4I$R%vq4|x?eOlkm0*%CKUd2%
zCU%*|Xe<$RX$+`$4D;z~y(80ZqglMTO-Sw84^2Mo{l+T*k!0{`gw<63?w#Wk*f-C2
z@|b+ec4|A68$DAmfIZPOcMt0NnR>w$6CKmFhh!%O^tS(=*
z3lGj!tNQbE*N0DZQp~&qEKMHf;#!Nq_VSO7jopnF=q~h#vXcwlhFi^2b<+8NG%$d(%sBMPjTvAYQm$y4*
z!z5PsyR*BM2@1h5j*B5!iHUzoLux@&t^QtSCQ!`0$n8J>m~p53FkPz_o0q5PCB>2f
zG^fgp{NfLRcYhZ=$!;l!K}s5FLaUj-r70n)jBK-dmFi(WVk@zm#2JJ9VmmAqocd;N
zC&(P2d2K+x`T)nA@y1twjQC4;}bH@Dc0M8EI@uV>7f`H98`v^Wb4(x
zi`ynqVdZ2mO5U@u+omAiT?@_kR+pWaji*<6Lqm2&Aj)5Ol#`oR74@+`guJjJcyrU7
z+P!J`D(cd~>`oQ7DWF1!c?a=<1pyHO90_V`W6c
zKFe@%v&5~Fm_V0~o@wyFi|g9L^$~&Ua8CaCg;tyZ&`bgyf8}B+UWCc=t5Z~V4~45G
zx!-z1h<{rA0p<|;m>)|6EL|#|xz?@-GtQHQ!Gy{^-D~~rp%vS970>CrQq~OBO>MI-
z!hg*?Fd3@b#RSe|2(O4iHA3p^dMO?Y#z~NHZNg&IisHIVl}h)nA;kT{O>M#ZIo+(g
zwdh-WSM-PE_E|#PIL>v6Yt6$5Ftb6hV#G0s6VNO=5LmZiAOdPsyXD!D(ZK6l^iXBf
zICy7XSaP8BvEesctv+SUOQiIFug2kQ-vE?M`-7@a-XHts+&HNJl={Y#d>=-lZnDV-
z7@yCDI_$6#aj-H$3-Iw_;A!8v63bO?Tc@X|mk6VbEJ0rZR~@$ZSQ|-Q!d#3Qcj)OG
zS49i-E4^WSHsE-6dU9|$6ci8cw7O9O3ZgIvC#TTChq0K22PR(`SDz)in9_DmT2%P9
zYWro^LPOAB3u+bSeQtxVL=ZJ3~;K3%~wo+Cb-(W|C;=A$f?N~}ws>;~vW~Pn*$Btfis6x-k
z4zUw%Yyt^y6sm)|W@fSHzI2v&yvXMqB)MFu_6F~jO7{hoLjv$qLRG8A{Uf9%FnuXb
z#mmcUw)uDs3TC7(b#p}K-s6S@pB1h3`pzWX2*tj=GrURDv=?3TRcLd&;LaJDQiSEE
zS<3lg}4v}E8Y%~@Lt=C@zgpu4o?Ds3VC18
z%95J!T;;Ol)xPAFf4;$_3bX+U2P&=C?V!!=s#=mxssF
z-3A6Im2au=9V?T)x}n9Xw+@d3dOgf(W?G>tq}UUyP`v8?gCuheUm-0yS@Rp8tq4Oh
zqbW5ZNOBZ7I7%BMpK6p|Q&65~3?-zAH;KR$Fh=5`FgR6lT{3G>dqDzWm^Unmzol#h!~An1DM{l_If!?XGPYaSSN`(
ziXNwTA_|31dUsLzg$S$=;#nC#d`EOw$2KX)sJDd5K6n^YcoF^uLCmI~3RkK8KS~6I
zOG5Qk+3>eQtRMvfsgUl1XNe*~UgY2Ic-EDtFN<`62-eS(?~4~85Hn8)kqZ|W*Ya4t
zQYWn<2KnvLhbY8`BBIe|cdDtW2@JI_#7sFuX$X~d!*0$&*fuLg34SsjfW}!{&lS+!
zXgN=I{5GuEl)M!uVXD$A31_q>&c(1;XM|Xn)_rYS8ty70Z~EO9FqCkQk%tGH!HZAM
zYpG5(&?zB;m~rDU;La9}AW7(SXx?pr0i9FsGBTJzh6L&th!Wvh%Y!MHmrVvVF~2V8
z(oW#}y#;K~m&NV#^!ruOXat|ZCst5+LD5|JNs|SB-gHkH67@l=;Qs?i83RMZyu!i@
zAfYH)D&ES-J8&>S-+sDh3B)hK!U2l`%s9N_Zw2O3U3Ocew9V@#r@;M0##mQ3y
zvlWPJK4IZAe3F!@7voM4ttx{n4OEuD5|f4&nMa(MD7ecIw?}(Ls7YQpMI>;Lzyw*U
zVhUNGzprRouORsG1g??fBNQ5tD3#qR{k#V(Vc8s62>8;8aDzAa8o~#DEmcxxDHck=
sASRSV!bH4E0kWJSdeVV=Qm40hTpyE?ZN2n?>B0z
+
+ TinyGo - A Go Compiler For Small Places
+
+
+
+ TinyGo - A Go Compiler For Small Places
+
+
+
diff --git a/examples/net/webstatic-httphi/main.go b/examples/net/webstatic-httphi/main.go
new file mode 100644
index 000000000..cd45b32de
--- /dev/null
+++ b/examples/net/webstatic-httphi/main.go
@@ -0,0 +1,123 @@
+// This example is the webstatic example using the heapless httphi router
+// from github.com/soypat/lneto instead of "net/http".
+
+//go:build ninafw || wioterminal
+
+package main
+
+import (
+ "embed"
+ "log"
+ "net"
+ "path"
+ "time"
+
+ "github.com/soypat/lneto/http/httphi"
+
+ "tinygo.org/x/drivers/netlink"
+ "tinygo.org/x/drivers/netlink/probe"
+)
+
+var (
+ ssid string
+ pass string
+ port string = ":80"
+)
+
+const (
+ numWorkers = 2
+ memoryPerConn = 1024
+)
+
+//go:embed index.html main.go images
+var fs embed.FS
+
+func main() {
+ // wait a bit for console
+ time.Sleep(2 * time.Second)
+
+ link, _ := probe.Probe()
+
+ err := link.NetConnect(&netlink.ConnectParams{
+ Ssid: ssid,
+ Passphrase: pass,
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var mux httphi.MuxSlice
+ mux.Handle("GET /", serveFile)
+
+ var router httphi.Router
+ cfg := httphi.DefaultRouterConfig(numWorkers, memoryPerConn, mux.MaxPathValues())
+ err = router.Configure(&mux, cfg)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ listener, err := net.Listen("tcp", port)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ println("accept:", err.Error())
+ time.Sleep(time.Second)
+ continue
+ }
+ if err := router.Handle(conn); err != nil {
+ conn.Close()
+ }
+ }
+}
+
+func serveFile(ex *httphi.Exchange) {
+ name := string(ex.RequestPath()[1:])
+ if name == "" {
+ name = "index.html"
+ }
+
+ f, err := fs.Open(name)
+ if err != nil {
+ ex.RespondString(httphi.StatusNotFound, "text/plain", "404 page not found")
+ return
+ }
+ defer f.Close()
+
+ info, err := f.Stat()
+ if err != nil || info.IsDir() {
+ ex.RespondString(httphi.StatusNotFound, "text/plain", "404 page not found")
+ return
+ }
+
+ ex.StageHeader("Content-Type", contentType(name))
+ ex.StageHeaderInt("Content-Length", info.Size())
+ ex.StageHeader("Connection", "close")
+
+ var buf [512]byte
+ for {
+ n, err := f.Read(buf[:])
+ if n > 0 {
+ if _, werr := ex.WriteBody(buf[:n]); werr != nil {
+ return
+ }
+ }
+ if err != nil {
+ return
+ }
+ }
+}
+
+func contentType(name string) string {
+ switch path.Ext(name) {
+ case ".html":
+ return "text/html; charset=utf-8"
+ case ".png":
+ return "image/png"
+ default:
+ return "text/plain; charset=utf-8"
+ }
+}
diff --git a/go.mod b/go.mod
index 432c77ae0..9ce9b8054 100644
--- a/go.mod
+++ b/go.mod
@@ -1,14 +1,13 @@
module tinygo.org/x/drivers
-go 1.22.1
-
-toolchain go1.23.1
+go 1.24
require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/frankban/quicktest v1.10.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/orsinium-labs/tinymath v1.1.0
+ github.com/soypat/lneto v0.4.0
github.com/soypat/natiu-mqtt v0.5.1
github.com/tinygo-org/pio v0.3.0
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
diff --git a/go.sum b/go.sum
index 673d984d8..8a889e8e4 100644
--- a/go.sum
+++ b/go.sum
@@ -15,6 +15,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/orsinium-labs/tinymath v1.1.0 h1:KomdsyLHB7vE3f1nRAJF2dyf1m/gnM2HxfTeV1vS5UA=
github.com/orsinium-labs/tinymath v1.1.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=
+github.com/soypat/lneto v0.4.0 h1:oBTcMnhEIBERXmAfwK4uDpItRaF7RiT1K2pljFVxtQc=
+github.com/soypat/lneto v0.4.0/go.mod h1:Be5PjwoYukvHFiUXxpYi8+ppH2F/gw/vjGBvFdv+Ti8=
github.com/soypat/natiu-mqtt v0.5.1 h1:rwaDmlvjzD2+3MCOjMZc4QEkDkNwDzbct2TJbpz+TPc=
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
github.com/tinygo-org/pio v0.3.0 h1:opEnOtw58KGB4RJD3/n/Rd0/djYGX3DeJiXLI6y/yDI=
diff --git a/smoketest.go b/smoketest.go
index 174526986..6219308ec 100644
--- a/smoketest.go
+++ b/smoketest.go
@@ -97,6 +97,7 @@ func runSmokeTest(filename string) error {
_ = flagSet.String("size", "", "")
_ = flagSet.String("o", "", "")
_ = flagSet.String("stack-size", "", "")
+ _ = flagSet.String("tags", "", "")
targetFlag := flagSet.String("target", "", "")
err = flagSet.Parse(fields[2:])
if err != nil {
diff --git a/smoketest.sh b/smoketest.sh
index b9f2c4995..8fdb530c8 100755
--- a/smoketest.sh
+++ b/smoketest.sh
@@ -176,11 +176,14 @@ tinygo build -size short -o ./build/test.hex -target=arduino-nano33 -stack-size
tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/websocket/dial/
tinygo build -size short -o ./build/test.hex -target=metro-m4-airlift -stack-size 8kb ./examples/net/socket/
tinygo build -size short -o ./build/test.hex -target=matrixportal-m4 -stack-size 8kb ./examples/net/webstatic/
+tinygo build -size short -o ./build/test.hex -tags=noslog -target=matrixportal-m4 -stack-size 8kb ./examples/net/webstatic-httphi/
+tinygo build -size short -o ./build/test.hex -tags=noslog -target=arduino-nano33 -stack-size 4kb ./examples/net/webserver-httphi/
tinygo build -size short -o ./build/test.hex -target=arduino-mkrwifi1010 -stack-size 8kb ./examples/net/tlsclient/
tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/mqttclient/natiu/
# network examples (rtl8720dn)
tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/webclient/
tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/webserver/
+tinygo build -size short -o ./build/test.hex -tags=noslog -target=wioterminal -stack-size 8kb ./examples/net/webserver-httphi/
tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/mqttclient/paho/
# network examples (comboat)
tinygo build -size short -o ./build/test.hex -target=elecrow-rp2040 -stack-size 8kb ./examples/net/tlsclient/