added code for rpx handling

This commit is contained in:
2025-08-19 20:20:18 +09:00
parent 31a4223aab
commit 10c139e837
19 changed files with 1518 additions and 427 deletions

597
server.go
View File

@@ -10,6 +10,7 @@ import "log"
import "net"
import "net/http"
import "net/netip"
import "regexp"
import "slices"
import "strconv"
import "strings"
@@ -32,8 +33,8 @@ const CTS_LIMIT int = 16384
type PortId uint16
const PORT_ID_MARKER string = "_"
const HS_ID_CTL string = "ctl"
const HS_ID_RPX string = "pxy"
const HS_ID_PXY string = "rpx"
const HS_ID_RPX string = "rpx"
const HS_ID_PXY string = "pxy"
const HS_ID_WPX string = "wpx"
type ServerConnMapByAddr map[net.Addr]*ServerConn
@@ -45,6 +46,7 @@ type ServerSvcPortMap map[PortId]ConnRouteId
type ServerRptyMap map[uint64]*ServerRpty
type ServerRptyMapByWs map[*websocket.Conn]*ServerRpty
type ServerRpxMap map[uint64]*ServerRpx
type ServerWpxResponseTransformer func(r *ServerRouteProxyInfo, resp *http.Response) io.Reader
type ServerWpxForeignPortProxyMaker func(wpx_type string, port_id string) (*ServerRouteProxyInfo, error)
@@ -67,6 +69,9 @@ type ServerConfig struct {
RpxAddrs []string
RpxTls *tls.Config
RpxClientTokenAttrName string
RpxClientTokenRegex *regexp.Regexp
RpxClientTokenSubmatchIndex int
PxyAddrs []string
PxyTls *tls.Config
@@ -166,12 +171,12 @@ type Server struct {
peers atomic.Int64
ssh_proxy_sessions atomic.Int64
pty_sessions atomic.Int64
rpty_sessions atomic.Int64
}
wpx_resp_tf ServerWpxResponseTransformer
wpx_foreign_port_proxy_maker ServerWpxForeignPortProxyMaker
pty_user string
pty_shell string
xterm_html string
@@ -202,6 +207,10 @@ type ServerConn struct {
rpty_map ServerRptyMap
rpty_map_by_ws ServerRptyMapByWs
rpx_next_id uint64
rpx_mtx sync.Mutex
rpx_map ServerRpxMap
wg sync.WaitGroup
stop_req atomic.Bool
stop_chan chan bool
@@ -236,6 +245,20 @@ type ServerRpty struct {
ws *websocket.Conn
}
type ServerRpx struct {
id uint64
pr *io.PipeReader
pw *io.PipeWriter
br io.ReadCloser // body reader
start_chan chan []byte
done_chan chan bool
br_chan chan bool
resp_status_code int
resp_error error
resp_done_chan chan bool
}
type GuardedPacketStreamServer struct {
mtx sync.Mutex
//pss Hodu_PacketStreamServer
@@ -265,6 +288,16 @@ func (g *GuardedPacketStreamServer) Context() context.Context {
// ------------------------------------
func (rpty *ServerRpty) ReqStop() {
rpty.ws.Close()
}
func (rpx *ServerRpx) ReqStop() {
rpx.done_chan <- true
rpx.pw.Close()
}
// ------------------------------------
func NewServerRoute(cts *ServerConn, id RouteId, option RouteOption, ptc_addr string, ptc_name string, svc_requested_addr string, svc_permitted_net string) (*ServerRoute, error) {
var r ServerRoute
var l *net.TCPListener
@@ -658,6 +691,7 @@ func (cts *ServerConn) ReqStopAllServerRoutes() {
cts.route_mtx.Unlock()
}
// Rpty
func (cts *ServerConn) StartRpty(ws *websocket.Conn) (*ServerRpty, error) {
var ok bool
var start_id uint64
@@ -707,11 +741,11 @@ func (cts *ServerConn) StartRpty(ws *websocket.Conn) (*ServerRpty, error) {
return nil , err
}
cts.S.stats.rpty_sessions.Add(1)
return rpty, nil
}
func (cts *ServerConn) StopRpty(ws *websocket.Conn) error {
// called by the websocket handler.
var rpty *ServerRpty
var id uint64
@@ -721,7 +755,9 @@ func (cts *ServerConn) StopRpty(ws *websocket.Conn) error {
cts.rpty_mtx.Lock()
rpty, ok = cts.rpty_map_by_ws[ws]
if !ok {
return fmt.Errorf("unknown ws connection for rpty - %v", ws.RemoteAddr())
cts.rpty_mtx.Unlock()
cts.S.log.Write(cts.Sid, LOG_ERROR, "Unknown websocket connection for rpty - websocket %v", ws.RemoteAddr())
return fmt.Errorf("unknown websocket connection for rpty - %v", ws.RemoteAddr())
}
id = rpty.id
@@ -730,14 +766,24 @@ func (cts *ServerConn) StopRpty(ws *websocket.Conn) error {
// send the stop request to the client side
err = cts.pss.Send(MakeRptyStopPacket(id, ""))
if err != nil {
return fmt.Errorf("unable to send stop rpty request to client - %s", err.Error())
cts.S.log.Write(cts.Sid, LOG_ERROR, "Failed to send RPTY_STOP(%d) for server %s websocket %v - %s", id, cts.RemoteAddr, ws.RemoteAddr(), err.Error())
// carry on
}
// delete the rpty entry from the maps as the websocket
// handler is ending
cts.rpty_mtx.Lock()
delete(cts.rpty_map, id)
delete(cts.rpty_map_by_ws, ws)
cts.rpty_mtx.Unlock()
cts.S.stats.rpty_sessions.Add(-1)
cts.S.log.Write(cts.Sid, LOG_INFO, "Stopped rpty(%d) for server %s websocket %vs", id, cts.RemoteAddr, ws.RemoteAddr())
return nil
}
func (cts *ServerConn) StopRptyWsById(id uint64, msg string) error {
// called this when the stop requested comes from the client
// call this when the stop requested comes from the client.
// abort the websocket side.
var rpty *ServerRpty
@@ -746,11 +792,12 @@ func (cts *ServerConn) StopRptyWsById(id uint64, msg string) error {
cts.rpty_mtx.Lock()
rpty, ok = cts.rpty_map[id]
if !ok {
cts.rpty_mtx.Unlock()
return fmt.Errorf("unknown rpty id %d", id)
}
rpty.ws.Close()
cts.rpty_mtx.Unlock()
rpty.ReqStop()
cts.S.log.Write(cts.Sid, LOG_INFO, "Stopped rpty(%d) for %s - %s", id, cts.RemoteAddr, msg)
return nil
}
@@ -764,6 +811,7 @@ func (cts *ServerConn) WriteRpty(ws *websocket.Conn, data []byte) error {
cts.rpty_mtx.Lock()
rpty, ok = cts.rpty_map_by_ws[ws]
if !ok {
cts.rpty_mtx.Unlock()
return fmt.Errorf("unknown ws connection for rpty - %v", ws.RemoteAddr())
}
@@ -787,6 +835,7 @@ func (cts *ServerConn) WriteRptySize(ws *websocket.Conn, data []byte) error {
cts.rpty_mtx.Lock()
rpty, ok = cts.rpty_map_by_ws[ws]
if !ok {
cts.rpty_mtx.Unlock()
return fmt.Errorf("unknown ws connection for rpty size - %v", ws.RemoteAddr())
}
@@ -812,33 +861,16 @@ func (cts *ServerConn) ReadRptyAndWriteWs(id uint64, data []byte) error {
cts.rpty_mtx.Unlock()
return fmt.Errorf("unknown rpty id - %d", id)
}
cts.rpty_mtx.Unlock()
err = send_ws_data_for_xterm(rpty.ws, "iov", string(data))
if err != nil {
cts.rpty_mtx.Unlock()
return fmt.Errorf("failed to write rpty data(%d) to ws - %s", id, err.Error())
}
cts.rpty_mtx.Unlock()
return nil
}
func (cts *ServerConn) ReportPacket(route_id RouteId, pts_id PeerId, packet_type PACKET_KIND, event_data interface{}) error {
var r *ServerRoute
var ok bool
cts.route_mtx.Lock()
r, ok = cts.route_map[route_id]
if !ok {
cts.route_mtx.Unlock()
return fmt.Errorf("non-existent route id - %d", route_id)
}
cts.route_mtx.Unlock()
return r.ReportPacket(pts_id, packet_type, event_data)
}
func (cts *ServerConn) HandleRptyEvent(packet_type PACKET_KIND, evt *RptyEvent) error {
switch packet_type {
case PACKET_KIND_RPTY_STOP:
@@ -853,6 +885,80 @@ func (cts *ServerConn) HandleRptyEvent(packet_type PACKET_KIND, evt *RptyEvent)
return nil
}
// Rpx
func (cts *ServerConn) StartRpxWebById(srpx* ServerRpx, id uint64, data []byte) error {
// pass the initial response to code in server-rpx.go
srpx.start_chan <- data
return nil
}
func (cts *ServerConn) StopRpxWebById(srpx* ServerRpx, id uint64) error {
srpx.ReqStop()
return nil
}
func (cts *ServerConn) WroteRpxWebById(srpx* ServerRpx, id uint64, data []byte) error {
var err error
_, err = srpx.pw.Write(data)
if err != nil {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Failed to write rpx data(%d) to rpx pipe - %s", id, err.Error())
srpx.ReqStop()
}
return err
}
func (cts *ServerConn) EofRpxWebById(srpx* ServerRpx, id uint64) error {
srpx.ReqStop()
return nil
}
func (cts *ServerConn) HandleRpxEvent(packet_type PACKET_KIND, evt *RpxEvent) error {
var ok bool
var rpx* ServerRpx
cts.rpx_mtx.Lock()
rpx, ok = cts.rpx_map[evt.Id]
if !ok {
cts.rpx_mtx.Unlock()
return fmt.Errorf("unknown rpx id - %v", evt.Id)
}
cts.rpx_mtx.Unlock()
switch packet_type {
case PACKET_KIND_RPX_START:
return cts.StartRpxWebById(rpx, evt.Id, evt.Data)
case PACKET_KIND_RPX_STOP:
// stop requested from the server
return cts.StopRpxWebById(rpx, evt.Id)
case PACKET_KIND_RPX_EOF:
return cts.EofRpxWebById(rpx, evt.Id)
case PACKET_KIND_RPX_DATA:
return cts.WroteRpxWebById(rpx, evt.Id, evt.Data)
}
// ignore other packet types
return nil
}
// Rpx
func (cts *ServerConn) ReportPacket(route_id RouteId, pts_id PeerId, packet_type PACKET_KIND, event_data interface{}) error {
var r *ServerRoute
var ok bool
cts.route_mtx.Lock()
r, ok = cts.route_map[route_id]
if !ok {
cts.route_mtx.Unlock()
return fmt.Errorf("non-existent route id - %d", route_id)
}
cts.route_mtx.Unlock()
return r.ReportPacket(pts_id, packet_type, event_data)
}
func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
var pkt *Packet
var err error
@@ -1055,10 +1161,30 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
err = cts.HandleRptyEvent(pkt.Kind, x.RptyEvt)
if err != nil {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Failed to handle %s event for rpty(%d) from %s - %s", pkt.Kind.String(), x.RptyEvt.Id, cts.RemoteAddr, err.Error())
} else {
} else {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Handled %s event for rpty(%d) from %s", pkt.Kind.String(), x.RptyEvt.Id, cts.RemoteAddr)
}
}
} else {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Invalid %s packet from %s", pkt.Kind.String(), cts.RemoteAddr)
}
case PACKET_KIND_RPX_START: // the client sends the response header using START
fallthrough
case PACKET_KIND_RPX_STOP:
fallthrough
case PACKET_KIND_RPX_EOF:
fallthrough
case PACKET_KIND_RPX_DATA:
var x *Packet_RpxEvt
var ok bool
x, ok = pkt.U.(*Packet_RpxEvt)
if ok {
err = cts.HandleRpxEvent(pkt.Kind, x.RpxEvt)
if err != nil {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Failed to handle %s event for rpx(%d) from %s - %s", pkt.Kind.String(), x.RpxEvt.Id, cts.RemoteAddr, err.Error())
} else {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Handled %s event for rpx(%d) from %s", pkt.Kind.String(), x.RpxEvt.Id, cts.RemoteAddr)
}
} else {
cts.S.log.Write(cts.Sid, LOG_ERROR, "Invalid %s packet from %s", pkt.Kind.String(), cts.RemoteAddr)
}
@@ -1066,17 +1192,26 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
}
done:
// arrange to break all rpty resources
cts.rpty_mtx.Lock()
if len(cts.rpty_map) > 0 {
var rpty *ServerRpty
for _, rpty = range cts.rpty_map {
rpty.ws.Close()
rpty.ReqStop()
}
}
cts.rpty_mtx.Unlock()
// arrange to break all rpx resources
cts.rpx_mtx.Lock()
if len(cts.rpx_map) > 0 {
var rpx *ServerRpx
for _, rpx = range cts.rpx_map {
rpx.ReqStop()
}
}
cts.rpx_mtx.Unlock()
cts.S.log.Write(cts.Sid, LOG_INFO, "RPC stream receiver ended")
}
@@ -1109,7 +1244,7 @@ func (cts *ServerConn) RunTask(wg *sync.WaitGroup) {
cts.route_wg.Add(1)
// start the loop inside a goroutine so that route_wg counter
// is likely to be greater than 1 what Wait() is called.
// is likely to be greater than 1 when Wait() is called.
go func() {
waiting_loop:
for {
@@ -1145,11 +1280,22 @@ func (cts *ServerConn) RunTask(wg *sync.WaitGroup) {
func (cts *ServerConn) ReqStop() {
if cts.stop_req.CompareAndSwap(false, true) {
var r *ServerRoute
var rpty *ServerRpty
var srpx *ServerRpx
cts.route_mtx.Lock()
for _, r = range cts.route_map { r.ReqStop() }
cts.route_mtx.Unlock()
cts.rpty_mtx.Lock()
for _, rpty = range cts.rpty_map { rpty.ReqStop() }
cts.rpty_mtx.Unlock()
cts.rpx_mtx.Lock()
for _, srpx = range cts.rpx_map { srpx.ReqStop() }
cts.rpx_mtx.Unlock()
// there is no good way to break a specific connection client to
// the grpc server. while the global grpc server is closed in
// ReqStop() for Server, the individuation connection is closed
@@ -1359,13 +1505,14 @@ func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServ
type server_http_log_writer struct {
svr *Server
depth int
}
func (hlw *server_http_log_writer) Write(p []byte) (n int, err error) {
// the standard http.Server always requires *log.Logger
// use this iowriter to create a logger to pass it to the http server.
// since this is another log write wrapper, give adjustment value
hlw.svr.log.WriteWithCallDepth("", LOG_INFO, +1, string(p))
hlw.svr.log.WriteWithCallDepth("", LOG_INFO, hlw.depth, string(p))
return len(p), nil
}
@@ -1422,13 +1569,13 @@ func (s *Server) WrapHttpHandler(handler ServerHttpHandler) http.Handler {
WriteEmptyRespHeader(w, status_code)
}
}
time_taken = time.Now().Sub(start_time)
time_taken = time.Since(start_time) // time.Now().Sub(start_time)
if status_code > 0 {
if err != nil {
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s %d %.9f - %s", req.RemoteAddr, req.Method, get_raw_url_path(req), status_code, time_taken.Seconds(), err.Error())
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s %d %.9f - %s", req.RemoteAddr, req.Method, req.RequestURI, status_code, time_taken.Seconds(), err.Error())
} else {
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s %d %.9f", req.RemoteAddr, req.Method, get_raw_url_path(req), status_code, time_taken.Seconds())
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s %d %.9f", req.RemoteAddr, req.Method, req.RequestURI, status_code, time_taken.Seconds())
}
}
})
@@ -1440,7 +1587,7 @@ func (s *Server) SafeWrapWebsocketHandler(handler websocket.Handler) http.Handle
!strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
var status_code int
status_code = WriteEmptyRespHeader(w, http.StatusBadRequest)
s.log.Write("", LOG_INFO, "[%s] %s %s %d[non-websocket]", req.RemoteAddr, req.Method, get_raw_url_path(req), status_code)
s.log.Write("", LOG_INFO, "[%s] %s %s %d[non-websocket]", req.RemoteAddr, req.Method, req.RequestURI, status_code)
return
}
handler.ServeHTTP(w, req)
@@ -1454,21 +1601,19 @@ func (s *Server) WrapWebsocketHandler(handler ServerWebsocketHandler) websocket.
var start_time time.Time
var time_taken time.Duration
var req *http.Request
var raw_url_path string
req = ws.Request()
raw_url_path = get_raw_url_path(req)
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws]", req.RemoteAddr, req.Method, raw_url_path)
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws]", req.RemoteAddr, req.Method, req.RequestURI)
start_time = time.Now()
status_code, err = handler.ServeWebsocket(ws)
time_taken = time.Now().Sub(start_time)
time_taken = time.Since(start_time) // time.Now().Sub(start_time)
if status_code > 0 {
if err != nil {
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws] %d %.9f - %s", req.RemoteAddr, req.Method, raw_url_path, status_code, time_taken.Seconds(), err.Error())
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws] %d %.9f - %s", req.RemoteAddr, req.Method, req.RequestURI, status_code, time_taken.Seconds(), err.Error())
} else {
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws] %d %.9f", req.RemoteAddr, req.Method, raw_url_path, status_code, time_taken.Seconds())
s.log.Write(handler.Identity(), LOG_INFO, "[%s] %s %s [ws] %d %.9f", req.RemoteAddr, req.Method, req.RequestURI, status_code, time_taken.Seconds())
}
}
})
@@ -1479,7 +1624,6 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
var l *net.TCPListener
var rpcaddr *net.TCPAddr
var addr string
var gl *net.TCPListener
var i int
var hs_log *log.Logger
var opts []grpc.ServerOption
@@ -1536,7 +1680,7 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
// ---------------------------------------------------------
hs_log = log.New(&server_http_log_writer{svr: &s}, "", 0)
hs_log = log.New(&server_http_log_writer{svr: &s, depth: +2}, "", 0)
// ---------------------------------------------------------
@@ -1626,7 +1770,8 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.ctl[i] = &http.Server{
Addr: cfg.CtlAddrs[i],
Handler: s.ctl_mux,
TLSConfig: s.Cfg.CtlTls,
// race condition issues without cloning. the http package modifies some fields in the configuration object
TLSConfig: cfg.CtlTls.Clone(),
ErrorLog: hs_log,
// TODO: more settings
}
@@ -1638,12 +1783,11 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.rpx_mux.Handle("/", s.WrapHttpHandler(&server_rpx{ S: &s, Id: HS_ID_RPX }))
s.rpx = make([]*http.Server, len(cfg.RpxAddrs))
for i = 0; i < len(cfg.RpxAddrs); i++ {
s.rpx[i] = &http.Server{
Addr: cfg.RpxAddrs[i],
Handler: s.rpx_mux,
TLSConfig: cfg.RpxTls,
TLSConfig: cfg.RpxTls.Clone(),
ErrorLog: hs_log,
// TODO: more settings
}
@@ -1696,7 +1840,7 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.pxy[i] = &http.Server{
Addr: cfg.PxyAddrs[i],
Handler: s.pxy_mux,
TLSConfig: cfg.PxyTls,
TLSConfig: cfg.PxyTls.Clone(),
ErrorLog: hs_log,
// TODO: more settings
}
@@ -1746,7 +1890,7 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.wpx[i] = &http.Server{
Addr: cfg.WpxAddrs[i],
Handler: s.wpx_mux,
TLSConfig: cfg.WpxTls,
TLSConfig: cfg.WpxTls.Clone(),
ErrorLog: hs_log,
}
}
@@ -1757,11 +1901,11 @@ func NewServer(ctx context.Context, name string, logger Logger, cfg *ServerConfi
s.stats.peers.Store(0)
s.stats.ssh_proxy_sessions.Store(0)
s.stats.pty_sessions.Store(0)
s.stats.rpty_sessions.Store(0)
return &s, nil
oops:
if gl != nil { gl.Close() }
for _, l = range s.rpc { l.Close() }
s.rpc = make([]*net.TCPListener, 0)
return nil, err
@@ -1840,16 +1984,10 @@ func (s *Server) RunTask(wg *sync.WaitGroup) {
go s.run_grpc_server(idx, &s.rpc_wg)
}
// most work is done by in separate goroutines (s.run_grp_server)
// this loop serves as a placeholder to prevent the logic flow from
// most work is done in separate goroutines (s.run_grp_server)
// this read on the stop channel serves as a placeholder to prevent the logic flow from
// descening down to s.ReqStop()
task_loop:
for {
select {
case <-s.stop_chan:
break task_loop
}
}
<-s.stop_chan
s.ReqStop()
@@ -1863,8 +2001,52 @@ task_loop:
s.rpc_svr.Stop()
}
func (s *Server) RunCtlTask(wg *sync.WaitGroup) {
func (s* Server) run_single_ctl_server(i int, cs *http.Server, wg* sync.WaitGroup) {
var l net.Listener
var err error
defer wg.Done()
s.log.Write("", LOG_INFO, "Control channel[%d] started on %s", i, cs.Addr)
if s.stop_req.Load() == false {
// defeat hard-coded "tcp" in ListenAndServe() and ListenAndServeTLS()
// err = cs.ListenAndServe()
// err = cs.ListenAndServeTLS("", "")
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.ctl_addrs_mtx.Lock()
node = s.ctl_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.ctl_addrs_mtx.Unlock()
if s.Cfg.CtlTls == nil {
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.CtlTls must provide a certificate and a key
}
s.ctl_addrs_mtx.Lock()
s.ctl_addrs.Remove(node)
s.ctl_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Control channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Control channel[%d] error - %s", i, err.Error())
}
}
func (s *Server) RunCtlTask(wg *sync.WaitGroup) {
var ctl *http.Server
var idx int
var l_wg sync.WaitGroup
@@ -1873,54 +2055,55 @@ func (s *Server) RunCtlTask(wg *sync.WaitGroup) {
for idx, ctl = range s.ctl {
l_wg.Add(1)
go func(i int, cs *http.Server) {
var l net.Listener
s.log.Write("", LOG_INFO, "Control channel[%d] started on %s", i, cs.Addr)
if s.stop_req.Load() == false {
// defeat hard-coded "tcp" in ListenAndServe() and ListenAndServeTLS()
// err = cs.ListenAndServe()
// err = cs.ListenAndServeTLS("", "")
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.ctl_addrs_mtx.Lock()
node = s.ctl_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.ctl_addrs_mtx.Unlock()
if s.Cfg.CtlTls == nil {
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.CtlTls must provide a certificate and a key
}
s.ctl_addrs_mtx.Lock()
s.ctl_addrs.Remove(node)
s.ctl_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Control channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Control channel[%d] error - %s", i, err.Error())
}
l_wg.Done()
}(idx, ctl)
go s.run_single_ctl_server(idx, ctl, &l_wg);
}
l_wg.Wait()
}
func (s *Server) RunRpxTask(wg *sync.WaitGroup) {
func (s *Server) run_single_rpx_server(i int, cs *http.Server, wg* sync.WaitGroup) {
var l net.Listener
var err error
defer wg.Done()
s.log.Write("", LOG_INFO, "RPX channel[%d] started on %s", i, s.Cfg.RpxAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.rpx_addrs_mtx.Lock()
node = s.rpx_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.rpx_addrs_mtx.Unlock()
if s.Cfg.RpxTls == nil { // TODO: change this
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.RpxTls must provide a certificate and a key
}
s.rpx_addrs_mtx.Lock()
s.rpx_addrs.Remove(node)
s.rpx_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "RPX channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "RPX channel[%d] error - %s", i, err.Error())
}
}
func (s *Server) RunRpxTask(wg *sync.WaitGroup) {
var rpx *http.Server
var idx int
var l_wg sync.WaitGroup
@@ -1929,51 +2112,54 @@ func (s *Server) RunRpxTask(wg *sync.WaitGroup) {
for idx, rpx = range s.rpx {
l_wg.Add(1)
go func(i int, cs *http.Server) {
var l net.Listener
s.log.Write("", LOG_INFO, "RPX channel[%d] started on %s", i, s.Cfg.RpxAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.rpx_addrs_mtx.Lock()
node = s.rpx_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.rpx_addrs_mtx.Unlock()
if s.Cfg.RpxTls == nil { // TODO: change this
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.RpxTls must provide a certificate and a key
}
s.rpx_addrs_mtx.Lock()
s.rpx_addrs.Remove(node)
s.rpx_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "RPX channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "RPX channel[%d] error - %s", i, err.Error())
}
l_wg.Done()
}(idx, rpx)
go s.run_single_rpx_server(idx, rpx, &l_wg)
}
l_wg.Wait()
}
func (s *Server) RunPxyTask(wg *sync.WaitGroup) {
func (s *Server) run_single_pxy_server(i int, cs *http.Server, wg* sync.WaitGroup) {
var l net.Listener
var err error
defer wg.Done()
s.log.Write("", LOG_INFO, "Proxy channel[%d] started on %s", i, s.Cfg.PxyAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.pxy_addrs_mtx.Lock()
node = s.pxy_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.pxy_addrs_mtx.Unlock()
if s.Cfg.PxyTls == nil { // TODO: change this
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.PxyTls must provide a certificate and a key
}
s.pxy_addrs_mtx.Lock()
s.pxy_addrs.Remove(node)
s.pxy_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Proxy channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Proxy channel[%d] error - %s", i, err.Error())
}
}
func (s *Server) RunPxyTask(wg *sync.WaitGroup) {
var pxy *http.Server
var idx int
var l_wg sync.WaitGroup
@@ -1982,51 +2168,55 @@ func (s *Server) RunPxyTask(wg *sync.WaitGroup) {
for idx, pxy = range s.pxy {
l_wg.Add(1)
go func(i int, cs *http.Server) {
var l net.Listener
s.log.Write("", LOG_INFO, "Proxy channel[%d] started on %s", i, s.Cfg.PxyAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.pxy_addrs_mtx.Lock()
node = s.pxy_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.pxy_addrs_mtx.Unlock()
if s.Cfg.PxyTls == nil { // TODO: change this
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.PxyTls must provide a certificate and a key
}
s.pxy_addrs_mtx.Lock()
s.pxy_addrs.Remove(node)
s.pxy_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Proxy channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Proxy channel[%d] error - %s", i, err.Error())
}
l_wg.Done()
}(idx, pxy)
go s.run_single_pxy_server(idx, pxy, &l_wg);
}
l_wg.Wait()
}
func (s *Server) RunWpxTask(wg *sync.WaitGroup) {
func (s *Server) run_single_wpx_server(i int, cs *http.Server, wg* sync.WaitGroup) {
var l net.Listener
var err error
defer wg.Done()
s.log.Write("", LOG_INFO, "Wpx channel[%d] started on %s", i, s.Cfg.WpxAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.wpx_addrs_mtx.Lock()
node = s.wpx_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.wpx_addrs_mtx.Unlock()
if s.Cfg.WpxTls == nil {
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.WpxTls must provide a certificate and a key
}
s.wpx_addrs_mtx.Lock()
s.wpx_addrs.Remove(node)
s.wpx_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Wpx channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Wpx channel[%d] error - %s", i, err.Error())
}
}
func (s *Server) RunWpxTask(wg *sync.WaitGroup) {
var wpx *http.Server
var idx int
var l_wg sync.WaitGroup
@@ -2035,45 +2225,7 @@ func (s *Server) RunWpxTask(wg *sync.WaitGroup) {
for idx, wpx = range s.wpx {
l_wg.Add(1)
go func(i int, cs *http.Server) {
var l net.Listener
s.log.Write("", LOG_INFO, "Wpx channel[%d] started on %s", i, s.Cfg.WpxAddrs[i])
if s.stop_req.Load() == false {
l, err = net.Listen(TcpAddrStrClass(cs.Addr), cs.Addr)
if err == nil {
if s.stop_req.Load() == false {
var node *list.Element
s.wpx_addrs_mtx.Lock()
node = s.wpx_addrs.PushBack(l.Addr().(*net.TCPAddr))
s.wpx_addrs_mtx.Unlock()
if s.Cfg.WpxTls == nil {
err = cs.Serve(l)
} else {
err = cs.ServeTLS(l, "", "") // s.Cfg.WpxTls must provide a certificate and a key
}
s.wpx_addrs_mtx.Lock()
s.wpx_addrs.Remove(node)
s.wpx_addrs_mtx.Unlock()
} else {
err = fmt.Errorf("stop requested")
}
l.Close()
}
} else {
err = fmt.Errorf("stop requested")
}
if errors.Is(err, http.ErrServerClosed) {
s.log.Write("", LOG_INFO, "Wpx channel[%d] ended", i)
} else {
s.log.Write("", LOG_ERROR, "Wpx channel[%d] error - %s", i, err.Error())
}
l_wg.Done()
}(idx, wpx)
go s.run_single_wpx_server(idx, wpx, &l_wg)
}
l_wg.Wait()
}
@@ -2141,6 +2293,7 @@ func (s *Server) AddNewServerConn(remote_addr *net.Addr, local_addr *net.Addr, p
cts.rpty_map = make(ServerRptyMap)
cts.rpty_map_by_ws = make(ServerRptyMapByWs)
cts.rpx_map = make(ServerRpxMap)
s.cts_mtx.Lock()