cb7e06bdb9
All sync status reads now also check for failure status, using the same logic as the normal Scanner (the only difference being that for normal scanners, length is encoded as a hex string, but for sync scanners it's in binary little-endian).
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package wire
|
|
|
|
import "github.com/zach-klippenstein/goadb/util"
|
|
|
|
const (
|
|
// The official implementation of adb imposes an undocumented 255-byte limit
|
|
// on messages.
|
|
MaxMessageLength = 255
|
|
)
|
|
|
|
/*
|
|
Conn is a normal connection to an adb server.
|
|
|
|
For most cases, usage looks something like:
|
|
conn := wire.Dial()
|
|
conn.SendMessage(data)
|
|
conn.ReadStatus() == StatusSuccess || StatusFailure
|
|
conn.ReadMessage()
|
|
conn.Close()
|
|
|
|
For some messages, the server will return more than one message (but still a single
|
|
status). Generally, after calling ReadStatus once, you should call ReadMessage until
|
|
it returns an io.EOF error. Note: the protocol docs seem to suggest that connections will be
|
|
kept open for multiple commands, but this is not the case. The official client closes
|
|
a connection immediately after its read the response, in most cases. The docs might be
|
|
referring to the connection between the adb server and the device, but I haven't confirmed
|
|
that.
|
|
|
|
For most commands, the server will close the connection after sending the response.
|
|
You should still always call Close() when you're done with the connection.
|
|
*/
|
|
type Conn struct {
|
|
Scanner
|
|
Sender
|
|
}
|
|
|
|
func NewConn(scanner Scanner, sender Sender) *Conn {
|
|
return &Conn{scanner, sender}
|
|
}
|
|
|
|
// NewSyncConn returns connection that can operate in sync mode.
|
|
// The connection must already have been switched (by sending the sync command
|
|
// to a specific device), or the return connection will return an error.
|
|
func (c *Conn) NewSyncConn() *SyncConn {
|
|
return &SyncConn{
|
|
SyncScanner: c.Scanner.NewSyncScanner(),
|
|
SyncSender: c.Sender.NewSyncSender(),
|
|
}
|
|
}
|
|
|
|
// RoundTripSingleResponse sends a message to the server, and reads a single
|
|
// message response. If the reponse has a failure status code, returns it as an error.
|
|
func (conn *Conn) RoundTripSingleResponse(req []byte) (resp []byte, err error) {
|
|
if err = conn.SendMessage(req); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if _, err = conn.ReadStatus(string(req)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return conn.ReadMessage()
|
|
}
|
|
|
|
func (conn *Conn) Close() error {
|
|
errs := struct {
|
|
SenderErr error
|
|
ScannerErr error
|
|
}{
|
|
SenderErr: conn.Sender.Close(),
|
|
ScannerErr: conn.Scanner.Close(),
|
|
}
|
|
|
|
if errs.ScannerErr != nil || errs.SenderErr != nil {
|
|
return &util.Err{
|
|
Code: util.NetworkError,
|
|
Message: "error closing connection",
|
|
Details: errs,
|
|
}
|
|
}
|
|
return nil
|
|
}
|