github.com/mendersoftware/go-lib-micro@v0.0.0-20240304135804-e8e39c59b148/ws/protomsg.go (about) 1 // Copyright 2023 Northern.tech AS 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ws 16 17 import "encoding" 18 19 const ProtocolVersion = 1 20 21 // ProtoType defines how the ProtoMsg should be interpreted. 22 type ProtoType uint16 23 24 const ( 25 // ProtoInvalid signifies an invalid (uninitialized) ProtoMsg. 26 ProtoInvalid ProtoType = iota 27 // ProtoTypeShell is used for communicating remote terminal session data. 28 ProtoTypeShell 29 // ProtoTypeFileTransfer is used for file transfer from/to the device. 30 ProtoTypeFileTransfer 31 // ProtoTypePortForward is used for port-forwarding connections to the device. 32 ProtoTypePortForward 33 // ProtoTypeMenderClient is used for communication with the Mender client. 34 ProtoTypeMenderClient 35 36 // ProtoTypeControl is a reserved proto type for session control messages. 37 ProtoTypeControl ProtoType = 0xFFFF 38 ) 39 40 const ( 41 // MessageTypes for session control messages (ProtoTypeControl). 42 43 // MessageTypePing sends a ping. After receiving a ping, the receiver 44 // MUST respond with a pong message or the session will time out. 45 MessageTypePing = "ping" 46 // MessageTypePong is sent in response to a MessageTypePing. 47 MessageTypePong = "pong" 48 // MessageTypeOpen allocates a new peer-to-peer deviceconnect session. 49 // The other peer can either respond with MessageTypeAccept or 50 // MessageTypeError 51 MessageTypeOpen = "open" 52 // MessageTypeAccept is a successful response to an open request. 53 MessageTypeAccept = "accept" 54 // MessageTypeClose is sent when the session MUST close. All 55 // communication on the session stop after receiving this message. 56 MessageTypeClose = "close" 57 // MessageTypeError is sent on a general protocol violation/error. 58 // An error message MUST contain an Error object. If the object's 59 // "close" field is set this message also closes the session. 60 MessageTypeError = "error" 61 ) 62 63 // ProtoHdr provides the info about what the ProtoMsg contains and 64 // to which protocol the message should be routed. 65 type ProtoHdr struct { 66 // Proto defines which protocol this message belongs 67 // to (required). 68 Proto ProtoType `msgpack:"proto"` 69 // MsgType is an optional content type header describing 70 // the protocol specific content type of the message. 71 MsgType string `msgpack:"typ,omitempty"` 72 // SessionID is used to identify one ProtoMsg stream for 73 // multiplexing multiple ProtoMsg sessions over the same connection. 74 SessionID string `msgpack:"sid,omitempty"` 75 // Properties provide a map of optional prototype specific 76 // properties (such as http headers or other meta-data). 77 Properties map[string]interface{} `msgpack:"props,omitempty"` 78 } 79 80 // ProtoMsg is a wrapper to messages communicated on bidirectional interfaces 81 // such as websockets to wrap data from other application protocols. 82 type ProtoMsg struct { 83 // Header contains a protocol specific header with a single 84 // fixed ProtoType ("typ") field and optional hints for decoding 85 // the payload. 86 Header ProtoHdr `msgpack:"hdr"` 87 // Body contains the raw protocol data. The data contained in Body 88 // can be arbitrary and must be decoded according to the protocol 89 // defined in the header. 90 Body []byte `msgpack:"body,omitempty"` 91 } 92 93 func (m *ProtoMsg) Bind(b encoding.BinaryMarshaler) error { 94 data, err := b.MarshalBinary() 95 m.Body = data 96 return err 97 } 98 99 // The Error struct is passed in the Body of MessageTypeError. 100 type Error struct { 101 // The error description, as in "Permission denied while opening a file" 102 Error string `msgpack:"err" json:"error"` 103 // Close determines whether the session closed as a result of this error. 104 Close bool `msgpack:"close" json:"close"` 105 // Code is the error code associated with the error. Values in the 106 // range 400-599 carry the same semantic meaning as the HTTP equivalent. 107 // Please allocate new error codes starting from 1000 for custom error codes. 108 Code int `msgpack:"code,omitempty" json:"code,omitempty"` 109 // MessageProto is the protocol of the message that caused the error. 110 MessageProto ProtoType `msgpack:"msgproto,omitempty" json:"message_protocol,omitempty"` 111 // Type of message that raised the error 112 MessageType string `msgpack:"msgtype,omitempty" json:"message_type,omitempty"` 113 // Message id is passed in the MsgProto Properties, and in case it is available and 114 // error occurs it is passed for reference in the Body of the error message 115 MessageID string `msgpack:"msgid,omitempty" json:"message_id,omitempty"` 116 } 117 118 // ProtoMsg handshake semantics: 119 // 1) The requester sends an "open" control message with all the protocol 120 // versions it supports to the peer. 121 // 2a) On success, the peer will respond with a message of type Accept with an 122 // agreed upon version together with all the ProtoTypes the peer is willing 123 // to accept. 124 // 2b) On failure, the peer will respond with an Error message with a reasoning.* 125 // 126 // *The client can also expect to get an Open message type in return. In 127 // this case it MUST check the header's "status" property, if the property 128 // exists and equal to 1 the client is version 0, and does not support 129 // features added after Mender 2.6. 130 131 // Open is the schema used for initiating a ProtoMsg handshake. 132 type Open struct { 133 // Versions is a list of versions the client is able to interpret. 134 Versions []int `msgpack:"versions"` 135 } 136 137 // Accept is the schema for the message type "accept" for a successful response to 138 // a ProtoMsg handshake. 139 type Accept struct { 140 // Version is the accepted version used for this session. 141 Version int `msgpack:"version"` 142 // Protocols is a list of protocols the peer is willing to accept. 143 Protocols []ProtoType `msgpack:"protocols"` 144 }