Files
drivers/rtl8720dn/http.go
T
2021-07-24 09:44:17 +02:00

237 lines
4.9 KiB
Go

package rtl8720dn
import (
"bufio"
"bytes"
"fmt"
"io"
"time"
"tinygo.org/x/drivers/net/http"
)
func (rtl *RTL8720DN) setupHTTPServer() error {
_, err := rtl.Rpc_lwip_close(-1)
if err != nil {
return err
}
_, err = rtl.Rpc_lwip_socket(0x00000002, 0x00000001, 0x00000000)
if err != nil {
return err
}
name := []byte{0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x42, 0x00, 0x00, 0xC7, 0x61, 0x01, 0x00}
_, err = rtl.Rpc_lwip_bind(0, name, uint32(len(name)))
if err != nil {
return err
}
_, err = rtl.Rpc_lwip_listen(0, 4)
if err != nil {
return err
}
_, err = rtl.Rpc_lwip_fcntl(0, 4, 1)
if err != nil {
return err
}
return nil
}
func (rtl *RTL8720DN) accept() (bool, error) {
addr := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xD7, 0x00, 0x20, 0x00, 0xD8, 0x00, 0x20}
length := uint32(len(addr))
ret, err := rtl.Rpc_lwip_accept(0, addr, &length)
if err != nil {
return false, err
}
return ret == 1, nil
}
func (rtl *RTL8720DN) handleHTTP() error {
socket := int32(1)
optval := []byte{0x01, 0x00, 0x00, 0x00}
_, err := rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 8, optval, uint32(len(optval)))
if err != nil {
return nil
}
_, err = rtl.Rpc_lwip_setsockopt(socket, 6, 1, optval, uint32(len(optval)))
if err != nil {
return nil
}
buf := make([]byte, 4096)
for {
_, err = rtl.Rpc_lwip_recv(socket, &buf, uint32(len(buf)), 8, 0)
if err != nil {
return nil
}
if len(buf) > 0 {
break
}
_, err = rtl.Rpc_lwip_errno()
if err != nil {
return nil
}
time.Sleep(100 * time.Millisecond)
}
buf2 := make([]byte, 4096)
result, err := rtl.Rpc_lwip_recv(socket, &buf2, uint32(len(buf2)), 8, 0)
if err != nil {
return nil
}
if result != -1 && result != 0 {
return fmt.Errorf("Rpc_lwip_recv error")
}
result, err = rtl.Rpc_lwip_errno()
if err != nil {
return nil
}
if result != 11 {
return fmt.Errorf("Rpc_lwip_errno error")
}
b := bufio.NewReader(bytes.NewReader(buf))
req, err := http.ReadRequest(b)
if err != nil {
return err
}
if rtl.debug {
fmt.Printf("%s %s %s\r\n", req.Method, req.RequestURI, req.Proto)
}
pos := bytes.Index(buf, []byte("\r\n\r\n"))
if pos > 0 {
body := bytes.NewReader(buf[pos+4:])
req.Body = io.NopCloser(body)
}
handler, _ := http.DefaultServeMux.Handler(req)
rwx := responseWriter{
header: http.Header{},
statusCode: 200,
}
rwx.header.Add(`Content-Type`, `text/html; charset=UTF-8`)
rwx.header.Add(`Connection`, `close`)
handler.ServeHTTP(&rwx, req)
rwx.header.Add(`Content-Length`, fmt.Sprintf("%d", len(rwx.Buf)))
optval = []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xA5, 0xA5, 0xA5}
_, err = rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 0x1006, optval, uint32(len(optval)))
if err != nil {
return nil
}
optval = []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xA5, 0xA5, 0xA5}
_, err = rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 0x1005, optval, uint32(len(optval)))
if err != nil {
return nil
}
maxfdp1 := int32(2)
writeset := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
timeout := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x0A, 0x00, 0x00, 0x00}
_, err = rtl.Rpc_lwip_select(maxfdp1, []byte{}, writeset, []byte{}, timeout)
if err != nil {
return nil
}
msg := rwx.Buf
hb := bytes.Buffer{}
err = rwx.header.Write(&hb)
if err != nil {
return err
}
data := []byte(fmt.Sprintf("HTTP/1.1 %d OK\n", rwx.statusCode))
data = append(data, hb.Bytes()...)
data = append(data, byte('\n'))
_, err = rtl.Rpc_lwip_send(socket, data, 8)
if err != nil {
return nil
}
if len(msg) > 0 {
timeout = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x54, 0x00, 0x00, 0x00}
_, err = rtl.Rpc_lwip_select(maxfdp1, []byte{}, writeset, []byte{}, timeout)
if err != nil {
return nil
}
_, err = rtl.Rpc_lwip_send(socket, msg, 8)
if err != nil {
return nil
}
}
for i := 0; i < 4; i++ {
buf := make([]byte, 4096)
_, err = rtl.Rpc_lwip_recv(socket, &buf, uint32(len(buf)), 8, 0)
if err != nil {
return nil
}
_, err = rtl.Rpc_lwip_errno()
if err != nil {
return nil
}
}
_, err = rtl.Rpc_lwip_close(socket)
if err != nil {
return nil
}
return nil
}
func (rtl *RTL8720DN) ListenAndServe(addr string, handler http.Handler) error {
err := rtl.setupHTTPServer()
if err != nil {
return err
}
for {
connected, err := rtl.accept()
if err != nil {
return err
}
if connected {
err := rtl.handleHTTP()
if err != nil {
return err
}
}
time.Sleep(100 * time.Millisecond)
}
}
type responseWriter struct {
Buf []byte
header http.Header
statusCode int
}
func (r *responseWriter) Header() http.Header {
return r.header
}
func (r *responseWriter) Write(b []byte) (int, error) {
r.Buf = append(r.Buf, b...)
return len(b), nil
}
func (r *responseWriter) WriteHeader(statusCode int) {
r.statusCode = statusCode
}