Created
November 2, 2017 04:07
-
-
Save antoniomika/2f56cd2d62145d10e10423fbfaf7b553 to your computer and use it in GitHub Desktop.
SeeShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/xterm.min.css" /> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/addons/fullscreen/fullscreen.min.css" /> | |
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" /> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> | |
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/xterm.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/addons/fullscreen/fullscreen.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/addons/fit/fit.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/addons/attach/attach.min.js"></script> | |
<style> | |
body { | |
font-family: "DejaVu Sans Mono", "Liberation Mono", monospace; | |
font-size: 11px; | |
} | |
</style> | |
<script type="text/javascript"> | |
$(function() { | |
var ip = window.location.hash.substr(1) || prompt("Address:"); | |
var websocket = new WebSocket("ws://" + window.location.hostname + ":" + window.location.port + "/ws/" + ip); | |
websocket.onopen = function(evt) { | |
term = new Terminal({ | |
cursorBlink: true, | |
cols: 250, | |
rows: 50 | |
}); | |
term.open(document.getElementById("terminal-container"), true); | |
term.toggleFullscreen(true); | |
term.attach(websocket); | |
} | |
}); | |
</script> | |
</head> | |
<div id="terminal-container"></div> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"log" | |
"net/http" | |
"text/template" | |
"github.com/fatih/color" | |
"github.com/gorilla/mux" | |
"github.com/gorilla/websocket" | |
"net" | |
"time" | |
"sync" | |
"bufio" | |
) | |
var httpAddr = flag.String("http-addr", "localhost:8080", "HTTP/WS service address") | |
var tcpAddr = flag.String("tcp-add", "localhost:8081", "TCP service address") | |
var indexTemplate = template.Must(template.ParseFiles("templates/index.html")) | |
var upgrader = websocket.Upgrader{ | |
CheckOrigin: func(r *http.Request) bool { return true }, | |
} | |
var webSocketClients = make(map[string][]*websocket.Conn) | |
var tcpClients = make(map[string]net.Conn) | |
var mutex = &sync.Mutex{} | |
func logHTTP(handler http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
color.Set(color.FgYellow) | |
log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL) | |
color.Unset() | |
handler.ServeHTTP(w, r) | |
}) | |
} | |
func main() { | |
flag.Parse() | |
log.SetFlags(0) | |
r := mux.NewRouter() | |
r.HandleFunc("/", indexHandler) | |
r.HandleFunc("/ws/{id}", wsHandler) | |
http.Handle("/", r) | |
color.Set(color.FgGreen) | |
log.Println("Running HTTP and WS server on:", *httpAddr) | |
color.Unset() | |
color.Set(color.FgRed) | |
go http.ListenAndServe(*httpAddr, logHTTP(http.DefaultServeMux)) | |
color.Unset() | |
color.Set(color.FgGreen) | |
log.Println("Running TCP server on:", *tcpAddr) | |
color.Unset() | |
startTCP() | |
} | |
func indexHandler(w http.ResponseWriter, r *http.Request) { | |
indexTemplate.Execute(w, r.Host) | |
} | |
func wsHandler(w http.ResponseWriter, r *http.Request) { | |
vars := mux.Vars(r) | |
pathKey := vars["id"] | |
c, err := upgrader.Upgrade(w, r, nil) | |
color.Set(color.FgBlue) | |
log.Println("New WebSocket Connection From:", r.RemoteAddr) | |
log.Println("Path:", pathKey) | |
color.Unset() | |
if err != nil { | |
color.Set(color.FgRed) | |
log.Println("Upgrade error:", err) | |
color.Unset() | |
return | |
} | |
mutex.Lock() | |
if _, ok := webSocketClients[pathKey]; ok { | |
webSocketClients[pathKey] = append(webSocketClients[pathKey], c) | |
} else { | |
webSocketClients[pathKey] = []*websocket.Conn{c} | |
} | |
mutex.Unlock() | |
for { | |
_, _, err := c.ReadMessage() | |
if err != nil { | |
color.Set(color.FgRed) | |
log.Println("wsReader error:", err) | |
color.Unset() | |
break | |
} | |
// This will redirect input from the web based terminal to the client (netcat). | |
// If netcat bidirectionally opened stdin and stdout, you could control your process with that. | |
/*if val, ok := tcpClients[pathKey]; ok { | |
writer := bufio.NewWriter(val) | |
writer.Write(data) | |
writer.Flush() | |
}*/ | |
} | |
defer func() { | |
c.Close() | |
color.Set(color.FgMagenta) | |
log.Println("Closed WebSocket Connection From:", r.RemoteAddr) | |
color.Unset() | |
mutex.Lock() | |
if _, ok := webSocketClients[pathKey]; ok { | |
newclients := []*websocket.Conn{} | |
for _, varclient := range webSocketClients[pathKey] { | |
if c != varclient { | |
newclients = append(newclients, varclient) | |
} | |
} | |
webSocketClients[pathKey] = newclients | |
} else { | |
webSocketClients[pathKey] = []*websocket.Conn{} | |
} | |
mutex.Unlock() | |
}() | |
} | |
func startTCP() { | |
socket, err := net.Listen("tcp", *tcpAddr) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer socket.Close() | |
for { | |
conn, err := socket.Accept() | |
if err != nil { | |
log.Println(err) | |
continue | |
} | |
color.Set(color.FgBlue) | |
log.Println("New TCPServer Connection From:", conn.RemoteAddr().String()) | |
color.Unset() | |
go handleTCP(conn) | |
} | |
} | |
func handleTCP(conn net.Conn) { | |
tcpClients[conn.RemoteAddr().String()] = conn | |
conn.SetReadDeadline(time.Now()) | |
reader := bufio.NewReader(conn) | |
writer := bufio.NewWriter(conn) | |
writer.Write([]byte("Access the RTV at http://" + *httpAddr + "/#" + conn.RemoteAddr().String() + "\n")) | |
writer.Flush() | |
for { | |
zero := make([]byte, 0) | |
if _, err := conn.Read(zero); err != nil { | |
log.Println("Foobbar", err) | |
break | |
} else { | |
conn.SetReadDeadline(time.Now().Add(30 * time.Millisecond)) | |
} | |
mutex.Lock() | |
if data, _ := reader.Peek(1); len(data) > 0 { | |
if val, ok := webSocketClients[conn.RemoteAddr().String()]; ok { | |
data, _, err := reader.ReadLine() | |
if err != nil { | |
color.Set(color.FgRed) | |
log.Println("TCPReader error:", err) | |
color.Unset() | |
} | |
for _, wsClient := range val { | |
wsWriter, err := wsClient.NextWriter(websocket.TextMessage) | |
if err != nil { | |
color.Set(color.FgRed) | |
log.Println("wsWriter error:", err) | |
color.Unset() | |
} else { | |
wsWriter.Write(data) | |
wsWriter.Close() | |
} | |
} | |
} | |
} | |
mutex.Unlock() | |
} | |
defer func() { | |
conn.Close() | |
color.Set(color.FgMagenta) | |
log.Println("Closed TCPServer Connection From:", conn.RemoteAddr().String()) | |
color.Unset() | |
}() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment