used 'flag' to parse command line
This commit is contained in:
parent
662f623f4c
commit
7333e40d9c
118
client.go
118
client.go
@ -5,11 +5,12 @@ package main
|
|||||||
import "context"
|
import "context"
|
||||||
import "crypto/tls"
|
import "crypto/tls"
|
||||||
import "crypto/x509"
|
import "crypto/x509"
|
||||||
//import "encoding/binary"
|
import "encoding/json"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "io"
|
import "io"
|
||||||
import "log"
|
import "log"
|
||||||
import "net"
|
import "net"
|
||||||
|
import "net/http"
|
||||||
import "os"
|
import "os"
|
||||||
import "os/signal"
|
import "os/signal"
|
||||||
import "sync"
|
import "sync"
|
||||||
@ -36,19 +37,20 @@ type ClientConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctx_cancel context.CancelFunc
|
ctx_cancel context.CancelFunc
|
||||||
tlscfg *tls.Config
|
tlscfg *tls.Config
|
||||||
|
|
||||||
cts_mtx sync.Mutex
|
ctl *http.Server // control server
|
||||||
cts_map ServerConnMap
|
|
||||||
|
|
||||||
wg sync.WaitGroup
|
cts_mtx sync.Mutex
|
||||||
stop_req atomic.Bool
|
cts_map ServerConnMap
|
||||||
stop_chan chan bool
|
|
||||||
|
wg sync.WaitGroup
|
||||||
|
stop_req atomic.Bool
|
||||||
|
stop_chan chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type ClientPeerConn struct {
|
type ClientPeerConn struct {
|
||||||
route *ClientRoute
|
route *ClientRoute
|
||||||
conn_id uint32
|
conn_id uint32
|
||||||
@ -96,6 +98,10 @@ type ClientRoute struct {
|
|||||||
stop_chan chan bool
|
stop_chan chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientCtlParamServer struct {
|
||||||
|
ServerAddr string `json:"server-addr"`
|
||||||
|
PeerAddrs []string `json:"peer-addrs"`
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
func NewClientRoute(cts *ServerConn, id uint32, addr *net.TCPAddr, proto ROUTE_PROTO) *ClientRoute {
|
func NewClientRoute(cts *ServerConn, id uint32, addr *net.TCPAddr, proto ROUTE_PROTO) *ClientRoute {
|
||||||
@ -280,21 +286,22 @@ func (cts *ServerConn) RunTask(wg *sync.WaitGroup) {
|
|||||||
var psc PacketStreamClient
|
var psc PacketStreamClient
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
defer wg.Done(); // arrange to call at the end of this function
|
defer wg.Done() // arrange to call at the end of this function
|
||||||
|
|
||||||
// TODO: HANDLE connection timeout..
|
// TODO: HANDLE connection timeout..
|
||||||
// ctx, _/*cancel*/ := context.WithTimeout(context.Background(), time.Second)
|
// ctx, _/*cancel*/ := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
fmt.Printf (">>>[%s]\n", cts.saddr.String())
|
||||||
conn, err = grpc.NewClient(cts.saddr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
conn, err = grpc.NewClient(cts.saddr.String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: logging
|
// TODO: logging
|
||||||
fmt.Printf("ERROR - unable to connect to %s - %s", cts.cfg.server_addr, err.Error())
|
fmt.Printf("ERROR: unable to connect to %s - %s", cts.cfg.server_addr, err.Error())
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
|
|
||||||
hdc = NewHoduClient(conn)
|
hdc = NewHoduClient(conn)
|
||||||
psc, err = hdc.PacketStream(cts.cli.ctx) // TODO: accept external context and use it.L
|
psc, err = hdc.PacketStream(cts.cli.ctx) // TODO: accept external context and use it.L
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf ("failed to get the packet stream - %s", err.Error())
|
fmt.Printf ("ERROR: unable to get the packet stream - %s", err.Error())
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +313,7 @@ func (cts *ServerConn) RunTask(wg *sync.WaitGroup) {
|
|||||||
// let's add routes to the client-side peers.
|
// let's add routes to the client-side peers.
|
||||||
err = cts.AddClientRoutes(cts.cfg.peer_addrs)
|
err = cts.AddClientRoutes(cts.cfg.peer_addrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf ("unable to add routes to client-side peers - %s", err.Error())
|
fmt.Printf ("ERROR: unable to add routes to client-side peers - %s", err.Error())
|
||||||
goto done
|
goto done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +485,8 @@ func (r *ClientRoute) AddNewClientPeerConn (c net.Conn) (*ClientPeerConn, error)
|
|||||||
}
|
}
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
func NewClient(ctx context.Context, tlscfg *tls.Config) *Client {
|
|
||||||
|
func NewClient(ctx context.Context, listen_on string, 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)
|
||||||
@ -487,6 +495,11 @@ func NewClient(ctx context.Context, tlscfg *tls.Config) *Client {
|
|||||||
c.stop_req.Store(false)
|
c.stop_req.Store(false)
|
||||||
c.stop_chan = make(chan bool, 1)
|
c.stop_chan = make(chan bool, 1)
|
||||||
|
|
||||||
|
c.ctl = &http.Server{
|
||||||
|
Addr: listen_on,
|
||||||
|
Handler: &c,
|
||||||
|
}
|
||||||
|
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +540,9 @@ fmt.Printf ("REMOVE total servers %d\n", len(c.cts_map));
|
|||||||
func (c *Client) ReqStop() {
|
func (c *Client) ReqStop() {
|
||||||
if c.stop_req.CompareAndSwap(false, true) {
|
if c.stop_req.CompareAndSwap(false, true) {
|
||||||
var cts *ServerConn
|
var cts *ServerConn
|
||||||
|
|
||||||
|
c.ctl.Shutdown(c.ctx) // to break c.ctl.ListenAndServe()
|
||||||
|
|
||||||
for _, cts = range c.cts_map {
|
for _, cts = range c.cts_map {
|
||||||
cts.ReqStop()
|
cts.ReqStop()
|
||||||
}
|
}
|
||||||
@ -538,6 +554,67 @@ func (c *Client) ReqStop() {
|
|||||||
fmt.Printf ("*** Sent stop request to client..\n");
|
fmt.Printf ("*** Sent stop request to client..\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// command handler for the control channel
|
||||||
|
if req.URL.String() == "/servers" {
|
||||||
|
switch req.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
goto bad_request // TODO:
|
||||||
|
|
||||||
|
case http.MethodPost:
|
||||||
|
var s ClientCtlParamServer
|
||||||
|
var cc ClientConfig
|
||||||
|
err = json.NewDecoder(req.Body).Decode(&s)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf ("failed to decode body - %s\n", err.Error())
|
||||||
|
goto bad_request
|
||||||
|
}
|
||||||
|
cc.server_addr = s.ServerAddr
|
||||||
|
cc.peer_addrs = s.PeerAddrs
|
||||||
|
c.RunService(&cc)
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
|
||||||
|
case http.MethodPut:
|
||||||
|
goto bad_request // TODO:
|
||||||
|
|
||||||
|
case http.MethodDelete:
|
||||||
|
var cts *ServerConn
|
||||||
|
for _, cts = range c.cts_map {
|
||||||
|
cts.ReqStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
goto bad_request
|
||||||
|
}
|
||||||
|
fmt.Printf ("[%s][%s][%s]\n", req.RequestURI, req.URL.String(), req.Method)
|
||||||
|
return
|
||||||
|
|
||||||
|
bad_request:
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POST GET PUT DELETE
|
||||||
|
* /servers - create new server list all servers bulk update delete all servers
|
||||||
|
* /servers/1 - X get server 1 details update server 1 delete server 1
|
||||||
|
* /servers/1/xxx -
|
||||||
|
*/
|
||||||
|
func (c *Client) RunCtlTask() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
defer c.wg.Done()
|
||||||
|
|
||||||
|
err = c.ctl.ListenAndServe()
|
||||||
|
if err != http.ErrServerClosed {
|
||||||
|
fmt.Printf ("------------http server error - %s\n", err.Error())
|
||||||
|
} else {
|
||||||
|
fmt.Printf ("********* http server ended\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// naming convention:
|
// naming convention:
|
||||||
// RunService - returns after having executed another go routine
|
// RunService - returns after having executed another go routine
|
||||||
// RunTask - supposed to be detached as a go routine
|
// RunTask - supposed to be detached as a go routine
|
||||||
@ -630,7 +707,7 @@ BAMCA0gAMEUCIEKzVMF3JqjQjuM2rX7Rx8hancI5KJhwfeKu1xbyR7XaAiEA2UT7
|
|||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
`
|
`
|
||||||
|
|
||||||
func client_main(server_addr string, peer_addrs []string) error {
|
func client_main(listen_on string, server_addr string, peer_addrs []string) error {
|
||||||
var c *Client
|
var c *Client
|
||||||
var cert_pool *x509.CertPool
|
var cert_pool *x509.CertPool
|
||||||
var tlscfg *tls.Config
|
var tlscfg *tls.Config
|
||||||
@ -647,19 +724,18 @@ func client_main(server_addr string, peer_addrs []string) error {
|
|||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
c = NewClient(context.Background(), tlscfg)
|
c = NewClient(context.Background(), listen_on, tlscfg)
|
||||||
|
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
go c.handle_os_signals()
|
go c.handle_os_signals()
|
||||||
|
|
||||||
|
c.wg.Add(1)
|
||||||
|
go c.RunCtlTask() // control channel task
|
||||||
|
|
||||||
cc.server_addr = server_addr
|
cc.server_addr = server_addr
|
||||||
cc.peer_addrs = peer_addrs
|
cc.peer_addrs = peer_addrs
|
||||||
c.RunService(&cc)
|
c.RunService(&cc)
|
||||||
|
|
||||||
//cc.server_addr = "some other address..."
|
|
||||||
//cc.peer_addrs = peer_addrs
|
|
||||||
//c.RunService(&cc)
|
|
||||||
|
|
||||||
c.WaitForTermination()
|
c.WaitForTermination()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
70
main.go
70
main.go
@ -1,33 +1,80 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "flag"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "os"
|
import "os"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
|
type VoidWriter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *VoidWriter) Write(p []byte) (int, error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
|
var flgs *flag.FlagSet
|
||||||
|
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.EqualFold(os.Args[1], "server") {
|
if strings.EqualFold(os.Args[1], "server") {
|
||||||
if len(os.Args) < 3 {
|
var la []string
|
||||||
|
la = make([]string, 0)
|
||||||
|
|
||||||
|
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
flgs.Func("listen-on", "specify a listening address", func(v string) error {
|
||||||
|
la = append(la, v)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
flgs.SetOutput(&VoidWriter{}) // prevent usage output
|
||||||
|
err = flgs.Parse(os.Args[2:])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf ("ERROR: unable to parse command arguments - %s\n", err.Error())
|
||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
}
|
}
|
||||||
err = server_main(os.Args[2:])
|
|
||||||
|
if len(la) < 0 || flgs.NArg() > 0 {
|
||||||
|
goto wrong_usage
|
||||||
|
}
|
||||||
|
|
||||||
|
err = server_main(la)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: serer error - %s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error())
|
||||||
os.Exit(1)
|
goto oops
|
||||||
}
|
}
|
||||||
} else if strings.EqualFold(os.Args[1], "client") {
|
} else if strings.EqualFold(os.Args[1], "client") {
|
||||||
if len(os.Args) < 4 {
|
var la []string
|
||||||
|
var sa []string
|
||||||
|
|
||||||
|
la = make([]string, 0)
|
||||||
|
sa = make([]string, 0)
|
||||||
|
|
||||||
|
flgs = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
flgs.Func("listen-on", "specify a control channel address", func(v string) error {
|
||||||
|
la = append(la, v)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
flgs.Func("server", "specify a server address", func(v string) error {
|
||||||
|
sa = append(sa, v)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
flgs.SetOutput(&VoidWriter{}) // prevent usage output
|
||||||
|
err = flgs.Parse(os.Args[2:])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf ("ERROR: unable to parse command arguments - %s\n", err.Error())
|
||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
}
|
}
|
||||||
err = client_main(os.Args[2], os.Args[3:])
|
|
||||||
|
if len(la) != 1 || len(sa) != 1 || flgs.NArg() < 1 {
|
||||||
|
goto wrong_usage
|
||||||
|
}
|
||||||
|
err = client_main(la[0], sa[0], flgs.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: client error - %s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "ERROR: client error - %s\n", err.Error())
|
||||||
os.Exit(1)
|
goto oops
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goto wrong_usage
|
goto wrong_usage
|
||||||
@ -36,7 +83,10 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
||||||
wrong_usage:
|
wrong_usage:
|
||||||
fmt.Fprintf(os.Stderr, "USAGE: %s server listen-addr:listen-port\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "USAGE: %s server --listen-on=addr:port\n", os.Args[0])
|
||||||
fmt.Fprintf(os.Stderr, " %s client target-addr:target-port peer-addr:peer-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])
|
||||||
|
os.Exit(1)
|
||||||
|
|
||||||
|
oops:
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user