mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcbe2d64f7 | ||
|
|
a0c0860051 | ||
|
|
e374d6b51d | ||
|
|
9703a12bc2 | ||
|
|
f9f52d1001 | ||
|
|
51c16989fe | ||
|
|
75c609211b | ||
|
|
6d545dc5c9 | ||
|
|
b17da3cbcb | ||
|
|
d1108ebd86 | ||
|
|
792839a2d4 | ||
|
|
f493931b41 | ||
|
|
7df065ef93 | ||
|
|
c265b3581c | ||
|
|
f802e03d01 | ||
|
|
c08cb461dd | ||
|
|
1a2649a02a | ||
|
|
facd6bdb3d | ||
|
|
a1117dee62 | ||
|
|
b28eaef6a7 | ||
|
|
46aebef01f | ||
|
|
3791f48737 | ||
|
|
fc76b70713 | ||
|
|
e990dc1d0f | ||
|
|
d636449073 | ||
|
|
e85e1a6c40 | ||
|
|
40d09716c4 | ||
|
|
63792172bd |
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
@@ -24,6 +24,8 @@ jobs:
|
||||
uses: medyagh/setup-minikube@latest
|
||||
with:
|
||||
cache: true
|
||||
cpus: 'max'
|
||||
memory: 'max'
|
||||
|
||||
- name: Kubernetes info
|
||||
run: |
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -41,6 +41,8 @@ jobs:
|
||||
uses: medyagh/setup-minikube@latest
|
||||
with:
|
||||
cache: true
|
||||
cpus: 'max'
|
||||
memory: 'max'
|
||||
|
||||
- name: Kubernetes info
|
||||
run: |
|
||||
|
||||
@@ -1,6 +1,78 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
kubevpn:
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.12
|
||||
created: "2025-05-23T03:38:02.484001975Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: b9e28ceda8bb07b42ec37eb2d6b283496d83645479b2f1f4e921d9c462eeb54e
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn-2.7.12.tgz
|
||||
version: 2.7.12
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.11
|
||||
created: "2025-05-18T09:03:21.60777933Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: ee30c2533dff51fa389767e56931583cdfff8c5fca7d6c9698f521c6fc508d42
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.11/kubevpn-2.7.11.tgz
|
||||
version: 2.7.11
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.10
|
||||
created: "2025-05-14T13:08:51.09371872Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: fd23dd5bf0c3a9343d73276c4997a34027a93c1a88667265d92297630579d165
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.10/kubevpn-2.7.10.tgz
|
||||
version: 2.7.10
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.9
|
||||
created: "2025-05-12T09:14:52.66116293Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: 56e022017177603290575849553c2e9c19f6a1691288dbd67c32a2fdcbde0834
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.9/kubevpn-2.7.9.tgz
|
||||
version: 2.7.9
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.8
|
||||
created: "2025-05-10T15:46:13.342045201Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: bfab5a7e4e1e795071a7ce3fd7713b517aa447d967ec58500e5a551564869109
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.8/kubevpn-2.7.8.tgz
|
||||
version: 2.7.8
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
appVersion: v2.7.7
|
||||
created: "2025-05-09T06:43:01.403047355Z"
|
||||
description: A Helm chart for KubeVPN
|
||||
digest: 14b3e7873aa71fa7a380631c83be8df1dfb8d0ccb49eb6746aa4f83e3df934f6
|
||||
name: kubevpn
|
||||
type: application
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.7/kubevpn-2.7.7.tgz
|
||||
version: 2.7.7
|
||||
- annotations:
|
||||
app: kubevpn
|
||||
apiVersion: v2
|
||||
@@ -503,4 +575,4 @@ entries:
|
||||
urls:
|
||||
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.2/kubevpn-2.2.2.tgz
|
||||
version: 2.2.2
|
||||
generated: "2025-05-07T11:46:09.644591701Z"
|
||||
generated: "2025-05-23T03:38:02.484184006Z"
|
||||
|
||||
@@ -31,6 +31,7 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
||||
var sshConf = &pkgssh.SshConfig{}
|
||||
var transferImage, foreground, lite bool
|
||||
var imagePullSecretName string
|
||||
var managerNamespace string
|
||||
cmd := &cobra.Command{
|
||||
Use: "connect",
|
||||
Short: i18n.T("Connect to kubernetes cluster network"),
|
||||
@@ -98,6 +99,7 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
||||
Image: config.Image,
|
||||
ImagePullSecretName: imagePullSecretName,
|
||||
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
|
||||
ManagerNamespace: managerNamespace,
|
||||
}
|
||||
// if is foreground, send to sudo daemon server
|
||||
cli, err := daemon.GetClient(false)
|
||||
@@ -137,6 +139,7 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
|
||||
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &connect.Engine)
|
||||
cmd.Flags().BoolVar(&foreground, "foreground", false, "Hang up")
|
||||
cmd.Flags().BoolVar(&lite, "lite", false, "connect to multiple cluster in lite mode. mode \"lite\": design for only connecting to multiple cluster network. mode \"full\": not only connect to cluster network, it also supports proxy workloads inbound traffic to local PC.")
|
||||
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
|
||||
|
||||
handler.AddExtraRoute(cmd.Flags(), extraRoute)
|
||||
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
|
||||
|
||||
@@ -29,7 +29,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
|
||||
var sshConf = &pkgssh.SshConfig{}
|
||||
var transferImage bool
|
||||
var imagePullSecretName string
|
||||
var connectNamespace string
|
||||
var managerNamespace string
|
||||
cmd := &cobra.Command{
|
||||
Use: "dev TYPE/NAME [-c CONTAINER] [flags] -- [args...]",
|
||||
Short: i18n.T("Startup your kubernetes workloads in local Docker container"),
|
||||
@@ -131,7 +131,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
return options.Main(cmd.Context(), sshConf, conf, hostConfig, imagePullSecretName, connectNamespace)
|
||||
return options.Main(cmd.Context(), sshConf, conf, hostConfig, imagePullSecretName, managerNamespace)
|
||||
},
|
||||
}
|
||||
cmd.Flags().SortFlags = false
|
||||
@@ -141,7 +141,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
|
||||
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc("container", completion.ContainerCompletionFunc(f)))
|
||||
cmd.Flags().StringVar((*string)(&options.ConnectMode), "connect-mode", string(dev.ConnectModeHost), "Connect to kubernetes network in container or in host, eg: ["+string(dev.ConnectModeContainer)+"|"+string(dev.ConnectModeHost)+"]")
|
||||
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &options.Engine)
|
||||
cmd.Flags().StringVarP(&connectNamespace, "connect-namespace", "C", config.DefaultNamespaceKubevpn, "Connect to special namespace which kubevpn server installed by helm in cluster mode")
|
||||
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
|
||||
|
||||
// diy docker options
|
||||
cmd.Flags().StringVar(&options.DevImage, "dev-image", "", "Use to startup docker container, Default is pod image")
|
||||
|
||||
@@ -32,7 +32,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
|
||||
var sshConf = &pkgssh.SshConfig{}
|
||||
var transferImage, foreground bool
|
||||
var imagePullSecretName string
|
||||
var connectNamespace string
|
||||
var managerNamespace string
|
||||
cmd := &cobra.Command{
|
||||
Use: "proxy",
|
||||
Short: i18n.T("Proxy kubernetes workloads inbound traffic into local PC"),
|
||||
@@ -142,7 +142,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
|
||||
ImagePullSecretName: imagePullSecretName,
|
||||
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
|
||||
OriginKubeconfigPath: util.GetKubeConfigPath(f),
|
||||
ConnectNamespace: connectNamespace,
|
||||
ManagerNamespace: managerNamespace,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -174,7 +174,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
|
||||
cmd.Flags().StringArrayVar(&portmap, "portmap", []string{}, "Port map, map container port to local port, format: [tcp/udp]/containerPort:localPort, If not special, localPort will use containerPort. eg: tcp/80:8080 or udp/5000:5001 or 80 or 80:8080")
|
||||
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &connect.Engine)
|
||||
cmd.Flags().BoolVar(&foreground, "foreground", false, "foreground hang up")
|
||||
cmd.Flags().StringVarP(&connectNamespace, "connect-namespace", "C", config.DefaultNamespaceKubevpn, "Connect to special namespace which kubevpn server installed by helm in cluster mode")
|
||||
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
|
||||
|
||||
handler.AddExtraRoute(cmd.Flags(), extraRoute)
|
||||
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
|
||||
|
||||
2
go.mod
2
go.mod
@@ -161,7 +161,7 @@ require (
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 // indirect
|
||||
github.com/ebitengine/purego v0.9.0-alpha.3.0.20250507171635-5047c08daa38 // indirect
|
||||
github.com/ebitengine/purego v0.8.3 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -265,8 +265,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
|
||||
github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 h1:8EXxF+tCLqaVk8AOC29zl2mnhQjwyLxxOTuhUazWRsg=
|
||||
github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4/go.mod h1:I5sHm0Y0T1u5YjlyqC5GVArM7aNZRUYtTjmJ8mPJFds=
|
||||
github.com/ebitengine/purego v0.9.0-alpha.3.0.20250507171635-5047c08daa38 h1:61WY14WhyU89bEJCjegpt6b8wDNsU+Z1416JGwfEKwI=
|
||||
github.com/ebitengine/purego v0.9.0-alpha.3.0.20250507171635-5047c08daa38/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
|
||||
|
||||
@@ -88,7 +88,11 @@ func (h *gvisorTCPHandler) readFromTCPConnWriteToEndpoint(ctx context.Context, c
|
||||
|
||||
h.addToRouteMapTCP(ctx, src, conn)
|
||||
// inner ip like 198.19.0.100/102/103 connect each other
|
||||
if config.CIDR.Contains(dst) || config.CIDR6.Contains(dst) {
|
||||
// for issue 594, sometimes k8s service network CIDR also use CIDR 198.19.151.170
|
||||
// if we can find dst in route map, just trade packet as inner communicate
|
||||
// if not find dst in route map, just trade packet as k8s service/pod ip
|
||||
_, found := h.routeMapTCP.Load(dst.String())
|
||||
if found && (config.CIDR.Contains(dst) || config.CIDR6.Contains(dst)) {
|
||||
err = h.handlePacket(ctx, buf, read, src, dst, layers.IPProtocol(ipProtocol).String())
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("[TCP-GVISOR] Failed to handle packet: %v", err)
|
||||
|
||||
@@ -29,7 +29,7 @@ func (h *gvisorUDPHandler) Handle(ctx context.Context, tcpConn net.Conn) {
|
||||
plog.G(ctx).Errorf("[TUN-UDP] Failed to parse proxy info: %v", err)
|
||||
return
|
||||
}
|
||||
plog.G(ctx).Debugf("[TUN-UDP] LocalPort: %d, LocalAddress: %s, RemotePort: %d, RemoteAddress: %s",
|
||||
plog.G(ctx).Infof("[TUN-UDP] LocalPort: %d, LocalAddress: %s, RemotePort: %d, RemoteAddress: %s",
|
||||
endpointID.LocalPort, endpointID.LocalAddress.String(), endpointID.RemotePort, endpointID.RemoteAddress.String(),
|
||||
)
|
||||
// 2, dial proxy
|
||||
|
||||
@@ -26,7 +26,7 @@ func (h *tunHandler) HandleClient(ctx context.Context, tun net.Conn) {
|
||||
go device.handlePacket(ctx, h.forward)
|
||||
go device.readFromTun(ctx)
|
||||
go device.writeToTun(ctx)
|
||||
go heartbeats(ctx, device.tun)
|
||||
go device.heartbeats(ctx)
|
||||
select {
|
||||
case <-device.errChan:
|
||||
case <-ctx.Done():
|
||||
@@ -73,7 +73,13 @@ func handlePacketClient(ctx context.Context, tunInbound <-chan *Packet, tunOutbo
|
||||
go func() {
|
||||
defer util.HandleCrash()
|
||||
for packet := range tunInbound {
|
||||
_, err := conn.Write(packet.data[:packet.length])
|
||||
err := conn.SetWriteDeadline(time.Now().Add(config.KeepAliveTime))
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to set write deadline: %v", err)
|
||||
util.SafeWrite(errChan, errors.Wrap(err, "failed to set write deadline"))
|
||||
return
|
||||
}
|
||||
_, err = conn.Write(packet.data[:packet.length])
|
||||
config.LPool.Put(packet.data[:])
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to write packet to remote: %v", err)
|
||||
@@ -87,6 +93,12 @@ func handlePacketClient(ctx context.Context, tunInbound <-chan *Packet, tunOutbo
|
||||
defer util.HandleCrash()
|
||||
for {
|
||||
buf := config.LPool.Get().([]byte)[:]
|
||||
err := conn.SetReadDeadline(time.Now().Add(config.KeepAliveTime))
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to set read deadline: %v", err)
|
||||
util.SafeWrite(errChan, errors.Wrap(err, "failed to set read deadline"))
|
||||
return
|
||||
}
|
||||
n, err := conn.Read(buf[:])
|
||||
if err != nil {
|
||||
config.LPool.Put(buf[:])
|
||||
@@ -168,8 +180,8 @@ func (d *ClientDevice) Close() {
|
||||
util.SafeClose(d.tunOutbound)
|
||||
}
|
||||
|
||||
func heartbeats(ctx context.Context, tun net.Conn) {
|
||||
tunIfi, err := util.GetTunDeviceByConn(tun)
|
||||
func (d *ClientDevice) heartbeats(ctx context.Context) {
|
||||
tunIfi, err := util.GetTunDeviceByConn(d.tun)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to get tun device: %v", err)
|
||||
return
|
||||
|
||||
@@ -25,10 +25,11 @@ func (svr *Server) ConnectFork(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectF
|
||||
|
||||
ctx := resp.Context()
|
||||
connect := &handler.ConnectOptions{
|
||||
Namespace: req.Namespace,
|
||||
Namespace: req.ManagerNamespace,
|
||||
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
OriginNamespace: req.Namespace,
|
||||
Lock: &svr.Lock,
|
||||
ImagePullSecretName: req.ImagePullSecretName,
|
||||
}
|
||||
@@ -51,7 +52,7 @@ func (svr *Server) ConnectFork(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectF
|
||||
}
|
||||
}()
|
||||
|
||||
err = connect.InitClient(util.InitFactoryByPath(file, req.Namespace))
|
||||
err = connect.InitClient(util.InitFactoryByPath(file, req.ManagerNamespace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,6 +95,7 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
|
||||
defer plog.WithoutLogger(sshCtx)
|
||||
connect := &handler.ConnectOptions{
|
||||
Namespace: req.Namespace,
|
||||
OriginNamespace: req.Namespace,
|
||||
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
@@ -123,16 +125,18 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
|
||||
return err
|
||||
}
|
||||
|
||||
connectNs, err := util.DetectConnectNamespace(sshCtx, connect.GetFactory(), req.Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
if req.ManagerNamespace == "" {
|
||||
req.ManagerNamespace, err = util.DetectManagerNamespace(plog.WithLogger(sshCtx, logger), connect.GetFactory(), req.Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if connectNs != "" {
|
||||
logger.Infof("Use connect namespace %s", connectNs)
|
||||
connect.Namespace = connectNs
|
||||
req.Namespace = connectNs
|
||||
if req.ManagerNamespace != "" {
|
||||
logger.Infof("Use manager namespace %s", req.ManagerNamespace)
|
||||
connect.Namespace = req.ManagerNamespace
|
||||
} else {
|
||||
logger.Infof("Use special namespace %s", req.Namespace)
|
||||
req.ManagerNamespace = req.Namespace
|
||||
}
|
||||
|
||||
for _, options := range svr.secondaryConnect {
|
||||
|
||||
@@ -28,9 +28,7 @@ func (svr *Server) Connect(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectServe
|
||||
|
||||
ctx := resp.Context()
|
||||
if !svr.t.IsZero() {
|
||||
s := "Already connected to cluster in full mode, you can use options `--lite` to connect to another cluster"
|
||||
logger.Debugf(s)
|
||||
// todo define already connect error?
|
||||
s := "Only support one cluster connect with full mode, you can use options `--lite` to connect to another cluster"
|
||||
return status.Error(codes.AlreadyExists, s)
|
||||
}
|
||||
defer func() {
|
||||
@@ -44,10 +42,11 @@ func (svr *Server) Connect(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectServe
|
||||
}()
|
||||
svr.t = time.Now()
|
||||
svr.connect = &handler.ConnectOptions{
|
||||
Namespace: req.Namespace,
|
||||
Namespace: req.ManagerNamespace,
|
||||
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
OriginNamespace: req.Namespace,
|
||||
Lock: &svr.Lock,
|
||||
ImagePullSecretName: req.ImagePullSecretName,
|
||||
}
|
||||
@@ -72,7 +71,7 @@ func (svr *Server) Connect(req *rpc.ConnectRequest, resp rpc.Daemon_ConnectServe
|
||||
sshCancel()
|
||||
}
|
||||
}()
|
||||
err = svr.connect.InitClient(util.InitFactoryByPath(file, req.Namespace))
|
||||
err = svr.connect.InitClient(util.InitFactoryByPath(file, req.ManagerNamespace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,6 +109,7 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
|
||||
defer plog.WithoutLogger(sshCtx)
|
||||
connect := &handler.ConnectOptions{
|
||||
Namespace: req.Namespace,
|
||||
OriginNamespace: req.Namespace,
|
||||
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
@@ -140,16 +140,18 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
|
||||
return err
|
||||
}
|
||||
|
||||
connectNs, err := util.DetectConnectNamespace(plog.WithLogger(sshCtx, logger), connect.GetFactory(), req.Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
if req.ManagerNamespace == "" {
|
||||
req.ManagerNamespace, err = util.DetectManagerNamespace(plog.WithLogger(sshCtx, logger), connect.GetFactory(), req.Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if connectNs != "" {
|
||||
logger.Infof("Use connect namespace %s", connectNs)
|
||||
connect.Namespace = connectNs
|
||||
req.Namespace = connectNs
|
||||
if req.ManagerNamespace != "" {
|
||||
logger.Infof("Use manager namespace %s", req.ManagerNamespace)
|
||||
connect.Namespace = req.ManagerNamespace
|
||||
} else {
|
||||
logger.Infof("Use special namespace %s", req.Namespace)
|
||||
req.ManagerNamespace = req.Namespace
|
||||
}
|
||||
|
||||
if svr.connect != nil {
|
||||
@@ -165,6 +167,9 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
|
||||
// same cluster, do nothing
|
||||
logger.Infof("Connected to cluster")
|
||||
return nil
|
||||
} else {
|
||||
s := "Only support one cluster connect with full mode, you can use options `--lite` to connect to another cluster"
|
||||
return status.Error(codes.AlreadyExists, s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ func disconnect(ctx context.Context, svr *Server, connect *handler.ConnectOption
|
||||
if svr.connect != nil {
|
||||
isSameCluster, _ := util.IsSameCluster(
|
||||
ctx,
|
||||
svr.connect.GetClientset().CoreV1(), svr.connect.Namespace,
|
||||
svr.connect.GetClientset().CoreV1(), svr.connect.OriginNamespace,
|
||||
connect.GetClientset().CoreV1(), connect.Namespace,
|
||||
)
|
||||
if isSameCluster {
|
||||
@@ -173,7 +173,7 @@ func disconnect(ctx context.Context, svr *Server, connect *handler.ConnectOption
|
||||
options := svr.secondaryConnect[i]
|
||||
isSameCluster, _ := util.IsSameCluster(
|
||||
ctx,
|
||||
options.GetClientset().CoreV1(), options.Namespace,
|
||||
options.GetClientset().CoreV1(), options.OriginNamespace,
|
||||
connect.GetClientset().CoreV1(), connect.Namespace,
|
||||
)
|
||||
if isSameCluster {
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
@@ -45,7 +47,7 @@ func (svr *Server) Proxy(req *rpc.ProxyRequest, resp rpc.Daemon_ProxyServer) (e
|
||||
return err
|
||||
}
|
||||
connect := &handler.ConnectOptions{
|
||||
Namespace: req.ConnectNamespace,
|
||||
Namespace: req.Namespace,
|
||||
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
|
||||
Engine: config.Engine(req.Engine),
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
@@ -72,48 +74,33 @@ func (svr *Server) Proxy(req *rpc.ProxyRequest, resp rpc.Daemon_ProxyServer) (e
|
||||
return errors.Wrap(err, "daemon is not available")
|
||||
}
|
||||
|
||||
connectNs, err := util.DetectConnectNamespace(ctx, connect.GetFactory(), req.ConnectNamespace)
|
||||
plog.G(ctx).Debugf("Connecting to cluster")
|
||||
var connResp rpc.Daemon_ConnectClient
|
||||
connResp, err = cli.Connect(ctx, convert(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if connectNs != "" {
|
||||
connect.Namespace = connectNs
|
||||
}
|
||||
|
||||
if svr.connect != nil {
|
||||
isSameCluster, _ := util.IsSameCluster(
|
||||
ctx,
|
||||
svr.connect.GetClientset().CoreV1(), svr.connect.Namespace,
|
||||
connect.GetClientset().CoreV1(), connect.Namespace,
|
||||
)
|
||||
if isSameCluster {
|
||||
// same cluster, do nothing
|
||||
plog.G(ctx).Infof("Connected to cluster")
|
||||
} else {
|
||||
plog.G(ctx).Infof("Disconnecting from another cluster...")
|
||||
var disconnectResp rpc.Daemon_DisconnectClient
|
||||
disconnectResp, err = cli.Disconnect(ctx, &rpc.DisconnectRequest{
|
||||
ID: ptr.To[int32](0),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.CopyAndConvertGRPCStream[rpc.DisconnectResponse, rpc.ConnectResponse](
|
||||
disconnectResp,
|
||||
resp,
|
||||
func(response *rpc.DisconnectResponse) *rpc.ConnectResponse {
|
||||
return &rpc.ConnectResponse{Message: response.Message}
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.CopyGRPCStream[rpc.ConnectResponse](connResp, resp)
|
||||
if err != nil {
|
||||
if status.Code(err) != codes.AlreadyExists {
|
||||
return err
|
||||
}
|
||||
plog.G(ctx).Infof("Disconnecting from another cluster...")
|
||||
var disconnectResp rpc.Daemon_DisconnectClient
|
||||
disconnectResp, err = cli.Disconnect(ctx, &rpc.DisconnectRequest{ID: ptr.To[int32](0)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.CopyAndConvertGRPCStream[rpc.DisconnectResponse, rpc.ConnectResponse](
|
||||
disconnectResp,
|
||||
resp,
|
||||
func(response *rpc.DisconnectResponse) *rpc.ConnectResponse {
|
||||
return &rpc.ConnectResponse{Message: response.Message}
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if svr.connect == nil {
|
||||
plog.G(ctx).Debugf("Connectting to cluster")
|
||||
var connResp rpc.Daemon_ConnectClient
|
||||
connResp, err = cli.Connect(ctx, convert(req))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -160,5 +147,6 @@ func convert(req *rpc.ProxyRequest) *rpc.ConnectRequest {
|
||||
Foreground: req.Foreground,
|
||||
Level: req.Level,
|
||||
OriginKubeconfigPath: req.OriginKubeconfigPath,
|
||||
ManagerNamespace: req.ManagerNamespace,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func genStatus(connect *handler.ConnectOptions, mode string, index int32) *rpc.S
|
||||
Cluster: util.GetKubeconfigCluster(connect.GetFactory()),
|
||||
Mode: mode,
|
||||
Kubeconfig: connect.OriginKubeconfigPath,
|
||||
Namespace: connect.Namespace,
|
||||
Namespace: connect.OriginNamespace,
|
||||
Status: status,
|
||||
Netif: tunName,
|
||||
}
|
||||
@@ -136,7 +136,7 @@ func gen(ctx context.Context, connect *handler.ConnectOptions, clone *handler.Cl
|
||||
clusterID = connect.GetClusterID()
|
||||
cluster = util.GetKubeconfigCluster(connect.GetFactory())
|
||||
kubeconfig = connect.OriginKubeconfigPath
|
||||
namespace = connect.Namespace
|
||||
namespace = connect.OriginNamespace
|
||||
}
|
||||
cloneList = append(cloneList, &rpc.Clone{
|
||||
ClusterID: clusterID,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,14 @@ message ConnectRequest {
|
||||
int32 Level = 10;
|
||||
|
||||
string OriginKubeconfigPath = 11;
|
||||
|
||||
// The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)
|
||||
// reason: user helm install kubevpn server, and all users use this one kubevpn-traffic-manager instance
|
||||
// but if normal user don't have list namespace permission(for: helm list -A), needs to special this options.
|
||||
// 1. default is namespace kubevpn if kubevpn namespace is exists
|
||||
// 2. detect which namespace helm installed by (helm list -A), match app name==kubevpn and status is deployed
|
||||
// 3. otherwise, use options '-n' or '--namespace'
|
||||
string ManagerNamespace = 12;
|
||||
}
|
||||
|
||||
message ConnectResponse {
|
||||
@@ -106,12 +114,13 @@ message ProxyRequest {
|
||||
|
||||
string OriginKubeconfigPath = 15;
|
||||
|
||||
// connect to which namespace, reason: user helm install kubevpn server, and all users use this one instance
|
||||
// The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)
|
||||
// reason: user helm install kubevpn server, and all users use this one kubevpn-traffic-manager instance
|
||||
// but if normal user don't have list namespace permission(for: helm list -A), needs to special this options.
|
||||
// 1. default is namespace kubevpn if kubevpn namespace is exists
|
||||
// 2. detect which namespace helm installed by (helm list -A), match app name==kubevpn and status is deployed
|
||||
// 3. otherwise, use options '-n' or '--namespace'
|
||||
string ConnectNamespace = 16;
|
||||
string ManagerNamespace = 16;
|
||||
}
|
||||
|
||||
message ProxyResponse {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v3.21.2
|
||||
// - protoc v5.29.3
|
||||
// source: daemon.proto
|
||||
|
||||
package rpc
|
||||
|
||||
@@ -63,7 +63,7 @@ type Options struct {
|
||||
rollbackFuncList []func() error
|
||||
}
|
||||
|
||||
func (option *Options) Main(ctx context.Context, sshConfig *pkgssh.SshConfig, config *Config, hostConfig *HostConfig, imagePullSecretName string, connectNamespace string) error {
|
||||
func (option *Options) Main(ctx context.Context, sshConfig *pkgssh.SshConfig, config *Config, hostConfig *HostConfig, imagePullSecretName string, managerNamespace string) error {
|
||||
mode := typescontainer.NetworkMode(option.ContainerOptions.netMode.NetworkMode())
|
||||
if mode.IsContainer() {
|
||||
plog.G(ctx).Infof("Network mode container is %s", mode.ConnectedContainer())
|
||||
@@ -80,7 +80,7 @@ func (option *Options) Main(ctx context.Context, sshConfig *pkgssh.SshConfig, co
|
||||
}
|
||||
|
||||
// Connect to cluster, in container or host
|
||||
err := option.Connect(ctx, sshConfig, imagePullSecretName, hostConfig.PortBindings, connectNamespace)
|
||||
err := option.Connect(ctx, sshConfig, imagePullSecretName, hostConfig.PortBindings, managerNamespace)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Connect to cluster failed, err: %v", err)
|
||||
return err
|
||||
@@ -90,7 +90,7 @@ func (option *Options) Main(ctx context.Context, sshConfig *pkgssh.SshConfig, co
|
||||
}
|
||||
|
||||
// Connect to cluster network on docker container or host
|
||||
func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig, imagePullSecretName string, portBindings nat.PortMap, connectNamespace string) error {
|
||||
func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig, imagePullSecretName string, portBindings nat.PortMap, managerNamespace string) error {
|
||||
if option.ConnectMode == ConnectModeHost {
|
||||
cli, err := daemon.GetClient(false)
|
||||
if err != nil {
|
||||
@@ -119,7 +119,7 @@ func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig,
|
||||
ImagePullSecretName: imagePullSecretName,
|
||||
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
|
||||
SshJump: sshConfig.ToRPC(),
|
||||
ConnectNamespace: connectNamespace,
|
||||
ManagerNamespace: managerNamespace,
|
||||
}
|
||||
option.AddRollbackFunc(func() error {
|
||||
resp, err := cli.Disconnect(ctx, &rpc.DisconnectRequest{
|
||||
@@ -144,7 +144,7 @@ func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig,
|
||||
}
|
||||
|
||||
if option.ConnectMode == ConnectModeContainer {
|
||||
name, err := option.CreateConnectContainer(ctx, portBindings, connectNamespace)
|
||||
name, err := option.CreateConnectContainer(ctx, portBindings, managerNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -227,7 +227,7 @@ func (option *Options) Dev(ctx context.Context, config *Config, hostConfig *Host
|
||||
return configList.Run(ctx)
|
||||
}
|
||||
|
||||
func (option *Options) CreateConnectContainer(ctx context.Context, portBindings nat.PortMap, connectNamespace string) (*string, error) {
|
||||
func (option *Options) CreateConnectContainer(ctx context.Context, portBindings nat.PortMap, managerNamespace string) (*string, error) {
|
||||
portMap, portSet, err := option.GetExposePort(portBindings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -264,7 +264,7 @@ func (option *Options) CreateConnectContainer(ctx context.Context, portBindings
|
||||
"--kubeconfig", "/root/.kube/config",
|
||||
"--image", config.Image,
|
||||
"--netstack", string(option.Engine),
|
||||
"--connect-namespace", connectNamespace,
|
||||
"--manager-namespace", managerNamespace,
|
||||
}
|
||||
for k, v := range option.Headers {
|
||||
entrypoint = append(entrypoint, "--headers", fmt.Sprintf("%s=%s", k, v))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v3.21.2
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: dhcpserver.proto
|
||||
|
||||
package rpc
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -21,21 +22,18 @@ const (
|
||||
)
|
||||
|
||||
type RentIPRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RentIPRequest) Reset() {
|
||||
*x = RentIPRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RentIPRequest) String() string {
|
||||
@@ -46,7 +44,7 @@ func (*RentIPRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RentIPRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -76,21 +74,18 @@ func (x *RentIPRequest) GetPodNamespace() string {
|
||||
}
|
||||
|
||||
type RentIPResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RentIPResponse) Reset() {
|
||||
*x = RentIPResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RentIPResponse) String() string {
|
||||
@@ -101,7 +96,7 @@ func (*RentIPResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RentIPResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -131,23 +126,20 @@ func (x *RentIPResponse) GetIPv6CIDR() string {
|
||||
}
|
||||
|
||||
type ReleaseIPRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
|
||||
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
|
||||
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
|
||||
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ReleaseIPRequest) Reset() {
|
||||
*x = ReleaseIPRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ReleaseIPRequest) String() string {
|
||||
@@ -158,7 +150,7 @@ func (*ReleaseIPRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ReleaseIPRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -202,20 +194,17 @@ func (x *ReleaseIPRequest) GetIPv6CIDR() string {
|
||||
}
|
||||
|
||||
type ReleaseIPResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ReleaseIPResponse) Reset() {
|
||||
*x = ReleaseIPResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ReleaseIPResponse) String() string {
|
||||
@@ -226,7 +215,7 @@ func (*ReleaseIPResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ReleaseIPResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_dhcpserver_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
@@ -250,55 +239,40 @@ func (x *ReleaseIPResponse) GetMessage() string {
|
||||
|
||||
var File_dhcpserver_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_dhcpserver_proto_rawDesc = []byte{
|
||||
0x0a, 0x10, 0x64, 0x68, 0x63, 0x70, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63, 0x22, 0x4d, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x74, 0x49,
|
||||
0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x48, 0x0a, 0x0e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34,
|
||||
0x43, 0x49, 0x44, 0x52, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34,
|
||||
0x43, 0x49, 0x44, 0x52, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
|
||||
0x22, 0x88, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
||||
0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x22, 0x2d, 0x0a, 0x11, 0x52,
|
||||
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x79, 0x0a, 0x04, 0x44, 0x48,
|
||||
0x43, 0x50, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x12, 0x2e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x52, 0x65, 0x6c, 0x65, 0x61,
|
||||
0x73, 0x65, 0x49, 0x50, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
|
||||
0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
const file_dhcpserver_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x10dhcpserver.proto\x12\x03rpc\"M\n" +
|
||||
"\rRentIPRequest\x12\x18\n" +
|
||||
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
|
||||
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\"H\n" +
|
||||
"\x0eRentIPResponse\x12\x1a\n" +
|
||||
"\bIPv4CIDR\x18\x01 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
|
||||
"\bIPv6CIDR\x18\x02 \x01(\tR\bIPv6CIDR\"\x88\x01\n" +
|
||||
"\x10ReleaseIPRequest\x12\x18\n" +
|
||||
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
|
||||
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\x12\x1a\n" +
|
||||
"\bIPv4CIDR\x18\x03 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
|
||||
"\bIPv6CIDR\x18\x04 \x01(\tR\bIPv6CIDR\"-\n" +
|
||||
"\x11ReleaseIPResponse\x12\x18\n" +
|
||||
"\amessage\x18\x01 \x01(\tR\amessage2y\n" +
|
||||
"\x04DHCP\x123\n" +
|
||||
"\x06RentIP\x12\x12.rpc.RentIPRequest\x1a\x13.rpc.RentIPResponse\"\x00\x12<\n" +
|
||||
"\tReleaseIP\x12\x15.rpc.ReleaseIPRequest\x1a\x16.rpc.ReleaseIPResponse\"\x00B\aZ\x05.;rpcb\x06proto3"
|
||||
|
||||
var (
|
||||
file_dhcpserver_proto_rawDescOnce sync.Once
|
||||
file_dhcpserver_proto_rawDescData = file_dhcpserver_proto_rawDesc
|
||||
file_dhcpserver_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_dhcpserver_proto_rawDescGZIP() []byte {
|
||||
file_dhcpserver_proto_rawDescOnce.Do(func() {
|
||||
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(file_dhcpserver_proto_rawDescData)
|
||||
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)))
|
||||
})
|
||||
return file_dhcpserver_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_dhcpserver_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_dhcpserver_proto_goTypes = []interface{}{
|
||||
var file_dhcpserver_proto_goTypes = []any{
|
||||
(*RentIPRequest)(nil), // 0: rpc.RentIPRequest
|
||||
(*RentIPResponse)(nil), // 1: rpc.RentIPResponse
|
||||
(*ReleaseIPRequest)(nil), // 2: rpc.ReleaseIPRequest
|
||||
@@ -321,61 +295,11 @@ func file_dhcpserver_proto_init() {
|
||||
if File_dhcpserver_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_dhcpserver_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RentIPRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RentIPResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReleaseIPRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_dhcpserver_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReleaseIPResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_dhcpserver_proto_rawDesc,
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
@@ -386,7 +310,6 @@ func file_dhcpserver_proto_init() {
|
||||
MessageInfos: file_dhcpserver_proto_msgTypes,
|
||||
}.Build()
|
||||
File_dhcpserver_proto = out.File
|
||||
file_dhcpserver_proto_rawDesc = nil
|
||||
file_dhcpserver_proto_goTypes = nil
|
||||
file_dhcpserver_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v3.21.2
|
||||
// - protoc v5.29.3
|
||||
// source: dhcpserver.proto
|
||||
|
||||
package rpc
|
||||
|
||||
162
pkg/dns/dns.go
162
pkg/dns/dns.go
@@ -17,12 +17,8 @@ import (
|
||||
miekgdns "github.com/miekg/dns"
|
||||
"github.com/pkg/errors"
|
||||
v12 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
v13 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"tailscale.com/net/dns"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
@@ -31,10 +27,11 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Config *miekgdns.ClientConfig
|
||||
Ns []string
|
||||
Services []v12.Service
|
||||
TunName string
|
||||
Config *miekgdns.ClientConfig
|
||||
Ns []string
|
||||
Services []v12.Service
|
||||
SvcInformer cache.SharedIndexInformer
|
||||
TunName string
|
||||
|
||||
Hosts []Entry
|
||||
Lock *sync.Mutex
|
||||
@@ -45,22 +42,8 @@ type Config struct {
|
||||
OSConfigurator dns.OSConfigurator
|
||||
}
|
||||
|
||||
func (c *Config) AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInterface, hosts ...Entry) error {
|
||||
func (c *Config) AddServiceNameToHosts(ctx context.Context, hosts ...Entry) error {
|
||||
var serviceList []v12.Service
|
||||
//listOptions := v1.ListOptions{Limit: 100}
|
||||
//for {
|
||||
// services, err := serviceInterface.List(ctx, listOptions)
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// serviceList = append(serviceList, services.Items...)
|
||||
// if services.Continue != "" {
|
||||
// listOptions.Continue = services.Continue
|
||||
// } else {
|
||||
// break
|
||||
// }
|
||||
//}
|
||||
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
@@ -71,100 +54,65 @@ func (c *Config) AddServiceNameToHosts(ctx context.Context, serviceInterface v13
|
||||
return err
|
||||
}
|
||||
|
||||
go c.watchServiceToAddHosts(ctx, serviceInterface, hosts)
|
||||
go c.watchServiceToAddHosts(ctx, hosts)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) watchServiceToAddHosts(ctx context.Context, serviceInterface v13.ServiceInterface, hosts []Entry) {
|
||||
func (c *Config) watchServiceToAddHosts(ctx context.Context, hosts []Entry) {
|
||||
defer util.HandleCrash()
|
||||
ticker := time.NewTicker(time.Second * 15)
|
||||
defer ticker.Stop()
|
||||
immediate := make(chan struct{}, 1)
|
||||
immediate <- struct{}{}
|
||||
var ErrChanDone = errors.New("watch service chan done")
|
||||
for ctx.Err() == nil {
|
||||
err := func() error {
|
||||
w, err := serviceInterface.Watch(ctx, v1.ListOptions{Watch: true})
|
||||
if err != nil {
|
||||
return err
|
||||
_, err := c.SvcInformer.AddEventHandler(cache.FilteringResourceEventHandler{
|
||||
FilterFunc: func(obj interface{}) bool {
|
||||
if svc, ok := obj.(*v12.Service); ok && svc.Namespace == c.Ns[0] {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
defer w.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case event, ok := <-w.ResultChan():
|
||||
if !ok {
|
||||
return ErrChanDone
|
||||
}
|
||||
svc, ok := event.Object.(*v12.Service)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
if event.Type == watch.Deleted {
|
||||
if net.ParseIP(svc.Spec.ClusterIP) == nil {
|
||||
continue
|
||||
}
|
||||
var list = []Entry{{
|
||||
IP: svc.Spec.ClusterIP,
|
||||
Domain: svc.Name,
|
||||
}}
|
||||
err = c.removeHosts(list)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to remove hosts(%s) to hosts: %v", entryList2String(list), err)
|
||||
}
|
||||
}
|
||||
if event.Type == watch.Added {
|
||||
c.Lock.Lock()
|
||||
appendHosts := c.generateAppendHosts([]v12.Service{*svc}, hosts)
|
||||
err = c.appendHosts(appendHosts)
|
||||
c.Lock.Unlock()
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add hosts(%s) to hosts: %v", entryList2String(appendHosts), err)
|
||||
}
|
||||
}
|
||||
case <-ticker.C:
|
||||
var list *v12.ServiceList
|
||||
list, err = serviceInterface.List(ctx, v1.ListOptions{})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
c.Lock.Lock()
|
||||
appendHosts := c.generateAppendHosts(list.Items, hosts)
|
||||
err = c.appendHosts(appendHosts)
|
||||
c.Lock.Unlock()
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add hosts(%s) to hosts: %v", entryList2String(appendHosts), err)
|
||||
}
|
||||
case <-immediate:
|
||||
var list *v12.ServiceList
|
||||
list, err = serviceInterface.List(ctx, v1.ListOptions{})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
c.Lock.Lock()
|
||||
appendHosts := c.generateAppendHosts(list.Items, hosts)
|
||||
err = c.appendHosts(appendHosts)
|
||||
c.Lock.Unlock()
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add hosts(%s) to hosts: %v", entryList2String(appendHosts), err)
|
||||
}
|
||||
}
|
||||
},
|
||||
Handler: cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add service event handler: %v", err)
|
||||
return
|
||||
}
|
||||
for ; ctx.Err() == nil; <-ticker.C {
|
||||
ticker.Reset(time.Second * 15)
|
||||
serviceList, err := c.SvcInformer.GetIndexer().ByIndex(cache.NamespaceIndex, c.Ns[0])
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to list service by namespace %s: %v", c.Ns[0], err)
|
||||
continue
|
||||
}
|
||||
var services []v12.Service
|
||||
for _, service := range serviceList {
|
||||
svc, ok := service.(*v12.Service)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
}()
|
||||
services = append(services, *svc)
|
||||
}
|
||||
if len(services) == 0 {
|
||||
continue
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, ErrChanDone) {
|
||||
plog.G(ctx).Debugf("Failed to watch service to add route table: %v", err)
|
||||
}
|
||||
if utilnet.IsConnectionRefused(err) || apierrors.IsTooManyRequests(err) || apierrors.IsForbidden(err) {
|
||||
time.Sleep(time.Second * 1)
|
||||
} else {
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
c.Lock.Lock()
|
||||
appendHosts := c.generateAppendHosts(services, hosts)
|
||||
err = c.appendHosts(appendHosts)
|
||||
c.Lock.Unlock()
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
plog.G(ctx).Errorf("Failed to add hosts(%s) to hosts: %v", entryList2String(appendHosts), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -17,6 +17,10 @@ import (
|
||||
miekgdns "github.com/miekg/dns"
|
||||
v12 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
|
||||
)
|
||||
|
||||
// https://github.com/golang/go/issues/12524
|
||||
@@ -32,6 +36,59 @@ var resolv = "/etc/resolv.conf"
|
||||
// service.namespace.svc.cluster:port
|
||||
// service.namespace.svc.cluster.local:port
|
||||
func (c *Config) SetupDNS(ctx context.Context) error {
|
||||
defer util.HandleCrash()
|
||||
ticker := time.NewTicker(time.Second * 15)
|
||||
_, err := c.SvcInformer.AddEventHandler(cache.FilteringResourceEventHandler{
|
||||
FilterFunc: func(obj interface{}) bool {
|
||||
if svc, ok := obj.(*v12.Service); ok && svc.Namespace == c.Ns[0] {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
Handler: cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
ticker.Reset(time.Second * 3)
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add service event handler: %v", err)
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
defer ticker.Stop()
|
||||
for ; ctx.Err() == nil; <-ticker.C {
|
||||
ticker.Reset(time.Second * 15)
|
||||
serviceList, err := c.SvcInformer.GetIndexer().ByIndex(cache.NamespaceIndex, c.Ns[0])
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to list service by namespace %s: %v", c.Ns[0], err)
|
||||
continue
|
||||
}
|
||||
var services []v12.Service
|
||||
for _, service := range serviceList {
|
||||
svc, ok := service.(*v12.Service)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
services = append(services, *svc)
|
||||
}
|
||||
if len(services) == 0 {
|
||||
continue
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
c.Services = services
|
||||
c.usingResolver(ctx)
|
||||
}
|
||||
}()
|
||||
c.usingResolver(ctx)
|
||||
return nil
|
||||
}
|
||||
@@ -72,6 +129,9 @@ func (c *Config) usingResolver(ctx context.Context) {
|
||||
plog.G(ctx).Errorf("Parse resolver %s error: %v", filename, err)
|
||||
continue
|
||||
}
|
||||
if slices.Contains(conf.Servers, clientConfig.Servers[0]) {
|
||||
continue
|
||||
}
|
||||
// insert current name server to first location
|
||||
conf.Servers = append([]string{clientConfig.Servers[0]}, conf.Servers...)
|
||||
err = os.WriteFile(filename, []byte(toString(*conf)), 0644)
|
||||
|
||||
@@ -58,6 +58,7 @@ func (c *ConnectOptions) Cleanup(ctx context.Context) {
|
||||
}
|
||||
if c.clientset != nil {
|
||||
_ = c.clientset.CoreV1().Pods(c.Namespace).Delete(ctx2, config.CniNetName, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
|
||||
_ = c.clientset.BatchV1().Jobs(c.Namespace).Delete(ctx2, config.ConfigMapPodTrafficManager, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
|
||||
}
|
||||
// leave proxy resources
|
||||
err := c.LeaveAllProxyResources(ctx2)
|
||||
|
||||
@@ -32,15 +32,16 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
pkgruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
pkgtypes "k8s.io/apimachinery/pkg/types"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
runtimeresource "k8s.io/cli-runtime/pkg/resource"
|
||||
informerv1 "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v2 "k8s.io/client-go/kubernetes/typed/networking/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/kubectl/pkg/cmd/set"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
@@ -67,6 +68,7 @@ type ConnectOptions struct {
|
||||
Engine config.Engine
|
||||
Foreground bool
|
||||
OriginKubeconfigPath string
|
||||
OriginNamespace string
|
||||
Lock *sync.Mutex
|
||||
ImagePullSecretName string
|
||||
|
||||
@@ -279,13 +281,14 @@ func (c *ConnectOptions) DoConnect(ctx context.Context, isLite bool, stopChan <-
|
||||
return
|
||||
}
|
||||
plog.G(ctx).Infof("Adding Pod IP and Service IP to route table...")
|
||||
if err = c.addRouteDynamic(c.ctx); err != nil {
|
||||
var svcInformer cache.SharedIndexInformer
|
||||
if svcInformer, _, err = c.addRouteDynamic(c.ctx); err != nil {
|
||||
plog.G(ctx).Errorf("Add route dynamic failed: %v", err)
|
||||
return
|
||||
}
|
||||
go c.deleteFirewallRule(c.ctx)
|
||||
plog.G(ctx).Infof("Configuring DNS service...")
|
||||
if err = c.setupDNS(c.ctx); err != nil {
|
||||
if err = c.setupDNS(c.ctx, svcInformer); err != nil {
|
||||
plog.G(ctx).Errorf("Configure DNS failed: %v", err)
|
||||
return
|
||||
}
|
||||
@@ -329,19 +332,19 @@ func (c *ConnectOptions) portForward(ctx context.Context, portPair []string) err
|
||||
podName := pod.GetName()
|
||||
// try to detect pod is delete event, if pod is deleted, needs to redo port-forward
|
||||
go util.CheckPodStatus(childCtx, cancelFunc, podName, c.clientset.CoreV1().Pods(c.Namespace))
|
||||
go healthCheck(childCtx, cancelFunc, readyChan, strings.Split(portPair[1], ":")[0], fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, c.Namespace))
|
||||
go func() {
|
||||
select {
|
||||
case <-readyChan:
|
||||
for _, pair := range portPair {
|
||||
ports := strings.Split(pair, ":")
|
||||
plog.G(ctx).Infof("Forwarding from %s -> %s", net.JoinHostPort("127.0.0.1", ports[0]), ports[1])
|
||||
domain := fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, c.Namespace)
|
||||
go healthCheckPortForward(childCtx, cancelFunc, readyChan, strings.Split(portPair[1], ":")[0], domain, c.localTunIPv4.IP)
|
||||
go healthCheckTCPConn(childCtx, cancelFunc, readyChan, domain, util.GetPodIP(pod)[0])
|
||||
if *first {
|
||||
go func() {
|
||||
select {
|
||||
case <-readyChan:
|
||||
firstCancelFunc()
|
||||
case <-childCtx.Done():
|
||||
}
|
||||
firstCancelFunc()
|
||||
case <-childCtx.Done():
|
||||
}
|
||||
}()
|
||||
|
||||
}()
|
||||
}
|
||||
out := plog.G(ctx).Out
|
||||
err = util.PortForwardPod(
|
||||
c.config,
|
||||
c.restclient,
|
||||
@@ -350,8 +353,8 @@ func (c *ConnectOptions) portForward(ctx context.Context, portPair []string) err
|
||||
portPair,
|
||||
readyChan,
|
||||
childCtx.Done(),
|
||||
nil,
|
||||
plog.G(ctx).Out,
|
||||
out,
|
||||
out,
|
||||
)
|
||||
if *first {
|
||||
util.SafeWrite(errChan, err)
|
||||
@@ -419,7 +422,7 @@ func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress
|
||||
}
|
||||
|
||||
var routes []types.Route
|
||||
for _, ipNet := range util.RemoveLargerOverlappingCIDRs(cidrList) {
|
||||
for _, ipNet := range util.RemoveCIDRsContainingIPs(util.RemoveLargerOverlappingCIDRs(cidrList), c.apiServerIPs) {
|
||||
if ipNet != nil {
|
||||
routes = append(routes, types.Route{Dst: *ipNet})
|
||||
}
|
||||
@@ -489,57 +492,116 @@ func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress
|
||||
}
|
||||
|
||||
// Listen all pod, add route if needed
|
||||
func (c *ConnectOptions) addRouteDynamic(ctx context.Context) error {
|
||||
podNs, svcNs, err1 := util.GetNsForListPodAndSvc(ctx, c.clientset, []string{v1.NamespaceAll, c.Namespace})
|
||||
if err1 != nil {
|
||||
return err1
|
||||
func (c *ConnectOptions) addRouteDynamic(ctx context.Context) (cache.SharedIndexInformer, cache.SharedIndexInformer, error) {
|
||||
podNs, svcNs, err := util.GetNsForListPodAndSvc(ctx, c.clientset, []string{v1.NamespaceAll, c.OriginNamespace})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
conf := rest.CopyConfig(c.config)
|
||||
conf.QPS = 1
|
||||
conf.Burst = 2
|
||||
clientSet, err := kubernetes.NewForConfig(conf)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to create clientset: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
svcIndexers := cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}
|
||||
svcInformer := informerv1.NewServiceInformer(clientSet, svcNs, 0, svcIndexers)
|
||||
svcTicker := time.NewTicker(time.Second * 15)
|
||||
_, err = svcInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
svcTicker.Reset(time.Second * 3)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
svcTicker.Reset(time.Second * 3)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
svcTicker.Reset(time.Second * 3)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add service event handler: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
go svcInformer.Run(ctx.Done())
|
||||
go func() {
|
||||
var listDone bool
|
||||
for ctx.Err() == nil {
|
||||
err := func() error {
|
||||
if !listDone {
|
||||
err := util.ListService(ctx, c.clientset.CoreV1().Services(svcNs), c.addRoute)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listDone = true
|
||||
defer svcTicker.Stop()
|
||||
for ; ctx.Err() == nil; <-svcTicker.C {
|
||||
svcTicker.Reset(time.Second * 15)
|
||||
serviceList := svcInformer.GetIndexer().List()
|
||||
var ips = sets.New[string]()
|
||||
for _, service := range serviceList {
|
||||
svc, ok := service.(*v1.Service)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
err := util.WatchServiceToAddRoute(ctx, c.clientset.CoreV1().Services(svcNs), c.addRoute)
|
||||
return err
|
||||
}()
|
||||
if utilnet.IsConnectionRefused(err) || apierrors.IsTooManyRequests(err) || apierrors.IsForbidden(err) {
|
||||
time.Sleep(time.Second * 10)
|
||||
} else {
|
||||
time.Sleep(time.Second * 2)
|
||||
ips.Insert(svc.Spec.ClusterIP)
|
||||
ips.Insert(svc.Spec.ClusterIPs...)
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
if ips.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
err := c.addRoute(ips.UnsortedList()...)
|
||||
if err != nil {
|
||||
plog.G(ctx).Debugf("Add service IP to route table failed: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
podIndexers := cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}
|
||||
podInformer := informerv1.NewPodInformer(clientSet, podNs, 0, podIndexers)
|
||||
podTicker := time.NewTicker(time.Second * 15)
|
||||
_, err = podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
podTicker.Reset(time.Second * 3)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
podTicker.Reset(time.Second * 3)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
podTicker.Reset(time.Second * 3)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add service event handler: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
go podInformer.Run(ctx.Done())
|
||||
go func() {
|
||||
var listDone bool
|
||||
for ctx.Err() == nil {
|
||||
err := func() error {
|
||||
if !listDone {
|
||||
err := util.ListPod(ctx, c.clientset.CoreV1().Pods(podNs), c.addRoute)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listDone = true
|
||||
defer podTicker.Stop()
|
||||
for ; ctx.Err() == nil; <-podTicker.C {
|
||||
podTicker.Reset(time.Second * 15)
|
||||
podList := podInformer.GetIndexer().List()
|
||||
var ips = sets.New[string]()
|
||||
for _, pod := range podList {
|
||||
p, ok := pod.(*v1.Pod)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
err := util.WatchPodToAddRoute(ctx, c.clientset.CoreV1().Pods(podNs), c.addRoute)
|
||||
return err
|
||||
}()
|
||||
if utilnet.IsConnectionRefused(err) || apierrors.IsTooManyRequests(err) || apierrors.IsForbidden(err) {
|
||||
time.Sleep(time.Second * 10)
|
||||
} else {
|
||||
time.Sleep(time.Second * 2)
|
||||
if p.Spec.HostNetwork {
|
||||
continue
|
||||
}
|
||||
ips.Insert(util.GetPodIP(*p)...)
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
if ips.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
err := c.addRoute(ips.UnsortedList()...)
|
||||
if err != nil {
|
||||
plog.G(ctx).Debugf("Add pod IP to route table failed: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
return svcInformer, podInformer, nil
|
||||
}
|
||||
|
||||
func (c *ConnectOptions) addRoute(ipStrList ...string) error {
|
||||
@@ -547,6 +609,7 @@ func (c *ConnectOptions) addRoute(ipStrList ...string) error {
|
||||
return nil
|
||||
}
|
||||
var routes []types.Route
|
||||
r, _ := netroute.New()
|
||||
for _, ipStr := range ipStrList {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip == nil {
|
||||
@@ -569,7 +632,7 @@ func (c *ConnectOptions) addRoute(ipStrList ...string) error {
|
||||
} else {
|
||||
mask = net.CIDRMask(128, 128)
|
||||
}
|
||||
if r, err := netroute.New(); err == nil {
|
||||
if r != nil {
|
||||
ifi, _, _, err := r.Route(ip)
|
||||
if err == nil && ifi.Name == c.tunName {
|
||||
continue
|
||||
@@ -577,6 +640,9 @@ func (c *ConnectOptions) addRoute(ipStrList ...string) error {
|
||||
}
|
||||
routes = append(routes, types.Route{Dst: net.IPNet{IP: ip, Mask: mask}})
|
||||
}
|
||||
if len(routes) == 0 {
|
||||
return nil
|
||||
}
|
||||
err := tun.AddRoutes(c.tunName, routes...)
|
||||
return err
|
||||
}
|
||||
@@ -599,7 +665,7 @@ func (c *ConnectOptions) deleteFirewallRule(ctx context.Context) {
|
||||
util.DeleteBlockFirewallRule(ctx)
|
||||
}
|
||||
|
||||
func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
||||
func (c *ConnectOptions) setupDNS(ctx context.Context, svcInformer cache.SharedIndexInformer) error {
|
||||
const portTCP = 10800
|
||||
podList, err := c.GetRunningPodList(ctx)
|
||||
if err != nil {
|
||||
@@ -640,8 +706,8 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ns := []string{c.Namespace}
|
||||
list, err := c.clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
ns := []string{c.OriginNamespace}
|
||||
list, err := c.clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{Limit: 100})
|
||||
if err == nil {
|
||||
for _, item := range list.Items {
|
||||
if !sets.New[string](ns...).Has(item.Name) {
|
||||
@@ -650,20 +716,15 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
plog.G(ctx).Infof("Listing namespace %s services...", c.Namespace)
|
||||
var serviceList []v1.Service
|
||||
services, err := c.clientset.CoreV1().Services(c.Namespace).List(ctx, metav1.ListOptions{})
|
||||
if err == nil {
|
||||
serviceList = append(serviceList, services.Items...)
|
||||
}
|
||||
|
||||
plog.G(ctx).Infof("Listing namespace %s services...", c.OriginNamespace)
|
||||
c.dnsConfig = &dns.Config{
|
||||
Config: relovConf,
|
||||
Ns: ns,
|
||||
Services: serviceList,
|
||||
TunName: c.tunName,
|
||||
Hosts: c.extraHost,
|
||||
Lock: c.Lock,
|
||||
Config: relovConf,
|
||||
Ns: ns,
|
||||
Services: []v1.Service{},
|
||||
SvcInformer: svcInformer,
|
||||
TunName: c.tunName,
|
||||
Hosts: c.extraHost,
|
||||
Lock: c.Lock,
|
||||
HowToGetExternalName: func(domain string) (string, error) {
|
||||
podList, err := c.GetRunningPodList(ctx)
|
||||
if err != nil {
|
||||
@@ -685,9 +746,9 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error {
|
||||
if err = c.dnsConfig.SetupDNS(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
plog.G(ctx).Infof("Dump service in namespace %s into hosts...", c.Namespace)
|
||||
plog.G(ctx).Infof("Dump service in namespace %s into hosts...", c.OriginNamespace)
|
||||
// dump service in current namespace for support DNS resolve service:port
|
||||
err = c.dnsConfig.AddServiceNameToHosts(ctx, c.clientset.CoreV1().Services(c.Namespace), c.extraHost...)
|
||||
err = c.dnsConfig.AddServiceNameToHosts(ctx, c.extraHost...)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -787,18 +848,13 @@ func (c *ConnectOptions) getCIDR(ctx context.Context, m *dhcp.Manager) error {
|
||||
}
|
||||
|
||||
// (2) get CIDR from cni
|
||||
c.cidrs, err = util.GetCIDR(ctx, c.clientset, c.config, c.Namespace)
|
||||
c.cidrs = util.RemoveCIDRsContainingIPs(util.RemoveLargerOverlappingCIDRs(c.cidrs), c.apiServerIPs)
|
||||
if err == nil {
|
||||
s := sets.New[string]()
|
||||
for _, cidr := range c.cidrs {
|
||||
s.Insert(cidr.String())
|
||||
}
|
||||
return m.Set(ctx, config.KeyClusterIPv4POOLS, strings.Join(s.UnsortedList(), " "))
|
||||
cidrs := util.GetCIDR(ctx, c.clientset, c.config, c.Namespace)
|
||||
c.cidrs = util.RemoveCIDRsContainingIPs(util.RemoveLargerOverlappingCIDRs(cidrs), c.apiServerIPs)
|
||||
s := sets.New[string]()
|
||||
for _, cidr := range c.cidrs {
|
||||
s.Insert(cidr.String())
|
||||
}
|
||||
|
||||
// ignore error
|
||||
return nil
|
||||
return m.Set(ctx, config.KeyClusterIPv4POOLS, strings.Join(s.UnsortedList(), " "))
|
||||
}
|
||||
|
||||
func (c *ConnectOptions) addExtraRoute(ctx context.Context, name string) error {
|
||||
@@ -1206,7 +1262,7 @@ func (c *ConnectOptions) ProxyResources() ProxyList {
|
||||
return c.proxyWorkloads
|
||||
}
|
||||
|
||||
func healthCheck(ctx context.Context, cancelFunc context.CancelFunc, readyChan chan struct{}, localGvisorUDPPort string, domain string) {
|
||||
func healthCheckPortForward(ctx context.Context, cancelFunc context.CancelFunc, readyChan chan struct{}, localGvisorUDPPort string, domain string, ipv4 net.IP) {
|
||||
defer cancelFunc()
|
||||
ticker := time.NewTicker(time.Second * 60)
|
||||
defer ticker.Stop()
|
||||
@@ -1230,7 +1286,7 @@ func healthCheck(ctx context.Context, cancelFunc context.CancelFunc, readyChan c
|
||||
LocalPort: 53,
|
||||
LocalAddress: tcpip.AddrFrom4Slice(net.ParseIP("127.0.0.1").To4()),
|
||||
RemotePort: 0,
|
||||
RemoteAddress: tcpip.AddrFrom4Slice(net.IPv4zero.To4()),
|
||||
RemoteAddress: tcpip.AddrFrom4Slice(ipv4.To4()),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1260,3 +1316,40 @@ func healthCheck(ctx context.Context, cancelFunc context.CancelFunc, readyChan c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func healthCheckTCPConn(ctx context.Context, cancelFunc context.CancelFunc, readyChan chan struct{}, domain string, dnsServer string) {
|
||||
defer cancelFunc()
|
||||
ticker := time.NewTicker(time.Second * 60)
|
||||
defer ticker.Stop()
|
||||
|
||||
select {
|
||||
case <-readyChan:
|
||||
case <-ticker.C:
|
||||
plog.G(ctx).Debugf("Wait port-forward to be ready timeout")
|
||||
return
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
var healthChecker = func() error {
|
||||
msg := new(miekgdns.Msg)
|
||||
msg.SetQuestion(miekgdns.Fqdn(domain), miekgdns.TypeA)
|
||||
client := miekgdns.Client{Net: "udp", Timeout: time.Second * 10}
|
||||
_, _, err := client.ExchangeContext(ctx, msg, net.JoinHostPort(dnsServer, "53"))
|
||||
return err
|
||||
}
|
||||
|
||||
newTicker := time.NewTicker(config.KeepAliveTime / 2)
|
||||
defer newTicker.Stop()
|
||||
for ; ctx.Err() == nil; <-newTicker.C {
|
||||
err := retry.OnError(wait.Backoff{Duration: time.Second * 10, Steps: 6}, func(err error) bool {
|
||||
return err != nil
|
||||
}, func() error {
|
||||
return healthChecker()
|
||||
})
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to query DNS: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"k8s.io/client-go/util/retry"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
pkgconfig "github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ const (
|
||||
|
||||
func TestFunctions(t *testing.T) {
|
||||
// 1) test connect
|
||||
Init()
|
||||
t.Run("init", Init)
|
||||
t.Run("kubevpnConnect", kubevpnConnect)
|
||||
t.Run("commonTest", commonTest)
|
||||
|
||||
@@ -65,6 +65,37 @@ func TestFunctions(t *testing.T) {
|
||||
t.Run("commonTest", commonTest)
|
||||
t.Run("serviceMeshReviewsServiceIP", serviceMeshReviewsServiceIP)
|
||||
t.Run("kubevpnQuit", kubevpnQuit)
|
||||
|
||||
// 5) install centrally in ns test -- connect mode
|
||||
t.Run("centerKubevpnUninstall", kubevpnUninstall)
|
||||
t.Run("centerKubevpnInstallInNsKubevpn", kubevpnConnectToNsKubevpn)
|
||||
t.Run("centerKubevpnConnect", kubevpnConnect)
|
||||
t.Run("checkServiceShouldNotInNsDefault", checkServiceShouldNotInNsDefault)
|
||||
t.Run("centerCommonTest", commonTest)
|
||||
|
||||
// 6) install centrally in ns test -- proxy mode
|
||||
t.Run("centerKubevpnProxy", kubevpnProxy)
|
||||
t.Run("checkServiceShouldNotInNsDefault", checkServiceShouldNotInNsDefault)
|
||||
t.Run("centerCommonTest", commonTest)
|
||||
t.Run("centerTestUDP", testUDP)
|
||||
t.Run("centerProxyServiceReviewsServiceIP", proxyServiceReviewsServiceIP)
|
||||
t.Run("centerProxyServiceReviewsPodIP", proxyServiceReviewsPodIP)
|
||||
|
||||
// 7) install centrally in ns test -- proxy mode with service mesh
|
||||
t.Run("kubevpnLeave", kubevpnLeave)
|
||||
t.Run("kubevpnProxyWithServiceMesh", kubevpnProxyWithServiceMesh)
|
||||
t.Run("checkServiceShouldNotInNsDefault", checkServiceShouldNotInNsDefault)
|
||||
t.Run("commonTest", commonTest)
|
||||
t.Run("serviceMeshReviewsServiceIP", serviceMeshReviewsServiceIP)
|
||||
t.Run("serviceMeshReviewsPodIP", serviceMeshReviewsPodIP)
|
||||
|
||||
// 8) install centrally in ns test -- proxy mode with service mesh and gvisor
|
||||
t.Run("kubevpnQuit", kubevpnQuit)
|
||||
t.Run("kubevpnProxyWithServiceMeshAndGvisorMode", kubevpnProxyWithServiceMeshAndGvisorMode)
|
||||
t.Run("checkServiceShouldNotInNsDefault", checkServiceShouldNotInNsDefault)
|
||||
t.Run("commonTest", commonTest)
|
||||
t.Run("serviceMeshReviewsServiceIP", serviceMeshReviewsServiceIP)
|
||||
t.Run("kubevpnQuit", kubevpnQuit)
|
||||
}
|
||||
|
||||
func commonTest(t *testing.T) {
|
||||
@@ -275,34 +306,37 @@ func proxyServiceReviewsServiceIP(t *testing.T) {
|
||||
|
||||
func testUDP(t *testing.T) {
|
||||
app := "reviews"
|
||||
port, _ := util.GetAvailableUDPPortOrDie()
|
||||
go udpServer(port)
|
||||
|
||||
ip, err := getPodIP(app)
|
||||
port, err := util.GetAvailableUDPPortOrDie()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Printf("Dail udp to IP: %s", ip)
|
||||
go udpServer(t, port)
|
||||
|
||||
var ip string
|
||||
err = retry.OnError(
|
||||
wait.Backoff{Duration: time.Second, Factor: 2, Jitter: 0.2, Steps: 5},
|
||||
func(err error) bool {
|
||||
return err != nil
|
||||
},
|
||||
func() error {
|
||||
return udpClient(ip, port)
|
||||
ip, err = getPodIP(app)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("Dail udp to IP: %s", ip)
|
||||
return udpClient(t, ip, port)
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to access pod IP: %s, port: %v", ip, port)
|
||||
}
|
||||
}
|
||||
|
||||
func udpClient(ip string, port int) error {
|
||||
func udpClient(t *testing.T, ip string, port int) error {
|
||||
udpConn, err := net.DialUDP("udp4", nil, &net.UDPAddr{
|
||||
IP: net.ParseIP(ip),
|
||||
Port: port,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("连接失败!", err)
|
||||
return err
|
||||
}
|
||||
defer udpConn.Close()
|
||||
@@ -312,51 +346,48 @@ func udpClient(ip string, port int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送数据
|
||||
sendData := []byte("hello server!")
|
||||
_, err = udpConn.Write(sendData)
|
||||
if err != nil {
|
||||
fmt.Println("发送数据失败!", err)
|
||||
t.Logf("Failed to send udp packet: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
data := make([]byte, 4096)
|
||||
read, remoteAddr, err := udpConn.ReadFromUDP(data)
|
||||
if err != nil {
|
||||
fmt.Println("读取数据失败!", err)
|
||||
t.Logf("Failed to read udp packet: %v", err)
|
||||
return err
|
||||
}
|
||||
fmt.Println(read, remoteAddr)
|
||||
fmt.Printf("%s\n", data[0:read])
|
||||
t.Logf("read data from %v: %v", remoteAddr, string(data[:read]))
|
||||
return nil
|
||||
}
|
||||
|
||||
func udpServer(port int) {
|
||||
func udpServer(t *testing.T, port int) {
|
||||
// 创建监听
|
||||
udpConn, err := net.ListenUDP("udp4", &net.UDPAddr{
|
||||
IP: net.IPv4(0, 0, 0, 0),
|
||||
Port: port,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
return
|
||||
}
|
||||
defer udpConn.Close()
|
||||
|
||||
data := make([]byte, 4096)
|
||||
for {
|
||||
data := make([]byte, 4096)
|
||||
read, remoteAddr, err := udpConn.ReadFromUDP(data)
|
||||
read, remoteAddr, err := udpConn.ReadFromUDP(data[:])
|
||||
if err != nil {
|
||||
fmt.Println("读取数据失败!", err)
|
||||
t.Logf("failed to read udp data from %v: %v", remoteAddr, err)
|
||||
continue
|
||||
}
|
||||
fmt.Println(read, remoteAddr)
|
||||
fmt.Printf("%s\n\n", data[0:read])
|
||||
t.Logf("read data from %v: %v", remoteAddr, string(data[:read]))
|
||||
|
||||
sendData := []byte("hello client!")
|
||||
_, err = udpConn.WriteToUDP(sendData, remoteAddr)
|
||||
if err != nil {
|
||||
fmt.Println("发送数据失败!", err)
|
||||
t.Logf("failed to send udp data to %v: %v", remoteAddr, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -372,6 +403,27 @@ func kubevpnConnect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func kubevpnConnectToNsKubevpn(t *testing.T) {
|
||||
_, err := clientset.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "kubevpn",
|
||||
},
|
||||
}, v1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cmdConnect := exec.Command("kubevpn", "connect", "--namespace", "kubevpn", "--debug")
|
||||
cmdQuit := exec.Command("kubevpn", "quit")
|
||||
for _, cmd := range []*exec.Cmd{cmdConnect, cmdQuit} {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func kubevpnProxy(t *testing.T) {
|
||||
cmd := exec.Command("kubevpn", "proxy", "deployments/reviews", "--debug")
|
||||
cmd.Stdout = os.Stdout
|
||||
@@ -442,52 +494,58 @@ func kubevpnQuit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func kubectl(t *testing.T) {
|
||||
cmd := exec.Command("kubectl", "get", "pods", "-o", "wide")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = exec.Command("kubectl", "get", "services", "-o", "wide")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
func checkServiceShouldNotInNsDefault(t *testing.T) {
|
||||
_, err := clientset.CoreV1().Services(namespace).Get(context.Background(), pkgconfig.ConfigMapPodTrafficManager, v1.GetOptions{})
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Init() {
|
||||
func kubectl(t *testing.T) {
|
||||
cmdGetPod := exec.Command("kubectl", "get", "pods", "-o", "wide")
|
||||
cmdDescribePod := exec.Command("kubectl", "describe", "pods")
|
||||
cmdGetSvc := exec.Command("kubectl", "get", "services", "-o", "wide")
|
||||
cmdDescribeSvc := exec.Command("kubectl", "describe", "services")
|
||||
for _, cmd := range []*exec.Cmd{cmdGetPod, cmdDescribePod, cmdGetSvc, cmdDescribeSvc} {
|
||||
t.Logf("exec: %v", cmd.Args)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Init(t *testing.T) {
|
||||
var err error
|
||||
|
||||
configFlags := genericclioptions.NewConfigFlags(true)
|
||||
f := cmdutil.NewFactory(cmdutil.NewMatchVersionFlags(configFlags))
|
||||
|
||||
if restconfig, err = f.ToRESTConfig(); err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
if clientset, err = kubernetes.NewForConfig(restconfig); err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
if namespace, _, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go startupHttpServer(local)
|
||||
go startupHttpServer(t, local)
|
||||
}
|
||||
|
||||
func startupHttpServer(str string) {
|
||||
func startupHttpServer(t *testing.T, str string) {
|
||||
var health = func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(str))
|
||||
}
|
||||
|
||||
http.HandleFunc("/", health)
|
||||
http.HandleFunc("/health", health)
|
||||
log.Println("Start listening http port 9080 ...")
|
||||
if err := http.ListenAndServe(":9080", nil); err != nil {
|
||||
panic(err)
|
||||
t.Log("Start listening http port 9080 ...")
|
||||
err := http.ListenAndServe(":9080", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ func createOutboundPod(ctx context.Context, clientset *kubernetes.Clientset, nam
|
||||
_ = clientset.CoreV1().Services(namespace).Delete(ctx, name, options)
|
||||
_ = clientset.CoreV1().Secrets(namespace).Delete(ctx, name, options)
|
||||
_ = clientset.CoreV1().Pods(namespace).Delete(ctx, config.CniNetName, options)
|
||||
_ = clientset.BatchV1().Jobs(namespace).Delete(ctx, name, options)
|
||||
_ = clientset.AppsV1().Deployments(namespace).Delete(ctx, name, options)
|
||||
}
|
||||
defer func() {
|
||||
@@ -219,8 +220,9 @@ func genMutatingWebhookConfiguration(namespace string, crt []byte) *admissionv1.
|
||||
},
|
||||
}},
|
||||
FailurePolicy: ptr.To(admissionv1.Ignore),
|
||||
// namespace kubevpn is special, if installed to this namespace, means center install mode
|
||||
// same as above label ns
|
||||
NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"ns": namespace}},
|
||||
NamespaceSelector: util.If(namespace == config.DefaultNamespaceKubevpn, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"ns": namespace}}),
|
||||
SideEffects: ptr.To(admissionv1.SideEffectClassNone),
|
||||
TimeoutSeconds: ptr.To[int32](15),
|
||||
AdmissionReviewVersions: []string{"v1", "v1beta1"},
|
||||
|
||||
@@ -45,7 +45,7 @@ func (c *ConnectOptions) Uninstall(ctx context.Context) error {
|
||||
_ = c.clientset.RbacV1().Roles(ns).Delete(ctx, name, options)
|
||||
_ = c.clientset.CoreV1().Services(ns).Delete(ctx, name, options)
|
||||
_ = c.clientset.AppsV1().Deployments(ns).Delete(ctx, name, options)
|
||||
|
||||
_ = c.clientset.BatchV1().Jobs(ns).Delete(ctx, name, options)
|
||||
_ = c.CleanupLocalContainer(ctx)
|
||||
plog.G(ctx).Info("Done")
|
||||
return nil
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 0
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
imagePullPolicy: IfNotPresent
|
||||
- name: tomcat
|
||||
image: tomcat
|
||||
imagePullPolicy: IfNotPresent
|
||||
restartPolicy: Always
|
||||
@@ -1,47 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/tun"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := net.ParseIP("fe80::cff4:d42c:7e73:e84a")
|
||||
listener, err := tun.Listener(tun.Config{
|
||||
Addr: ip.String() + "/64",
|
||||
MTU: 1350,
|
||||
Routes: []types.Route{
|
||||
{
|
||||
Dst: net.IPNet{
|
||||
IP: ip,
|
||||
Mask: net.CIDRMask(64, 128),
|
||||
},
|
||||
}, {
|
||||
Dst: net.IPNet{
|
||||
IP: net.ParseIP("192.168.0.0"),
|
||||
Mask: net.CIDRMask(64, 128),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var tunConn net.Conn
|
||||
tunConn, err = listener.Accept()
|
||||
if err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
}
|
||||
defer tunConn.Close()
|
||||
tcpConn, err := net.Dial("tcp", ":1080")
|
||||
if err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
}
|
||||
go io.Copy(tunConn, tcpConn)
|
||||
io.Copy(tcpConn, tunConn)
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 0
|
||||
containers:
|
||||
- name: traffic-test
|
||||
image: ghcr.io/kubenetworks/kubevpn:v1.1.28
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
|
||||
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy
|
||||
iptables -P INPUT ACCEPT
|
||||
iptables -P FORWARD ACCEPT
|
||||
ip6tables -t nat -A POSTROUTING -s fe80::cff4:d42c:7e73:e84b/64 -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
|
||||
tail -f /dev/null
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add:
|
||||
- NET_ADMIN
|
||||
restartPolicy: Always
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export KUBECONFIG=~/.kube/vke
|
||||
export NS=kube-system
|
||||
kubectl apply -f pod.yaml -n $NS
|
||||
kubectl wait --for=condition=Ready pod/test -n $NS
|
||||
cd ./server && GOARCH=amd64 GOOS=linux go build -o main
|
||||
kubectl cp main test:/app/main -n $NS
|
||||
rm -fr main
|
||||
kubectl port-forward pods/test 1080 -n $NS
|
||||
@@ -1,39 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/tun"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := net.ParseIP("fe80::cff4:d42c:7e73:e84b")
|
||||
listener, err := tun.Listener(tun.Config{
|
||||
Addr: ip.String() + "/64",
|
||||
MTU: 1350,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tunConn, _ := listener.Accept()
|
||||
|
||||
tcpListener, err := net.Listen("tcp", ":1080")
|
||||
if err != nil {
|
||||
plog.G(context.Background()).Fatal(err)
|
||||
}
|
||||
for {
|
||||
tcpConn, err := tcpListener.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go func(tcpConn net.Conn) {
|
||||
defer tcpConn.Close()
|
||||
go io.Copy(tunConn, tcpConn)
|
||||
io.Copy(tcpConn, tunConn)
|
||||
}(tcpConn)
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
// 2) grep cmdline
|
||||
// 3) create svc + cat *.conflist
|
||||
// 4) create svc + get pod ip with svc mask
|
||||
func GetCIDR(ctx context.Context, clientset *kubernetes.Clientset, restconfig *rest.Config, namespace string) ([]*net.IPNet, error) {
|
||||
func GetCIDR(ctx context.Context, clientset *kubernetes.Clientset, restconfig *rest.Config, namespace string) []*net.IPNet {
|
||||
defer func() {
|
||||
_ = clientset.CoreV1().Pods(namespace).Delete(context.Background(), config.CniNetName, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
|
||||
}()
|
||||
@@ -70,7 +70,7 @@ func GetCIDR(ctx context.Context, clientset *kubernetes.Clientset, restconfig *r
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return result
|
||||
}
|
||||
|
||||
// ParseCIDRFromString
|
||||
|
||||
@@ -53,10 +53,10 @@ func TestByDumpClusterInfo(t *testing.T) {
|
||||
before()
|
||||
info, err := GetCIDRByDumpClusterInfo(context.Background(), clientset)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Log(err.Error())
|
||||
}
|
||||
for _, ipNet := range info {
|
||||
fmt.Println(ipNet.String())
|
||||
t.Log(ipNet.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,19 +64,18 @@ func TestByCreateSvc(t *testing.T) {
|
||||
before()
|
||||
info, err := GetServiceCIDRByCreateService(context.Background(), clientset.CoreV1().Services("default"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Log(err.Error())
|
||||
}
|
||||
if info != nil {
|
||||
t.Log(info.String())
|
||||
}
|
||||
fmt.Println(info)
|
||||
}
|
||||
|
||||
func TestElegant(t *testing.T) {
|
||||
before()
|
||||
elegant, err := GetCIDR(context.Background(), clientset, restconfig, namespace)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for _, net := range elegant {
|
||||
fmt.Println(net.String())
|
||||
elegant := GetCIDR(context.Background(), clientset, restconfig, namespace)
|
||||
for _, ipNet := range elegant {
|
||||
t.Log(ipNet.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
)
|
||||
|
||||
func DownloadFileWithName(uri, name string) (string, error) {
|
||||
@@ -120,7 +122,7 @@ func ParseDirMapping(dir string) (local, remote string, err error) {
|
||||
}
|
||||
|
||||
func CleanupTempKubeConfigFile() error {
|
||||
return filepath.Walk(os.TempDir(), func(path string, info fs.FileInfo, err error) error {
|
||||
return filepath.Walk(config.GetTempPath(), func(path string, info fs.FileInfo, err error) error {
|
||||
if strings.HasSuffix(path, ".kubeconfig") {
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
@@ -16,26 +16,26 @@ import (
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
)
|
||||
|
||||
// DetectConnectNamespace
|
||||
// DetectManagerNamespace
|
||||
// 1. use helm to install kubevpn server, means cluster mode,
|
||||
// all kubevpn client should connect to this namespace.
|
||||
// 2. if any error occurs, just ignore and will use options `-n` or `--namespace`
|
||||
func DetectConnectNamespace(ctx context.Context, f cmdutil.Factory, connectNamespace string) (string, error) {
|
||||
func DetectManagerNamespace(ctx context.Context, f cmdutil.Factory, namespace string) (string, error) {
|
||||
clientSet, err := f.KubernetesClientSet()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var exists bool
|
||||
exists, err = DetectPodExists(ctx, clientSet, connectNamespace)
|
||||
exists, err = DetectPodExists(ctx, clientSet, namespace)
|
||||
if err != nil && !k8serrors.IsNotFound(err) && !k8serrors.IsForbidden(err) {
|
||||
return "", err
|
||||
} else if err != nil {
|
||||
plog.G(ctx).Debugf("Failed to detect if kubevpn exists in namespace %s: %v", connectNamespace, err)
|
||||
plog.G(ctx).Debugf("Failed to detect if kubevpn exists in namespace %s: %v", namespace, err)
|
||||
}
|
||||
if exists {
|
||||
plog.G(ctx).Debugf("Find exists kubevpn in namespace %s", connectNamespace)
|
||||
return connectNamespace, nil
|
||||
plog.G(ctx).Debugf("Find exists kubevpn in namespace %s", namespace)
|
||||
return namespace, nil
|
||||
}
|
||||
|
||||
exists, err = DetectPodExists(ctx, clientSet, config.DefaultNamespaceKubevpn)
|
||||
|
||||
@@ -8,14 +8,18 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
errors2 "github.com/pkg/errors"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v12 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
@@ -25,6 +29,7 @@ import (
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
|
||||
"github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
)
|
||||
|
||||
func GetClusterID(ctx context.Context, client v12.ConfigMapInterface) (types.UID, error) {
|
||||
@@ -131,8 +136,9 @@ func GetAPIServerFromKubeConfigBytes(kubeconfigBytes []byte) *net.IPNet {
|
||||
func ConvertToTempKubeconfigFile(kubeconfigBytes []byte) (string, error) {
|
||||
pattern := "*.kubeconfig"
|
||||
cluster, ns, _ := GetCluster(kubeconfigBytes)
|
||||
if cluster != "" {
|
||||
if cluster != "" && !containerPathSeparator(cluster) && !containerPathSeparator(ns) {
|
||||
pattern = fmt.Sprintf("%s_%s_%s", cluster, ns, pattern)
|
||||
pattern = strings.ReplaceAll(pattern, string(os.PathSeparator), "-")
|
||||
}
|
||||
temp, err := os.CreateTemp(config.GetTempPath(), pattern)
|
||||
if err != nil {
|
||||
@@ -153,6 +159,15 @@ func ConvertToTempKubeconfigFile(kubeconfigBytes []byte) (string, error) {
|
||||
return temp.Name(), nil
|
||||
}
|
||||
|
||||
func containerPathSeparator(pattern string) bool {
|
||||
for i := 0; i < len(pattern); i++ {
|
||||
if os.IsPathSeparator(pattern[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetCluster(kubeConfigBytes []byte) (cluster string, ns string, err error) {
|
||||
var clientConfig clientcmd.ClientConfig
|
||||
clientConfig, err = clientcmd.NewClientConfigFromBytes(kubeConfigBytes)
|
||||
@@ -248,3 +263,48 @@ func GetKubeconfigPath(factory cmdutil.Factory) (string, error) {
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func GetNsForListPodAndSvc(ctx context.Context, clientset *kubernetes.Clientset, nsList []string) (podNs string, svcNs string, err error) {
|
||||
for _, ns := range nsList {
|
||||
_, err = clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{Limit: 1})
|
||||
if errors.IsForbidden(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
podNs = ns
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
err = errors2.Wrap(err, "can not list pod to add it to route table")
|
||||
return
|
||||
}
|
||||
if podNs == "" {
|
||||
log.G(ctx).Debugf("List all namepsace pods")
|
||||
} else {
|
||||
log.G(ctx).Debugf("List namepsace %s pods", podNs)
|
||||
}
|
||||
|
||||
for _, ns := range nsList {
|
||||
_, err = clientset.CoreV1().Services(ns).List(ctx, metav1.ListOptions{Limit: 1})
|
||||
if errors.IsForbidden(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
svcNs = ns
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
err = errors2.Wrap(err, "can not list service to add it to route table")
|
||||
return
|
||||
}
|
||||
if svcNs == "" {
|
||||
log.G(ctx).Debugf("List all namepsace services")
|
||||
} else {
|
||||
log.G(ctx).Debugf("List namepsace %s services", svcNs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v12 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
|
||||
)
|
||||
|
||||
func GetNsForListPodAndSvc(ctx context.Context, clientset *kubernetes.Clientset, nsList []string) (podNs string, svcNs string, err error) {
|
||||
for _, ns := range nsList {
|
||||
_, err = clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{Limit: 1})
|
||||
if apierrors.IsForbidden(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
podNs = ns
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "can not list pod to add it to route table")
|
||||
return
|
||||
}
|
||||
if podNs == "" {
|
||||
plog.G(ctx).Debugf("List all namepsace pods")
|
||||
} else {
|
||||
plog.G(ctx).Debugf("List namepsace %s pods", podNs)
|
||||
}
|
||||
|
||||
for _, ns := range nsList {
|
||||
_, err = clientset.CoreV1().Services(ns).List(ctx, metav1.ListOptions{Limit: 1})
|
||||
if apierrors.IsForbidden(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
svcNs = ns
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "can not list service to add it to route table")
|
||||
return
|
||||
}
|
||||
if svcNs == "" {
|
||||
plog.G(ctx).Debugf("List all namepsace services")
|
||||
} else {
|
||||
plog.G(ctx).Debugf("List namepsace %s services", svcNs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ListService(ctx context.Context, lister v12.ServiceInterface, addRouteFunc func(ipStr ...string) error) error {
|
||||
opts := metav1.ListOptions{Limit: 100, Continue: ""}
|
||||
for {
|
||||
serviceList, err := lister.List(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ips []string
|
||||
for _, service := range serviceList.Items {
|
||||
ips = append(ips, service.Spec.ClusterIP)
|
||||
}
|
||||
err = addRouteFunc(ips...)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add service IP to route table: %v", err)
|
||||
}
|
||||
if serviceList.Continue == "" {
|
||||
return nil
|
||||
}
|
||||
opts.Continue = serviceList.Continue
|
||||
}
|
||||
}
|
||||
|
||||
func WatchServiceToAddRoute(ctx context.Context, watcher v12.ServiceInterface, routeFunc func(ipStr ...string) error) error {
|
||||
defer func() {
|
||||
if er := recover(); er != nil {
|
||||
plog.G(ctx).Error(er)
|
||||
}
|
||||
}()
|
||||
w, err := watcher.Watch(ctx, metav1.ListOptions{Watch: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case e, ok := <-w.ResultChan():
|
||||
if !ok {
|
||||
return errors.New("watch service chan done")
|
||||
}
|
||||
var svc *v1.Service
|
||||
svc, ok = e.Object.(*v1.Service)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
_ = routeFunc(svc.Spec.ClusterIP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ListPod(ctx context.Context, lister v12.PodInterface, addRouteFunc func(ipStr ...string) error) error {
|
||||
opts := metav1.ListOptions{Limit: 100, Continue: ""}
|
||||
for {
|
||||
podList, err := lister.List(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ips []string
|
||||
for _, pod := range podList.Items {
|
||||
if pod.Spec.HostNetwork {
|
||||
continue
|
||||
}
|
||||
ips = append(ips, pod.Status.PodIP)
|
||||
}
|
||||
err = addRouteFunc(ips...)
|
||||
if err != nil {
|
||||
plog.G(ctx).Errorf("Failed to add Pod IP to route table: %v", err)
|
||||
}
|
||||
if podList.Continue == "" {
|
||||
return nil
|
||||
}
|
||||
opts.Continue = podList.Continue
|
||||
}
|
||||
}
|
||||
|
||||
func WatchPodToAddRoute(ctx context.Context, watcher v12.PodInterface, addRouteFunc func(ipStrList ...string) error) error {
|
||||
defer func() {
|
||||
if er := recover(); er != nil {
|
||||
plog.G(ctx).Errorln(er)
|
||||
}
|
||||
}()
|
||||
w, err := watcher.Watch(ctx, metav1.ListOptions{Watch: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case e, ok := <-w.ResultChan():
|
||||
if !ok {
|
||||
return fmt.Errorf("watch pod chan done")
|
||||
}
|
||||
var pod *v1.Pod
|
||||
pod, ok = e.Object.(*v1.Pod)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if pod.Spec.HostNetwork {
|
||||
continue
|
||||
}
|
||||
ip := pod.Status.PodIP
|
||||
_ = addRouteFunc(ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ kind: Plugin
|
||||
metadata:
|
||||
name: kubevpn
|
||||
spec:
|
||||
version: v2.7.6
|
||||
version: v2.7.12
|
||||
homepage: https://github.com/kubenetworks/kubevpn
|
||||
shortDescription: "KubeVPN offers a Cloud Native Dev Environment that connects to kubernetes cluster network"
|
||||
description: |
|
||||
@@ -16,8 +16,8 @@ spec:
|
||||
matchLabels:
|
||||
os: windows
|
||||
arch: amd64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_windows_amd64.zip
|
||||
sha256: c05eed78a60e88160e81a10220bc35a8050061ad26602c983c36fb25b19c0ce1
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_windows_amd64.zip
|
||||
sha256: 6ba7929c168e3890e872295005d54d00e7172f513b3fa410988cf6015e018b91
|
||||
files:
|
||||
- from: ./bin/kubevpn.exe
|
||||
to: .
|
||||
@@ -28,8 +28,8 @@ spec:
|
||||
matchLabels:
|
||||
os: windows
|
||||
arch: arm64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_windows_arm64.zip
|
||||
sha256: 007858a4f0a8053c07066dcb8dc04d2e2cbf29d93948a4d0482d92b5eb1e7a2a
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_windows_arm64.zip
|
||||
sha256: a266fc82a97301651f957b77294ee0d810b1c2e6c3474f5566d9327c71d20e2a
|
||||
files:
|
||||
- from: ./bin/kubevpn.exe
|
||||
to: .
|
||||
@@ -40,8 +40,8 @@ spec:
|
||||
matchLabels:
|
||||
os: windows
|
||||
arch: 386
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_windows_386.zip
|
||||
sha256: 4b9db8811e96997b42ffa79571f7626d9d0d86eee2b7a019dfbf5f626426afb6
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_windows_386.zip
|
||||
sha256: 49863cf493ff121e6863f7a21975038c3d71b6fa6eafa3ef7a422f1370e1d929
|
||||
files:
|
||||
- from: ./bin/kubevpn.exe
|
||||
to: .
|
||||
@@ -52,8 +52,8 @@ spec:
|
||||
matchLabels:
|
||||
os: linux
|
||||
arch: amd64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_linux_amd64.zip
|
||||
sha256: 5038a4139ba6839c2a0836179457b0d9980ea7eb552480a3ea585dfda0093f86
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_linux_amd64.zip
|
||||
sha256: 894aca7c4f0ef1626121128e7bca7ee0e2dd56f4a0c518b6f4818c2dbdda8881
|
||||
files:
|
||||
- from: ./bin/kubevpn
|
||||
to: .
|
||||
@@ -64,8 +64,8 @@ spec:
|
||||
matchLabels:
|
||||
os: linux
|
||||
arch: arm64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_linux_arm64.zip
|
||||
sha256: 923a6658da82233ee30b74b282cfc8f9c869b6997a390cb33bcc18587a70be23
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_linux_arm64.zip
|
||||
sha256: 8692b2f8cf697f3ae2e168bcca3f18ae90657f36be6a0a321ffc4e5a778e706c
|
||||
files:
|
||||
- from: ./bin/kubevpn
|
||||
to: .
|
||||
@@ -76,8 +76,8 @@ spec:
|
||||
matchLabels:
|
||||
os: linux
|
||||
arch: 386
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_linux_386.zip
|
||||
sha256: ad18711f3a6ac56a1481daace84a0a24794d4fcc310fd1fdcf39dcdcba32fe5d
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_linux_386.zip
|
||||
sha256: bf3a96b919fe716527a625c781fe96bdf882f9ba80a37e8a2d90dd76568d07c3
|
||||
files:
|
||||
- from: ./bin/kubevpn
|
||||
to: .
|
||||
@@ -88,8 +88,8 @@ spec:
|
||||
matchLabels:
|
||||
os: darwin
|
||||
arch: amd64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_darwin_amd64.zip
|
||||
sha256: 24219bcbc98cabbb4267b5c8041a7d8a379adf09218b0e4bf503883d85a60adb
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_darwin_amd64.zip
|
||||
sha256: 97be61dfd1e880f64f3f3d91d026301a0f20cadb04272bfd2e2e3543783c040f
|
||||
files:
|
||||
- from: ./bin/kubevpn
|
||||
to: .
|
||||
@@ -100,8 +100,8 @@ spec:
|
||||
matchLabels:
|
||||
os: darwin
|
||||
arch: arm64
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn_v2.7.6_darwin_arm64.zip
|
||||
sha256: 8c5728d8ba16304eb1dbeaff076123d92257cdecfdcc165cc2c9e1b06c3c95db
|
||||
uri: https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn_v2.7.12_darwin_arm64.zip
|
||||
sha256: c6359ff064338d42efd648a793841e09741f22f4449275fc003ba7cabe8d32ce
|
||||
files:
|
||||
- from: ./bin/kubevpn
|
||||
to: .
|
||||
|
||||
@@ -1 +1 @@
|
||||
v2.7.6
|
||||
v2.7.12
|
||||
|
||||
3
vendor/github.com/ebitengine/purego/README.md
generated
vendored
3
vendor/github.com/ebitengine/purego/README.md
generated
vendored
@@ -36,7 +36,7 @@ except for float arguments and return values.
|
||||
## Example
|
||||
|
||||
The example below only showcases purego use for macOS and Linux. The other platforms require special handling which can
|
||||
be seen in the complete example at [examples/libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports FreeBSD and Windows.
|
||||
be seen in the complete example at [examples/libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows and FreeBSD.
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -92,7 +92,6 @@ This is a list of the copied files:
|
||||
* `internal/fakecgo/iscgo.go` from package `runtime/cgo`
|
||||
* `internal/fakecgo/setenv.go` from package `runtime/cgo`
|
||||
* `internal/fakecgo/freebsd.go` from package `runtime/cgo`
|
||||
* `internal/fakecgo/netbsd.go` from package `runtime/cgo`
|
||||
|
||||
The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of
|
||||
`#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/cgo.go
generated
vendored
2
vendor/github.com/ebitengine/purego/cgo.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build cgo && (darwin || freebsd || linux)
|
||||
|
||||
package purego
|
||||
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/dlerror.go
generated
vendored
2
vendor/github.com/ebitengine/purego/dlerror.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
package purego
|
||||
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/dlfcn.go
generated
vendored
2
vendor/github.com/ebitengine/purego/dlfcn.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build (darwin || freebsd || linux || netbsd) && !android && !faketime
|
||||
//go:build (darwin || freebsd || linux) && !android && !faketime
|
||||
|
||||
package purego
|
||||
|
||||
|
||||
15
vendor/github.com/ebitengine/purego/dlfcn_netbsd.go
generated
vendored
15
vendor/github.com/ebitengine/purego/dlfcn_netbsd.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
|
||||
|
||||
package purego
|
||||
|
||||
// Source for constants: https://github.com/NetBSD/src/blob/trunk/include/dlfcn.h
|
||||
|
||||
const (
|
||||
intSize = 32 << (^uint(0) >> 63) // 32 or 64
|
||||
RTLD_DEFAULT = 1<<intSize - 2 // Pseudo-handle for dlsym so search for any loaded symbol
|
||||
RTLD_LAZY = 0x00000001 // Relocations are performed at an implementation-dependent time.
|
||||
RTLD_NOW = 0x00000002 // Relocations are performed when the object is loaded.
|
||||
RTLD_LOCAL = 0x00000000 // All symbols are not made available for relocation processing by other modules.
|
||||
RTLD_GLOBAL = 0x00000100 // All symbols are available for relocation processing of other modules.
|
||||
)
|
||||
9
vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go
generated
vendored
9
vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go
generated
vendored
@@ -1,9 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
|
||||
|
||||
package purego
|
||||
|
||||
//go:cgo_import_dynamic purego_dlopen dlopen "libc.so"
|
||||
//go:cgo_import_dynamic purego_dlsym dlsym "libc.so"
|
||||
//go:cgo_import_dynamic purego_dlerror dlerror "libc.so"
|
||||
//go:cgo_import_dynamic purego_dlclose dlclose "libc.so"
|
||||
2
vendor/github.com/ebitengine/purego/dlfcn_stubs.s
generated
vendored
2
vendor/github.com/ebitengine/purego/dlfcn_stubs.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || !cgo && (freebsd || linux || netbsd) && !faketime
|
||||
//go:build darwin || !cgo && (freebsd || linux) && !faketime
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
155
vendor/github.com/ebitengine/purego/func.go
generated
vendored
155
vendor/github.com/ebitengine/purego/func.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd || windows
|
||||
//go:build darwin || freebsd || linux || windows
|
||||
|
||||
package purego
|
||||
|
||||
@@ -10,20 +10,14 @@ import (
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego/internal/strings"
|
||||
)
|
||||
|
||||
var thePool = sync.Pool{New: func() any {
|
||||
return new(syscall15Args)
|
||||
}}
|
||||
|
||||
// RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).
|
||||
// It panics if it can't find the name symbol.
|
||||
func RegisterLibFunc(fptr any, handle uintptr, name string) {
|
||||
func RegisterLibFunc(fptr interface{}, handle uintptr, name string) {
|
||||
sym, err := loadSymbol(handle, name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -66,7 +60,7 @@ func RegisterLibFunc(fptr any, handle uintptr, name string) {
|
||||
//
|
||||
// There is a special case when the last argument of fptr is a variadic interface (or []interface}
|
||||
// it will be expanded into a call to the C function as if it had the arguments in that slice.
|
||||
// This means that using arg ...any is like a cast to the function with the arguments inside arg.
|
||||
// This means that using arg ...interface{} is like a cast to the function with the arguments inside arg.
|
||||
// This is not the same as C variadic.
|
||||
//
|
||||
// # Memory
|
||||
@@ -111,7 +105,7 @@ func RegisterLibFunc(fptr any, handle uintptr, name string) {
|
||||
// defer free(mustFree)
|
||||
//
|
||||
// [Cgo rules]: https://pkg.go.dev/cmd/cgo#hdr-Go_references_to_C
|
||||
func RegisterFunc(fptr any, cfn uintptr) {
|
||||
func RegisterFunc(fptr interface{}, cfn uintptr) {
|
||||
fn := reflect.ValueOf(fptr).Elem()
|
||||
ty := fn.Type()
|
||||
if ty.Kind() != reflect.Func {
|
||||
@@ -162,7 +156,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
if is32bit {
|
||||
panic("purego: floats only supported on 64bit platforms")
|
||||
}
|
||||
if floats < numOfFloatRegisters {
|
||||
if floats < numOfFloats {
|
||||
floats++
|
||||
} else {
|
||||
stack++
|
||||
@@ -206,8 +200,21 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
}
|
||||
}
|
||||
v := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) {
|
||||
if len(args) > 0 {
|
||||
if variadic, ok := args[len(args)-1].Interface().([]interface{}); ok {
|
||||
// subtract one from args bc the last argument in args is []interface{}
|
||||
// which we are currently expanding
|
||||
tmp := make([]reflect.Value, len(args)-1+len(variadic))
|
||||
n := copy(tmp, args[:len(args)-1])
|
||||
for i, v := range variadic {
|
||||
tmp[n+i] = reflect.ValueOf(v)
|
||||
}
|
||||
args = tmp
|
||||
}
|
||||
}
|
||||
var sysargs [maxArgs]uintptr
|
||||
var floats [numOfFloatRegisters]uintptr
|
||||
stack := sysargs[numOfIntegerRegisters():]
|
||||
var floats [numOfFloats]uintptr
|
||||
var numInts int
|
||||
var numFloats int
|
||||
var numStack int
|
||||
@@ -215,7 +222,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
|
||||
// Windows arm64 uses the same calling convention as macOS and Linux
|
||||
addStack = func(x uintptr) {
|
||||
sysargs[numOfIntegerRegisters()+numStack] = x
|
||||
stack[numStack] = x
|
||||
numStack++
|
||||
}
|
||||
addInt = func(x uintptr) {
|
||||
@@ -248,13 +255,12 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
addFloat = addStack
|
||||
}
|
||||
|
||||
var keepAlive []any
|
||||
var keepAlive []interface{}
|
||||
defer func() {
|
||||
runtime.KeepAlive(keepAlive)
|
||||
runtime.KeepAlive(args)
|
||||
}()
|
||||
|
||||
var arm64_r8 uintptr
|
||||
var syscall syscall15Args
|
||||
if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct {
|
||||
outType := ty.Out(0)
|
||||
if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize {
|
||||
@@ -266,63 +272,53 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
if !isAllFloats || numFields > 4 {
|
||||
val := reflect.New(outType)
|
||||
keepAlive = append(keepAlive, val)
|
||||
arm64_r8 = val.Pointer()
|
||||
syscall.arm64_r8 = val.Pointer()
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, v := range args {
|
||||
if variadic, ok := args[i].Interface().([]any); ok {
|
||||
if i != len(args)-1 {
|
||||
panic("purego: can only expand last parameter")
|
||||
for _, v := range args {
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
ptr := strings.CString(v.String())
|
||||
keepAlive = append(keepAlive, ptr)
|
||||
addInt(uintptr(unsafe.Pointer(ptr)))
|
||||
case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
addInt(uintptr(v.Uint()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
addInt(uintptr(v.Int()))
|
||||
case reflect.Ptr, reflect.UnsafePointer, reflect.Slice:
|
||||
// There is no need to keepAlive this pointer separately because it is kept alive in the args variable
|
||||
addInt(v.Pointer())
|
||||
case reflect.Func:
|
||||
addInt(NewCallback(v.Interface()))
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
addInt(1)
|
||||
} else {
|
||||
addInt(0)
|
||||
}
|
||||
for _, x := range variadic {
|
||||
keepAlive = addValue(reflect.ValueOf(x), keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
|
||||
}
|
||||
continue
|
||||
case reflect.Float32:
|
||||
addFloat(uintptr(math.Float32bits(float32(v.Float()))))
|
||||
case reflect.Float64:
|
||||
addFloat(uintptr(math.Float64bits(v.Float())))
|
||||
case reflect.Struct:
|
||||
keepAlive = addStruct(v, &numInts, &numFloats, &numStack, addInt, addFloat, addStack, keepAlive)
|
||||
default:
|
||||
panic("purego: unsupported kind: " + v.Kind().String())
|
||||
}
|
||||
if runtime.GOARCH == "arm64" && runtime.GOOS == "darwin" &&
|
||||
(numInts >= numOfIntegerRegisters() || numFloats >= numOfFloatRegisters) && v.Kind() != reflect.Struct { // hit the stack
|
||||
fields := make([]reflect.StructField, len(args[i:]))
|
||||
|
||||
for j, val := range args[i:] {
|
||||
if val.Kind() == reflect.String {
|
||||
ptr := strings.CString(v.String())
|
||||
keepAlive = append(keepAlive, ptr)
|
||||
val = reflect.ValueOf(ptr)
|
||||
args[i+j] = val
|
||||
}
|
||||
fields[j] = reflect.StructField{
|
||||
Name: "X" + strconv.Itoa(j),
|
||||
Type: val.Type(),
|
||||
}
|
||||
}
|
||||
structType := reflect.StructOf(fields)
|
||||
structInstance := reflect.New(structType).Elem()
|
||||
for j, val := range args[i:] {
|
||||
structInstance.Field(j).Set(val)
|
||||
}
|
||||
placeRegisters(structInstance, addFloat, addInt)
|
||||
break
|
||||
}
|
||||
keepAlive = addValue(v, keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
|
||||
}
|
||||
|
||||
syscall := thePool.Get().(*syscall15Args)
|
||||
defer thePool.Put(syscall)
|
||||
|
||||
if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
|
||||
// Use the normal arm64 calling convention even on Windows
|
||||
*syscall = syscall15Args{
|
||||
syscall = syscall15Args{
|
||||
cfn,
|
||||
sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5],
|
||||
sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
|
||||
sysargs[12], sysargs[13], sysargs[14],
|
||||
floats[0], floats[1], floats[2], floats[3], floats[4], floats[5], floats[6], floats[7],
|
||||
arm64_r8,
|
||||
syscall.arm64_r8,
|
||||
}
|
||||
runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
|
||||
runtime_cgocall(syscall15XABI0, unsafe.Pointer(&syscall))
|
||||
} else {
|
||||
*syscall = syscall15Args{}
|
||||
// This is a fallback for Windows amd64, 386, and arm. Note this may not support floats
|
||||
syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4],
|
||||
sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
|
||||
@@ -361,54 +357,15 @@ func RegisterFunc(fptr any, cfn uintptr) {
|
||||
// On 32bit platforms syscall.r2 is the upper part of a 64bit return.
|
||||
v.SetFloat(math.Float64frombits(uint64(syscall.f1)))
|
||||
case reflect.Struct:
|
||||
v = getStruct(outType, *syscall)
|
||||
v = getStruct(outType, syscall)
|
||||
default:
|
||||
panic("purego: unsupported return kind: " + outType.Kind().String())
|
||||
}
|
||||
if len(args) > 0 {
|
||||
// reuse args slice instead of allocating one when possible
|
||||
args[0] = v
|
||||
return args[:1]
|
||||
} else {
|
||||
return []reflect.Value{v}
|
||||
}
|
||||
return []reflect.Value{v}
|
||||
})
|
||||
fn.Set(v)
|
||||
}
|
||||
|
||||
func addValue(v reflect.Value, keepAlive []any, addInt func(x uintptr), addFloat func(x uintptr), addStack func(x uintptr), numInts *int, numFloats *int, numStack *int) []any {
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
ptr := strings.CString(v.String())
|
||||
keepAlive = append(keepAlive, ptr)
|
||||
addInt(uintptr(unsafe.Pointer(ptr)))
|
||||
case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
addInt(uintptr(v.Uint()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
addInt(uintptr(v.Int()))
|
||||
case reflect.Ptr, reflect.UnsafePointer, reflect.Slice:
|
||||
// There is no need to keepAlive this pointer separately because it is kept alive in the args variable
|
||||
addInt(v.Pointer())
|
||||
case reflect.Func:
|
||||
addInt(NewCallback(v.Interface()))
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
addInt(1)
|
||||
} else {
|
||||
addInt(0)
|
||||
}
|
||||
case reflect.Float32:
|
||||
addFloat(uintptr(math.Float32bits(float32(v.Float()))))
|
||||
case reflect.Float64:
|
||||
addFloat(uintptr(math.Float64bits(v.Float())))
|
||||
case reflect.Struct:
|
||||
keepAlive = addStruct(v, numInts, numFloats, numStack, addInt, addFloat, addStack, keepAlive)
|
||||
default:
|
||||
panic("purego: unsupported kind: " + v.Kind().String())
|
||||
}
|
||||
return keepAlive
|
||||
}
|
||||
|
||||
// maxRegAllocStructSize is the biggest a struct can be while still fitting in registers.
|
||||
// if it is bigger than this than enough space must be allocated on the heap and then passed into
|
||||
// the function as the first parameter on amd64 or in R8 on arm64.
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/go_runtime.go
generated
vendored
2
vendor/github.com/ebitengine/purego/go_runtime.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd || windows
|
||||
//go:build darwin || freebsd || linux || windows
|
||||
|
||||
package purego
|
||||
|
||||
|
||||
4
vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
generated
vendored
4
vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
generated
vendored
@@ -1,12 +1,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
|
||||
|
||||
//go:build freebsd || linux || netbsd
|
||||
//go:build freebsd || linux
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo !netbsd LDFLAGS: -ldl
|
||||
#cgo LDFLAGS: -ldl
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
4
vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
generated
vendored
4
vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build freebsd || (linux && !(arm64 || amd64)) || netbsd
|
||||
//go:build freebsd || (linux && !(arm64 || amd64))
|
||||
|
||||
package cgo
|
||||
|
||||
@@ -9,7 +9,7 @@ package cgo
|
||||
// because Cgo and assembly files can't be in the same package.
|
||||
|
||||
/*
|
||||
#cgo !netbsd LDFLAGS: -ldl
|
||||
#cgo LDFLAGS: -ldl
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
// Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
|
||||
// This allows code that calls into C to function properly when CGO_ENABLED=0.
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
106
vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go
generated
vendored
106
vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !cgo && (amd64 || arm64)
|
||||
|
||||
package fakecgo
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//go:nosplit
|
||||
func _cgo_sys_thread_start(ts *ThreadStart) {
|
||||
var attr pthread_attr_t
|
||||
var ign, oset sigset_t
|
||||
var p pthread_t
|
||||
var size size_t
|
||||
var err int
|
||||
|
||||
// fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
|
||||
sigfillset(&ign)
|
||||
pthread_sigmask(SIG_SETMASK, &ign, &oset)
|
||||
|
||||
pthread_attr_init(&attr)
|
||||
pthread_attr_getstacksize(&attr, &size)
|
||||
// Leave stacklo=0 and set stackhi=size; mstart will do the rest.
|
||||
ts.g.stackhi = uintptr(size)
|
||||
|
||||
err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &oset, nil)
|
||||
|
||||
if err != 0 {
|
||||
print("fakecgo: pthread_create failed: ")
|
||||
println(err)
|
||||
abort()
|
||||
}
|
||||
}
|
||||
|
||||
// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
|
||||
//
|
||||
//go:linkname x_threadentry_trampoline threadentry_trampoline
|
||||
var x_threadentry_trampoline byte
|
||||
var threadentry_trampolineABI0 = &x_threadentry_trampoline
|
||||
|
||||
//go:nosplit
|
||||
func threadentry(v unsafe.Pointer) unsafe.Pointer {
|
||||
var ss stack_t
|
||||
ts := *(*ThreadStart)(v)
|
||||
free(v)
|
||||
|
||||
// On NetBSD, a new thread inherits the signal stack of the
|
||||
// creating thread. That confuses minit, so we remove that
|
||||
// signal stack here before calling the regular mstart. It's
|
||||
// a bit baroque to remove a signal stack here only to add one
|
||||
// in minit, but it's a simple change that keeps NetBSD
|
||||
// working like other OS's. At this point all signals are
|
||||
// blocked, so there is no race.
|
||||
ss.ss_flags = SS_DISABLE
|
||||
sigaltstack(&ss, nil)
|
||||
|
||||
setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
|
||||
|
||||
// faking funcs in go is a bit a... involved - but the following works :)
|
||||
fn := uintptr(unsafe.Pointer(&ts.fn))
|
||||
(*(*func())(unsafe.Pointer(&fn)))()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// here we will store a pointer to the provided setg func
|
||||
var setg_func uintptr
|
||||
|
||||
//go:nosplit
|
||||
func x_cgo_init(g *G, setg uintptr) {
|
||||
var size size_t
|
||||
var attr *pthread_attr_t
|
||||
|
||||
/* The memory sanitizer distributed with versions of clang
|
||||
before 3.8 has a bug: if you call mmap before malloc, mmap
|
||||
may return an address that is later overwritten by the msan
|
||||
library. Avoid this problem by forcing a call to malloc
|
||||
here, before we ever call malloc.
|
||||
|
||||
This is only required for the memory sanitizer, so it's
|
||||
unfortunate that we always run it. It should be possible
|
||||
to remove this when we no longer care about versions of
|
||||
clang before 3.8. The test for this is
|
||||
misc/cgo/testsanitizers.
|
||||
|
||||
GCC works hard to eliminate a seemingly unnecessary call to
|
||||
malloc, so we actually use the memory we allocate. */
|
||||
|
||||
setg_func = setg
|
||||
attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
|
||||
if attr == nil {
|
||||
println("fakecgo: malloc failed")
|
||||
abort()
|
||||
}
|
||||
pthread_attr_init(attr)
|
||||
pthread_attr_getstacksize(attr, &size)
|
||||
// runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
|
||||
// but this should be OK since we are taking the address of the first variable in this function.
|
||||
g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
|
||||
pthread_attr_destroy(attr)
|
||||
free(unsafe.Pointer(attr))
|
||||
}
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
// The runtime package contains an uninitialized definition
|
||||
// for runtime·iscgo. Override it to tell the runtime we're here.
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
generated
vendored
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
generated
vendored
@@ -20,7 +20,3 @@ var (
|
||||
PTHREAD_COND_INITIALIZER = pthread_cond_t{sig: 0x3CB0B1BB}
|
||||
PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{sig: 0x32AAABA7}
|
||||
)
|
||||
|
||||
type stack_t struct {
|
||||
/* not implemented */
|
||||
}
|
||||
|
||||
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
generated
vendored
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
generated
vendored
@@ -14,7 +14,3 @@ var (
|
||||
PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
|
||||
PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
|
||||
)
|
||||
|
||||
type stack_t struct {
|
||||
/* not implemented */
|
||||
}
|
||||
|
||||
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
generated
vendored
4
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
generated
vendored
@@ -14,7 +14,3 @@ var (
|
||||
PTHREAD_COND_INITIALIZER = pthread_cond_t{}
|
||||
PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{}
|
||||
)
|
||||
|
||||
type stack_t struct {
|
||||
/* not implemented */
|
||||
}
|
||||
|
||||
26
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go
generated
vendored
26
vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo
|
||||
|
||||
package fakecgo
|
||||
|
||||
type (
|
||||
pthread_cond_t uintptr
|
||||
pthread_mutex_t uintptr
|
||||
)
|
||||
|
||||
var (
|
||||
PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
|
||||
PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
|
||||
)
|
||||
|
||||
// Source: https://github.com/NetBSD/src/blob/613e27c65223fd2283b6ed679da1197e12f50e27/sys/compat/linux/arch/m68k/linux_signal.h#L133
|
||||
type stack_t struct {
|
||||
ss_sp uintptr
|
||||
ss_flags int32
|
||||
ss_size uintptr
|
||||
}
|
||||
|
||||
// Source: https://github.com/NetBSD/src/blob/613e27c65223fd2283b6ed679da1197e12f50e27/sys/sys/signal.h#L261
|
||||
const SS_DISABLE = 0x004
|
||||
23
vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go
generated
vendored
23
vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build netbsd
|
||||
|
||||
package fakecgo
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
// Supply environ and __progname, because we don't
|
||||
// link against the standard NetBSD crt0.o and the
|
||||
// libc dynamic library needs them.
|
||||
|
||||
//go:linkname _environ environ
|
||||
//go:linkname _progname __progname
|
||||
//go:linkname ___ps_strings __ps_strings
|
||||
|
||||
var (
|
||||
_environ uintptr
|
||||
_progname uintptr
|
||||
___ps_strings uintptr
|
||||
)
|
||||
2
vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
generated
vendored
2
vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
|
||||
11
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
generated
vendored
11
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go
generated
vendored
@@ -3,7 +3,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package fakecgo
|
||||
|
||||
@@ -55,11 +55,6 @@ func abort() {
|
||||
call5(abortABI0, 0, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sigaltstack(ss *stack_t, old_ss *stack_t) int32 {
|
||||
return int32(call5(sigaltstackABI0, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(old_ss)), 0, 0, 0))
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func pthread_attr_init(attr *pthread_attr_t) int32 {
|
||||
return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
|
||||
@@ -153,10 +148,6 @@ var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
|
||||
var _abort uint8
|
||||
var abortABI0 = uintptr(unsafe.Pointer(&_abort))
|
||||
|
||||
//go:linkname _sigaltstack _sigaltstack
|
||||
var _sigaltstack uint8
|
||||
var sigaltstackABI0 = uintptr(unsafe.Pointer(&_sigaltstack))
|
||||
|
||||
//go:linkname _pthread_attr_init _pthread_attr_init
|
||||
var _pthread_attr_init uint8
|
||||
var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
|
||||
|
||||
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go
generated
vendored
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_darwin.go
generated
vendored
@@ -14,7 +14,6 @@ package fakecgo
|
||||
//go:cgo_import_dynamic purego_sigfillset sigfillset "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_nanosleep nanosleep "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_abort abort "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_sigaltstack sigaltstack "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"
|
||||
//go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go
generated
vendored
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go
generated
vendored
@@ -14,7 +14,6 @@ package fakecgo
|
||||
//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_abort abort "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_sigaltstack sigaltstack "libc.so.7"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
|
||||
|
||||
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go
generated
vendored
1
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_linux.go
generated
vendored
@@ -14,7 +14,6 @@ package fakecgo
|
||||
//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6"
|
||||
//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6"
|
||||
//go:cgo_import_dynamic purego_abort abort "libc.so.6"
|
||||
//go:cgo_import_dynamic purego_sigaltstack sigaltstack "libc.so.6"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0"
|
||||
//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
|
||||
//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
|
||||
|
||||
30
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_netbsd.go
generated
vendored
30
vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_netbsd.go
generated
vendored
@@ -1,30 +0,0 @@
|
||||
// Code generated by 'go generate' with gen.go. DO NOT EDIT.
|
||||
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo
|
||||
|
||||
package fakecgo
|
||||
|
||||
//go:cgo_import_dynamic purego_malloc malloc "libc.so"
|
||||
//go:cgo_import_dynamic purego_free free "libc.so"
|
||||
//go:cgo_import_dynamic purego_setenv setenv "libc.so"
|
||||
//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so"
|
||||
//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so"
|
||||
//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so"
|
||||
//go:cgo_import_dynamic purego_abort abort "libc.so"
|
||||
//go:cgo_import_dynamic purego_sigaltstack sigaltstack "libc.so"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
|
||||
//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
|
||||
6
vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s
generated
vendored
6
vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s
generated
vendored
@@ -3,7 +3,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
@@ -37,10 +37,6 @@ TEXT _abort(SB), NOSPLIT|NOFRAME, $0-0
|
||||
JMP purego_abort(SB)
|
||||
RET
|
||||
|
||||
TEXT _sigaltstack(SB), NOSPLIT|NOFRAME, $0-0
|
||||
JMP purego_sigaltstack(SB)
|
||||
RET
|
||||
|
||||
TEXT _pthread_attr_init(SB), NOSPLIT|NOFRAME, $0-0
|
||||
JMP purego_pthread_attr_init(SB)
|
||||
RET
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/nocgo.go
generated
vendored
2
vendor/github.com/ebitengine/purego/nocgo.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build !cgo && (darwin || freebsd || linux || netbsd)
|
||||
//go:build !cgo && (darwin || freebsd || linux)
|
||||
|
||||
package purego
|
||||
|
||||
|
||||
8
vendor/github.com/ebitengine/purego/struct_amd64.go
generated
vendored
8
vendor/github.com/ebitengine/purego/struct_amd64.go
generated
vendored
@@ -85,7 +85,7 @@ const (
|
||||
_MEMORY = 0b1111
|
||||
)
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
if v.Type().Size() == 0 {
|
||||
return keepAlive
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func postMerger(t reflect.Type) (passInMemory bool) {
|
||||
if t.Size() <= 2*8 {
|
||||
return false
|
||||
}
|
||||
return true // Go does not have an SSE/SSEUP type so this is always true
|
||||
return true // Go does not have an SSE/SEEUP type so this is always true
|
||||
}
|
||||
|
||||
func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) {
|
||||
@@ -258,7 +258,3 @@ func placeStack(v reflect.Value, addStack func(uintptr)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
|
||||
panic("purego: not needed on amd64")
|
||||
}
|
||||
|
||||
22
vendor/github.com/ebitengine/purego/struct_arm64.go
generated
vendored
22
vendor/github.com/ebitengine/purego/struct_arm64.go
generated
vendored
@@ -65,7 +65,7 @@ const (
|
||||
_INT = 0b11
|
||||
)
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
if v.Type().Size() == 0 {
|
||||
return keepAlive
|
||||
}
|
||||
@@ -73,8 +73,8 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
|
||||
if hva, hfa, size := isHVA(v.Type()), isHFA(v.Type()), v.Type().Size(); hva || hfa || size <= 16 {
|
||||
// if this doesn't fit entirely in registers then
|
||||
// each element goes onto the stack
|
||||
if hfa && *numFloats+v.NumField() > numOfFloatRegisters {
|
||||
*numFloats = numOfFloatRegisters
|
||||
if hfa && *numFloats+v.NumField() > numOfFloats {
|
||||
*numFloats = numOfFloats
|
||||
} else if hva && *numInts+v.NumField() > numOfIntegerRegisters() {
|
||||
*numInts = numOfIntegerRegisters()
|
||||
}
|
||||
@@ -107,8 +107,6 @@ func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr
|
||||
} else {
|
||||
f = v.Index(k)
|
||||
}
|
||||
align := byte(f.Type().Align()*8 - 1)
|
||||
shift = (shift + align) &^ align
|
||||
if shift >= 64 {
|
||||
shift = 0
|
||||
flushed = true
|
||||
@@ -139,11 +137,10 @@ func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr
|
||||
val |= f.Uint() << shift
|
||||
shift += 32
|
||||
class |= _INT
|
||||
case reflect.Uint64, reflect.Uint, reflect.Uintptr:
|
||||
case reflect.Uint64:
|
||||
addInt(uintptr(f.Uint()))
|
||||
shift = 0
|
||||
flushed = true
|
||||
class = _NO_CLASS
|
||||
case reflect.Int8:
|
||||
val |= uint64(f.Int()&0xFF) << shift
|
||||
shift += 8
|
||||
@@ -156,11 +153,10 @@ func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr
|
||||
val |= uint64(f.Int()&0xFFFF_FFFF) << shift
|
||||
shift += 32
|
||||
class |= _INT
|
||||
case reflect.Int64, reflect.Int:
|
||||
case reflect.Int64:
|
||||
addInt(uintptr(f.Int()))
|
||||
shift = 0
|
||||
flushed = true
|
||||
class = _NO_CLASS
|
||||
case reflect.Float32:
|
||||
if class == _FLOAT {
|
||||
addFloat(uintptr(val))
|
||||
@@ -174,12 +170,6 @@ func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr
|
||||
addFloat(uintptr(math.Float64bits(float64(f.Float()))))
|
||||
shift = 0
|
||||
flushed = true
|
||||
class = _NO_CLASS
|
||||
case reflect.Ptr:
|
||||
addInt(f.Pointer())
|
||||
shift = 0
|
||||
flushed = true
|
||||
class = _NO_CLASS
|
||||
case reflect.Array:
|
||||
place(f)
|
||||
default:
|
||||
@@ -197,7 +187,7 @@ func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr
|
||||
}
|
||||
}
|
||||
|
||||
func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
|
||||
func placeStack(v reflect.Value, keepAlive []interface{}, addInt func(uintptr)) []interface{} {
|
||||
// Struct is too big to be placed in registers.
|
||||
// Copy to heap and place the pointer in register
|
||||
ptrStruct := reflect.New(v.Type())
|
||||
|
||||
6
vendor/github.com/ebitengine/purego/struct_other.go
generated
vendored
6
vendor/github.com/ebitengine/purego/struct_other.go
generated
vendored
@@ -7,14 +7,10 @@ package purego
|
||||
|
||||
import "reflect"
|
||||
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
|
||||
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} {
|
||||
panic("purego: struct arguments are not supported")
|
||||
}
|
||||
|
||||
func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
|
||||
panic("purego: struct returns are not supported")
|
||||
}
|
||||
|
||||
func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
|
||||
panic("purego: not needed on other platforms")
|
||||
}
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/sys_amd64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/sys_amd64.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
#include "textflag.h"
|
||||
#include "abi_amd64.h"
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/sys_arm64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/sys_arm64.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd || windows
|
||||
//go:build darwin || freebsd || linux || windows
|
||||
|
||||
#include "textflag.h"
|
||||
#include "go_asm.h"
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/sys_unix_arm64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/sys_unix_arm64.s
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
#include "textflag.h"
|
||||
#include "go_asm.h"
|
||||
|
||||
9
vendor/github.com/ebitengine/purego/syscall.go
generated
vendored
9
vendor/github.com/ebitengine/purego/syscall.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd || windows
|
||||
//go:build darwin || freebsd || linux || windows
|
||||
|
||||
package purego
|
||||
|
||||
@@ -13,8 +13,8 @@ package purego
|
||||
type CDecl struct{}
|
||||
|
||||
const (
|
||||
maxArgs = 15
|
||||
numOfFloatRegisters = 8 // arm64 and amd64 both have 8 float registers
|
||||
maxArgs = 15
|
||||
numOfFloats = 8 // arm64 and amd64 both have 8 float registers
|
||||
)
|
||||
|
||||
type syscall15Args struct {
|
||||
@@ -27,9 +27,6 @@ type syscall15Args struct {
|
||||
// There is an internal maximum number of arguments that SyscallN can take. It panics
|
||||
// when the maximum is exceeded. It returns the result and the libc error code if there is one.
|
||||
//
|
||||
// In order to call this function properly make sure to follow all the rules specified in [unsafe.Pointer]
|
||||
// especially point 4.
|
||||
//
|
||||
// NOTE: SyscallN does not properly call functions that have both integer and float parameters.
|
||||
// See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
|
||||
// for an explanation of why that is.
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
generated
vendored
2
vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
generated
vendored
@@ -16,6 +16,6 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
|
||||
return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
|
||||
}
|
||||
|
||||
func NewCallback(_ any) uintptr {
|
||||
func NewCallback(_ interface{}) uintptr {
|
||||
panic("purego: NewCallback on Linux is only supported on amd64/arm64")
|
||||
}
|
||||
|
||||
12
vendor/github.com/ebitengine/purego/syscall_sysv.go
generated
vendored
12
vendor/github.com/ebitengine/purego/syscall_sysv.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
||||
|
||||
//go:build darwin || freebsd || (linux && (amd64 || arm64)) || netbsd
|
||||
//go:build darwin || freebsd || (linux && (amd64 || arm64))
|
||||
|
||||
package purego
|
||||
|
||||
@@ -31,7 +31,7 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
|
||||
// of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated
|
||||
// for these callbacks is never released. At least 2000 callbacks can always be created. Although this function
|
||||
// provides similar functionality to windows.NewCallback it is distinct.
|
||||
func NewCallback(fn any) uintptr {
|
||||
func NewCallback(fn interface{}) uintptr {
|
||||
ty := reflect.TypeOf(fn)
|
||||
for i := 0; i < ty.NumIn(); i++ {
|
||||
in := ty.In(i)
|
||||
@@ -71,7 +71,7 @@ type callbackArgs struct {
|
||||
result uintptr
|
||||
}
|
||||
|
||||
func compileCallback(fn any) uintptr {
|
||||
func compileCallback(fn interface{}) uintptr {
|
||||
val := reflect.ValueOf(fn)
|
||||
if val.Kind() != reflect.Func {
|
||||
panic("purego: the type must be a function but was not")
|
||||
@@ -146,12 +146,12 @@ func callbackWrap(a *callbackArgs) {
|
||||
var intsN int // intsN represents the number of integer arguments processed
|
||||
// stack points to the index into frame of the current stack element.
|
||||
// The stack begins after the float and integer registers.
|
||||
stack := numOfIntegerRegisters() + numOfFloatRegisters
|
||||
stack := numOfIntegerRegisters() + numOfFloats
|
||||
for i := range args {
|
||||
var pos int
|
||||
switch fnType.In(i).Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if floatsN >= numOfFloatRegisters {
|
||||
if floatsN >= numOfFloats {
|
||||
pos = stack
|
||||
stack++
|
||||
} else {
|
||||
@@ -169,7 +169,7 @@ func callbackWrap(a *callbackArgs) {
|
||||
stack++
|
||||
} else {
|
||||
// the integers begin after the floats in frame
|
||||
pos = intsN + numOfFloatRegisters
|
||||
pos = intsN + numOfFloats
|
||||
}
|
||||
intsN++
|
||||
}
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/syscall_windows.go
generated
vendored
2
vendor/github.com/ebitengine/purego/syscall_windows.go
generated
vendored
@@ -22,7 +22,7 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
|
||||
// allocated for these callbacks is never released. Between NewCallback and NewCallbackCDecl, at least 1024
|
||||
// callbacks can always be created. Although this function is similiar to the darwin version it may act
|
||||
// differently.
|
||||
func NewCallback(fn any) uintptr {
|
||||
func NewCallback(fn interface{}) uintptr {
|
||||
isCDecl := false
|
||||
ty := reflect.TypeOf(fn)
|
||||
for i := 0; i < ty.NumIn(); i++ {
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/zcallback_amd64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/zcallback_amd64.s
generated
vendored
@@ -1,6 +1,6 @@
|
||||
// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
// runtime·callbackasm is called by external code to
|
||||
// execute Go implemented callback function. It is not
|
||||
|
||||
2
vendor/github.com/ebitengine/purego/zcallback_arm64.s
generated
vendored
2
vendor/github.com/ebitengine/purego/zcallback_arm64.s
generated
vendored
@@ -1,6 +1,6 @@
|
||||
// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
//go:build darwin || freebsd || linux || netbsd
|
||||
//go:build darwin || freebsd || linux
|
||||
|
||||
// External code calls into callbackasm at an offset corresponding
|
||||
// to the callback index. Callbackasm is a table of MOV and B instructions.
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -673,7 +673,7 @@ github.com/dustin/go-humanize
|
||||
# github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4
|
||||
## explicit; go 1.20
|
||||
github.com/eapache/queue/v2
|
||||
# github.com/ebitengine/purego v0.9.0-alpha.3.0.20250507171635-5047c08daa38
|
||||
# github.com/ebitengine/purego v0.8.3
|
||||
## explicit; go 1.18
|
||||
github.com/ebitengine/purego
|
||||
github.com/ebitengine/purego/internal/cgo
|
||||
|
||||
Reference in New Issue
Block a user