File: protomsg.go

package info (click to toggle)
golang-github-mendersoftware-go-lib-micro 0.0~git20211108.4e20429%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, experimental, forky, sid, trixie
  • size: 656 kB
  • sloc: makefile: 5
file content (140 lines) | stat: -rw-r--r-- 5,847 bytes parent folder | download
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
139
140
// Copyright 2021 Northern.tech AS
//
//    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.

package ws

import "encoding"

const ProtocolVersion = 1

// ProtoType defines how the ProtoMsg should be interpreted.
type ProtoType uint16

const (
	// ProtoInvalid signifies an invalid (uninitialized) ProtoMsg.
	ProtoInvalid ProtoType = iota
	// ProtoTypeShell is used for communicating remote terminal session data.
	ProtoTypeShell
	// ProtoTypeFileTransfer is used for file transfer from/to the device.
	ProtoTypeFileTransfer
	// ProtoTypePortForward is used for port-forwarding connections to the device.
	ProtoTypePortForward
	// ProtoTypeMenderClient is used for communication with the Mender client.
	ProtoTypeMenderClient

	// ProtoTypeControl is a reserved proto type for session control messages.
	ProtoTypeControl ProtoType = 0xFFFF
)

const (
	// MessageTypes for session control messages (ProtoTypeControl).

	// MessageTypePing sends a ping. After receiving a ping, the receiver
	// MUST respond with a pong message or the session will time out.
	MessageTypePing = "ping"
	// MessageTypePong is sent in response to a MessageTypePing.
	MessageTypePong = "pong"
	// MessageTypeOpen allocates a new peer-to-peer deviceconnect session.
	// The other peer can either respond with MessageTypeAccept or
	// MessageTypeError
	MessageTypeOpen = "open"
	// MessageTypeAccept is a successful response to an open request.
	MessageTypeAccept = "accept"
	// MessageTypeClose is sent when the session MUST close. All
	// communication on the session stop after receiving this message.
	MessageTypeClose = "close"
	// MessageTypeError is sent on a general protocol violation/error.
	// An error message MUST contain an Error object. If the object's
	// "close" field is set this message also closes the session.
	MessageTypeError = "error"
)

// ProtoHdr provides the info about what the ProtoMsg contains and
// to which protocol the message should be routed.
type ProtoHdr struct {
	// Proto defines which protocol this message belongs
	// to (required).
	Proto ProtoType `msgpack:"proto"`
	// MsgType is an optional content type header describing
	// the protocol specific content type of the message.
	MsgType string `msgpack:"typ,omitempty"`
	// SessionID is used to identify one ProtoMsg stream for
	// multiplexing multiple ProtoMsg sessions over the same connection.
	SessionID string `msgpack:"sid,omitempty"`
	// Properties provide a map of optional prototype specific
	// properties (such as http headers or other meta-data).
	Properties map[string]interface{} `msgpack:"props,omitempty"`
}

// ProtoMsg is a wrapper to messages communicated on bidirectional interfaces
// such as websockets to wrap data from other application protocols.
type ProtoMsg struct {
	// Header contains a protocol specific header with a single
	// fixed ProtoType ("typ") field and optional hints for decoding
	// the payload.
	Header ProtoHdr `msgpack:"hdr"`
	// Body contains the raw protocol data. The data contained in Body
	// can be arbitrary and must be decoded according to the protocol
	// defined in the header.
	Body []byte `msgpack:"body,omitempty"`
}

func (m *ProtoMsg) Bind(b encoding.BinaryMarshaler) error {
	data, err := b.MarshalBinary()
	m.Body = data
	return err
}

// The Error struct is passed in the Body of MessageTypeError.
type Error struct {
	// The error description, as in "Permission denied while opening a file"
	Error string `msgpack:"err" json:"error"`
	// Close determines whether the session closed as a result of this error.
	Close bool `msgpack:"close" json:"close"`
	// MessageProto is the protocol of the message that caused the error.
	MessageProto ProtoType `msgpack:"msgproto,omitempty" json:"message_protocol,omitempty"`
	// Type of message that raised the error
	MessageType string `msgpack:"msgtype,omitempty" json:"message_type,omitempty"`
	// Message id is passed in the MsgProto Properties, and in case it is available and
	// error occurs it is passed for reference in the Body of the error message
	MessageID string `msgpack:"msgid,omitempty" json:"message_id,omitempty"`
}

// ProtoMsg handshake semantics:
// 1)  The requester sends an "open" control message with all the protocol
//     versions it supports to the peer.
// 2a) On success, the peer will respond with a message of type Accept with an
//     agreed upon version together with all the ProtoTypes the peer is willing
//     to accept.
// 2b) On failure, the peer will respond with an Error message with a reasoning.*
//
//     *The client can also expect to get an Open message type in return. In
//     this case it MUST check the header's "status" property, if the property
//     exists and equal to 1 the client is version 0, and does not support
//     features added after Mender 2.6.

// Open is the schema used for initiating a ProtoMsg handshake.
type Open struct {
	// Versions is a list of versions the client is able to interpret.
	Versions []int `msgpack:"versions"`
}

// Accept is the schema for the message type "accept" for a successful response to
// a ProtoMsg handshake.
type Accept struct {
	// Version is the accepted version used for this session.
	Version int `msgpack:"version"`
	// Protocols is a list of protocols the peer is willing to accept.
	Protocols []ProtoType `msgpack:"protocols"`
}