77 lines
1.5 KiB
Go
77 lines
1.5 KiB
Go
package gost
|
|
|
|
import (
|
|
"net"
|
|
"strconv"
|
|
|
|
"github.com/mdlayher/vsock"
|
|
)
|
|
|
|
// vsockTransporter is a raw VSOCK transporter.
|
|
type vsockTransporter struct{}
|
|
|
|
// VSOCKTransporter creates a raw VSOCK client.
|
|
func VSOCKTransporter() Transporter {
|
|
return &vsockTransporter{}
|
|
}
|
|
|
|
func (tr *vsockTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
|
opts := &DialOptions{}
|
|
for _, option := range options {
|
|
option(opts)
|
|
}
|
|
if opts.Chain == nil {
|
|
vAddr, err := parseAddr(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return vsock.Dial(vAddr.ContextID, vAddr.Port, nil)
|
|
}
|
|
return opts.Chain.Dial(addr)
|
|
}
|
|
|
|
func parseUint32(s string) (uint32, error ) {
|
|
n, err := strconv.ParseUint(s, 10, 32)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return uint32(n), nil
|
|
}
|
|
|
|
func parseAddr(addr string) (*vsock.Addr, error) {
|
|
hostStr, portStr, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
host := uint32(0)
|
|
if hostStr != "" {
|
|
host, err = parseUint32(hostStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
port, err := parseUint32(portStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &vsock.Addr{ContextID: host, Port: port}, nil
|
|
}
|
|
|
|
func (tr *vsockTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
|
return conn, nil
|
|
}
|
|
|
|
func (tr *vsockTransporter) Multiplex() bool {
|
|
return false
|
|
}
|
|
|
|
// VSOCKListener creates a Listener for VSOCK proxy server.
|
|
func VSOCKListener(addr string) (Listener, error) {
|
|
vAddr, err := parseAddr(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return vsock.Listen(vAddr.Port, nil)
|
|
}
|