Skip to content

Commit

Permalink
support TLS
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdimidium committed Apr 24, 2024
1 parent 013c55f commit 9ca281d
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ ragel:
lint:
golangci-lint run ./...

.PHONY: tlsgen
tlsgen:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 1

.PHONY: update-pebble
update-pebble:
go mod edit -replace github.com/cockroachdb/pebble=github.com/drpcorg/pebble@master
Expand Down
31 changes: 31 additions & 0 deletions toytlv/cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFQzCCAyugAwIBAgIUXkqeHsvnkiMe4yjySqigWAaryVYwDQYJKoZIhvcNAQEL
BQAwMTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoM
BGRSUEMwHhcNMjQwNDI0MDcxODExWhcNMjcwMTE4MDcxODExWjAxMQswCQYDVQQG
EwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UECgwEZFJQQzCCAiIwDQYJ
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL6HOs+h2TWFXdbQGs3dBxYhqFSB81pe
gLxkeRd1hvwDTbm6W4MuXBfpV8akd2P6kpa+2VxdWRsx9q1CskvsIsHS6XE/qKPr
9nx1jgNmzQ5KiKkT0RcIWMkR09rhUy5qx7N7yqa2zrdtMYvQUOo563Nl/hwD/495
wQgFd4w56f9UIBjbnf9V/iV/+ic00on95xmlkx3/F3ug2iDbS6CrVZOWPDj1p4Lk
27bxUTY7EpC23eF5iyDth1cwgRxVDIps5Fz6g3iOH8h55qmwnqx9c+t7VaKHnOJE
onHLxiitoTbzyJ7XAXO61foHDFdmuIuO/9PzDdpiFwYQBO1GcicsWjmoLrlOx2oe
tb1+uBy9PM/00U7n0a059Ekuv4acme+I6IHCgdKERbb2bro5d5ncM6shoGSWY3MU
mqDXP4DoElbO8Q0CStFTrKmT0d4dTHEuJcbD4ZYBPrRJOV1jjoDlQzlZAES4tJMj
Wp04G6WwnMFmdBkUyE2V4Xt00jkc1k1C9tXnjTu3BHL+YYiS5b2R2d3A2o9c35w7
LyFQ6K7WaAus6Rnj8uqS0O25TOfsHCERpJavK/WOE47vnZDfDgpTDhNiPMMz1W8S
N0557FjtLYfI3B8JHMldFZR4n1VYfEg5HL/6KU3S7OIQSGgq/6Bmd6AO9chlibg9
xBrmDGqakNkHAgMBAAGjUzBRMB0GA1UdDgQWBBTvhR8YVgQ18f+qFJ9j+YitMhPj
EjAfBgNVHSMEGDAWgBTvhR8YVgQ18f+qFJ9j+YitMhPjEjAPBgNVHRMBAf8EBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCHkGRnAo0eLt/gahxm2ey6X4nNw/av1TBa
xdbSIXfubam8kdddHs6Yk3Dnxim/DDmRN292TeeoWCc3IsbmQyPv0iptTd27hMDj
d8casciVJlB9x9TYjsfWf5b9e/cIatWYC6dk1G7lK0Yci2WgEBShXgu/Ba/SqyFN
k1hzoSFIQ+j9twPoPv1ZxDJ0AqZiwbFOpDvw8YplVgJ7ovAi07LtAXBxoPARqHkV
NIxsktHn4b0CprBjkQC2XXP8IDjLYmvnDAGUiQOMluOB2LaISc4RIubv/bcTsTh9
1FgawcD/tckeUZBaowzVu2bZ3o3VIhf2HEnFkesnqSTjn1pgjg2232tzHvc+o4xG
MpArlPGwVjGJPR/vZRa7d00b2O5CbfNcPin3EsWKeIYCaLZbZk/6fYK9sHXhbUOu
cEWuIzdXm/LPZbHm+tzVAmROArtMMeq1D+ugWqYJ63w/D6aDAygcEVyO62F1Cw7V
QH7puwfa9y48tvr43emnQwGTI3dv6Ikxs+ApHZImTPdzDdrBaRDyE9Ltr4Tq2czu
iD3W61pLaaSuVEMHzYYcTuo+lRVCdTG7ahEIDTxvWuTIJ1E2O/C5XxoduidGgZsM
YH/o06eoIdVP2Y7IPRJoI85r4DRmad1Iv38ZwpVL86MwNy9Rt1tQadaSQb43SQb/
QdO9DkM7Mg==
-----END CERTIFICATE-----
54 changes: 54 additions & 0 deletions toytlv/key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
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
ppVc8JF88cLzaXBX8tf5Ow==
-----END ENCRYPTED PRIVATE KEY-----
18 changes: 0 additions & 18 deletions toytlv/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,6 @@ import (
"github.com/drpcorg/chotki/toyqueue"
)

type ConnType = uint

const (
TCP ConnType = iota + 1
TLS
QUIC
)

const (
TYPICAL_MTU = 1500
MAX_OUT_QUEUE_LEN = 1 << 20 // 16MB of pointers is a lot

MAX_RETRY_PERIOD = time.Minute
MIN_RETRY_PERIOD = time.Second / 2
)

type Jack func(conn net.Conn) toyqueue.FeedDrainCloser

