From 3dbdd694df41a1f3a667a89a2f5cc258f9185753 Mon Sep 17 00:00:00 2001 From: Henry Camacho Date: Wed, 15 Feb 2017 17:53:34 -0600 Subject: [PATCH] =?UTF-8?q?Admin=20interface=20=E2=80=94=20added=20api/ser?= =?UTF-8?q?vers=20-=20collects=20a=20list=20of=20WSS=20servers,=20and=20th?= =?UTF-8?q?e=20connection=20structure=20-=20calculates=20a=20connection=20?= =?UTF-8?q?duration=20-=20collects=20the=20bytes=20in/out=20-=20encodes=20?= =?UTF-8?q?to=20JSON=20and=20sends=20response.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +++++++ admin/html/index.html | 1 + admin/static/test.html | 1 + rvpn/admin/listener_admin.go | 93 +++++++++++++++++++++++------ rvpn/connection/connection.go | 23 +++++++ rvpn/connection/connection_table.go | 6 ++ rvpn/rvpnmain/run.go | 2 +- 7 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 admin/html/index.html create mode 100644 admin/static/test.html diff --git a/README.md b/README.md index d38a36f..b6d0b0d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,28 @@ # RVPN Server +Admin Interface +--------------- +Developing the API calls and buliding the structure behind it. +- build get mux router package --- +```bash +go get "github.com/gorilla/mux" +``` +- run go-rvpn-server +- execute stunnel (as below) +- browse to https://127.0.0.2:8000/api/servers + +```json +{"Servers":[{"ServerName":"0xc42005b110","Duration":42.342176121,"BytesIn":91,"BytesOut":3476}]} +``` + +The above is telemetry from the RVPN server. + +Work is continuing, please review make sure it is what you are looking for. + +We will need to deal with server name, I am placing the point address for now, not sure how to handle the name. + + + Traffic Testing --------------- * run go-rvpn-server diff --git a/admin/html/index.html b/admin/html/index.html new file mode 100644 index 0000000..d9cf2b7 --- /dev/null +++ b/admin/html/index.html @@ -0,0 +1 @@ +Hank diff --git a/admin/static/test.html b/admin/static/test.html new file mode 100644 index 0000000..896227b --- /dev/null +++ b/admin/static/test.html @@ -0,0 +1 @@ +Test.html diff --git a/rvpn/admin/listener_admin.go b/rvpn/admin/listener_admin.go index 52d4d8e..be141e4 100644 --- a/rvpn/admin/listener_admin.go +++ b/rvpn/admin/listener_admin.go @@ -1,39 +1,94 @@ package admin import ( - "html/template" + "encoding/json" + "fmt" "net/http" + "time" + + "git.daplie.com/Daplie/go-rvpn-server/rvpn/connection" + + "github.com/gorilla/mux" +) + +var ( + connTable *connection.Table ) //LaunchAdminListener - starts up http listeners and handles various URI paths -func LaunchAdminListener(serverBinding *string) (err error) { +func LaunchAdminListener(serverBinding *string, connectionTable *connection.Table) (err error) { loginfo.Println("starting launchAdminListener", *serverBinding) - mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - switch url := r.URL.Path; url { - case "/": - //handleConnectionWebSocket(connectionTable, w, r, false) - //w.Header().Set("Content-Type", "text/html; charset=utf-8") - //template.Must(template.ParseFiles("html/client.html")).Execute(w, r.Host) + connTable = connectionTable - case "/admin": - w.Header().Set("Content-Type", "text/html; charset=utf-8") - template.Must(template.ParseFiles("html/admin.html")).Execute(w, r.Host) + router := mux.NewRouter().StrictSlash(true) + router.HandleFunc("/", index) + router.HandleFunc("/api/servers", apiServers) - default: - http.Error(w, "Not Found", 404) - - } - }) s := &http.Server{ Addr: *serverBinding, - Handler: mux, + Handler: router, } - err = s.ListenAndServe() + err = s.ListenAndServeTLS("certs/fullchain.pem", "certs/privkey.pem") if err != nil { loginfo.Println("ListenAndServe: ", err) } return } + +func index(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Welcome!") +} + +//ServerAPI -- Structure to support the server API +type ServerAPI struct { + ServerName string + Duration float64 + BytesIn int64 + BytesOut int64 +} + +//NewServerAPI - Constructor +func NewServerAPI(c *connection.Connection) (s *ServerAPI) { + s = new(ServerAPI) + s.ServerName = fmt.Sprintf("%p", c) + + fmt.Println(s.ServerName) + + s.Duration = time.Since(c.ConnectTime()).Seconds() + s.BytesIn = c.BytesIn() + s.BytesOut = c.BytesOut() + return + +} + +//ServerAPIContainer -- Holder for all the Servers +type ServerAPIContainer struct { + Servers []*ServerAPI +} + +//NewServerAPIContainer -- Constructor +func NewServerAPIContainer() (p *ServerAPIContainer) { + p = new(ServerAPIContainer) + p.Servers = make([]*ServerAPI, 0) + return p +} + +func apiServers(w http.ResponseWriter, r *http.Request) { + fmt.Println("here") + serverContainer := NewServerAPIContainer() + + for c := range connTable.Connections() { + serverAPI := NewServerAPI(c) + serverContainer.Servers = append(serverContainer.Servers, serverAPI) + } + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + json.NewEncoder(w).Encode(serverContainer) + +} + +func handleRequest(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Domain not supported", http.StatusBadRequest) +} diff --git a/rvpn/connection/connection.go b/rvpn/connection/connection.go index dd4cdd4..67fca8c 100755 --- a/rvpn/connection/connection.go +++ b/rvpn/connection/connection.go @@ -2,6 +2,7 @@ package connection import ( "encoding/hex" + "time" "github.com/gorilla/websocket" ) @@ -33,6 +34,9 @@ type Connection struct { // communications channel between go routines commCh chan bool + // Connect Time + connectTime time.Time + //initialDomains - a list of domains from the JWT initialDomains []interface{} } @@ -47,10 +51,29 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s p.bytesOut = 0 p.send = make(chan []byte, 256) p.commCh = make(chan bool) + p.connectTime = time.Now() p.initialDomains = initialDomains return } +//ConnectTime -- Property +func (c *Connection) ConnectTime() (t time.Time) { + t = c.connectTime + return +} + +//BytesIn -- Property +func (c *Connection) BytesIn() (b int64) { + b = c.bytesIn + return +} + +//BytesOut -- Property +func (c *Connection) BytesOut() (b int64) { + b = c.bytesOut + return +} + //SendCh -- property to sending channel func (c *Connection) SendCh() chan []byte { return c.send diff --git a/rvpn/connection/connection_table.go b/rvpn/connection/connection_table.go index f85ad08..46c787e 100755 --- a/rvpn/connection/connection_table.go +++ b/rvpn/connection/connection_table.go @@ -29,6 +29,12 @@ func NewTable() (p *Table) { return } +//Connections Property +func (c *Table) Connections() (table map[*Connection][]string) { + table = c.connections + return +} + //ConnByDomain -- Obtains a connection from a domain announcement. func (c *Table) ConnByDomain(domain string) (conn *Connection, ok bool) { conn, ok = c.domains[domain] diff --git a/rvpn/rvpnmain/run.go b/rvpn/rvpnmain/run.go index 438d12e..d58832f 100644 --- a/rvpn/rvpnmain/run.go +++ b/rvpn/rvpnmain/run.go @@ -58,7 +58,7 @@ func Run() { go client.LaunchClientListener(connectionTable, &secretKey, &argServerBinding) go external.LaunchWebRequestExternalListener(&argServerExternalBinding, connectionTable) - err := admin.LaunchAdminListener(&argServerAdminBinding) + err := admin.LaunchAdminListener(&argServerAdminBinding, connectionTable) if err != nil { loginfo.Println("LauchAdminListener failed: ", err) }