64 lines
1.4 KiB
Go
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)
|
|
}
|