type Peer struct {
conn atomic.Pointer[net.Conn]
inout toyqueue.FeedDrainCloser
Expand Down
1 change: 1 addition & 0 deletions toytlv/tlv.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
const CaseBit uint8 = 'a' - 'A'

var (
ErrAddressInvalid = errors.New("the address invalid")
ErrAddressDuplicated = errors.New("the address already used")

ErrIncomplete = errors.New("incomplete data")
Expand Down
142 changes: 139 additions & 3 deletions toytlv/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,40 @@ package toytlv

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"log/slog"
"net"
"net/url"
"os"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/drpcorg/chotki/toyqueue"
"golang.org/x/exp/constraints"
)

type ConnType = uint

const (
TCP ConnType = iota + 1
TLS
QUIC
)

const (
TYPICAL_MTU = 1500
MAX_OUT_QUEUE_LEN = 1 << 20 // 16MB of pointers is a lot

MAX_RETRY_PERIOD = time.Minute
MIN_RETRY_PERIOD = time.Second / 2
)

type Jack func(conn net.Conn) toyqueue.FeedDrainCloser

// A TCP/TLS/QUIC server/client for the use case of real-time async communication.
// Differently from the case of request-response (like HTTP), we do not
// wait for a request, then dedicating a thread to processing, then sending
Expand All @@ -26,6 +51,9 @@ type Transport struct {

conns sync.Map // *Peer
listens sync.Map // net.Listener

CertFile, KeyFile string
ClientCertFiles []string
}

func NewTransport(jack Jack) *Transport {
Expand Down Expand Up @@ -80,11 +108,36 @@ func (de *Transport) Disconnect(addr string) (err error) {
}

func (t *Transport) Listen(ctx context.Context, addr string) error {
listener, err := net.Listen("tcp", addr)
connType, address, err := parseAddr(addr)
if err != nil {
return err
}

var listener net.Listener
switch connType {
case TCP:
config := net.ListenConfig{}
if listener, err = config.Listen(ctx, "tcp", address); err != nil {
return err
}

case TLS:
config := net.ListenConfig{}
if listener, err = config.Listen(ctx, "tcp", address); err != nil {
return err
}

tlsConfig, err := t.tlsConfig()
if err != nil {
return err
}

listener = tls.NewListener(listener, tlsConfig)

case QUIC:
return errors.New("QUIC unimplemented")
}

if _, ok := t.listens.LoadOrStore(addr, listener); ok {
listener.Close()
return ErrAddressDuplicated
Expand Down Expand Up @@ -120,13 +173,13 @@ func (t *Transport) KeepConnecting(ctx context.Context, addr string) {
for !t.closed.Load() {
time.Sleep(connBackoff + talkBackoff)

conn, err := net.Dial("tcp", addr)
conn, err := t.createDialConnect(ctx, addr)
if err != nil {
slog.Error("couldn't connect", "addr", addr, "err", err)
connBackoff = min(MAX_RETRY_PERIOD, connBackoff*2)
continue
}

connBackoff = MIN_RETRY_PERIOD

peer := &Peer{inout: t.jack(conn)}
Expand Down Expand Up @@ -207,6 +260,89 @@ func (t *Transport) keepPeer(ctx context.Context, addr string, peer *Peer) error
return nil
}

func (t *Transport) createDialConnect(ctx context.Context, addr string) (net.Conn, error) {
connType, address, err := parseAddr(addr)
if err != nil {
return nil, err
}

var conn net.Conn
switch connType {
case TCP:
var d net.Dialer
if conn, err = d.DialContext(ctx, "tcp", address); err != nil {
return nil, err
}

case TLS:
var d tls.Dialer
if d.Config, err = t.tlsConfig(); err != nil {
return nil, err
}

if conn, err = d.DialContext(ctx, "tcp", address); err != nil {
return nil, err
}

case QUIC:
return nil, errors.New("QUIC unimplemented")
}

return conn, err
}

func (t *Transport) tlsConfig() (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(t.CertFile, t.KeyFile)
if err != nil {
return nil, err
}

tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS13,
Certificates: []tls.Certificate{cert},
}

if len(t.ClientCertFiles) > 0 {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
tlsConfig.ClientCAs = x509.NewCertPool()

for _, file := range t.ClientCertFiles {
if clientCert, err := os.ReadFile(file); err != nil {
return nil, err
} else {
tlsConfig.ClientCAs.AppendCertsFromPEM(clientCert)
}
}
}

return tlsConfig, nil
}

func parseAddr(addr string) (ConnType, string, error) {
u, err := url.Parse(addr)
if err != nil {
return TCP, "", err
}

var conn ConnType

switch u.Scheme {
case "", "tcp", "tcp4", "tcp6":
conn = TCP
case "tls":
conn = TLS
case "quic":
conn = QUIC
default:
return conn, addr, ErrAddressInvalid
}

u.Scheme = ""
address := strings.TrimPrefix(u.String(), "//")

return conn, address, nil
}

func min[T constraints.Ordered](s ...T) T {
if len(s) == 0 {
var zero T
Expand Down
10 changes: 9 additions & 1 deletion toytlv/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ func (c *TestConsumer) Close() error {
}

func TestTCPDepot_Connect(t *testing.T) {
loop := "127.0.0.1:32000"
loop := "tcp://127.0.0.1:32000"

cert, key := "cert.pem", "key.pem"

lCon := TestConsumer{}
lCon.co.L = &lCon.mx
Expand All @@ -58,6 +60,9 @@ func TestTCPDepot_Connect(t *testing.T) {
err := l.Listen(context.Background(), loop)
assert.Nil(t, err)

l.CertFile = cert
l.KeyFile = key

cCon := TestConsumer{}
cCon.co.L = &cCon.mx
c := NewTransport(func(conn net.Conn) toyqueue.FeedDrainCloser {
Expand All @@ -66,6 +71,9 @@ func TestTCPDepot_Connect(t *testing.T) {
err = c.Connect(context.Background(), loop)
assert.Nil(t, err)

c.CertFile = cert
c.KeyFile = key

time.Sleep(time.Second * 2) // TODO: use events

// send a record
Expand Down

0 comments on commit 9ca281d

Please sign in to comment.