@@ -2,20 +2,18 @@ package portfwd
2
2
3
3
import (
4
4
"context"
5
- "errors"
6
5
"fmt"
7
- "io"
8
6
"net"
7
+ "time"
9
8
9
+ "github.com/containers/gvisor-tap-vsock/pkg/services/forwarder"
10
+ "github.com/containers/gvisor-tap-vsock/pkg/tcpproxy"
10
11
"github.com/lima-vm/lima/pkg/guestagent/api"
11
12
guestagentclient "github.com/lima-vm/lima/pkg/guestagent/api/client"
12
13
"github.com/sirupsen/logrus"
13
- "golang.org/x/sync/errgroup"
14
14
)
15
15
16
16
func HandleTCPConnection (ctx context.Context , client * guestagentclient.GuestAgentClient , conn net.Conn , guestAddr string ) {
17
- defer conn .Close ()
18
-
19
17
id := fmt .Sprintf ("tcp-%s-%s" , conn .LocalAddr ().String (), conn .RemoteAddr ().String ())
20
18
21
19
stream , err := client .Tunnel (ctx )
@@ -24,26 +22,23 @@ func HandleTCPConnection(ctx context.Context, client *guestagentclient.GuestAgen
24
22
return
25
23
}
26
24
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
- })
25
+ // Handshake message to start tunnel
26
+ err = stream .Send (& api.TunnelMessage {Id : id , Protocol : "tcp" , GuestAddr : guestAddr })
27
+ if err != nil {
28
+ logrus .Errorf ("could not start tcp tunnel for id: %s error:%v" , id , err )
29
+ return
30
+ }
38
31
39
- if err := g .Wait (); err != nil {
40
- logrus .Debugf ("error in tcp tunnel for id: %s error:%v" , id , err )
32
+ remote := tcpproxy.DialProxy {
33
+ DialContext : func (_ context.Context , _ , _ string ) (net.Conn , error ) {
34
+ rw := & GrpcClientRW {stream : stream , id : id , addr : guestAddr , protocol : "tcp" }
35
+ return rw , nil
36
+ },
41
37
}
38
+ remote .HandleConn (conn )
42
39
}
43
40
44
41
func HandleUDPConnection (ctx context.Context , client * guestagentclient.GuestAgentClient , conn net.PacketConn , guestAddr string ) {
45
- defer conn .Close ()
46
-
47
42
id := fmt .Sprintf ("udp-%s" , conn .LocalAddr ().String ())
48
43
49
44
stream , err := client .Tunnel (ctx )
@@ -52,74 +47,43 @@ func HandleUDPConnection(ctx context.Context, client *guestagentclient.GuestAgen
52
47
return
53
48
}
54
49
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
- if err != nil {
62
- // https://pkg.go.dev/net#PacketConn does not mention io.EOF semantics.
63
- if errors .Is (err , io .EOF ) {
64
- return nil
65
- }
66
- return err
67
- }
68
- msg := & api.TunnelMessage {
69
- Id : id + "-" + addr .String (),
70
- Protocol : "udp" ,
71
- GuestAddr : guestAddr ,
72
- Data : buf [:n ],
73
- UdpTargetAddr : addr .String (),
74
- }
75
- if err := stream .Send (msg ); err != nil {
76
- return err
77
- }
78
- }
79
- })
50
+ //Handshake message to start tunnel
51
+ err = stream .Send (& api.TunnelMessage {Id : id , Protocol : "udp" , GuestAddr : guestAddr })
52
+ if err != nil {
53
+ logrus .Errorf ("could not start udp tunnel for id: %s error:%v" , id , err )
54
+ return
55
+ }
80
56
81
- g .Go (func () error {
82
- for {
83
- in , err := stream .Recv ()
84
- if err != nil {
85
- if errors .Is (err , io .EOF ) {
86
- return nil
87
- }
88
- return err
89
- }
90
- addr , err := net .ResolveUDPAddr ("udp" , in .UdpTargetAddr )
91
- if err != nil {
92
- return err
93
- }
94
- _ , err = conn .WriteTo (in .Data , addr )
95
- if err != nil {
96
- return err
97
- }
98
- }
57
+ proxy , err := forwarder .NewUDPProxy (conn , func () (net.Conn , error ) {
58
+ rw := & GrpcClientRW {stream : stream , id : id , addr : guestAddr , protocol : "udp" }
59
+ return rw , nil
99
60
})
100
61
101
- if err := g .Wait (); err != nil {
102
- logrus .Debugf ("error in udp tunnel for id: %s error:%v" , id , err )
62
+ if err != nil {
63
+ logrus .Errorf ("error in udp tunnel proxy for id: %s error:%v" , id , err )
64
+ return
103
65
}
66
+
67
+ defer proxy .Close ()
68
+ proxy .Run ()
104
69
}
105
70
106
71
type GrpcClientRW struct {
107
- id string
108
- addr string
109
- stream api.GuestService_TunnelClient
72
+ id string
73
+ addr string
74
+
75
+ protocol string
76
+ stream api.GuestService_TunnelClient
110
77
}
111
78
112
- var _ io. ReadWriter = (* GrpcClientRW )(nil )
79
+ var _ net. Conn = (* GrpcClientRW )(nil )
113
80
114
81
func (g GrpcClientRW ) Write (p []byte ) (n int , err error ) {
115
- if len (p ) == 0 {
116
- return 0 , nil
117
- }
118
82
err = g .stream .Send (& api.TunnelMessage {
119
83
Id : g .id ,
120
84
GuestAddr : g .addr ,
121
85
Data : p ,
122
- Protocol : "tcp" ,
86
+ Protocol : g . protocol ,
123
87
})
124
88
if err != nil {
125
89
return 0 , err
@@ -130,14 +94,32 @@ func (g GrpcClientRW) Write(p []byte) (n int, err error) {
130
94
func (g GrpcClientRW ) Read (p []byte ) (n int , err error ) {
131
95
in , err := g .stream .Recv ()
132
96
if err != nil {
133
- if errors .Is (err , io .EOF ) {
134
- return 0 , nil
135
- }
136
97
return 0 , err
137
98
}
138
- if len (in .Data ) == 0 {
139
- return 0 , nil
140
- }
141
99
copy (p , in .Data )
142
100
return len (in .Data ), nil
143
101
}
102
+
103
+ func (g GrpcClientRW ) Close () error {
104
+ return g .stream .CloseSend ()
105
+ }
106
+
107
+ func (g GrpcClientRW ) LocalAddr () net.Addr {
108
+ return & net.UnixAddr {Name : "grpc" , Net : "unixpacket" }
109
+ }
110
+
111
+ func (g GrpcClientRW ) RemoteAddr () net.Addr {
112
+ return & net.UnixAddr {Name : "grpc" , Net : "unixpacket" }
113
+ }
114
+
115
+ func (g GrpcClientRW ) SetDeadline (_ time.Time ) error {
116
+ return nil
117
+ }
118
+
119
+ func (g GrpcClientRW ) SetReadDeadline (_ time.Time ) error {
120
+ return nil
121
+ }
122
+
123
+ func (g GrpcClientRW ) SetWriteDeadline (_ time.Time ) error {
124
+ return nil
125
+ }
0 commit comments