diff --git a/rvpn/envelope/envelope.go b/rvpn/envelope/envelope.go
new file mode 100644
index 0000000..b484b40
--- /dev/null
+++ b/rvpn/envelope/envelope.go
@@ -0,0 +1,43 @@
+package envelope
+
+import "time"
+import "encoding/json"
+import "bytes"
+import "io"
+
+//Envelope -- Standard daplie response structure
+type Envelope struct {
+ TransactionType string `json:"type"`
+ Schema string `json:"schema"`
+ TransactionTimeStamp int64 `json:"txts"`
+ TransactionID int64 `json:"txid"`
+ Error string `json:"error"`
+ ErrorDescription string `json:"error_description"`
+ ErrorURI string `json:"error_uri"`
+ Result interface{} `json:"result"`
+}
+
+//NewEnvelope -- Constructor
+func NewEnvelope(transactionType string) (p *Envelope) {
+ transactionID++
+
+ p = new(Envelope)
+ p.TransactionType = transactionType
+ p.TransactionID = transactionID
+ p.TransactionTimeStamp = time.Now().Unix()
+ p.Error = "ok"
+
+ return
+}
+
+//Generate -- encode into JSON and return string
+func (e *Envelope) Generate() string {
+ buf := new(bytes.Buffer)
+ json.NewEncoder(buf).Encode(e)
+ return buf.String()
+}
+
+//GenerateWriter --
+func (e *Envelope) GenerateWriter(w io.Writer) {
+ json.NewEncoder(w).Encode(e)
+}
diff --git a/rvpn/envelope/setup.go b/rvpn/envelope/setup.go
new file mode 100644
index 0000000..ccd443b
--- /dev/null
+++ b/rvpn/envelope/setup.go
@@ -0,0 +1,19 @@
+package envelope
+
+import (
+ "log"
+ "os"
+)
+
+var (
+ loginfo *log.Logger
+ logdebug *log.Logger
+ logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
+ transactionID int64
+)
+
+func init() {
+ loginfo = log.New(os.Stdout, "INFO: envelope: ", logFlags)
+ logdebug = log.New(os.Stdout, "DEBUG: envelope:", logFlags)
+ transactionID = 1
+}
diff --git a/rvpn/genericlistener/api_collect_server.go b/rvpn/genericlistener/api_collect_server.go
new file mode 100644
index 0000000..813fb8d
--- /dev/null
+++ b/rvpn/genericlistener/api_collect_server.go
@@ -0,0 +1,31 @@
+package genericlistener
+
+import (
+ "fmt"
+ "time"
+)
+
+//ServerAPI -- Structure to support the server API
+type ServerAPI struct {
+ ServerName string `json:"server_name"`
+ ServerID int64 `json:"server_id"`
+ Domains []*DomainAPI `json:"domains"`
+ Duration float64 `json:"duration"`
+ BytesIn int64 `json:"bytes_in"`
+ BytesOut int64 `json:"bytes_out"`
+ Source string `json:"source_address"`
+}
+
+//NewServerAPI - Constructor
+func NewServerAPI(c *Connection) (s *ServerAPI) {
+ s = new(ServerAPI)
+ s.ServerName = fmt.Sprintf("%p", c)
+ s.ServerID = c.ConnectionID()
+ s.Domains = make([]*DomainAPI, 0)
+ s.Duration = time.Since(c.ConnectTime()).Seconds()
+ s.BytesIn = c.BytesIn()
+ s.BytesOut = c.BytesOut()
+ s.Source = c.source
+
+ return
+}
diff --git a/rvpn/genericlistener/server_api.go b/rvpn/genericlistener/api_collect_servers.go
similarity index 68%
rename from rvpn/genericlistener/server_api.go
rename to rvpn/genericlistener/api_collect_servers.go
index 2f84e27..152322e 100644
--- a/rvpn/genericlistener/server_api.go
+++ b/rvpn/genericlistener/api_collect_servers.go
@@ -5,23 +5,27 @@ import (
"time"
)
-//ServerAPI -- Structure to support the server API
-type ServerAPI struct {
+//ServersAPI -- Structure to support the server API
+type ServersAPI struct {
ServerName string `json:"server_name"`
+ ServerID int64 `json:"server_id"`
Domains []*DomainAPI `json:"domains"`
Duration float64 `json:"duration"`
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"`
+ Source string `json:"source_address"`
}
-//NewServerAPI - Constructor
-func NewServerAPI(c *Connection) (s *ServerAPI) {
- s = new(ServerAPI)
+//NewServersAPI - Constructor
+func NewServersAPI(c *Connection) (s *ServersAPI) {
+ s = new(ServersAPI)
s.ServerName = fmt.Sprintf("%p", c)
+ s.ServerID = c.ConnectionID()
s.Domains = make([]*DomainAPI, 0)
s.Duration = time.Since(c.ConnectTime()).Seconds()
s.BytesIn = c.BytesIn()
s.BytesOut = c.BytesOut()
+ s.Source = c.Source()
for d := range c.DomainTrack {
dt := c.DomainTrack[d]
@@ -33,12 +37,12 @@ func NewServerAPI(c *Connection) (s *ServerAPI) {
//ServerAPIContainer -- Holder for all the Servers
type ServerAPIContainer struct {
- Servers []*ServerAPI `json:"servers"`
+ Servers []*ServersAPI `json:"servers"`
}
//NewServerAPIContainer -- Constructor
func NewServerAPIContainer() (p *ServerAPIContainer) {
p = new(ServerAPIContainer)
- p.Servers = make([]*ServerAPI, 0)
+ p.Servers = make([]*ServersAPI, 0)
return p
}
diff --git a/rvpn/genericlistener/api_endpoints.go b/rvpn/genericlistener/api_endpoints.go
deleted file mode 100644
index 92ffa03..0000000
--- a/rvpn/genericlistener/api_endpoints.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package genericlistener
-
-import "net/http"
-
-type apiEndPoint struct {
- pack string
- endpoint string
- method func(w http.ResponseWriter, r *http.Request)
-}
-
-type APIEndPoints struct {
- endPoint map[string]*apiEndPoint
-}
-
-//NewAPIEndPoints -- Constructor
-func NewAPIEndPoints() (p *APIEndPoints) {
- p = new(apiEndPoints)
- p.endPoint = make(map[string]*apiEndPoint)
- return
-}
-
-func (p *apiEndPoints) add(pack string, endpoint string, method func(w http.ResponseWriter, r *http.Request)) {
-
- router.HandleFunc("/api/"+rDNSPackageName+"servers", apiServers)
-}
diff --git a/rvpn/genericlistener/api_interface.go b/rvpn/genericlistener/api_interface.go
index fc6ac23..688b9ff 100644
--- a/rvpn/genericlistener/api_interface.go
+++ b/rvpn/genericlistener/api_interface.go
@@ -2,16 +2,18 @@ package genericlistener
import (
"context"
- "encoding/json"
"fmt"
"net/http"
+ "runtime"
+ "strconv"
"strings"
+ "git.daplie.com/Daplie/go-rvpn-server/rvpn/envelope"
"github.com/gorilla/mux"
)
const (
- rDNSPackageName = "com.daplie.rvpn"
+ endPointPrefix = "/api/com.daplie.rvpn/"
)
var connectionTable *Table
@@ -23,8 +25,6 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
connectionTable = ctx.Value(ctxConnectionTable).(*Table)
router := mux.NewRouter().StrictSlash(true)
- endpoints := make(map[string]string)
-
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
loginfo.Println("HandleFunc /")
switch url := r.URL.Path; url {
@@ -41,10 +41,12 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
router.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
- fmt.Fprintln(w, "Welcome..press Servers to access stats")
+ fmt.Fprintln(w, "Welcome..press Servers to access stats")
})
- router.HandleFunc("/api/"+rDNSPackageName+"servers", apiServers)
+ router.HandleFunc(endPointPrefix+"servers", getServersEndpoint).Methods("GET")
+ router.HandleFunc(endPointPrefix+"server/", getServerEndpoint).Methods("GET")
+ router.HandleFunc(endPointPrefix+"server/{server-id}", getServerEndpoint).Methods("GET")
s := &http.Server{
Addr: ":80",
@@ -63,17 +65,60 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
}
}
-func apiServers(w http.ResponseWriter, r *http.Request) {
- fmt.Println("here")
+func getServersEndpoint(w http.ResponseWriter, r *http.Request) {
+ pc, _, _, _ := runtime.Caller(0)
+ loginfo.Println(runtime.FuncForPC(pc).Name())
+
serverContainer := NewServerAPIContainer()
for c := range connectionTable.Connections() {
- serverAPI := NewServerAPI(c)
+ serverAPI := NewServersAPI(c)
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
- json.NewEncoder(w).Encode(serverContainer)
+
+ env := envelope.NewEnvelope("servers/GET")
+ env.Result = serverContainer
+ env.GenerateWriter(w)
+
+ //json.NewEncoder(w).Encode(serverContainer)
}
+
+func getServerEndpoint(w http.ResponseWriter, r *http.Request) {
+ pc, _, _, _ := runtime.Caller(0)
+ loginfo.Println(runtime.FuncForPC(pc).Name())
+
+ env := envelope.NewEnvelope("server/GET")
+
+ params := mux.Vars(r)
+ if id, ok := params["server-id"]; !ok {
+ env.Error = "server-id is missing"
+ env.ErrorURI = r.RequestURI
+ env.ErrorDescription = "server API requires a server-id"
+ } else {
+ serverID, err := strconv.Atoi(id)
+ if err != nil {
+ env.Error = "server-id is not an integer"
+ env.ErrorURI = r.RequestURI
+ env.ErrorDescription = "server API requires a server-id"
+
+ } else {
+ conn, err := connectionTable.GetConnection(int64(serverID))
+ if err != nil {
+ env.Error = "server-id was not found"
+ env.ErrorURI = r.RequestURI
+ env.ErrorDescription = "missing server-id, make sure desired service-id is in servers"
+ } else {
+ loginfo.Println("test")
+ serverAPI := NewServerAPI(conn)
+ env.Result = serverAPI
+
+ }
+ }
+ }
+ w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+ env.GenerateWriter(w)
+}
diff --git a/rvpn/genericlistener/connection.go b/rvpn/genericlistener/connection.go
index 6112e28..c7cd016 100755
--- a/rvpn/genericlistener/connection.go
+++ b/rvpn/genericlistener/connection.go
@@ -63,10 +63,15 @@ type Connection struct {
///wssState tracks a highlevel status of the connection, false means do nothing.
wssState bool
+
+ //connectionID
+ connectionID int64
}
//NewConnection -- Constructor
func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress string, initialDomains []interface{}, connectionTrack *Tracking) (p *Connection) {
+ connectionID = connectionID + 1
+
p = new(Connection)
p.mutex = &sync.Mutex{}
p.connectionTable = connectionTable
@@ -85,6 +90,7 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s
}
p.State(true)
+ p.connectionID = connectionID
return
}
@@ -124,6 +130,11 @@ func (c *Connection) SendCh() chan *SendTrack {
return c.send
}
+//Source --
+func (c *Connection) Source() string {
+ return c.source
+}
+
func (c *Connection) addIn(num int64) {
c.bytesIn = c.bytesIn + num
}
@@ -167,6 +178,11 @@ func (c *Connection) Update() {
c.lastUpdate = time.Now()
}
+//ConnectionID - Get
+func (c *Connection) ConnectionID() int64 {
+ return c.connectionID
+}
+
//NextWriter -- Wrapper to allow a high level state check before offering NextWriter
//The libary failes if client abends during write-cycle. a fast moving write is not caught before socket state bubbles up
//A synchronised state is maintained
diff --git a/rvpn/genericlistener/connection_table.go b/rvpn/genericlistener/connection_table.go
index ff57042..e0a2f6e 100755
--- a/rvpn/genericlistener/connection_table.go
+++ b/rvpn/genericlistener/connection_table.go
@@ -66,6 +66,19 @@ func (c *Table) reaper(delay int, idle int) {
}
}
+//GetConnection -- find connection by server-id
+func (c *Table) GetConnection(serverID int64) (conn *Connection, err error) {
+ for conn := range c.connections {
+ if conn.ConnectionID() == serverID {
+ return conn, err
+ }
+ }
+
+ err = fmt.Errorf("Server-id %d not found", serverID)
+
+ return nil, err
+}
+
//Run -- Execute
func (c *Table) Run(ctx context.Context) {
loginfo.Println("ConnectionTable starting")
diff --git a/rvpn/genericlistener/setup.go b/rvpn/genericlistener/setup.go
index 79d6113..6541c3b 100644
--- a/rvpn/genericlistener/setup.go
+++ b/rvpn/genericlistener/setup.go
@@ -3,15 +3,21 @@ package genericlistener
import (
"log"
"os"
+ "runtime"
)
var (
- loginfo *log.Logger
- logdebug *log.Logger
- logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
+ loginfo *log.Logger
+ logdebug *log.Logger
+ logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
+ connectionID int64
)
func init() {
loginfo = log.New(os.Stdout, "INFO: genericlistener: ", logFlags)
logdebug = log.New(os.Stdout, "DEBUG: genericlistener:", logFlags)
+ pc, _, _, _ := runtime.Caller(0)
+ loginfo.Println(runtime.FuncForPC(pc).Name())
+
+ connectionID = 0
}