diff --git a/backend/services/controller/go.mod b/backend/services/controller/go.mod index 8b2af54..9841213 100755 --- a/backend/services/controller/go.mod +++ b/backend/services/controller/go.mod @@ -30,5 +30,6 @@ require ( github.com/xdg-go/stringprep v1.0.3 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect ) diff --git a/backend/services/controller/go.sum b/backend/services/controller/go.sum index 009aa33..c6c36ac 100644 --- a/backend/services/controller/go.sum +++ b/backend/services/controller/go.sum @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/backend/services/controller/internal/api/api.go b/backend/services/controller/internal/api/api.go index be73415..408e589 100644 --- a/backend/services/controller/internal/api/api.go +++ b/backend/services/controller/internal/api/api.go @@ -50,6 +50,7 @@ func StartApi(a Api) { authentication.HandleFunc("/admin/register", a.registerAdminUser).Methods("POST") authentication.HandleFunc("/admin/exists", a.adminUserExists).Methods("GET") iot := r.PathPrefix("/api/device").Subrouter() + //TODO: create query for devices iot.HandleFunc("", a.retrieveDevices).Methods("GET") iot.HandleFunc("/{sn}/get", a.deviceGetMsg).Methods("PUT") iot.HandleFunc("/{sn}/add", a.deviceCreateMsg).Methods("PUT") @@ -60,18 +61,24 @@ func StartApi(a Api) { iot.HandleFunc("/{sn}/operate", a.deviceOperateMsg).Methods("PUT") iot.HandleFunc("/{sn}/fw_update", a.deviceFwUpdate).Methods("PUT") iot.HandleFunc("/{sn}/wifi", a.deviceWifi).Methods("PUT", "GET") + mtp := r.PathPrefix("/api/mtp").Subrouter() + mtp.HandleFunc("/mqtt", a.MqttInfo).Methods("GET") + users := r.PathPrefix("/api/users").Subrouter() + users.HandleFunc("", a.retrieveUsers).Methods("GET") - // Middleware for requests which requires user to be authenticated + /* ----- Middleware for requests which requires user to be authenticated ---- */ iot.Use(func(handler http.Handler) http.Handler { return middleware.Middleware(handler) }) - users := r.PathPrefix("/api/users").Subrouter() - users.HandleFunc("", a.retrieveUsers).Methods("GET") + mtp.Use(func(handler http.Handler) http.Handler { + return middleware.Middleware(handler) + }) users.Use(func(handler http.Handler) http.Handler { return middleware.Middleware(handler) }) + /* -------------------------------------------------------------------------- */ // Verifies CORS configs for requests corsOpts := cors.GetCorsConfig() diff --git a/backend/services/controller/internal/api/mtp.go b/backend/services/controller/internal/api/mtp.go new file mode 100644 index 0000000..10c4ca6 --- /dev/null +++ b/backend/services/controller/internal/api/mtp.go @@ -0,0 +1,55 @@ +package api + +import ( + "encoding/json" + "net" + "net/http" + "time" + + "golang.org/x/sys/unix" +) + +type mqttInfo struct { + Rtt time.Duration +} + +func (a *Api) MqttInfo(w http.ResponseWriter, r *http.Request) { + //TODO: address with value from env or something like that + conn, err := net.Dial("tcp", "127.0.0.1:1883") + if err != nil { + json.NewEncoder(w).Encode("Error to connect to broker") + w.WriteHeader(http.StatusInternalServerError) + return + } + defer conn.Close() + + info, err := tcpInfo(conn.(*net.TCPConn)) + if err != nil { + json.NewEncoder(w).Encode("Error to get TCP socket info") + w.WriteHeader(http.StatusInternalServerError) + return + } + rtt := time.Duration(info.Rtt) * time.Microsecond + json.NewEncoder(w).Encode(mqttInfo{ + Rtt: rtt / 1000, + }) +} + +func tcpInfo(conn *net.TCPConn) (*unix.TCPInfo, error) { + raw, err := conn.SyscallConn() + if err != nil { + return nil, err + } + + var info *unix.TCPInfo + ctrlErr := raw.Control(func(fd uintptr) { + info, err = unix.GetsockoptTCPInfo(int(fd), unix.IPPROTO_TCP, unix.TCP_INFO) + }) + switch { + case ctrlErr != nil: + return nil, ctrlErr + case err != nil: + return nil, err + } + return info, nil +}