adding some server-side control handlers
This commit is contained in:
parent
18b3028a46
commit
8346011d27
2
Makefile
2
Makefile
@ -8,7 +8,9 @@ SRCS=\
|
|||||||
hodu_grpc.pb.go \
|
hodu_grpc.pb.go \
|
||||||
packet.go \
|
packet.go \
|
||||||
server.go \
|
server.go \
|
||||||
|
server-ctl.go \
|
||||||
server-peer.go \
|
server-peer.go \
|
||||||
|
server-ws.go \
|
||||||
cmd/main.go
|
cmd/main.go
|
||||||
|
|
||||||
all: hodu
|
all: hodu
|
||||||
|
30
client.go
30
client.go
@ -39,10 +39,11 @@ type Client struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctx_cancel context.CancelFunc
|
ctx_cancel context.CancelFunc
|
||||||
tlscfg *tls.Config
|
tlscfg *tls.Config
|
||||||
api_prefix string
|
ctl_prefix string
|
||||||
|
|
||||||
ext_mtx sync.Mutex
|
ext_mtx sync.Mutex
|
||||||
ext_svcs []Service
|
ext_svcs []Service
|
||||||
|
ctl_mux *http.ServeMux
|
||||||
ctl *http.Server // control server
|
ctl *http.Server // control server
|
||||||
|
|
||||||
cts_mtx sync.Mutex
|
cts_mtx sync.Mutex
|
||||||
@ -54,7 +55,6 @@ type Client struct {
|
|||||||
stop_chan chan bool
|
stop_chan chan bool
|
||||||
|
|
||||||
log Logger
|
log Logger
|
||||||
mux *http.ServeMux
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// client connection to server
|
// client connection to server
|
||||||
@ -840,7 +840,7 @@ func (cts *ClientConn) ReportEvent (route_id uint32, pts_id uint32, event_type P
|
|||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
func NewClient(ctx context.Context, listen_on string, logger Logger, tlscfg *tls.Config) *Client {
|
func NewClient(ctx context.Context, ctl_addr string, logger Logger, tlscfg *tls.Config) *Client {
|
||||||
var c Client
|
var c Client
|
||||||
|
|
||||||
c.ctx, c.ctx_cancel = context.WithCancel(ctx)
|
c.ctx, c.ctx_cancel = context.WithCancel(ctx)
|
||||||
@ -851,21 +851,21 @@ func NewClient(ctx context.Context, listen_on string, logger Logger, tlscfg *tls
|
|||||||
c.stop_req.Store(false)
|
c.stop_req.Store(false)
|
||||||
c.stop_chan = make(chan bool, 8)
|
c.stop_chan = make(chan bool, 8)
|
||||||
c.log = logger
|
c.log = logger
|
||||||
c.api_prefix = "" // TODO:
|
c.ctl_prefix = "" // TODO:
|
||||||
|
|
||||||
c.mux = http.NewServeMux()
|
c.ctl_mux = http.NewServeMux()
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns", &client_ctl_client_conns{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns", &client_ctl_client_conns{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns/{conn_id}", &client_ctl_client_conns_id{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns/{conn_id}", &client_ctl_client_conns_id{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns/{conn_id}/routes", &client_ctl_client_conns_id_routes{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns/{conn_id}/routes", &client_ctl_client_conns_id_routes{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns/{conn_id}/routes/{route_id}", &client_ctl_client_conns_id_routes_id{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns/{conn_id}/routes/{route_id}", &client_ctl_client_conns_id_routes_id{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns/{conn_id}/routes/{route_id}/peers", &client_ctl_client_conns_id_routes_id_peers{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns/{conn_id}/routes/{route_id}/peers", &client_ctl_client_conns_id_routes_id_peers{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/client-conns/{conn_id}/routes/{route_id}/peers/{peer_id}", &client_ctl_client_conns_id_routes_id_peers_id{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/client-conns/{conn_id}/routes/{route_id}/peers/{peer_id}", &client_ctl_client_conns_id_routes_id_peers_id{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/server-conns", &client_ctl_clients{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/server-conns", &client_ctl_clients{c: &c})
|
||||||
c.mux.Handle(c.api_prefix + "/server-conns/{id}", &client_ctl_clients_id{c: &c})
|
c.ctl_mux.Handle(c.ctl_prefix + "/server-conns/{id}", &client_ctl_clients_id{c: &c})
|
||||||
|
|
||||||
c.ctl = &http.Server{
|
c.ctl = &http.Server{
|
||||||
Addr: listen_on,
|
Addr: ctl_addr,
|
||||||
Handler: c.mux,
|
Handler: c.ctl_mux,
|
||||||
// TODO: more settings
|
// TODO: more settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
cmd/main.go
29
cmd/main.go
@ -146,7 +146,7 @@ func (sh *signal_handler) WriteLog(id string, level hodu.LogLevel, fmt string, a
|
|||||||
sh.svc.WriteLog(id, level, fmt, args...)
|
sh.svc.WriteLog(id, level, fmt, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func server_main(laddrs []string) error {
|
func server_main(ctl_addr string, laddrs []string) error {
|
||||||
var s *hodu.Server
|
var s *hodu.Server
|
||||||
var err error
|
var err error
|
||||||
var cert tls.Certificate
|
var cert tls.Certificate
|
||||||
@ -156,12 +156,13 @@ func server_main(laddrs []string) error {
|
|||||||
return fmt.Errorf("ERROR: failed to load key pair - %s\n", err)
|
return fmt.Errorf("ERROR: failed to load key pair - %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err = hodu.NewServer(context.Background(), laddrs, &AppLogger{id: "server", out: os.Stderr}, &tls.Config{Certificates: []tls.Certificate{cert}})
|
s, err = hodu.NewServer(context.Background(), ctl_addr, laddrs, &AppLogger{id: "server", out: os.Stderr}, &tls.Config{Certificates: []tls.Certificate{cert}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ERROR: failed to create new server - %s", err.Error())
|
return fmt.Errorf("ERROR: failed to create new server - %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
s.StartService(nil)
|
s.StartService(nil)
|
||||||
|
s.StartCtlService()
|
||||||
s.StartExtService(&signal_handler{svc:s}, nil)
|
s.StartExtService(&signal_handler{svc:s}, nil)
|
||||||
s.WaitForTermination()
|
s.WaitForTermination()
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ func server_main(laddrs []string) error {
|
|||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
func client_main(listen_on string, server_addr string, peer_addrs []string) error {
|
func client_main(ctl_addr string, server_addr string, peer_addrs []string) error {
|
||||||
var c *hodu.Client
|
var c *hodu.Client
|
||||||
var cert_pool *x509.CertPool
|
var cert_pool *x509.CertPool
|
||||||
var tlscfg *tls.Config
|
var tlscfg *tls.Config
|
||||||
@ -187,7 +188,8 @@ func client_main(listen_on string, server_addr string, peer_addrs []string) erro
|
|||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
c = hodu.NewClient(context.Background(), listen_on, &AppLogger{id: "client", out: os.Stderr}, tlscfg)
|
// TODO: support multiple ctl addrs
|
||||||
|
c = hodu.NewClient(context.Background(), ctl_addr, &AppLogger{id: "client", out: os.Stderr}, tlscfg)
|
||||||
|
|
||||||
cc.ServerAddr = server_addr
|
cc.ServerAddr = server_addr
|
||||||
cc.PeerAddrs = peer_addrs
|
cc.PeerAddrs = peer_addrs
|
||||||
@ -209,14 +211,19 @@ func main() {
|
|||||||
}
|
}
|
||||||
if strings.EqualFold(os.Args[1], "server") {
|
if strings.EqualFold(os.Args[1], "server") {
|
||||||
var la []string
|
var la []string
|
||||||
|
var ctl_addr string
|
||||||
|
|
||||||
la = make([]string, 0)
|
la = make([]string, 0)
|
||||||
|
|
||||||
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
flgs.Func("listen-on", "specify a listening address", func(v string) error {
|
flgs.Func("rpc-on", "specify a rpc listening address", func(v string) error {
|
||||||
la = append(la, v)
|
la = append(la, v)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
flgs.Func("ctl-on", "specify a listening address for control channel", func(v string) error {
|
||||||
|
ctl_addr = v // TODO: support multiple addrs
|
||||||
|
return nil
|
||||||
|
})
|
||||||
flgs.SetOutput(io.Discard) // prevent usage output
|
flgs.SetOutput(io.Discard) // prevent usage output
|
||||||
err = flgs.Parse(os.Args[2:])
|
err = flgs.Parse(os.Args[2:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -224,11 +231,11 @@ func main() {
|
|||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(la) < 0 || flgs.NArg() > 0 {
|
if ctl_addr == "" || len(la) < 0 || flgs.NArg() > 0 {
|
||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
err = server_main(la)
|
err = server_main(ctl_addr, la)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error())
|
||||||
goto oops
|
goto oops
|
||||||
@ -241,11 +248,11 @@ func main() {
|
|||||||
sa = make([]string, 0)
|
sa = make([]string, 0)
|
||||||
|
|
||||||
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
flgs.Func("listen-on", "specify a control channel address", func(v string) error {
|
flgs.Func("rpc-on", "specify a control channel address", func(v string) error {
|
||||||
la = append(la, v)
|
la = append(la, v)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
flgs.Func("server", "specify a server address", func(v string) error {
|
flgs.Func("rpc-server", "specify a rpc server address", func(v string) error {
|
||||||
sa = append(sa, v)
|
sa = append(sa, v)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -271,8 +278,8 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
||||||
wrong_usage:
|
wrong_usage:
|
||||||
fmt.Fprintf(os.Stderr, "USAGE: %s server --listen-on=addr:port\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "USAGE: %s server --rpc-on=addr:port --ctl-on=addr:port \n", os.Args[0])
|
||||||
fmt.Fprintf(os.Stderr, " %s client --listen-on=addr:port --server=addr:port peer-addr:peer-port\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, " %s client --rpc-server=addr:port --ctl-on=addr:port peer-addr:peer-port\n", os.Args[0])
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
|
13
server-ctl.go
Normal file
13
server-ctl.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package hodu
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type server_ctl_client_conns struct {
|
||||||
|
s *Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
func (ctl *server_ctl_client_conns) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
w.Write([]byte("hello"))
|
||||||
|
}
|
40
server-ws.go
Normal file
40
server-ws.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package hodu
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "net/http"
|
||||||
|
import "golang.org/x/net/websocket"
|
||||||
|
|
||||||
|
type server_ctl_ws_tty struct {
|
||||||
|
s *Server
|
||||||
|
h websocket.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func server_ws_tty (ws* websocket.Conn) {
|
||||||
|
var msg []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ws.Write([]byte("hello world\r\n"))
|
||||||
|
ws.Write([]byte("it's so wrong. it's awesome\r\n"))
|
||||||
|
ws.Write([]byte("it's so wrong. 동키가 지나간다.it's awesome\r\n"))
|
||||||
|
|
||||||
|
|
||||||
|
for {
|
||||||
|
err = websocket.Message.Receive(ws, &msg)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
} else if len(msg) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf ("RECEIVED MESSAGE [%v]\n", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctl *server_ctl_ws_tty) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ctl.h.ServeHTTP(w, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
server.go
29
server.go
@ -8,14 +8,16 @@ import "io"
|
|||||||
import "math/rand"
|
import "math/rand"
|
||||||
import "net"
|
import "net"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
import "os"
|
||||||
import "sync"
|
import "sync"
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
//import "time"
|
|
||||||
|
|
||||||
import "google.golang.org/grpc"
|
import "google.golang.org/grpc"
|
||||||
//import "google.golang.org/grpc/metadata"
|
//import "google.golang.org/grpc/metadata"
|
||||||
import "google.golang.org/grpc/peer"
|
import "google.golang.org/grpc/peer"
|
||||||
import "google.golang.org/grpc/stats"
|
import "google.golang.org/grpc/stats"
|
||||||
|
import "golang.org/x/net/websocket"
|
||||||
|
|
||||||
|
|
||||||
const PTS_LIMIT = 8192
|
const PTS_LIMIT = 8192
|
||||||
|
|
||||||
@ -34,6 +36,8 @@ type Server struct {
|
|||||||
stop_req atomic.Bool
|
stop_req atomic.Bool
|
||||||
stop_chan chan bool
|
stop_chan chan bool
|
||||||
|
|
||||||
|
ctl_prefix string
|
||||||
|
ctl_mux *http.ServeMux
|
||||||
ctl *http.Server // control server
|
ctl *http.Server // control server
|
||||||
|
|
||||||
l []*net.TCPListener // main listener for grpc
|
l []*net.TCPListener // main listener for grpc
|
||||||
@ -689,13 +693,14 @@ func unaryInterceptor(ctx context.Context, req any, _ *grpc.UnaryServerInfo, han
|
|||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(ctx context.Context, laddrs []string, logger Logger, tlscfg *tls.Config) (*Server, error) {
|
func NewServer(ctx context.Context, ctl_addr string, laddrs []string, logger Logger, tlscfg *tls.Config) (*Server, error) {
|
||||||
var s Server
|
var s Server
|
||||||
var l *net.TCPListener
|
var l *net.TCPListener
|
||||||
var laddr *net.TCPAddr
|
var laddr *net.TCPAddr
|
||||||
var err error
|
var err error
|
||||||
var addr string
|
var addr string
|
||||||
var gl *net.TCPListener
|
var gl *net.TCPListener
|
||||||
|
var cwd string
|
||||||
|
|
||||||
if len(laddrs) <= 0 {
|
if len(laddrs) <= 0 {
|
||||||
return nil, fmt.Errorf("no server addresses provided")
|
return nil, fmt.Errorf("no server addresses provided")
|
||||||
@ -738,6 +743,21 @@ func NewServer(ctx context.Context, laddrs []string, logger Logger, tlscfg *tls.
|
|||||||
) // TODO: have this outside the server struct?
|
) // TODO: have this outside the server struct?
|
||||||
RegisterHoduServer(s.gs, &s)
|
RegisterHoduServer(s.gs, &s)
|
||||||
|
|
||||||
|
s.ctl_prefix = "" // TODO:
|
||||||
|
|
||||||
|
s.ctl_mux = http.NewServeMux()
|
||||||
|
cwd, _ = os.Getwd()
|
||||||
|
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.HandleFunc(s.ctl_prefix + "/ws/tty", websocket.Handler(server_ws_tty).ServeHTTP)
|
||||||
|
s.ctl_mux.Handle(s.ctl_prefix + "/ws/tty", &server_ctl_ws_tty{s: &s, h: websocket.Handler(server_ws_tty)})
|
||||||
|
s.ctl_mux.Handle(s.ctl_prefix + "/server-conns", &server_ctl_client_conns{s: &s})
|
||||||
|
|
||||||
|
s.ctl = &http.Server{
|
||||||
|
Addr: ctl_addr,
|
||||||
|
Handler: s.ctl_mux,
|
||||||
|
// TODO: more settings
|
||||||
|
}
|
||||||
|
|
||||||
return &s, nil
|
return &s, nil
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
@ -921,6 +941,11 @@ func (s *Server) StartExtService(svc Service, data interface{}) {
|
|||||||
go svc.RunTask(&s.wg)
|
go svc.RunTask(&s.wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) StartCtlService() {
|
||||||
|
s.wg.Add(1)
|
||||||
|
go s.RunCtlTask(&s.wg)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) StopServices() {
|
func (s *Server) StopServices() {
|
||||||
var ext_svc Service
|
var ext_svc Service
|
||||||
s.ReqStop()
|
s.ReqStop()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user