1
- #### Table of Contents
1
+ ### Table of Contents
2
2
3
3
- [ "net" Package] ( #net-package )
4
4
- [ Using "net" Package] ( #using-net-package )
5
5
- [ Using "net/http" Package] ( #using-nethttp-package )
6
6
- [ Using "crypto/tls" Package] ( #using-cryptotls-package )
7
7
- [ Using Sockets] ( #using-sockets )
8
- - [ Netdev and Netlink] ( #netdev-and-netlink )
9
- - [ Writing a New Netdev Driver] ( #writing-a-new-netdev-driver )
10
8
11
9
## "net" Package
12
10
13
11
TinyGo's "net" package is ported from Go. The port offers a subset of Go's
14
12
"net" package. The subset maintains Go 1 compatiblity guarantee. A Go
15
13
application that uses "net" will most-likey just work on TinyGo if the usage is
16
14
within the subset offered. (There may be external constraints such as limited
17
- SRAM on embedded environment that may limit full functionality).
15
+ SRAM on some targets that may limit full "net" functionality).
18
16
19
17
Continue below for details on using "net" and "net/http" packages.
20
18
@@ -24,143 +22,140 @@ TinyGo's "net" package.
24
22
## Using "net" Package
25
23
26
24
Ideally, TinyGo's "net" package would be Go's "net" package and applications
27
- using "net" would just work, as-is. TinyGo's net package is a partial port
28
- from Go's net package, replacing OS socket syscalls with netdev socket calls.
29
-
30
- Netdev is TinyGo's network device driver model; read more about
31
- [ Netdev] ( #netdev-and-netlink ) .
25
+ using "net" would just work, as-is. TinyGo's net package is a partial port of
26
+ Go's net package, so some things may not work because they have not been
27
+ ported.
32
28
33
29
There are a few features excluded during the porting process, in particular:
34
30
35
31
- No IPv6 support
36
32
- No DualStack support
37
33
38
- Run ``` go doc -all ./src/net ``` in TinyGo repo to see full listing.
34
+ Run ``` go doc -all ./src/net ``` in TinyGo repo to see full listing of what has
35
+ been ported. Here is a list of things known to work. You can find examples
36
+ of these at [ examples/net] ( examples/net/ ) .
39
37
40
- Applications using Go's net package will need a few setup steps to work with
41
- TinyGo's net package.
38
+ ### What is Known to Work
42
39
43
- ### Step 1: Create the netdev for your target device .
40
+ (These are all IPv4 only) .
44
41
45
- The available netdev are:
42
+ - TCP client and server
43
+ - UDP client
44
+ - TLS client
45
+ - HTTP client and server
46
+ - HTTPS client
47
+ - NTP client (UDP)
48
+ - MQTT client (paho & natiu)
49
+ - WebSocket client and server
46
50
47
- - [ wifinina] : ESP32 WiFi co-controller running Arduino WiFiNINA firmware
51
+ Multiple sockets can be opened in a single app. For example, the app could run
52
+ as an http server listen on port :80 and also use NTP to get the current time
53
+ or send something over MQTT. There is a practical limit to the number of
54
+ active sockets per app, around 8 or 10, so don't go crazy.
48
55
49
- targets: pyportal arduino_nano33 nano_rp2040 metro_m4_airlift
50
- arduino_mkrwifi1010 matrixportal_m4
56
+ Applications using Go's net package will need a few setup steps to work with
57
+ TinyGo's net package. The steps are required before using "net".
51
58
52
- - [ rtl8720dn ] : RealTek WiFi rtl8720dn co-controller
59
+ ### Step 1: Probe to Load Network Driver
53
60
54
- targets: wioterminal
61
+ Call Probe() to load the correct network driver for your target. Probe()
62
+ allows the app to work on multiple targets.
55
63
56
- - [ espat] : ESP32/ESP8266 WiFi co-controller running Espressif AT firmware
64
+ ``` go
65
+ package main
57
66
58
- targets: TBD
67
+ import (
68
+ " tinygo.org/x/drivers/netlink/probe"
69
+ )
59
70
60
- This example configures and creates a wifinina netdev using New().
71
+ func main () {
61
72
62
- ``` go
63
- import " tinygo.org/x/drivers/wifinina "
73
+ // load network driver for target
74
+ link , dev := probe. Probe ()
64
75
65
- func main () {
66
- cfg := wifinina.Config {Ssid: " foo" , Passphrase: " bar" }
67
- netdev := wifinina.New (&cfg)
68
- ...
76
+ ...
69
77
}
70
78
```
71
79
72
- New() registers the netdev with the "net" package using net.useNetdev().
80
+ Probe() will load the driver with default configuration for the target. For
81
+ custom configuration, the app can open code Probe() for the target
82
+ requirements.
73
83
74
- The Config structure is netdev-specific; consult the specific netdev package
75
- for Config details. In this case, the WiFi credentials are passed, but other
76
- settings are typically passed such as device configuration .
84
+ Probe() returns a [ Netlinker ] ( netlink/README.md ) and a
85
+ [ Netdever ] ( netdev/README.md ) , interfaces implemented by the network driver.
86
+ Next, we'll use the Netlinker interface to connect the target to an IP network .
77
87
78
88
### Step 2: Connect to an IP Network
79
89
80
- Before the net package is fully functional, connect the netdev to an underlying
81
- IP network. For example, a WiFi netdev would connect to a WiFi access point or
82
- become a WiFi access point; either way, once connected, the netdev has a
83
- station IP address and is connected on the IP network. Similarly, a LTE netdev
84
- would connect to a LTE provider, giving the device an IP address on the LTE
85
- network.
86
-
87
- Using the Netlinker interface, Call netdev.NetConnect() to connect the device
88
- to an IP network. Call netdev.NetDisconnect() to disconnect. Continuing example:
90
+ Before the net package is fully functional, we need to connect the target to an
91
+ IP network.
89
92
90
93
``` go
94
+ package main
95
+
91
96
import (
92
- " tinygo.org/x/drivers/wifinina"
97
+ " tinygo.org/x/drivers/netlink"
98
+ " tinygo.org/x/drivers/netlink/probe"
93
99
)
94
100
95
101
func main () {
96
- cfg := wifinina.Config {Ssid: " foo" , Passphrase: " bar" }
97
- netdev := wifinina.New (&cfg)
98
102
99
- netdev.NetConnect ()
103
+ // load network driver for target
104
+ link , _ := probe.Probe ()
100
105
101
- // "net" package calls here
106
+ // Connect target to IP network
107
+ link.NetConnect (&netlink.ConnectParams {
108
+ Ssid: " my SSID" ,
109
+ Passphrase: " my passphrase" ,
110
+ })
102
111
103
- netdev.NetDisconnect ()
112
+ // OK to use "net" from here on
113
+ ...
104
114
}
105
115
```
106
116
107
117
Optionally, get notified of IP network connects and disconnects:
108
118
109
119
``` go
110
- netdev .Notify (func (e drivers. NetlinkEvent ) {
120
+ link .Notify (func (e netlink. Event ) {
111
121
switch e {
112
- case drivers.NetlinkEventNetUp :
113
- println (" Network UP" )
114
- case drivers.NetlinkEventNetDown :
115
- println (" Network DOWN" )
122
+ case netlink.EventNetUp : println (" Network UP" )
123
+ case netlink.EventNetDown : println (" Network DOWN" )
116
124
})
117
125
` ` `
118
126
119
- Here is a simple example of an http server listening on port :8080, before and
120
- after:
127
+ Here is an example of an http server listening on port :8080:
121
128
122
- #### Before
123
129
` ` ` go
124
130
package main
125
131
126
132
import (
127
133
" fmt"
128
134
" net/http"
129
- )
130
135
131
- func main () {
132
- http.HandleFunc (" /" , HelloServer)
133
- http.ListenAndServe (" :8080" , nil )
134
- }
136
+ " tinygo.org/x/drivers/netlink"
137
+ " tinygo.org/x/drivers/netlink/probe"
138
+ )
135
139
136
140
func HelloServer (w http.ResponseWriter , r *http.Request ) {
137
141
fmt.Fprintf (w, " Hello, %s !" , r.URL .Path [1 :])
138
142
}
139
- ` ` `
140
143
141
- #### After
142
- ` ` ` go
143
- package main
144
+ func main () {
144
145
145
- import (
146
- " fmt"
147
- " net/http"
146
+ // load network driver for target
147
+ link , _ := probe.Probe ()
148
148
149
- " tinygo.org/x/drivers/wifinina"
150
- )
151
-
152
- func main () {
153
- cfg := wifinina.Config {Ssid: " foo" , Passphrase: " bar" }
154
- netdev := wifinina.New (&cfg)
155
- netdev.NetConnect ()
149
+ // Connect target to IP network
150
+ link.NetConnect (&netlink.ConnectParams {
151
+ Ssid: " my SSID" ,
152
+ Passphrase: " my passphrase" ,
153
+ })
156
154
155
+ // Serve it up
157
156
http.HandleFunc (" /" , HelloServer)
158
157
http.ListenAndServe (" :8080" , nil )
159
158
}
160
-
161
- func HelloServer (w http.ResponseWriter , r *http.Request ) {
162
- fmt.Fprintf (w, " Hello, %s !" , r.URL .Path [1 :])
163
- }
164
159
` ` `
165
160
166
161
## Using "net/http" Package
@@ -191,99 +186,48 @@ protocol. This is different from Go's crypto/tls package which handles the TLS
191
186
protocol in software.
192
187
193
188
TinyGo's TLS support is only available for client applications. You can
194
- http.Get() to an http:// or https:// address, but you cannot
195
- http.ListenAndServeTLS() an https server.
189
+ http.Get() to an https:// address, but you cannot http.ListenAndServeTLS() an
190
+ https server.
196
191
197
192
The offloading hardware has pre-defined TLS certificates built-in.
198
193
199
194
## Using Sockets
200
195
201
- A netdev implements a BSD socket-like interface so an application can make direct
202
- socket calls, bypassing the net package.
196
+ The Netdever interface is a BSD socket-like interface so an application can make direct
197
+ socket calls, bypassing the " net" package for the lowest overhead .
203
198
204
- Here is a simple TCP application using direct sockets:
199
+ Here is a simple TCP client application using direct sockets:
205
200
206
201
` ` ` go
207
202
package main
208
203
209
204
import (
210
205
" net" // only need to parse IP address
211
206
212
- " tinygo.org/x/drivers"
213
- " tinygo.org/x/drivers/wifinina"
207
+ " tinygo.org/x/drivers/netdev"
208
+ " tinygo.org/x/drivers/netlink"
209
+ " tinygo.org/x/drivers/netlink/probe"
214
210
)
215
211
216
212
func main () {
217
- cfg := wifinina.Config {Ssid: " foo" , Passphrase: " bar" }
218
- netdev := wifinina.New (&cfg)
219
-
220
- // ignoring error handling
221
-
222
- netdev.NetConnect ()
223
-
224
- sock , _ := netdev.Socket (drivers.AF_INET , drivers.SOCK_STREAM , drivers.IPPROTO_TCP )
225
-
226
- netdev.Connect (sock, " " , net.ParseIP (" 10.0.0.100" ), 8080 )
227
- netdev.Send (sock, []bytes (" hello" ), 0 , 0 )
228
-
229
- netdev.Close (sock)
230
- }
231
- ` ` `
232
213
233
- ## Netdev and Netlink
214
+ // load network driver for target
215
+ link , dev := probe.Probe ()
234
216
235
- Netdev is TinyGo's network device driver model. Network drivers implement the
236
- netdever interface, providing a common network I/O interface to TinyGo's "net"
237
- package. The interface is modeled after the BSD socket interface. net.Conn
238
- implementations (TCPConn, UDPConn, and TLSConn) use the netdev interface for
239
- device I/O access. For example, net.DialTCP, which returns a net.TCPConn,
240
- calls netdev.Socket() and netdev.Connect():
217
+ // Connect target to IP network
218
+ link.NetConnect (&netlink.ConnectParams {
219
+ Ssid: " my SSID" ,
220
+ Passphrase: " my passphrase" ,
221
+ })
241
222
242
- ` ` ` go
243
- func DialTCP (network string , laddr, raddr *TCPAddr) (*TCPConn, error ) {
223
+ // omit error handling
244
224
245
- fd , _ := netdev .Socket (syscall .AF_INET , syscall .SOCK_STREAM , syscall .IPPROTO_TCP )
225
+ sock , _ := dev .Socket (netdev .AF_INET , netdev .SOCK_STREAM , netdev .IPPROTO_TCP )
246
226
247
- netdev.Connect (fd, " " , raddr.IP , raddr.Port )
227
+ dev.Connect (sock, " " , net.ParseIP (" 10.0.0.100" ), 8080 )
228
+ dev.Send (sock, []bytes (" hello" ), 0 , 0 )
248
229
249
- return &TCPConn{
250
- fd: fd,
251
- laddr: laddr,
252
- raddr: raddr,
253
- }, nil
230
+ dev.Close (sock)
231
+ link.NetDisconnect ()
254
232
}
255
233
` ` `
256
-
257
- Network drivers also (optionally) implement the Netlinker interface. This
258
- interface is not used by TinyGo's "net" package, but rather provides the TinyGo
259
- application direct access to the network device for common settings and control
260
- that fall outside of netdev's socket interface.
261
-
262
- ## Writing a New Netdev Driver
263
-
264
- A new netdev driver will implement the netdever and optionally the Netlinker
265
- interfaces. See the wifinina or rtl8720dn drivers for examples.
266
-
267
- #### Locking
268
-
269
- Multiple goroutines may invoke methods on a net.Conn simultaneously, and since
270
- the net package translates net.Conn calls into netdev socket calls, it follows
271
- that multiple goroutines may invoke socket calls, so locking is required to
272
- keep socket calls from stepping on one another.
273
-
274
- Don't hold a lock while Time.Sleep()ing waiting for a hardware operation to
275
- finish. Unlocking while sleeping let's other goroutines make progress. If the
276
- sleep period is really small, then you can get away with holding the lock.
277
-
278
- #### Sockfd
279
-
280
- The netdev socket interface uses a socket fd (int) to represent a socket
281
- connection (end-point). Each net.Conn maps 1:1 to a fd. The number of fds
282
- available is a hardware limitation. Wifinina, for example, can hand out 10
283
- fds.
284
-
285
- ### Testing
286
-
287
- The netdev driver should minimally run all of the example/net examples.
288
-
289
- TODO: automate testing to catch regressions.
0 commit comments