added the proxy service for http/https client peer on the server side. work in progress
This commit is contained in:
parent
41e7222b98
commit
f6ea852e61
1
Makefile
1
Makefile
@ -13,6 +13,7 @@ SRCS=\
|
||||
server.go \
|
||||
server-ctl.go \
|
||||
server-peer.go \
|
||||
server-proxy.go \
|
||||
server-ws.go \
|
||||
system.go
|
||||
|
||||
|
@ -5,6 +5,7 @@ import "net/http"
|
||||
import "net/url"
|
||||
import "runtime"
|
||||
import "strconv"
|
||||
import "unsafe"
|
||||
|
||||
/*
|
||||
* POST GET PUT DELETE
|
||||
@ -31,8 +32,9 @@ type json_in_client_conn struct {
|
||||
|
||||
type json_in_client_route struct {
|
||||
ClientPeerAddr string `json:"client-peer-addr"`
|
||||
ServerPeerNet string `json:"server-peer-net"` // allowed network in prefix notation
|
||||
ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"`
|
||||
ServerPeerOption string `json:"server-peer-option"`
|
||||
ServerPeerServiceAddr string `json:"server-peer-service-addr"` // desired listening address on the server side
|
||||
ServerPeerServiceNet string `json:"server-peer-service-net"` // permitted network in prefix notation
|
||||
}
|
||||
|
||||
type json_out_client_conn_id struct {
|
||||
@ -55,9 +57,9 @@ type json_out_client_route_id struct {
|
||||
type json_out_client_route struct {
|
||||
Id RouteId `json:"id"`
|
||||
ClientPeerAddr string `json:"client-peer-addr"`
|
||||
ServerPeerListenAddr string `json:"server-peer-listen-addr"`
|
||||
ServerPeerNet string `json:"server-peer-net"`
|
||||
ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"`
|
||||
ServerPeerOption string `json:"server-peer-option"`
|
||||
ServerPeerListenAddr string `json:"server-peer-service-addr"`
|
||||
ServerPeerNet string `json:"server-peer-service-net"`
|
||||
}
|
||||
|
||||
type json_out_client_peer struct {
|
||||
@ -152,7 +154,7 @@ func (ctl *client_ctl_client_conns) ServeHTTP(w http.ResponseWriter, req *http.R
|
||||
ClientPeerAddr: r.peer_addr,
|
||||
ServerPeerListenAddr: r.server_peer_listen_addr.String(),
|
||||
ServerPeerNet: r.server_peer_net,
|
||||
ServerPeerProto: r.server_peer_proto,
|
||||
ServerPeerOption: r.server_peer_proto.string(),
|
||||
})
|
||||
}
|
||||
js = append(js, json_out_client_conn{
|
||||
@ -242,7 +244,7 @@ func (ctl *client_ctl_client_conns_id) ServeHTTP(w http.ResponseWriter, req *htt
|
||||
|
||||
conn_id = req.PathValue("conn_id")
|
||||
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, 32)
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
@ -270,7 +272,7 @@ func (ctl *client_ctl_client_conns_id) ServeHTTP(w http.ResponseWriter, req *htt
|
||||
ClientPeerAddr: r.peer_addr,
|
||||
ServerPeerListenAddr: r.server_peer_listen_addr.String(),
|
||||
ServerPeerNet: r.server_peer_net,
|
||||
ServerPeerProto: r.server_peer_proto,
|
||||
ServerPeerOption: r.server_peer_proto.string(),
|
||||
})
|
||||
}
|
||||
js = &json_out_client_conn{
|
||||
@ -326,10 +328,10 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r
|
||||
|
||||
conn_id = req.PathValue("conn_id")
|
||||
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, 32)
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id }); err != nil { goto oops }
|
||||
goto done
|
||||
}
|
||||
|
||||
@ -353,7 +355,7 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r
|
||||
ClientPeerAddr: r.peer_addr,
|
||||
ServerPeerListenAddr: r.server_peer_listen_addr.String(),
|
||||
ServerPeerNet: r.server_peer_net,
|
||||
ServerPeerProto: r.server_peer_proto,
|
||||
ServerPeerOption: r.server_peer_proto.string(),
|
||||
})
|
||||
}
|
||||
cts.route_mtx.Unlock()
|
||||
@ -364,14 +366,21 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r
|
||||
case http.MethodPost:
|
||||
var jcr json_in_client_route
|
||||
var r *ClientRoute
|
||||
var server_peer_proto RouteOption
|
||||
|
||||
err = json.NewDecoder(req.Body).Decode(&jcr)
|
||||
if err != nil || jcr.ClientPeerAddr == "" || jcr.ServerPeerProto < 0 || jcr.ServerPeerProto > ROUTE_PROTO_TCP6 {
|
||||
if err != nil || jcr.ClientPeerAddr == "" {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
goto done
|
||||
}
|
||||
|
||||
r, err = cts.AddNewClientRoute(jcr.ClientPeerAddr, jcr.ServerPeerNet, jcr.ServerPeerProto)
|
||||
server_peer_proto = string_to_route_proto(jcr.ServerPeerOption)
|
||||
if server_peer_proto == RouteOption(ROUTE_OPTION_UNSPEC) {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
goto done
|
||||
}
|
||||
|
||||
r, err = cts.AddNewClientRoute(jcr.ClientPeerAddr, jcr.ServerPeerServiceAddr, jcr.ServerPeerServiceNet, server_peer_proto)
|
||||
if err != nil {
|
||||
status_code = http.StatusInternalServerError; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: err.Error()}); err != nil { goto oops }
|
||||
@ -424,13 +433,13 @@ func (ctl *client_ctl_client_conns_id_routes_id) ServeHTTP(w http.ResponseWriter
|
||||
conn_id = req.PathValue("conn_id")
|
||||
route_id = req.PathValue("route_id")
|
||||
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, 32)
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
goto done
|
||||
}
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, 32)
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops }
|
||||
@ -459,7 +468,7 @@ func (ctl *client_ctl_client_conns_id_routes_id) ServeHTTP(w http.ResponseWriter
|
||||
ClientPeerAddr: r.peer_addr,
|
||||
ServerPeerListenAddr: r.server_peer_listen_addr.String(),
|
||||
ServerPeerNet: r.server_peer_net,
|
||||
ServerPeerProto: r.server_peer_proto,
|
||||
ServerPeerOption: r.server_peer_proto.string(),
|
||||
})
|
||||
if err != nil { goto oops }
|
||||
|
||||
@ -511,7 +520,7 @@ func (ctl *client_ctl_client_conns_id_routes_id_peers) ServeHTTP(w http.Response
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
goto done
|
||||
}
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, 32)
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops }
|
||||
@ -595,7 +604,7 @@ func (ctl *client_ctl_client_conns_id_routes_id_peers_id) ServeHTTP(w http.Respo
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
goto done
|
||||
}
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, 32)
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops }
|
||||
|
@ -3,6 +3,7 @@ package hodu
|
||||
import "errors"
|
||||
import "io"
|
||||
import "net"
|
||||
import "strings"
|
||||
import "sync"
|
||||
|
||||
func NewClientPeerConn(r *ClientRoute, c *net.TCPConn, id PeerId, pts_raddr string, pts_laddr string) *ClientPeerConn {
|
||||
@ -29,7 +30,7 @@ func (cpc *ClientPeerConn) RunTask(wg *sync.WaitGroup) error {
|
||||
for {
|
||||
n, err = cpc.conn.Read(buf[:])
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "use of closed network connection") { // i hate checking this condition with strings.Contains()
|
||||
cpc.route.cts.cli.log.Write(cpc.route.cts.sid, LOG_INFO,
|
||||
"Client-side peer(%d,%d,%s,%s) closed",
|
||||
cpc.route.id, cpc.conn_id, cpc.conn.RemoteAddr().String(), cpc.conn.LocalAddr().String())
|
||||
|
71
client.go
71
client.go
@ -8,6 +8,7 @@ import "log"
|
||||
import "math/rand"
|
||||
import "net"
|
||||
import "net/http"
|
||||
import "strings"
|
||||
import "sync"
|
||||
import "sync/atomic"
|
||||
import "time"
|
||||
@ -101,9 +102,12 @@ type ClientRoute struct {
|
||||
cts *ClientConn
|
||||
id RouteId
|
||||
peer_addr string
|
||||
server_peer_listen_addr *net.TCPAddr
|
||||
peer_proto RouteOption
|
||||
|
||||
server_peer_listen_addr *net.TCPAddr // actual service-side service address
|
||||
server_peer_addr string // desired server-side service address
|
||||
server_peer_net string
|
||||
server_peer_proto ROUTE_PROTO
|
||||
server_peer_proto RouteOption
|
||||
|
||||
ptc_mtx sync.Mutex
|
||||
ptc_map ClientPeerConnMap
|
||||
@ -151,7 +155,7 @@ func (g *GuardedPacketStreamClient) Context() context.Context {
|
||||
}*/
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server_peer_net string, server_peer_proto ROUTE_PROTO) *ClientRoute {
|
||||
func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server_peer_svc_addr string, server_peer_svc_net string, server_peer_proto RouteOption) *ClientRoute {
|
||||
var r ClientRoute
|
||||
|
||||
r.cts = cts
|
||||
@ -159,7 +163,11 @@ func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server
|
||||
r.ptc_map = make(ClientPeerConnMap)
|
||||
r.ptc_cancel_map = make(ClientPeerCancelFuncMap)
|
||||
r.peer_addr = client_peer_addr // client-side peer
|
||||
r.server_peer_net = server_peer_net // permitted network for server-side peer
|
||||
// if the client_peer_addr is a domain name, it can't tell between tcp4 and tcp6
|
||||
r.peer_proto = string_to_route_proto(tcp_addr_str_class(client_peer_addr))
|
||||
|
||||
r.server_peer_addr = server_peer_svc_addr
|
||||
r.server_peer_net = server_peer_svc_net // permitted network for server-side peer
|
||||
r.server_peer_proto = server_peer_proto
|
||||
r.stop_req.Store(false)
|
||||
r.stop_chan = make(chan bool, 8)
|
||||
@ -249,7 +257,7 @@ func (r *ClientRoute) RunTask(wg *sync.WaitGroup) {
|
||||
// most useful works are triggered by ReportEvent() and done by ConnectToPeer()
|
||||
defer wg.Done()
|
||||
|
||||
err = r.cts.psc.Send(MakeRouteStartPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_net))
|
||||
err = r.cts.psc.Send(MakeRouteStartPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_addr, r.server_peer_net))
|
||||
if err != nil {
|
||||
r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG,
|
||||
"Failed to send route_start for route(%d,%s,%v,%v) to %s",
|
||||
@ -273,7 +281,7 @@ done:
|
||||
r.ReqStop()
|
||||
r.ptc_wg.Wait() // wait for all peer tasks are finished
|
||||
|
||||
err = r.cts.psc.Send(MakeRouteStopPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_net))
|
||||
err = r.cts.psc.Send(MakeRouteStopPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_addr, r.server_peer_net))
|
||||
if err != nil {
|
||||
r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG,
|
||||
"Failed to route_stop for route(%d,%s,%v,%v) to %s - %s",
|
||||
@ -297,7 +305,7 @@ func (r *ClientRoute) ReqStop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ClientRoute) ConnectToPeer(pts_id PeerId, pts_raddr string, pts_laddr string, wg *sync.WaitGroup) {
|
||||
func (r *ClientRoute) ConnectToPeer(pts_id PeerId, route_proto RouteOption, pts_raddr string, pts_laddr string, wg *sync.WaitGroup) {
|
||||
var err error
|
||||
var conn net.Conn
|
||||
var real_conn *net.TCPConn
|
||||
@ -310,10 +318,14 @@ func (r *ClientRoute) ConnectToPeer(pts_id PeerId, pts_raddr string, pts_laddr s
|
||||
var tmout time.Duration
|
||||
var ok bool
|
||||
|
||||
// TODO: handle TTY
|
||||
// if route_proto & RouteOption(ROUTE_OPTION_TTY) it must create a pseudo-tty insteaad of connecting to tcp address
|
||||
//
|
||||
|
||||
defer wg.Done()
|
||||
|
||||
tmout = time.Duration(r.cts.cli.ptc_tmout)
|
||||
if tmout < 0 { tmout = 10 * time.Second}
|
||||
if tmout <= 0 { tmout = 10 * time.Second}
|
||||
ctx, cancel = context.WithTimeout(r.cts.cli.ctx, tmout)
|
||||
r.ptc_mtx.Lock()
|
||||
r.ptc_cancel_map[pts_id] = cancel
|
||||
@ -458,7 +470,7 @@ func (r *ClientRoute) ReportEvent(pts_id PeerId, event_type PACKET_KIND, event_d
|
||||
}
|
||||
} else {
|
||||
r.ptc_wg.Add(1)
|
||||
go r.ConnectToPeer(pts_id, pd.RemoteAddrStr, pd.LocalAddrStr, &r.ptc_wg)
|
||||
go r.ConnectToPeer(pts_id, r.peer_proto, pd.RemoteAddrStr, pd.LocalAddrStr, &r.ptc_wg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,7 +589,7 @@ func NewClientConn(c *Client, cfg *ClientConfig) *ClientConn {
|
||||
return &cts
|
||||
}
|
||||
|
||||
func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_net string, proto ROUTE_PROTO) (*ClientRoute, error) {
|
||||
func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_svc_addr string, server_peer_svc_net string, option RouteOption) (*ClientRoute, error) {
|
||||
var r *ClientRoute
|
||||
var id RouteId
|
||||
var nattempts RouteId
|
||||
@ -599,11 +611,7 @@ func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_net string, pr
|
||||
}
|
||||
}
|
||||
|
||||
//if cts.route_map[route_id] != nil {
|
||||
// cts.route_mtx.Unlock()
|
||||
// return nil, fmt.Errorf("existent route id - %d", route_id)
|
||||
//}
|
||||
r = NewClientRoute(cts, id, addr, server_peer_net, proto)
|
||||
r = NewClientRoute(cts, id, addr, server_peer_svc_addr, server_peer_svc_net, option)
|
||||
cts.route_map[id] = r
|
||||
cts.cli.stats.routes.Add(1)
|
||||
cts.route_mtx.Unlock()
|
||||
@ -701,10 +709,41 @@ func (cts *ClientConn) FindClientRouteById(route_id RouteId) *ClientRoute {
|
||||
|
||||
func (cts *ClientConn) AddClientRoutes(peer_addrs []string) error {
|
||||
var v string
|
||||
var port string
|
||||
var option RouteOption
|
||||
var va []string
|
||||
var svc_addr string
|
||||
var err error
|
||||
|
||||
for _, v = range peer_addrs {
|
||||
_, err = cts.AddNewClientRoute(v, "", ROUTE_PROTO_TCP)
|
||||
va = strings.Split(v, ",")
|
||||
if len(va) <= 0 || len(va) > 2 {
|
||||
return fmt.Errorf("invalid address %s")
|
||||
}
|
||||
|
||||
_, port, err = net.SplitHostPort(va[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid address %s", va[0], err.Error())
|
||||
}
|
||||
|
||||
if len(va) >= 2 {
|
||||
_, _, err = net.SplitHostPort(va[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid address %s", va[1], err.Error())
|
||||
}
|
||||
svc_addr = va[1]
|
||||
}
|
||||
|
||||
option = RouteOption(ROUTE_OPTION_TCP)
|
||||
// automatic determination of optioncol for common ports
|
||||
switch port {
|
||||
case "80":
|
||||
option |= RouteOption(ROUTE_OPTION_HTTP)
|
||||
case "443":
|
||||
option |= RouteOption(ROUTE_OPTION_HTTPS)
|
||||
}
|
||||
|
||||
_, err = cts.AddNewClientRoute(va[0], svc_addr, "", option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to add client route for %s - %s", v, err.Error())
|
||||
}
|
||||
|
@ -47,6 +47,10 @@ type CTLServiceConfig struct {
|
||||
Addrs []string `yaml:"addresses"`
|
||||
}
|
||||
|
||||
type PXYServiceConfig struct {
|
||||
Addrs []string `yaml:"addresses"`
|
||||
}
|
||||
|
||||
type RPCServiceConfig struct { // rpc server-side configuration
|
||||
Addrs []string `yaml:"addresses"`
|
||||
}
|
||||
@ -80,6 +84,11 @@ type ServerConfig struct {
|
||||
TLS ServerTLSConfig `yaml:"tls"`
|
||||
} `yaml:"ctl"`
|
||||
|
||||
PXY struct {
|
||||
Service PXYServiceConfig `yaml:"service"`
|
||||
TLS ServerTLSConfig `yaml:"tls"`
|
||||
} `yaml:"pxy"`
|
||||
|
||||
RPC struct {
|
||||
Service RPCServiceConfig `yaml:"service"`
|
||||
TLS ServerTLSConfig `yaml:"tls"`
|
||||
|
32
cmd/main.go
32
cmd/main.go
@ -143,10 +143,11 @@ func (sh *signal_handler) WriteLog(id string, level hodu.LogLevel, fmt string, a
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) error {
|
||||
func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg *ServerConfig) error {
|
||||
var s *hodu.Server
|
||||
var ctltlscfg *tls.Config
|
||||
var rpctlscfg *tls.Config
|
||||
var pxytlscfg *tls.Config
|
||||
var ctl_prefix string
|
||||
var logger *AppLogger
|
||||
var log_mask hodu.LogMask
|
||||
@ -158,13 +159,11 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro
|
||||
|
||||
if cfg != nil {
|
||||
ctltlscfg, err = make_tls_server_config(&cfg.CTL.TLS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil { return err }
|
||||
rpctlscfg, err = make_tls_server_config(&cfg.RPC.TLS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil { return err }
|
||||
pxytlscfg, err = make_tls_server_config(&cfg.PXY.TLS)
|
||||
if err != nil { return err }
|
||||
|
||||
if len(ctl_addrs) <= 0 {
|
||||
ctl_addrs = cfg.CTL.Service.Addrs
|
||||
@ -174,6 +173,10 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro
|
||||
rpc_addrs = cfg.RPC.Service.Addrs
|
||||
}
|
||||
|
||||
if len(pxy_addrs) <= 0 {
|
||||
pxy_addrs = cfg.PXY.Service.Addrs
|
||||
}
|
||||
|
||||
ctl_prefix = cfg.CTL.Service.Prefix
|
||||
log_mask = log_strings_to_mask(cfg.APP.LogMask)
|
||||
max_rpc_conns = cfg.APP.MaxRpcConns
|
||||
@ -191,9 +194,11 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro
|
||||
logger,
|
||||
ctl_addrs,
|
||||
rpc_addrs,
|
||||
pxy_addrs,
|
||||
ctl_prefix,
|
||||
ctltlscfg,
|
||||
rpctlscfg,
|
||||
pxytlscfg,
|
||||
max_rpc_conns,
|
||||
max_peers)
|
||||
if err != nil {
|
||||
@ -202,6 +207,7 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro
|
||||
|
||||
s.StartService(nil)
|
||||
s.StartCtlService()
|
||||
s.StartPxyService()
|
||||
s.StartExtService(&signal_handler{svc:s}, nil)
|
||||
s.WaitForTermination()
|
||||
|
||||
@ -278,13 +284,15 @@ func main() {
|
||||
if len(os.Args) < 2 { goto wrong_usage }
|
||||
|
||||
if strings.EqualFold(os.Args[1], "server") {
|
||||
var rpc_addrs[] string
|
||||
var ctl_addrs[] string
|
||||
var rpc_addrs []string
|
||||
var ctl_addrs []string
|
||||
var pxy_addrs []string
|
||||
var cfgfile string
|
||||
var cfg *ServerConfig
|
||||
|
||||
ctl_addrs = make([]string, 0)
|
||||
rpc_addrs = make([]string, 0)
|
||||
pxy_addrs = make([]string, 0)
|
||||
|
||||
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
flgs.Func("ctl-on", "specify a listening address for control channel", func(v string) error {
|
||||
@ -295,6 +303,10 @@ func main() {
|
||||
rpc_addrs = append(rpc_addrs, v)
|
||||
return nil
|
||||
})
|
||||
flgs.Func("pxy-on", "specify a proxy listening address", func(v string) error {
|
||||
pxy_addrs = append(pxy_addrs, v)
|
||||
return nil
|
||||
})
|
||||
flgs.Func("config-file", "specify a configuration file path", func(v string) error {
|
||||
cfgfile = v
|
||||
return nil
|
||||
@ -317,7 +329,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
err = server_main(ctl_addrs, rpc_addrs, cfg)
|
||||
err = server_main(ctl_addrs, rpc_addrs, pxy_addrs, cfg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error())
|
||||
goto oops
|
||||
|
68
hodu.go
68
hodu.go
@ -1,10 +1,13 @@
|
||||
package hodu
|
||||
|
||||
import "net/http"
|
||||
import "net/netip"
|
||||
import "os"
|
||||
import "runtime"
|
||||
import "strings"
|
||||
import "sync"
|
||||
|
||||
|
||||
const HODU_RPC_VERSION uint32 = 0x010000
|
||||
|
||||
type LogLevel int
|
||||
@ -20,6 +23,9 @@ const (
|
||||
const LOG_ALL LogMask = LogMask(LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR)
|
||||
const LOG_NONE LogMask = LogMask(0)
|
||||
|
||||
var IPV4_PREFIX_ZERO = netip.MustParsePrefix("0.0.0.0/0")
|
||||
var IPV6_PREFIX_ZERO = netip.MustParsePrefix("::/0")
|
||||
|
||||
type Logger interface {
|
||||
Write(id string, level LogLevel, fmtstr string, args ...interface{})
|
||||
}
|
||||
@ -33,20 +39,68 @@ type Service interface {
|
||||
}
|
||||
|
||||
func tcp_addr_str_class(addr string) string {
|
||||
// the string is supposed to be addr:port
|
||||
|
||||
if len(addr) > 0 {
|
||||
switch addr[0] {
|
||||
case '[':
|
||||
return "tcp6"
|
||||
case ':':
|
||||
return "tcp"
|
||||
default:
|
||||
return "tcp4"
|
||||
var ap netip.AddrPort
|
||||
var err error
|
||||
ap, err = netip.ParseAddrPort(addr)
|
||||
if err == nil {
|
||||
if ap.Addr().Is6() { return "tcp6" }
|
||||
if ap.Addr().Is4() { return "tcp4" }
|
||||
}
|
||||
}
|
||||
|
||||
return "tcp"
|
||||
}
|
||||
|
||||
func word_to_route_proto(word string) RouteOption {
|
||||
switch word {
|
||||
case "tcp4":
|
||||
return RouteOption(ROUTE_OPTION_TCP4)
|
||||
case "tcp6":
|
||||
return RouteOption(ROUTE_OPTION_TCP6)
|
||||
case "tcp":
|
||||
return RouteOption(ROUTE_OPTION_TCP)
|
||||
case "tty":
|
||||
return RouteOption(ROUTE_OPTION_TTY)
|
||||
case "http":
|
||||
return RouteOption(ROUTE_OPTION_HTTP)
|
||||
case "https":
|
||||
return RouteOption(ROUTE_OPTION_HTTPS)
|
||||
}
|
||||
|
||||
return RouteOption(ROUTE_OPTION_UNSPEC)
|
||||
}
|
||||
|
||||
func string_to_route_proto(desc string) RouteOption {
|
||||
var fld string
|
||||
var proto RouteOption
|
||||
var p RouteOption
|
||||
|
||||
proto = RouteOption(0)
|
||||
for _, fld = range strings.Fields(desc) {
|
||||
p = word_to_route_proto(fld)
|
||||
if p == RouteOption(ROUTE_OPTION_UNSPEC) { return p }
|
||||
proto |= p
|
||||
}
|
||||
return proto
|
||||
}
|
||||
|
||||
func (proto RouteOption) string() string {
|
||||
var str string
|
||||
|
||||
str = ""
|
||||
if proto & RouteOption(ROUTE_OPTION_TCP6) != 0 { str += " tcp6" }
|
||||
if proto & RouteOption(ROUTE_OPTION_TCP4) != 0 { str += " tcp4" }
|
||||
if proto & RouteOption(ROUTE_OPTION_TCP) != 0 { str += " tcp" }
|
||||
if proto & RouteOption(ROUTE_OPTION_TTY) != 0 { str += " tty" }
|
||||
if proto & RouteOption(ROUTE_OPTION_HTTP) != 0 { str += " http" }
|
||||
if proto & RouteOption(ROUTE_OPTION_HTTPS) != 0 { str += " https" }
|
||||
if str == "" { return str }
|
||||
return str[1:] // remove the leading space
|
||||
}
|
||||
|
||||
func dump_call_frame_and_exit(log Logger, req *http.Request, err interface{}) {
|
||||
var buf []byte
|
||||
buf = make([]byte, 65536); buf = buf[:min(65536, runtime.Stack(buf, false))]
|
||||
|
222
hodu.pb.go
222
hodu.pb.go
@ -20,52 +20,64 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ROUTE_PROTO int32
|
||||
type ROUTE_OPTION int32
|
||||
|
||||
const (
|
||||
ROUTE_PROTO_TCP ROUTE_PROTO = 0
|
||||
ROUTE_PROTO_TCP4 ROUTE_PROTO = 1
|
||||
ROUTE_PROTO_TCP6 ROUTE_PROTO = 2
|
||||
ROUTE_OPTION_UNSPEC ROUTE_OPTION = 0
|
||||
ROUTE_OPTION_TCP ROUTE_OPTION = 1
|
||||
ROUTE_OPTION_TCP4 ROUTE_OPTION = 2
|
||||
ROUTE_OPTION_TCP6 ROUTE_OPTION = 4
|
||||
ROUTE_OPTION_TTY ROUTE_OPTION = 8
|
||||
ROUTE_OPTION_HTTP ROUTE_OPTION = 16
|
||||
ROUTE_OPTION_HTTPS ROUTE_OPTION = 32
|
||||
)
|
||||
|
||||
// Enum value maps for ROUTE_PROTO.
|
||||
// Enum value maps for ROUTE_OPTION.
|
||||
var (
|
||||
ROUTE_PROTO_name = map[int32]string{
|
||||
0: "TCP",
|
||||
1: "TCP4",
|
||||
2: "TCP6",
|
||||
ROUTE_OPTION_name = map[int32]string{
|
||||
0: "UNSPEC",
|
||||
1: "TCP",
|
||||
2: "TCP4",
|
||||
4: "TCP6",
|
||||
8: "TTY",
|
||||
16: "HTTP",
|
||||
32: "HTTPS",
|
||||
}
|
||||
ROUTE_PROTO_value = map[string]int32{
|
||||
"TCP": 0,
|
||||
"TCP4": 1,
|
||||
"TCP6": 2,
|
||||
ROUTE_OPTION_value = map[string]int32{
|
||||
"UNSPEC": 0,
|
||||
"TCP": 1,
|
||||
"TCP4": 2,
|
||||
"TCP6": 4,
|
||||
"TTY": 8,
|
||||
"HTTP": 16,
|
||||
"HTTPS": 32,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ROUTE_PROTO) Enum() *ROUTE_PROTO {
|
||||
p := new(ROUTE_PROTO)
|
||||
func (x ROUTE_OPTION) Enum() *ROUTE_OPTION {
|
||||
p := new(ROUTE_OPTION)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ROUTE_PROTO) String() string {
|
||||
func (x ROUTE_OPTION) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ROUTE_PROTO) Descriptor() protoreflect.EnumDescriptor {
|
||||
func (ROUTE_OPTION) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_hodu_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (ROUTE_PROTO) Type() protoreflect.EnumType {
|
||||
func (ROUTE_OPTION) Type() protoreflect.EnumType {
|
||||
return &file_hodu_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x ROUTE_PROTO) Number() protoreflect.EnumNumber {
|
||||
func (x ROUTE_OPTION) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ROUTE_PROTO.Descriptor instead.
|
||||
func (ROUTE_PROTO) EnumDescriptor() ([]byte, []int) {
|
||||
// Deprecated: Use ROUTE_OPTION.Descriptor instead.
|
||||
func (ROUTE_OPTION) EnumDescriptor() ([]byte, []int) {
|
||||
return file_hodu_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
@ -197,10 +209,23 @@ type RouteDesc struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RouteId uint32 `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"`
|
||||
TargetAddrStr string `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"`
|
||||
ServiceProto ROUTE_PROTO `protobuf:"varint,3,opt,name=ServiceProto,proto3,enum=ROUTE_PROTO" json:"ServiceProto,omitempty"`
|
||||
ServiceNetStr string `protobuf:"bytes,4,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"`
|
||||
RouteId uint32 `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"`
|
||||
// C->S(ROUTE_START): client-side peer address
|
||||
// S->C(ROUTE_STARTED): server-side listening address
|
||||
TargetAddrStr string `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"`
|
||||
// C->S(ROUTE_START): desired listening option on the server-side(e.g. tcp, tcp4, tcp6) +
|
||||
//
|
||||
// hint to the service-side peer(e.g. local) +
|
||||
// hint to the client-side peer(e.g. tty, http, https)
|
||||
//
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
||||
ServiceOption uint32 `protobuf:"varint,3,opt,name=ServiceOption,proto3" json:"ServiceOption,omitempty"`
|
||||
// C->S(ROUTE_START): desired lisening address on the service-side
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C
|
||||
ServiceAddrStr string `protobuf:"bytes,4,opt,name=ServiceAddrStr,proto3" json:"ServiceAddrStr,omitempty"`
|
||||
// C->S(ROUTE_START): permitted network of server-side peers.
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
||||
ServiceNetStr string `protobuf:"bytes,5,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RouteDesc) Reset() {
|
||||
@ -247,11 +272,18 @@ func (x *RouteDesc) GetTargetAddrStr() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RouteDesc) GetServiceProto() ROUTE_PROTO {
|
||||
func (x *RouteDesc) GetServiceOption() uint32 {
|
||||
if x != nil {
|
||||
return x.ServiceProto
|
||||
return x.ServiceOption
|
||||
}
|
||||
return ROUTE_PROTO_TCP
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RouteDesc) GetServiceAddrStr() string {
|
||||
if x != nil {
|
||||
return x.ServiceAddrStr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RouteDesc) GetServiceNetStr() string {
|
||||
@ -499,60 +531,65 @@ var file_hodu_proto_rawDesc = []byte{
|
||||
0x53, 0x65, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x46,
|
||||
0x6c, 0x61, 0x67, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65,
|
||||
0x6c, 0x61, 0x67, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65,
|
||||
0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d,
|
||||
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53,
|
||||
0x74, 0x72, 0x12, 0x30, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x52, 0x4f, 0x55, 0x54, 0x45,
|
||||
0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e,
|
||||
0x65, 0x74, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x53, 0x74, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50,
|
||||
0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49,
|
||||
0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6d,
|
||||
0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x12,
|
||||
0x22, 0x0a, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72,
|
||||
0x53, 0x74, 0x72, 0x22, 0x50, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65,
|
||||
0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49,
|
||||
0x64, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
||||
0x12, 0x20, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c,
|
||||
0x2e, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x52, 0x04, 0x4b, 0x69,
|
||||
0x6e, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x0a, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52,
|
||||
0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x48,
|
||||
0x00, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61,
|
||||
0x48, 0x00, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x42, 0x03, 0x0a, 0x01, 0x55, 0x2a, 0x2a, 0x0a,
|
||||
0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x12, 0x07, 0x0a, 0x03,
|
||||
0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x34, 0x10, 0x01, 0x12,
|
||||
0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x36, 0x10, 0x02, 0x2a, 0xb5, 0x01, 0x0a, 0x0b, 0x50, 0x41,
|
||||
0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53,
|
||||
0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45,
|
||||
0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x4f, 0x55, 0x54,
|
||||
0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54,
|
||||
0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52,
|
||||
0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x04, 0x12, 0x10,
|
||||
0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05,
|
||||
0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44,
|
||||
0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54,
|
||||
0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x45, 0x4f, 0x46,
|
||||
0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10,
|
||||
0x09, 0x32, 0x49, 0x0a, 0x04, 0x48, 0x6f, 0x64, 0x75, 0x12, 0x19, 0x0a, 0x07, 0x47, 0x65, 0x74,
|
||||
0x53, 0x65, 0x65, 0x64, 0x12, 0x05, 0x2e, 0x53, 0x65, 0x65, 0x64, 0x1a, 0x05, 0x2e, 0x53, 0x65,
|
||||
0x65, 0x64, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74,
|
||||
0x72, 0x65, 0x61, 0x6d, 0x12, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x1a, 0x07, 0x2e,
|
||||
0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06,
|
||||
0x2e, 0x2f, 0x68, 0x6f, 0x64, 0x75, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x74, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72,
|
||||
0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x53, 0x74,
|
||||
0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x4e, 0x65, 0x74, 0x53, 0x74, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44,
|
||||
0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50,
|
||||
0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41,
|
||||
0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65,
|
||||
0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x4c,
|
||||
0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x22,
|
||||
0x50, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x52,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74,
|
||||
0x61, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x04,
|
||||
0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x50, 0x41, 0x43,
|
||||
0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x22,
|
||||
0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
|
||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x05, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x04, 0x50,
|
||||
0x65, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x04,
|
||||
0x44, 0x61, 0x74, 0x61, 0x42, 0x03, 0x0a, 0x01, 0x55, 0x2a, 0x55, 0x0a, 0x0c, 0x52, 0x4f, 0x55,
|
||||
0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x4e, 0x53,
|
||||
0x50, 0x45, 0x43, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x08,
|
||||
0x0a, 0x04, 0x54, 0x43, 0x50, 0x34, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x36,
|
||||
0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x54, 0x59, 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x48,
|
||||
0x54, 0x54, 0x50, 0x10, 0x10, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x20,
|
||||
0x2a, 0xb5, 0x01, 0x0a, 0x0b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44,
|
||||
0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f,
|
||||
0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12,
|
||||
0x0e, 0x0a, 0x0a, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12,
|
||||
0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44,
|
||||
0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50,
|
||||
0x50, 0x45, 0x44, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54,
|
||||
0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f,
|
||||
0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45,
|
||||
0x52, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x50,
|
||||
0x45, 0x45, 0x52, 0x5f, 0x45, 0x4f, 0x46, 0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x45,
|
||||
0x52, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10, 0x09, 0x32, 0x49, 0x0a, 0x04, 0x48, 0x6f, 0x64, 0x75,
|
||||
0x12, 0x19, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x65, 0x65, 0x64, 0x12, 0x05, 0x2e, 0x53, 0x65,
|
||||
0x65, 0x64, 0x1a, 0x05, 0x2e, 0x53, 0x65, 0x65, 0x64, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x0c, 0x50,
|
||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x07, 0x2e, 0x50, 0x61,
|
||||
0x63, 0x6b, 0x65, 0x74, 0x1a, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x00, 0x28,
|
||||
0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x68, 0x6f, 0x64, 0x75, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -570,7 +607,7 @@ func file_hodu_proto_rawDescGZIP() []byte {
|
||||
var file_hodu_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_hodu_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_hodu_proto_goTypes = []any{
|
||||
(ROUTE_PROTO)(0), // 0: ROUTE_PROTO
|
||||
(ROUTE_OPTION)(0), // 0: ROUTE_OPTION
|
||||
(PACKET_KIND)(0), // 1: PACKET_KIND
|
||||
(*Seed)(nil), // 2: Seed
|
||||
(*RouteDesc)(nil), // 3: RouteDesc
|
||||
@ -579,20 +616,19 @@ var file_hodu_proto_goTypes = []any{
|
||||
(*Packet)(nil), // 6: Packet
|
||||
}
|
||||
var file_hodu_proto_depIdxs = []int32{
|
||||
0, // 0: RouteDesc.ServiceProto:type_name -> ROUTE_PROTO
|
||||
1, // 1: Packet.Kind:type_name -> PACKET_KIND
|
||||
3, // 2: Packet.Route:type_name -> RouteDesc
|
||||
4, // 3: Packet.Peer:type_name -> PeerDesc
|
||||
5, // 4: Packet.Data:type_name -> PeerData
|
||||
2, // 5: Hodu.GetSeed:input_type -> Seed
|
||||
6, // 6: Hodu.PacketStream:input_type -> Packet
|
||||
2, // 7: Hodu.GetSeed:output_type -> Seed
|
||||
6, // 8: Hodu.PacketStream:output_type -> Packet
|
||||
7, // [7:9] is the sub-list for method output_type
|
||||
5, // [5:7] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
1, // 0: Packet.Kind:type_name -> PACKET_KIND
|
||||
3, // 1: Packet.Route:type_name -> RouteDesc
|
||||
4, // 2: Packet.Peer:type_name -> PeerDesc
|
||||
5, // 3: Packet.Data:type_name -> PeerData
|
||||
2, // 4: Hodu.GetSeed:input_type -> Seed
|
||||
6, // 5: Hodu.PacketStream:input_type -> Packet
|
||||
2, // 6: Hodu.GetSeed:output_type -> Seed
|
||||
6, // 7: Hodu.PacketStream:output_type -> Packet
|
||||
6, // [6:8] is the sub-list for method output_type
|
||||
4, // [4:6] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_hodu_proto_init() }
|
||||
|
35
hodu.proto
35
hodu.proto
@ -18,17 +18,36 @@ message Seed {
|
||||
uint64 Flags = 2;
|
||||
}
|
||||
|
||||
enum ROUTE_PROTO {
|
||||
TCP = 0;
|
||||
TCP4 = 1;
|
||||
TCP6 = 2;
|
||||
enum ROUTE_OPTION {
|
||||
UNSPEC = 0;
|
||||
TCP = 1;
|
||||
TCP4 = 2;
|
||||
TCP6 = 4;
|
||||
TTY = 8;
|
||||
HTTP = 16;
|
||||
HTTPS = 32;
|
||||
};
|
||||
|
||||
message RouteDesc {
|
||||
uint32 RouteId = 1;
|
||||
string TargetAddrStr = 2;
|
||||
ROUTE_PROTO ServiceProto = 3;
|
||||
string ServiceNetStr = 4;
|
||||
uint32 RouteId = 1;
|
||||
|
||||
// C->S(ROUTE_START): client-side peer address
|
||||
// S->C(ROUTE_STARTED): server-side listening address
|
||||
string TargetAddrStr = 2;
|
||||
|
||||
// C->S(ROUTE_START): desired listening option on the server-side(e.g. tcp, tcp4, tcp6) +
|
||||
// hint to the service-side peer(e.g. local) +
|
||||
// hint to the client-side peer(e.g. tty, http, https)
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
||||
uint32 ServiceOption = 3;
|
||||
|
||||
// C->S(ROUTE_START): desired lisening address on the service-side
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C
|
||||
string ServiceAddrStr = 4;
|
||||
|
||||
// C->S(ROUTE_START): permitted network of server-side peers.
|
||||
// S->C(ROUTE_STARTED): cloned as sent by C.
|
||||
string ServiceNetStr = 5;
|
||||
};
|
||||
|
||||
message PeerDesc {
|
||||
|
23
packet.go
23
packet.go
@ -1,31 +1,32 @@
|
||||
package hodu
|
||||
|
||||
type ConnId uint64
|
||||
type RouteId uint32 // keep this in sync with the type of RouteId in hodu.proto
|
||||
type PeerId uint32 // keep this in sync with the type of RouteId in hodu.proto
|
||||
type ConnId uint64
|
||||
type RouteId uint32 // keep this in sync with the type of RouteId in hodu.proto
|
||||
type PeerId uint32 // keep this in sync with the type of RouteId in hodu.proto
|
||||
type RouteOption uint32
|
||||
|
||||
func MakeRouteStartPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet {
|
||||
func MakeRouteStartPacket(route_id RouteId, proto RouteOption, ptc_addr string, svc_addr string, svc_net string) *Packet {
|
||||
return &Packet{
|
||||
Kind: PACKET_KIND_ROUTE_START,
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}}
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: ptc_addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}}
|
||||
}
|
||||
|
||||
func MakeRouteStopPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet {
|
||||
func MakeRouteStopPacket(route_id RouteId, proto RouteOption, ptc_addr string, svc_addr string, svc_net string) *Packet {
|
||||
return &Packet{
|
||||
Kind: PACKET_KIND_ROUTE_STOP,
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}}
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: ptc_addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}}
|
||||
}
|
||||
|
||||
func MakeRouteStartedPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet {
|
||||
func MakeRouteStartedPacket(route_id RouteId, proto RouteOption, addr string, svc_addr string, svc_net string) *Packet {
|
||||
// the connection from a peer to the server has been established
|
||||
return &Packet{Kind: PACKET_KIND_ROUTE_STARTED,
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}}
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}}
|
||||
}
|
||||
|
||||
func MakeRouteStoppedPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet {
|
||||
func MakeRouteStoppedPacket(route_id RouteId, proto RouteOption, addr string, svc_addr string, svc_net string) *Packet {
|
||||
// the connection from a peer to the server has been established
|
||||
return &Packet{Kind: PACKET_KIND_ROUTE_STOPPED,
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}}
|
||||
U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}}
|
||||
}
|
||||
|
||||
func MakePeerStartedPacket(route_id RouteId, peer_id PeerId, remote_addr string, local_addr string) *Packet {
|
||||
|
@ -4,6 +4,7 @@ import "encoding/json"
|
||||
import "net/http"
|
||||
import "runtime"
|
||||
import "strconv"
|
||||
import "unsafe"
|
||||
|
||||
type json_out_server_conn struct {
|
||||
Id ConnId `json:"id"`
|
||||
@ -15,9 +16,9 @@ type json_out_server_conn struct {
|
||||
type json_out_server_route struct {
|
||||
Id RouteId `json:"id"`
|
||||
ClientPeerAddr string `json:"client-peer-addr"`
|
||||
ServerPeerListenAddr string `json:"server-peer-listen-addr"`
|
||||
ServerPeerNet string `json:"server-peer-net"`
|
||||
ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"`
|
||||
ServerPeerOption string `json:"server-peer-option"`
|
||||
ServerPeerServiceAddr string `json:"server-peer-service-addr"` // actual listening address
|
||||
ServerPeerServiceNet string `json:"server-peer-service-net"`
|
||||
}
|
||||
|
||||
type json_out_server_stats struct {
|
||||
@ -94,9 +95,9 @@ func (ctl *server_ctl_server_conns) ServeHTTP(w http.ResponseWriter, req *http.R
|
||||
jsp = append(jsp, json_out_server_route{
|
||||
Id: r.id,
|
||||
ClientPeerAddr: r.ptc_addr,
|
||||
ServerPeerListenAddr: r.svc_addr.String(),
|
||||
ServerPeerNet: r.svc_permitted_net.String(),
|
||||
ServerPeerProto: r.svc_proto,
|
||||
ServerPeerServiceAddr: r.svc_addr.String(),
|
||||
ServerPeerServiceNet: r.svc_permitted_net.String(),
|
||||
ServerPeerOption: r.svc_option.string(),
|
||||
})
|
||||
}
|
||||
js = append(js, json_out_server_conn{
|
||||
@ -176,9 +177,9 @@ func (ctl *server_ctl_server_conns_id) ServeHTTP(w http.ResponseWriter, req *htt
|
||||
jsp = append(jsp, json_out_server_route{
|
||||
Id: r.id,
|
||||
ClientPeerAddr: r.ptc_addr,
|
||||
ServerPeerListenAddr: r.svc_addr.String(),
|
||||
ServerPeerNet: r.svc_permitted_net.String(),
|
||||
ServerPeerProto: r.svc_proto,
|
||||
ServerPeerServiceAddr: r.svc_addr.String(),
|
||||
ServerPeerServiceNet: r.svc_permitted_net.String(),
|
||||
ServerPeerOption: r.svc_option.string(),
|
||||
})
|
||||
}
|
||||
js = &json_out_server_conn{
|
||||
@ -256,9 +257,9 @@ func (ctl *server_ctl_server_conns_id_routes) ServeHTTP(w http.ResponseWriter, r
|
||||
jsp = append(jsp, json_out_server_route{
|
||||
Id: r.id,
|
||||
ClientPeerAddr: r.ptc_addr,
|
||||
ServerPeerListenAddr: r.svc_addr.String(),
|
||||
ServerPeerNet: r.svc_permitted_net.String(),
|
||||
ServerPeerProto: r.svc_proto,
|
||||
ServerPeerServiceAddr: r.svc_addr.String(),
|
||||
ServerPeerServiceNet: r.svc_permitted_net.String(),
|
||||
ServerPeerOption: r.svc_option.string(),
|
||||
})
|
||||
}
|
||||
cts.route_mtx.Unlock()
|
||||
@ -309,13 +310,13 @@ func (ctl *server_ctl_server_conns_id_routes_id) ServeHTTP(w http.ResponseWriter
|
||||
conn_id = req.PathValue("conn_id")
|
||||
route_id = req.PathValue("route_id")
|
||||
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, 32)
|
||||
conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops }
|
||||
goto done
|
||||
}
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, 32)
|
||||
route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8))
|
||||
if err != nil {
|
||||
status_code = http.StatusBadRequest; w.WriteHeader(status_code)
|
||||
if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops }
|
||||
@ -342,9 +343,9 @@ func (ctl *server_ctl_server_conns_id_routes_id) ServeHTTP(w http.ResponseWriter
|
||||
err = je.Encode(json_out_server_route{
|
||||
Id: r.id,
|
||||
ClientPeerAddr: r.ptc_addr,
|
||||
ServerPeerListenAddr: r.svc_addr.String(),
|
||||
ServerPeerNet: r.svc_permitted_net.String(),
|
||||
ServerPeerProto: r.svc_proto,
|
||||
ServerPeerServiceAddr: r.svc_addr.String(),
|
||||
ServerPeerServiceNet: r.svc_permitted_net.String(),
|
||||
ServerPeerOption: r.svc_option.string(),
|
||||
})
|
||||
if err != nil { goto oops }
|
||||
|
||||
|
@ -3,6 +3,7 @@ package hodu
|
||||
import "errors"
|
||||
import "io"
|
||||
import "net"
|
||||
import "strings"
|
||||
import "sync"
|
||||
import "sync/atomic"
|
||||
import "time"
|
||||
@ -90,7 +91,7 @@ wait_for_started:
|
||||
for {
|
||||
n, err = spc.conn.Read(buf[:])
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "use of closed network connection") { // i don't like this way to check this error.
|
||||
err = pss.Send(MakePeerEofPacket(spc.route.id, spc.conn_id))
|
||||
if err != nil {
|
||||
spc.route.cts.svr.log.Write(spc.route.cts.sid, LOG_ERROR,
|
||||
|
243
server.go
243
server.go
@ -6,7 +6,7 @@ import "errors"
|
||||
import "fmt"
|
||||
import "io"
|
||||
import "log"
|
||||
import "math/rand"
|
||||
//import "math/rand"
|
||||
import "net"
|
||||
import "net/http"
|
||||
import "net/netip"
|
||||
@ -28,10 +28,10 @@ type ServerConnMap = map[ConnId]*ServerConn
|
||||
type ServerRouteMap = map[RouteId]*ServerRoute
|
||||
type ServerPeerConnMap = map[PeerId]*ServerPeerConn
|
||||
|
||||
|
||||
type Server struct {
|
||||
ctx context.Context
|
||||
ctx_cancel context.CancelFunc
|
||||
pxytlscfg *tls.Config
|
||||
ctltlscfg *tls.Config
|
||||
rpctlscfg *tls.Config
|
||||
|
||||
@ -42,6 +42,10 @@ type Server struct {
|
||||
ext_mtx sync.Mutex
|
||||
ext_svcs []Service
|
||||
|
||||
pxy_addr []string
|
||||
pxy_mux *http.ServeMux
|
||||
pxy []*http.Server // proxy server
|
||||
|
||||
ctl_addr []string
|
||||
ctl_prefix string
|
||||
ctl_mux *http.ServeMux
|
||||
@ -91,10 +95,11 @@ type ServerConn struct {
|
||||
|
||||
type ServerRoute struct {
|
||||
cts *ServerConn
|
||||
l *net.TCPListener
|
||||
svc_addr *net.TCPAddr // listening address
|
||||
svc_l *net.TCPListener
|
||||
svc_addr *net.TCPAddr // actual listening address
|
||||
svc_requested_addr string
|
||||
svc_permitted_net netip.Prefix
|
||||
svc_proto ROUTE_PROTO
|
||||
svc_option RouteOption
|
||||
|
||||
ptc_addr string
|
||||
id RouteId
|
||||
@ -136,7 +141,7 @@ func (g *GuardedPacketStreamServer) Context() context.Context {
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
func NewServerRoute(cts *ServerConn, id RouteId, proto ROUTE_PROTO, ptc_addr string, svc_permitted_net string) (*ServerRoute, error) {
|
||||
func NewServerRoute(cts *ServerConn, id RouteId, option RouteOption, ptc_addr string, svc_requested_addr string, svc_permitted_net string) (*ServerRoute, error) {
|
||||
var r ServerRoute
|
||||
var l *net.TCPListener
|
||||
var svcaddr *net.TCPAddr
|
||||
@ -144,31 +149,34 @@ func NewServerRoute(cts *ServerConn, id RouteId, proto ROUTE_PROTO, ptc_addr str
|
||||
var err error
|
||||
|
||||
if svc_permitted_net != "" {
|
||||
// parse the permitted network before creating a listener.
|
||||
// the listener opened doesn't have to be closed when parsing fails.
|
||||
svcnet, err = netip.ParsePrefix(svc_permitted_net)
|
||||
if err != nil {
|
||||
return nil , err
|
||||
}
|
||||
}
|
||||
|
||||
l, svcaddr, err = cts.make_route_listener(id, proto)
|
||||
l, svcaddr, err = cts.make_route_listener(id, option, svc_requested_addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if svc_permitted_net == "" {
|
||||
if svcaddr.IP.To4() != nil {
|
||||
svcnet, _ = netip.ParsePrefix("0.0.0.0/0")
|
||||
svcnet = IPV4_PREFIX_ZERO
|
||||
} else {
|
||||
svcnet, _ = netip.ParsePrefix("::/0")
|
||||
svcnet = IPV6_PREFIX_ZERO
|
||||
}
|
||||
}
|
||||
|
||||
r.cts = cts
|
||||
r.id = id
|
||||
r.l = l
|
||||
r.svc_l = l
|
||||
r.svc_addr = svcaddr
|
||||
r.svc_requested_addr = svc_requested_addr
|
||||
r.svc_permitted_net = svcnet
|
||||
r.svc_proto = proto
|
||||
r.svc_option = option
|
||||
|
||||
r.ptc_addr = ptc_addr
|
||||
r.pts_limit = PTS_LIMIT
|
||||
@ -230,7 +238,7 @@ func (r *ServerRoute) RunTask(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
for {
|
||||
conn, err = r.l.AcceptTCP()
|
||||
conn, err = r.svc_l.AcceptTCP() // this call is blocking...
|
||||
if err != nil {
|
||||
if errors.Is(err, net.ErrClosed) {
|
||||
r.cts.svr.log.Write(r.cts.sid, LOG_INFO, "Server-side peer listener closed on route(%d)", r.id)
|
||||
@ -280,7 +288,7 @@ func (r *ServerRoute) ReqStop() {
|
||||
pts.ReqStop()
|
||||
}
|
||||
|
||||
r.l.Close()
|
||||
r.svc_l.Close()
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,52 +308,53 @@ func (r *ServerRoute) ReportEvent(pts_id PeerId, event_type PACKET_KIND, event_d
|
||||
}
|
||||
// ------------------------------------
|
||||
|
||||
func (cts *ServerConn) make_route_listener(id RouteId, proto ROUTE_PROTO) (*net.TCPListener, *net.TCPAddr, error) {
|
||||
func (cts *ServerConn) make_route_listener(id RouteId, option RouteOption, svc_requested_addr string) (*net.TCPListener, *net.TCPAddr, error) {
|
||||
var l *net.TCPListener
|
||||
var err error
|
||||
var svcaddr *net.TCPAddr
|
||||
var port int
|
||||
var tries int = 0
|
||||
var nw string
|
||||
var ip string
|
||||
var err error
|
||||
|
||||
switch proto {
|
||||
case ROUTE_PROTO_TCP:
|
||||
if svc_requested_addr != "" {
|
||||
var ap netip.AddrPort
|
||||
|
||||
ap, err = netip.ParseAddrPort(svc_requested_addr)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("invalid service address %s - %s", svc_requested_addr, err.Error())
|
||||
}
|
||||
|
||||
svcaddr = &net.TCPAddr{IP: ap.Addr().AsSlice(), Port: int(ap.Port())}
|
||||
}
|
||||
|
||||
if option & RouteOption(ROUTE_OPTION_TCP) != 0 {
|
||||
nw = "tcp"
|
||||
ip = ""
|
||||
case ROUTE_PROTO_TCP4:
|
||||
nw = "tcp4"
|
||||
ip = "0.0.0.0"
|
||||
case ROUTE_PROTO_TCP6:
|
||||
nw = "tcp6"
|
||||
ip = "[::]"
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid protocol number %d", proto)
|
||||
}
|
||||
|
||||
for {
|
||||
port = rand.Intn(65535-32000+1) + 32000 // TODO: configurable port range
|
||||
|
||||
svcaddr, err = net.ResolveTCPAddr(nw, fmt.Sprintf("%s:%d", ip, port))
|
||||
if err == nil {
|
||||
l, err = net.ListenTCP(nw, svcaddr) // make the binding address configurable. support multiple binding addresses???
|
||||
if err == nil {
|
||||
cts.svr.log.Write(cts.sid, LOG_DEBUG, "Route(%d) listening on %d", id, port)
|
||||
return l, svcaddr, nil
|
||||
if svcaddr == nil {
|
||||
svcaddr = &net.TCPAddr{Port: 0} // port 0 for automatic assignment.
|
||||
}
|
||||
}
|
||||
|
||||
tries++
|
||||
if tries >= 1000 {
|
||||
err = fmt.Errorf("unable to allocate port")
|
||||
break
|
||||
}
|
||||
} else if option & RouteOption(ROUTE_OPTION_TCP4) != 0 {
|
||||
nw = "tcp4"
|
||||
if svcaddr == nil {
|
||||
svcaddr = &net.TCPAddr{IP: net.IPv4zero, Port: 0} // port 0 for automatic assignment.
|
||||
}
|
||||
} else if option & RouteOption(ROUTE_OPTION_TCP6) != 0 {
|
||||
nw = "tcp6"
|
||||
if svcaddr == nil {
|
||||
svcaddr = &net.TCPAddr{IP: net.IPv6zero, Port: 0} // port 0 for automatic assignment.
|
||||
}
|
||||
} else {
|
||||
return nil, nil, fmt.Errorf("invalid route option value %d(%s)", option, option.string())
|
||||
}
|
||||
|
||||
return nil, nil, err
|
||||
l, err = net.ListenTCP(nw, svcaddr) // make the binding address configurable. support multiple binding addresses???
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
svcaddr = l.Addr().(*net.TCPAddr)
|
||||
cts.svr.log.Write(cts.sid, LOG_DEBUG, "Route(%d) listening on %s", id, svcaddr.String())
|
||||
return l, svcaddr, nil
|
||||
}
|
||||
|
||||
func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto ROUTE_PROTO, ptc_addr string, svc_permitted_net string) (*ServerRoute, error) {
|
||||
func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto RouteOption, ptc_addr string, svc_requested_addr string, svc_permitted_net string) (*ServerRoute, error) {
|
||||
var r *ServerRoute
|
||||
var err error
|
||||
|
||||
@ -358,7 +367,7 @@ func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto ROUTE_PROTO, pt
|
||||
cts.route_mtx.Unlock()
|
||||
return nil, fmt.Errorf("existent route id - %d", route_id)
|
||||
}
|
||||
r, err = NewServerRoute(cts, route_id, proto, ptc_addr, svc_permitted_net)
|
||||
r, err = NewServerRoute(cts, route_id, proto, ptc_addr, svc_requested_addr, svc_permitted_net)
|
||||
if err != nil {
|
||||
cts.route_mtx.Unlock()
|
||||
return nil, err
|
||||
@ -478,34 +487,34 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
|
||||
if ok {
|
||||
var r *ServerRoute
|
||||
|
||||
r, err = cts.AddNewServerRoute(RouteId(x.Route.RouteId), x.Route.ServiceProto, x.Route.TargetAddrStr, x.Route.ServiceNetStr)
|
||||
r, err = cts.AddNewServerRoute(RouteId(x.Route.RouteId), RouteOption(x.Route.ServiceOption), x.Route.TargetAddrStr, x.Route.ServiceAddrStr, x.Route.ServiceNetStr)
|
||||
if err != nil {
|
||||
cts.svr.log.Write(cts.sid, LOG_ERROR,
|
||||
"Failed to add route(%d,%s) for %s - %s",
|
||||
x.Route.RouteId, x.Route.TargetAddrStr, cts.remote_addr, err.Error())
|
||||
|
||||
err = cts.pss.Send(MakeRouteStoppedPacket(RouteId(x.Route.RouteId), x.Route.ServiceProto, x.Route.TargetAddrStr, x.Route.ServiceNetStr))
|
||||
err = cts.pss.Send(MakeRouteStoppedPacket(RouteId(x.Route.RouteId), RouteOption(x.Route.ServiceOption), x.Route.TargetAddrStr, x.Route.ServiceAddrStr, x.Route.ServiceNetStr))
|
||||
if err != nil {
|
||||
cts.svr.log.Write(cts.sid, LOG_ERROR,
|
||||
"Failed to send route_stopped event(%d,%s,%v,%s) to client %s - %s",
|
||||
x.Route.RouteId, x.Route.TargetAddrStr, x.Route.ServiceProto, x.Route.ServiceNetStr, cts.remote_addr, err.Error())
|
||||
x.Route.RouteId, x.Route.TargetAddrStr, x.Route.ServiceOption, x.Route.ServiceNetStr, cts.remote_addr, err.Error())
|
||||
goto done
|
||||
} else {
|
||||
cts.svr.log.Write(cts.sid, LOG_DEBUG,
|
||||
"Sent route_stopped event(%d,%s,%v,%s) to client %s",
|
||||
x.Route.RouteId, x.Route.TargetAddrStr, x.Route.ServiceProto, x.Route.ServiceNetStr, cts.remote_addr)
|
||||
x.Route.RouteId, x.Route.TargetAddrStr, x.Route.ServiceOption, x.Route.ServiceNetStr, cts.remote_addr)
|
||||
}
|
||||
|
||||
} else {
|
||||
cts.svr.log.Write(cts.sid, LOG_INFO,
|
||||
"Added route(%d,%s,%s,%v,%v) for client %s to cts(%d)",
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net, cts.remote_addr, cts.id)
|
||||
err = cts.pss.Send(MakeRouteStartedPacket(r.id, r.svc_proto, r.svc_addr.String(), r.svc_permitted_net.String()))
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net, cts.remote_addr, cts.id)
|
||||
err = cts.pss.Send(MakeRouteStartedPacket(r.id, r.svc_option, r.svc_addr.String(), r.svc_requested_addr, r.svc_permitted_net.String()))
|
||||
if err != nil {
|
||||
r.ReqStop()
|
||||
cts.svr.log.Write(cts.sid, LOG_ERROR,
|
||||
"Failed to send route_started event(%d,%s,%s,%s%v,%v) to client %s - %s",
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net, cts.remote_addr, err.Error())
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net, cts.remote_addr, err.Error())
|
||||
goto done
|
||||
}
|
||||
}
|
||||
@ -529,13 +538,13 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) {
|
||||
} else {
|
||||
cts.svr.log.Write(cts.sid, LOG_ERROR,
|
||||
"Deleted route(%d,%s,%s,%v,%v) for client %s",
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net.String(), cts.remote_addr)
|
||||
err = cts.pss.Send(MakeRouteStoppedPacket(r.id, r.svc_proto, r.ptc_addr, r.svc_permitted_net.String()))
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net.String(), cts.remote_addr)
|
||||
err = cts.pss.Send(MakeRouteStoppedPacket(r.id, r.svc_option, r.ptc_addr, r.svc_requested_addr, r.svc_permitted_net.String()))
|
||||
if err != nil {
|
||||
r.ReqStop()
|
||||
cts.svr.log.Write(cts.sid, LOG_ERROR,
|
||||
"Failed to send route_stopped event(%d,%s,%s,%v.%v) to client %s - %s",
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net.String(), cts.remote_addr, err.Error())
|
||||
r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net.String(), cts.remote_addr, err.Error())
|
||||
goto done
|
||||
}
|
||||
}
|
||||
@ -846,18 +855,18 @@ func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServ
|
||||
}
|
||||
|
||||
|
||||
type server_ctl_log_writer struct {
|
||||
type server_http_log_writer struct {
|
||||
svr *Server
|
||||
}
|
||||
|
||||
func (hlw *server_ctl_log_writer) Write(p []byte) (n int, err error) {
|
||||
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.
|
||||
hlw.svr.log.Write("", LOG_INFO, string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs []string, ctl_prefix string, ctltlscfg *tls.Config, rpctlscfg *tls.Config, rpc_max int, peer_max int) (*Server, error) {
|
||||
func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, ctl_prefix string, ctltlscfg *tls.Config, rpctlscfg *tls.Config, pxytlscfg *tls.Config, rpc_max int, peer_max int) (*Server, error) {
|
||||
var s Server
|
||||
var l *net.TCPListener
|
||||
var rpcaddr *net.TCPAddr
|
||||
@ -893,6 +902,7 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs
|
||||
|
||||
s.ctltlscfg = ctltlscfg
|
||||
s.rpctlscfg = rpctlscfg
|
||||
s.pxytlscfg = pxytlscfg
|
||||
s.ext_svcs = make([]Service, 0, 1)
|
||||
s.pts_limit = peer_max
|
||||
s.cts_limit = rpc_max
|
||||
@ -916,10 +926,16 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs
|
||||
s.rpc_svr = grpc.NewServer(opts...)
|
||||
RegisterHoduServer(s.rpc_svr, &s)
|
||||
|
||||
s.ctl_prefix = ctl_prefix
|
||||
// ---------------------------------------------------------
|
||||
|
||||
hs_log = log.New(&server_http_log_writer{svr: &s}, "", 0);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
s.ctl_prefix = ctl_prefix
|
||||
s.ctl_mux = http.NewServeMux()
|
||||
cwd, _ = os.Getwd()
|
||||
cwd, _ = os.Getwd() // TODO:
|
||||
|
||||
s.ctl_mux.Handle(s.ctl_prefix + "/ui/", http.StripPrefix(s.ctl_prefix, http.FileServer(http.Dir(cwd)))) // TODO: proper directory. it must not use the current working directory...
|
||||
s.ctl_mux.Handle(s.ctl_prefix + "/ws/tty", new_server_ctl_ws_tty(&s))
|
||||
s.ctl_mux.Handle(s.ctl_prefix + "/server-conns", &server_ctl_server_conns{s: &s})
|
||||
@ -931,7 +947,6 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs
|
||||
s.ctl_addr = make([]string, len(ctl_addrs))
|
||||
s.ctl = make([]*http.Server, len(ctl_addrs))
|
||||
copy(s.ctl_addr, ctl_addrs)
|
||||
hs_log = log.New(&server_ctl_log_writer{svr: &s}, "", 0);
|
||||
|
||||
for i = 0; i < len(ctl_addrs); i++ {
|
||||
s.ctl[i] = &http.Server{
|
||||
@ -943,6 +958,26 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
s.pxy_mux = http.NewServeMux() // TODO: make /_init configurable...
|
||||
s.pxy_mux.Handle("/_init/{conn_id}/{route_id}/{trailer...}", &server_proxy_http_init{s: &s})
|
||||
s.pxy_mux.Handle("/", &server_proxy_http_main{s: &s})
|
||||
|
||||
s.pxy_addr = make([]string, len(pxy_addrs))
|
||||
s.pxy = make([]*http.Server, len(pxy_addrs))
|
||||
copy(s.pxy_addr, pxy_addrs)
|
||||
|
||||
for i = 0; i < len(pxy_addrs); i++ {
|
||||
s.pxy[i] = &http.Server{
|
||||
Addr: pxy_addrs[i],
|
||||
Handler: s.pxy_mux,
|
||||
TLSConfig: s.pxytlscfg,
|
||||
ErrorLog: hs_log,
|
||||
// TODO: more settings
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
|
||||
s.stats.conns.Store(0)
|
||||
s.stats.routes.Store(0)
|
||||
s.stats.peers.Store(0)
|
||||
@ -1032,7 +1067,6 @@ func (s *Server) RunCtlTask(wg *sync.WaitGroup) {
|
||||
|
||||
s.log.Write("", LOG_INFO, "Control channel[%d] started on %s", i, s.ctl_addr[i])
|
||||
|
||||
|
||||
if s.stop_req.Load() == false {
|
||||
// defeat hard-coded "tcp" in ListenAndServe() and ListenAndServeTLS()
|
||||
// err = cs.ListenAndServe()
|
||||
@ -1064,14 +1098,61 @@ func (s *Server) RunCtlTask(wg *sync.WaitGroup) {
|
||||
l_wg.Wait()
|
||||
}
|
||||
|
||||
func (s *Server) RunPxyTask(wg *sync.WaitGroup) {
|
||||
var err error
|
||||
var pxy *http.Server
|
||||
var idx int
|
||||
var l_wg sync.WaitGroup
|
||||
|
||||
defer wg.Done()
|
||||
|
||||
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.pxy_addr[i])
|
||||
|
||||
if s.stop_req.Load() == false {
|
||||
l, err = net.Listen(tcp_addr_str_class(cs.Addr), cs.Addr)
|
||||
if err == nil {
|
||||
if s.stop_req.Load() == false {
|
||||
if s.pxytlscfg == nil { // TODO: change this
|
||||
err = cs.Serve(l)
|
||||
} else {
|
||||
err = cs.ServeTLS(l, "", "") // s.pxytlscfg must provide a certificate and a key
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
l_wg.Wait()
|
||||
}
|
||||
|
||||
func (s *Server) ReqStop() {
|
||||
if s.stop_req.CompareAndSwap(false, true) {
|
||||
var l *net.TCPListener
|
||||
var cts *ServerConn
|
||||
var ctl *http.Server
|
||||
var hs *http.Server
|
||||
|
||||
for _, ctl = range s.ctl {
|
||||
ctl.Shutdown(s.ctx) // to break c.ctl.ListenAndServe()
|
||||
for _, hs = range s.ctl {
|
||||
hs.Shutdown(s.ctx) // to break s.ctl.Serve()
|
||||
}
|
||||
|
||||
for _, hs = range s.pxy {
|
||||
hs.Shutdown(s.ctx) // to break s.pxy.Serve()
|
||||
}
|
||||
|
||||
//s.rpc_svr.GracefulStop()
|
||||
@ -1222,6 +1303,23 @@ func (s *Server) FindServerConnByAddr(addr net.Addr) *ServerConn {
|
||||
return cts
|
||||
}
|
||||
|
||||
|
||||
func (s *Server) FindServerRouteById(id ConnId, route_id RouteId) *ServerRoute {
|
||||
var cts *ServerConn
|
||||
var ok bool
|
||||
|
||||
s.cts_mtx.Lock()
|
||||
defer s.cts_mtx.Unlock()
|
||||
|
||||
cts, ok = s.cts_map[id]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cts.FindServerRouteById(route_id)
|
||||
}
|
||||
|
||||
|
||||
func (s *Server) StartService(cfg interface{}) {
|
||||
s.wg.Add(1)
|
||||
go s.RunTask(&s.wg)
|
||||
@ -1240,6 +1338,11 @@ func (s *Server) StartCtlService() {
|
||||
go s.RunCtlTask(&s.wg)
|
||||
}
|
||||
|
||||
func (s *Server) StartPxyService() {
|
||||
s.wg.Add(1)
|
||||
go s.RunPxyTask(&s.wg)
|
||||
}
|
||||
|
||||
func (s *Server) StopServices() {
|
||||
var ext_svc Service
|
||||
s.ReqStop()
|
||||
|
Loading…
x
Reference in New Issue
Block a user