Add support for joining a session from command line

pull/25/head
Vasile Popescu 4 years ago committed by Elis Popescu
parent 46e1bdaab2
commit afc909a358

@ -0,0 +1,118 @@
package main
import (
"encoding/json"
"io"
"net/http"
"net/url"
"os"
ttyServer "github.com/elisescu/tty-share/server"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"
)
type ttyShareClient struct {
url string
connection *websocket.Conn
}
func newTtyShareClient(url string) *ttyShareClient {
return &ttyShareClient{
url: url,
connection: nil,
}
}
type wsTextWriter struct {
conn *websocket.Conn
}
func (w *wsTextWriter) Write(data []byte) (n int, err error) {
err = w.conn.WriteMessage(websocket.TextMessage, data)
return len(data), err
}
func (c *ttyShareClient) Run() (err error) {
log.Printf("Starting tty-share client on %s", c.url)
resp, err := http.Get(c.url)
if err != nil {
return
}
// Get the path of the websockts route from the header
wsPath := resp.Header.Get("TTYSHARE-WSPATH")
// Build the WS URL from the host part of the given http URL and the wsPath
httpURL, err := url.Parse(c.url)
if err != nil {
return
}
wsScheme := "ws"
if httpURL.Scheme == "https" {
wsScheme = "wss"
}
wsURL := wsScheme + "://" + httpURL.Host + wsPath
log.Printf("Connecting to WS URL: %s", wsURL)
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
if err != nil {
log.Fatal("Cannot create the websocket connection:", err)
}
state, err := terminal.MakeRaw(0)
defer terminal.Restore(0, state)
c.connection = conn
readLoop := func() {
for {
var msg ttyServer.MsgAll
_, r, err := conn.NextReader()
if err != nil {
log.Infof("Connection closed: %s", err.Error())
return
}
err = json.NewDecoder(r).Decode(&msg)
if err != nil {
log.Errorf("Cannot read JSON: %s", err.Error())
}
switch msg.Type {
case ttyServer.MsgIDWrite:
var msgWrite ttyServer.MsgTTYWrite
err := json.Unmarshal(msg.Data, &msgWrite)
if err != nil {
log.Errorf("Cannot read JSON: %s", err.Error())
}
os.Stdout.Write(msgWrite.Data)
case ttyServer.MsgIDWinSize:
log.Debugf("Got Win Size msg")
}
}
}
writeLoop := func() {
ww := &wsTextWriter{
conn: conn,
}
_, err := io.Copy(ttyServer.NewTTYProtocolWriter(ww), os.Stdin)
if err != nil {
log.Errorf("Finished io.Copy with %s", err.Error())
}
}
go writeLoop()
readLoop()
return
}
func (c *ttyShareClient) Stop() {
c.connection.Close()
}

@ -8,7 +8,10 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2
github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce
github.com/jroimartin/gocui v0.4.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 // indirect
github.com/sirupsen/logrus v1.4.2
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7 // indirect

@ -11,9 +11,15 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfviiAgIUjg2PXxsQfs5bphsG8F7Keo=
github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/jroimartin/gocui v0.4.0 h1:52jnalstgmc25FmtGcWqa0tcbMEWS6RpFLsOIO+I+E8=
github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag=
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=

