drivers icon indicating copy to clipboard operation
drivers copied to clipboard

wifinina: Can't complete read from net.Conn

Open jasonmf opened this issue 2 years ago • 1 comments

$ tinygo version
tinygo version 0.23.0 linux/amd64 (using go version go1.17.7 and LLVM version 14.0.0)
$ tinygo flash -target=arduino-nano33 main.go
...
$ cat go.mod
module blarg

go 1.17

require tinygo.org/x/drivers v0.20.0

require (
        golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
        golang.org/x/text v0.3.6 // indirect
)

I'm using an arduino-nano33 (IoT) to connect to an HTTPS server I control. It's not clear how to retrieve data. I've tried a few different approaches:

Using a conn based on tls.Dial() and breaking the loop if no data is retrieved, as in the tlsclient example:

	println("Connected!\r")

	print("Sending HTTPS request...")
	fmt.Fprintln(conn, "GET / HTTP/1.1")
	fmt.Fprintln(conn, "Host:", strings.Split(server, ":")[0])
	fmt.Fprintln(conn, "User-Agent: TinyGo")
	fmt.Fprintln(conn, "Connection: close")
	fmt.Fprintln(conn)
	println("Sent!\r\n\r")

	conn.SetReadDeadline(time.Now().Add(time.Second * 10))
	for n, err := conn.Read(socketBuf[:]); n > 0; n, err = conn.Read(socketBuf[:]) {
		if err != nil {
			println("Read error: " + err.Error())
			break
		} else {
			print(string(socketBuf[0:n]))
		}
	}

It connects, the request is sent, and it immediately falls out of the loop with no error and no output.

Using a conn based on tls.Dial() and breaking the loop only on error with read timeout:

	println("Connected!\r")

	print("Sending HTTPS request...")
	fmt.Fprintln(conn, "GET / HTTP/1.1")
	fmt.Fprintln(conn, "Host:", strings.Split(server, ":")[0])
	fmt.Fprintln(conn, "User-Agent: TinyGo")
	fmt.Fprintln(conn, "Connection: close")
	fmt.Fprintln(conn)
	println("Sent!\r\n\r")

	conn.SetReadDeadline(time.Now().Add(time.Second * 10))
	for {
		n, err := conn.Read(socketBuf[:])
		if n > 0 {
			print(string(socketBuf[:n]))
		}
		if err != nil {
			println("read error: ", err.Error())
			break
		}
	}
	println("read done")

The HTTP response is printed but it never breaks out of the loop.

Trying the drivers/net/http package:

	println("Sending request")
	resp, err := http.Get("https://myserver:443/")
	if err != nil {
		return fmt.Errorf("getting: %w", err)
	}

	println("hanlding response")
	fmt.Printf("%s %s\r\n", resp.Proto, resp.Status)
	for k, v := range resp.Header {
		fmt.Printf("%s: %s\r\n", k, strings.Join(v, " "))
	}
	fmt.Printf("\r\n")

	println("scanning")
	scanner := bufio.NewScanner(resp.Body)
	for scanner.Scan() {
		fmt.Printf("%s\r\n", scanner.Text())
	}
	resp.Body.Close()
	println("done")
	return nil

It never gets passed Sending request.

The docs for net.Conn.Read say:

Read can be made to time out and return an Error with Timeout() == true

Which I can't make sense of searching the net and wifinina sources.

jasonmf avatar May 08 '22 06:05 jasonmf

Hey @jasonmf 👋

I have managed to get the request to go through on my nano33 if you are still having issues.

I used the drivers/net/http package but added a buffer

var buf [0x500]byte
http.SetBuf(buf[:])

damongolding avatar Dec 08 '22 10:12 damongolding