Files
net/tlssock.go
T
Scott Feldman 693edae782 Add network device driver model, netdev
This PR adds a network device driver model called netdev. There will be a companion PR for TinyGo drivers to update the netdev drivers and network examples. This PR covers the core "net" package.

An RFC for the work is here: #tinygo-org/drivers#487. Some things have changed from the RFC, but nothing major.

The "net" package is a partial port of Go's "net" package, version 1.19.3. The src/net/README file has details on what is modified from Go's "net" package.

Most "net" features are working as they would in normal Go. TCP/UDP/TLS protocol support is there. As well as HTTP client and server support. Standard Go network packages such as golang.org/x/net/websockets and Paho MQTT client work as-is. Other packages are likely to work as-is.

Testing results are here (https://docs.google.com/spreadsheets/d/e/2PACX-1vT0cCjBvwXf9HJf6aJV2Sw198F2ief02gmbMV0sQocKT4y4RpfKv3dh6Jyew8lQW64FouZ8GwA2yjxI/pubhtml?gid=1013173032&single=true).
2023-07-07 20:00:29 +02:00

155 lines
3.5 KiB
Go

// TINYGO: The following is copied and modified from Go 1.19.3 official implementation.
// Copyright 2010 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.
// TLS low level connection and record layer
package net
import (
"fmt"
"strconv"
"syscall"
"time"
)
func DialTLS(addr string) (*TLSConn, error) {
host, sport, err := SplitHostPort(addr)
if err != nil {
return nil, err
}
port, err := strconv.Atoi(sport)
if err != nil {
return nil, err
}
if port == 0 {
port = 443
}
fd, err := netdev.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TLS)
if err != nil {
return nil, err
}
if err = netdev.Connect(fd, host, IP{}, port); err != nil {
netdev.Close(fd)
return nil, err
}
return &TLSConn{
fd: fd,
}, nil
}
// A TLSConn represents a secured connection.
// It implements the net.Conn interface.
type TLSConn struct {
fd int
readDeadline time.Time
writeDeadline time.Time
}
// Access to net.Conn methods.
// Cannot just embed net.Conn because that would
// export the struct field too.
// LocalAddr returns the local network address.
func (c *TLSConn) LocalAddr() Addr {
// TODO
return nil
}
// RemoteAddr returns the remote network address.
func (c *TLSConn) RemoteAddr() Addr {
// TODO
return nil
}
// SetDeadline sets the read and write deadlines associated with the connection.
// A zero value for t means Read and Write will not time out.
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func (c *TLSConn) SetDeadline(t time.Time) error {
c.readDeadline = t
c.writeDeadline = t
return nil
}
// SetReadDeadline sets the read deadline on the underlying connection.
// A zero value for t means Read will not time out.
func (c *TLSConn) SetReadDeadline(t time.Time) error {
c.readDeadline = t
return nil
}
// SetWriteDeadline sets the write deadline on the underlying connection.
// A zero value for t means Write will not time out.
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func (c *TLSConn) SetWriteDeadline(t time.Time) error {
c.writeDeadline = t
return nil
}
func (c *TLSConn) Read(b []byte) (int, error) {
var timeout time.Duration
now := time.Now()
if !c.readDeadline.IsZero() {
if c.readDeadline.Before(now) {
return 0, fmt.Errorf("Read deadline expired")
} else {
timeout = c.readDeadline.Sub(now)
}
}
n, err := netdev.Recv(c.fd, b, 0, timeout)
// Turn the -1 socket error into 0 and let err speak for error
if n < 0 {
n = 0
}
return n, err
}
func (c *TLSConn) Write(b []byte) (int, error) {
var timeout time.Duration
now := time.Now()
if !c.writeDeadline.IsZero() {
if c.writeDeadline.Before(now) {
return 0, fmt.Errorf("Write deadline expired")
} else {
timeout = c.writeDeadline.Sub(now)
}
}
n, err := netdev.Send(c.fd, b, 0, timeout)
// Turn the -1 socket error into 0 and let err speak for error
if n < 0 {
n = 0
}
return n, err
}
func (c *TLSConn) Close() error {
return netdev.Close(c.fd)
}
// Handshake runs the client or server handshake
// protocol if it has not yet been run.
//
// Most uses of this package need not call Handshake explicitly: the
// first Read or Write will call it automatically.
//
// For control over canceling or setting a timeout on a handshake, use
// HandshakeContext or the Dialer's DialContext method instead.
func (c *TLSConn) Handshake() error {
panic("TLSConn.Handshake() not implemented")
return nil
}