Admin interface — added api/servers

- collects a list of WSS servers, and the connection structure
- calculates a connection duration
- collects the bytes in/out
- encodes to JSON and sends response.
This commit is contained in:
Henry Camacho 2017-02-15 17:53:34 -06:00
parent 2fdb033c55
commit 3dbdd694df
7 changed files with 129 additions and 20 deletions

View File

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

1
admin/html/index.html Normal file
View File

@ -0,0 +1 @@
Hank

1
admin/static/test.html Normal file
View File

@ -0,0 +1 @@
Test.html

View File

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

View File

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

View File

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

View File

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