merged xterm.html and xterm-pts.html
made relevant code changes oin the server side as well
This commit is contained in:
parent
7835696166
commit
d092540f08
3
Makefile
3
Makefile
@ -33,8 +33,7 @@ DATA = \
|
|||||||
xterm.css \
|
xterm.css \
|
||||||
xterm.js \
|
xterm.js \
|
||||||
xterm-addon-fit.js \
|
xterm-addon-fit.js \
|
||||||
xterm.html \
|
xterm.html
|
||||||
xterm-pts.html
|
|
||||||
|
|
||||||
CMD_DATA=\
|
CMD_DATA=\
|
||||||
cmd/rsa.key \
|
cmd/rsa.key \
|
||||||
|
@ -11,6 +11,7 @@ import "os/user"
|
|||||||
import "strconv"
|
import "strconv"
|
||||||
import "sync"
|
import "sync"
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
import "text/template"
|
||||||
|
|
||||||
import "github.com/creack/pty"
|
import "github.com/creack/pty"
|
||||||
import "golang.org/x/net/websocket"
|
import "golang.org/x/net/websocket"
|
||||||
@ -276,7 +277,7 @@ done:
|
|||||||
func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
||||||
var c *Client
|
var c *Client
|
||||||
var status_code int
|
var status_code int
|
||||||
// var err error
|
var err error
|
||||||
|
|
||||||
c = pts.c
|
c = pts.c
|
||||||
|
|
||||||
@ -290,12 +291,26 @@ func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
case "xterm.css":
|
case "xterm.css":
|
||||||
status_code = WriteCssRespHeader(w, http.StatusOK)
|
status_code = WriteCssRespHeader(w, http.StatusOK)
|
||||||
w.Write(xterm_css)
|
w.Write(xterm_css)
|
||||||
case "xterm-pts.html":
|
case "xterm.html":
|
||||||
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
var tmpl *template.Template
|
||||||
if c.xterm_pts_html != "" {
|
|
||||||
w.Write([]byte(c.xterm_pts_html))
|
tmpl = template.New("")
|
||||||
|
if c.xterm_html != "" {
|
||||||
|
_, err = tmpl.Parse(c.xterm_html)
|
||||||
} else {
|
} else {
|
||||||
w.Write(xterm_pts_html)
|
_, err = tmpl.Parse(xterm_html)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
status_code = WriteEmptyRespHeader(w, http.StatusInternalServerError)
|
||||||
|
goto oops
|
||||||
|
} else {
|
||||||
|
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
||||||
|
tmpl.Execute(w,
|
||||||
|
&xterm_session_info{
|
||||||
|
Mode: "pts",
|
||||||
|
ConnId: "-1",
|
||||||
|
RouteId: "-1",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
case "_forbidden":
|
case "_forbidden":
|
||||||
@ -311,6 +326,6 @@ func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
//done:
|
//done:
|
||||||
return status_code, nil
|
return status_code, nil
|
||||||
|
|
||||||
//oops:
|
oops:
|
||||||
// return status_code, err
|
return status_code, err
|
||||||
}
|
}
|
||||||
|
14
client.go
14
client.go
@ -151,7 +151,7 @@ type Client struct {
|
|||||||
|
|
||||||
pts_user string
|
pts_user string
|
||||||
pts_shell string
|
pts_shell string
|
||||||
xterm_pts_html string
|
xterm_html string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientConnState = int32
|
type ClientConnState = int32
|
||||||
@ -1660,8 +1660,8 @@ func NewClient(ctx context.Context, name string, logger Logger, cfg *ClientConfi
|
|||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_notfound"}))
|
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_notfound"}))
|
||||||
c.ctl_mux.Handle("/_pts/xterm.css",
|
c.ctl_mux.Handle("/_pts/xterm.css",
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm.css"}))
|
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm.css"}))
|
||||||
c.ctl_mux.Handle("/_pts/xterm-pts.html",
|
c.ctl_mux.Handle("/_pts/xterm.html",
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm-pts.html"}))
|
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm.html"}))
|
||||||
c.ctl_mux.Handle("/_pts/",
|
c.ctl_mux.Handle("/_pts/",
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_forbidden"}))
|
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_forbidden"}))
|
||||||
c.ctl_mux.Handle("/_pts/favicon.ico",
|
c.ctl_mux.Handle("/_pts/favicon.ico",
|
||||||
@ -1977,12 +1977,12 @@ func (c *Client) ReqStop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SetXtermPtsHtml(html string) {
|
func (c *Client) SetXtermHtml(html string) {
|
||||||
c.xterm_pts_html = html
|
c.xterm_html = html
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetXtermPtsHtml() string {
|
func (c *Client) GetXtermHtml() string {
|
||||||
return c.xterm_pts_html
|
return c.xterm_html
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SetPtsUser(user string) {
|
func (c *Client) SetPtsUser(user string) {
|
||||||
|
@ -107,7 +107,7 @@ type ClientAppConfig struct {
|
|||||||
PeerConnTmout time.Duration `yaml:"peer-conn-timeout"`
|
PeerConnTmout time.Duration `yaml:"peer-conn-timeout"`
|
||||||
PtsUser string `yaml:"pts-user"`
|
PtsUser string `yaml:"pts-user"`
|
||||||
PtsShell string `yaml:"pts-shell"`
|
PtsShell string `yaml:"pts-shell"`
|
||||||
XtermPtsHtmlFile string `yaml:"xterm-pts-html-file"`
|
XtermHtmlFile string `yaml:"xterm-html-file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
|
16
cmd/main.go
16
cmd/main.go
@ -254,8 +254,8 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
var logfile_rotate int
|
var logfile_rotate int
|
||||||
var pts_user string
|
var pts_user string
|
||||||
var pts_shell string
|
var pts_shell string
|
||||||
var xterm_pts_html_file string
|
var xterm_html_file string
|
||||||
var xterm_pts_html string
|
var xterm_html string
|
||||||
var i int
|
var i int
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
logfile_rotate = cfg.APP.LogRotate
|
logfile_rotate = cfg.APP.LogRotate
|
||||||
pts_user = cfg.APP.PtsUser
|
pts_user = cfg.APP.PtsUser
|
||||||
pts_shell = cfg.APP.PtsShell
|
pts_shell = cfg.APP.PtsShell
|
||||||
xterm_pts_html_file = cfg.APP.XtermPtsHtmlFile
|
xterm_html_file = cfg.APP.XtermHtmlFile
|
||||||
config.RpcConnMax = cfg.APP.MaxRpcConns
|
config.RpcConnMax = cfg.APP.MaxRpcConns
|
||||||
config.PeerConnMax = cfg.APP.MaxPeers
|
config.PeerConnMax = cfg.APP.MaxPeers
|
||||||
config.PeerConnTmout = cfg.APP.PeerConnTmout
|
config.PeerConnTmout = cfg.APP.PeerConnTmout
|
||||||
@ -313,20 +313,20 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if xterm_pts_html_file != "" {
|
if xterm_html_file != "" {
|
||||||
var tmp []byte
|
var tmp []byte
|
||||||
tmp, err = os.ReadFile(xterm_pts_html_file)
|
tmp, err = os.ReadFile(xterm_html_file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read %s - %s", xterm_pts_html_file, err.Error())
|
return fmt.Errorf("failed to read %s - %s", xterm_html_file, err.Error())
|
||||||
}
|
}
|
||||||
xterm_pts_html = string(tmp)
|
xterm_html = string(tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
c = hodu.NewClient(context.Background(), HODU_NAME, logger, config)
|
c = hodu.NewClient(context.Background(), HODU_NAME, logger, config)
|
||||||
|
|
||||||
if pts_user != "" { c.SetPtsUser(pts_user) }
|
if pts_user != "" { c.SetPtsUser(pts_user) }
|
||||||
if pts_shell != "" { c.SetPtsShell(pts_shell) }
|
if pts_shell != "" { c.SetPtsShell(pts_shell) }
|
||||||
if xterm_pts_html != "" { c.SetXtermPtsHtml(xterm_pts_html) }
|
if xterm_html != "" { c.SetXtermHtml(xterm_html) }
|
||||||
|
|
||||||
c.StartService(&cc)
|
c.StartService(&cc)
|
||||||
c.StartCtlService() // control channel
|
c.StartCtlService() // control channel
|
||||||
|
8
hodu.go
8
hodu.go
@ -128,8 +128,12 @@ var xterm_addon_fit_js []byte
|
|||||||
var xterm_css []byte
|
var xterm_css []byte
|
||||||
//go:embed xterm.html
|
//go:embed xterm.html
|
||||||
var xterm_html string
|
var xterm_html string
|
||||||
//go:embed xterm-pts.html
|
|
||||||
var xterm_pts_html []byte
|
type xterm_session_info struct {
|
||||||
|
Mode string
|
||||||
|
ConnId string
|
||||||
|
RouteId string
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
|
@ -458,11 +458,6 @@ func (pxy *server_pxy_http_wpx) ServeHTTP(w http.ResponseWriter, req *http.Reque
|
|||||||
}
|
}
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
type server_pxy_xterm_session_info struct {
|
|
||||||
ConnId string
|
|
||||||
RouteId string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pxy *server_pxy_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
func (pxy *server_pxy_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
||||||
var s *Server
|
var s *Server
|
||||||
var status_code int
|
var status_code int
|
||||||
@ -516,7 +511,8 @@ func (pxy *server_pxy_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
} else {
|
} else {
|
||||||
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
||||||
tmpl.Execute(w,
|
tmpl.Execute(w,
|
||||||
&server_pxy_xterm_session_info{
|
&xterm_session_info{
|
||||||
|
Mode: "ssh",
|
||||||
ConnId: conn_id,
|
ConnId: conn_id,
|
||||||
RouteId: route_id,
|
RouteId: route_id,
|
||||||
})
|
})
|
||||||
|
286
xterm-pts.html
286
xterm-pts.html
@ -1,286 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
|
|
||||||
<title>Terminal</title>
|
|
||||||
<link rel="stylesheet" href="xterm.css" />
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-info-container {
|
|
||||||
vertical-align: middle;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-target {
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-status {
|
|
||||||
display: inline-block;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-errmsg {
|
|
||||||
display: inline-block;
|
|
||||||
color: red;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-control {
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-control button {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#terminal-view-container {
|
|
||||||
flex: 1;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 0;
|
|
||||||
/*height: 100%;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
z-index: 99999;
|
|
||||||
}
|
|
||||||
#login-form-container {
|
|
||||||
background: white;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#login-form-title {
|
|
||||||
line-height: 2em;
|
|
||||||
font-size: 2em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script src="xterm.js"></script>
|
|
||||||
<script src="xterm-addon-fit.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
window.onload = function(event) {
|
|
||||||
const terminal_container = document.getElementById('terminal-container');
|
|
||||||
const terminal_target = document.getElementById('terminal-target');
|
|
||||||
const terminal_status = document.getElementById('terminal-status');
|
|
||||||
const terminal_errmsg = document.getElementById('terminal-errmsg');
|
|
||||||
const terminal_view_container = document.getElementById('terminal-view-container');
|
|
||||||
const terminal_connect = document.getElementById('terminal-connect');
|
|
||||||
const terminal_disconnect = document.getElementById('terminal-disconnect');
|
|
||||||
const login_container = document.getElementById('login-container');
|
|
||||||
const login_form_title = document.getElementById('login-form-title');
|
|
||||||
const login_form = document.getElementById('login-form');
|
|
||||||
//const username_field = document.getElementById('username');
|
|
||||||
//const password_field= document.getElementById('password');
|
|
||||||
|
|
||||||
const term = new window.Terminal({
|
|
||||||
lineHeight: 1.2,
|
|
||||||
//fontSize: 14,
|
|
||||||
fontFamily: 'Ubuntu Mono, Consolas, SF Mono, courier-new, courier, monospace'
|
|
||||||
});
|
|
||||||
const fit_addon = new window.FitAddon.FitAddon();
|
|
||||||
const text_decoder = new TextDecoder();
|
|
||||||
|
|
||||||
term.loadAddon(fit_addon)
|
|
||||||
term.open(terminal_view_container);
|
|
||||||
|
|
||||||
let set_terminal_target = function(name) {
|
|
||||||
terminal_target.innerText = name;
|
|
||||||
login_form_title.innerText = name
|
|
||||||
}
|
|
||||||
|
|
||||||
let set_terminal_status = function(msg, errmsg) {
|
|
||||||
if (msg != null) terminal_status.innerText = msg;
|
|
||||||
if (errmsg != null) terminal_errmsg.innerText = errmsg
|
|
||||||
}
|
|
||||||
|
|
||||||
let adjust_terminal_size_unconnected = function() {
|
|
||||||
fit_addon.fit();
|
|
||||||
}
|
|
||||||
|
|
||||||
let fetch_session_info = async function() {
|
|
||||||
let url = window.location.protocol + '//' + window.location.host;
|
|
||||||
let pathname = window.location.pathname;
|
|
||||||
pathname = pathname.replace(/\/$/, '');
|
|
||||||
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
|
||||||
url += pathname + `/session-info`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resp = await fetch(url);
|
|
||||||
if (!resp.ok) throw new Error(`HTTP error in getting session info - status ${resp.status}`);
|
|
||||||
const route = await resp.json()
|
|
||||||
if ('client-peer-name' in route) {
|
|
||||||
set_terminal_target(route['client-peer-name']) // change to the name
|
|
||||||
document.title = route['client-peer-name']
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
set_terminal_target('');
|
|
||||||
document.title = '';
|
|
||||||
set_terminal_status (null, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let toggle_login_form = function(visible) {
|
|
||||||
//if (visible) fetch_session_info();
|
|
||||||
login_container.style.visibility = (visible? 'visible': 'hidden');
|
|
||||||
terminal_disconnect.style.visibility = (visible? 'hidden': 'visible');
|
|
||||||
//if (visible) username_field.focus();
|
|
||||||
//else term.focus();
|
|
||||||
if (visible) terminal_connect.focus();
|
|
||||||
else term.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_login_form(true);
|
|
||||||
window.onresize = adjust_terminal_size_unconnected;
|
|
||||||
adjust_terminal_size_unconnected()
|
|
||||||
|
|
||||||
login_form.onsubmit = async function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
toggle_login_form(false)
|
|
||||||
|
|
||||||
const username = "" //username_field.value.trim();
|
|
||||||
const password = "" //password_field.value.trim();
|
|
||||||
|
|
||||||
const prefix = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
|
||||||
let pathname = window.location.pathname;
|
|
||||||
pathname = pathname.replace(/\/$/, '');
|
|
||||||
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
|
||||||
let url = prefix + window.location.host + pathname + `/ws`;
|
|
||||||
|
|
||||||
const socket = new WebSocket(url);
|
|
||||||
socket.binaryType = 'arraybuffer';
|
|
||||||
|
|
||||||
set_terminal_status('Connecting...', '');
|
|
||||||
|
|
||||||
const adjust_terminal_size_connected = function() {
|
|
||||||
fit_addon.fit();
|
|
||||||
if (socket.readyState == 1) // if open
|
|
||||||
socket.send(JSON.stringify({ type: 'size', data: [term.rows.toString(), term.cols.toString()] }));
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onopen = function () {
|
|
||||||
socket.send(JSON.stringify({ type: 'open', data: [username, password]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onmessage = function(event) {
|
|
||||||
try {
|
|
||||||
let event_text;
|
|
||||||
event_text = (typeof event.data === 'string')? event.data: text_decoder.decode(new Uint8Array(event.data));
|
|
||||||
const msg = JSON.parse(event_text);
|
|
||||||
if (msg.type == "iov") {
|
|
||||||
for (const data of msg.data) term.write(data);
|
|
||||||
} else if (msg.type == "status") {
|
|
||||||
if (msg.data.length >= 1) {
|
|
||||||
if (msg.data[0] == 'opened') {
|
|
||||||
set_terminal_status('Connected', '');
|
|
||||||
adjust_terminal_size_connected()
|
|
||||||
term.clear()
|
|
||||||
} else if (msg.data[0] == 'closed') {
|
|
||||||
// doesn't really matter
|
|
||||||
// socket.onclose() will be executed anyway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (msg.type == "error") {
|
|
||||||
toggle_login_form(true);
|
|
||||||
window.onresize = adjust_terminal_size_unconnected;
|
|
||||||
set_terminal_status(null, msg.data.join(' '))
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
set_terminal_status('Disconnected', e);
|
|
||||||
toggle_login_form(true)
|
|
||||||
window.onresize = adjust_terminal_size_unconnected;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onerror = function(event) {
|
|
||||||
//set_terminal_status('Disconnected', event);
|
|
||||||
set_terminal_status('Disconnected', '');
|
|
||||||
toggle_login_form(true)
|
|
||||||
window.onresize = adjust_terminal_size_unconnected;
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onclose = function() {
|
|
||||||
set_terminal_status('Disconnected', null);
|
|
||||||
toggle_login_form(true)
|
|
||||||
window.onresize = adjust_terminal_size_unconnected;
|
|
||||||
};
|
|
||||||
|
|
||||||
term.onData(function(data) {
|
|
||||||
if (socket.readyState == 1) // if open
|
|
||||||
socket.send(JSON.stringify({ type: 'iov', data: [data] }));
|
|
||||||
});
|
|
||||||
|
|
||||||
window.onresize = adjust_terminal_size_connected;
|
|
||||||
terminal_disconnect.onclick = function(event) {
|
|
||||||
socket.send(JSON.stringify({ type: 'close', data: [""] }));
|
|
||||||
//socket.close()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="login-container">
|
|
||||||
<div id="login-form-container">
|
|
||||||
<div id="login-form-title"></div>
|
|
||||||
<form id="login-form">
|
|
||||||
<!-- <label>
|
|
||||||
Username: <input type="text" id="username" required />
|
|
||||||
</label>
|
|
||||||
<br /><br />
|
|
||||||
<label>
|
|
||||||
Password: <input type="password" id="password" required />
|
|
||||||
</label> -->
|
|
||||||
Click Connect below to start a new terminal session
|
|
||||||
<br /><br />
|
|
||||||
<button type="submit" id="terminal-connect">Connect</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="terminal-container">
|
|
||||||
<div id="terminal-info-container">
|
|
||||||
<div id="terminal-target"></div>
|
|
||||||
<div id="terminal-status"></div>
|
|
||||||
<div id="terminal-errmsg"></div>
|
|
||||||
<div id="terminal-control">
|
|
||||||
<button id="terminal-disconnect" type="button">Disconnect</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="terminal-view-container"></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
62
xterm.html
62
xterm.html
@ -90,6 +90,7 @@
|
|||||||
<script src="xterm-addon-fit.js"></script>
|
<script src="xterm-addon-fit.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const xt_mode = '{{ .Mode }}';
|
||||||
const conn_id = '{{ .ConnId }}';
|
const conn_id = '{{ .ConnId }}';
|
||||||
const route_id = '{{ .RouteId }}';
|
const route_id = '{{ .RouteId }}';
|
||||||
|
|
||||||
@ -99,13 +100,28 @@ window.onload = function(event) {
|
|||||||
const terminal_status = document.getElementById('terminal-status');
|
const terminal_status = document.getElementById('terminal-status');
|
||||||
const terminal_errmsg = document.getElementById('terminal-errmsg');
|
const terminal_errmsg = document.getElementById('terminal-errmsg');
|
||||||
const terminal_view_container = document.getElementById('terminal-view-container');
|
const terminal_view_container = document.getElementById('terminal-view-container');
|
||||||
|
const terminal_connect = document.getElementById('terminal-connect');
|
||||||
const terminal_disconnect = document.getElementById('terminal-disconnect');
|
const terminal_disconnect = document.getElementById('terminal-disconnect');
|
||||||
const login_container = document.getElementById('login-container');
|
const login_container = document.getElementById('login-container');
|
||||||
const login_form_title = document.getElementById('login-form-title');
|
const login_form_title = document.getElementById('login-form-title');
|
||||||
const login_form = document.getElementById('login-form');
|
const login_form = document.getElementById('login-form');
|
||||||
|
const login_ssh_part = document.getElementById('login-ssh-part');
|
||||||
|
const login_pts_part = document.getElementById('login-pts-part');
|
||||||
const username_field = document.getElementById('username');
|
const username_field = document.getElementById('username');
|
||||||
const password_field= document.getElementById('password');
|
const password_field= document.getElementById('password');
|
||||||
|
|
||||||
|
if (xt_mode == 'ssh') {
|
||||||
|
login_ssh_part.style.display = 'block';
|
||||||
|
username_field.disabled = false;
|
||||||
|
password_field.disabled = false;
|
||||||
|
login_pts_part.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
login_ssh_part.style.display = 'none';
|
||||||
|
username_field.disabled = true;
|
||||||
|
password_field.disabled = true;
|
||||||
|
login_pts_part.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
const term = new window.Terminal({
|
const term = new window.Terminal({
|
||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
//fontSize: 14,
|
//fontSize: 14,
|
||||||
@ -136,11 +152,19 @@ window.onload = function(event) {
|
|||||||
let pathname = window.location.pathname;
|
let pathname = window.location.pathname;
|
||||||
pathname = pathname.replace(/\/$/, '');
|
pathname = pathname.replace(/\/$/, '');
|
||||||
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
||||||
|
if (xt_mode == 'ssh')
|
||||||
url += pathname + `/server-conns/${conn_id}/routes/${route_id}`;
|
url += pathname + `/server-conns/${conn_id}/routes/${route_id}`;
|
||||||
|
else
|
||||||
|
url += pathname + `/session-info`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(url);
|
const resp = await fetch(url);
|
||||||
if (!resp.ok) throw new Error(`HTTP error in getting route(${conn_id},${route_id}) info - status ${resp.status}`);
|
if (!resp.ok) {
|
||||||
|
if (xt_mode == 'ssh')
|
||||||
|
throw new Error(`HTTP error in getting route(${conn_id},${route_id}) information - status ${resp.status}`);
|
||||||
|
else
|
||||||
|
throw new Error(`HTTP error in getting session information - status ${resp.status}`);
|
||||||
|
}
|
||||||
const route = await resp.json()
|
const route = await resp.json()
|
||||||
if ('client-peer-name' in route) {
|
if ('client-peer-name' in route) {
|
||||||
set_terminal_target(route['client-peer-name']) // change to the name
|
set_terminal_target(route['client-peer-name']) // change to the name
|
||||||
@ -154,11 +178,15 @@ window.onload = function(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let toggle_login_form = function(visible) {
|
let toggle_login_form = function(visible) {
|
||||||
if (visible) fetch_session_info();
|
if (visible && xt_mode == 'ssh') fetch_session_info();
|
||||||
login_container.style.visibility = (visible? 'visible': 'hidden');
|
login_container.style.visibility = (visible? 'visible': 'hidden');
|
||||||
terminal_disconnect.style.visibility = (visible? 'hidden': 'visible');
|
terminal_disconnect.style.visibility = (visible? 'hidden': 'visible');
|
||||||
if (visible) username_field.focus();
|
if (visible) {
|
||||||
else term.focus();
|
if (xt_mode == 'ssh') username_field.focus();
|
||||||
|
else terminal_connect.focus();
|
||||||
|
} else {
|
||||||
|
term.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_login_form(true);
|
toggle_login_form(true);
|
||||||
@ -169,14 +197,20 @@ window.onload = function(event) {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
toggle_login_form(false)
|
toggle_login_form(false)
|
||||||
|
|
||||||
const username = username_field.value.trim();
|
let username = '';
|
||||||
const password = password_field.value.trim();
|
let password = '';
|
||||||
|
|
||||||
|
if (xt_mode == 'ssh') {
|
||||||
|
username = username_field.value.trim();
|
||||||
|
password = password_field.value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
const prefix = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
const prefix = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||||
let pathname = window.location.pathname;
|
let pathname = window.location.pathname;
|
||||||
pathname = pathname.replace(/\/$/, '');
|
pathname = pathname.replace(/\/$/, '');
|
||||||
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
pathname = pathname.substring(0, pathname.lastIndexOf('/'));
|
||||||
let url = prefix + window.location.host + pathname + `/ws/${conn_id}/${route_id}`;
|
let url = prefix + window.location.host + pathname;
|
||||||
|
url += (xt_mode == 'ssh'? `/ws/${conn_id}/${route_id}`: `/ws`);
|
||||||
|
|
||||||
const socket = new WebSocket(url);
|
const socket = new WebSocket(url);
|
||||||
socket.binaryType = 'arraybuffer';
|
socket.binaryType = 'arraybuffer';
|
||||||
@ -257,15 +291,21 @@ window.onload = function(event) {
|
|||||||
<div id="login-form-container">
|
<div id="login-form-container">
|
||||||
<div id="login-form-title"></div>
|
<div id="login-form-title"></div>
|
||||||
<form id="login-form">
|
<form id="login-form">
|
||||||
|
<div id="login-ssh-part" style="display: none;">
|
||||||
<label>
|
<label>
|
||||||
Username: <input type="text" id="username" required />
|
Username: <input type="text" id="username" disabled required />
|
||||||
</label>
|
</label>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<label>
|
<label>
|
||||||
Password: <input type="password" id="password" required />
|
Password: <input type="password" id="password" disabled required />
|
||||||
</label>
|
</label>
|
||||||
<br /><br />
|
</div>
|
||||||
<button type="submit">Connect</button>
|
<div id="login-pts-part" style="display: none;">
|
||||||
|
Click Connect below to start a new terminal session
|
||||||
|
</div>
|
||||||
|
<div id="login-submit-part" style="padding-top: 1em;">
|
||||||
|
<button type="submit" id="terminal-connect">Connect</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user