Skip to content

Commit

Permalink
espat: refactor net and tls interface compatible code into separate s…
Browse files Browse the repository at this point in the history
…ub-packages

Signed-off-by: Ron Evans <[email protected]>
  • Loading branch information
deadprogram committed Jul 15, 2019
1 parent 7e78e2c commit 50633f3
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 115 deletions.
4 changes: 4 additions & 0 deletions espat/espat.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ type Device struct {
socketdata []byte
}

// ActiveDevice is the currently configured Device in use. There can only be one.
var ActiveDevice *Device

// New returns a new espat driver. Pass in a fully configured UART bus.
func New(b machine.UART) *Device {
return &Device{bus: b, response: make([]byte, 512), socketdata: make([]byte, 0, 1024)}
}

// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
}

// Connected checks if there is communication with the ESP8266/ESP32.
Expand Down
8 changes: 5 additions & 3 deletions espat/mqtt/mqtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

"github.com/eclipse/paho.mqtt.golang/packets"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
"tinygo.org/x/drivers/espat/tls"
)

// NewClient will create an MQTT v3.1.1 client with all of the options specified
Expand All @@ -20,7 +22,7 @@ func NewClient(o *ClientOptions) Client {

type mqttclient struct {
adaptor *espat.Device
conn espat.Conn
conn net.Conn
connected bool
opts *ClientOptions
mid uint16
Expand Down Expand Up @@ -52,13 +54,13 @@ func (c *mqttclient) Connect() Token {
// make connection
if strings.Contains(c.opts.Servers, "ssl://") {
url := strings.TrimPrefix(c.opts.Servers, "ssl://")
c.conn, err = c.adaptor.DialTLS("tcp", url, nil)
c.conn, err = tls.Dial("tcp", url, nil)
if err != nil {
return &mqtttoken{err: err}
}
} else if strings.Contains(c.opts.Servers, "tcp://") {
url := strings.TrimPrefix(c.opts.Servers, "tcp://")
c.conn, err = c.adaptor.Dial("tcp", url)
c.conn, err = net.Dial("tcp", url)
if err != nil {
return &mqtttoken{err: err}
}
Expand Down
91 changes: 39 additions & 52 deletions espat/net.go → espat/net/net.go
Original file line number Diff line number Diff line change
@@ -1,113 +1,93 @@
package espat
// package net is intended to provide compatible interfaces with the
// Go standard library's net package.
package net

import (
"errors"
"strconv"
"strings"
"time"

"tinygo.org/x/drivers/espat"
)

// DialUDP makes a UDP network connection. raadr is the port that the messages will
// be sent to, and laddr is the port that will be listened to in order to
// receive incoming messages.
func (d *Device) DialUDP(network string, laddr, raddr *UDPAddr) (*UDPSerialConn, error) {
func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPSerialConn, error) {
addr := raddr.IP.String()
sendport := strconv.Itoa(raddr.Port)
listenport := strconv.Itoa(laddr.Port)

// disconnect any old socket
d.DisconnectSocket()
espat.ActiveDevice.DisconnectSocket()

// connect new socket
d.ConnectUDPSocket(addr, sendport, listenport)
espat.ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)

return &UDPSerialConn{SerialConn: SerialConn{Adaptor: d}, laddr: laddr, raddr: raddr}, nil
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr, raddr: raddr}, nil
}

// ListenUDP listens for UDP connections on the port listed in laddr.
func (d *Device) ListenUDP(network string, laddr *UDPAddr) (*UDPSerialConn, error) {
func ListenUDP(network string, laddr *UDPAddr) (*UDPSerialConn, error) {
addr := "0"
sendport := "0"
listenport := strconv.Itoa(laddr.Port)

// disconnect any old socket
d.DisconnectSocket()
espat.ActiveDevice.DisconnectSocket()

// connect new socket
d.ConnectUDPSocket(addr, sendport, listenport)
espat.ActiveDevice.ConnectUDPSocket(addr, sendport, listenport)

return &UDPSerialConn{SerialConn: SerialConn{Adaptor: d}, laddr: laddr}, nil
return &UDPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr}, nil
}

// DialTCP makes a TCP network connection. raadr is the port that the messages will
// be sent to, and laddr is the port that will be listened to in order to
// receive incoming messages.
func (d *Device) DialTCP(network string, laddr, raddr *TCPAddr) (*TCPSerialConn, error) {
func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPSerialConn, error) {
addr := raddr.IP.String()
sendport := strconv.Itoa(raddr.Port)

// disconnect any old socket
d.DisconnectSocket()
espat.ActiveDevice.DisconnectSocket()

// connect new socket
d.ConnectTCPSocket(addr, sendport)
espat.ActiveDevice.ConnectTCPSocket(addr, sendport)

return &TCPSerialConn{SerialConn: SerialConn{Adaptor: d}, laddr: laddr, raddr: raddr}, nil
return &TCPSerialConn{SerialConn: SerialConn{Adaptor: espat.ActiveDevice}, laddr: laddr, raddr: raddr}, nil
}

// Dial connects to the address on the named network.
// It tries to provide a mostly compatible interface
// to net.Dial().
func (d *Device) Dial(network, address string) (Conn, error) {
func Dial(network, address string) (Conn, error) {
switch network {
case "tcp":
raddr, err := d.ResolveTCPAddr(network, address)
raddr, err := ResolveTCPAddr(network, address)
if err != nil {
return nil, err
}

c, e := d.DialTCP(network, &TCPAddr{}, raddr)
c, e := DialTCP(network, &TCPAddr{}, raddr)
return c.opConn(), e
case "udp":
raddr, err := d.ResolveUDPAddr(network, address)
raddr, err := ResolveUDPAddr(network, address)
if err != nil {
return nil, err
}

c, e := d.DialUDP(network, &UDPAddr{}, raddr)
c, e := DialUDP(network, &UDPAddr{}, raddr)
return c.opConn(), e
default:
return nil, errors.New("invalid network for dial")
}
}

// DialTLS makes a TLS network connection. It tries to provide a mostly compatible interface
// to tls.Dial().
// DialTLS connects to the given network address.
func (d *Device) DialTLS(network, address string, config *TLSConfig) (*TCPSerialConn, error) {
raddr, err := d.ResolveTCPAddr(network, address)
if err != nil {
return nil, err
}

addr := raddr.IP.String()
sendport := strconv.Itoa(raddr.Port)

// disconnect any old socket
d.DisconnectSocket()

// connect new socket
err = d.ConnectSSLSocket(addr, sendport)
if err != nil {
return nil, err
}

return &TCPSerialConn{SerialConn: SerialConn{Adaptor: d}, raddr: raddr}, nil
}

// SerialConn is a loosely net.Conn compatible implementation
type SerialConn struct {
Adaptor *Device
Adaptor *espat.Device
}

// UDPSerialConn is a loosely net.Conn compatible intended to support
Expand All @@ -118,6 +98,11 @@ type UDPSerialConn struct {
raddr *UDPAddr
}

// NewUDPSerialConn returns a new UDPSerialConn/
func NewUDPSerialConn(c SerialConn, laddr, raddr *UDPAddr) *UDPSerialConn {
return &UDPSerialConn{SerialConn: c, raddr: raddr}
}

// TCPSerialConn is a loosely net.Conn compatible intended to support
// TCP over serial.
type TCPSerialConn struct {
Expand All @@ -126,6 +111,11 @@ type TCPSerialConn struct {
raddr *TCPAddr
}

// NewTCPSerialConn returns a new TCPSerialConn/
func NewTCPSerialConn(c SerialConn, laddr, raddr *TCPAddr) *TCPSerialConn {
return &TCPSerialConn{SerialConn: c, raddr: raddr}
}

// Read reads data from the connection.
// TODO: implement the full method functionality:
// Read can be made to time out and return an Error with Timeout() == true
Expand Down Expand Up @@ -226,14 +216,15 @@ func (c *SerialConn) SetWriteDeadline(t time.Time) error {
//
// The network must be a TCP network name.
//
func (d *Device) ResolveTCPAddr(network, address string) (*TCPAddr, error) {
func ResolveTCPAddr(network, address string) (*TCPAddr, error) {
// TODO: make sure network is 'tcp'
// separate domain from port, if any
r := strings.Split(address, ":")
ip, err := d.GetDNS(r[0])
addr, err := espat.ActiveDevice.GetDNS(r[0])
if err != nil {
return nil, err
}
ip := IP(addr)
if len(r) > 1 {
port, e := strconv.Atoi(r[1])
if e != nil {
Expand All @@ -248,14 +239,15 @@ func (d *Device) ResolveTCPAddr(network, address string) (*TCPAddr, error) {
//
// The network must be a UDP network name.
//
func (d *Device) ResolveUDPAddr(network, address string) (*UDPAddr, error) {
func ResolveUDPAddr(network, address string) (*UDPAddr, error) {
// TODO: make sure network is 'udp'
// separate domain from port, if any
r := strings.Split(address, ":")
ip, err := d.GetDNS(r[0])
addr, err := espat.ActiveDevice.GetDNS(r[0])
if err != nil {
return nil, err
}
ip := IP(addr)
if len(r) > 1 {
port, e := strconv.Atoi(r[1])
if e != nil {
Expand Down Expand Up @@ -339,11 +331,6 @@ func (ip IP) String() string {
return string(ip)
}

// TLSConfig is a placeholder for future compatibility with
// tls.Config.
type TLSConfig struct {
}

// Conn is a generic stream-oriented network connection.
// This interface is from the Go standard library.
type Conn interface {
Expand Down
6 changes: 3 additions & 3 deletions espat/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ const (
)

// GetDNS returns the IP address for a domain name.
func (d *Device) GetDNS(domain string) (IP, error) {
func (d *Device) GetDNS(domain string) (string, error) {
d.Set(TCPDNSLookup, "\""+domain+"\"")
r := strings.Split(string(d.Response(1000)), ":")
if len(r) != 2 {
return nil, errors.New("Invalid domain lookup result")
return "", errors.New("Invalid domain lookup result")
}
res := strings.Split(r[1], "\r\n")
return IP(res[0]), nil
return res[0], nil
}

// ConnectTCPSocket creates a new TCP socket connection for the ESP8266/ESP32.
Expand Down
39 changes: 39 additions & 0 deletions espat/tls/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Package tls is intended to provide a minimal set of compatible interfaces with the
// Go standard library's tls package.
package tls

import (
"strconv"

"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/espat/net"
)

// Dial makes a TLS network connection. It tries to provide a mostly compatible interface
// to tls.Dial().
// Dial connects to the given network address.
func Dial(network, address string, config *Config) (*net.TCPSerialConn, error) {
raddr, err := net.ResolveTCPAddr(network, address)
if err != nil {
return nil, err
}

addr := raddr.IP.String()
sendport := strconv.Itoa(raddr.Port)

// disconnect any old socket
espat.ActiveDevice.DisconnectSocket()

// connect new socket
err = espat.ActiveDevice.ConnectSSLSocket(addr, sendport)
if err != nil {
return nil, err
}

return net.NewTCPSerialConn(net.SerialConn{Adaptor: espat.ActiveDevice}, nil, raddr), nil
}

// Config is a placeholder for future compatibility with
// tls.Config.
type Config struct {
}
Loading

0 comments on commit 50633f3

Please sign in to comment.