From 6a4cd9d8e72c7db7ab79f73b0a3b6b13defe1082 Mon Sep 17 00:00:00 2001
From: sago35
Date: Mon, 5 Jul 2021 18:21:33 +0900
Subject: [PATCH] rtl8720dn: add examples/rtl8720dn/webserver
---
Makefile | 2 +
examples/rtl8720dn/webserver/main.go | 162 ++++++
examples/rtl8720dn/webserver/wioterminal.go | 73 +++
go.mod | 1 +
go.sum | 8 +
net/http/driver.go | 15 +
net/http/header.go | 259 +++++++++
net/http/http.go | 162 ++++++
net/http/request.go | 608 ++++++++++++++++++++
net/http/response.go | 112 ++++
net/http/server.go | 581 +++++++++++++++++++
net/http/status.go | 152 +++++
net/http/transefer.go | 34 ++
rtl8720dn/http.go | 236 ++++++++
rtl8720dn/netdriver.go | 17 +-
rtl8720dn/rpc.go | 397 +++++++------
rtl8720dn/wifi.go | 2 +-
17 files changed, 2650 insertions(+), 171 deletions(-)
create mode 100644 examples/rtl8720dn/webserver/main.go
create mode 100644 examples/rtl8720dn/webserver/wioterminal.go
create mode 100644 net/http/driver.go
create mode 100644 net/http/header.go
create mode 100644 net/http/http.go
create mode 100644 net/http/request.go
create mode 100644 net/http/response.go
create mode 100644 net/http/server.go
create mode 100644 net/http/status.go
create mode 100644 net/http/transefer.go
create mode 100644 rtl8720dn/http.go
diff --git a/Makefile b/Makefile
index b42d834..f3169a4 100644
--- a/Makefile
+++ b/Makefile
@@ -199,6 +199,8 @@ endif
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webclient/
@md5sum ./build/test.hex
+ tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webserver/
+ @md5sum ./build/test.hex
DRIVERS = $(wildcard */)
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
diff --git a/examples/rtl8720dn/webserver/main.go b/examples/rtl8720dn/webserver/main.go
new file mode 100644
index 0000000..7c9adaf
--- /dev/null
+++ b/examples/rtl8720dn/webserver/main.go
@@ -0,0 +1,162 @@
+package main
+
+import (
+ "fmt"
+ "machine"
+ "strconv"
+ "time"
+
+ "tinygo.org/x/drivers/net/http"
+)
+
+// You can override the setting with the init() in another source code.
+// func init() {
+// ssid = "your-ssid"
+// password = "your-password"
+// debug = true
+// }
+
+var (
+ ssid string
+ password string
+ debug = false
+)
+
+var led = machine.LED
+var backlight = machine.LCD_BACKLIGHT
+
+func main() {
+ led.Configure(machine.PinConfig{Mode: machine.PinOutput})
+ backlight.Configure(machine.PinConfig{Mode: machine.PinOutput})
+
+ err := run()
+ for err != nil {
+ fmt.Printf("error: %s\r\n", err.Error())
+ time.Sleep(5 * time.Second)
+ }
+}
+
+func run() error {
+ rtl, err := setupRTL8720DN()
+ if err != nil {
+ return err
+ }
+ http.UseDriver(rtl)
+
+ err = rtl.ConnectToAP(ssid, password)
+ if err != nil {
+ return err
+ }
+
+ ip, subnet, gateway, err := rtl.GetIP()
+ if err != nil {
+ return err
+ }
+ fmt.Printf("IP Address : %s\r\n", ip)
+ fmt.Printf("Mask : %s\r\n", subnet)
+ fmt.Printf("Gateway : %s\r\n", gateway)
+
+ http.HandleFunc("/", root)
+ http.HandleFunc("/hello", hello)
+ http.HandleFunc("/cnt", cnt)
+ http.HandleFunc("/6", sixlines)
+ http.HandleFunc("/off", LED_OFF)
+ http.HandleFunc("/on", LED_ON)
+ if err := http.ListenAndServe(":80", nil); err != nil {
+ message(err.Error())
+ }
+ return nil
+}
+
+func root(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `
+
+
+ TinyGo HTTP Server
+
+
+
+ TinyGo HTTP Server
+ /hello
+ /6
+
+
+ LED
+ /on
+ /off
+
+
+
+
+ /cnt
+ cnt:
+ incrCnt()
+
+
+
+
+ `)
+}
+
+func sixlines(w http.ResponseWriter, r *http.Request) {
+ // https://fukuno.jig.jp/3267
+ fmt.Fprint(w, ``)
+}
+
+func LED_ON(w http.ResponseWriter, r *http.Request) {
+ led.High()
+ backlight.High()
+ w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
+ fmt.Fprintf(w, "led.High()")
+}
+
+func LED_OFF(w http.ResponseWriter, r *http.Request) {
+ led.Low()
+ backlight.Low()
+ w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
+ fmt.Fprintf(w, "led.Low()")
+}
+
+func hello(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
+ fmt.Fprintf(w, "hello")
+}
+
+var counter int
+
+func cnt(w http.ResponseWriter, r *http.Request) {
+ r.ParseForm()
+ if r.Method == "POST" {
+ c := r.Form.Get("cnt")
+ if c != "" {
+ i64, _ := strconv.ParseInt(c, 0, 0)
+ counter = int(i64)
+ }
+ }
+
+ w.Header().Set(`Content-Type`, `application/json`)
+ fmt.Fprintf(w, `{"cnt": %d}`, counter)
+}
+
+func message(msg string) {
+ println(msg, "\r")
+}
diff --git a/examples/rtl8720dn/webserver/wioterminal.go b/examples/rtl8720dn/webserver/wioterminal.go
new file mode 100644
index 0000000..9da045f
--- /dev/null
+++ b/examples/rtl8720dn/webserver/wioterminal.go
@@ -0,0 +1,73 @@
+// +build wioterminal
+
+package main
+
+import (
+ "device/sam"
+ "machine"
+ "runtime/interrupt"
+ "time"
+
+ "tinygo.org/x/drivers/rtl8720dn"
+)
+
+var (
+ uart UARTx
+)
+
+func handleInterrupt(interrupt.Interrupt) {
+ // should reset IRQ
+ uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
+ uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
+}
+
+func setupRTL8720DN() (*rtl8720dn.RTL8720DN, error) {
+ machine.RTL8720D_CHIP_PU.Configure(machine.PinConfig{Mode: machine.PinOutput})
+ machine.RTL8720D_CHIP_PU.Low()
+ time.Sleep(100 * time.Millisecond)
+ machine.RTL8720D_CHIP_PU.High()
+ time.Sleep(1000 * time.Millisecond)
+ if debug {
+ waitSerial()
+ }
+
+ uart = UARTx{
+ UART: &machine.UART{
+ Buffer: machine.NewRingBuffer(),
+ Bus: sam.SERCOM0_USART_INT,
+ SERCOM: 0,
+ },
+ }
+
+ uart.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, handleInterrupt)
+ uart.Configure(machine.UARTConfig{TX: machine.PB24, RX: machine.PC24, BaudRate: 614400})
+
+ rtl := rtl8720dn.New(uart)
+ rtl.Debug(debug)
+
+ _, err := rtl.Rpc_tcpip_adapter_init()
+ if err != nil {
+ return nil, err
+ }
+
+ return rtl, nil
+}
+
+// Wait for user to open serial console
+func waitSerial() {
+ for !machine.Serial.DTR() {
+ time.Sleep(100 * time.Millisecond)
+ }
+}
+
+type UARTx struct {
+ *machine.UART
+}
+
+func (u UARTx) Read(p []byte) (n int, err error) {
+ if u.Buffered() == 0 {
+ time.Sleep(1 * time.Millisecond)
+ return 0, nil
+ }
+ return u.UART.Read(p)
+}
diff --git a/go.mod b/go.mod
index a3bff76..f6dcef2 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.15
require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/frankban/quicktest v1.10.2
+ golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
tinygo.org/x/tinyfont v0.2.1
tinygo.org/x/tinyfs v0.1.0
tinygo.org/x/tinyterm v0.1.0
diff --git a/go.sum b/go.sum
index c28f71e..6be0cea 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
+golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
+golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
tinygo.org/x/drivers v0.14.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
diff --git a/net/http/driver.go b/net/http/driver.go
new file mode 100644
index 0000000..d125939
--- /dev/null
+++ b/net/http/driver.go
@@ -0,0 +1,15 @@
+package http
+
+type DeviceDriver interface {
+ ListenAndServe(addr string, handler Handler) error
+}
+
+var ActiveDevice DeviceDriver
+
+func UseDriver(driver DeviceDriver) {
+ // TODO: rethink and refactor this
+ if ActiveDevice != nil {
+ panic("net.ActiveDevice is already set")
+ }
+ ActiveDevice = driver
+}
diff --git a/net/http/header.go b/net/http/header.go
new file mode 100644
index 0000000..0cc0e55
--- /dev/null
+++ b/net/http/header.go
@@ -0,0 +1,259 @@
+package http
+
+import (
+ "io"
+ "net/http/httptrace"
+ "net/textproto"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+)
+
+// A Header represents the key-value pairs in an HTTP header.
+//
+// The keys should be in canonical form, as returned by
+// CanonicalHeaderKey.
+type Header map[string][]string
+
+// Add adds the key, value pair to the header.
+// It appends to any existing values associated with key.
+// The key is case insensitive; it is canonicalized by
+// CanonicalHeaderKey.
+func (h Header) Add(key, value string) {
+ textproto.MIMEHeader(h).Add(key, value)
+}
+
+// Set sets the header entries associated with key to the
+// single element value. It replaces any existing values
+// associated with key. The key is case insensitive; it is
+// canonicalized by textproto.CanonicalMIMEHeaderKey.
+// To use non-canonical keys, assign to the map directly.
+func (h Header) Set(key, value string) {
+ textproto.MIMEHeader(h).Set(key, value)
+}
+
+// Get gets the first value associated with the given key. If
+// there are no values associated with the key, Get returns "".
+// It is case insensitive; textproto.CanonicalMIMEHeaderKey is
+// used to canonicalize the provided key. To use non-canonical keys,
+// access the map directly.
+func (h Header) Get(key string) string {
+ return textproto.MIMEHeader(h).Get(key)
+}
+
+// Values returns all values associated with the given key.
+// It is case insensitive; textproto.CanonicalMIMEHeaderKey is
+// used to canonicalize the provided key. To use non-canonical
+// keys, access the map directly.
+// The returned slice is not a copy.
+func (h Header) Values(key string) []string {
+ return textproto.MIMEHeader(h).Values(key)
+}
+
+// get is like Get, but key must already be in CanonicalHeaderKey form.
+func (h Header) get(key string) string {
+ if v := h[key]; len(v) > 0 {
+ return v[0]
+ }
+ return ""
+}
+
+// has reports whether h has the provided key defined, even if it's
+// set to 0-length slice.
+func (h Header) has(key string) bool {
+ _, ok := h[key]
+ return ok
+}
+
+// Del deletes the values associated with key.
+// The key is case insensitive; it is canonicalized by
+// CanonicalHeaderKey.
+func (h Header) Del(key string) {
+ textproto.MIMEHeader(h).Del(key)
+}
+
+// Write writes a header in wire format.
+func (h Header) Write(w io.Writer) error {
+ return h.write(w, nil)
+}
+
+func (h Header) write(w io.Writer, trace *httptrace.ClientTrace) error {
+ return h.writeSubset(w, nil, trace)
+}
+
+// Clone returns a copy of h or nil if h is nil.
+func (h Header) Clone() Header {
+ if h == nil {
+ return nil
+ }
+
+ // Find total number of values.
+ nv := 0
+ for _, vv := range h {
+ nv += len(vv)
+ }
+ sv := make([]string, nv) // shared backing array for headers' values
+ h2 := make(Header, len(h))
+ for k, vv := range h {
+ n := copy(sv, vv)
+ h2[k] = sv[:n:n]
+ sv = sv[n:]
+ }
+ return h2
+}
+
+var timeFormats = []string{
+ TimeFormat,
+ time.RFC850,
+ time.ANSIC,
+}
+
+// ParseTime parses a time header (such as the Date: header),
+// trying each of the three formats allowed by HTTP/1.1:
+// TimeFormat, time.RFC850, and time.ANSIC.
+func ParseTime(text string) (t time.Time, err error) {
+ for _, layout := range timeFormats {
+ t, err = time.Parse(layout, text)
+ if err == nil {
+ return
+ }
+ }
+ return
+}
+
+var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
+
+// stringWriter implements WriteString on a Writer.
+type stringWriter struct {
+ w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (n int, err error) {
+ return w.w.Write([]byte(s))
+}
+
+type keyValues struct {
+ key string
+ values []string
+}
+
+// A headerSorter implements sort.Interface by sorting a []keyValues
+// by key. It's used as a pointer, so it can fit in a sort.Interface
+// interface value without allocation.
+type headerSorter struct {
+ kvs []keyValues
+}
+
+func (s *headerSorter) Len() int { return len(s.kvs) }
+func (s *headerSorter) Swap(i, j int) { s.kvs[i], s.kvs[j] = s.kvs[j], s.kvs[i] }
+func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key }
+
+var headerSorterPool = sync.Pool{
+ New: func() interface{} { return new(headerSorter) },
+}
+
+// sortedKeyValues returns h's keys sorted in the returned kvs
+// slice. The headerSorter used to sort is also returned, for possible
+// return to headerSorterCache.
+func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) {
+ hs = headerSorterPool.Get().(*headerSorter)
+ if cap(hs.kvs) < len(h) {
+ hs.kvs = make([]keyValues, 0, len(h))
+ }
+ kvs = hs.kvs[:0]
+ for k, vv := range h {
+ if !exclude[k] {
+ kvs = append(kvs, keyValues{k, vv})
+ }
+ }
+ hs.kvs = kvs
+ sort.Sort(hs)
+ return kvs, hs
+}
+
+// WriteSubset writes a header in wire format.
+// If exclude is not nil, keys where exclude[key] == true are not written.
+// Keys are not canonicalized before checking the exclude map.
+func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
+ return h.writeSubset(w, exclude, nil)
+}
+
+func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptrace.ClientTrace) error {
+ ws, ok := w.(io.StringWriter)
+ if !ok {
+ ws = stringWriter{w}
+ }
+ kvs, sorter := h.sortedKeyValues(exclude)
+ var formattedVals []string
+ for _, kv := range kvs {
+ for _, v := range kv.values {
+ v = headerNewlineToSpace.Replace(v)
+ v = textproto.TrimString(v)
+ for _, s := range []string{kv.key, ": ", v, "\r\n"} {
+ if _, err := ws.WriteString(s); err != nil {
+ headerSorterPool.Put(sorter)
+ return err
+ }
+ }
+ if trace != nil && trace.WroteHeaderField != nil {
+ formattedVals = append(formattedVals, v)
+ }
+ }
+ if trace != nil && trace.WroteHeaderField != nil {
+ trace.WroteHeaderField(kv.key, formattedVals)
+ formattedVals = nil
+ }
+ }
+ headerSorterPool.Put(sorter)
+ return nil
+}
+
+// CanonicalHeaderKey returns the canonical format of the
+// header key s. The canonicalization converts the first
+// letter and any letter following a hyphen to upper case;
+// the rest are converted to lowercase. For example, the
+// canonical key for "accept-encoding" is "Accept-Encoding".
+// If s contains a space or invalid header field bytes, it is
+// returned without modifications.
+func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
+
+// hasToken reports whether token appears with v, ASCII
+// case-insensitive, with space or comma boundaries.
+// token must be all lowercase.
+// v may contain mixed cased.
+func hasToken(v, token string) bool {
+ if len(token) > len(v) || token == "" {
+ return false
+ }
+ if v == token {
+ return true
+ }
+ for sp := 0; sp <= len(v)-len(token); sp++ {
+ // Check that first character is good.
+ // The token is ASCII, so checking only a single byte
+ // is sufficient. We skip this potential starting
+ // position if both the first byte and its potential
+ // ASCII uppercase equivalent (b|0x20) don't match.
+ // False positives ('^' => '~') are caught by EqualFold.
+ if b := v[sp]; b != token[0] && b|0x20 != token[0] {
+ continue
+ }
+ // Check that start pos is on a valid token boundary.
+ if sp > 0 && !isTokenBoundary(v[sp-1]) {
+ continue
+ }
+ // Check that end pos is on a valid token boundary.
+ if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
+ continue
+ }
+ if strings.EqualFold(v[sp:sp+len(token)], token) {
+ return true
+ }
+ }
+ return false
+}
+
+func isTokenBoundary(b byte) bool {
+ return b == ' ' || b == ',' || b == '\t'
+}
diff --git a/net/http/http.go b/net/http/http.go
new file mode 100644
index 0000000..9268698
--- /dev/null
+++ b/net/http/http.go
@@ -0,0 +1,162 @@
+package http
+
+import (
+ "io"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+
+ "golang.org/x/net/http/httpguts"
+)
+
+// incomparable is a zero-width, non-comparable type. Adding it to a struct
+// makes that struct also non-comparable, and generally doesn't add
+// any size (as long as it's first).
+type incomparable [0]func()
+
+// maxInt64 is the effective "infinite" value for the Server and
+// Transport's byte-limiting readers.
+const maxInt64 = 1<<63 - 1
+
+// aLongTimeAgo is a non-zero time, far in the past, used for
+// immediate cancellation of network operations.
+var aLongTimeAgo = time.Unix(1, 0)
+
+// omitBundledHTTP2 is set by omithttp2.go when the nethttpomithttp2
+// build tag is set. That means h2_bundle.go isn't compiled in and we
+// shouldn't try to use it.
+var omitBundledHTTP2 bool
+
+// TODO(bradfitz): move common stuff here. The other files have accumulated
+// generic http stuff in random places.
+
+// contextKey is a value for use with context.WithValue. It's used as
+// a pointer so it fits in an interface{} without allocation.
+type contextKey struct {
+ name string
+}
+
+func (k *contextKey) String() string { return "net/http context value " + k.name }
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+// removeEmptyPort strips the empty port in ":port" to ""
+// as mandated by RFC 3986 Section 6.2.3.
+func removeEmptyPort(host string) string {
+ if hasPort(host) {
+ return strings.TrimSuffix(host, ":")
+ }
+ return host
+}
+
+func isNotToken(r rune) bool {
+ return !httpguts.IsTokenRune(r)
+}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+// stringContainsCTLByte reports whether s contains any ASCII control character.
+func stringContainsCTLByte(s string) bool {
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if b < ' ' || b == 0x7f {
+ return true
+ }
+ }
+ return false
+}
+
+func hexEscapeNonASCII(s string) string {
+ newLen := 0
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ newLen += 3
+ } else {
+ newLen++
+ }
+ }
+ if newLen == len(s) {
+ return s
+ }
+ b := make([]byte, 0, newLen)
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ b = append(b, '%')
+ b = strconv.AppendInt(b, int64(s[i]), 16)
+ } else {
+ b = append(b, s[i])
+ }
+ }
+ return string(b)
+}
+
+// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
+// and Close always returns nil. It can be used in an outgoing client
+// request to explicitly signal that a request has zero bytes.
+// An alternative, however, is to simply set Request.Body to nil.
+var NoBody = noBody{}
+
+type noBody struct{}
+
+func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
+func (noBody) Close() error { return nil }
+func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
+
+var (
+ // verify that an io.Copy from NoBody won't require a buffer:
+ _ io.WriterTo = NoBody
+ _ io.ReadCloser = NoBody
+)
+
+// PushOptions describes options for Pusher.Push.
+type PushOptions struct {
+ // Method specifies the HTTP method for the promised request.
+ // If set, it must be "GET" or "HEAD". Empty means "GET".
+ Method string
+
+ // Header specifies additional promised request headers. This cannot
+ // include HTTP/2 pseudo header fields like ":path" and ":scheme",
+ // which will be added automatically.
+ Header Header
+}
+
+// Pusher is the interface implemented by ResponseWriters that support
+// HTTP/2 server push. For more background, see
+// https://tools.ietf.org/html/rfc7540#section-8.2.
+type Pusher interface {
+ // Push initiates an HTTP/2 server push. This constructs a synthetic
+ // request using the given target and options, serializes that request
+ // into a PUSH_PROMISE frame, then dispatches that request using the
+ // server's request handler. If opts is nil, default options are used.
+ //
+ // The target must either be an absolute path (like "/path") or an absolute
+ // URL that contains a valid host and the same scheme as the parent request.
+ // If the target is a path, it will inherit the scheme and host of the
+ // parent request.
+ //
+ // The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
+ // Push may or may not detect these invalid pushes; however, invalid
+ // pushes will be detected and canceled by conforming clients.
+ //
+ // Handlers that wish to push URL X should call Push before sending any
+ // data that may trigger a request for URL X. This avoids a race where the
+ // client issues requests for X before receiving the PUSH_PROMISE for X.
+ //
+ // Push will run in a separate goroutine making the order of arrival
+ // non-deterministic. Any required synchronization needs to be implemented
+ // by the caller.
+ //
+ // Push returns ErrNotSupported if the client has disabled push or if push
+ // is not supported on the underlying connection.
+ Push(target string, opts *PushOptions) error
+}
diff --git a/net/http/request.go b/net/http/request.go
new file mode 100644
index 0000000..58756ea
--- /dev/null
+++ b/net/http/request.go
@@ -0,0 +1,608 @@
+package http
+
+import (
+ "bufio"
+ "context"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "mime"
+ "mime/multipart"
+ "net/textproto"
+ "net/url"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+func badStringError(what, val string) error { return fmt.Errorf("%s %q", what, val) }
+
+type Request struct {
+ // Method specifies the HTTP method (GET, POST, PUT, etc.).
+ // For client requests, an empty string means GET.
+ //
+ // Go's HTTP client does not support sending a request with
+ // the CONNECT method. See the documentation on Transport for
+ // details.
+ Method string
+
+ // URL specifies either the URI being requested (for server
+ // requests) or the URL to access (for client requests).
+ //
+ // For server requests, the URL is parsed from the URI
+ // supplied on the Request-Line as stored in RequestURI. For
+ // most requests, fields other than Path and RawQuery will be
+ // empty. (See RFC 7230, Section 5.3)
+ //
+ // For client requests, the URL's Host specifies the server to
+ // connect to, while the Request's Host field optionally
+ // specifies the Host header value to send in the HTTP
+ // request.
+ URL *url.URL
+
+ // The protocol version for incoming server requests.
+ //
+ // For client requests, these fields are ignored. The HTTP
+ // client code always uses either HTTP/1.1 or HTTP/2.
+ // See the docs on Transport for details.
+ Proto string // "HTTP/1.0"
+ ProtoMajor int // 1
+ ProtoMinor int // 0
+
+ // Header contains the request header fields either received
+ // by the server or to be sent by the client.
+ //
+ // If a server received a request with header lines,
+ //
+ // Host: example.com
+ // accept-encoding: gzip, deflate
+ // Accept-Language: en-us
+ // fOO: Bar
+ // foo: two
+ //
+ // then
+ //
+ // Header = map[string][]string{
+ // "Accept-Encoding": {"gzip, deflate"},
+ // "Accept-Language": {"en-us"},
+ // "Foo": {"Bar", "two"},
+ // }
+ //
+ // For incoming requests, the Host header is promoted to the
+ // Request.Host field and removed from the Header map.
+ //
+ // HTTP defines that header names are case-insensitive. The
+ // request parser implements this by using CanonicalHeaderKey,
+ // making the first character and any characters following a
+ // hyphen uppercase and the rest lowercase.
+ //
+ // For client requests, certain headers such as Content-Length
+ // and Connection are automatically written when needed and
+ // values in Header may be ignored. See the documentation
+ // for the Request.Write method.
+ Header Header
+
+ // Body is the request's body.
+ //
+ // For client requests, a nil body means the request has no
+ // body, such as a GET request. The HTTP Client's Transport
+ // is responsible for calling the Close method.
+ //
+ // For server requests, the Request Body is always non-nil
+ // but will return EOF immediately when no body is present.
+ // The Server will close the request body. The ServeHTTP
+ // Handler does not need to.
+ //
+ // Body must allow Read to be called concurrently with Close.
+ // In particular, calling Close should unblock a Read waiting
+ // for input.
+ Body io.ReadCloser
+
+ // GetBody defines an optional func to return a new copy of
+ // Body. It is used for client requests when a redirect requires
+ // reading the body more than once. Use of GetBody still
+ // requires setting Body.
+ //
+ // For server requests, it is unused.
+ GetBody func() (io.ReadCloser, error)
+
+ // ContentLength records the length of the associated content.
+ // The value -1 indicates that the length is unknown.
+ // Values >= 0 indicate that the given number of bytes may
+ // be read from Body.
+ //
+ // For client requests, a value of 0 with a non-nil Body is
+ // also treated as unknown.
+ ContentLength int64
+
+ // TransferEncoding lists the transfer encodings from outermost to
+ // innermost. An empty list denotes the "identity" encoding.
+ // TransferEncoding can usually be ignored; chunked encoding is
+ // automatically added and removed as necessary when sending and
+ // receiving requests.
+ TransferEncoding []string
+
+ // Close indicates whether to close the connection after
+ // replying to this request (for servers) or after sending this
+ // request and reading its response (for clients).
+ //
+ // For server requests, the HTTP server handles this automatically
+ // and this field is not needed by Handlers.
+ //
+ // For client requests, setting this field prevents re-use of
+ // TCP connections between requests to the same hosts, as if
+ // Transport.DisableKeepAlives were set.
+ Close bool
+
+ // For server requests, Host specifies the host on which the
+ // URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this
+ // is either the value of the "Host" header or the host name
+ // given in the URL itself. For HTTP/2, it is the value of the
+ // ":authority" pseudo-header field.
+ // It may be of the form "host:port". For international domain
+ // names, Host may be in Punycode or Unicode form. Use
+ // golang.org/x/net/idna to convert it to either format if
+ // needed.
+ // To prevent DNS rebinding attacks, server Handlers should
+ // validate that the Host header has a value for which the
+ // Handler considers itself authoritative. The included
+ // ServeMux supports patterns registered to particular host
+ // names and thus protects its registered Handlers.
+ //
+ // For client requests, Host optionally overrides the Host
+ // header to send. If empty, the Request.Write method uses
+ // the value of URL.Host. Host may contain an international
+ // domain name.
+ Host string
+
+ // Form contains the parsed form data, including both the URL
+ // field's query parameters and the PATCH, POST, or PUT form data.
+ // This field is only available after ParseForm is called.
+ // The HTTP client ignores Form and uses Body instead.
+ Form url.Values
+
+ // PostForm contains the parsed form data from PATCH, POST
+ // or PUT body parameters.
+ //
+ // This field is only available after ParseForm is called.
+ // The HTTP client ignores PostForm and uses Body instead.
+ PostForm url.Values
+
+ // MultipartForm is the parsed multipart form, including file uploads.
+ // This field is only available after ParseMultipartForm is called.
+ // The HTTP client ignores MultipartForm and uses Body instead.
+ MultipartForm *multipart.Form
+
+ // Trailer specifies additional headers that are sent after the request
+ // body.
+ //
+ // For server requests, the Trailer map initially contains only the
+ // trailer keys, with nil values. (The client declares which trailers it
+ // will later send.) While the handler is reading from Body, it must
+ // not reference Trailer. After reading from Body returns EOF, Trailer
+ // can be read again and will contain non-nil values, if they were sent
+ // by the client.
+ //
+ // For client requests, Trailer must be initialized to a map containing
+ // the trailer keys to later send. The values may be nil or their final
+ // values. The ContentLength must be 0 or -1, to send a chunked request.
+ // After the HTTP request is sent the map values can be updated while
+ // the request body is read. Once the body returns EOF, the caller must
+ // not mutate Trailer.
+ //
+ // Few HTTP clients, servers, or proxies support HTTP trailers.
+ Trailer Header
+
+ // RemoteAddr allows HTTP servers and other software to record
+ // the network address that sent the request, usually for
+ // logging. This field is not filled in by ReadRequest and
+ // has no defined format. The HTTP server in this package
+ // sets RemoteAddr to an "IP:port" address before invoking a
+ // handler.
+ // This field is ignored by the HTTP client.
+ RemoteAddr string
+
+ // RequestURI is the unmodified request-target of the
+ // Request-Line (RFC 7230, Section 3.1.1) as sent by the client
+ // to a server. Usually the URL field should be used instead.
+ // It is an error to set this field in an HTTP client request.
+ RequestURI string
+
+ // TLS allows HTTP servers and other software to record
+ // information about the TLS connection on which the request
+ // was received. This field is not filled in by ReadRequest.
+ // The HTTP server in this package sets the field for
+ // TLS-enabled connections before invoking a handler;
+ // otherwise it leaves the field nil.
+ // This field is ignored by the HTTP client.
+ TLS *tls.ConnectionState
+
+ // Cancel is an optional channel whose closure indicates that the client
+ // request should be regarded as canceled. Not all implementations of
+ // RoundTripper may support Cancel.
+ //
+ // For server requests, this field is not applicable.
+ //
+ // Deprecated: Set the Request's context with NewRequestWithContext
+ // instead. If a Request's Cancel field and context are both
+ // set, it is undefined whether Cancel is respected.
+ Cancel <-chan struct{}
+
+ // Response is the redirect response which caused this request
+ // to be created. This field is only populated during client
+ // redirects.
+ Response *Response
+
+ // ctx is either the client or server context. It should only
+ // be modified via copying the whole Request using WithContext.
+ // It is unexported to prevent people from using Context wrong
+ // and mutating the contexts held by callers of the same request.
+ ctx context.Context
+}
+
+// ProtoAtLeast reports whether the HTTP protocol used
+// in the request is at least major.minor.
+func (r *Request) ProtoAtLeast(major, minor int) bool {
+ return r.ProtoMajor > major ||
+ r.ProtoMajor == major && r.ProtoMinor >= minor
+}
+
+// isH2Upgrade reports whether r represents the http2 "client preface"
+// magic string.
+func (r *Request) isH2Upgrade() bool {
+ return r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0"
+}
+
+// ParseHTTPVersion parses an HTTP version string.
+// "HTTP/1.0" returns (1, 0, true).
+func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
+ const Big = 1000000 // arbitrary upper bound
+ switch vers {
+ case "HTTP/1.1":
+ return 1, 1, true
+ case "HTTP/1.0":
+ return 1, 0, true
+ }
+ if !strings.HasPrefix(vers, "HTTP/") {
+ return 0, 0, false
+ }
+ dot := strings.Index(vers, ".")
+ if dot < 0 {
+ return 0, 0, false
+ }
+ major, err := strconv.Atoi(vers[5:dot])
+ if err != nil || major < 0 || major > Big {
+ return 0, 0, false
+ }
+ minor, err = strconv.Atoi(vers[dot+1:])
+ if err != nil || minor < 0 || minor > Big {
+ return 0, 0, false
+ }
+ return major, minor, true
+}
+
+func validMethod(method string) bool {
+ /*
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+ token = 1*
+ */
+ return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
+// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
+func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
+ s1 := strings.Index(line, " ")
+ s2 := strings.Index(line[s1+1:], " ")
+ if s1 < 0 || s2 < 0 {
+ return
+ }
+ s2 += s1 + 1
+ return line[:s1], line[s1+1 : s2], line[s2+1:], true
+}
+
+var textprotoReaderPool sync.Pool
+
+func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
+ if v := textprotoReaderPool.Get(); v != nil {
+ tr := v.(*textproto.Reader)
+ tr.R = br
+ return tr
+ }
+ return textproto.NewReader(br)
+}
+
+func putTextprotoReader(r *textproto.Reader) {
+ r.R = nil
+ textprotoReaderPool.Put(r)
+}
+
+// ReadRequest reads and parses an incoming request from b.
+//
+// ReadRequest is a low-level function and should only be used for
+// specialized applications; most code should use the Server to read
+// requests and handle them via the Handler interface. ReadRequest
+// only supports HTTP/1.x requests. For HTTP/2, use golang.org/x/net/http2.
+func ReadRequest(b *bufio.Reader) (*Request, error) {
+ return readRequest(b, deleteHostHeader)
+}
+
+// Constants for readRequest's deleteHostHeader parameter.
+const (
+ deleteHostHeader = true
+ keepHostHeader = false
+)
+
+func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) {
+ tp := newTextprotoReader(b)
+ req = new(Request)
+
+ // First line: GET /index.html HTTP/1.0
+ var s string
+ if s, err = tp.ReadLine(); err != nil {
+ return nil, err
+ }
+ defer func() {
+ putTextprotoReader(tp)
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ }()
+
+ var ok bool
+ req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
+ if !ok {
+ return nil, badStringError("malformed HTTP request", s)
+ }
+ if !validMethod(req.Method) {
+ return nil, badStringError("invalid method", req.Method)
+ }
+ rawurl := req.RequestURI
+ if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
+ return nil, badStringError("malformed HTTP version", req.Proto)
+ }
+
+ // CONNECT requests are used two different ways, and neither uses a full URL:
+ // The standard use is to tunnel HTTPS through an HTTP proxy.
+ // It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
+ // just the authority section of a URL. This information should go in req.URL.Host.
+ //
+ // The net/rpc package also uses CONNECT, but there the parameter is a path
+ // that starts with a slash. It can be parsed with the regular URL parser,
+ // and the path will end up in req.URL.Path, where it needs to be in order for
+ // RPC to work.
+ justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
+ if justAuthority {
+ rawurl = "http://" + rawurl
+ }
+
+ if req.URL, err = url.ParseRequestURI(rawurl); err != nil {
+ return nil, err
+ }
+
+ if justAuthority {
+ // Strip the bogus "http://" back off.
+ req.URL.Scheme = ""
+ }
+
+ // Subsequent lines: Key: value.
+ mimeHeader, err := tp.ReadMIMEHeader()
+ if err != nil {
+ return nil, err
+ }
+ req.Header = Header(mimeHeader)
+
+ // RFC 7230, section 5.3: Must treat
+ // GET /index.html HTTP/1.1
+ // Host: www.google.com
+ // and
+ // GET http://www.google.com/index.html HTTP/1.1
+ // Host: doesntmatter
+ // the same. In the second case, any Host line is ignored.
+ req.Host = req.URL.Host
+ if req.Host == "" {
+ req.Host = req.Header.get("Host")
+ }
+ if deleteHostHeader {
+ delete(req.Header, "Host")
+ }
+
+ fixPragmaCacheControl(req.Header)
+
+ req.Close = shouldClose(req.ProtoMajor, req.ProtoMinor, req.Header, false)
+
+ err = readTransfer(req, b)
+ if err != nil {
+ return nil, err
+ }
+
+ if req.isH2Upgrade() {
+ // Because it's neither chunked, nor declared:
+ req.ContentLength = -1
+
+ // We want to give handlers a chance to hijack the
+ // connection, but we need to prevent the Server from
+ // dealing with the connection further if it's not
+ // hijacked. Set Close to ensure that:
+ req.Close = true
+ }
+ return req, nil
+}
+
+// MaxBytesReader is similar to io.LimitReader but is intended for
+// limiting the size of incoming request bodies. In contrast to
+// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
+// non-EOF error for a Read beyond the limit, and closes the
+// underlying reader when its Close method is called.
+//
+// MaxBytesReader prevents clients from accidentally or maliciously
+// sending a large request and wasting server resources.
+func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
+ return &maxBytesReader{w: w, r: r, n: n}
+}
+
+type maxBytesReader struct {
+ w ResponseWriter
+ r io.ReadCloser // underlying reader
+ n int64 // max bytes remaining
+ err error // sticky error
+}
+
+func (l *maxBytesReader) Read(p []byte) (n int, err error) {
+ if l.err != nil {
+ return 0, l.err
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+ // If they asked for a 32KB byte read but only 5 bytes are
+ // remaining, no need to read 32KB. 6 bytes will answer the
+ // question of the whether we hit the limit or go past it.
+ if int64(len(p)) > l.n+1 {
+ p = p[:l.n+1]
+ }
+ n, err = l.r.Read(p)
+
+ if int64(n) <= l.n {
+ l.n -= int64(n)
+ l.err = err
+ return n, err
+ }
+
+ n = int(l.n)
+ l.n = 0
+
+ // The server code and client code both use
+ // maxBytesReader. This "requestTooLarge" check is
+ // only used by the server code. To prevent binaries
+ // which only using the HTTP Client code (such as
+ // cmd/go) from also linking in the HTTP server, don't
+ // use a static type assertion to the server
+ // "*response" type. Check this interface instead:
+ type requestTooLarger interface {
+ requestTooLarge()
+ }
+ if res, ok := l.w.(requestTooLarger); ok {
+ res.requestTooLarge()
+ }
+ l.err = errors.New("http: request body too large")
+ return n, l.err
+}
+
+func (l *maxBytesReader) Close() error {
+ return l.r.Close()
+}
+
+func copyValues(dst, src url.Values) {
+ for k, vs := range src {
+ dst[k] = append(dst[k], vs...)
+ }
+}
+
+func parsePostForm(r *Request) (vs url.Values, err error) {
+ if r.Body == nil {
+ err = errors.New("missing form body")
+ return
+ }
+ ct := r.Header.Get("Content-Type")
+ // RFC 7231, section 3.1.1.5 - empty type
+ // MAY be treated as application/octet-stream
+ if ct == "" {
+ ct = "application/octet-stream"
+ }
+ ct, _, err = mime.ParseMediaType(ct)
+ switch {
+ case ct == "application/x-www-form-urlencoded":
+ var reader io.Reader = r.Body
+ maxFormSize := int64(1<<63 - 1)
+ if _, ok := r.Body.(*maxBytesReader); !ok {
+ maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+ reader = io.LimitReader(r.Body, maxFormSize+1)
+ }
+ b, e := io.ReadAll(reader)
+ if e != nil {
+ if err == nil {
+ err = e
+ }
+ break
+ }
+ if int64(len(b)) > maxFormSize {
+ err = errors.New("http: POST too large")
+ return
+ }
+ vs, e = url.ParseQuery(string(b))
+ if err == nil {
+ err = e
+ }
+ case ct == "multipart/form-data":
+ // handled by ParseMultipartForm (which is calling us, or should be)
+ // TODO(bradfitz): there are too many possible
+ // orders to call too many functions here.
+ // Clean this up and write more tests.
+ // request_test.go contains the start of this,
+ // in TestParseMultipartFormOrder and others.
+ }
+ return
+}
+
+// ParseForm populates r.Form and r.PostForm.
+//
+// For all requests, ParseForm parses the raw query from the URL and updates
+// r.Form.
+//
+// For POST, PUT, and PATCH requests, it also reads the request body, parses it
+// as a form and puts the results into both r.PostForm and r.Form. Request body
+// parameters take precedence over URL query string values in r.Form.
+//
+// If the request Body's size has not already been limited by MaxBytesReader,
+// the size is capped at 10MB.
+//
+// For other HTTP methods, or when the Content-Type is not
+// application/x-www-form-urlencoded, the request Body is not read, and
+// r.PostForm is initialized to a non-nil, empty value.
+//
+// ParseMultipartForm calls ParseForm automatically.
+// ParseForm is idempotent.
+func (r *Request) ParseForm() error {
+ var err error
+ if r.PostForm == nil {
+ if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" {
+ r.PostForm, err = parsePostForm(r)
+ }
+ if r.PostForm == nil {
+ r.PostForm = make(url.Values)
+ }
+ }
+ if r.Form == nil {
+ if len(r.PostForm) > 0 {
+ r.Form = make(url.Values)
+ copyValues(r.Form, r.PostForm)
+ }
+ var newValues url.Values
+ if r.URL != nil {
+ var e error
+ newValues, e = url.ParseQuery(r.URL.RawQuery)
+ if err == nil {
+ err = e
+ }
+ }
+ if newValues == nil {
+ newValues = make(url.Values)
+ }
+ if r.Form == nil {
+ r.Form = newValues
+ } else {
+ copyValues(r.Form, newValues)
+ }
+ }
+ return err
+}
diff --git a/net/http/response.go b/net/http/response.go
new file mode 100644
index 0000000..508ae39
--- /dev/null
+++ b/net/http/response.go
@@ -0,0 +1,112 @@
+package http
+
+import (
+ "crypto/tls"
+ "io"
+)
+
+// Response represents the response from an HTTP request.
+//
+// The Client and Transport return Responses from servers once
+// the response headers have been received. The response body
+// is streamed on demand as the Body field is read.
+type Response struct {
+ Status string // e.g. "200 OK"
+ StatusCode int // e.g. 200
+ Proto string // e.g. "HTTP/1.0"
+ ProtoMajor int // e.g. 1
+ ProtoMinor int // e.g. 0
+
+ // Header maps header keys to values. If the response had multiple
+ // headers with the same key, they may be concatenated, with comma
+ // delimiters. (RFC 7230, section 3.2.2 requires that multiple headers
+ // be semantically equivalent to a comma-delimited sequence.) When
+ // Header values are duplicated by other fields in this struct (e.g.,
+ // ContentLength, TransferEncoding, Trailer), the field values are
+ // authoritative.
+ //
+ // Keys in the map are canonicalized (see CanonicalHeaderKey).
+ Header Header
+
+ // Body represents the response body.
+ //
+ // The response body is streamed on demand as the Body field
+ // is read. If the network connection fails or the server
+ // terminates the response, Body.Read calls return an error.
+ //
+ // The http Client and Transport guarantee that Body is always
+ // non-nil, even on responses without a body or responses with
+ // a zero-length body. It is the caller's responsibility to
+ // close Body. The default HTTP client's Transport may not
+ // reuse HTTP/1.x "keep-alive" TCP connections if the Body is
+ // not read to completion and closed.
+ //
+ // The Body is automatically dechunked if the server replied
+ // with a "chunked" Transfer-Encoding.
+ //
+ // As of Go 1.12, the Body will also implement io.Writer
+ // on a successful "101 Switching Protocols" response,
+ // as used by WebSockets and HTTP/2's "h2c" mode.
+ Body io.ReadCloser
+
+ // ContentLength records the length of the associated content. The
+ // value -1 indicates that the length is unknown. Unless Request.Method
+ // is "HEAD", values >= 0 indicate that the given number of bytes may
+ // be read from Body.
+ ContentLength int64
+
+ // Contains transfer encodings from outer-most to inner-most. Value is
+ // nil, means that "identity" encoding is used.
+ TransferEncoding []string
+
+ // Close records whether the header directed that the connection be
+ // closed after reading Body. The value is advice for clients: neither
+ // ReadResponse nor Response.Write ever closes a connection.
+ Close bool
+
+ // Uncompressed reports whether the response was sent compressed but
+ // was decompressed by the http package. When true, reading from
+ // Body yields the uncompressed content instead of the compressed
+ // content actually set from the server, ContentLength is set to -1,
+ // and the "Content-Length" and "Content-Encoding" fields are deleted
+ // from the responseHeader. To get the original response from
+ // the server, set Transport.DisableCompression to true.
+ Uncompressed bool
+
+ // Trailer maps trailer keys to values in the same
+ // format as Header.
+ //
+ // The Trailer initially contains only nil values, one for
+ // each key specified in the server's "Trailer" header
+ // value. Those values are not added to Header.
+ //
+ // Trailer must not be accessed concurrently with Read calls
+ // on the Body.
+ //
+ // After Body.Read has returned io.EOF, Trailer will contain
+ // any trailer values sent by the server.
+ Trailer Header
+
+ // Request is the request that was sent to obtain this Response.
+ // Request's Body is nil (having already been consumed).
+ // This is only populated for Client requests.
+ Request *Request
+
+ // TLS contains information about the TLS connection on which the
+ // response was received. It is nil for unencrypted responses.
+ // The pointer is shared between responses and should not be
+ // modified.
+ TLS *tls.ConnectionState
+}
+
+// RFC 7234, section 5.4: Should treat
+// Pragma: no-cache
+// like
+// Cache-Control: no-cache
+func fixPragmaCacheControl(header Header) {
+ if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" {
+ if _, presentcc := header["Cache-Control"]; !presentcc {
+ header["Cache-Control"] = []string{"no-cache"}
+ }
+ }
+}
diff --git a/net/http/server.go b/net/http/server.go
new file mode 100644
index 0000000..f497901
--- /dev/null
+++ b/net/http/server.go
@@ -0,0 +1,581 @@
+package http
+
+import (
+ "fmt"
+ "net"
+ "net/url"
+ urlpkg "net/url"
+ "path"
+ "sort"
+ "strings"
+ "sync"
+)
+
+// A Handler responds to an HTTP request.
+//
+// ServeHTTP should write reply headers and data to the ResponseWriter
+// and then return. Returning signals that the request is finished; it
+// is not valid to use the ResponseWriter or read from the
+// Request.Body after or concurrently with the completion of the
+// ServeHTTP call.
+//
+// Depending on the HTTP client software, HTTP protocol version, and
+// any intermediaries between the client and the Go server, it may not
+// be possible to read from the Request.Body after writing to the
+// ResponseWriter. Cautious handlers should read the Request.Body
+// first, and then reply.
+//
+// Except for reading the body, handlers should not modify the
+// provided Request.
+//
+// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
+// that the effect of the panic was isolated to the active request.
+// It recovers the panic, logs a stack trace to the server error log,
+// and either closes the network connection or sends an HTTP/2
+// RST_STREAM, depending on the HTTP protocol. To abort a handler so
+// the client sees an interrupted response but the server doesn't log
+// an error, panic with the value ErrAbortHandler.
+type Handler interface {
+ ServeHTTP(ResponseWriter, *Request)
+}
+
+// A ResponseWriter interface is used by an HTTP handler to
+// construct an HTTP response.
+//
+// A ResponseWriter may not be used after the Handler.ServeHTTP method
+// has returned.
+type ResponseWriter interface {
+ // Header returns the header map that will be sent by
+ // WriteHeader. The Header map also is the mechanism with which
+ // Handlers can set HTTP trailers.
+ //
+ // Changing the header map after a call to WriteHeader (or
+ // Write) has no effect unless the modified headers are
+ // trailers.
+ //
+ // There are two ways to set Trailers. The preferred way is to
+ // predeclare in the headers which trailers you will later
+ // send by setting the "Trailer" header to the names of the
+ // trailer keys which will come later. In this case, those
+ // keys of the Header map are treated as if they were
+ // trailers. See the example. The second way, for trailer
+ // keys not known to the Handler until after the first Write,
+ // is to prefix the Header map keys with the TrailerPrefix
+ // constant value. See TrailerPrefix.
+ //
+ // To suppress automatic response headers (such as "Date"), set
+ // their value to nil.
+ Header() Header
+
+ // Write writes the data to the connection as part of an HTTP reply.
+ //
+ // If WriteHeader has not yet been called, Write calls
+ // WriteHeader(http.StatusOK) before writing the data. If the Header
+ // does not contain a Content-Type line, Write adds a Content-Type set
+ // to the result of passing the initial 512 bytes of written data to
+ // DetectContentType. Additionally, if the total size of all written
+ // data is under a few KB and there are no Flush calls, the
+ // Content-Length header is added automatically.
+ //
+ // Depending on the HTTP protocol version and the client, calling
+ // Write or WriteHeader may prevent future reads on the
+ // Request.Body. For HTTP/1.x requests, handlers should read any
+ // needed request body data before writing the response. Once the
+ // headers have been flushed (due to either an explicit Flusher.Flush
+ // call or writing enough data to trigger a flush), the request body
+ // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
+ // handlers to continue to read the request body while concurrently
+ // writing the response. However, such behavior may not be supported
+ // by all HTTP/2 clients. Handlers should read before writing if
+ // possible to maximize compatibility.
+ Write([]byte) (int, error)
+
+ // WriteHeader sends an HTTP response header with the provided
+ // status code.
+ //
+ // If WriteHeader is not called explicitly, the first call to Write
+ // will trigger an implicit WriteHeader(http.StatusOK).
+ // Thus explicit calls to WriteHeader are mainly used to
+ // send error codes.
+ //
+ // The provided code must be a valid HTTP 1xx-5xx status code.
+ // Only one header may be written. Go does not currently
+ // support sending user-defined 1xx informational headers,
+ // with the exception of 100-continue response header that the
+ // Server sends automatically when the Request.Body is read.
+ WriteHeader(statusCode int)
+}
+
+// TimeFormat is the time format to use when generating times in HTTP
+// headers. It is like time.RFC1123 but hard-codes GMT as the time
+// zone. The time being formatted must be in UTC for Format to
+// generate the correct format.
+//
+// For parsing this time format, see ParseTime.
+const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as HTTP handlers. If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler that calls f.
+type HandlerFunc func(ResponseWriter, *Request)
+
+// ServeHTTP calls f(w, r).
+func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
+ f(w, r)
+}
+
+// Helper handlers
+
+// Error replies to the request with the specified error message and HTTP code.
+// It does not otherwise end the request; the caller should ensure no further
+// writes are done to w.
+// The error message should be plain text.
+func Error(w ResponseWriter, error string, code int) {
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ w.Header().Set("X-Content-Type-Options", "nosniff")
+ w.WriteHeader(code)
+ fmt.Fprintln(w, error)
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
+
+// NotFoundHandler returns a simple request handler
+// that replies to each request with a ``404 page not found'' reply.
+func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
+
+// StripPrefix returns a handler that serves HTTP requests by removing the
+// given prefix from the request URL's Path (and RawPath if set) and invoking
+// the handler h. StripPrefix handles a request for a path that doesn't begin
+// with prefix by replying with an HTTP 404 not found error. The prefix must
+// match exactly: if the prefix in the request contains escaped characters
+// the reply is also an HTTP 404 not found error.
+func StripPrefix(prefix string, h Handler) Handler {
+ if prefix == "" {
+ return h
+ }
+ return HandlerFunc(func(w ResponseWriter, r *Request) {
+ p := strings.TrimPrefix(r.URL.Path, prefix)
+ rp := strings.TrimPrefix(r.URL.RawPath, prefix)
+ if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
+ r2 := new(Request)
+ *r2 = *r
+ r2.URL = new(url.URL)
+ *r2.URL = *r.URL
+ r2.URL.Path = p
+ r2.URL.RawPath = rp
+ h.ServeHTTP(w, r2)
+ } else {
+ NotFound(w, r)
+ }
+ })
+}
+
+// Redirect replies to the request with a redirect to url,
+// which may be a path relative to the request path.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
+//
+// If the Content-Type header has not been set, Redirect sets it
+// to "text/html; charset=utf-8" and writes a small HTML body.
+// Setting the Content-Type header to any value, including nil,
+// disables that behavior.
+func Redirect(w ResponseWriter, r *Request, url string, code int) {
+ if u, err := urlpkg.Parse(url); err == nil {
+ // If url was relative, make its path absolute by
+ // combining with request path.
+ // The client would probably do this for us,
+ // but doing it ourselves is more reliable.
+ // See RFC 7231, section 7.1.2
+ if u.Scheme == "" && u.Host == "" {
+ oldpath := r.URL.Path
+ if oldpath == "" { // should not happen, but avoid a crash if it does
+ oldpath = "/"
+ }
+
+ // no leading http://server
+ if url == "" || url[0] != '/' {
+ // make relative path absolute
+ olddir, _ := path.Split(oldpath)
+ url = olddir + url
+ }
+
+ var query string
+ if i := strings.Index(url, "?"); i != -1 {
+ url, query = url[:i], url[i:]
+ }
+
+ // clean up but preserve trailing slash
+ trailing := strings.HasSuffix(url, "/")
+ url = path.Clean(url)
+ if trailing && !strings.HasSuffix(url, "/") {
+ url += "/"
+ }
+ url += query
+ }
+ }
+
+ h := w.Header()
+
+ // RFC 7231 notes that a short HTML body is usually included in
+ // the response because older user agents may not understand 301/307.
+ // Do it only if the request didn't already have a Content-Type header.
+ _, hadCT := h["Content-Type"]
+
+ h.Set("Location", hexEscapeNonASCII(url))
+ if !hadCT && (r.Method == "GET" || r.Method == "HEAD") {
+ h.Set("Content-Type", "text/html; charset=utf-8")
+ }
+ w.WriteHeader(code)
+
+ // Shouldn't send the body for POST or HEAD; that leaves GET.
+ if !hadCT && r.Method == "GET" {
+ body := "" + statusText[code] + ".\n"
+ fmt.Fprintln(w, body)
+ }
+}
+
+var htmlReplacer = strings.NewReplacer(
+ "&", "&",
+ "<", "<",
+ ">", ">",
+ // """ is shorter than """.
+ `"`, """,
+ // "'" is shorter than "'" and apos was not in HTML until HTML5.
+ "'", "'",
+)
+
+func htmlEscape(s string) string {
+ return htmlReplacer.Replace(s)
+}
+
+// Redirect to a fixed URL
+type redirectHandler struct {
+ url string
+ code int
+}
+
+func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
+ Redirect(w, r, rh.url, rh.code)
+}
+
+// RedirectHandler returns a request handler that redirects
+// each request it receives to the given url using the given
+// status code.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
+func RedirectHandler(url string, code int) Handler {
+ return &redirectHandler{url, code}
+}
+
+// ServeMux is an HTTP request multiplexer.
+// It matches the URL of each incoming request against a list of registered
+// patterns and calls the handler for the pattern that
+// most closely matches the URL.
+//
+// Patterns name fixed, rooted paths, like "/favicon.ico",
+// or rooted subtrees, like "/images/" (note the trailing slash).
+// Longer patterns take precedence over shorter ones, so that
+// if there are handlers registered for both "/images/"
+// and "/images/thumbnails/", the latter handler will be
+// called for paths beginning "/images/thumbnails/" and the
+// former will receive requests for any other paths in the
+// "/images/" subtree.
+//
+// Note that since a pattern ending in a slash names a rooted subtree,
+// the pattern "/" matches all paths not matched by other registered
+// patterns, not just the URL with Path == "/".
+//
+// If a subtree has been registered and a request is received naming the
+// subtree root without its trailing slash, ServeMux redirects that
+// request to the subtree root (adding the trailing slash). This behavior can
+// be overridden with a separate registration for the path without
+// the trailing slash. For example, registering "/images/" causes ServeMux
+// to redirect a request for "/images" to "/images/", unless "/images" has
+// been registered separately.
+//
+// Patterns may optionally begin with a host name, restricting matches to
+// URLs on that host only. Host-specific patterns take precedence over
+// general patterns, so that a handler might register for the two patterns
+// "/codesearch" and "codesearch.google.com/" without also taking over
+// requests for "http://www.google.com/".
+//
+// ServeMux also takes care of sanitizing the URL request path and the Host
+// header, stripping the port number and redirecting any request containing . or
+// .. elements or repeated slashes to an equivalent, cleaner URL.
+type ServeMux struct {
+ mu sync.RWMutex
+ m map[string]muxEntry
+ es []muxEntry // slice of entries sorted from longest to shortest.
+ hosts bool // whether any patterns contain hostnames
+}
+
+type muxEntry struct {
+ h Handler
+ pattern string
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return new(ServeMux) }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = &defaultServeMux
+
+var defaultServeMux ServeMux
+
+// cleanPath returns the canonical path for p, eliminating . and .. elements.
+func cleanPath(p string) string {
+ if p == "" {
+ return "/"
+ }
+ if p[0] != '/' {
+ p = "/" + p
+ }
+ np := path.Clean(p)
+ // path.Clean removes trailing slash except for root;
+ // put the trailing slash back if necessary.
+ if p[len(p)-1] == '/' && np != "/" {
+ // Fast path for common case of p being the string we want:
+ if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
+ np = p
+ } else {
+ np += "/"
+ }
+ }
+ return np
+}
+
+// stripHostPort returns h without any trailing ":".
+func stripHostPort(h string) string {
+ // If no port on host, return unchanged
+ if strings.IndexByte(h, ':') == -1 {
+ return h
+ }
+ host, _, err := net.SplitHostPort(h)
+ if err != nil {
+ return h // on error, return unchanged
+ }
+ return host
+}
+
+// Find a handler on a handler map given a path string.
+// Most-specific (longest) pattern wins.
+func (mux *ServeMux) match(path string) (h Handler, pattern string) {
+ // Check for exact match first.
+ v, ok := mux.m[path]
+ if ok {
+ return v.h, v.pattern
+ }
+
+ // Check for longest valid match. mux.es contains all patterns
+ // that end in / sorted from longest to shortest.
+ for _, e := range mux.es {
+ if strings.HasPrefix(path, e.pattern) {
+ return e.h, e.pattern
+ }
+ }
+ return nil, ""
+}
+
+// redirectToPathSlash determines if the given path needs appending "/" to it.
+// This occurs when a handler for path + "/" was already registered, but
+// not for path itself. If the path needs appending to, it creates a new
+// URL, setting the path to u.Path + "/" and returning true to indicate so.
+func (mux *ServeMux) redirectToPathSlash(host, path string, u *url.URL) (*url.URL, bool) {
+ mux.mu.RLock()
+ shouldRedirect := mux.shouldRedirectRLocked(host, path)
+ mux.mu.RUnlock()
+ if !shouldRedirect {
+ return u, false
+ }
+ path = path + "/"
+ u = &url.URL{Path: path, RawQuery: u.RawQuery}
+ return u, true
+}
+
+// shouldRedirectRLocked reports whether the given path and host should be redirected to
+// path+"/". This should happen if a handler is registered for path+"/" but
+// not path -- see comments at ServeMux.
+func (mux *ServeMux) shouldRedirectRLocked(host, path string) bool {
+ p := []string{path, host + path}
+
+ for _, c := range p {
+ if _, exist := mux.m[c]; exist {
+ return false
+ }
+ }
+
+ n := len(path)
+ if n == 0 {
+ return false
+ }
+ for _, c := range p {
+ if _, exist := mux.m[c+"/"]; exist {
+ return path[n-1] != '/'
+ }
+ }
+
+ return false
+}
+
+// Handler returns the handler to use for the given request,
+// consulting r.Method, r.Host, and r.URL.Path. It always returns
+// a non-nil handler. If the path is not in its canonical form, the
+// handler will be an internally-generated handler that redirects
+// to the canonical path. If the host contains a port, it is ignored
+// when matching handlers.
+//
+// The path and host are used unchanged for CONNECT requests.
+//
+// Handler also returns the registered pattern that matches the
+// request or, in the case of internally-generated redirects,
+// the pattern that will match after following the redirect.
+//
+// If there is no registered handler that applies to the request,
+// Handler returns a ``page not found'' handler and an empty pattern.
+func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
+
+ // CONNECT requests are not canonicalized.
+ if r.Method == "CONNECT" {
+ // If r.URL.Path is /tree and its handler is not registered,
+ // the /tree -> /tree/ redirect applies to CONNECT requests
+ // but the path canonicalization does not.
+ if u, ok := mux.redirectToPathSlash(r.URL.Host, r.URL.Path, r.URL); ok {
+ return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
+ }
+
+ return mux.handler(r.Host, r.URL.Path)
+ }
+
+ // All other requests have any port stripped and path cleaned
+ // before passing to mux.handler.
+ host := stripHostPort(r.Host)
+ path := cleanPath(r.URL.Path)
+
+ // If the given path is /tree and its handler is not registered,
+ // redirect for /tree/.
+ if u, ok := mux.redirectToPathSlash(host, path, r.URL); ok {
+ return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
+ }
+
+ if path != r.URL.Path {
+ _, pattern = mux.handler(host, path)
+ url := *r.URL
+ url.Path = path
+ return RedirectHandler(url.String(), StatusMovedPermanently), pattern
+ }
+
+ return mux.handler(host, r.URL.Path)
+}
+
+// handler is the main implementation of Handler.
+// The path is known to be in canonical form, except for CONNECT methods.
+func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
+ mux.mu.RLock()
+ defer mux.mu.RUnlock()
+
+ // Host-specific pattern takes precedence over generic ones
+ if mux.hosts {
+ h, pattern = mux.match(host + path)
+ }
+ if h == nil {
+ h, pattern = mux.match(path)
+ }
+ if h == nil {
+ h, pattern = NotFoundHandler(), ""
+ }
+ return
+}
+
+// ServeHTTP dispatches the request to the handler whose
+// pattern most closely matches the request URL.
+func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
+ if r.RequestURI == "*" {
+ if r.ProtoAtLeast(1, 1) {
+ w.Header().Set("Connection", "close")
+ }
+ w.WriteHeader(StatusBadRequest)
+ return
+ }
+ h, _ := mux.Handler(r)
+ h.ServeHTTP(w, r)
+}
+
+// Handle registers the handler for the given pattern.
+// If a handler already exists for pattern, Handle panics.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+ mux.mu.Lock()
+ defer mux.mu.Unlock()
+
+ if pattern == "" {
+ panic("http: invalid pattern")
+ }
+ if handler == nil {
+ panic("http: nil handler")
+ }
+ if _, exist := mux.m[pattern]; exist {
+ panic("http: multiple registrations for " + pattern)
+ }
+
+ if mux.m == nil {
+ mux.m = make(map[string]muxEntry)
+ }
+ e := muxEntry{h: handler, pattern: pattern}
+ mux.m[pattern] = e
+ if pattern[len(pattern)-1] == '/' {
+ mux.es = appendSorted(mux.es, e)
+ }
+
+ if pattern[0] != '/' {
+ mux.hosts = true
+ }
+}
+
+func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
+ n := len(es)
+ i := sort.Search(n, func(i int) bool {
+ return len(es[i].pattern) < len(e.pattern)
+ })
+ if i == n {
+ return append(es, e)
+ }
+ // we now know that i points at where we want to insert
+ es = append(es, muxEntry{}) // try to grow the slice in place, any entry works.
+ copy(es[i+1:], es[i:]) // Move shorter entries down
+ es[i] = e
+ return es
+}
+
+// HandleFunc registers the handler function for the given pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+ if handler == nil {
+ panic("http: nil handler")
+ }
+ mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// Handle registers the handler for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleFunc registers the handler function for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+ DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// ListenAndServe listens on the TCP network address addr and then calls
+// Serve with handler to handle requests on incoming connections.
+// Accepted connections are configured to enable TCP keep-alives.
+//
+// The handler is typically nil, in which case the DefaultServeMux is used.
+//
+// ListenAndServe always returns a non-nil error.
+func ListenAndServe(addr string, handler Handler) error {
+ return ActiveDevice.ListenAndServe(addr, handler)
+}
diff --git a/net/http/status.go b/net/http/status.go
new file mode 100644
index 0000000..286315f
--- /dev/null
+++ b/net/http/status.go
@@ -0,0 +1,152 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+// HTTP status codes as registered with IANA.
+// See: https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+const (
+ StatusContinue = 100 // RFC 7231, 6.2.1
+ StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
+ StatusProcessing = 102 // RFC 2518, 10.1
+ StatusEarlyHints = 103 // RFC 8297
+
+ StatusOK = 200 // RFC 7231, 6.3.1
+ StatusCreated = 201 // RFC 7231, 6.3.2
+ StatusAccepted = 202 // RFC 7231, 6.3.3
+ StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4
+ StatusNoContent = 204 // RFC 7231, 6.3.5
+ StatusResetContent = 205 // RFC 7231, 6.3.6
+ StatusPartialContent = 206 // RFC 7233, 4.1
+ StatusMultiStatus = 207 // RFC 4918, 11.1
+ StatusAlreadyReported = 208 // RFC 5842, 7.1
+ StatusIMUsed = 226 // RFC 3229, 10.4.1
+
+ StatusMultipleChoices = 300 // RFC 7231, 6.4.1
+ StatusMovedPermanently = 301 // RFC 7231, 6.4.2
+ StatusFound = 302 // RFC 7231, 6.4.3
+ StatusSeeOther = 303 // RFC 7231, 6.4.4
+ StatusNotModified = 304 // RFC 7232, 4.1
+ StatusUseProxy = 305 // RFC 7231, 6.4.5
+ _ = 306 // RFC 7231, 6.4.6 (Unused)
+ StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
+ StatusPermanentRedirect = 308 // RFC 7538, 3
+
+ StatusBadRequest = 400 // RFC 7231, 6.5.1
+ StatusUnauthorized = 401 // RFC 7235, 3.1
+ StatusPaymentRequired = 402 // RFC 7231, 6.5.2
+ StatusForbidden = 403 // RFC 7231, 6.5.3
+ StatusNotFound = 404 // RFC 7231, 6.5.4
+ StatusMethodNotAllowed = 405 // RFC 7231, 6.5.5
+ StatusNotAcceptable = 406 // RFC 7231, 6.5.6
+ StatusProxyAuthRequired = 407 // RFC 7235, 3.2
+ StatusRequestTimeout = 408 // RFC 7231, 6.5.7
+ StatusConflict = 409 // RFC 7231, 6.5.8
+ StatusGone = 410 // RFC 7231, 6.5.9
+ StatusLengthRequired = 411 // RFC 7231, 6.5.10
+ StatusPreconditionFailed = 412 // RFC 7232, 4.2
+ StatusRequestEntityTooLarge = 413 // RFC 7231, 6.5.11
+ StatusRequestURITooLong = 414 // RFC 7231, 6.5.12
+ StatusUnsupportedMediaType = 415 // RFC 7231, 6.5.13
+ StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
+ StatusExpectationFailed = 417 // RFC 7231, 6.5.14
+ StatusTeapot = 418 // RFC 7168, 2.3.3
+ StatusMisdirectedRequest = 421 // RFC 7540, 9.1.2
+ StatusUnprocessableEntity = 422 // RFC 4918, 11.2
+ StatusLocked = 423 // RFC 4918, 11.3
+ StatusFailedDependency = 424 // RFC 4918, 11.4
+ StatusTooEarly = 425 // RFC 8470, 5.2.
+ StatusUpgradeRequired = 426 // RFC 7231, 6.5.15
+ StatusPreconditionRequired = 428 // RFC 6585, 3
+ StatusTooManyRequests = 429 // RFC 6585, 4
+ StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5
+ StatusUnavailableForLegalReasons = 451 // RFC 7725, 3
+
+ StatusInternalServerError = 500 // RFC 7231, 6.6.1
+ StatusNotImplemented = 501 // RFC 7231, 6.6.2
+ StatusBadGateway = 502 // RFC 7231, 6.6.3
+ StatusServiceUnavailable = 503 // RFC 7231, 6.6.4
+ StatusGatewayTimeout = 504 // RFC 7231, 6.6.5
+ StatusHTTPVersionNotSupported = 505 // RFC 7231, 6.6.6
+ StatusVariantAlsoNegotiates = 506 // RFC 2295, 8.1
+ StatusInsufficientStorage = 507 // RFC 4918, 11.5
+ StatusLoopDetected = 508 // RFC 5842, 7.2
+ StatusNotExtended = 510 // RFC 2774, 7
+ StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
+)
+
+var statusText = map[int]string{
+ StatusContinue: "Continue",
+ StatusSwitchingProtocols: "Switching Protocols",
+ StatusProcessing: "Processing",
+ StatusEarlyHints: "Early Hints",
+
+ StatusOK: "OK",
+ StatusCreated: "Created",
+ StatusAccepted: "Accepted",
+ StatusNonAuthoritativeInfo: "Non-Authoritative Information",
+ StatusNoContent: "No Content",
+ StatusResetContent: "Reset Content",
+ StatusPartialContent: "Partial Content",
+ StatusMultiStatus: "Multi-Status",
+ StatusAlreadyReported: "Already Reported",
+ StatusIMUsed: "IM Used",
+
+ StatusMultipleChoices: "Multiple Choices",
+ StatusMovedPermanently: "Moved Permanently",
+ StatusFound: "Found",
+ StatusSeeOther: "See Other",
+ StatusNotModified: "Not Modified",
+ StatusUseProxy: "Use Proxy",
+ StatusTemporaryRedirect: "Temporary Redirect",
+ StatusPermanentRedirect: "Permanent Redirect",
+
+ StatusBadRequest: "Bad Request",
+ StatusUnauthorized: "Unauthorized",
+ StatusPaymentRequired: "Payment Required",
+ StatusForbidden: "Forbidden",
+ StatusNotFound: "Not Found",
+ StatusMethodNotAllowed: "Method Not Allowed",
+ StatusNotAcceptable: "Not Acceptable",
+ StatusProxyAuthRequired: "Proxy Authentication Required",
+ StatusRequestTimeout: "Request Timeout",
+ StatusConflict: "Conflict",
+ StatusGone: "Gone",
+ StatusLengthRequired: "Length Required",
+ StatusPreconditionFailed: "Precondition Failed",
+ StatusRequestEntityTooLarge: "Request Entity Too Large",
+ StatusRequestURITooLong: "Request URI Too Long",
+ StatusUnsupportedMediaType: "Unsupported Media Type",
+ StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
+ StatusExpectationFailed: "Expectation Failed",
+ StatusTeapot: "I'm a teapot",
+ StatusMisdirectedRequest: "Misdirected Request",
+ StatusUnprocessableEntity: "Unprocessable Entity",
+ StatusLocked: "Locked",
+ StatusFailedDependency: "Failed Dependency",
+ StatusTooEarly: "Too Early",
+ StatusUpgradeRequired: "Upgrade Required",
+ StatusPreconditionRequired: "Precondition Required",
+ StatusTooManyRequests: "Too Many Requests",
+ StatusRequestHeaderFieldsTooLarge: "Request Header Fields Too Large",
+ StatusUnavailableForLegalReasons: "Unavailable For Legal Reasons",
+
+ StatusInternalServerError: "Internal Server Error",
+ StatusNotImplemented: "Not Implemented",
+ StatusBadGateway: "Bad Gateway",
+ StatusServiceUnavailable: "Service Unavailable",
+ StatusGatewayTimeout: "Gateway Timeout",
+ StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
+ StatusVariantAlsoNegotiates: "Variant Also Negotiates",
+ StatusInsufficientStorage: "Insufficient Storage",
+ StatusLoopDetected: "Loop Detected",
+ StatusNotExtended: "Not Extended",
+ StatusNetworkAuthenticationRequired: "Network Authentication Required",
+}
+
+// StatusText returns a text for the HTTP status code. It returns the empty
+// string if the code is unknown.
+func StatusText(code int) string {
+ return statusText[code]
+}
diff --git a/net/http/transefer.go b/net/http/transefer.go
new file mode 100644
index 0000000..d9a4406
--- /dev/null
+++ b/net/http/transefer.go
@@ -0,0 +1,34 @@
+package http
+
+import (
+ "bufio"
+
+ "golang.org/x/net/http/httpguts"
+)
+
+// msg is *Request or *Response.
+func readTransfer(msg *Request, r *bufio.Reader) (err error) {
+ // TODO:
+ return nil
+}
+
+// Determine whether to hang up after sending a request and body, or
+// receiving a response and body
+// 'header' is the request headers
+func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
+ if major < 1 {
+ return true
+ }
+
+ conv := header["Connection"]
+ hasClose := httpguts.HeaderValuesContainsToken(conv, "close")
+ if major == 1 && minor == 0 {
+ return hasClose || !httpguts.HeaderValuesContainsToken(conv, "keep-alive")
+ }
+
+ if hasClose && removeCloseHeader {
+ header.Del("Connection")
+ }
+
+ return hasClose
+}
diff --git a/rtl8720dn/http.go b/rtl8720dn/http.go
new file mode 100644
index 0000000..921ee9d
--- /dev/null
+++ b/rtl8720dn/http.go
@@ -0,0 +1,236 @@
+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
+}
diff --git a/rtl8720dn/netdriver.go b/rtl8720dn/netdriver.go
index 56f438d..f646cdc 100644
--- a/rtl8720dn/netdriver.go
+++ b/rtl8720dn/netdriver.go
@@ -12,8 +12,8 @@ func (r *RTL8720DN) GetDNS(domain string) (string, error) {
fmt.Printf("GetDNS(%q)\r\n", domain)
}
- ipaddr := [4]byte{}
- _, err := r.Rpc_netconn_gethostbyname(domain, ipaddr[:])
+ ipaddr := make([]byte, 4)
+ _, err := r.Rpc_netconn_gethostbyname(domain, &ipaddr)
if err != nil {
return "", err
}
@@ -31,8 +31,8 @@ func (r *RTL8720DN) ConnectTCPSocket(addr, port string) error {
fmt.Printf("ConnectTCPSocket(%q, %q)\r\n", addr, port)
}
- ipaddr := [4]byte{}
- _, err := r.Rpc_netconn_gethostbyname(addr, ipaddr[:])
+ ipaddr := make([]byte, 4)
+ _, err := r.Rpc_netconn_gethostbyname(addr, &ipaddr)
if err != nil {
return err
}
@@ -81,8 +81,9 @@ func (r *RTL8720DN) ConnectTCPSocket(addr, port string) error {
return err
}
- optlen := uint32(4)
- _, err = r.Rpc_lwip_getsockopt(socket, 0x00000FFF, 0x00001007, []byte{0xA5, 0xA5, 0xA5, 0xA5}, nil, optlen)
+ optval := make([]byte, 4)
+ optlen := uint32(len(optval))
+ _, err = r.Rpc_lwip_getsockopt(socket, 0x00000FFF, 0x00001007, []byte{0xA5, 0xA5, 0xA5, 0xA5}, &optval, &optlen)
if err != nil {
return err
}
@@ -225,7 +226,7 @@ func (r *RTL8720DN) ReadSocket(b []byte) (n int, err error) {
switch r.connectionType {
case ConnectionTypeTCP:
- nn, err := r.Rpc_lwip_recv(r.socket, b, uint32(len(b)), 0x00000008, 0x00002800)
+ nn, err := r.Rpc_lwip_recv(r.socket, &b, uint32(len(b)), 0x00000008, 0x00002800)
if err != nil {
return 0, err
}
@@ -245,7 +246,7 @@ func (r *RTL8720DN) ReadSocket(b []byte) (n int, err error) {
}
n = int(nn)
case ConnectionTypeTLS:
- nn, err := r.Rpc_wifi_get_ssl_receive(r.client, b, int32(len(b)))
+ nn, err := r.Rpc_wifi_get_ssl_receive(r.client, &b, int32(len(b)))
if err != nil {
return 0, err
}
diff --git a/rtl8720dn/rpc.go b/rtl8720dn/rpc.go
index 5d31294..a8a137a 100644
--- a/rtl8720dn/rpc.go
+++ b/rtl8720dn/rpc.go
@@ -138,7 +138,7 @@ func (r *RTL8720DN) Rpc_gap_set_param(param RPC_T_GAP_PARAM_TYPE, value []byte)
return result, err
}
-func (r *RTL8720DN) Rpc_gap_get_param(param RPC_T_GAP_PARAM_TYPE, value []byte) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_gap_get_param(param RPC_T_GAP_PARAM_TYPE, value *[]byte) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_gap_get_param()\r\n")
}
@@ -161,9 +161,10 @@ func (r *RTL8720DN) Rpc_gap_get_param(param RPC_T_GAP_PARAM_TYPE, value []byte)
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -222,7 +223,7 @@ func (r *RTL8720DN) Rpc_le_bond_set_param(param RPC_T_LE_BOND_PARAM_TYPE, value
return result, err
}
-func (r *RTL8720DN) Rpc_le_bond_get_param(param RPC_T_LE_BOND_PARAM_TYPE, value []byte) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_bond_get_param(param RPC_T_LE_BOND_PARAM_TYPE, value *[]byte) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_bond_get_param()\r\n")
}
@@ -245,9 +246,10 @@ func (r *RTL8720DN) Rpc_le_bond_get_param(param RPC_T_LE_BOND_PARAM_TYPE, value
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -280,7 +282,7 @@ func (r *RTL8720DN) Rpc_le_bond_pair(conn_id uint8) (RPC_T_GAP_CAUSE, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_le_bond_get_display_key(conn_id uint8, key uint32) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_bond_get_display_key(conn_id uint8, key *uint32) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_bond_get_display_key()\r\n")
}
@@ -297,7 +299,8 @@ func (r *RTL8720DN) Rpc_le_bond_get_display_key(conn_id uint8, key uint32) (RPC_
<-r.received
widx := 8
// key : out uint32
- // not impl
+ *key = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -569,7 +572,7 @@ func (r *RTL8720DN) Rpc_le_bond_get_sec_level(conn_id uint8, sec_type RPC_T_GAP_
<-r.received
widx := 8
// sec_type : out RPC_T_GAP_SEC_LEVEL
- // not impl
+ // not impl (a.Size() > 0)
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -676,7 +679,7 @@ func (r *RTL8720DN) Rpc_le_set_gap_param(param RPC_T_GAP_LE_PARAM_TYPE, value []
return result, err
}
-func (r *RTL8720DN) Rpc_le_get_gap_param(param RPC_T_GAP_LE_PARAM_TYPE, value []byte) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_get_gap_param(param RPC_T_GAP_LE_PARAM_TYPE, value *[]byte) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_get_gap_param()\r\n")
}
@@ -699,9 +702,10 @@ func (r *RTL8720DN) Rpc_le_get_gap_param(param RPC_T_GAP_LE_PARAM_TYPE, value []
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -744,7 +748,7 @@ func (r *RTL8720DN) Rpc_le_modify_white_list(operation RPC_T_GAP_WHITE_LIST_OP,
return result, err
}
-func (r *RTL8720DN) Rpc_le_gen_rand_addr(rand_addr_type RPC_T_GAP_RAND_ADDR_TYPE, random_bd uint8) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_gen_rand_addr(rand_addr_type RPC_T_GAP_RAND_ADDR_TYPE, random_bd *uint8) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_gen_rand_addr()\r\n")
}
@@ -764,7 +768,8 @@ func (r *RTL8720DN) Rpc_le_gen_rand_addr(rand_addr_type RPC_T_GAP_RAND_ADDR_TYPE
<-r.received
widx := 8
// random_bd : out uint8
- // not impl
+ *random_bd = payload[widx]
+ widx += 1
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1095,7 +1100,7 @@ func (r *RTL8720DN) Rpc_le_adv_set_param(param RPC_T_LE_ADV_PARAM_TYPE, value []
return result, err
}
-func (r *RTL8720DN) Rpc_le_adv_get_param(param RPC_T_LE_ADV_PARAM_TYPE, value []byte) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_adv_get_param(param RPC_T_LE_ADV_PARAM_TYPE, value *[]byte) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_adv_get_param()\r\n")
}
@@ -1118,9 +1123,10 @@ func (r *RTL8720DN) Rpc_le_adv_get_param(param RPC_T_LE_ADV_PARAM_TYPE, value []
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1219,7 +1225,7 @@ func (r *RTL8720DN) Rpc_le_scan_set_param(param RPC_T_LE_SCAN_PARAM_TYPE, value
return result, err
}
-func (r *RTL8720DN) Rpc_le_scan_get_param(param RPC_T_LE_SCAN_PARAM_TYPE, value []byte) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_scan_get_param(param RPC_T_LE_SCAN_PARAM_TYPE, value *[]byte) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_scan_get_param()\r\n")
}
@@ -1242,9 +1248,10 @@ func (r *RTL8720DN) Rpc_le_scan_get_param(param RPC_T_LE_SCAN_PARAM_TYPE, value
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1354,7 +1361,7 @@ func (r *RTL8720DN) Rpc_le_scan_info_filter(enable bool, offset uint8, length ui
return result, err
}
-func (r *RTL8720DN) Rpc_le_get_conn_param(param RPC_T_LE_CONN_PARAM_TYPE, value []byte, conn_id uint8) (RPC_T_GAP_CAUSE, error) {
+func (r *RTL8720DN) Rpc_le_get_conn_param(param RPC_T_LE_CONN_PARAM_TYPE, value *[]byte, conn_id uint8) (RPC_T_GAP_CAUSE, error) {
if r.debug {
fmt.Printf("rpc_le_get_conn_param()\r\n")
}
@@ -1379,9 +1386,10 @@ func (r *RTL8720DN) Rpc_le_get_conn_param(param RPC_T_LE_CONN_PARAM_TYPE, value
value_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if value_length > 0 {
- copy(value, payload[widx:widx+int(value_length)])
+ copy(*value, payload[widx:widx+int(value_length)])
widx += int(value_length)
}
+ *value = (*value)[:value_length]
var result RPC_T_GAP_CAUSE
result = RPC_T_GAP_CAUSE(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1407,7 +1415,7 @@ func (r *RTL8720DN) Rpc_le_get_conn_info(conn_id uint8, p_conn_info RPC_T_GAP_CO
<-r.received
widx := 8
// p_conn_info : out RPC_T_GAP_CONN_INFO
- // not impl
+ // not impl (a.Size() > 0)
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -1416,7 +1424,7 @@ func (r *RTL8720DN) Rpc_le_get_conn_info(conn_id uint8, p_conn_info RPC_T_GAP_CO
return result, err
}
-func (r *RTL8720DN) Rpc_le_get_conn_addr(conn_id uint8, bd_addr uint8, bd_type uint8) (bool, error) {
+func (r *RTL8720DN) Rpc_le_get_conn_addr(conn_id uint8, bd_addr *uint8, bd_type *uint8) (bool, error) {
if r.debug {
fmt.Printf("rpc_le_get_conn_addr()\r\n")
}
@@ -1433,9 +1441,11 @@ func (r *RTL8720DN) Rpc_le_get_conn_addr(conn_id uint8, bd_addr uint8, bd_type u
<-r.received
widx := 8
// bd_addr : out uint8
- // not impl
+ *bd_addr = payload[widx]
+ widx += 1
// bd_type : out uint8
- // not impl
+ *bd_type = payload[widx]
+ widx += 1
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -1444,7 +1454,7 @@ func (r *RTL8720DN) Rpc_le_get_conn_addr(conn_id uint8, bd_addr uint8, bd_type u
return result, err
}
-func (r *RTL8720DN) Rpc_le_get_conn_id(bd_addr uint8, bd_type uint8, p_conn_id uint8) (bool, error) {
+func (r *RTL8720DN) Rpc_le_get_conn_id(bd_addr uint8, bd_type uint8, p_conn_id *uint8) (bool, error) {
if r.debug {
fmt.Printf("rpc_le_get_conn_id()\r\n")
}
@@ -1463,7 +1473,8 @@ func (r *RTL8720DN) Rpc_le_get_conn_id(bd_addr uint8, bd_type uint8, p_conn_id u
<-r.received
widx := 8
// p_conn_id : out uint8
- // not impl
+ *p_conn_id = payload[widx]
+ widx += 1
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -1779,7 +1790,7 @@ func (r *RTL8720DN) Rpc_flash_load_local_name(p_data RPC_T_LOCAL_NAME) (uint32,
<-r.received
widx := 8
// p_data : out RPC_T_LOCAL_NAME
- // not impl
+ // not impl (a.Size() > 0)
var result uint32
result = uint32(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1829,7 +1840,7 @@ func (r *RTL8720DN) Rpc_flash_load_local_appearance(p_data RPC_T_LOCAL_APPEARANC
<-r.received
widx := 8
// p_data : out RPC_T_LOCAL_APPEARANCE
- // not impl
+ // not impl (a.Size() > 0)
var result uint32
result = uint32(binary.LittleEndian.Uint32(payload[widx:]))
@@ -1980,7 +1991,7 @@ func (r *RTL8720DN) Rpc_le_set_high_priority_bond(bd_addr uint8, bd_type RPC_T_G
return result, err
}
-func (r *RTL8720DN) Rpc_le_resolve_random_address(unresolved_addr uint8, resolved_addr uint8, resolved_addr_type RPC_T_GAP_IDENT_ADDR_TYPE) (bool, error) {
+func (r *RTL8720DN) Rpc_le_resolve_random_address(unresolved_addr uint8, resolved_addr *uint8, resolved_addr_type RPC_T_GAP_IDENT_ADDR_TYPE) (bool, error) {
if r.debug {
fmt.Printf("rpc_le_resolve_random_address()\r\n")
}
@@ -1989,7 +2000,7 @@ func (r *RTL8720DN) Rpc_le_resolve_random_address(unresolved_addr uint8, resolve
// unresolved_addr : in uint8
msg = append(msg, byte(unresolved_addr>>0))
// resolved_addr : inout uint8
- msg = append(msg, byte(resolved_addr>>0))
+ msg = append(msg, byte(*resolved_addr>>0))
// resolved_addr_type : inout RPC_T_GAP_IDENT_ADDR_TYPE
msg = append(msg, byte(resolved_addr_type>>0))
msg = append(msg, byte(resolved_addr_type>>8))
@@ -2004,9 +2015,10 @@ func (r *RTL8720DN) Rpc_le_resolve_random_address(unresolved_addr uint8, resolve
<-r.received
widx := 8
// resolved_addr : inout uint8
- // not impl
+ *resolved_addr = payload[widx]
+ widx += 1
// resolved_addr_type : inout RPC_T_GAP_IDENT_ADDR_TYPE
- // not impl
+ // not impl (a.Size() > 0)
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -2035,7 +2047,7 @@ func (r *RTL8720DN) Rpc_le_get_cccd_data(p_entry RPC_T_LE_KEY_ENTRY, p_data RPC_
<-r.received
widx := 8
// p_data : out RPC_T_LE_CCCD
- // not impl
+ // not impl (a.Size() > 0)
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -2111,7 +2123,7 @@ func (r *RTL8720DN) Rpc_le_get_dev_bond_info_len() (uint16, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_le_set_dev_bond_info(p_data []byte, exist bool) (RPC_T_LE_KEY_ENTRY, error) {
+func (r *RTL8720DN) Rpc_le_set_dev_bond_info(p_data []byte, exist *bool) (RPC_T_LE_KEY_ENTRY, error) {
if r.debug {
fmt.Printf("rpc_le_set_dev_bond_info()\r\n")
}
@@ -2129,7 +2141,8 @@ func (r *RTL8720DN) Rpc_le_set_dev_bond_info(p_data []byte, exist bool) (RPC_T_L
<-r.received
widx := 8
// exist : out bool
- // not impl
+ *exist = payload[widx] != 0
+ widx += 1
var result RPC_T_LE_KEY_ENTRY
result = RPC_T_LE_KEY_ENTRY(binary.LittleEndian.Uint32(payload[widx:]))
@@ -2138,7 +2151,7 @@ func (r *RTL8720DN) Rpc_le_set_dev_bond_info(p_data []byte, exist bool) (RPC_T_L
return result, err
}
-func (r *RTL8720DN) Rpc_le_get_dev_bond_info(p_entry RPC_T_LE_KEY_ENTRY, p_data []byte) (bool, error) {
+func (r *RTL8720DN) Rpc_le_get_dev_bond_info(p_entry RPC_T_LE_KEY_ENTRY, p_data *[]byte) (bool, error) {
if r.debug {
fmt.Printf("rpc_le_get_dev_bond_info()\r\n")
}
@@ -2161,9 +2174,10 @@ func (r *RTL8720DN) Rpc_le_get_dev_bond_info(p_entry RPC_T_LE_KEY_ENTRY, p_data
p_data_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if p_data_length > 0 {
- copy(p_data, payload[widx:widx+int(p_data_length)])
+ copy(*p_data, payload[widx:widx+int(p_data_length)])
widx += int(p_data_length)
}
+ *p_data = (*p_data)[:p_data_length]
var result bool
result = binary.LittleEndian.Uint32(payload[widx:]) == 1
@@ -3080,7 +3094,7 @@ func (r *RTL8720DN) Rpc_ble_gattc_callback(gatt_if uint8, conn_id uint8, cb_data
return result, err
}
-func (r *RTL8720DN) Rpc_ble_gatts_callback(gatt_if uint8, conn_id uint8, attrib_index uint16, event RPC_T_SERVICE_CALLBACK_TYPE, property uint16, read_cb_data []byte, write_cb_data []byte, app_cb_data []byte) (RPC_T_APP_RESULT, error) {
+func (r *RTL8720DN) Rpc_ble_gatts_callback(gatt_if uint8, conn_id uint8, attrib_index uint16, event RPC_T_SERVICE_CALLBACK_TYPE, property uint16, read_cb_data *[]byte, write_cb_data []byte, app_cb_data []byte) (RPC_T_APP_RESULT, error) {
if r.debug {
fmt.Printf("rpc_ble_gatts_callback()\r\n")
}
@@ -3133,9 +3147,10 @@ func (r *RTL8720DN) Rpc_ble_gatts_callback(gatt_if uint8, conn_id uint8, attrib_
widx += 4
}
if read_cb_data_length > 0 {
- copy(read_cb_data, payload[widx:widx+int(read_cb_data_length)])
+ copy(*read_cb_data, payload[widx:widx+int(read_cb_data_length)])
widx += int(read_cb_data_length)
}
+ *read_cb_data = (*read_cb_data)[:read_cb_data_length]
var result RPC_T_APP_RESULT
result = RPC_T_APP_RESULT(binary.LittleEndian.Uint32(payload[widx:]))
@@ -3404,7 +3419,7 @@ func (r *RTL8720DN) Rpc_wifi_set_mac_address(mac []byte) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_mac_address(mac uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_mac_address(mac *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_mac_address()\r\n")
}
@@ -3418,7 +3433,8 @@ func (r *RTL8720DN) Rpc_wifi_get_mac_address(mac uint8) (int32, error) {
<-r.received
widx := 8
// mac : out uint8
- // not impl
+ *mac = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3545,7 +3561,7 @@ func (r *RTL8720DN) Rpc_wifi_btcoex_set_bt_off() error {
return err
}
-func (r *RTL8720DN) Rpc_wifi_get_associated_client_list(client_list_buffer []byte, buffer_length uint16) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_associated_client_list(client_list_buffer *[]byte, buffer_length uint16) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_associated_client_list()\r\n")
}
@@ -3566,9 +3582,10 @@ func (r *RTL8720DN) Rpc_wifi_get_associated_client_list(client_list_buffer []byt
client_list_buffer_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if client_list_buffer_length > 0 {
- copy(client_list_buffer, payload[widx:widx+int(client_list_buffer_length)])
+ copy(*client_list_buffer, payload[widx:widx+int(client_list_buffer_length)])
widx += int(client_list_buffer_length)
}
+ *client_list_buffer = (*client_list_buffer)[:client_list_buffer_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3583,7 +3600,7 @@ func (r *RTL8720DN) Rpc_wifi_get_associated_client_list(client_list_buffer []byt
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_ap_bssid(bssid uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_ap_bssid(bssid *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_ap_bssid()\r\n")
}
@@ -3597,7 +3614,8 @@ func (r *RTL8720DN) Rpc_wifi_get_ap_bssid(bssid uint8) (int32, error) {
<-r.received
widx := 8
// bssid : out uint8
- // not impl
+ *bssid = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3612,7 +3630,7 @@ func (r *RTL8720DN) Rpc_wifi_get_ap_bssid(bssid uint8) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_ap_info(ap_info []byte, security uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_ap_info(ap_info *[]byte, security *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_ap_info()\r\n")
}
@@ -3629,11 +3647,13 @@ func (r *RTL8720DN) Rpc_wifi_get_ap_info(ap_info []byte, security uint32) (int32
ap_info_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if ap_info_length > 0 {
- copy(ap_info, payload[widx:widx+int(ap_info_length)])
+ copy(*ap_info, payload[widx:widx+int(ap_info_length)])
widx += int(ap_info_length)
}
+ *ap_info = (*ap_info)[:ap_info_length]
// security : out uint32
- // not impl
+ *security = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3681,7 +3701,7 @@ func (r *RTL8720DN) Rpc_wifi_set_country(country_code uint32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_sta_max_data_rate(inidata_rate uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_sta_max_data_rate(inidata_rate *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_sta_max_data_rate()\r\n")
}
@@ -3695,7 +3715,8 @@ func (r *RTL8720DN) Rpc_wifi_get_sta_max_data_rate(inidata_rate uint8) (int32, e
<-r.received
widx := 8
// inidata_rate : out uint8
- // not impl
+ *inidata_rate = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3710,7 +3731,7 @@ func (r *RTL8720DN) Rpc_wifi_get_sta_max_data_rate(inidata_rate uint8) (int32, e
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_rssi(pRSSI int32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_rssi(pRSSI *int32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_rssi()\r\n")
}
@@ -3724,7 +3745,8 @@ func (r *RTL8720DN) Rpc_wifi_get_rssi(pRSSI int32) (int32, error) {
<-r.received
widx := 8
// pRSSI : out int32
- // not impl
+ *pRSSI = int32(binary.LittleEndian.Uint32(payload[widx:]))
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -3772,7 +3794,7 @@ func (r *RTL8720DN) Rpc_wifi_set_channel(channel int32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_channel(channel int32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_channel(channel *int32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_channel()\r\n")
}
@@ -3786,7 +3808,8 @@ func (r *RTL8720DN) Rpc_wifi_get_channel(channel int32) (int32, error) {
<-r.received
widx := 8
// channel : out int32
- // not impl
+ *channel = int32(binary.LittleEndian.Uint32(payload[widx:]))
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4159,7 +4182,7 @@ func (r *RTL8720DN) Rpc_wifi_set_lps_dtim(dtim uint8) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_lps_dtim(dtim uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_lps_dtim(dtim *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_lps_dtim()\r\n")
}
@@ -4173,7 +4196,8 @@ func (r *RTL8720DN) Rpc_wifi_get_lps_dtim(dtim uint8) (int32, error) {
<-r.received
widx := 8
// dtim : out uint8
- // not impl
+ *dtim = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4409,7 +4433,7 @@ func (r *RTL8720DN) Rpc_wifi_set_pscan_chan(channel_list []byte, pscan_config ui
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_setting(ifname string, pSetting []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_setting(ifname string, pSetting *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_setting()\r\n")
}
@@ -4430,9 +4454,10 @@ func (r *RTL8720DN) Rpc_wifi_get_setting(ifname string, pSetting []byte) (int32,
pSetting_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pSetting_length > 0 {
- copy(pSetting, payload[widx:widx+int(pSetting_length)])
+ copy(*pSetting, payload[widx:widx+int(pSetting_length)])
widx += int(pSetting_length)
}
+ *pSetting = (*pSetting)[:pSetting_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4480,7 +4505,7 @@ func (r *RTL8720DN) Rpc_wifi_set_network_mode(mode uint32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_network_mode(pmode uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_network_mode(pmode *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_network_mode()\r\n")
}
@@ -4494,7 +4519,8 @@ func (r *RTL8720DN) Rpc_wifi_get_network_mode(pmode uint32) (int32, error) {
<-r.received
widx := 8
// pmode : out uint32
- // not impl
+ *pmode = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4648,7 +4674,7 @@ func (r *RTL8720DN) Rpc_wifi_set_autoreconnect(mode uint8) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_autoreconnect(mode uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_autoreconnect(mode *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_autoreconnect()\r\n")
}
@@ -4662,7 +4688,8 @@ func (r *RTL8720DN) Rpc_wifi_get_autoreconnect(mode uint8) (int32, error) {
<-r.received
widx := 8
// mode : out uint8
- // not impl
+ *mode = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4819,7 +4846,7 @@ func (r *RTL8720DN) Rpc_wifi_set_indicate_mgnt(enable int32) error {
return err
}
-func (r *RTL8720DN) Rpc_wifi_get_drv_ability(ability uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_drv_ability(ability *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_drv_ability()\r\n")
}
@@ -4833,7 +4860,8 @@ func (r *RTL8720DN) Rpc_wifi_get_drv_ability(ability uint32) (int32, error) {
<-r.received
widx := 8
// ability : out uint32
- // not impl
+ *ability = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -4878,7 +4906,7 @@ func (r *RTL8720DN) Rpc_wifi_set_channel_plan(channel_plan uint8) (int32, error)
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_channel_plan(channel_plan uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_channel_plan(channel_plan *uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_channel_plan()\r\n")
}
@@ -4892,7 +4920,8 @@ func (r *RTL8720DN) Rpc_wifi_get_channel_plan(channel_plan uint8) (int32, error)
<-r.received
widx := 8
// channel_plan : out uint8
- // not impl
+ *channel_plan = payload[widx]
+ widx += 1
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5042,7 +5071,7 @@ func (r *RTL8720DN) Rpc_wifi_set_tx_pause_data(NewState uint32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_reconnect_data(wifi_info []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_reconnect_data(wifi_info *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_reconnect_data()\r\n")
}
@@ -5059,9 +5088,10 @@ func (r *RTL8720DN) Rpc_wifi_get_reconnect_data(wifi_info []byte) (int32, error)
wifi_info_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if wifi_info_length > 0 {
- copy(wifi_info, payload[widx:widx+int(wifi_info_length)])
+ copy(*wifi_info, payload[widx:widx+int(wifi_info_length)])
widx += int(wifi_info_length)
}
+ *wifi_info = (*wifi_info)[:wifi_info_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5148,7 +5178,7 @@ func (r *RTL8720DN) Rpc_wifi_is_scaning() (bool, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_scan_get_ap_records(number uint16, _scanResult []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_scan_get_ap_records(number uint16, _scanResult *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_scan_get_ap_records()\r\n")
}
@@ -5169,9 +5199,10 @@ func (r *RTL8720DN) Rpc_wifi_scan_get_ap_records(number uint16, _scanResult []by
_scanResult_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if _scanResult_length > 0 {
- copy(_scanResult, payload[widx:widx+int(_scanResult_length)])
+ copy(*_scanResult, payload[widx:widx+int(_scanResult_length)])
widx += int(_scanResult_length)
}
+ *_scanResult = (*_scanResult)[:_scanResult_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5399,7 +5430,7 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_down(tcpip_if uint32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_tcpip_adapter_get_ip_info(tcpip_if uint32, ip_info []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcpip_adapter_get_ip_info(tcpip_if uint32, ip_info *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcpip_adapter_get_ip_info()\r\n")
}
@@ -5422,9 +5453,10 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_get_ip_info(tcpip_if uint32, ip_info []byt
ip_info_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if ip_info_length > 0 {
- copy(ip_info, payload[widx:widx+int(ip_info_length)])
+ copy(*ip_info, payload[widx:widx+int(ip_info_length)])
widx += int(ip_info_length)
}
+ *ip_info = (*ip_info)[:ip_info_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5516,7 +5548,7 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_set_dns_info(tcpip_if uint32, dns_type uin
return result, err
}
-func (r *RTL8720DN) Rpc_tcpip_adapter_get_dns_info(tcpip_if uint32, dns_type uint32, dns []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcpip_adapter_get_dns_info(tcpip_if uint32, dns_type uint32, dns *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcpip_adapter_get_dns_info()\r\n")
}
@@ -5544,9 +5576,10 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_get_dns_info(tcpip_if uint32, dns_type uin
dns_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if dns_length > 0 {
- copy(dns, payload[widx:widx+int(dns_length)])
+ copy(*dns, payload[widx:widx+int(dns_length)])
widx += int(dns_length)
}
+ *dns = (*dns)[:dns_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5755,6 +5788,7 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_get_hostname(tcpip_if uint32, hostname str
hostname = string(payload[widx : widx+int(hostname_length)])
widx += int(hostname_length)
}
+ hostname = (hostname)[:hostname_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5769,7 +5803,7 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_get_hostname(tcpip_if uint32, hostname str
return result, err
}
-func (r *RTL8720DN) Rpc_tcpip_adapter_get_mac(tcpip_if uint32, mac []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcpip_adapter_get_mac(tcpip_if uint32, mac *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcpip_adapter_get_mac()\r\n")
}
@@ -5792,9 +5826,10 @@ func (r *RTL8720DN) Rpc_tcpip_adapter_get_mac(tcpip_if uint32, mac []byte) (int3
mac_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if mac_length > 0 {
- copy(mac, payload[widx:widx+int(mac_length)])
+ copy(*mac, payload[widx:widx+int(mac_length)])
widx += int(mac_length)
}
+ *mac = (*mac)[:mac_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5879,7 +5914,7 @@ func (r *RTL8720DN) Rpc_tcpip_api_call(fn []byte, call []byte) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_connect(pcb_in []byte, pcb_out []byte, ipaddr []byte, port uint16, connected []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_connect(pcb_in []byte, pcb_out *[]byte, ipaddr []byte, port uint16, connected []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_connect()\r\n")
}
@@ -5909,9 +5944,10 @@ func (r *RTL8720DN) Rpc_tcp_connect(pcb_in []byte, pcb_out []byte, ipaddr []byte
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5926,7 +5962,7 @@ func (r *RTL8720DN) Rpc_tcp_connect(pcb_in []byte, pcb_out []byte, ipaddr []byte
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_recved(pcb_in []byte, pcb_out []byte, length uint16) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_recved(pcb_in []byte, pcb_out *[]byte, length uint16) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_recved()\r\n")
}
@@ -5950,9 +5986,10 @@ func (r *RTL8720DN) Rpc_tcp_recved(pcb_in []byte, pcb_out []byte, length uint16)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -5967,7 +6004,7 @@ func (r *RTL8720DN) Rpc_tcp_recved(pcb_in []byte, pcb_out []byte, length uint16)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_abort(pcb_in []byte, pcb_out []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_abort(pcb_in []byte, pcb_out *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_abort()\r\n")
}
@@ -5988,9 +6025,10 @@ func (r *RTL8720DN) Rpc_tcp_abort(pcb_in []byte, pcb_out []byte) (int32, error)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6005,7 +6043,7 @@ func (r *RTL8720DN) Rpc_tcp_abort(pcb_in []byte, pcb_out []byte) (int32, error)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_write(pcb_in []byte, pcb_out []byte, data []byte, apiflags uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_write(pcb_in []byte, pcb_out *[]byte, data []byte, apiflags uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_write()\r\n")
}
@@ -6031,9 +6069,10 @@ func (r *RTL8720DN) Rpc_tcp_write(pcb_in []byte, pcb_out []byte, data []byte, ap
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6048,7 +6087,7 @@ func (r *RTL8720DN) Rpc_tcp_write(pcb_in []byte, pcb_out []byte, data []byte, ap
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_output(pcb_in []byte, pcb_out []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_output(pcb_in []byte, pcb_out *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_output()\r\n")
}
@@ -6069,9 +6108,10 @@ func (r *RTL8720DN) Rpc_tcp_output(pcb_in []byte, pcb_out []byte) (int32, error)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6086,7 +6126,7 @@ func (r *RTL8720DN) Rpc_tcp_output(pcb_in []byte, pcb_out []byte) (int32, error)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_close(pcb_in []byte, pcb_out []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_close(pcb_in []byte, pcb_out *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_close()\r\n")
}
@@ -6107,9 +6147,10 @@ func (r *RTL8720DN) Rpc_tcp_close(pcb_in []byte, pcb_out []byte) (int32, error)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6124,7 +6165,7 @@ func (r *RTL8720DN) Rpc_tcp_close(pcb_in []byte, pcb_out []byte) (int32, error)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_bind(pcb_in []byte, pcb_out []byte, ipaddr []byte, port uint16) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_bind(pcb_in []byte, pcb_out *[]byte, ipaddr []byte, port uint16) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_bind()\r\n")
}
@@ -6151,9 +6192,10 @@ func (r *RTL8720DN) Rpc_tcp_bind(pcb_in []byte, pcb_out []byte, ipaddr []byte, p
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6168,7 +6210,7 @@ func (r *RTL8720DN) Rpc_tcp_bind(pcb_in []byte, pcb_out []byte, ipaddr []byte, p
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_new_ip_type(ip_type uint8, pcb_out []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_new_ip_type(ip_type uint8, pcb_out *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_new_ip_type()\r\n")
}
@@ -6188,9 +6230,10 @@ func (r *RTL8720DN) Rpc_tcp_new_ip_type(ip_type uint8, pcb_out []byte) (int32, e
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6205,7 +6248,7 @@ func (r *RTL8720DN) Rpc_tcp_new_ip_type(ip_type uint8, pcb_out []byte) (int32, e
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_arg(pcb_in []byte, pcb_out []byte, func_arg []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_arg(pcb_in []byte, pcb_out *[]byte, func_arg []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_arg()\r\n")
}
@@ -6229,9 +6272,10 @@ func (r *RTL8720DN) Rpc_tcp_arg(pcb_in []byte, pcb_out []byte, func_arg []byte)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6246,7 +6290,7 @@ func (r *RTL8720DN) Rpc_tcp_arg(pcb_in []byte, pcb_out []byte, func_arg []byte)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_err(pcb_in []byte, pcb_out []byte, func_err []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_err(pcb_in []byte, pcb_out *[]byte, func_err []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_err()\r\n")
}
@@ -6270,9 +6314,10 @@ func (r *RTL8720DN) Rpc_tcp_err(pcb_in []byte, pcb_out []byte, func_err []byte)
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6287,7 +6332,7 @@ func (r *RTL8720DN) Rpc_tcp_err(pcb_in []byte, pcb_out []byte, func_err []byte)
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_recv(pcb_in []byte, pcb_out []byte, func_recv []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_recv(pcb_in []byte, pcb_out *[]byte, func_recv []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_recv()\r\n")
}
@@ -6311,9 +6356,10 @@ func (r *RTL8720DN) Rpc_tcp_recv(pcb_in []byte, pcb_out []byte, func_recv []byte
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6328,7 +6374,7 @@ func (r *RTL8720DN) Rpc_tcp_recv(pcb_in []byte, pcb_out []byte, func_recv []byte
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_sent(pcb_in []byte, pcb_out []byte, func_sent []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_sent(pcb_in []byte, pcb_out *[]byte, func_sent []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_sent()\r\n")
}
@@ -6352,9 +6398,10 @@ func (r *RTL8720DN) Rpc_tcp_sent(pcb_in []byte, pcb_out []byte, func_sent []byte
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6369,7 +6416,7 @@ func (r *RTL8720DN) Rpc_tcp_sent(pcb_in []byte, pcb_out []byte, func_sent []byte
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_accept(pcb_in []byte, pcb_out []byte, func_accept []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_accept(pcb_in []byte, pcb_out *[]byte, func_accept []byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_accept()\r\n")
}
@@ -6393,9 +6440,10 @@ func (r *RTL8720DN) Rpc_tcp_accept(pcb_in []byte, pcb_out []byte, func_accept []
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6410,7 +6458,7 @@ func (r *RTL8720DN) Rpc_tcp_accept(pcb_in []byte, pcb_out []byte, func_accept []
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_poll(pcb_in []byte, pcb_out []byte, func_poll []byte, interval uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_poll(pcb_in []byte, pcb_out *[]byte, func_poll []byte, interval uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_poll()\r\n")
}
@@ -6436,9 +6484,10 @@ func (r *RTL8720DN) Rpc_tcp_poll(pcb_in []byte, pcb_out []byte, func_poll []byte
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6453,7 +6502,7 @@ func (r *RTL8720DN) Rpc_tcp_poll(pcb_in []byte, pcb_out []byte, func_poll []byte
return result, err
}
-func (r *RTL8720DN) Rpc_tcp_listen_with_backlog(pcb_in []byte, pcb_out []byte, backlog uint8) (int32, error) {
+func (r *RTL8720DN) Rpc_tcp_listen_with_backlog(pcb_in []byte, pcb_out *[]byte, backlog uint8) (int32, error) {
if r.debug {
fmt.Printf("rpc_tcp_listen_with_backlog()\r\n")
}
@@ -6476,9 +6525,10 @@ func (r *RTL8720DN) Rpc_tcp_listen_with_backlog(pcb_in []byte, pcb_out []byte, b
pcb_out_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if pcb_out_length > 0 {
- copy(pcb_out, payload[widx:widx+int(pcb_out_length)])
+ copy(*pcb_out, payload[widx:widx+int(pcb_out_length)])
widx += int(pcb_out_length)
}
+ *pcb_out = (*pcb_out)[:pcb_out_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6576,7 +6626,7 @@ func (r *RTL8720DN) Rpc_inet_chksum(dataptr_in []byte) (uint16, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_accept(s int32, addr []byte, addrlen uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_accept(s int32, addr []byte, addrlen *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_accept()\r\n")
}
@@ -6591,10 +6641,10 @@ func (r *RTL8720DN) Rpc_lwip_accept(s int32, addr []byte, addrlen uint32) (int32
msg = append(msg, byte(len(addr)), byte(len(addr)>>8), byte(len(addr)>>16), byte(len(addr)>>24))
msg = append(msg, []byte(addr)...)
// addrlen : inout uint32
- msg = append(msg, byte(addrlen>>0))
- msg = append(msg, byte(addrlen>>8))
- msg = append(msg, byte(addrlen>>16))
- msg = append(msg, byte(addrlen>>24))
+ msg = append(msg, byte(*addrlen>>0))
+ msg = append(msg, byte(*addrlen>>8))
+ msg = append(msg, byte(*addrlen>>16))
+ msg = append(msg, byte(*addrlen>>24))
err := r.performRequest(msg)
if err != nil {
@@ -6604,7 +6654,8 @@ func (r *RTL8720DN) Rpc_lwip_accept(s int32, addr []byte, addrlen uint32) (int32
<-r.received
widx := 8
// addrlen : inout uint32
- // not impl
+ *addrlen = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6698,7 +6749,7 @@ func (r *RTL8720DN) Rpc_lwip_shutdown(s int32, how int32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_getpeername(s int32, name []byte, namelen uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_getpeername(s int32, name *[]byte, namelen *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_getpeername()\r\n")
}
@@ -6710,10 +6761,10 @@ func (r *RTL8720DN) Rpc_lwip_getpeername(s int32, name []byte, namelen uint32) (
msg = append(msg, byte(s>>16))
msg = append(msg, byte(s>>24))
// namelen : inout uint32
- msg = append(msg, byte(namelen>>0))
- msg = append(msg, byte(namelen>>8))
- msg = append(msg, byte(namelen>>16))
- msg = append(msg, byte(namelen>>24))
+ msg = append(msg, byte(*namelen>>0))
+ msg = append(msg, byte(*namelen>>8))
+ msg = append(msg, byte(*namelen>>16))
+ msg = append(msg, byte(*namelen>>24))
err := r.performRequest(msg)
if err != nil {
@@ -6726,11 +6777,13 @@ func (r *RTL8720DN) Rpc_lwip_getpeername(s int32, name []byte, namelen uint32) (
name_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if name_length > 0 {
- copy(name, payload[widx:widx+int(name_length)])
+ copy(*name, payload[widx:widx+int(name_length)])
widx += int(name_length)
}
+ *name = (*name)[:name_length]
// namelen : inout uint32
- // not impl
+ *namelen = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6745,7 +6798,7 @@ func (r *RTL8720DN) Rpc_lwip_getpeername(s int32, name []byte, namelen uint32) (
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_getsockname(s int32, name []byte, namelen uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_getsockname(s int32, name *[]byte, namelen *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_getsockname()\r\n")
}
@@ -6757,10 +6810,10 @@ func (r *RTL8720DN) Rpc_lwip_getsockname(s int32, name []byte, namelen uint32) (
msg = append(msg, byte(s>>16))
msg = append(msg, byte(s>>24))
// namelen : inout uint32
- msg = append(msg, byte(namelen>>0))
- msg = append(msg, byte(namelen>>8))
- msg = append(msg, byte(namelen>>16))
- msg = append(msg, byte(namelen>>24))
+ msg = append(msg, byte(*namelen>>0))
+ msg = append(msg, byte(*namelen>>8))
+ msg = append(msg, byte(*namelen>>16))
+ msg = append(msg, byte(*namelen>>24))
err := r.performRequest(msg)
if err != nil {
@@ -6773,11 +6826,13 @@ func (r *RTL8720DN) Rpc_lwip_getsockname(s int32, name []byte, namelen uint32) (
name_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if name_length > 0 {
- copy(name, payload[widx:widx+int(name_length)])
+ copy(*name, payload[widx:widx+int(name_length)])
widx += int(name_length)
}
+ *name = (*name)[:name_length]
// namelen : inout uint32
- // not impl
+ *namelen = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -6792,7 +6847,7 @@ func (r *RTL8720DN) Rpc_lwip_getsockname(s int32, name []byte, namelen uint32) (
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_getsockopt(s int32, level int32, optname int32, in_optval []byte, out_optval []byte, optlen uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_getsockopt(s int32, level int32, optname int32, in_optval []byte, out_optval *[]byte, optlen *uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_getsockopt()\r\n")
}
@@ -6817,10 +6872,10 @@ func (r *RTL8720DN) Rpc_lwip_getsockopt(s int32, level int32, optname int32, in_
msg = append(msg, byte(len(in_optval)), byte(len(in_optval)>>8), byte(len(in_optval)>>16), byte(len(in_optval)>>24))
msg = append(msg, []byte(in_optval)...)
// optlen : inout uint32
- msg = append(msg, byte(optlen>>0))
- msg = append(msg, byte(optlen>>8))
- msg = append(msg, byte(optlen>>16))
- msg = append(msg, byte(optlen>>24))
+ msg = append(msg, byte(*optlen>>0))
+ msg = append(msg, byte(*optlen>>8))
+ msg = append(msg, byte(*optlen>>16))
+ msg = append(msg, byte(*optlen>>24))
err := r.performRequest(msg)
if err != nil {
@@ -6833,11 +6888,13 @@ func (r *RTL8720DN) Rpc_lwip_getsockopt(s int32, level int32, optname int32, in_
out_optval_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if out_optval_length > 0 {
- copy(out_optval, payload[widx:widx+int(out_optval_length)])
+ copy(*out_optval, payload[widx:widx+int(out_optval_length)])
widx += int(out_optval_length)
}
+ *out_optval = (*out_optval)[:out_optval_length]
// optlen : inout uint32
- // not impl
+ *optlen = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7048,7 +7105,7 @@ func (r *RTL8720DN) Rpc_lwip_available(s int32) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_recv(s int32, mem []byte, length uint32, flags int32, timeout uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_recv(s int32, mem *[]byte, length uint32, flags int32, timeout uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_recv()\r\n")
}
@@ -7086,9 +7143,10 @@ func (r *RTL8720DN) Rpc_lwip_recv(s int32, mem []byte, length uint32, flags int3
mem_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if mem_length > 0 {
- copy(mem, payload[widx:widx+int(mem_length)])
+ copy(*mem, payload[widx:widx+int(mem_length)])
widx += int(mem_length)
}
+ *mem = (*mem)[:mem_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7103,7 +7161,7 @@ func (r *RTL8720DN) Rpc_lwip_recv(s int32, mem []byte, length uint32, flags int3
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_read(s int32, mem []byte, length uint32, timeout uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_read(s int32, mem *[]byte, length uint32, timeout uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_read()\r\n")
}
@@ -7136,9 +7194,10 @@ func (r *RTL8720DN) Rpc_lwip_read(s int32, mem []byte, length uint32, timeout ui
mem_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if mem_length > 0 {
- copy(mem, payload[widx:widx+int(mem_length)])
+ copy(*mem, payload[widx:widx+int(mem_length)])
widx += int(mem_length)
}
+ *mem = (*mem)[:mem_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7153,7 +7212,7 @@ func (r *RTL8720DN) Rpc_lwip_read(s int32, mem []byte, length uint32, timeout ui
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_recvfrom(s int32, mem []byte, length uint32, flags int32, from []byte, fromlen uint32, timeout uint32) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_recvfrom(s int32, mem *[]byte, length uint32, flags int32, from *[]byte, fromlen *uint32, timeout uint32) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_recvfrom()\r\n")
}
@@ -7175,10 +7234,10 @@ func (r *RTL8720DN) Rpc_lwip_recvfrom(s int32, mem []byte, length uint32, flags
msg = append(msg, byte(flags>>16))
msg = append(msg, byte(flags>>24))
// fromlen : inout uint32
- msg = append(msg, byte(fromlen>>0))
- msg = append(msg, byte(fromlen>>8))
- msg = append(msg, byte(fromlen>>16))
- msg = append(msg, byte(fromlen>>24))
+ msg = append(msg, byte(*fromlen>>0))
+ msg = append(msg, byte(*fromlen>>8))
+ msg = append(msg, byte(*fromlen>>16))
+ msg = append(msg, byte(*fromlen>>24))
// timeout : in uint32
msg = append(msg, byte(timeout>>0))
msg = append(msg, byte(timeout>>8))
@@ -7196,18 +7255,21 @@ func (r *RTL8720DN) Rpc_lwip_recvfrom(s int32, mem []byte, length uint32, flags
mem_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if mem_length > 0 {
- copy(mem, payload[widx:widx+int(mem_length)])
+ copy(*mem, payload[widx:widx+int(mem_length)])
widx += int(mem_length)
}
+ *mem = (*mem)[:mem_length]
// from : out []byte
from_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if from_length > 0 {
- copy(from, payload[widx:widx+int(from_length)])
+ copy(*from, payload[widx:widx+int(from_length)])
widx += int(from_length)
}
+ *from = (*from)[:from_length]
// fromlen : inout uint32
- // not impl
+ *fromlen = binary.LittleEndian.Uint32(payload[widx:])
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7554,7 +7616,7 @@ func (r *RTL8720DN) Rpc_lwip_select(maxfdp1 int32, readset []byte, writeset []by
return result, err
}
-func (r *RTL8720DN) Rpc_lwip_ioctl(s int32, cmd uint32, in_argp []byte, out_argp []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_lwip_ioctl(s int32, cmd uint32, in_argp []byte, out_argp *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_lwip_ioctl()\r\n")
}
@@ -7585,9 +7647,10 @@ func (r *RTL8720DN) Rpc_lwip_ioctl(s int32, cmd uint32, in_argp []byte, out_argp
out_argp_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if out_argp_length > 0 {
- copy(out_argp, payload[widx:widx+int(out_argp_length)])
+ copy(*out_argp, payload[widx:widx+int(out_argp_length)])
widx += int(out_argp_length)
}
+ *out_argp = (*out_argp)[:out_argp_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7671,7 +7734,7 @@ func (r *RTL8720DN) Rpc_lwip_errno() (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_netconn_gethostbyname(name string, addr []byte) (int8, error) {
+func (r *RTL8720DN) Rpc_netconn_gethostbyname(name string, addr *[]byte) (int8, error) {
if r.debug {
fmt.Printf("rpc_netconn_gethostbyname()\r\n")
}
@@ -7692,9 +7755,10 @@ func (r *RTL8720DN) Rpc_netconn_gethostbyname(name string, addr []byte) (int8, e
addr_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if addr_length > 0 {
- copy(addr, payload[widx:widx+int(addr_length)])
+ copy(*addr, payload[widx:widx+int(addr_length)])
widx += int(addr_length)
}
+ *addr = (*addr)[:addr_length]
var result int8
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -7709,7 +7773,7 @@ func (r *RTL8720DN) Rpc_netconn_gethostbyname(name string, addr []byte) (int8, e
return result, err
}
-func (r *RTL8720DN) Rpc_dns_gethostbyname_addrtype(hostname string, addr []byte, found uint32, callback_arg []byte, dns_addrtype uint8) (int8, error) {
+func (r *RTL8720DN) Rpc_dns_gethostbyname_addrtype(hostname string, addr *[]byte, found uint32, callback_arg []byte, dns_addrtype uint8) (int8, error) {
if r.debug {
fmt.Printf("rpc_dns_gethostbyname_addrtype()\r\n")
}
@@ -7745,9 +7809,10 @@ func (r *RTL8720DN) Rpc_dns_gethostbyname_addrtype(hostname string, addr []byte,
addr_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if addr_length > 0 {
- copy(addr, payload[widx:widx+int(addr_length)])
+ copy(*addr, payload[widx:widx+int(addr_length)])
widx += int(addr_length)
}
+ *addr = (*addr)[:addr_length]
var result int8
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -8004,6 +8069,7 @@ func (r *RTL8720DN) Rpc_wifi_ssl_get_rootCA(ssl_client uint32, rootCABuff string
rootCABuff = string(payload[widx : widx+int(rootCABuff_length)])
widx += int(rootCABuff_length)
}
+ rootCABuff = (rootCABuff)[:rootCABuff_length]
var result uint32
result = uint32(binary.LittleEndian.Uint32(payload[widx:]))
@@ -8418,7 +8484,7 @@ func (r *RTL8720DN) Rpc_wifi_send_ssl_data(ssl_client uint32, data []byte, lengt
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_get_ssl_receive(ssl_client uint32, data []byte, length int32) (int32, error) {
+func (r *RTL8720DN) Rpc_wifi_get_ssl_receive(ssl_client uint32, data *[]byte, length int32) (int32, error) {
if r.debug {
fmt.Printf("rpc_wifi_get_ssl_receive()\r\n")
}
@@ -8446,9 +8512,10 @@ func (r *RTL8720DN) Rpc_wifi_get_ssl_receive(ssl_client uint32, data []byte, len
data_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if data_length > 0 {
- copy(data, payload[widx:widx+int(data_length)])
+ copy(*data, payload[widx:widx+int(data_length)])
widx += int(data_length)
}
+ *data = (*data)[:data_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -8526,7 +8593,7 @@ func (r *RTL8720DN) Rpc_wifi_verify_ssl_dn(ssl_client uint32, domain_name string
return result, err
}
-func (r *RTL8720DN) Rpc_wifi_ssl_strerror(errnum int32, buffer []byte, buflen uint32) error {
+func (r *RTL8720DN) Rpc_wifi_ssl_strerror(errnum int32, buffer *[]byte, buflen uint32) error {
if r.debug {
fmt.Printf("rpc_wifi_ssl_strerror()\r\n")
}
@@ -8554,9 +8621,10 @@ func (r *RTL8720DN) Rpc_wifi_ssl_strerror(errnum int32, buffer []byte, buflen ui
buffer_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if buffer_length > 0 {
- copy(buffer, payload[widx:widx+int(buffer_length)])
+ copy(*buffer, payload[widx:widx+int(buffer_length)])
widx += int(buffer_length)
}
+ *buffer = (*buffer)[:buffer_length]
r.seq++
return err
@@ -8827,7 +8895,7 @@ func (r *RTL8720DN) Rpc_mdns_hostname_set(hostname string) (int32, error) {
return result, err
}
-func (r *RTL8720DN) Rpc_mdns_query_a(host_name string, timeout uint32, addr []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_mdns_query_a(host_name string, timeout uint32, addr *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_mdns_query_a()\r\n")
}
@@ -8853,9 +8921,10 @@ func (r *RTL8720DN) Rpc_mdns_query_a(host_name string, timeout uint32, addr []by
addr_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if addr_length > 0 {
- copy(addr, payload[widx:widx+int(addr_length)])
+ copy(*addr, payload[widx:widx+int(addr_length)])
widx += int(addr_length)
}
+ *addr = (*addr)[:addr_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -8870,7 +8939,7 @@ func (r *RTL8720DN) Rpc_mdns_query_a(host_name string, timeout uint32, addr []by
return result, err
}
-func (r *RTL8720DN) Rpc_mdns_query_ptr(service_type string, proto string, timeout uint32, max_results int32, result_total int32) (int32, error) {
+func (r *RTL8720DN) Rpc_mdns_query_ptr(service_type string, proto string, timeout uint32, max_results int32, result_total *int32) (int32, error) {
if r.debug {
fmt.Printf("rpc_mdns_query_ptr()\r\n")
}
@@ -8901,7 +8970,8 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr(service_type string, proto string, timeou
<-r.received
widx := 8
// result_total : out int32
- // not impl
+ *result_total = int32(binary.LittleEndian.Uint32(payload[widx:]))
+ widx += 4
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -8916,7 +8986,7 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr(service_type string, proto string, timeou
return result, err
}
-func (r *RTL8720DN) Rpc_mdns_query_ptr_result_basic(result_target int32, scan_result []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_mdns_query_ptr_result_basic(result_target int32, scan_result *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_mdns_query_ptr_result_basic()\r\n")
}
@@ -8939,9 +9009,10 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr_result_basic(result_target int32, scan_re
scan_result_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if scan_result_length > 0 {
- copy(scan_result, payload[widx:widx+int(scan_result_length)])
+ copy(*scan_result, payload[widx:widx+int(scan_result_length)])
widx += int(scan_result_length)
}
+ *scan_result = (*scan_result)[:scan_result_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -8956,7 +9027,7 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr_result_basic(result_target int32, scan_re
return result, err
}
-func (r *RTL8720DN) Rpc_mdns_query_ptr_result_txt(result_target int32, txt_target int32, txt []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_mdns_query_ptr_result_txt(result_target int32, txt_target int32, txt *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_mdns_query_ptr_result_txt()\r\n")
}
@@ -8984,9 +9055,10 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr_result_txt(result_target int32, txt_targe
txt_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if txt_length > 0 {
- copy(txt, payload[widx:widx+int(txt_length)])
+ copy(*txt, payload[widx:widx+int(txt_length)])
widx += int(txt_length)
}
+ *txt = (*txt)[:txt_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
@@ -9001,7 +9073,7 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr_result_txt(result_target int32, txt_targe
return result, err
}
-func (r *RTL8720DN) Rpc_mdns_query_ptr_result_addr(result_target int32, addr_target int32, addr []byte) (int32, error) {
+func (r *RTL8720DN) Rpc_mdns_query_ptr_result_addr(result_target int32, addr_target int32, addr *[]byte) (int32, error) {
if r.debug {
fmt.Printf("rpc_mdns_query_ptr_result_addr()\r\n")
}
@@ -9029,9 +9101,10 @@ func (r *RTL8720DN) Rpc_mdns_query_ptr_result_addr(result_target int32, addr_tar
addr_length := binary.LittleEndian.Uint32(payload[widx:])
widx += 4
if addr_length > 0 {
- copy(addr, payload[widx:widx+int(addr_length)])
+ copy(*addr, payload[widx:widx+int(addr_length)])
widx += int(addr_length)
}
+ *addr = (*addr)[:addr_length]
var result int32
x := binary.LittleEndian.Uint32(payload[widx:])
diff --git a/rtl8720dn/wifi.go b/rtl8720dn/wifi.go
index 9329b4a..cfd7fb8 100644
--- a/rtl8720dn/wifi.go
+++ b/rtl8720dn/wifi.go
@@ -59,7 +59,7 @@ func (r *RTL8720DN) ConnectToAP(ssid string, password string) error {
func (r *RTL8720DN) GetIP() (ip, subnet, gateway IPAddress, err error) {
ip_info := make([]byte, 12)
- _, err = r.Rpc_tcpip_adapter_get_ip_info(0, ip_info)
+ _, err = r.Rpc_tcpip_adapter_get_ip_info(0, &ip_info)
if err != nil {
return nil, nil, nil, err
}