summaryrefslogtreecommitdiff
path: root/vendor/github.com/dtylman/scp/msg.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dtylman/scp/msg.go')
-rw-r--r--vendor/github.com/dtylman/scp/msg.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/github.com/dtylman/scp/msg.go b/vendor/github.com/dtylman/scp/msg.go
new file mode 100644
index 000000000..6dfc53535
--- /dev/null
+++ b/vendor/github.com/dtylman/scp/msg.go
@@ -0,0 +1,121 @@
+package scp
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strconv"
+ "strings"
+)
+
+const (
+ //CopyMessage Copy Message Opcode
+ CopyMessage = 'C'
+ //ErrorMessage Error OpCode
+ ErrorMessage = 0x1
+ //WarnMessage Warning Opcode
+ WarnMessage = 0x2
+)
+
+//Message is scp control message
+type Message struct {
+ Type byte
+ Error error
+ Mode string
+ Size int64
+ FileName string
+}
+
+func (m *Message) readByte(reader io.Reader) (byte, error) {
+ buff := make([]byte, 1)
+ _, err := io.ReadFull(reader, buff)
+ if err != nil {
+ return 0, err
+ }
+ return buff[0], nil
+
+}
+
+func (m *Message) readOpCode(reader io.Reader) error {
+ var err error
+ m.Type, err = m.readByte(reader)
+ return err
+}
+
+//ReadError reads an error message
+func (m *Message) ReadError(reader io.Reader) error {
+ msg, err := ioutil.ReadAll(reader)
+ if err != nil {
+ return err
+ }
+ m.Error = errors.New(strings.TrimSpace(string(msg)))
+ return nil
+}
+
+func (m *Message) readLine(reader io.Reader) (string, error) {
+ line := ""
+ b, err := m.readByte(reader)
+ if err != nil {
+ return "", err
+ }
+ for b != 10 {
+ line += string(b)
+ b, err = m.readByte(reader)
+ if err != nil {
+ return "", err
+ }
+ }
+ return line, nil
+}
+
+func (m *Message) readCopy(reader io.Reader) error {
+ line, err := m.readLine(reader)
+ if err != nil {
+ return err
+ }
+ parts := strings.Split(line, " ")
+ if len(parts) < 2 {
+ return errors.New("Invalid copy line: " + line)
+ }
+ m.Mode = parts[0]
+ m.Size, err = strconv.ParseInt(parts[1], 10, 0)
+ if err != nil {
+ return err
+ }
+ m.FileName = parts[2]
+ return nil
+}
+
+//ReadFrom reads message from reader
+func (m *Message) ReadFrom(reader io.Reader) (int64, error) {
+ err := m.readOpCode(reader)
+ if err != nil {
+ return 0, err
+ }
+ switch m.Type {
+ case CopyMessage:
+ err = m.readCopy(reader)
+ if err != nil {
+ return 0, err
+ }
+ case ErrorMessage, WarnMessage:
+ err = m.ReadError(reader)
+ if err != nil {
+ return 0, err
+ }
+ default:
+ return 0, fmt.Errorf("Unsupported opcode: %v", m.Type)
+ }
+ return m.Size, nil
+}
+
+//NewMessageFromReader constructs a new message from a data in reader
+func NewMessageFromReader(reader io.Reader) (*Message, error) {
+ m := new(Message)
+ _, err := m.ReadFrom(reader)
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}