implemented the pts feature in the server side as well

This commit is contained in:
hyung-hwan 2025-06-23 13:20:17 +09:00
parent d092540f08
commit ec70cc897c
10 changed files with 79 additions and 17 deletions

View File

@ -25,6 +25,7 @@ SRCS=\
server-ctl.go \
server-metrics.go \
server-peer.go \
server-pts.go \
server-pxy.go \
system.go \
transform.go \

View File

@ -60,6 +60,7 @@ func (c ClientCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.ClientConns
ch <- c.ClientRoutes
ch <- c.ClientPeers
ch <- c.PtsSessions
}
func (c ClientCollector) Collect(ch chan<- prometheus.Metric) {

View File

@ -28,13 +28,6 @@ type client_pts_xterm_file struct {
file string
}
/*
type json_ssh_ws_event struct {
Type string `json:"type"`
Data []string `json:"data"`
}
*/
// ------------------------------------------------------
func (pts *client_pts_ws) Identity() string {
@ -45,7 +38,7 @@ func (pts *client_pts_ws) send_ws_data(ws *websocket.Conn, type_val string, data
var msg []byte
var err error
msg, err = json.Marshal(json_ssh_ws_event{Type: type_val, Data: []string{ data } })
msg, err = json.Marshal(json_xterm_ws_event{Type: type_val, Data: []string{ data } })
if err == nil { err = websocket.Message.Send(ws, msg) }
return err
}
@ -186,7 +179,7 @@ ws_recv_loop:
if err != nil { goto done }
if len(msg) > 0 {
var ev json_ssh_ws_event
var ev json_xterm_ws_event
err = json.Unmarshal(msg, &ev)
if err == nil {
switch ev.Type {

View File

@ -94,6 +94,8 @@ type ServerAppConfig struct {
LogRotate int `yaml:"log-rotate"`
MaxPeers int `yaml:"max-peer-conns"` // maximum number of connections from peers
MaxRpcConns int `yaml:"max-rpc-conns"` // maximum number of rpc connections
PtsUser string `yaml:"pts-user"`
PtsShell string `yaml:"pts-shell"`
XtermHtmlFile string `yaml:"xterm-html-file"`
}

View File

@ -97,6 +97,8 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, wpx
var logmask hodu.LogMask
var logfile_maxsize int64
var logfile_rotate int
var pts_user string
var pts_shell string
var xterm_html_file string
var xterm_html string
var err error
@ -132,6 +134,9 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, wpx
config.CtlPrefix = cfg.CTL.Service.Prefix
config.RpcMaxConns = cfg.APP.MaxRpcConns
config.MaxPeers = cfg.APP.MaxPeers
pts_user = cfg.APP.PtsUser
pts_shell = cfg.APP.PtsShell
xterm_html_file = cfg.APP.XtermHtmlFile
logmask = log_strings_to_mask(cfg.APP.LogMask)
@ -167,6 +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())
}
if pts_user != "" { s.SetPtsUser(pts_user) }
if pts_shell != "" { s.SetPtsShell(pts_shell) }
if xterm_html != "" { s.SetXtermHtml(xterm_html) }
s.StartService(nil)

View File

@ -118,6 +118,11 @@ type json_out_go_stats struct {
}
type json_xterm_ws_event struct {
Type string `json:"type"`
Data []string `json:"data"`
}
// ---------------------------------------------------------
//go:embed xterm.js

View File

@ -76,6 +76,7 @@ type json_out_server_stats struct {
ServerPeers int64 `json:"server-peers"`
SshProxySessions int64 `json:"pxy-ssh-sessions"`
ServerPtsSessions int64 `json:"server-pts-sessions"`
}
// this is a more specialized variant of json_in_notice
@ -911,6 +912,7 @@ func (ctl *server_ctl_stats) ServeHTTP(w http.ResponseWriter, req *http.Request)
stats.ServerRoutes = s.stats.routes.Load()
stats.ServerPeers = s.stats.peers.Load()
stats.SshProxySessions = s.stats.ssh_proxy_sessions.Load()
stats.ServerPtsSessions = s.stats.pts_sessions.Load()
status_code = WriteJsonRespHeader(w, http.StatusOK)
if err = je.Encode(stats); err != nil { goto oops }

View File

@ -11,6 +11,7 @@ type ServerCollector struct {
ServerRoutes *prometheus.Desc
ServerPeers *prometheus.Desc
SshProxySessions *prometheus.Desc
PtsSessions *prometheus.Desc
}
// NewServerCollector returns a new ServerCollector with all prometheus.Desc initialized
@ -52,6 +53,11 @@ func NewServerCollector(server *Server) ServerCollector {
"Number of SSH proxy sessions",
nil, nil,
),
PtsSessions: prometheus.NewDesc(
prefix + "pts_sessions",
"Number of pts session",
nil, nil,
),
}
}
@ -61,6 +67,7 @@ func (c ServerCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.ServerRoutes
ch <- c.ServerPeers
ch <- c.SshProxySessions
ch <- c.PtsSessions
}
func (c ServerCollector) Collect(ch chan<- prometheus.Metric) {
@ -97,4 +104,10 @@ func (c ServerCollector) Collect(ch chan<- prometheus.Metric) {
prometheus.GaugeValue,
float64(c.server.stats.ssh_proxy_sessions.Load()),
)
ch <- prometheus.MustNewConstMetric(
c.PtsSessions,
prometheus.GaugeValue,
float64(c.server.stats.pts_sessions.Load()),
)
}

View File

@ -550,11 +550,6 @@ type server_pxy_ssh_ws struct {
Id string
}
type json_ssh_ws_event struct {
Type string `json:"type"`
Data []string `json:"data"`
}
func (pxy *server_pxy_ssh_ws) Identity() string {
return pxy.Id
}
@ -566,7 +561,7 @@ func (pxy *server_pxy_ssh_ws) send_ws_data(ws *websocket.Conn, type_val string,
var msg []byte
var err error
msg, err = json.Marshal(json_ssh_ws_event{Type: type_val, Data: []string{ data } })
msg, err = json.Marshal(json_xterm_ws_event{Type: type_val, Data: []string{ data } })
if err == nil { err = websocket.Message.Send(ws, msg) }
return err
}
@ -723,7 +718,7 @@ ws_recv_loop:
if err != nil { goto done }
if len(msg) > 0 {
var ev json_ssh_ws_event
var ev json_xterm_ws_event
err = json.Unmarshal(msg, &ev)
if err == nil {
switch ev.Type {

View File

@ -154,11 +154,16 @@ type Server struct {
routes atomic.Int64
peers atomic.Int64
ssh_proxy_sessions atomic.Int64
pts_sessions atomic.Int64
}
wpx_resp_tf ServerWpxResponseTransformer
wpx_foreign_port_proxy_maker ServerWpxForeignPortProxyMaker
xterm_html string
pts_user string
pts_shell string
xterm_html string
}
// connection from client.
@ -1376,6 +1381,27 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.ctl_mux.Handle("/_ctl/events",
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_ctl_ws{ServerCtl{S: &s, Id: HS_ID_CTL}})))
s.ctl_mux.Handle("/_pts/ws",
s.SafeWrapWebsocketHandler(s.WrapWebsocketHandler(&server_pts_ws{S: &s, Id: HS_ID_CTL})))
s.ctl_mux.Handle("/_pts/xterm.js",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.js"}))
s.ctl_mux.Handle("/_pts/xterm.js.map",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_notfound"}))
s.ctl_mux.Handle("/_pts/xterm-addon-fit.js",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm-addon-fit.js"}))
s.ctl_mux.Handle("/_pts/xterm-addon-fit.js.map",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_notfound"}))
s.ctl_mux.Handle("/_pts/xterm.css",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.css"}))
s.ctl_mux.Handle("/_pts/xterm.html",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "xterm.html"}))
s.ctl_mux.Handle("/_pts/",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
s.ctl_mux.Handle("/_pts/favicon.ico",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
s.ctl_mux.Handle("/_pts/favicon.ico/",
s.WrapHttpHandler(&server_pts_xterm_file{ServerCtl: ServerCtl{S: &s, Id: HS_ID_CTL}, file: "_forbidden"}))
/*
// this part is duplcate of pxy_mux.
s.ctl_mux.Handle("/_ssh/ws/{conn_id}/{route_id}",
@ -1503,6 +1529,7 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.stats.routes.Store(0)
s.stats.peers.Store(0)
s.stats.ssh_proxy_sessions.Store(0)
s.stats.pts_sessions.Store(0)
return &s, nil
@ -1538,6 +1565,22 @@ func (s *Server) GetXtermHtml() string {
return s.xterm_html
}
func (s *Server) SetPtsUser(user string) {
s.pts_user = user
}
func (s *Server) GetPtsUser() string {
return s.pts_user
}
func (s *Server) SetPtsShell(user string) {
s.pts_shell = user
}
func (s *Server) GetPtsShell() string {
return s.pts_shell
}
func (s *Server) run_grpc_server(idx int, wg *sync.WaitGroup) error {
var l *net.TCPListener
var err error