summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsinanmohd <sinan@sinanmohd.com>2024-07-04 13:13:23 +0530
committersinanmohd <sinan@sinanmohd.com>2024-07-05 17:02:06 +0530
commite2f67996a608346ea3f3525ef2febf6ca5d2b78c (patch)
tree932f766b65ed5a6ff3d57c772292a2b75210d9aa
parente309091d17720b69c53172a41c0ea45ad7b66911 (diff)
refactor: drop http api, move to sqlc/postgresql
-rw-r--r--api/exampleReq.go57
-rw-r--r--api/login.go61
-rw-r--r--api/main.go44
-rw-r--r--api/utils.go31
-rw-r--r--bpf/bpf_bpfel.go (renamed from cmd/bpf/bpf_bpfel.go)2
-rw-r--r--bpf/bpf_bpfel.o (renamed from cmd/bpf/bpf_bpfel.o)bin5312 -> 5312 bytes
-rw-r--r--bpf/bpf_usage.c (renamed from cmd/bpf/bpf_usage.c)0
-rw-r--r--bpf/gen.go (renamed from cmd/bpf/gen.go)2
-rw-r--r--bpf/main.go124
-rw-r--r--cmd/bpf/main.go96
-rw-r--r--cmd/redq/main.go14
-rw-r--r--cmd/redqctl/main.go74
-rw-r--r--db/account.go129
-rw-r--r--db/bearer.go127
-rw-r--r--db/db.go32
-rw-r--r--db/main.go77
-rw-r--r--db/models.go17
-rw-r--r--db/query.sql6
-rw-r--r--db/query.sql.go39
-rw-r--r--db/schema.sql7
-rw-r--r--db/sqlc.yaml10
-rw-r--r--db/utils.go24
-rw-r--r--flake.nix2
-rw-r--r--go.mod14
-rw-r--r--go.sum39
25 files changed, 268 insertions, 760 deletions
diff --git a/api/exampleReq.go b/api/exampleReq.go
deleted file mode 100644
index 54454a1..0000000
--- a/api/exampleReq.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package api
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
-
- redqdb "sinanmohd.com/redq/db"
-)
-
-type examplApiName struct {
- db *redqdb.SafeDB
- req *RequestApiName
- resp *ResponseApiName
-}
-
-type RequestApiName struct {
- BearerToken string
-}
-
-type ResponseApiName struct {
- Bearer *redqdb.Bearer
-}
-
-func newExamplApiName(db *redqdb.SafeDB) *examplApiName {
- a := &examplApiName{}
- a.db = db
-
- return a
-}
-
-func (a *examplApiName) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
- a.req = &RequestApiName{}
- a.resp = &ResponseApiName{}
- a.resp.Bearer = &redqdb.Bearer{}
-
- err := unmarshal(r.Body, a.req)
- fmt.Println(a.req)
- if err != nil {
- handleError(err, rw, http.StatusUnprocessableEntity)
- return
- }
-
- err = a.resp.Bearer.VerifyAndUpdate(a.db, a.req.BearerToken)
- if err != nil {
- handleError(err, rw, http.StatusUnauthorized)
- return
- }
-
- json, err := json.Marshal(a.resp)
- if err != nil {
- handleError(err, rw, http.StatusInternalServerError)
- return
- }
-
- rw.Write(json)
-}
diff --git a/api/login.go b/api/login.go
deleted file mode 100644
index ef43304..0000000
--- a/api/login.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package api
-
-import (
- "encoding/json"
- "net/http"
-
- "github.com/go-playground/validator/v10"
- redqdb "sinanmohd.com/redq/db"
-)
-
-type loginAPI struct {
- db *redqdb.SafeDB
- validate *validator.Validate
- req *RequestLogin
- resp *ResponseLogin
-}
-
-type RequestLogin struct {
- Account *redqdb.Account `validate:"required"`
-}
-
-type ResponseLogin struct {
- Account *redqdb.Account
-}
-
-func newLogin(db *redqdb.SafeDB) *loginAPI {
- a := &loginAPI{}
- a.db = db
- a.validate = validator.New(validator.WithRequiredStructEnabled())
-
- return a
-}
-
-func (a *loginAPI) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
- a.req = &RequestLogin{}
- a.resp = &ResponseLogin{}
-
- err := unmarshal(r.Body, a.req)
- if err == nil {
- err = a.validate.Struct(a.req)
- }
- if err != nil {
- handleError(err, rw, http.StatusUnprocessableEntity)
- return
- }
-
- err = a.req.Account.Login(a.db)
- if err != nil {
- handleError(err, rw, http.StatusUnauthorized)
- return
- }
- a.resp.Account = a.req.Account
-
- json, err := json.Marshal(a.resp)
- if err != nil {
- handleError(err, rw, http.StatusInternalServerError)
- return
- }
-
- rw.Write(json)
-}
diff --git a/api/main.go b/api/main.go
deleted file mode 100644
index c4645b8..0000000
--- a/api/main.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package api
-
-import (
- "fmt"
- "net/http"
-
- redqdb "sinanmohd.com/redq/db"
-)
-
-func Run(db *redqdb.SafeDB) {
- const prefix string = "POST /_redq/api"
-
- login := newLogin(db)
- http.Handle(prefix+"/ac/login", login)
- exampleApi := newExamplApiName(db)
- http.Handle(prefix+"/example", exampleApi)
-
- http.HandleFunc("GET /{$}", home)
- http.ListenAndServe(":8008", nil)
-}
-
-func home(rw http.ResponseWriter, r *http.Request) {
- const index string = `
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>🚨 redq</title>
- </head>
- <body>
- <center>
- <h1 style="font-size: 10em">
- redq is active
- </h1>
- <p style="font-weight: bold">
- we're soo back 🥳
- </p>
- </center>
- </body>
- </html>
- `
-
- fmt.Fprint(rw, index)
-}
diff --git a/api/utils.go b/api/utils.go
deleted file mode 100644
index 0fc7d35..0000000
--- a/api/utils.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package api
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "log"
- "net/http"
-)
-
-func unmarshal(r io.Reader, v any) error {
- body, err := io.ReadAll(r)
- if err != nil {
- return err
- }
-
- err = json.Unmarshal(body, v)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func handleError(err error, rw http.ResponseWriter, status int) {
- log.Println(err)
-
- rw.WriteHeader(status)
- json := fmt.Sprintf(`{"Error": "%v"}`, http.StatusText(status))
- rw.Write([]byte(json))
-}
diff --git a/cmd/bpf/bpf_bpfel.go b/bpf/bpf_bpfel.go
index 1efd705..f4ffb76 100644
--- a/cmd/bpf/bpf_bpfel.go
+++ b/bpf/bpf_bpfel.go
@@ -1,7 +1,7 @@
// Code generated by bpf2go; DO NOT EDIT.
//go:build 386 || amd64 || arm || arm64 || loong64 || mips64le || mipsle || ppc64le || riscv64
-package main
+package bpf
import (
"bytes"
diff --git a/cmd/bpf/bpf_bpfel.o b/bpf/bpf_bpfel.o
index 789c00f..789c00f 100644
--- a/cmd/bpf/bpf_bpfel.o
+++ b/bpf/bpf_bpfel.o
Binary files differ
diff --git a/cmd/bpf/bpf_usage.c b/bpf/bpf_usage.c
index 5e505da..5e505da 100644
--- a/cmd/bpf/bpf_usage.c
+++ b/bpf/bpf_usage.c
diff --git a/cmd/bpf/gen.go b/bpf/gen.go
index c90c0a7..ff585db 100644
--- a/cmd/bpf/gen.go
+++ b/bpf/gen.go
@@ -1,3 +1,3 @@
-package main
+package bpf
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel bpf bpf_usage.c
diff --git a/bpf/main.go b/bpf/main.go
new file mode 100644
index 0000000..47fdc41
--- /dev/null
+++ b/bpf/main.go
@@ -0,0 +1,124 @@
+package bpf
+
+import (
+ "errors"
+ "fmt"
+ "log"
+ "net"
+ "time"
+
+ "github.com/cilium/ebpf"
+ "github.com/cilium/ebpf/link"
+)
+
+type UsageStat struct {
+ lastSeen time.Time
+ lastDbPush time.Time
+ ingress uint64
+ egress uint64
+}
+type UsageMap map[uint32]UsageStat
+
+func Run(iface *net.Interface) {
+ usageMap := make(UsageMap)
+
+ objs := bpfObjects{}
+ if err := loadBpfObjects(&objs, nil); err != nil {
+ log.Fatalf("loading objects: %s", err)
+ }
+ defer objs.Close()
+
+ ingressLink, err := link.AttachTCX(link.TCXOptions{
+ Interface: iface.Index,
+ Program: objs.IngressFunc,
+ Attach: ebpf.AttachTCXIngress,
+ })
+ if err != nil {
+ log.Fatalf("could not attach TCx program: %s", err)
+ }
+ defer ingressLink.Close()
+
+ egressLink, err := link.AttachTCX(link.TCXOptions{
+ Interface: iface.Index,
+ Program: objs.EgressFunc,
+ Attach: ebpf.AttachTCXEgress,
+ })
+ if err != nil {
+ log.Fatalf("could not attach TCx program: %s", err)
+ }
+ defer egressLink.Close()
+
+ bpfTicker := time.NewTicker(1 * time.Second)
+ defer bpfTicker.Stop()
+ dbTicker := time.NewTicker(60 * time.Second)
+ defer dbTicker.Stop()
+ for {
+ select {
+ case <-bpfTicker.C:
+ usageMap.update(objs.IngressIp4UsageMap, objs.EgressIp4UsageMap)
+ case <-dbTicker.C:
+ continue;
+ }
+ }
+}
+
+func (usageMap UsageMap) update(ingress *ebpf.Map, egress *ebpf.Map) {
+ timeStart := time.Now()
+ batchKeys := make([]uint32, 4096)
+ batchValues := make([]uint64, 4096)
+ var key uint32
+
+ cursor := ebpf.MapBatchCursor{}
+ for {
+ _, err := ingress.BatchLookupAndDelete(&cursor, batchKeys, batchValues, nil)
+ for i := range batchKeys {
+ key = batchKeys[i]
+ usage, ok := usageMap[key]
+ if ok {
+ usage.ingress += batchValues[i]
+ usage.lastSeen = timeStart
+ usageMap[key] = usage;
+ } else {
+ usageMap[key] = UsageStat {
+ ingress: batchValues[i],
+ lastDbPush: timeStart,
+ lastSeen: timeStart,
+ }
+ }
+ }
+
+ if (errors.Is(err, ebpf.ErrKeyNotExist)) {
+ break;
+ } else if err != nil{
+ fmt.Println(err)
+ break
+ }
+ }
+
+ cursor = ebpf.MapBatchCursor{}
+ for {
+ _, err := egress.BatchLookupAndDelete(&cursor, batchKeys, batchValues, nil)
+ for i := range batchKeys {
+ key = batchKeys[i]
+ usage, ok := usageMap[key]
+ if ok {
+ usage.egress += batchValues[i]
+ usage.lastSeen = timeStart
+ usageMap[key] = usage;
+ } else {
+ usageMap[key] = UsageStat {
+ egress: batchValues[i],
+ lastDbPush: timeStart,
+ lastSeen: timeStart,
+ }
+ }
+ }
+
+ if (errors.Is(err, ebpf.ErrKeyNotExist)) {
+ break;
+ } else if err != nil{
+ fmt.Println(err)
+ break
+ }
+ }
+}
diff --git a/cmd/bpf/main.go b/cmd/bpf/main.go
deleted file mode 100644
index 5a5f842..0000000
--- a/cmd/bpf/main.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "net"
- "net/netip"
- "os"
- "time"
-
- "github.com/cilium/ebpf"
- "github.com/cilium/ebpf/link"
-)
-
-type Usage struct {
- ingress uint64
- egress uint64
-}
-
-func main() {
- if len(os.Args) < 2 {
- log.Fatalf("Please specify a network interface")
- }
-
- ifaceName := os.Args[1]
- iface, err := net.InterfaceByName(ifaceName)
- if err != nil {
- log.Fatalf("lookup network iface %q: %s", ifaceName, err)
- }
-
- // Load pre-compiled programs into the kernel.
- objs := bpfObjects{}
- if err := loadBpfObjects(&objs, nil); err != nil {
- log.Fatalf("loading objects: %s", err)
- }
- defer objs.Close()
-
- // Attach the program.
- ingressLink, err := link.AttachTCX(link.TCXOptions{
- Interface: iface.Index,
- Program: objs.IngressFunc,
- Attach: ebpf.AttachTCXIngress,
- })
- if err != nil {
- log.Fatalf("could not attach TCx program: %s", err)
- }
- defer ingressLink.Close()
-
- // Attach the program to Egress TC.
- egressLink, err := link.AttachTCX(link.TCXOptions{
- Interface: iface.Index,
- Program: objs.EgressFunc,
- Attach: ebpf.AttachTCXEgress,
- })
- if err != nil {
- log.Fatalf("could not attach TCx program: %s", err)
- }
- defer egressLink.Close()
-
- ticker := time.NewTicker(1 * time.Second)
- defer ticker.Stop()
- for range ticker.C {
- prettyPrint(objs.IngressIp4UsageMap, objs.EgressIp4UsageMap)
- }
-}
-
-func prettyPrint(ingress *ebpf.Map, egress *ebpf.Map) {
- ipUsage := make(map[netip.Addr]Usage)
- var key netip.Addr
- var value uint64
-
- iter := ingress.Iterate()
- for iter.Next(&key, &value) {
- ipUsage[key] = Usage {
- ingress: value,
- }
- }
-
- iter = egress.Iterate()
- for iter.Next(&key, &value) {
- usage, ok := ipUsage[key]
- if (ok) {
- usage.egress = value
- } else {
- usage = Usage { egress: value }
- }
-
- ipUsage[key] = usage
- }
-
- fmt.Print("\033[H\033[2J")
- fmt.Printf("%15s\t%16s\t%16s\n", "ip", "down", "up")
- for ip4, usage := range ipUsage {
- fmt.Printf("%15s\t%16d\t%16d\n", ip4, usage.ingress, usage.egress)
- }
-}
diff --git a/cmd/redq/main.go b/cmd/redq/main.go
index 1f153d3..d8b9b58 100644
--- a/cmd/redq/main.go
+++ b/cmd/redq/main.go
@@ -2,16 +2,16 @@ package main
import (
"log"
+ "net"
- redqapi "sinanmohd.com/redq/api"
- redqdb "sinanmohd.com/redq/db"
+ redqbpf "sinanmohd.com/redq/bpf"
)
func main() {
- db, err := redqdb.NewSafeDB()
- if err != nil {
- log.Fatal(err)
- }
+ iface, err := net.InterfaceByName("wlan0")
+ if err != nil {
+ log.Fatalf("lookup network: %s", err)
+ }
- redqapi.Run(db)
+ redqbpf.Run(iface)
}
diff --git a/cmd/redqctl/main.go b/cmd/redqctl/main.go
deleted file mode 100644
index ce77f77..0000000
--- a/cmd/redqctl/main.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package main
-
-import (
- "flag"
- "fmt"
- "log"
- "os"
-
- redqdb "sinanmohd.com/redq/db"
-)
-
-func help() {
- const helpString string =
-`redqctl is a tool for managing redq.
-
-Usage:
-
- redqctl <command> [arguments]
-
-The commands are:
-
- create create a redq account
- help show this help cruft
-
-`
-
- fmt.Print(helpString)
-}
-
-func create(args []string, db *redqdb.SafeDB) {
- f := flag.NewFlagSet("create", flag.ExitOnError)
- ac := &redqdb.Account{}
- ac.Info = &redqdb.Login{}
-
- f.StringVar(&ac.UserName, "username", "",
- "The username to associate with the account")
- f.StringVar(&ac.Info.FirstName, "fname", "",
- "The first name to associate with the account")
- f.StringVar(&ac.Info.LastName, "lname", "",
- "The last name to associate with the account")
- f.StringVar(&ac.Password, "pass", "",
- "The password to associate with the account")
- f.UintVar(&ac.Info.Level, "level", 0,
- "The level to associate with the account")
- f.Parse(args)
-
- err := ac.CreateAccount(db)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func main() {
- args := os.Args[1:]
- if len(args) == 0 {
- help()
- os.Exit(2)
- }
-
- db, err := redqdb.NewSafeDB()
- if err != nil {
- log.Fatal(err)
- }
-
- switch args[0] {
- case "help":
- help()
- case "create":
- create(args[1:], db)
- default:
- help()
- os.Exit(2)
- }
-}
diff --git a/db/account.go b/db/account.go
deleted file mode 100644
index 0668016..0000000
--- a/db/account.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package db
-
-import (
- "errors"
- "fmt"
- "log"
-)
-
-type Account struct {
- UserName string `validate:"required,alphanum,max=64"`
- Password string `json:",omitempty" validate:"required,min=10,max=128"`
-
- Info *Login
-}
-
-type Login struct {
- id uint
- Level uint `validate:"gte=0,lte=100"`
- FirstName, LastName string `validate:"required,alphanumunicode"`
- Bearer *Bearer
-}
-
-func (ac *Account) CreateAccount(safe *SafeDB) error {
- const sqlStatement string = `
- INSERT INTO Accounts (
- id,
- UserName,
- Password,
- Level,
- FirstName,
- LastName
- )
- VALUES (NULL, ?, ?, ?, ?, ?);
- `
-
- err := safe.validate.Struct(ac)
- if err != nil {
- return err
- }
-
- safe.mu.Lock()
- defer safe.mu.Unlock()
-
- _, err = safe.db.Exec(
- sqlStatement,
- ac.UserName,
- ToBlake3(ac.Password),
-
- ac.Info.FirstName,
- ac.Info.LastName,
- ac.Info.Level,
- )
-
- return err
-}
-
-func (ac *Account) Login(safe *SafeDB) error {
- const sqlStatementQuery string = `
- SELECT id, Password, Level, FirstName, LastName
- FROM Accounts
- WHERE Accounts.UserName = ?
- `
-
- err := safe.validate.Struct(ac)
- fmt.Println(ac.Password, ac.UserName)
- if err != nil {
- log.Println(err)
- return err
- }
-
- ac.Info = &Login{}
- ac.Info.Bearer = &Bearer{}
- safe.mu.Lock()
- row := safe.db.QueryRow(sqlStatementQuery, ac.UserName)
- safe.mu.Unlock()
-
- var Password string
- err = row.Scan(
- &ac.Info.id,
- &Password,
- &ac.Info.FirstName,
- &ac.Info.LastName,
- &ac.Info.Level,
- )
- if err != nil {
- return err
- }
- if Password != ToBlake3(ac.Password) {
- return errors.New("Auth failed")
- }
- ac.Password = ""
-
- err = ac.Info.Bearer.Generate(safe, ac.Info)
- if err != nil {
- return err
- }
-
- return err
-}
-
-func (ac *Account) fromBearer(safe *SafeDB, b *Bearer) error {
- const sqlStatementAccount string = `
- SELECT UserName, Password, Level, FirstName, LastName
- FROM Accounts
- WHERE Accounts.id = ?
- `
-
- safe.mu.Lock()
- row := safe.db.QueryRow(sqlStatementAccount, b.accountId)
- safe.mu.Unlock()
-
- ac.Info = &Login{}
- ac.Info.id = b.accountId
- ac.Info.Bearer = b
- err := row.Scan(
- &ac.UserName,
- &ac.Password,
-
- &ac.Info.FirstName,
- &ac.Info.LastName,
- &ac.Info.Level,
- )
- if err != nil {
- return err
- }
- ac.Info.Bearer = b
-
- return err
-}
diff --git a/db/bearer.go b/db/bearer.go
deleted file mode 100644
index b16d506..0000000
--- a/db/bearer.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package db
-
-import (
- "errors"
- "time"
-
- _ "github.com/mattn/go-sqlite3"
-)
-
-type Bearer struct {
- id, accountId uint
- Token string
- ValidUpTo time.Time
-}
-
-func (b *Bearer) FromToken(safe *SafeDB, Token string) error {
- const sqlStatementBearer string = `
- SELECT id, ValidUpTo, accountId
- FROM Bearer
- WHERE Bearer.Token = ?
- `
-
- b.Token = Token
- var ValidUpToString string
- safe.mu.Lock()
- row := safe.db.QueryRow(sqlStatementBearer, Token)
- safe.mu.Unlock()
-
- err := row.Scan(
- &b.id,
- &ValidUpToString,
- &b.accountId,
- )
- if err != nil {
- return err
- }
-
- layout := "2006-01-02 15:04:05.999999999-07:00"
- b.ValidUpTo, err = time.Parse(layout, ValidUpToString)
- if err != nil {
- return err
- }
-
- timeNow := time.Now()
- if timeNow.After(b.ValidUpTo) {
- return errors.New("Outdated Bearer Token")
- }
-
- return err
-}
-
-func (b *Bearer) Update(safe *SafeDB) error {
- const sqlStatementBearer string = `
- UPDATE Bearer
- SET ValidUpTo = ?
- WHERE id = ?
- `
-
- validUpTo := time.Now().Add(time.Hour * 24)
- safe.mu.Lock()
- _, err := safe.db.Exec(sqlStatementBearer, validUpTo, b.id)
- safe.mu.Unlock()
- if err != nil {
- return err
- }
- b.ValidUpTo = validUpTo
-
- return nil
-}
-
-func (b *Bearer) VerifyAndUpdate(safe *SafeDB, token string) error {
- err := b.FromToken(safe, token)
- if err != nil {
- return err
- }
-
- err = b.Update(safe)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (b *Bearer) Generate(safe *SafeDB, lg *Login) error {
- const sqlGenBearer string = `
- INSERT INTO Bearer (
- id,
- Token,
- ValidUpTo,
- accountId
- )
- VALUES (NULL, ?, ?, ?);
- `
-
- Token, err := GenRandomString(128)
- if err != nil {
- return err
- }
-
- timeNow := time.Now()
- ValidUpTo := timeNow.Add(time.Hour * 24)
- safe.mu.Lock()
- res, err := safe.db.Exec(
- sqlGenBearer,
- Token,
- ValidUpTo,
- lg.id,
- )
- safe.mu.Unlock()
- if err != nil {
- return err
- }
-
- id, err := res.LastInsertId()
- if err != nil {
- return err
- }
-
- b.id = uint(id)
- b.accountId = lg.id
- b.Token = Token
- b.ValidUpTo = ValidUpTo
- lg.Bearer = b
-
- return err
-}
diff --git a/db/db.go b/db/db.go
new file mode 100644
index 0000000..5b8c8f5
--- /dev/null
+++ b/db/db.go
@@ -0,0 +1,32 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+// sqlc v1.26.0
+
+package db
+
+import (
+ "context"
+
+ "github.com/jackc/pgx/v5"
+ "github.com/jackc/pgx/v5/pgconn"
+)
+
+type DBTX interface {
+ Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
+ Query(context.Context, string, ...interface{}) (pgx.Rows, error)
+ QueryRow(context.Context, string, ...interface{}) pgx.Row
+}
+
+func New(db DBTX) *Queries {
+ return &Queries{db: db}
+}
+
+type Queries struct {
+ db DBTX
+}
+
+func (q *Queries) WithTx(tx pgx.Tx) *Queries {
+ return &Queries{
+ db: tx,
+ }
+}
diff --git a/db/main.go b/db/main.go
deleted file mode 100644
index 49658cd..0000000
--- a/db/main.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package db
-
-import (
- "database/sql"
- "os"
- "path/filepath"
- "sync"
-
- "github.com/go-playground/validator/v10"
- _ "github.com/mattn/go-sqlite3"
-)
-
-type SafeDB struct {
- mu sync.Mutex
- validate *validator.Validate
-
- path string
- db *sql.DB
-}
-
-func (safe *SafeDB) setupPath() error {
- const path string = "/var/lib/redq/"
- const name string = "redq.sqlite3"
-
- err := os.MkdirAll(path, os.ModeDir)
- if err != nil {
- return err
- }
-
- safe.path = filepath.Join(path, name)
- return nil
-}
-
-func NewSafeDB() (*SafeDB, error) {
- const create string = `
- CREATE TABLE IF NOT EXISTS Accounts(
- id INTEGER PRIMARY KEY,
- UserName CHAR(64) NOT NULL UNIQUE,
- Password CHAR(128) NOT NULL,
-
- Level INTEGER NOT NULL,
- FirstName CHAR(32) NOT NULL,
- LastName CHAR(32) NOT NULL
- );
-
- CREATE TABLE IF NOT EXISTS Bearer(
- id INTEGER PRIMARY KEY,
- Token CHAR(128) NOT NULL UNIQUE,
- ValidUpTo TIME NOT NULL,
- accountId INTEGER NOT NULL,
-
- FOREIGN KEY (accountId)
- REFERENCES Accounts (id)
- );
- `
- safe := &SafeDB{}
- err := safe.setupPath()
- if err != nil {
- return nil, err
- }
-
- safe.mu.Lock()
- defer safe.mu.Unlock()
-
- safe.db, err = sql.Open("sqlite3", safe.path)
- if err != nil {
- return nil, err
- }
-
- _, err = safe.db.Exec(create)
- if err != nil {
- return nil, err
- }
-
- safe.validate = validator.New(validator.WithRequiredStructEnabled())
- return safe, nil
-}
diff --git a/db/models.go b/db/models.go
new file mode 100644
index 0000000..83e4051
--- /dev/null
+++ b/db/models.go
@@ -0,0 +1,17 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+// sqlc v1.26.0
+
+package db
+
+import (
+ "github.com/jackc/pgx/v5/pgtype"
+)
+
+type Usage struct {
+ Hardwareaddr int32
+ Starttime pgtype.Timestamp
+ Stoptime pgtype.Timestamp
+ Egress int32
+ Ingress int32
+}
diff --git a/db/query.sql b/db/query.sql
new file mode 100644
index 0000000..75d5b61
--- /dev/null
+++ b/db/query.sql
@@ -0,0 +1,6 @@
+-- name: EnterUsage :exec
+INSERT INTO Usage (
+ HardwareAddr, StartTime, StopTime, Egress, Ingress
+) VALUES (
+ $1, $2, $3, $4, $5
+);
diff --git a/db/query.sql.go b/db/query.sql.go
new file mode 100644
index 0000000..de68384
--- /dev/null
+++ b/db/query.sql.go
@@ -0,0 +1,39 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+// sqlc v1.26.0
+// source: query.sql
+
+package db
+
+import (
+ "context"
+
+ "github.com/jackc/pgx/v5/pgtype"
+)
+
+const enterUsage = `-- name: EnterUsage :exec
+INSERT INTO Usage (
+ HardwareAddr, StartTime, StopTime, Egress, Ingress
+) VALUES (
+ $1, $2, $3, $4, $5
+)
+`
+
+type EnterUsageParams struct {
+ Hardwareaddr int32
+ Starttime pgtype.Timestamp
+ Stoptime pgtype.Timestamp
+ Egress int32
+ Ingress int32
+}
+
+func (q *Queries) EnterUsage(ctx context.Context, arg EnterUsageParams) error {
+ _, err := q.db.Exec(ctx, enterUsage,
+ arg.Hardwareaddr,
+ arg.Starttime,
+ arg.Stoptime,
+ arg.Egress,
+ arg.Ingress,
+ )
+ return err
+}
diff --git a/db/schema.sql b/db/schema.sql
new file mode 100644
index 0000000..b8f8540
--- /dev/null
+++ b/db/schema.sql
@@ -0,0 +1,7 @@
+CREATE TABLE Usage (
+ HardwareAddr INTEGER NOT NULL,
+ StartTime TIMESTAMP NOT NULL,
+ StopTime TIMESTAMP NOT NULL,
+ Egress INTEGER NOT NULL,
+ Ingress INTEGER NOT NULL
+);
diff --git a/db/sqlc.yaml b/db/sqlc.yaml
new file mode 100644
index 0000000..0cd3357
--- /dev/null
+++ b/db/sqlc.yaml
@@ -0,0 +1,10 @@
+version: "2"
+sql:
+ - engine: "postgresql"
+ queries: "query.sql"
+ schema: "schema.sql"
+ gen:
+ go:
+ package: "db"
+ out: "./"
+ sql_package: "pgx/v5"
diff --git a/db/utils.go b/db/utils.go
deleted file mode 100644
index 0b0f1cb..0000000
--- a/db/utils.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package db
-
-import (
- "encoding/base64"
- "lukechampine.com/blake3"
- "math/rand"
-)
-
-func ToBlake3(pass string) string {
- hash := blake3.Sum512([]byte(pass))
- hash64b := base64.StdEncoding.EncodeToString(hash[:])
-
- return "blake3-" + hash64b
-}
-
-func GenRandomString(n int) (string, error) {
- b := make([]byte, n)
- _, err := rand.Read(b)
- if err != nil {
- return "", err
- }
-
- return base64.URLEncoding.EncodeToString(b)[:n], nil
-}
diff --git a/flake.nix b/flake.nix
index 115172a..c100e82 100644
--- a/flake.nix
+++ b/flake.nix
@@ -21,7 +21,7 @@
gopls
jq
- sqlite
+ sqlc
libbpf
ccls
diff --git a/go.mod b/go.mod
index 9d0ee8c..84638f1 100644
--- a/go.mod
+++ b/go.mod
@@ -4,20 +4,16 @@ go 1.22.0
require (
github.com/cilium/ebpf v0.15.0
- github.com/go-playground/validator/v10 v10.19.0
- github.com/mattn/go-sqlite3 v1.14.22
- lukechampine.com/blake3 v1.2.1
+ github.com/jackc/pgx/v5 v5.6.0
+ golang.org/x/net v0.10.0
)
require (
- github.com/gabriel-vasile/mimetype v1.4.3 // indirect
- github.com/go-playground/locales v0.14.1 // indirect
- github.com/go-playground/universal-translator v0.18.1 // indirect
- github.com/klauspost/cpuid/v2 v2.2.4 // indirect
- github.com/leodido/go-urn v1.4.0 // indirect
+ github.com/jackc/pgpassfile v1.0.0 // indirect
+ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
+ github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
- golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
diff --git a/go.sum b/go.sum
index ca6b136..5d343e8 100644
--- a/go.sum
+++ b/go.sum
@@ -1,49 +1,46 @@
github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk=
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
-github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
-github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
-github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
-github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
-github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
-github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
-github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
+github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
-github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
-github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
-golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
-lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=