You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tty-share/server/tty_protocol_rw.go

144 lines
2.8 KiB
Go

package server
import (
"encoding/json"
"errors"
"fmt"
"io"
)
type TTYProtocolReader struct {
reader io.Reader
jsonDecoder *json.Decoder
}
type TTYProtocolWriter struct {
writer io.Writer
}
const (
MsgIDWrite = "Write"
MsgIDWinSize = "WinSize"
)
// Message used to encapsulate the rest of the bessages bellow
type MsgAll struct {
Type string
Data []byte
}
type MsgTTYWrite struct {
Data []byte
Size int
}
type MsgTTYWinSize struct {
Cols int
Rows int
}
func ReadAndUnmarshalMsg(reader io.Reader, aMessage interface{}) (err error) {
var wrapperMsg MsgAll
// Wait here for the right message to come
dec := json.NewDecoder(reader)
err = dec.Decode(&wrapperMsg)
if err != nil {
return errors.New("Cannot decode top message: " + err.Error())
}
err = json.Unmarshal(wrapperMsg.Data, aMessage)
if err != nil {
return errors.New("Cannot decode message: " + err.Error() + string(wrapperMsg.Data))
}
return
}
func MarshalMsg(aMessage interface{}) (_ []byte, err error) {
var msg MsgAll
if writeMsg, ok := aMessage.(MsgTTYWrite); ok {
msg.Type = MsgIDWrite
msg.Data, err = json.Marshal(writeMsg)
//fmt.Printf("Sent write message %s\n", string(writeMsg.Data))
if err != nil {
return
}
return json.Marshal(msg)
}
if winChangedMsg, ok := aMessage.(MsgTTYWinSize); ok {
msg.Type = MsgIDWinSize
msg.Data, err = json.Marshal(winChangedMsg)
if err != nil {
return
}
return json.Marshal(msg)
}
return nil, nil
}
func MarshalAndWriteMsg(writer io.Writer, aMessage interface{}) (err error) {
b, err := MarshalMsg(aMessage)
if err != nil {
return
}
n, err := writer.Write(b)
if n != len(b) {
err = fmt.Errorf("Unable to write : wrote %d out of %d bytes", n, len(b))
return
}
if err != nil {
return
}
return
}
func NewTTYProtocolWriter(w io.Writer) *TTYProtocolWriter {
return &TTYProtocolWriter{
writer: w,
}
}
func NewTTYProtocolReader(r io.Reader) *TTYProtocolReader {
return &TTYProtocolReader{
reader: r,
jsonDecoder: json.NewDecoder(r),
}
}
func (reader *TTYProtocolReader) ReadMessage() (msg MsgAll, err error) {
// TODO: perhaps read here the error, and transform it to something that's understandable
// from the outside in the context of this object
err = reader.jsonDecoder.Decode(&msg)
return
}
func (writer *TTYProtocolWriter) SetWinSize(cols, rows int) error {
msgWinChanged := MsgTTYWinSize{
Cols: cols,
Rows: rows,
}
return MarshalAndWriteMsg(writer.writer, msgWinChanged)
}
// Function to send data from one the sender to the server and the other way around.
func (writer *TTYProtocolWriter) Write(buff []byte) (int, error) {
msgWrite := MsgTTYWrite{
Data: buff,
Size: len(buff),
}
return len(buff), MarshalAndWriteMsg(writer.writer, msgWrite)
}
func (writer *TTYProtocolWriter) WriteRawData(buff []byte) (int, error) {
return writer.writer.Write(buff)
}