Start the Go rewrite: jsjson, awg-ctrl port, differential bench
- internal/jsjson: JSON.stringify-compatible encoder and order-preserving decoder, tested against fixtures produced by Node itself - internal/ctrl: awg-ctrl in Go (params, vpn:// keys, users, peers, sync, 3.1 upgrade, CAKE shaping, metrics, monitor job, Express-compatible HTTP layer) - internal/iauth, internal/logx: internal Ed25519 tokens and logging - tools/diffbench: Docker bench with stubbed awg/ip/tc/nft that runs one scenario against the TS and Go implementations for comparison
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
package ctrl
|
||||
|
||||
import (
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/maeneko/forgetting/internal/jsjson"
|
||||
)
|
||||
|
||||
var reOwner = regexp.MustCompile(`^[\w/.-]{0,64}$`)
|
||||
|
||||
// checkPubKeyAny — checkPubKey для значения из JSON (не строка → тот же 400).
|
||||
func checkPubKeyAny(v any) (string, error) {
|
||||
k, ok := v.(string)
|
||||
if !ok {
|
||||
return "", httpErr(400, "Неверный публичный ключ")
|
||||
}
|
||||
return checkPubKey(k)
|
||||
}
|
||||
|
||||
func checkPubKeys(arr []any) ([]string, error) {
|
||||
out := make([]string, 0, len(arr))
|
||||
for _, v := range arr {
|
||||
k, err := checkPubKeyAny(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, k)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// jsToNumber — Number(v) для значений из JSON.
|
||||
func jsToNumber(v any) float64 {
|
||||
switch x := v.(type) {
|
||||
case nil:
|
||||
return 0
|
||||
case float64:
|
||||
return x
|
||||
case bool:
|
||||
if x {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case string:
|
||||
return jsNumber(x)
|
||||
}
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
func (s *Server) knownPubKeys() (map[string]bool, error) {
|
||||
known := map[string]bool{}
|
||||
rows, err := s.db.Query("SELECT pub_key FROM users")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var k string
|
||||
rows.Scan(&k)
|
||||
known[k] = true
|
||||
}
|
||||
rows.Close()
|
||||
peers, err := s.peersAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range peers {
|
||||
known[p.PubKey] = true
|
||||
}
|
||||
return known, nil
|
||||
}
|
||||
|
||||
func (s *Server) isKnownPub(k string) (bool, error) {
|
||||
if p, err := s.peerGet(k); err != nil || p != nil {
|
||||
return p != nil, err
|
||||
}
|
||||
var n int
|
||||
if err := s.db.QueryRow("SELECT COUNT(*) FROM users WHERE pub_key = ?", k).Scan(&n); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return n > 0, nil
|
||||
}
|
||||
|
||||
// profileAwg — параметры для /api/profile в порядке CONFIG.awgParams (порядок объявления в
|
||||
// DEFAULT_AWG_PARAMS), без пустых значений; числа — строками.
|
||||
func profileAwg(p Params) jsjson.Object {
|
||||
o := jsjson.Object{}
|
||||
add := func(k, v string) {
|
||||
if v != "" {
|
||||
o = append(o, jsjson.KV{Key: k, Val: v})
|
||||
}
|
||||
}
|
||||
itoa := strconv.Itoa
|
||||
add("Jc", itoa(p.Jc))
|
||||
add("Jmin", itoa(p.Jmin))
|
||||
add("Jmax", itoa(p.Jmax))
|
||||
add("S1", itoa(p.S1))
|
||||
add("S2", itoa(p.S2))
|
||||
add("S3", itoa(p.S3))
|
||||
add("S4", itoa(p.S4))
|
||||
add("H1", p.H1)
|
||||
add("H2", p.H2)
|
||||
add("H3", p.H3)
|
||||
add("H4", p.H4)
|
||||
add("I1", p.I1)
|
||||
add("I2", p.I2)
|
||||
add("I3", p.I3)
|
||||
add("I4", p.I4)
|
||||
add("I5", p.I5)
|
||||
for _, k := range AWG3Keys {
|
||||
add(k, p.A3[k])
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
Reference in New Issue
Block a user