Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
vikulin committed Dec 20, 2023
1 parent ea7dc66 commit 197d153
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ require (
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/rivo/uniseg v0.3.4 // indirect
github.com/stretchr/testify v1.8.0 // indirect
github.com/vikulin/sctp v0.0.0-20221009200520-ae0f2830e422 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/sync v0.3.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/vikulin/sctp v0.0.0-20221009200520-ae0f2830e422 h1:KJn6ovcNlavPTgdK2uKJoonWPP3GTb8x4FyYPIrwpZw=
github.com/vikulin/sctp v0.0.0-20221009200520-ae0f2830e422/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
Expand Down
7 changes: 7 additions & 0 deletions src/core/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type links struct {
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
quic *linkQUIC // QUIC interface support
sctp *linkSCTP // QUIC interface support

Check failure on line 39 in src/core/link.go

View workflow job for this annotation

GitHub Actions / Build & Test (macOS, Go 1.21)

undefined: linkSCTP

Check failure on line 39 in src/core/link.go

View workflow job for this annotation

GitHub Actions / Build & Test (Windows, Go 1.21)

undefined: linkSCTP
// _links can only be modified safely from within the links actor
_links map[linkInfo]*link // *link is nil if connection in progress
}
Expand Down Expand Up @@ -95,6 +96,7 @@ func (l *links) init(c *Core) error {
l.unix = l.newLinkUNIX()
l.socks = l.newLinkSOCKS()
l.quic = l.newLinkQUIC()
l.sctp = l.newLinkSCTP()

Check failure on line 99 in src/core/link.go

View workflow job for this annotation

GitHub Actions / Build & Test (macOS, Go 1.21)

l.newLinkSCTP undefined (type *links has no field or method newLinkSCTP)

Check failure on line 99 in src/core/link.go

View workflow job for this annotation

GitHub Actions / Build & Test (Windows, Go 1.21)

l.newLinkSCTP undefined (type *links has no field or method newLinkSCTP)
l._links = make(map[linkInfo]*link)

var listeners []ListenAddress
Expand Down Expand Up @@ -421,6 +423,8 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
protocol = l.unix
case "quic":
protocol = l.quic
case "sctp":
protocol = l.sctp
default:
cancel()
return nil, ErrLinkUnrecognisedSchema
Expand Down Expand Up @@ -549,6 +553,9 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
dialer = l.unix
case "quic":
dialer = l.quic
case "sctp":
dialer = l.sctp

default:
return nil, ErrLinkUnrecognisedSchema
}
Expand Down
125 changes: 125 additions & 0 deletions src/core/link_sctp_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//go:build linux
// +build linux

package core

import (
"context"
"net"
"net/url"
"strconv"
"strings"

"github.com/Arceliar/phony"
sctp "github.com/vikulin/sctp"
)

type linkSCTP struct {
phony.Inbox
*links
listener *net.ListenConfig
_listeners map[*Listener]context.CancelFunc
}

func (l *links) newLinkSCTP() *linkSCTP {
lt := &linkSCTP{
links: l,
listener: &net.ListenConfig{
KeepAlive: -1,
},
_listeners: map[*Listener]context.CancelFunc{},
}
return lt
}

func (l *linkSCTP) dial(tx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
host, port, err := net.SplitHostPort(url.Host)
if err != nil {
return nil, err
}
dst, err := net.ResolveIPAddr("ip", host)
if err != nil {
return nil, err
}
raddress := l.getAddress(dst.String() + ":" + port)
var conn net.Conn
laddress := l.getAddress("0.0.0.0:0")
conn, err = sctp.NewSCTPConnection(laddress, laddress.AddressFamily, sctp.InitMsg{NumOstreams: 2, MaxInstreams: 2, MaxAttempts: 2, MaxInitTimeout: 5}, sctp.OneToOne, false)
if err != nil {
return nil, err
}
err = conn.(*sctp.SCTPConn).Connect(raddress)
if err != nil {
return nil, err
}
//conn.(*sctp.SCTPConn).SetWriteBuffer(324288)
//conn.(*sctp.SCTPConn).SetReadBuffer(324288)
//wbuf, _ := conn.(*sctp.SCTPConn).GetWriteBuffer()
//rbuf, _ := conn.(*sctp.SCTPConn).GetReadBuffer()

//l.core.log.Printf("Read buffer %d", rbuf)
//l.core.log.Printf("Write buffer %d", wbuf)
err = conn.(*sctp.SCTPConn).SetEvents(sctp.SCTP_EVENT_DATA_IO)
if err != nil {
return nil, err
}

return conn, nil
}

func (l *linkSCTP) listen(ctx context.Context, url *url.URL, sintf string) (net.Listener, error) {
addr := l.getAddress(url.Host)
listener, err := sctp.NewSCTPListener(addr, sctp.InitMsg{NumOstreams: 2, MaxInstreams: 2, MaxAttempts: 2, MaxInitTimeout: 5}, sctp.OneToOne, false)

if err != nil {
//cancel()
return nil, err
}
err = listener.SetEvents(sctp.SCTP_EVENT_DATA_IO)
if err != nil {
return nil, err
}

return listener, nil
}

// Returns the address of the listener.
//
//nolint:unused
func (l *linkSCTP) getAddr() *net.TCPAddr {
// TODO: Fix this, because this will currently only give a single address
// to multicast.go, which obviously is not great, but right now multicast.go
// doesn't have the ability to send more than one address in a packet either
var addr *net.TCPAddr
phony.Block(l, func() {
for listener := range l._listeners {
addr = listener.Addr().(*net.TCPAddr)
}
})
return addr
}

// SCTP infrastructure
func (l *linkSCTP) getAddress(host string) *sctp.SCTPAddr {

//sctp supports multihoming but current implementation reuires only one path
ips := []net.IPAddr{}
ip, port, err := net.SplitHostPort(host)
if err != nil {
panic(err)
}
for _, i := range strings.Split(ip, ",") {
if a, err := net.ResolveIPAddr("ip", i); err == nil {
l.core.log.Printf("Resolved address '%s' to %s", i, a)
ips = append(ips, *a)
} else {
l.core.log.Errorln("Error resolving address '%s': %v", i, err)
}
}
p, _ := strconv.Atoi(port)
addr := &sctp.SCTPAddr{
IPAddrs: ips,
Port: p,
}
return addr
}

0 comments on commit 197d153

Please sign in to comment.