From 4b4cf1246d7fec0b0bfe7a9d9c27a2f3203c01a8 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 24 Aug 2015 18:48:27 +0200 Subject: [PATCH] Initial version --- cmd/gotty-client/main.go | 38 ++++++++++++++++ gotty-client.go | 94 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 cmd/gotty-client/main.go create mode 100644 gotty-client.go diff --git a/cmd/gotty-client/main.go b/cmd/gotty-client/main.go new file mode 100644 index 0000000..134cbd9 --- /dev/null +++ b/cmd/gotty-client/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/Sirupsen/logrus" + "github.com/moul/gotty-client" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: %s [GoTTY URL]\n", os.Args[0]) + flag.PrintDefaults() + os.Exit(2) +} + +func main() { + flag.Usage = usage + flag.Parse() + + args := flag.Args() + if len(args) < 1 { + logrus.Fatalf("GoTTY URL is missing.") + } + + // create Client + client, err := gottyclient.NewClient(flag.Arg(0)) + if err != nil { + logrus.Fatalf("Cannot create client: %v", err) + } + + // loop + err = client.Loop() + if err != nil { + logrus.Fatalf("Communication error: %v", err) + } +} diff --git a/gotty-client.go b/gotty-client.go new file mode 100644 index 0000000..fac213a --- /dev/null +++ b/gotty-client.go @@ -0,0 +1,94 @@ +package gottyclient + +import ( + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/Sirupsen/logrus" + "github.com/gorilla/websocket" +) + +// GetWebsocketURL transforms a GoTTY http URL to its WebSocket URL +func GetWebsocketURL(httpURL string) (*url.URL, error) { + target, err := url.Parse(httpURL) + if err != nil { + return nil, err + } + + if target.Scheme == "https" { + target.Scheme = "wss" + } else { + target.Scheme = "ws" + } + + target.Path = strings.TrimLeft(target.Path+"ws", "/") + + return target, nil +} + +type Client struct { + Dialer *websocket.Dialer + Conn *websocket.Conn + Headers http.Header + Target string + Connected bool +} + +// Connect tries to dial a websocket server +func (c *Client) Connect() error { + conn, _, err := c.Dialer.Dial(c.Target, c.Headers) + if err != nil { + return err + } + c.Conn = conn + return nil +} + +// Close will nicely close the dialer +func (c *Client) Close() { + c.Conn.Close() +} + +// Loop will look indefinitely for new messages +func (c *Client) Loop() error { + if !c.Connected { + err := c.Connect() + if err != nil { + return err + } + } + + for { + _, data, err := c.Conn.ReadMessage() + if err != nil { + return err + } + + switch data[0] { + case '0': // data + fmt.Print(string(data[1:])) + case '1': // new title + logrus.Infof("New title: %s", string(data[1:])) + case '2': // json prefs + logrus.Warnf("Unhandled protocol message: json pref: %s", string(data)) + default: + logrus.Warnf("Unhandled protocol message: %s", string(data)) + } + } + return nil +} + +// NewClient returns a GoTTY client object +func NewClient(httpURL string) (*Client, error) { + target, err := GetWebsocketURL(httpURL) + if err != nil { + return nil, err + } + + return &Client{ + Dialer: &websocket.Dialer{}, + Target: target.String(), + }, nil +}