1
2
3
4
19
20 package util
21
22 import (
23 "context"
24 "fmt"
25 "net"
26 "net/url"
27 "path/filepath"
28 "strings"
29 "syscall"
30 "time"
31
32 "github.com/Microsoft/go-winio"
33 )
34
35 const (
36 tcpProtocol = "tcp"
37 npipeProtocol = "npipe"
38 )
39
40
41 func CreateListener(endpoint string) (net.Listener, error) {
42 protocol, addr, err := parseEndpoint(endpoint)
43 if err != nil {
44 return nil, err
45 }
46
47 switch protocol {
48 case tcpProtocol:
49 return net.Listen(tcpProtocol, addr)
50
51 case npipeProtocol:
52 return winio.ListenPipe(addr, nil)
53
54 default:
55 return nil, fmt.Errorf("only support tcp and npipe endpoint")
56 }
57 }
58
59
60 func GetAddressAndDialer(endpoint string) (string, func(ctx context.Context, addr string) (net.Conn, error), error) {
61 protocol, addr, err := parseEndpoint(endpoint)
62 if err != nil {
63 return "", nil, err
64 }
65
66 if protocol == tcpProtocol {
67 return addr, tcpDial, nil
68 }
69
70 if protocol == npipeProtocol {
71 return addr, npipeDial, nil
72 }
73
74 return "", nil, fmt.Errorf("only support tcp and npipe endpoint")
75 }
76
77 func tcpDial(ctx context.Context, addr string) (net.Conn, error) {
78 return (&net.Dialer{}).DialContext(ctx, tcpProtocol, addr)
79 }
80
81 func npipeDial(ctx context.Context, addr string) (net.Conn, error) {
82 return winio.DialPipeContext(ctx, addr)
83 }
84
85 func parseEndpoint(endpoint string) (string, string, error) {
86
87 endpoint = strings.Replace(endpoint, "\\", "/", -1)
88 u, err := url.Parse(endpoint)
89 if err != nil {
90 return "", "", err
91 }
92
93 if u.Scheme == "tcp" {
94 return "tcp", u.Host, nil
95 } else if u.Scheme == "npipe" {
96 if strings.HasPrefix(u.Path, "//./pipe") {
97 return "npipe", u.Path, nil
98 }
99
100
101 host := u.Host
102 if host == "" {
103 host = "."
104 }
105 return "npipe", fmt.Sprintf("//%s%s", host, u.Path), nil
106 } else if u.Scheme == "" {
107 return "", "", fmt.Errorf("Using %q as endpoint is deprecated, please consider using full url format", endpoint)
108 } else {
109 return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme)
110 }
111 }
112
113
114 func LocalEndpoint(path, file string) (string, error) {
115
116
117
118 podResourcesDir := filepath.Base(filepath.Dir(filepath.Join(path, file)))
119 if podResourcesDir == "" {
120
121
122 return "", fmt.Errorf("cannot infer the podresources directory from path %q", path)
123 }
124
125
126
127
128
129
130 serverPart := `\\.`
131 pipePart := "pipe"
132 pipeName := "kubelet-" + podResourcesDir
133 return npipeProtocol + "://" + filepath.Join(serverPart, pipePart, pipeName), nil
134 }
135
136 var tickCount = syscall.NewLazyDLL("kernel32.dll").NewProc("GetTickCount64")
137
138
139 func GetBootTime() (time.Time, error) {
140 currentTime := time.Now()
141 output, _, err := tickCount.Call()
142 if errno, ok := err.(syscall.Errno); !ok || errno != 0 {
143 return time.Time{}, err
144 }
145 return currentTime.Add(-time.Duration(output) * time.Millisecond).Truncate(time.Second), nil
146 }
147
148
149
150 func NormalizePath(path string) string {
151 path = strings.ReplaceAll(path, "/", "\\")
152 if strings.HasPrefix(path, "\\") {
153 path = "c:" + path
154 }
155 return path
156 }
157
View as plain text