goadb/wire/scanner.go

126 lines
2.9 KiB
Go
Raw Normal View History

package wire
import (
"io"
"io/ioutil"
"strconv"
2015-07-12 06:18:58 +00:00
"github.com/zach-klippenstein/goadb/util"
)
// StatusCodes are returned by the server. If the code indicates failure, the
// next message will be the error.
type StatusCode string
const (
StatusSuccess StatusCode = "OKAY"
StatusFailure = "FAIL"
StatusNone = ""
)
func (status StatusCode) IsSuccess() bool {
return status == StatusSuccess
}
/*
Scanner reads tokens from a server.
See Conn for more details.
*/
type Scanner interface {
ReadStatus() (StatusCode, error)
ReadMessage() ([]byte, error)
ReadUntilEof() ([]byte, error)
NewSyncScanner() SyncScanner
Close() error
}
type realScanner struct {
reader io.ReadCloser
}
func NewScanner(r io.ReadCloser) Scanner {
return &realScanner{r}
}
func ReadMessageString(s Scanner) (string, error) {
msg, err := s.ReadMessage()
if err != nil {
return string(msg), err
}
return string(msg), nil
}
func (s *realScanner) ReadStatus() (StatusCode, error) {
status := make([]byte, 4)
n, err := io.ReadFull(s.reader, status)
2015-07-12 06:18:58 +00:00
if err != nil && err != io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return "", util.WrapErrorf(err, util.NetworkError, "error reading status")
} else if err == io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return StatusCode(status), errIncompleteMessage("status", n, 4)
}
return StatusCode(status), nil
}
func (s *realScanner) ReadMessage() ([]byte, error) {
2015-07-12 06:18:58 +00:00
var err error
length, err := s.readLength()
if err != nil {
2015-07-12 06:18:58 +00:00
return nil, util.WrapErrorf(err, util.NetworkError, "error reading message length")
}
data := make([]byte, length)
n, err := io.ReadFull(s.reader, data)
2015-07-12 06:18:58 +00:00
if err != nil && err != io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return data, util.WrapErrorf(err, util.NetworkError, "error reading message data")
} else if err == io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return data, errIncompleteMessage("message data", n, length)
}
return data, nil
}
func (s *realScanner) ReadUntilEof() ([]byte, error) {
2015-07-12 06:18:58 +00:00
data, err := ioutil.ReadAll(s.reader)
if err != nil {
return nil, util.WrapErrorf(err, util.NetworkError, "error reading until EOF")
}
return data, nil
}
func (s *realScanner) NewSyncScanner() SyncScanner {
return NewSyncScanner(s.reader)
}
func (s *realScanner) Close() error {
2015-07-12 06:18:58 +00:00
return util.WrapErrorf(s.reader.Close(), util.NetworkError, "error closing scanner")
}
func (s *realScanner) readLength() (int, error) {
lengthHex := make([]byte, 4)
n, err := io.ReadFull(s.reader, lengthHex)
if err != nil && err != io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return 0, util.WrapErrorf(err, util.NetworkError, "error reading length")
} else if err == io.ErrUnexpectedEOF {
2015-07-12 06:18:58 +00:00
return 0, errIncompleteMessage("length", n, 4)
}
length, err := strconv.ParseInt(string(lengthHex), 16, 64)
if err != nil {
2015-07-12 06:18:58 +00:00
return 0, util.WrapErrorf(err, util.NetworkError, "could not parse hex length %v", lengthHex)
}
// Clip the length to 255, as per the Google implementation.
if length > MaxMessageLength {
length = MaxMessageLength
}
return int(length), nil
}
var _ Scanner = &realScanner{}