added the proxy service for http/https client peer on the server side. work in progress

This commit is contained in:
hyung-hwan 2024-12-12 21:09:16 +09:00
parent 41e7222b98
commit f6ea852e61
13 changed files with 538 additions and 252 deletions

View File

@ -13,6 +13,7 @@ SRCS=\
server.go \
server-ctl.go \
server-peer.go \
server-proxy.go \
server-ws.go \
system.go

View File

@ -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 }

View File

@ -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())

View File

@ -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())
}

View File

@ -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"`

View File

@ -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
View File

@ -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))]

View File

@ -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() }

View File

@ -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 {

View File

@ -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 {

View File

@ -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 }

View File

@ -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
View File

@ -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()