mirror of https://github.com/elisescu/tty-share
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.
144 lines
2.8 KiB
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)
|
|
}
|