-
Notifications
You must be signed in to change notification settings - Fork 11
/
dial_posix.go
102 lines (89 loc) · 3.39 KB
/
dial_posix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !windows
package ipc
import (
"context"
"os"
"os/exec"
"strings"
"google.golang.org/grpc"
)
const lsofOutputPrefix = "n/"
// DialContext connects to the serverAddress for grpc. Returns immediately and will make the connection lazily when needed.
// This is the recommended approach to dialing from the grpc documentation (https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md)
func DialContext(ctx context.Context, serverAddr string) (*grpc.ClientConn, error) {
return grpc.DialContext(ctx, serverAddr, grpc.WithInsecure(), grpc.WithMaxMsgSize(GrpcMaxMsgSize))
}
// DialContextWithBlock connects to the serverAddress for grpc, but waits until the connection is made (via WithBlock) until returning.
// This is NOT the recommended approach to dialing, but is needed for bootstrap which relies on WithBlock as a check that reproxy has started successfully.
// Also needed for reproxy connecting to the depsscannerservice.
// TODO(b/290804932): Remove the dependence on WithBlock as a startup check.
func DialContextWithBlock(ctx context.Context, serverAddr string) (*grpc.ClientConn, error) {
return grpc.DialContext(ctx, serverAddr, grpc.WithBlock(), grpc.WithInsecure(), grpc.WithMaxMsgSize(GrpcMaxMsgSize))
}
// GetAllReproxySockets returns all unix sockets where an reproxy service is listening.
func GetAllReproxySockets(ctx context.Context) ([]string, error) {
lsofOutput, err := execLsof("-U", "-c", "reproxy", "-a", "-Fn")
if err != nil {
// Lsof completes with exit code 1 when there is no output
if err.(*exec.ExitError).ExitCode() == 1 {
return nil, nil
}
return nil, err
}
return parseSockets(lsofOutput), nil
}
// Exists returns true if there is a UDS socket at the given address. If
// it's a TCP address, it will just continue and try connecting the normal
// way.
func Exists(address string) bool {
if strings.HasPrefix(address, "unix://") {
address := strings.TrimPrefix(address, "unix://")
if _, err := os.Stat(address); err != nil {
// An error on stat indicates it doesn't exist.
return false
}
return true
}
return true
}
func parseSockets(lsofOutput string) []string {
var sockets []string
seenSockets := map[string]bool{}
for _, line := range strings.Split(lsofOutput, "\n") {
if socket := parseSocketLine(line); socket != "" && !seenSockets[socket] {
sockets = append(sockets, "unix://"+socket)
seenSockets[socket] = true
}
}
return sockets
}
func parseSocketLine(line string) string {
for _, s := range strings.Split(line, " ") {
if strings.HasPrefix(s, lsofOutputPrefix) {
return strings.TrimLeft(s, "n")
}
}
return ""
}
func execLsof(args ...string) (string, error) {
command := "lsof"
args = append([]string{"-w"}, args...)
output, err := exec.Command(command, args...).Output()
if err != nil {
return "", err
}
return string(output), nil
}