@ -48,6 +48,7 @@ func main() {
proxyServerAddress := flag.String("proxy_address", "localhost:9000", "Address of the proxy for public facing connections")
readOnly := flag.Bool("readonly", false, "Start a read only session")
publicSession := flag.Bool("public", false, "Create a public session")
connectURL := flag.String("connect", "", "Use as client to connect to a remote tty-share, instead of using the browser")
flag.Parse()
if *versionFlag {
@ -55,7 +56,7 @@ func main() {
return
}
log.SetLevel(log.ErrorLevel)
log.SetLevel(log.InfoLevel)
if *logFileName != "-" {
fmt.Printf("Writing logs to: %s\n", *logFileName)
logFile, err := os.Create(*logFileName)
@ -71,6 +72,18 @@ func main() {
os.Exit(1)
}
if *connectURL != "" {
client := newTtyShareClient(*connectURL)
err := client.Run()
if err != nil {
panic(err.Error())
}
return
}
sessionID := "local"
if *publicSession {
proxy, err := proxy.NewProxyConnection(*listenAddress, *proxyServerAddress)

@ -97,7 +97,7 @@ func _404Css() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "404.css", size: 3393, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "404.css", size: 3393, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -117,7 +117,7 @@ func _404Html() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "404.html", size: 601, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "404.html", size: 601, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -137,7 +137,7 @@ func _404InHtml() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "404.in.html", size: 616, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "404.in.html", size: 616, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -157,12 +157,12 @@ func bootstrapMinCss() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "bootstrap.min.css", size: 140930, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "bootstrap.min.css", size: 140930, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _ttyShareInHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x91\x4d\x6b\xc3\x30\x0c\x86\xef\xfd\x15\x5a\xee\x8d\xae\x63\x38\x39\x8d\xc1\x6e\x85\x6d\xec\xac\xc5\xde\xa2\x92\x8f\x62\xbf\xa4\x0d\x26\xff\x7d\x38\x86\x35\xa5\xf3\xc5\x92\xfc\xe8\xb5\x3e\xcc\x83\x1d\x1b\xcc\x27\x47\x2d\xfa\xae\xde\x99\x7c\x11\x11\x99\xd6\x89\xcd\xe6\xea\xf6\x0e\x42\x4d\x2b\x3e\x38\x54\xc5\xc7\xfb\xcb\xfe\xb1\xd8\x3c\x43\xd1\xb9\x1a\x98\xf7\xa1\x15\xef\x0c\xe7\x40\x96\xe2\xab\x96\xf9\x1a\xed\xbc\xc9\xb3\x3a\x91\xda\xaa\x80\xf3\xbd\x0e\xd2\x15\xb5\x61\xab\xd3\x3f\x44\x70\x80\x0e\x3f\xe1\x9e\x08\x8d\xd7\x13\x28\xf5\x91\x84\x2e\xe0\xa3\x4c\x92\xa3\x9b\x1a\xd3\x39\xeb\x60\xc7\x73\x09\xcc\xaf\x83\x42\xa5\x7b\x16\x08\x55\x14\x6f\xa8\x95\x0c\x07\x41\xfb\x44\x31\x96\x9f\x6f\xc9\x5c\x96\x1b\xe6\xea\x19\xce\x5f\xdd\x57\x14\x7c\x53\x15\x1c\x63\x99\xf2\x0f\xde\x7d\xeb\x65\x59\x38\x40\xa0\x0d\xff\xcd\xaa\x3c\xae\x3d\x6d\x45\x0c\xe7\x31\x19\xce\x0b\xd9\xfd\x06\x00\x00\xff\xff\x8c\xe3\x5d\x6b\xa9\x01\x00\x00")
var _ttyShareInHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x92\xcf\xaf\xdb\x20\x0c\xc7\xef\xef\xaf\xf0\xe3\x4e\xd0\x6e\xd3\x44\x7a\x9a\x26\xed\x56\x69\x9d\x76\x76\x82\x37\x5c\x25\x10\x81\x97\x34\x8a\xf2\xbf\x4f\x09\x52\x9b\xaa\x7b\x5c\xc0\xe6\xeb\x8f\x7f\x80\x7d\x77\xb1\x95\x79\x20\xf0\xd2\x77\xa7\x37\x5b\x36\x00\x00\xeb\x09\x5d\x39\xee\x66\x4f\x82\xd0\x7a\x4c\x99\xa4\x56\x3f\x2f\xdf\xf4\x67\x75\xb8\x16\x96\x8e\x4e\x22\xb3\xce\x1e\x13\x59\x53\x1c\x05\x65\x1e\x2c\xdb\x44\x37\x1f\xe2\xde\xb5\x86\x8b\xe7\x0c\x8e\x47\x40\x91\xc4\xcd\x5f\xa1\x0c\x13\x77\x1d\x34\x04\x89\xd0\x41\x33\x83\x78\x82\x3b\x1d\xda\xd8\xf7\x18\x1c\x4c\x9e\x02\x24\x0c\x10\xc3\xae\x48\xd4\x47\x21\xc8\xec\x08\xb4\x3e\xa4\xd9\xe8\xec\x6a\x75\x47\xe8\xad\x1f\x05\x43\x8a\x12\xf5\x48\x29\x73\x0c\xb5\xfa\xa4\x60\xca\x7a\x40\xf1\xb5\x5a\x96\xea\xd7\x8f\x33\x8a\x5f\x57\x75\xb2\xc6\xf1\xf8\x3f\x1e\xa5\x9e\x03\x76\x1f\x2b\x32\x89\x70\xf8\x93\x5f\x15\xb9\x4d\x3c\x08\x6c\xe3\xdf\x40\x37\x31\x57\x1c\xb1\x78\x0f\xa3\xdd\xd6\xc4\xc1\xc5\xa9\x12\x99\xbf\x07\x16\xc6\xee\x2b\x0a\x42\x0d\xcb\x93\x6a\x57\xe6\xad\xe4\x2f\x70\xa8\xfe\x49\xf3\xb0\xac\x29\xa9\x5e\x2b\xca\xa9\xad\x95\x59\x96\x6a\x8b\x3f\x27\xfa\xcd\xb7\x75\x35\x59\x50\xb8\x35\xf7\x09\x56\xd7\xbd\xa7\x23\xc4\x9a\xf2\xba\xd6\x94\x7f\xf4\xf6\x2f\x00\x00\xff\xff\x73\xbb\x5a\x79\x60\x02\x00\x00")
func ttyShareInHtmlBytes() ([]byte, error) {
return bindataRead(
@ -177,7 +177,7 @@ func ttyShareInHtml() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "tty-share.in.html", size: 425, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "tty-share.in.html", size: 608, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -197,7 +197,7 @@ func ttyShareJs() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "tty-share.js", size: 404641, mode: os.FileMode(420), modTime: time.Unix(1601412768, 0)}
info := bindataFileInfo{name: "tty-share.js", size: 404641, mode: os.FileMode(420), modTime: time.Unix(1601583738, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}

@ -95,10 +95,14 @@ func NewTTYServer(config TTYServerConfig) (server *TTYServer) {
})))
routesHandler.HandleFunc(fmt.Sprintf("/%s/", session), func(w http.ResponseWriter, r *http.Request) {
wsPath := "/" + session + "/ws"
templateModel := struct {
PathPrefix string
WSPath string
}{session, "/" + session + "/ws"}
}{session, wsPath}
// Extract these in constants
w.Header().Add("TTYSHARE-VERSION", "1")
w.Header().Add("TTYSHARE-WSPATH", wsPath)
server.handleWithTemplateHtml(w, r, "tty-share.in.html", templateModel)
})

Loading…
Cancel
Save