renamed pts to pty to avoid name collision
This commit is contained in:
4
Makefile
4
Makefile
@ -15,7 +15,7 @@ SRCS=\
|
|||||||
client-ctl.go \
|
client-ctl.go \
|
||||||
client-metrics.go \
|
client-metrics.go \
|
||||||
client-peer.go \
|
client-peer.go \
|
||||||
client-pts.go \
|
client-pty.go \
|
||||||
hodu.go \
|
hodu.go \
|
||||||
hodu.pb.go \
|
hodu.pb.go \
|
||||||
hodu_grpc.pb.go \
|
hodu_grpc.pb.go \
|
||||||
@ -25,7 +25,7 @@ SRCS=\
|
|||||||
server-ctl.go \
|
server-ctl.go \
|
||||||
server-metrics.go \
|
server-metrics.go \
|
||||||
server-peer.go \
|
server-peer.go \
|
||||||
server-pts.go \
|
server-pty.go \
|
||||||
server-pxy.go \
|
server-pxy.go \
|
||||||
system.go \
|
system.go \
|
||||||
transform.go \
|
transform.go \
|
||||||
|
@ -109,7 +109,7 @@ type json_out_client_stats struct {
|
|||||||
ClientConns int64 `json:"client-conns"`
|
ClientConns int64 `json:"client-conns"`
|
||||||
ClientRoutes int64 `json:"client-routes"`
|
ClientRoutes int64 `json:"client-routes"`
|
||||||
ClientPeers int64 `json:"client-peers"`
|
ClientPeers int64 `json:"client-peers"`
|
||||||
ClientPtsSessions int64 `json:"client-pts-sessions"`
|
ClientPtySessions int64 `json:"client-pty-sessions"`
|
||||||
}
|
}
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
@ -1137,7 +1137,7 @@ func (ctl *client_ctl_stats) ServeHTTP(w http.ResponseWriter, req *http.Request)
|
|||||||
stats.ClientConns = c.stats.conns.Load()
|
stats.ClientConns = c.stats.conns.Load()
|
||||||
stats.ClientRoutes = c.stats.routes.Load()
|
stats.ClientRoutes = c.stats.routes.Load()
|
||||||
stats.ClientPeers = c.stats.peers.Load()
|
stats.ClientPeers = c.stats.peers.Load()
|
||||||
stats.ClientPtsSessions = c.stats.pts_sessions.Load()
|
stats.ClientPtySessions = c.stats.pty_sessions.Load()
|
||||||
status_code = WriteJsonRespHeader(w, http.StatusOK)
|
status_code = WriteJsonRespHeader(w, http.StatusOK)
|
||||||
if err = je.Encode(stats); err != nil { goto oops }
|
if err = je.Encode(stats); err != nil { goto oops }
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ type ClientCollector struct {
|
|||||||
ClientConns *prometheus.Desc
|
ClientConns *prometheus.Desc
|
||||||
ClientRoutes *prometheus.Desc
|
ClientRoutes *prometheus.Desc
|
||||||
ClientPeers *prometheus.Desc
|
ClientPeers *prometheus.Desc
|
||||||
PtsSessions *prometheus.Desc
|
PtySessions *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClientCollector returns a new ClientCollector with all prometheus.Desc initialized
|
// NewClientCollector returns a new ClientCollector with all prometheus.Desc initialized
|
||||||
@ -47,9 +47,9 @@ func NewClientCollector(client *Client) ClientCollector {
|
|||||||
"Number of client-side peers",
|
"Number of client-side peers",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
PtsSessions: prometheus.NewDesc(
|
PtySessions: prometheus.NewDesc(
|
||||||
prefix + "pts_sessions",
|
prefix + "pty_sessions",
|
||||||
"Number of pts sessions",
|
"Number of pty sessions",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ func (c ClientCollector) Describe(ch chan<- *prometheus.Desc) {
|
|||||||
ch <- c.ClientConns
|
ch <- c.ClientConns
|
||||||
ch <- c.ClientRoutes
|
ch <- c.ClientRoutes
|
||||||
ch <- c.ClientPeers
|
ch <- c.ClientPeers
|
||||||
ch <- c.PtsSessions
|
ch <- c.PtySessions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ClientCollector) Collect(ch chan<- prometheus.Metric) {
|
func (c ClientCollector) Collect(ch chan<- prometheus.Metric) {
|
||||||
@ -93,8 +93,8 @@ func (c ClientCollector) Collect(ch chan<- prometheus.Metric) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.PtsSessions,
|
c.PtySessions,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
float64(c.client.stats.pts_sessions.Load()),
|
float64(c.client.stats.pty_sessions.Load()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,28 +14,28 @@ import "sync"
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
import "text/template"
|
import "text/template"
|
||||||
|
|
||||||
import "github.com/creack/pty"
|
import pts "github.com/creack/pty"
|
||||||
import "golang.org/x/net/websocket"
|
import "golang.org/x/net/websocket"
|
||||||
import "golang.org/x/sys/unix"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
type client_pts_ws struct {
|
type client_pty_ws struct {
|
||||||
C *Client
|
C *Client
|
||||||
Id string
|
Id string
|
||||||
ws *websocket.Conn
|
ws *websocket.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type client_pts_xterm_file struct {
|
type client_pty_xterm_file struct {
|
||||||
client_ctl
|
client_ctl
|
||||||
file string
|
file string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
func (pts *client_pts_ws) Identity() string {
|
func (pty *client_pty_ws) Identity() string {
|
||||||
return pts.Id
|
return pty.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pts *client_pts_ws) send_ws_data(ws *websocket.Conn, type_val string, data string) error {
|
func (pty *client_pty_ws) send_ws_data(ws *websocket.Conn, type_val string, data string) error {
|
||||||
var msg []byte
|
var msg []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -45,26 +45,26 @@ func (pts *client_pts_ws) send_ws_data(ws *websocket.Conn, type_val string, data
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (pts *client_pts_ws) connect_pts(username string, password string) (*exec.Cmd, *os.File, error) {
|
func (pty *client_pty_ws) connect_pty(username string, password string) (*exec.Cmd, *os.File, error) {
|
||||||
var c *Client
|
var c *Client
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
var tty *os.File
|
var tty *os.File
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// username and password are not used yet.
|
// username and password are not used yet.
|
||||||
c = pts.C
|
c = pty.C
|
||||||
|
|
||||||
if c.pts_shell == "" {
|
if c.pty_shell == "" {
|
||||||
return nil, nil, fmt.Errorf("blank pts shell")
|
return nil, nil, fmt.Errorf("blank pty shell")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(c.pts_shell);
|
cmd = exec.Command(c.pty_shell);
|
||||||
if c.pts_user != "" {
|
if c.pty_user != "" {
|
||||||
var uid int
|
var uid int
|
||||||
var gid int
|
var gid int
|
||||||
var u *user.User
|
var u *user.User
|
||||||
|
|
||||||
u, err = user.Lookup(c.pts_user)
|
u, err = user.Lookup(c.pty_user)
|
||||||
if err != nil { return nil, nil, err }
|
if err != nil { return nil, nil, err }
|
||||||
|
|
||||||
uid, _ = strconv.Atoi(u.Uid)
|
uid, _ = strconv.Atoi(u.Uid)
|
||||||
@ -81,13 +81,13 @@ func (pts *client_pts_ws) connect_pts(username string, password string) (*exec.C
|
|||||||
"HOME=" + u.HomeDir,
|
"HOME=" + u.HomeDir,
|
||||||
"LOGNAME=" + u.Username,
|
"LOGNAME=" + u.Username,
|
||||||
"PATH=" + os.Getenv("PATH"),
|
"PATH=" + os.Getenv("PATH"),
|
||||||
"SHELL=" + c.pts_shell,
|
"SHELL=" + c.pty_shell,
|
||||||
"TERM=xterm",
|
"TERM=xterm",
|
||||||
"USER=" + u.Username,
|
"USER=" + u.Username,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tty, err = pty.Start(cmd)
|
tty, err = pts.Start(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ func (pts *client_pts_ws) connect_pts(username string, password string) (*exec.C
|
|||||||
return cmd, tty, nil
|
return cmd, tty, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pts *client_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
func (pty *client_pty_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
||||||
var c *Client
|
var c *Client
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var username string
|
var username string
|
||||||
@ -111,7 +111,7 @@ func (pts *client_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
var conn_ready_chan chan bool
|
var conn_ready_chan chan bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
c = pts.C
|
c = pty.C
|
||||||
req = ws.Request()
|
req = ws.Request()
|
||||||
conn_ready_chan = make(chan bool, 3)
|
conn_ready_chan = make(chan bool, 3)
|
||||||
|
|
||||||
@ -134,13 +134,13 @@ func (pts *client_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
unix.PollFd{Fd: int32(out.Fd()), Events: unix.POLLIN},
|
unix.PollFd{Fd: int32(out.Fd()), Events: unix.POLLIN},
|
||||||
}
|
}
|
||||||
|
|
||||||
c.stats.pts_sessions.Add(1)
|
c.stats.pty_sessions.Add(1)
|
||||||
buf = make([]byte, 2048)
|
buf = make([]byte, 2048)
|
||||||
for {
|
for {
|
||||||
n, err = unix.Poll(poll_fds, -1) // -1 means wait indefinitely
|
n, err = unix.Poll(poll_fds, -1) // -1 means wait indefinitely
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, unix.EINTR) { continue }
|
if errors.Is(err, unix.EINTR) { continue }
|
||||||
c.log.Write("", LOG_ERROR, "[%s] Failed to poll pts stdout - %s", req.RemoteAddr, err.Error())
|
c.log.Write("", LOG_ERROR, "[%s] Failed to poll pty stdout - %s", req.RemoteAddr, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n == 0 { // timed out
|
if n == 0 { // timed out
|
||||||
@ -148,7 +148,7 @@ func (pts *client_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (poll_fds[0].Revents & (unix.POLLERR | unix.POLLHUP | unix.POLLNVAL)) != 0 {
|
if (poll_fds[0].Revents & (unix.POLLERR | unix.POLLHUP | unix.POLLNVAL)) != 0 {
|
||||||
c.log.Write(pts.Id, LOG_DEBUG, "[%s] EOF detected on pts stdout", req.RemoteAddr)
|
c.log.Write(pty.Id, LOG_DEBUG, "[%s] EOF detected on pty stdout", req.RemoteAddr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,20 +156,20 @@ func (pts *client_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
n, err = out.Read(buf)
|
n, err = out.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, io.EOF) {
|
if !errors.Is(err, io.EOF) {
|
||||||
c.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to read pts stdout - %s", req.RemoteAddr, err.Error())
|
c.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to read pty stdout - %s", req.RemoteAddr, err.Error())
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
err = pts.send_ws_data(ws, "iov", string(buf[:n]))
|
err = pty.send_ws_data(ws, "iov", string(buf[:n]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to send to websocket - %s", req.RemoteAddr, err.Error())
|
c.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to send to websocket - %s", req.RemoteAddr, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.stats.pts_sessions.Add(-1)
|
c.stats.pty_sessions.Add(-1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -194,18 +194,18 @@ ws_recv_loop:
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
cmd, tty, err = pts.connect_pts(username, password)
|
cmd, tty, err = pty.connect_pty(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to connect pts - %s", req.RemoteAddr, err.Error())
|
c.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to connect pty - %s", req.RemoteAddr, err.Error())
|
||||||
pts.send_ws_data(ws, "error", err.Error())
|
pty.send_ws_data(ws, "error", err.Error())
|
||||||
ws.Close() // dirty way to flag out the error
|
ws.Close() // dirty way to flag out the error
|
||||||
} else {
|
} else {
|
||||||
err = pts.send_ws_data(ws, "status", "opened")
|
err = pty.send_ws_data(ws, "status", "opened")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to write opened event to websocket - %s", req.RemoteAddr, err.Error())
|
c.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to write opened event to websocket - %s", req.RemoteAddr, err.Error())
|
||||||
ws.Close() // dirty way to flag out the error
|
ws.Close() // dirty way to flag out the error
|
||||||
} else {
|
} else {
|
||||||
c.log.Write(pts.Id, LOG_DEBUG, "[%s] Opened pts session", req.RemoteAddr)
|
c.log.Write(pty.Id, LOG_DEBUG, "[%s] Opened pty session", req.RemoteAddr)
|
||||||
out = tty
|
out = tty
|
||||||
in = tty
|
in = tty
|
||||||
conn_ready_chan <- true
|
conn_ready_chan <- true
|
||||||
@ -235,8 +235,8 @@ ws_recv_loop:
|
|||||||
var cols int
|
var cols int
|
||||||
rows, _ = strconv.Atoi(ev.Data[0])
|
rows, _ = strconv.Atoi(ev.Data[0])
|
||||||
cols, _ = strconv.Atoi(ev.Data[1])
|
cols, _ = strconv.Atoi(ev.Data[1])
|
||||||
pty.Setsize(tty, &pty.Winsize{Rows: uint16(rows), Cols: uint16(cols)})
|
pts.Setsize(tty, &pts.Winsize{Rows: uint16(rows), Cols: uint16(cols)})
|
||||||
c.log.Write(pts.Id, LOG_DEBUG, "[%s] Resized terminal to %d,%d", req.RemoteAddr, rows, cols)
|
c.log.Write(pty.Id, LOG_DEBUG, "[%s] Resized terminal to %d,%d", req.RemoteAddr, rows, cols)
|
||||||
// ignore error
|
// ignore error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ ws_recv_loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tty != nil {
|
if tty != nil {
|
||||||
err = pts.send_ws_data(ws, "status", "closed")
|
err = pty.send_ws_data(ws, "status", "closed")
|
||||||
if err != nil { goto done }
|
if err != nil { goto done }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ done:
|
|||||||
if tty != nil { tty.Close() }
|
if tty != nil { tty.Close() }
|
||||||
if cmd != nil { cmd.Wait() }
|
if cmd != nil { cmd.Wait() }
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
c.log.Write(pts.Id, LOG_DEBUG, "[%s] Ended pts session", req.RemoteAddr)
|
c.log.Write(pty.Id, LOG_DEBUG, "[%s] Ended pty session", req.RemoteAddr)
|
||||||
|
|
||||||
return http.StatusOK, err
|
return http.StatusOK, err
|
||||||
}
|
}
|
||||||
@ -268,14 +268,14 @@ done:
|
|||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
func (pty *client_pty_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 = pty.c
|
||||||
|
|
||||||
switch pts.file {
|
switch pty.file {
|
||||||
case "xterm.js":
|
case "xterm.js":
|
||||||
status_code = WriteJsRespHeader(w, http.StatusOK)
|
status_code = WriteJsRespHeader(w, http.StatusOK)
|
||||||
w.Write(xterm_js)
|
w.Write(xterm_js)
|
||||||
@ -301,7 +301,7 @@ func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
||||||
tmpl.Execute(w,
|
tmpl.Execute(w,
|
||||||
&xterm_session_info{
|
&xterm_session_info{
|
||||||
Mode: "pts",
|
Mode: "pty",
|
||||||
ConnId: "-1",
|
ConnId: "-1",
|
||||||
RouteId: "-1",
|
RouteId: "-1",
|
||||||
})
|
})
|
||||||
@ -315,9 +315,9 @@ func (pts *client_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if strings.HasPrefix(pts.file, "_redir:") {
|
if strings.HasPrefix(pty.file, "_redir:") {
|
||||||
status_code = http.StatusMovedPermanently
|
status_code = http.StatusMovedPermanently
|
||||||
w.Header().Set("Location", pts.file[7:])
|
w.Header().Set("Location", pty.file[7:])
|
||||||
w.WriteHeader(status_code)
|
w.WriteHeader(status_code)
|
||||||
} else {
|
} else {
|
||||||
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
75
client.go
75
client.go
@ -146,11 +146,11 @@ type Client struct {
|
|||||||
conns atomic.Int64
|
conns atomic.Int64
|
||||||
routes atomic.Int64
|
routes atomic.Int64
|
||||||
peers atomic.Int64
|
peers atomic.Int64
|
||||||
pts_sessions atomic.Int64
|
pty_sessions atomic.Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
pts_user string
|
pty_user string
|
||||||
pts_shell string
|
pty_shell string
|
||||||
xterm_html string
|
xterm_html string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1348,6 +1348,16 @@ start_over:
|
|||||||
cts.C.log.Write(cts.Sid, LOG_ERROR, "Invalid conn_notice packet from %s", cts.remote_addr_p)
|
cts.C.log.Write(cts.Sid, LOG_ERROR, "Invalid conn_notice packet from %s", cts.remote_addr_p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case PACKET_KIND_RPTY_START:
|
||||||
|
// TODO:
|
||||||
|
case PACKET_KIND_RPTY_STOP:
|
||||||
|
// TODO:
|
||||||
|
case PACKET_KIND_RPTY_DATA:
|
||||||
|
// TODO:
|
||||||
|
case PACKET_KIND_RPTY_EOF:
|
||||||
|
// TODO:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// do nothing. ignore the rest
|
// do nothing. ignore the rest
|
||||||
}
|
}
|
||||||
@ -1646,28 +1656,27 @@ func NewClient(ctx context.Context, name string, logger Logger, cfg *ClientConfi
|
|||||||
c.ctl_mux.Handle("/_ctl/events",
|
c.ctl_mux.Handle("/_ctl/events",
|
||||||
c.SafeWrapWebsocketHandler(c.WrapWebsocketHandler(&client_ctl_ws{client_ctl{c: &c, id: HS_ID_CTL}})))
|
c.SafeWrapWebsocketHandler(c.WrapWebsocketHandler(&client_ctl_ws{client_ctl{c: &c, id: HS_ID_CTL}})))
|
||||||
|
|
||||||
|
c.ctl_mux.Handle("/_pty/ws",
|
||||||
|
c.SafeWrapWebsocketHandler(c.WrapWebsocketHandler(&client_pty_ws{C: &c, Id: HS_ID_CTL})))
|
||||||
|
|
||||||
c.ctl_mux.Handle("/_pts/ws",
|
c.ctl_mux.Handle("/_pty/xterm.js",
|
||||||
c.SafeWrapWebsocketHandler(c.WrapWebsocketHandler(&client_pts_ws{C: &c, Id: HS_ID_CTL})))
|
c.WrapHttpHandler(&client_pty_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm.js"}))
|
||||||
|
c.ctl_mux.Handle("/_pty/xterm.js/",
|
||||||
c.ctl_mux.Handle("/_pts/xterm.js",
|
c.WrapHttpHandler(&client_pty_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: "xterm.js"}))
|
c.ctl_mux.Handle("/_pty/xterm-addon-fit.js",
|
||||||
c.ctl_mux.Handle("/_pts/xterm.js/",
|
c.WrapHttpHandler(&client_pty_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm-addon-fit.js"}))
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_forbidden"}))
|
c.ctl_mux.Handle("/_pty/xterm-addon-fit.js/",
|
||||||
c.ctl_mux.Handle("/_pts/xterm-addon-fit.js",
|
c.WrapHttpHandler(&client_pty_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: "xterm-addon-fit.js"}))
|
c.ctl_mux.Handle("/_pty/xterm.css",
|
||||||
c.ctl_mux.Handle("/_pts/xterm-addon-fit.js/",
|
c.WrapHttpHandler(&client_pty_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: "_forbidden"}))
|
c.ctl_mux.Handle("/_pty/xterm.css/",
|
||||||
c.ctl_mux.Handle("/_pts/xterm.css",
|
c.WrapHttpHandler(&client_pty_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: "xterm.css"}))
|
c.ctl_mux.Handle("/_pty/xterm.html",
|
||||||
c.ctl_mux.Handle("/_pts/xterm.css/",
|
c.WrapHttpHandler(&client_pty_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "xterm.html"}))
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_forbidden"}))
|
c.ctl_mux.Handle("/_pty/xterm.html/", // without this forbidden, /_pty/xterm.js/ access resulted in xterm.html.
|
||||||
c.ctl_mux.Handle("/_pts/xterm.html",
|
c.WrapHttpHandler(&client_pty_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: "xterm.html"}))
|
c.ctl_mux.Handle("/_pty/",
|
||||||
c.ctl_mux.Handle("/_pts/xterm.html/", // without this forbidden, /_pts/xterm.js/ access resulted in xterm.html.
|
c.WrapHttpHandler(&client_pty_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_redir:xterm.html"}))
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_forbidden"}))
|
|
||||||
c.ctl_mux.Handle("/_pts/",
|
|
||||||
c.WrapHttpHandler(&client_pts_xterm_file{client_ctl: client_ctl{c: &c, id: HS_ID_CTL}, file: "_redir:xterm.html"}))
|
|
||||||
|
|
||||||
c.ctl_addr = make([]string, len(cfg.CtlAddrs))
|
c.ctl_addr = make([]string, len(cfg.CtlAddrs))
|
||||||
c.ctl = make([]*http.Server, len(cfg.CtlAddrs))
|
c.ctl = make([]*http.Server, len(cfg.CtlAddrs))
|
||||||
@ -1688,7 +1697,7 @@ func NewClient(ctx context.Context, name string, logger Logger, cfg *ClientConfi
|
|||||||
c.stats.conns.Store(0)
|
c.stats.conns.Store(0)
|
||||||
c.stats.routes.Store(0)
|
c.stats.routes.Store(0)
|
||||||
c.stats.peers.Store(0)
|
c.stats.peers.Store(0)
|
||||||
c.stats.pts_sessions.Store(0)
|
c.stats.pty_sessions.Store(0)
|
||||||
|
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
@ -1985,20 +1994,20 @@ func (c *Client) GetXtermHtml() string {
|
|||||||
return c.xterm_html
|
return c.xterm_html
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SetPtsUser(user string) {
|
func (c *Client) SetPtyUser(user string) {
|
||||||
c.pts_user = user
|
c.pty_user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetPtsUser() string {
|
func (c *Client) GetPtyUser() string {
|
||||||
return c.pts_user
|
return c.pty_user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SetPtsShell(user string) {
|
func (c *Client) SetPtyShell(user string) {
|
||||||
c.pts_shell = user
|
c.pty_shell = user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetPtsShell() string {
|
func (c *Client) GetPtyShell() string {
|
||||||
return c.pts_shell
|
return c.pty_shell
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) RunCtlTask(wg *sync.WaitGroup) {
|
func (c *Client) RunCtlTask(wg *sync.WaitGroup) {
|
||||||
|
@ -94,8 +94,8 @@ type ServerAppConfig struct {
|
|||||||
LogRotate int `yaml:"log-rotate"`
|
LogRotate int `yaml:"log-rotate"`
|
||||||
MaxPeers int `yaml:"max-peer-conns"` // maximum number of connections from peers
|
MaxPeers int `yaml:"max-peer-conns"` // maximum number of connections from peers
|
||||||
MaxRpcConns int `yaml:"max-rpc-conns"` // maximum number of rpc connections
|
MaxRpcConns int `yaml:"max-rpc-conns"` // maximum number of rpc connections
|
||||||
PtsUser string `yaml:"pts-user"`
|
PtyUser string `yaml:"pty-user"`
|
||||||
PtsShell string `yaml:"pts-shell"`
|
PtyShell string `yaml:"pty-shell"`
|
||||||
XtermHtmlFile string `yaml:"xterm-html-file"`
|
XtermHtmlFile string `yaml:"xterm-html-file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +107,10 @@ type ClientAppConfig struct {
|
|||||||
MaxPeers int `yaml:"max-peer-conns"` // maximum number of connections from peers
|
MaxPeers int `yaml:"max-peer-conns"` // maximum number of connections from peers
|
||||||
MaxRpcConns int `yaml:"max-rpc-conns"` // maximum number of rpc connections
|
MaxRpcConns int `yaml:"max-rpc-conns"` // maximum number of rpc connections
|
||||||
PeerConnTmout time.Duration `yaml:"peer-conn-timeout"`
|
PeerConnTmout time.Duration `yaml:"peer-conn-timeout"`
|
||||||
PtsUser string `yaml:"pts-user"`
|
TokenText string `yaml:"token-text"`
|
||||||
PtsShell string `yaml:"pts-shell"`
|
TokenFile string `yaml:"token-file"`
|
||||||
|
PtyUser string `yaml:"pty-user"`
|
||||||
|
PtyShell string `yaml:"pty-shell"`
|
||||||
XtermHtmlFile string `yaml:"xterm-html-file"`
|
XtermHtmlFile string `yaml:"xterm-html-file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
cmd/main.go
35
cmd/main.go
@ -97,8 +97,8 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, wpx
|
|||||||
var logmask hodu.LogMask
|
var logmask hodu.LogMask
|
||||||
var logfile_maxsize int64
|
var logfile_maxsize int64
|
||||||
var logfile_rotate int
|
var logfile_rotate int
|
||||||
var pts_user string
|
var pty_user string
|
||||||
var pts_shell string
|
var pty_shell string
|
||||||
var xterm_html_file string
|
var xterm_html_file string
|
||||||
var xterm_html string
|
var xterm_html string
|
||||||
var err error
|
var err error
|
||||||
@ -135,8 +135,8 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, wpx
|
|||||||
config.RpcMaxConns = cfg.APP.MaxRpcConns
|
config.RpcMaxConns = cfg.APP.MaxRpcConns
|
||||||
config.MaxPeers = cfg.APP.MaxPeers
|
config.MaxPeers = cfg.APP.MaxPeers
|
||||||
|
|
||||||
pts_user = cfg.APP.PtsUser
|
pty_user = cfg.APP.PtyUser
|
||||||
pts_shell = cfg.APP.PtsShell
|
pty_shell = cfg.APP.PtyShell
|
||||||
xterm_html_file = cfg.APP.XtermHtmlFile
|
xterm_html_file = cfg.APP.XtermHtmlFile
|
||||||
|
|
||||||
logmask = log_strings_to_mask(cfg.APP.LogMask)
|
logmask = log_strings_to_mask(cfg.APP.LogMask)
|
||||||
@ -172,8 +172,8 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, wpx
|
|||||||
return fmt.Errorf("failed to create server - %s", err.Error())
|
return fmt.Errorf("failed to create server - %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if pts_user != "" { s.SetPtsUser(pts_user) }
|
if pty_user != "" { s.SetPtyUser(pty_user) }
|
||||||
if pts_shell != "" { s.SetPtsShell(pts_shell) }
|
if pty_shell != "" { s.SetPtyShell(pty_shell) }
|
||||||
if xterm_html != "" { s.SetXtermHtml(xterm_html) }
|
if xterm_html != "" { s.SetXtermHtml(xterm_html) }
|
||||||
|
|
||||||
s.StartService(nil)
|
s.StartService(nil)
|
||||||
@ -259,8 +259,8 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
var logmask hodu.LogMask
|
var logmask hodu.LogMask
|
||||||
var logfile_maxsize int64
|
var logfile_maxsize int64
|
||||||
var logfile_rotate int
|
var logfile_rotate int
|
||||||
var pts_user string
|
var pty_user string
|
||||||
var pts_shell string
|
var pty_shell string
|
||||||
var xterm_html_file string
|
var xterm_html_file string
|
||||||
var xterm_html string
|
var xterm_html string
|
||||||
var i int
|
var i int
|
||||||
@ -292,12 +292,23 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
if logfile == "" { logfile = cfg.APP.LogFile }
|
if logfile == "" { logfile = cfg.APP.LogFile }
|
||||||
logfile_maxsize = cfg.APP.LogMaxSize
|
logfile_maxsize = cfg.APP.LogMaxSize
|
||||||
logfile_rotate = cfg.APP.LogRotate
|
logfile_rotate = cfg.APP.LogRotate
|
||||||
pts_user = cfg.APP.PtsUser
|
pty_user = cfg.APP.PtyUser
|
||||||
pts_shell = cfg.APP.PtsShell
|
pty_shell = cfg.APP.PtyShell
|
||||||
xterm_html_file = cfg.APP.XtermHtmlFile
|
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
|
||||||
|
|
||||||
|
if cfg.APP.TokenText != "" {
|
||||||
|
config.Token = cfg.APP.TokenText
|
||||||
|
} else if cfg.APP.TokenFile != "" {
|
||||||
|
var bytes []byte
|
||||||
|
bytes, err = os.ReadFile(cfg.APP.TokenFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read token file - %s", err.Error())
|
||||||
|
}
|
||||||
|
config.Token = string(bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlke the server, we allow the client to start with no rpc address.
|
// unlke the server, we allow the client to start with no rpc address.
|
||||||
@ -331,8 +342,8 @@ func client_main(ctl_addrs []string, rpc_addrs []string, route_configs []string,
|
|||||||
|
|
||||||
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 pty_user != "" { c.SetPtyUser(pty_user) }
|
||||||
if pts_shell != "" { c.SetPtsShell(pts_shell) }
|
if pty_shell != "" { c.SetPtyShell(pty_shell) }
|
||||||
if xterm_html != "" { c.SetXtermHtml(xterm_html) }
|
if xterm_html != "" { c.SetXtermHtml(xterm_html) }
|
||||||
|
|
||||||
c.StartService(&cc)
|
c.StartService(&cc)
|
||||||
|
328
hodu.pb.go
328
hodu.pb.go
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.5
|
// protoc-gen-go v1.36.7
|
||||||
// protoc v3.19.6
|
// protoc v3.19.6
|
||||||
// source: hodu.proto
|
// source: hodu.proto
|
||||||
|
|
||||||
@ -101,6 +101,13 @@ const (
|
|||||||
PACKET_KIND_CONN_DESC PACKET_KIND = 11
|
PACKET_KIND_CONN_DESC PACKET_KIND = 11
|
||||||
PACKET_KIND_CONN_ERROR PACKET_KIND = 12
|
PACKET_KIND_CONN_ERROR PACKET_KIND = 12
|
||||||
PACKET_KIND_CONN_NOTICE PACKET_KIND = 13
|
PACKET_KIND_CONN_NOTICE PACKET_KIND = 13
|
||||||
|
PACKET_KIND_RPTY_START PACKET_KIND = 14
|
||||||
|
PACKET_KIND_RPTY_STOP PACKET_KIND = 15
|
||||||
|
PACKET_KIND_RPTY_STARTED PACKET_KIND = 16
|
||||||
|
PACKET_KIND_RPTY_STOPPED PACKET_KIND = 17
|
||||||
|
PACKET_KIND_RPTY_ABORTED PACKET_KIND = 18
|
||||||
|
PACKET_KIND_RPTY_EOF PACKET_KIND = 19
|
||||||
|
PACKET_KIND_RPTY_DATA PACKET_KIND = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for PACKET_KIND.
|
// Enum value maps for PACKET_KIND.
|
||||||
@ -119,6 +126,13 @@ var (
|
|||||||
11: "CONN_DESC",
|
11: "CONN_DESC",
|
||||||
12: "CONN_ERROR",
|
12: "CONN_ERROR",
|
||||||
13: "CONN_NOTICE",
|
13: "CONN_NOTICE",
|
||||||
|
14: "RPTY_START",
|
||||||
|
15: "RPTY_STOP",
|
||||||
|
16: "RPTY_STARTED",
|
||||||
|
17: "RPTY_STOPPED",
|
||||||
|
18: "RPTY_ABORTED",
|
||||||
|
19: "RPTY_EOF",
|
||||||
|
20: "RPTY_DATA",
|
||||||
}
|
}
|
||||||
PACKET_KIND_value = map[string]int32{
|
PACKET_KIND_value = map[string]int32{
|
||||||
"RESERVED": 0,
|
"RESERVED": 0,
|
||||||
@ -134,6 +148,13 @@ var (
|
|||||||
"CONN_DESC": 11,
|
"CONN_DESC": 11,
|
||||||
"CONN_ERROR": 12,
|
"CONN_ERROR": 12,
|
||||||
"CONN_NOTICE": 13,
|
"CONN_NOTICE": 13,
|
||||||
|
"RPTY_START": 14,
|
||||||
|
"RPTY_STOP": 15,
|
||||||
|
"RPTY_STARTED": 16,
|
||||||
|
"RPTY_STOPPED": 17,
|
||||||
|
"RPTY_ABORTED": 18,
|
||||||
|
"RPTY_EOF": 19,
|
||||||
|
"RPTY_DATA": 20,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -219,24 +240,24 @@ func (x *Seed) GetFlags() uint64 {
|
|||||||
type RouteDesc struct {
|
type RouteDesc struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
RouteId uint32 `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"`
|
RouteId uint32 `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"`
|
||||||
// C->S(ROUTE_START): client-side peer address
|
// C->S(ROUTE_START/STOP): client-side peer address
|
||||||
// S->C(ROUTE_STARTED): server-side listening address
|
// S->C(ROUTE_STARTED/STOPPED): server-side listening address
|
||||||
TargetAddrStr string `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"`
|
TargetAddrStr string `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"`
|
||||||
// C->S(ROUTE_START): human-readable name of client-side peer
|
// C->S(ROUTE_START/STOPPED): human-readable name of client-side peer
|
||||||
// S->C(ROUTE_STARTED): clone as sent by C
|
// S->C(ROUTE_STARTED/STOPPED): clone as sent by C
|
||||||
TargetName string `protobuf:"bytes,3,opt,name=TargetName,proto3" json:"TargetName,omitempty"`
|
TargetName string `protobuf:"bytes,3,opt,name=TargetName,proto3" json:"TargetName,omitempty"`
|
||||||
// C->S(ROUTE_START): desired listening option on the server-side(e.g. tcp, tcp4, tcp6) +
|
// C->S(ROUTE_START): requested listening option on the server-side(e.g. tcp, tcp4, tcp6) +
|
||||||
//
|
//
|
||||||
// hint to the service-side peer(e.g. local) +
|
// hint to the service-side peer(e.g. local) +
|
||||||
// hint to the client-side peer(e.g. tty, http, https)
|
// hint to the client-side peer(e.g. tty, http, https)
|
||||||
//
|
//
|
||||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
// S->C(ROUTE_STARTED): cloned as sent by C.
|
||||||
ServiceOption uint32 `protobuf:"varint,4,opt,name=ServiceOption,proto3" json:"ServiceOption,omitempty"`
|
ServiceOption uint32 `protobuf:"varint,4,opt,name=ServiceOption,proto3" json:"ServiceOption,omitempty"`
|
||||||
// C->S(ROUTE_START): desired lisening address on the service-side
|
// C->S(ROUTE_START): requested lisening address on the service-side
|
||||||
// S->C(ROUTE_STARTED): cloned as sent by C
|
// S->C(ROUTE_STARTED): cloned as sent by C
|
||||||
ServiceAddrStr string `protobuf:"bytes,5,opt,name=ServiceAddrStr,proto3" json:"ServiceAddrStr,omitempty"`
|
ServiceAddrStr string `protobuf:"bytes,5,opt,name=ServiceAddrStr,proto3" json:"ServiceAddrStr,omitempty"`
|
||||||
// C->S(ROUTE_START): permitted network of server-side peers.
|
// C->S(ROUTE_START): requested permitted network of server-side peers.
|
||||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
// S->C(ROUTE_STARTED): actual permitted network of server-side peers
|
||||||
ServiceNetStr string `protobuf:"bytes,6,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"`
|
ServiceNetStr string `protobuf:"bytes,6,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -582,6 +603,58 @@ func (x *ConnNotice) GetText() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RptyEvent struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Token string `protobuf:"bytes,1,opt,name=Token,proto3" json:"Token,omitempty"`
|
||||||
|
Data []byte `protobuf:"bytes,2,opt,name=Data,proto3" json:"Data,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RptyEvent) Reset() {
|
||||||
|
*x = RptyEvent{}
|
||||||
|
mi := &file_hodu_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RptyEvent) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RptyEvent) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *RptyEvent) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_hodu_proto_msgTypes[7]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use RptyEvent.ProtoReflect.Descriptor instead.
|
||||||
|
func (*RptyEvent) Descriptor() ([]byte, []int) {
|
||||||
|
return file_hodu_proto_rawDescGZIP(), []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RptyEvent) GetToken() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Token
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RptyEvent) GetData() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Data
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Kind PACKET_KIND `protobuf:"varint,1,opt,name=Kind,proto3,enum=PACKET_KIND" json:"Kind,omitempty"`
|
Kind PACKET_KIND `protobuf:"varint,1,opt,name=Kind,proto3,enum=PACKET_KIND" json:"Kind,omitempty"`
|
||||||
@ -593,6 +666,7 @@ type Packet struct {
|
|||||||
// *Packet_Conn
|
// *Packet_Conn
|
||||||
// *Packet_ConnErr
|
// *Packet_ConnErr
|
||||||
// *Packet_ConnNoti
|
// *Packet_ConnNoti
|
||||||
|
// *Packet_Rpty
|
||||||
U isPacket_U `protobuf_oneof:"U"`
|
U isPacket_U `protobuf_oneof:"U"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -600,7 +674,7 @@ type Packet struct {
|
|||||||
|
|
||||||
func (x *Packet) Reset() {
|
func (x *Packet) Reset() {
|
||||||
*x = Packet{}
|
*x = Packet{}
|
||||||
mi := &file_hodu_proto_msgTypes[7]
|
mi := &file_hodu_proto_msgTypes[8]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -612,7 +686,7 @@ func (x *Packet) String() string {
|
|||||||
func (*Packet) ProtoMessage() {}
|
func (*Packet) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Packet) ProtoReflect() protoreflect.Message {
|
func (x *Packet) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hodu_proto_msgTypes[7]
|
mi := &file_hodu_proto_msgTypes[8]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -625,7 +699,7 @@ func (x *Packet) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Packet.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Packet.ProtoReflect.Descriptor instead.
|
||||||
func (*Packet) Descriptor() ([]byte, []int) {
|
func (*Packet) Descriptor() ([]byte, []int) {
|
||||||
return file_hodu_proto_rawDescGZIP(), []int{7}
|
return file_hodu_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Packet) GetKind() PACKET_KIND {
|
func (x *Packet) GetKind() PACKET_KIND {
|
||||||
@ -696,6 +770,15 @@ func (x *Packet) GetConnNoti() *ConnNotice {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Packet) GetRpty() *RptyEvent {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.U.(*Packet_Rpty); ok {
|
||||||
|
return x.Rpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type isPacket_U interface {
|
type isPacket_U interface {
|
||||||
isPacket_U()
|
isPacket_U()
|
||||||
}
|
}
|
||||||
@ -724,6 +807,10 @@ type Packet_ConnNoti struct {
|
|||||||
ConnNoti *ConnNotice `protobuf:"bytes,7,opt,name=ConnNoti,proto3,oneof"`
|
ConnNoti *ConnNotice `protobuf:"bytes,7,opt,name=ConnNoti,proto3,oneof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Packet_Rpty struct {
|
||||||
|
Rpty *RptyEvent `protobuf:"bytes,8,opt,name=Rpty,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
func (*Packet_Route) isPacket_U() {}
|
func (*Packet_Route) isPacket_U() {}
|
||||||
|
|
||||||
func (*Packet_Peer) isPacket_U() {}
|
func (*Packet_Peer) isPacket_U() {}
|
||||||
@ -736,94 +823,96 @@ func (*Packet_ConnErr) isPacket_U() {}
|
|||||||
|
|
||||||
func (*Packet_ConnNoti) isPacket_U() {}
|
func (*Packet_ConnNoti) isPacket_U() {}
|
||||||
|
|
||||||
|
func (*Packet_Rpty) isPacket_U() {}
|
||||||
|
|
||||||
var File_hodu_proto protoreflect.FileDescriptor
|
var File_hodu_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_hodu_proto_rawDesc = string([]byte{
|
const file_hodu_proto_rawDesc = "" +
|
||||||
0x0a, 0x0a, 0x68, 0x6f, 0x64, 0x75, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x36, 0x0a, 0x04,
|
"\n" +
|
||||||
0x53, 0x65, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
|
"\n" +
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14,
|
"hodu.proto\"6\n" +
|
||||||
0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x46,
|
"\x04Seed\x12\x18\n" +
|
||||||
0x6c, 0x61, 0x67, 0x73, 0x22, 0xdf, 0x01, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65,
|
"\aVersion\x18\x01 \x01(\rR\aVersion\x12\x14\n" +
|
||||||
0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
|
"\x05Flags\x18\x02 \x01(\x04R\x05Flags\"\xdf\x01\n" +
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d,
|
"\tRouteDesc\x12\x18\n" +
|
||||||
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x02, 0x20,
|
"\aRouteId\x18\x01 \x01(\rR\aRouteId\x12$\n" +
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53,
|
"\rTargetAddrStr\x18\x02 \x01(\tR\rTargetAddrStr\x12\x1e\n" +
|
||||||
0x74, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65,
|
"\n" +
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61,
|
"TargetName\x18\x03 \x01(\tR\n" +
|
||||||
0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74,
|
"TargetName\x12$\n" +
|
||||||
0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69,
|
"\rServiceOption\x18\x04 \x01(\rR\rServiceOption\x12&\n" +
|
||||||
0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76,
|
"\x0eServiceAddrStr\x18\x05 \x01(\tR\x0eServiceAddrStr\x12$\n" +
|
||||||
0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
"\rServiceNetStr\x18\x06 \x01(\tR\rServiceNetStr\"\x86\x01\n" +
|
||||||
0x52, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72,
|
"\bPeerDesc\x12\x18\n" +
|
||||||
0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x53, 0x74,
|
"\aRouteId\x18\x01 \x01(\rR\aRouteId\x12\x16\n" +
|
||||||
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
"\x06PeerId\x18\x02 \x01(\rR\x06PeerId\x12$\n" +
|
||||||
0x4e, 0x65, 0x74, 0x53, 0x74, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44,
|
"\rRemoteAddrStr\x18\x03 \x01(\tR\rRemoteAddrStr\x12\"\n" +
|
||||||
0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01,
|
"\fLocalAddrStr\x18\x04 \x01(\tR\fLocalAddrStr\"P\n" +
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a,
|
"\bPeerData\x12\x18\n" +
|
||||||
0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50,
|
"\aRouteId\x18\x01 \x01(\rR\aRouteId\x12\x16\n" +
|
||||||
0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41,
|
"\x06PeerId\x18\x02 \x01(\rR\x06PeerId\x12\x12\n" +
|
||||||
0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65,
|
"\x04Data\x18\x03 \x01(\fR\x04Data\" \n" +
|
||||||
0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x4c,
|
"\bConnDesc\x12\x14\n" +
|
||||||
0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
|
"\x05Token\x18\x01 \x01(\tR\x05Token\"9\n" +
|
||||||
0x09, 0x52, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x22,
|
"\tConnError\x12\x18\n" +
|
||||||
0x50, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x52,
|
"\aErrorId\x18\x01 \x01(\rR\aErrorId\x12\x12\n" +
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f,
|
"\x04Text\x18\x02 \x01(\tR\x04Text\" \n" +
|
||||||
0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18,
|
"\n" +
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a,
|
"ConnNotice\x12\x12\n" +
|
||||||
0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74,
|
"\x04Text\x18\x01 \x01(\tR\x04Text\"5\n" +
|
||||||
0x61, 0x22, 0x20, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x12, 0x14, 0x0a,
|
"\tRptyEvent\x12\x14\n" +
|
||||||
0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f,
|
"\x05Token\x18\x01 \x01(\tR\x05Token\x12\x12\n" +
|
||||||
0x6b, 0x65, 0x6e, 0x22, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72,
|
"\x04Data\x18\x02 \x01(\fR\x04Data\"\xab\x02\n" +
|
||||||
0x12, 0x18, 0x0a, 0x07, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
"\x06Packet\x12 \n" +
|
||||||
0x0d, 0x52, 0x07, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x65,
|
"\x04Kind\x18\x01 \x01(\x0e2\f.PACKET_KINDR\x04Kind\x12\"\n" +
|
||||||
0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x65, 0x78, 0x74, 0x22, 0x20,
|
"\x05Route\x18\x02 \x01(\v2\n" +
|
||||||
0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
".RouteDescH\x00R\x05Route\x12\x1f\n" +
|
||||||
0x54, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x65, 0x78, 0x74,
|
"\x04Peer\x18\x03 \x01(\v2\t.PeerDescH\x00R\x04Peer\x12\x1f\n" +
|
||||||
0x22, 0x89, 0x02, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x4b,
|
"\x04Data\x18\x04 \x01(\v2\t.PeerDataH\x00R\x04Data\x12\x1f\n" +
|
||||||
0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x50, 0x41, 0x43, 0x4b,
|
"\x04Conn\x18\x05 \x01(\v2\t.ConnDescH\x00R\x04Conn\x12&\n" +
|
||||||
0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x22, 0x0a,
|
"\aConnErr\x18\x06 \x01(\v2\n" +
|
||||||
0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x52,
|
".ConnErrorH\x00R\aConnErr\x12)\n" +
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x05, 0x52, 0x6f, 0x75, 0x74,
|
"\bConnNoti\x18\a \x01(\v2\v.ConnNoticeH\x00R\bConnNoti\x12 \n" +
|
||||||
0x65, 0x12, 0x1f, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
"\x04Rpty\x18\b \x01(\v2\n" +
|
||||||
0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x04, 0x50, 0x65,
|
".RptyEventH\x00R\x04RptyB\x03\n" +
|
||||||
0x65, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
|
"\x01U*^\n" +
|
||||||
0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x04, 0x44,
|
"\fROUTE_OPTION\x12\n" +
|
||||||
0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x04, 0x43, 0x6f, 0x6e, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
|
"\n" +
|
||||||
0x0b, 0x32, 0x09, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x04,
|
"\x06UNSPEC\x10\x00\x12\a\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x6e, 0x12, 0x26, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x18,
|
"\x03TCP\x10\x01\x12\b\n" +
|
||||||
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x6f,
|
"\x04TCP4\x10\x02\x12\b\n" +
|
||||||
0x72, 0x48, 0x00, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x45, 0x72, 0x72, 0x12, 0x29, 0x0a, 0x08,
|
"\x04TCP6\x10\x04\x12\a\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b,
|
"\x03TTY\x10\b\x12\b\n" +
|
||||||
0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x48, 0x00, 0x52, 0x08, 0x43,
|
"\x04HTTP\x10\x10\x12\t\n" +
|
||||||
0x6f, 0x6e, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x42, 0x03, 0x0a, 0x01, 0x55, 0x2a, 0x5e, 0x0a, 0x0c,
|
"\x05HTTPS\x10 \x12\a\n" +
|
||||||
0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x0a, 0x0a, 0x06,
|
"\x03SSH\x10@*\xd7\x02\n" +
|
||||||
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10,
|
"\vPACKET_KIND\x12\f\n" +
|
||||||
0x01, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x34, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x54,
|
"\bRESERVED\x10\x00\x12\x0f\n" +
|
||||||
0x43, 0x50, 0x36, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x54, 0x59, 0x10, 0x08, 0x12, 0x08,
|
"\vROUTE_START\x10\x01\x12\x0e\n" +
|
||||||
0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x10, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50,
|
"\n" +
|
||||||
0x53, 0x10, 0x20, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x40, 0x2a, 0xe5, 0x01, 0x0a,
|
"ROUTE_STOP\x10\x02\x12\x11\n" +
|
||||||
0x0b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x12, 0x0c, 0x0a, 0x08,
|
"\rROUTE_STARTED\x10\x03\x12\x11\n" +
|
||||||
0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f,
|
"\rROUTE_STOPPED\x10\x04\x12\x10\n" +
|
||||||
0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x52,
|
"\fPEER_STARTED\x10\x05\x12\x10\n" +
|
||||||
0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x52,
|
"\fPEER_STOPPED\x10\x06\x12\x10\n" +
|
||||||
0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11,
|
"\fPEER_ABORTED\x10\a\x12\f\n" +
|
||||||
0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10,
|
"\bPEER_EOF\x10\b\x12\r\n" +
|
||||||
0x04, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45,
|
"\tPEER_DATA\x10\t\x12\r\n" +
|
||||||
0x44, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50,
|
"\tCONN_DESC\x10\v\x12\x0e\n" +
|
||||||
0x50, 0x45, 0x44, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x41, 0x42,
|
"\n" +
|
||||||
0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x45, 0x52, 0x5f,
|
"CONN_ERROR\x10\f\x12\x0f\n" +
|
||||||
0x45, 0x4f, 0x46, 0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x44, 0x41,
|
"\vCONN_NOTICE\x10\r\x12\x0e\n" +
|
||||||
0x54, 0x41, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x5f, 0x44, 0x45, 0x53,
|
"\n" +
|
||||||
0x43, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4f, 0x4e, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f,
|
"RPTY_START\x10\x0e\x12\r\n" +
|
||||||
0x52, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49,
|
"\tRPTY_STOP\x10\x0f\x12\x10\n" +
|
||||||
0x43, 0x45, 0x10, 0x0d, 0x32, 0x49, 0x0a, 0x04, 0x48, 0x6f, 0x64, 0x75, 0x12, 0x19, 0x0a, 0x07,
|
"\fRPTY_STARTED\x10\x10\x12\x10\n" +
|
||||||
0x47, 0x65, 0x74, 0x53, 0x65, 0x65, 0x64, 0x12, 0x05, 0x2e, 0x53, 0x65, 0x65, 0x64, 0x1a, 0x05,
|
"\fRPTY_STOPPED\x10\x11\x12\x10\n" +
|
||||||
0x2e, 0x53, 0x65, 0x65, 0x64, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x65,
|
"\fRPTY_ABORTED\x10\x12\x12\f\n" +
|
||||||
0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
"\bRPTY_EOF\x10\x13\x12\r\n" +
|
||||||
0x1a, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42,
|
"\tRPTY_DATA\x10\x142I\n" +
|
||||||
0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x68, 0x6f, 0x64, 0x75, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
"\x04Hodu\x12\x19\n" +
|
||||||
0x33,
|
"\aGetSeed\x12\x05.Seed\x1a\x05.Seed\"\x00\x12&\n" +
|
||||||
})
|
"\fPacketStream\x12\a.Packet\x1a\a.Packet\"\x00(\x010\x01B\bZ\x06./hodub\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_hodu_proto_rawDescOnce sync.Once
|
file_hodu_proto_rawDescOnce sync.Once
|
||||||
@ -838,7 +927,7 @@ func file_hodu_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_hodu_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_hodu_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_hodu_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
var file_hodu_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||||
var file_hodu_proto_goTypes = []any{
|
var file_hodu_proto_goTypes = []any{
|
||||||
(ROUTE_OPTION)(0), // 0: ROUTE_OPTION
|
(ROUTE_OPTION)(0), // 0: ROUTE_OPTION
|
||||||
(PACKET_KIND)(0), // 1: PACKET_KIND
|
(PACKET_KIND)(0), // 1: PACKET_KIND
|
||||||
@ -849,25 +938,27 @@ var file_hodu_proto_goTypes = []any{
|
|||||||
(*ConnDesc)(nil), // 6: ConnDesc
|
(*ConnDesc)(nil), // 6: ConnDesc
|
||||||
(*ConnError)(nil), // 7: ConnError
|
(*ConnError)(nil), // 7: ConnError
|
||||||
(*ConnNotice)(nil), // 8: ConnNotice
|
(*ConnNotice)(nil), // 8: ConnNotice
|
||||||
(*Packet)(nil), // 9: Packet
|
(*RptyEvent)(nil), // 9: RptyEvent
|
||||||
|
(*Packet)(nil), // 10: Packet
|
||||||
}
|
}
|
||||||
var file_hodu_proto_depIdxs = []int32{
|
var file_hodu_proto_depIdxs = []int32{
|
||||||
1, // 0: Packet.Kind:type_name -> PACKET_KIND
|
1, // 0: Packet.Kind:type_name -> PACKET_KIND
|
||||||
3, // 1: Packet.Route:type_name -> RouteDesc
|
3, // 1: Packet.Route:type_name -> RouteDesc
|
||||||
4, // 2: Packet.Peer:type_name -> PeerDesc
|
4, // 2: Packet.Peer:type_name -> PeerDesc
|
||||||
5, // 3: Packet.Data:type_name -> PeerData
|
5, // 3: Packet.Data:type_name -> PeerData
|
||||||
6, // 4: Packet.Conn:type_name -> ConnDesc
|
6, // 4: Packet.Conn:type_name -> ConnDesc
|
||||||
7, // 5: Packet.ConnErr:type_name -> ConnError
|
7, // 5: Packet.ConnErr:type_name -> ConnError
|
||||||
8, // 6: Packet.ConnNoti:type_name -> ConnNotice
|
8, // 6: Packet.ConnNoti:type_name -> ConnNotice
|
||||||
2, // 7: Hodu.GetSeed:input_type -> Seed
|
9, // 7: Packet.Rpty:type_name -> RptyEvent
|
||||||
9, // 8: Hodu.PacketStream:input_type -> Packet
|
2, // 8: Hodu.GetSeed:input_type -> Seed
|
||||||
2, // 9: Hodu.GetSeed:output_type -> Seed
|
10, // 9: Hodu.PacketStream:input_type -> Packet
|
||||||
9, // 10: Hodu.PacketStream:output_type -> Packet
|
2, // 10: Hodu.GetSeed:output_type -> Seed
|
||||||
9, // [9:11] is the sub-list for method output_type
|
10, // 11: Hodu.PacketStream:output_type -> Packet
|
||||||
7, // [7:9] is the sub-list for method input_type
|
10, // [10:12] is the sub-list for method output_type
|
||||||
7, // [7:7] is the sub-list for extension type_name
|
8, // [8:10] is the sub-list for method input_type
|
||||||
7, // [7:7] is the sub-list for extension extendee
|
8, // [8:8] is the sub-list for extension type_name
|
||||||
0, // [0:7] is the sub-list for field type_name
|
8, // [8:8] is the sub-list for extension extendee
|
||||||
|
0, // [0:8] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_hodu_proto_init() }
|
func init() { file_hodu_proto_init() }
|
||||||
@ -875,13 +966,14 @@ func file_hodu_proto_init() {
|
|||||||
if File_hodu_proto != nil {
|
if File_hodu_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file_hodu_proto_msgTypes[7].OneofWrappers = []any{
|
file_hodu_proto_msgTypes[8].OneofWrappers = []any{
|
||||||
(*Packet_Route)(nil),
|
(*Packet_Route)(nil),
|
||||||
(*Packet_Peer)(nil),
|
(*Packet_Peer)(nil),
|
||||||
(*Packet_Data)(nil),
|
(*Packet_Data)(nil),
|
||||||
(*Packet_Conn)(nil),
|
(*Packet_Conn)(nil),
|
||||||
(*Packet_ConnErr)(nil),
|
(*Packet_ConnErr)(nil),
|
||||||
(*Packet_ConnNoti)(nil),
|
(*Packet_ConnNoti)(nil),
|
||||||
|
(*Packet_Rpty)(nil),
|
||||||
}
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
@ -889,7 +981,7 @@ func file_hodu_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_hodu_proto_rawDesc), len(file_hodu_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_hodu_proto_rawDesc), len(file_hodu_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 8,
|
NumMessages: 9,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
14
hodu.proto
14
hodu.proto
@ -81,6 +81,11 @@ message ConnNotice {
|
|||||||
string Text = 1;
|
string Text = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
message RptyEvent {
|
||||||
|
string Token = 1;
|
||||||
|
bytes Data = 2;
|
||||||
|
};
|
||||||
|
|
||||||
enum PACKET_KIND {
|
enum PACKET_KIND {
|
||||||
RESERVED = 0; // not used
|
RESERVED = 0; // not used
|
||||||
ROUTE_START = 1;
|
ROUTE_START = 1;
|
||||||
@ -95,6 +100,14 @@ enum PACKET_KIND {
|
|||||||
CONN_DESC = 11;
|
CONN_DESC = 11;
|
||||||
CONN_ERROR = 12;
|
CONN_ERROR = 12;
|
||||||
CONN_NOTICE = 13;
|
CONN_NOTICE = 13;
|
||||||
|
|
||||||
|
RPTY_START = 14;
|
||||||
|
RPTY_STOP = 15;
|
||||||
|
RPTY_STARTED = 16;
|
||||||
|
RPTY_STOPPED = 17;
|
||||||
|
RPTY_ABORTED = 18;
|
||||||
|
RPTY_EOF = 19;
|
||||||
|
RPTY_DATA = 20;
|
||||||
};
|
};
|
||||||
|
|
||||||
message Packet {
|
message Packet {
|
||||||
@ -107,5 +120,6 @@ message Packet {
|
|||||||
ConnDesc Conn = 5;
|
ConnDesc Conn = 5;
|
||||||
ConnError ConnErr = 6;
|
ConnError ConnErr = 6;
|
||||||
ConnNotice ConnNoti = 7;
|
ConnNotice ConnNoti = 7;
|
||||||
|
RptyEvent Rpty = 8;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
12
packet.go
12
packet.go
@ -74,3 +74,15 @@ func MakeConnErrorPacket(error_id uint32, msg string) *Packet {
|
|||||||
func MakeConnNoticePacket(msg string) *Packet {
|
func MakeConnNoticePacket(msg string) *Packet {
|
||||||
return &Packet{Kind: PACKET_KIND_CONN_NOTICE, U: &Packet_ConnNoti{ConnNoti: &ConnNotice{Text: msg}}}
|
return &Packet{Kind: PACKET_KIND_CONN_NOTICE, U: &Packet_ConnNoti{ConnNoti: &ConnNotice{Text: msg}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeRptyStartPacket(token string) *Packet {
|
||||||
|
return &Packet{Kind: PACKET_KIND_RPTY_START, U: &Packet_Rpty{Rpty: &RptyEvent{Token: token}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeRptyStopPacket(token string) *Packet {
|
||||||
|
return &Packet{Kind: PACKET_KIND_RPTY_START, U: &Packet_Rpty{Rpty: &RptyEvent{Token: token}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeRptyDataPacket(token string, data []byte) *Packet {
|
||||||
|
return &Packet{Kind: PACKET_KIND_RPTY_START, U: &Packet_Rpty{Rpty: &RptyEvent{Token: token, Data: data}}}
|
||||||
|
}
|
||||||
|
@ -76,7 +76,7 @@ type json_out_server_stats struct {
|
|||||||
ServerPeers int64 `json:"server-peers"`
|
ServerPeers int64 `json:"server-peers"`
|
||||||
|
|
||||||
SshProxySessions int64 `json:"pxy-ssh-sessions"`
|
SshProxySessions int64 `json:"pxy-ssh-sessions"`
|
||||||
ServerPtsSessions int64 `json:"server-pts-sessions"`
|
ServerPtySessions int64 `json:"server-pty-sessions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a more specialized variant of json_in_notice
|
// this is a more specialized variant of json_in_notice
|
||||||
@ -920,7 +920,7 @@ func (ctl *server_ctl_stats) ServeHTTP(w http.ResponseWriter, req *http.Request)
|
|||||||
stats.ServerRoutes = s.stats.routes.Load()
|
stats.ServerRoutes = s.stats.routes.Load()
|
||||||
stats.ServerPeers = s.stats.peers.Load()
|
stats.ServerPeers = s.stats.peers.Load()
|
||||||
stats.SshProxySessions = s.stats.ssh_proxy_sessions.Load()
|
stats.SshProxySessions = s.stats.ssh_proxy_sessions.Load()
|
||||||
stats.ServerPtsSessions = s.stats.pts_sessions.Load()
|
stats.ServerPtySessions = s.stats.pty_sessions.Load()
|
||||||
status_code = WriteJsonRespHeader(w, http.StatusOK)
|
status_code = WriteJsonRespHeader(w, http.StatusOK)
|
||||||
if err = je.Encode(stats); err != nil { goto oops }
|
if err = je.Encode(stats); err != nil { goto oops }
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ type ServerCollector struct {
|
|||||||
ServerRoutes *prometheus.Desc
|
ServerRoutes *prometheus.Desc
|
||||||
ServerPeers *prometheus.Desc
|
ServerPeers *prometheus.Desc
|
||||||
SshProxySessions *prometheus.Desc
|
SshProxySessions *prometheus.Desc
|
||||||
PtsSessions *prometheus.Desc
|
PtySessions *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServerCollector returns a new ServerCollector with all prometheus.Desc initialized
|
// NewServerCollector returns a new ServerCollector with all prometheus.Desc initialized
|
||||||
@ -53,9 +53,9 @@ func NewServerCollector(server *Server) ServerCollector {
|
|||||||
"Number of SSH proxy sessions",
|
"Number of SSH proxy sessions",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
PtsSessions: prometheus.NewDesc(
|
PtySessions: prometheus.NewDesc(
|
||||||
prefix + "pts_sessions",
|
prefix + "pty_sessions",
|
||||||
"Number of pts session",
|
"Number of pty session",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ func (c ServerCollector) Describe(ch chan<- *prometheus.Desc) {
|
|||||||
ch <- c.ServerRoutes
|
ch <- c.ServerRoutes
|
||||||
ch <- c.ServerPeers
|
ch <- c.ServerPeers
|
||||||
ch <- c.SshProxySessions
|
ch <- c.SshProxySessions
|
||||||
ch <- c.PtsSessions
|
ch <- c.PtySessions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ServerCollector) Collect(ch chan<- prometheus.Metric) {
|
func (c ServerCollector) Collect(ch chan<- prometheus.Metric) {
|
||||||
@ -106,8 +106,8 @@ func (c ServerCollector) Collect(ch chan<- prometheus.Metric) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.PtsSessions,
|
c.PtySessions,
|
||||||
prometheus.GaugeValue,
|
prometheus.GaugeValue,
|
||||||
float64(c.server.stats.pts_sessions.Load()),
|
float64(c.server.stats.pty_sessions.Load()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,28 +14,34 @@ import "sync"
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
import "text/template"
|
import "text/template"
|
||||||
|
|
||||||
import "github.com/creack/pty"
|
import pts "github.com/creack/pty"
|
||||||
import "golang.org/x/net/websocket"
|
import "golang.org/x/net/websocket"
|
||||||
import "golang.org/x/sys/unix"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
type server_pts_ws struct {
|
type server_pty_ws struct {
|
||||||
S *Server
|
S *Server
|
||||||
Id string
|
Id string
|
||||||
ws *websocket.Conn
|
ws *websocket.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type server_pts_xterm_file struct {
|
type server_rpty_ws struct {
|
||||||
|
S *Server
|
||||||
|
Id string
|
||||||
|
ws *websocket.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
type server_pty_xterm_file struct {
|
||||||
ServerCtl
|
ServerCtl
|
||||||
file string
|
file string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
func (pts *server_pts_ws) Identity() string {
|
func (pty *server_pty_ws) Identity() string {
|
||||||
return pts.Id
|
return pty.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pts *server_pts_ws) send_ws_data(ws *websocket.Conn, type_val string, data string) error {
|
func (pty *server_pty_ws) send_ws_data(ws *websocket.Conn, type_val string, data string) error {
|
||||||
var msg []byte
|
var msg []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -45,26 +51,26 @@ func (pts *server_pts_ws) send_ws_data(ws *websocket.Conn, type_val string, data
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (pts *server_pts_ws) connect_pts(username string, password string) (*exec.Cmd, *os.File, error) {
|
func (pty *server_pty_ws) connect_pty(username string, password string) (*exec.Cmd, *os.File, error) {
|
||||||
var s *Server
|
var s *Server
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
var tty *os.File
|
var tty *os.File
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// username and password are not used yet.
|
// username and password are not used yet.
|
||||||
s = pts.S
|
s = pty.S
|
||||||
|
|
||||||
if s.pts_shell == "" {
|
if s.pty_shell == "" {
|
||||||
return nil, nil, fmt.Errorf("blank pts shell")
|
return nil, nil, fmt.Errorf("blank pty shell")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(s.pts_shell);
|
cmd = exec.Command(s.pty_shell);
|
||||||
if s.pts_user != "" {
|
if s.pty_user != "" {
|
||||||
var uid int
|
var uid int
|
||||||
var gid int
|
var gid int
|
||||||
var u *user.User
|
var u *user.User
|
||||||
|
|
||||||
u, err = user.Lookup(s.pts_user)
|
u, err = user.Lookup(s.pty_user)
|
||||||
if err != nil { return nil, nil, err }
|
if err != nil { return nil, nil, err }
|
||||||
|
|
||||||
uid, _ = strconv.Atoi(u.Uid)
|
uid, _ = strconv.Atoi(u.Uid)
|
||||||
@ -81,13 +87,13 @@ func (pts *server_pts_ws) connect_pts(username string, password string) (*exec.C
|
|||||||
"HOME=" + u.HomeDir,
|
"HOME=" + u.HomeDir,
|
||||||
"LOGNAME=" + u.Username,
|
"LOGNAME=" + u.Username,
|
||||||
"PATH=" + os.Getenv("PATH"),
|
"PATH=" + os.Getenv("PATH"),
|
||||||
"SHELL=" + s.pts_shell,
|
"SHELL=" + s.pty_shell,
|
||||||
"TERM=xterm",
|
"TERM=xterm",
|
||||||
"USER=" + u.Username,
|
"USER=" + u.Username,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tty, err = pty.Start(cmd)
|
tty, err = pts.Start(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -98,7 +104,7 @@ func (pts *server_pts_ws) connect_pts(username string, password string) (*exec.C
|
|||||||
return cmd, tty, nil
|
return cmd, tty, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pts *server_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
func (pty *server_pty_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
||||||
var s *Server
|
var s *Server
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var username string
|
var username string
|
||||||
@ -111,7 +117,7 @@ func (pts *server_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
var conn_ready_chan chan bool
|
var conn_ready_chan chan bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
s = pts.S
|
s = pty.S
|
||||||
req = ws.Request()
|
req = ws.Request()
|
||||||
conn_ready_chan = make(chan bool, 3)
|
conn_ready_chan = make(chan bool, 3)
|
||||||
|
|
||||||
@ -129,18 +135,17 @@ func (pts *server_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
var n int
|
var n int
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
||||||
poll_fds = []unix.PollFd{
|
poll_fds = []unix.PollFd{
|
||||||
unix.PollFd{Fd: int32(out.Fd()), Events: unix.POLLIN},
|
unix.PollFd{Fd: int32(out.Fd()), Events: unix.POLLIN},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.stats.pts_sessions.Add(1)
|
s.stats.pty_sessions.Add(1)
|
||||||
buf = make([]byte, 2048)
|
buf = make([]byte, 2048)
|
||||||
for {
|
for {
|
||||||
n, err = unix.Poll(poll_fds, -1) // -1 means wait indefinitely
|
n, err = unix.Poll(poll_fds, -1) // -1 means wait indefinitely
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, unix.EINTR) { continue }
|
if errors.Is(err, unix.EINTR) { continue }
|
||||||
s.log.Write("", LOG_ERROR, "[%s] Failed to poll pts stdout - %s", req.RemoteAddr, err.Error())
|
s.log.Write("", LOG_ERROR, "[%s] Failed to poll pty stdout - %s", req.RemoteAddr, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n == 0 { // timed out
|
if n == 0 { // timed out
|
||||||
@ -148,7 +153,7 @@ func (pts *server_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (poll_fds[0].Revents & (unix.POLLERR | unix.POLLHUP | unix.POLLNVAL)) != 0 {
|
if (poll_fds[0].Revents & (unix.POLLERR | unix.POLLHUP | unix.POLLNVAL)) != 0 {
|
||||||
s.log.Write(pts.Id, LOG_DEBUG, "[%s] EOF detected on pts stdout", req.RemoteAddr)
|
s.log.Write(pty.Id, LOG_DEBUG, "[%s] EOF detected on pty stdout", req.RemoteAddr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,20 +161,20 @@ func (pts *server_pts_ws) ServeWebsocket(ws *websocket.Conn) (int, error) {
|
|||||||
n, err = out.Read(buf)
|
n, err = out.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, io.EOF) {
|
if !errors.Is(err, io.EOF) {
|
||||||
s.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to read pts stdout - %s", req.RemoteAddr, err.Error())
|
s.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to read pty stdout - %s", req.RemoteAddr, err.Error())
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
err = pts.send_ws_data(ws, "iov", string(buf[:n]))
|
err = pty.send_ws_data(ws, "iov", string(buf[:n]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to send to websocket - %s", req.RemoteAddr, err.Error())
|
s.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to send to websocket - %s", req.RemoteAddr, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.stats.pts_sessions.Add(-1)
|
s.stats.pty_sessions.Add(-1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -194,18 +199,18 @@ ws_recv_loop:
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
cmd, tty, err = pts.connect_pts(username, password)
|
cmd, tty, err = pty.connect_pty(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to connect pts - %s", req.RemoteAddr, err.Error())
|
s.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to connect pty - %s", req.RemoteAddr, err.Error())
|
||||||
pts.send_ws_data(ws, "error", err.Error())
|
pty.send_ws_data(ws, "error", err.Error())
|
||||||
ws.Close() // dirty way to flag out the error
|
ws.Close() // dirty way to flag out the error - this will make websocket.MessageReceive to fail
|
||||||
} else {
|
} else {
|
||||||
err = pts.send_ws_data(ws, "status", "opened")
|
err = pty.send_ws_data(ws, "status", "opened")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Write(pts.Id, LOG_ERROR, "[%s] Failed to write opened event to websocket - %s", req.RemoteAddr, err.Error())
|
s.log.Write(pty.Id, LOG_ERROR, "[%s] Failed to write opened event to websocket - %s", req.RemoteAddr, err.Error())
|
||||||
ws.Close() // dirty way to flag out the error
|
ws.Close() // dirty way to flag out the error
|
||||||
} else {
|
} else {
|
||||||
s.log.Write(pts.Id, LOG_DEBUG, "[%s] Opened pts session", req.RemoteAddr)
|
s.log.Write(pty.Id, LOG_DEBUG, "[%s] Opened pty session", req.RemoteAddr)
|
||||||
out = tty
|
out = tty
|
||||||
in = tty
|
in = tty
|
||||||
conn_ready_chan <- true
|
conn_ready_chan <- true
|
||||||
@ -235,8 +240,8 @@ ws_recv_loop:
|
|||||||
var cols int
|
var cols int
|
||||||
rows, _ = strconv.Atoi(ev.Data[0])
|
rows, _ = strconv.Atoi(ev.Data[0])
|
||||||
cols, _ = strconv.Atoi(ev.Data[1])
|
cols, _ = strconv.Atoi(ev.Data[1])
|
||||||
pty.Setsize(tty, &pty.Winsize{Rows: uint16(rows), Cols: uint16(cols)})
|
pts.Setsize(tty, &pts.Winsize{Rows: uint16(rows), Cols: uint16(cols)})
|
||||||
s.log.Write(pts.Id, LOG_DEBUG, "[%s] Resized terminal to %d,%d", req.RemoteAddr, rows, cols)
|
s.log.Write(pty.Id, LOG_DEBUG, "[%s] Resized terminal to %d,%d", req.RemoteAddr, rows, cols)
|
||||||
// ignore error
|
// ignore error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,7 +250,7 @@ ws_recv_loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tty != nil {
|
if tty != nil {
|
||||||
err = pts.send_ws_data(ws, "status", "closed")
|
err = pty.send_ws_data(ws, "status", "closed")
|
||||||
if err != nil { goto done }
|
if err != nil { goto done }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,22 +265,21 @@ done:
|
|||||||
if tty != nil { tty.Close() }
|
if tty != nil { tty.Close() }
|
||||||
if cmd != nil { cmd.Wait() }
|
if cmd != nil { cmd.Wait() }
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
s.log.Write(pts.Id, LOG_DEBUG, "[%s] Ended pts session", req.RemoteAddr)
|
s.log.Write(pty.Id, LOG_DEBUG, "[%s] Ended pty session", req.RemoteAddr)
|
||||||
|
|
||||||
return http.StatusOK, err
|
return http.StatusOK, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
func (pts *server_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Request) (int, error) {
|
func (pty *server_pty_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
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
s = pts.S
|
s = pty.S
|
||||||
|
|
||||||
switch pts.file {
|
switch pty.file {
|
||||||
case "xterm.js":
|
case "xterm.js":
|
||||||
status_code = WriteJsRespHeader(w, http.StatusOK)
|
status_code = WriteJsRespHeader(w, http.StatusOK)
|
||||||
w.Write(xterm_js)
|
w.Write(xterm_js)
|
||||||
@ -301,7 +305,7 @@ func (pts *server_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
status_code = WriteHtmlRespHeader(w, http.StatusOK)
|
||||||
tmpl.Execute(w,
|
tmpl.Execute(w,
|
||||||
&xterm_session_info{
|
&xterm_session_info{
|
||||||
Mode: "pts",
|
Mode: "pty",
|
||||||
ConnId: "-1",
|
ConnId: "-1",
|
||||||
RouteId: "-1",
|
RouteId: "-1",
|
||||||
})
|
})
|
||||||
@ -314,9 +318,9 @@ func (pts *server_pts_xterm_file) ServeHTTP(w http.ResponseWriter, req *http.Req
|
|||||||
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if strings.HasPrefix(pts.file, "_redir:") {
|
if strings.HasPrefix(pty.file, "_redir:") {
|
||||||
status_code = http.StatusMovedPermanently
|
status_code = http.StatusMovedPermanently
|
||||||
w.Header().Set("Location", pts.file[7:])
|
w.Header().Set("Location", pty.file[7:])
|
||||||
w.WriteHeader(status_code)
|
w.WriteHeader(status_code)
|
||||||
} else {
|
} else {
|
||||||
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
status_code = WriteEmptyRespHeader(w, http.StatusNotFound)
|
76
server.go
76
server.go
@ -153,15 +153,15 @@ type Server struct {
|
|||||||
routes atomic.Int64
|
routes atomic.Int64
|
||||||
peers atomic.Int64
|
peers atomic.Int64
|
||||||
ssh_proxy_sessions atomic.Int64
|
ssh_proxy_sessions atomic.Int64
|
||||||
pts_sessions atomic.Int64
|
pty_sessions atomic.Int64
|
||||||
}
|
}
|
||||||
|
|
||||||
wpx_resp_tf ServerWpxResponseTransformer
|
wpx_resp_tf ServerWpxResponseTransformer
|
||||||
wpx_foreign_port_proxy_maker ServerWpxForeignPortProxyMaker
|
wpx_foreign_port_proxy_maker ServerWpxForeignPortProxyMaker
|
||||||
|
|
||||||
|
|
||||||
pts_user string
|
pty_user string
|
||||||
pts_shell string
|
pty_shell string
|
||||||
xterm_html string
|
xterm_html string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,6 +635,10 @@ func (cts *ServerConn) ReqStopAllServerRoutes() {
|
|||||||
cts.route_mtx.Unlock()
|
cts.route_mtx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (cts *ServerConn) StartRpts() {
|
||||||
|
}
|
||||||
|
|
||||||
func (cts *ServerConn) ReportPacket(route_id RouteId, pts_id PeerId, packet_type PACKET_KIND, event_data interface{}) error {
|
func (cts *ServerConn) ReportPacket(route_id RouteId, pts_id PeerId, packet_type PACKET_KIND, event_data interface{}) error {
|
||||||
var r *ServerRoute
|
var r *ServerRoute
|
||||||
var ok bool
|
var ok bool
|
||||||
@ -877,6 +881,17 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
|
|||||||
} else {
|
} else {
|
||||||
cts.S.log.Write(cts.Sid, LOG_ERROR, "Invalid conn_notice packet from %s", cts.RemoteAddr)
|
cts.S.log.Write(cts.Sid, LOG_ERROR, "Invalid conn_notice packet from %s", cts.RemoteAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*case PACKET_KIND_RPTY_START:
|
||||||
|
case PACKET_KIND_RPTY_STOP:*/
|
||||||
|
case PACKET_KIND_RPTY_STARTED:
|
||||||
|
case PACKET_KIND_RPTY_STOPPED:
|
||||||
|
case PACKET_KIND_RPTY_ABORTED:
|
||||||
|
case PACKET_KIND_RPTY_EOF:
|
||||||
|
case PACKET_KIND_RPTY_DATA:
|
||||||
|
// inspect the token
|
||||||
|
// find the right websocket handler...
|
||||||
|
// report it to the right websocket handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,18 +1395,31 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
|
|||||||
s.ctl_mux.Handle("/_ctl/events",
|
s.ctl_mux.Handle("/_ctl/events",
|
||||||
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_ctl_ws{ServerCtl{S: &s, Id: HS_ID_CTL}})))
|
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_ctl_ws{ServerCtl{S: &s, Id: HS_ID_CTL}})))
|
||||||
|
|
||||||
s.ctl_mux.Handle("/_pts/ws",
|
s.ctl_mux.Handle("/_pty/ws",
|
||||||
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_pts_ws{S: &s, Id: HS_ID_CTL})))
|
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_pty_ws{S: &s, Id: HS_ID_CTL})))
|
||||||
s.ctl_mux.Handle("/_pts/xterm.js",
|
s.ctl_mux.Handle("/_pty/xterm.js",
|
||||||
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.js"}))
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.js"}))
|
||||||
s.ctl_mux.Handle("/_pts/xterm-addon-fit.js",
|
s.ctl_mux.Handle("/_pty/xterm.js/",
|
||||||
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm-addon-fit.js"}))
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
|
||||||
s.ctl_mux.Handle("/_pts/xterm.css",
|
s.ctl_mux.Handle("/_pty/xterm-addon-fit.js",
|
||||||
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.css"}))
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm-addon-fit.js"}))
|
||||||
s.ctl_mux.Handle("/_pts/xterm.html",
|
s.ctl_mux.Handle("/_pty/xterm-addon-fit.js/",
|
||||||
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.html"}))
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
|
||||||
s.ctl_mux.Handle("/_pts/",
|
s.ctl_mux.Handle("/_pty/xterm.css",
|
||||||
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_redir:xterm.html"}))
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.css"}))
|
||||||
|
s.ctl_mux.Handle("/_pty/xterm.css/",
|
||||||
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
|
||||||
|
s.ctl_mux.Handle("/_pty/xterm.html",
|
||||||
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.html"}))
|
||||||
|
s.ctl_mux.Handle("/_pty/xterm.html/",
|
||||||
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
|
||||||
|
s.ctl_mux.Handle("/_pty/",
|
||||||
|
s.WrapHttpHandler(&server_pty_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_redir:xterm.html"}))
|
||||||
|
|
||||||
|
/*
|
||||||
|
s.ctl_mux.Handle("/_rpts/ws",
|
||||||
|
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_rpts_ws{S: &s, Id: HS_ID_CTL})))
|
||||||
|
*/
|
||||||
|
|
||||||
s.ctl = make([]*http.Server, len(cfg.CtlAddrs))
|
s.ctl = make([]*http.Server, len(cfg.CtlAddrs))
|
||||||
for i = 0; i < len(cfg.CtlAddrs); i++ {
|
for i = 0; i < len(cfg.CtlAddrs); i++ {
|
||||||
@ -1511,7 +1539,7 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
|
|||||||
s.stats.routes.Store(0)
|
s.stats.routes.Store(0)
|
||||||
s.stats.peers.Store(0)
|
s.stats.peers.Store(0)
|
||||||
s.stats.ssh_proxy_sessions.Store(0)
|
s.stats.ssh_proxy_sessions.Store(0)
|
||||||
s.stats.pts_sessions.Store(0)
|
s.stats.pty_sessions.Store(0)
|
||||||
|
|
||||||
return &s, nil
|
return &s, nil
|
||||||
|
|
||||||
@ -1547,20 +1575,20 @@ func (s *Server) GetXtermHtml() string {
|
|||||||
return s.xterm_html
|
return s.xterm_html
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetPtsUser(user string) {
|
func (s *Server) SetPtyUser(user string) {
|
||||||
s.pts_user = user
|
s.pty_user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetPtsUser() string {
|
func (s *Server) GetPtyUser() string {
|
||||||
return s.pts_user
|
return s.pty_user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetPtsShell(user string) {
|
func (s *Server) SetPtyShell(user string) {
|
||||||
s.pts_shell = user
|
s.pty_shell = user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetPtsShell() string {
|
func (s *Server) GetPtyShell() string {
|
||||||
return s.pts_shell
|
return s.pty_shell
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) run_grpc_server(idx int, wg *sync.WaitGroup) error {
|
func (s *Server) run_grpc_server(idx int, wg *sync.WaitGroup) error {
|
||||||
|
@ -106,7 +106,7 @@ window.onload = function(event) {
|
|||||||
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_ssh_part = document.getElementById('login-ssh-part');
|
||||||
const login_pts_part = document.getElementById('login-pts-part');
|
const login_pty_part = document.getElementById('login-pty-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');
|
||||||
|
|
||||||
@ -114,12 +114,12 @@ window.onload = function(event) {
|
|||||||
login_ssh_part.style.display = 'block';
|
login_ssh_part.style.display = 'block';
|
||||||
username_field.disabled = false;
|
username_field.disabled = false;
|
||||||
password_field.disabled = false;
|
password_field.disabled = false;
|
||||||
login_pts_part.style.display = 'none';
|
login_pty_part.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
login_ssh_part.style.display = 'none';
|
login_ssh_part.style.display = 'none';
|
||||||
username_field.disabled = true;
|
username_field.disabled = true;
|
||||||
password_field.disabled = true;
|
password_field.disabled = true;
|
||||||
login_pts_part.style.display = 'block';
|
login_pty_part.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
const term = new window.Terminal({
|
const term = new window.Terminal({
|
||||||
@ -296,7 +296,7 @@ window.onload = function(event) {
|
|||||||
Password: <input type="password" id="password" disabled required />
|
Password: <input type="password" id="password" disabled required />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="login-pts-part" style="display: none;">
|
<div id="login-pty-part" style="display: none;">
|
||||||
Click Connect below to start a new terminal session
|
Click Connect below to start a new terminal session
|
||||||
</div>
|
</div>
|
||||||
<div id="login-submit-part" style="padding-top: 1em;">
|
<div id="login-submit-part" style="padding-top: 1em;">
|
||||||
|
Reference in New Issue
Block a user