mirror of
https://github.com/tinygo-org/net.git
synced 2026-07-26 08:18:39 +00:00
693edae782
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).
155 lines
3.5 KiB
Go
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
|
|
}
|