cli/port_forwarder.go
2021-07-23 01:17:32 +00:00

64 lines
1.4 KiB
Go

package liveshare
import (
"context"
"fmt"
"io"
"net"
"strconv"
)
// A PortForwader can forward ports from a remote liveshare host to localhost
type PortForwarder struct {
client *Client
server *Server
port int
errCh chan error
}
// NewPortForwarder creates a new PortForwader with a given client, server and port
func NewPortForwarder(client *Client, server *Server, port int) *PortForwarder {
return &PortForwarder{
client: client,
server: server,
port: port,
errCh: make(chan error),
}
}
// Start is a method to start forwarding the server to a localhost port
func (l *PortForwarder) Start(ctx context.Context) error {
ln, err := net.Listen("tcp", ":"+strconv.Itoa(l.port))
if err != nil {
return fmt.Errorf("error listening on tcp port: %v", err)
}
for {
conn, err := ln.Accept()
if err != nil {
return fmt.Errorf("error accepting incoming connection: %v", err)
}
go l.handleConnection(ctx, conn)
}
return nil
}
func (l *PortForwarder) handleConnection(ctx context.Context, conn net.Conn) {
channel, err := l.client.openStreamingChannel(ctx, l.server.streamName, l.server.streamCondition)
if err != nil {
l.errCh <- fmt.Errorf("error opening streaming channel for new connection: %v", err)
return
}
copyConn := func(writer io.Writer, reader io.Reader) {
if _, err := io.Copy(writer, reader); err != nil {
channel.Close()
conn.Close()
}
}
go copyConn(conn, channel)
go copyConn(channel, conn)
}