@@ -2,20 +2,18 @@ package portfwd
22
33import (
44 "context"
5- "errors"
65 "fmt"
7- "io"
86 "net"
7+ "time"
98
9+ "github.com/containers/gvisor-tap-vsock/pkg/services/forwarder"
10+ "github.com/lima-vm/lima/pkg/bicopy"
1011 "github.com/lima-vm/lima/pkg/guestagent/api"
1112 guestagentclient "github.com/lima-vm/lima/pkg/guestagent/api/client"
1213 "github.com/sirupsen/logrus"
13- "golang.org/x/sync/errgroup"
1414)
1515
1616func HandleTCPConnection (ctx context.Context , client * guestagentclient.GuestAgentClient , conn net.Conn , guestAddr string ) {
17- defer conn .Close ()
18-
1917 id := fmt .Sprintf ("tcp-%s-%s" , conn .LocalAddr ().String (), conn .RemoteAddr ().String ())
2018
2119 stream , err := client .Tunnel (ctx )
@@ -24,26 +22,17 @@ func HandleTCPConnection(ctx context.Context, client *guestagentclient.GuestAgen
2422 return
2523 }
2624
27- g , _ := errgroup .WithContext (ctx )
28-
29- rw := & GrpcClientRW {stream : stream , id : id , addr : guestAddr }
30- g .Go (func () error {
31- _ , err := io .Copy (rw , conn )
32- return err
33- })
34- g .Go (func () error {
35- _ , err := io .Copy (conn , rw )
36- return err
37- })
38-
39- if err := g .Wait (); err != nil {
40- logrus .Debugf ("error in tcp tunnel for id: %s error:%v" , id , err )
25+ // Handshake message to start tunnel
26+ if err := stream .Send (& api.TunnelMessage {Id : id , Protocol : "tcp" , GuestAddr : guestAddr }); err != nil {
27+ logrus .Errorf ("could not start tcp tunnel for id: %s error:%v" , id , err )
28+ return
4129 }
30+
31+ rw := & GrpcClientRW {stream : stream , id : id , addr : guestAddr , protocol : "tcp" }
32+ bicopy .Bicopy (rw , conn , nil )
4233}
4334
4435func HandleUDPConnection (ctx context.Context , client * guestagentclient.GuestAgentClient , conn net.PacketConn , guestAddr string ) {
45- defer conn .Close ()
46-
4736 id := fmt .Sprintf ("udp-%s" , conn .LocalAddr ().String ())
4837
4938 stream , err := client .Tunnel (ctx )
@@ -52,98 +41,82 @@ func HandleUDPConnection(ctx context.Context, client *guestagentclient.GuestAgen
5241 return
5342 }
5443
55- g , _ := errgroup .WithContext (ctx )
56-
57- g .Go (func () error {
58- buf := make ([]byte , 65507 )
59- for {
60- n , addr , err := conn .ReadFrom (buf )
61- // We must handle n > 0 bytes before considering the error.
62- // https://pkg.go.dev/net#PacketConn
63- if n > 0 {
64- msg := & api.TunnelMessage {
65- Id : id + "-" + addr .String (),
66- Protocol : "udp" ,
67- GuestAddr : guestAddr ,
68- Data : buf [:n ],
69- UdpTargetAddr : addr .String (),
70- }
71- if err := stream .Send (msg ); err != nil {
72- return err
73- }
74- }
75- if err != nil {
76- // https://pkg.go.dev/net#PacketConn does not mention io.EOF semantics.
77- if errors .Is (err , io .EOF ) {
78- return nil
79- }
80- return err
81- }
82- }
83- })
44+ // Handshake message to start tunnel
45+ if err := stream .Send (& api.TunnelMessage {Id : id , Protocol : "udp" , GuestAddr : guestAddr }); err != nil {
46+ logrus .Errorf ("could not start udp tunnel for id: %s error:%v" , id , err )
47+ return
48+ }
8449
85- g .Go (func () error {
86- for {
87- // Not documented: when err != nil, in is always nil.
88- in , err := stream .Recv ()
89- if err != nil {
90- if errors .Is (err , io .EOF ) {
91- return nil
92- }
93- return err
94- }
95- addr , err := net .ResolveUDPAddr ("udp" , in .UdpTargetAddr )
96- if err != nil {
97- return err
98- }
99- _ , err = conn .WriteTo (in .Data , addr )
100- if err != nil {
101- return err
102- }
103- }
50+ proxy , err := forwarder .NewUDPProxy (conn , func () (net.Conn , error ) {
51+ rw := & GrpcClientRW {stream : stream , id : id , addr : guestAddr , protocol : "udp" }
52+ return rw , nil
10453 })
105-
106- if err := g . Wait (); err != nil {
107- logrus . Debugf ( "error in udp tunnel for id: %s error:%v" , id , err )
54+ if err != nil {
55+ logrus . Errorf ( "error in udp tunnel proxy for id: %s error:%v" , id , err )
56+ return
10857 }
58+
59+ defer func () {
60+ err := proxy .Close ()
61+ if err != nil {
62+ logrus .Errorf ("error in closing udp tunnel proxy for id: %s error:%v" , id , err )
63+ }
64+ }()
65+ proxy .Run ()
10966}
11067
11168type GrpcClientRW struct {
112- id string
113- addr string
114- stream api.GuestService_TunnelClient
69+ id string
70+ addr string
71+
72+ protocol string
73+ stream api.GuestService_TunnelClient
11574}
11675
117- var _ io. ReadWriter = (* GrpcClientRW )(nil )
76+ var _ net. Conn = (* GrpcClientRW )(nil )
11877
119- func (g GrpcClientRW ) Write (p []byte ) (n int , err error ) {
120- if len (p ) == 0 {
121- return 0 , nil
122- }
78+ func (g * GrpcClientRW ) Write (p []byte ) (n int , err error ) {
12379 err = g .stream .Send (& api.TunnelMessage {
12480 Id : g .id ,
12581 GuestAddr : g .addr ,
12682 Data : p ,
127- Protocol : "tcp" ,
83+ Protocol : g . protocol ,
12884 })
12985 if err != nil {
13086 return 0 , err
13187 }
13288 return len (p ), nil
13389}
13490
135- func (g GrpcClientRW ) Read (p []byte ) (n int , err error ) {
136- // Not documented: when err != nil, in is always nil.
91+ func (g * GrpcClientRW ) Read (p []byte ) (n int , err error ) {
13792 in , err := g .stream .Recv ()
13893 if err != nil {
139- if errors .Is (err , io .EOF ) {
140- return 0 , nil
141- }
14294 return 0 , err
14395 }
144- if len (in .Data ) == 0 {
145- return 0 , nil
146- }
14796 copy (p , in .Data )
14897 return len (in .Data ), nil
14998}
99+
100+ func (g * GrpcClientRW ) Close () error {
101+ return g .stream .CloseSend ()
102+ }
103+
104+ func (g * GrpcClientRW ) LocalAddr () net.Addr {
105+ return & net.UnixAddr {Name : "grpc" , Net : "unixpacket" }
106+ }
107+
108+ func (g * GrpcClientRW ) RemoteAddr () net.Addr {
109+ return & net.UnixAddr {Name : "grpc" , Net : "unixpacket" }
110+ }
111+
112+ func (g * GrpcClientRW ) SetDeadline (_ time.Time ) error {
113+ return nil
114+ }
115+
116+ func (g * GrpcClientRW ) SetReadDeadline (_ time.Time ) error {
117+ return nil
118+ }
119+
120+ func (g * GrpcClientRW ) SetWriteDeadline (_ time.Time ) error {
121+ return nil
122+ }
0 commit comments