forked from zach-klippenstein/goadb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
138 lines (120 loc) · 3.29 KB
/
server.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package adb
import (
"bytes"
"net"
"os/exec"
"strconv"
"github.com/pkg/errors"
)
const (
// DefaultExecutableName is the name of the ADB-Server on the Path
DefaultExecutableName = "adb"
// DefaultPort is the default port for the ADB-Server to listens on.
DefaultPort = 5037
// use statusOK
statusSuccess string = "OKAY"
// use statusFail
statusFailure string = "FAIL"
)
// dialer used to connect to the adb server.
// Default is the regular Dialer form net.
// This exist only for easier mocking.
var dial = func(address string) (net.Conn, error) { return net.Dial("tcp", address) }
// Server holds information needed to connect to a server repeatedly.
// Use New or NewDefault to create one.
type Server struct {
path string
address string
}
// NewDefault creates a new Adb client that uses the default ServerConfig.
func NewDefault() (*Server, error) {
return New(DefaultExecutableName, "localhost", DefaultPort)
}
// New creates a new Server.
func New(path, host string, port int) (*Server, error) {
// maybe add path search for adb?
s := &Server{
path: path,
address: host + ":" + strconv.Itoa(port),
}
err := start(s)
if err != nil {
return nil, err
}
return s, nil
}
func start(s *Server) error {
out, err := exec.Command(s.path, "start-server").CombinedOutput()
return errors.WithMessagef(err, "error starting server. Output:\n%s", out)
}
// requestResponseBytes sends msg to server and returns the response.
// The connection is closed. It prepends "host:" to the message.
// The connection times out after 10 seconds.
func (s *Server) requestResponseBytes(msg string) ([]byte, error) {
return requestResponseBytes(s.address, "host:"+msg)
}
// send sends msg to server reads status then closes the connection.
// prepends 'host:'
func (s *Server) send(msg string) error {
return send(s.address, "host:"+msg)
}
// Version asks the adb server for its internal version number.
// TODO(jmh): Check server version format
func (s *Server) Version() (int, error) {
b, err := s.requestResponseBytes("version")
if err != nil {
return 0, err
}
v, _ := strconv.ParseInt(string(b), 16, 32)
return int(v), nil
}
// Kill tells the server to quit immediately.
func (s *Server) Kill() error {
return s.send("kill")
}
// ListDevices returns the list of connected devices.
func (s *Server) ListDevices() ([]DeviceInfo, error) {
b, err := s.requestResponseBytes("devices-l")
if err != nil {
return nil, err
}
return parseDeviceList(bytes.NewBuffer(b), parseDeviceLong)
}
// ListDeviceSerials returns the serial numbers of all attached devices.
func (s *Server) ListDeviceSerials() ([]string, error) {
b, err := s.requestResponseBytes("devices")
if err != nil {
return nil, err
}
devices, err := parseDeviceList(bytes.NewBuffer(b), parseDeviceShort)
if err != nil {
return nil, err
}
serials := make([]string, len(devices))
for i, dev := range devices {
serials[i] = dev.Serial
}
return serials, nil
}
// Device takes a devices serial number and returns it.
// Returns nil on error.
func (s *Server) Device(serial string) *Device {
ds, err := s.ListDeviceSerials()
if err != nil {
return nil
}
found := false
for _, s := range ds {
if s == serial {
found = true
break
}
}
if !found {
return nil
}
return &Device{
server: &(*s), // copy server
serial: serial,
}
}