// Sshwifty - A Web SSH client // // Copyright (C) 2019 Rui NI // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package command import "fmt" // Header Packet Type type Header byte // Packet Types const ( // 00------: Control signals // Remaing bits: Data length // // Format: // 0011111 [63 bytes long data] - 63 bytes of control data // HeaderControl Header = 0x00 // 01------: Bidirectional stream data // Remaining bits: Stream ID // Followed by: Parameter or data // // Format: // 0111111 [Command parameters / data] - Open/use stream 63 to execute // command or transmit data HeaderStream Header = 0x40 // 10------: Close stream // Remaining bits: Stream ID // // Format: // 1011111 - Close stream 63 // // WARNING: The requester MUST NOT send any data to this stream once this // header is sent. // // WARNING: The receiver MUST reply with a Completed header to indicate // the success of the Close action. Until a Completed header is // replied, all data from the sender must be proccessed as normal. HeaderClose Header = 0x80 // 11------: Stream has been closed/completed in respond to client request // Remaining bits: Stream ID // // Format: // 1111111 - Stream 63 is completed // // WARNING: This header can ONLY be send in respond to a Close header // // WARNING: The sender of this header MUST NOT send any data to the stream // once this header is sent until this stream been re-opened by a // Data header HeaderCompleted Header = 0xc0 ) // Control signal types const ( HeaderControlEcho = 0x00 HeaderControlPauseStream = 0x01 HeaderControlResumeStream = 0x02 ) // Consts const ( HeaderMaxData = 0x3f ) // Cutters const ( headerHeaderCutter = 0xc0 headerDataCutter = 0x3f ) // Type get packet type func (p Header) Type() Header { return (p & headerHeaderCutter) } // Data returns the data of current Packet header func (p Header) Data() byte { return byte(p & headerDataCutter) } // Set set a new value of the Header func (p *Header) Set(data byte) { if data > headerDataCutter { panic("data must not be greater than 0x3f") } *p |= (headerDataCutter & Header(data)) } // Set set a new value of the Header func (p Header) String() string { switch p.Type() { case HeaderControl: return fmt.Sprintf("Control (%d bytes)", p.Data()) case HeaderStream: return fmt.Sprintf("Stream (%d)", p.Data()) case HeaderClose: return fmt.Sprintf("Close (Stream %d)", p.Data()) case HeaderCompleted: return fmt.Sprintf("Completed (Stream %d)", p.Data()) default: return "Unknown" } } // IsStreamControl returns true when the header is for stream control, false // when otherwise func (p Header) IsStreamControl() bool { switch p { case HeaderStream: fallthrough case HeaderClose: fallthrough case HeaderCompleted: return true default: return false } }