Skip to content

Commit

Permalink
uaid, part 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
schwarzlichtbezirk committed Feb 28, 2023
1 parent 565167e commit 729534b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 63 deletions.
17 changes: 10 additions & 7 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type CfgJWTAuth struct {
AccessKey string `json:"access-key" yaml:"access-key"`
// Key for refresh HS-256 JWT-tokens.
RefreshKey string `json:"refresh-key" yaml:"refresh-key"`
// Key to calculate user agent ID by xxhash algorithm.
UaidHmacKey string `json:"uaid-hmac-key" yaml:"uaid-hmac-key"`
}

// CfgWebServ is web server settings.
Expand All @@ -55,6 +57,8 @@ type CfgWebServ struct {
WriteTimeout time.Duration `json:"write-timeout" yaml:"write-timeout" long:"wt" description:"Maximum duration before timing out writes of the response."`
IdleTimeout time.Duration `json:"idle-timeout" yaml:"idle-timeout" long:"it" description:"Maximum amount of time to wait for the next request when keep-alives are enabled."`
MaxHeaderBytes int `json:"max-header-bytes" yaml:"max-header-bytes" long:"mhb" description:"Controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line, in bytes."`
// Maximum duration between two ajax-calls to think client is online.
OnlineTimeout time.Duration `json:"online-timeout" yaml:"online-timeout" long:"ot" description:"Maximum duration between two ajax-calls to think client is online."`
// Maximum duration to wait for graceful shutdown.
ShutdownTimeout time.Duration `json:"shutdown-timeout" yaml:"shutdown-timeout" long:"st" description:"Maximum duration to wait for graceful shutdown."`
}
Expand Down Expand Up @@ -83,8 +87,6 @@ type CfgAppSets struct {
WPKName []string `json:"wpk-name" yaml:"wpk-name,flow" long:"wpk" description:"Name of wpk-file with program resources."`
// Memory mapping technology for WPK, or load into one solid byte slice otherwise.
WPKmmap bool `json:"wpk-mmap" yaml:"wpk-mmap" long:"mmap" description:"Memory mapping technology for WPK, or load into one solid byte slice otherwise."`
// Maximum duration between two ajax-calls to think client is online.
OnlineTimeout time.Duration `json:"online-timeout" yaml:"online-timeout" long:"ot" description:"Maximum duration between two ajax-calls to think client is online."`
// Maximum number of cached embedded thumbnails.
ThumbCacheMaxNum int `json:"thumb-cache-maxnum" yaml:"thumb-cache-maxnum" long:"pcmn" description:"Maximum number of cached embedded thumbnails."`
// Maximum number of converted media files at memory cache.
Expand All @@ -110,10 +112,11 @@ type Config struct {
// Instance of common service settings.
var cfg = Config{ // inits default values:
CfgJWTAuth: CfgJWTAuth{
AccessTTL: 1 * 24 * time.Hour,
RefreshTTL: 3 * 24 * time.Hour,
AccessKey: "skJgM4NsbP3fs4k7vh0gfdkgGl8dJTszdLxZ1sQ9ksFnxbgvw2RsGH8xxddUV479",
RefreshKey: "zxK4dUnuq3Lhd1Gzhpr3usI5lAzgvy2t3fmxld2spzz7a5nfv0hsksm9cheyutie",
AccessTTL: 1 * 24 * time.Hour,
RefreshTTL: 3 * 24 * time.Hour,
AccessKey: "skJgM4NsbP3fs4k7vh0gfdkgGl8dJTszdLxZ1sQ9ksFnxbgvw2RsGH8xxddUV479",
RefreshKey: "zxK4dUnuq3Lhd1Gzhpr3usI5lAzgvy2t3fmxld2spzz7a5nfv0hsksm9cheyutie",
UaidHmacKey: "hms-ua",
},
CfgWebServ: CfgWebServ{
AutoCert: false,
Expand All @@ -124,6 +127,7 @@ var cfg = Config{ // inits default values:
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
MaxHeaderBytes: 1 << 20,
OnlineTimeout: 3 * 60 * time.Second,
ShutdownTimeout: 15 * time.Second,
},
CfgImgProp: CfgImgProp{
Expand All @@ -137,7 +141,6 @@ var cfg = Config{ // inits default values:
CfgAppSets: CfgAppSets{
WPKName: []string{"hms-full.wpk"},
WPKmmap: false,
OnlineTimeout: 3 * 60 * time.Second,
ThumbCacheMaxNum: 16 * 1024,
MediaCacheMaxNum: 64,
HdCacheMaxNum: 256,
Expand Down
6 changes: 4 additions & 2 deletions config/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ authentication:
access-key: skJgM4NsbP3fs4k7vh0gfdkgGl8dJTszdLxZ1sQ9ksFnxbgvw2RsGH8xxddUV479
# Key for refresh HS-256 JWT-tokens.
refresh-key: zxK4dUnuq3Lhd1Gzhpr3usI5lAzgvy2t3fmxld2spzz7a5nfv0hsksm9cheyutie
# Key to calculate user agent ID by xxhash algorithm.
uaid-hmac-key: hms-ua
web-server: # See https://golang.org/pkg/net/http/#Server for details.
# Indicates to get TLS-certificate from letsencrypt.org service
# if this value is true. Uses local TLS-certificate otherwise.
Expand All @@ -37,6 +39,8 @@ web-server: # See https://golang.org/pkg/net/http/#Server for details.
# Controls the maximum number of bytes the server will read parsing
# the request header's keys and values, including the request line, in bytes.
max-header-bytes: 1048576 # 1M
# Maximum duration between two ajax-calls to think client is online.
online-timeout: 180s # 3 minutes
# Maximum duration to wait for graceful shutdown.
shutdown-timeout: 15s
images-prop:
Expand All @@ -61,8 +65,6 @@ specification:
# On 'true' use memory mapping technology for access to wpk-package nested files.
# On 'false' use wpk-package loaded into one solid byte slice.
wpk-mmap: false
# Maximum duration between two ajax-calls to think client is online.
online-timeout: 180s # 3 minutes
# Maximum number of cached embedded thumbnails.
thumb-cache-maxnum: 16384
# Maximum number of converted media files at memory cache.
Expand Down
16 changes: 7 additions & 9 deletions folder.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,13 @@ func folderAPI(w http.ResponseWriter, r *http.Request, aid, uid ID_t) {

var latency = time.Since(t)
Log.Infof("id%d: navigate to %s, items %d, timeout %s", acc.ID, syspath, len(ret.List), latency)
if uaid, err := GetUAID(r); err == nil {
go xormUserlog.InsertOne(&OpenStore{
UAID: uaid,
AID: aid,
UID: uid,
Path: syspath,
Latency: int(latency / time.Millisecond),
})
}
go xormUserlog.InsertOne(&OpenStore{
UAID: RequestUAID(r),
AID: aid,
UID: uid,
Path: syspath,
Latency: int(latency / time.Millisecond),
})

WriteOK(w, r, &ret)
}
Expand Down
48 changes: 21 additions & 27 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,13 @@ func fileHandler(w http.ResponseWriter, r *http.Request, aid, uid ID_t) {

if HasRangeBegin(r) { // beginning of content
Log.Infof("id%d: media-hd %s", acc.ID, path.Base(syspath))
if uaid, err := GetUAID(r); err == nil {
go xormUserlog.InsertOne(&OpenStore{
UAID: uaid,
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}
go xormUserlog.InsertOne(&OpenStore{
UAID: RequestUAID(r),
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}
w.Header().Set("Content-Type", MimeStr[md.Mime])
http.ServeContent(w, r, syspath, starttime, bytes.NewReader(md.Data))
Expand All @@ -147,15 +145,13 @@ func fileHandler(w http.ResponseWriter, r *http.Request, aid, uid ID_t) {

if HasRangeBegin(r) { // beginning of content
Log.Infof("id%d: media %s", acc.ID, path.Base(syspath))
if uaid, err := GetUAID(r); err == nil {
go xormUserlog.InsertOne(&OpenStore{
UAID: uaid,
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}
go xormUserlog.InsertOne(&OpenStore{
UAID: RequestUAID(r),
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}
w.Header().Set("Content-Type", MimeStr[md.Mime])
http.ServeContent(w, r, syspath, starttime, bytes.NewReader(md.Data))
Expand All @@ -165,15 +161,13 @@ func fileHandler(w http.ResponseWriter, r *http.Request, aid, uid ID_t) {

if HasRangeBegin(r) { // beginning of content
Log.Infof("id%d: serve %s", acc.ID, path.Base(syspath))
if uaid, err := GetUAID(r); err == nil {
go xormUserlog.InsertOne(&OpenStore{
UAID: uaid,
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}
go xormUserlog.InsertOne(&OpenStore{
UAID: RequestUAID(r),
AID: aid,
UID: uid,
Path: syspath,
Latency: -1,
})
}

var content io.ReadSeekCloser
Expand Down
20 changes: 9 additions & 11 deletions routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,8 @@ func AjaxMiddleware(next http.Handler) http.Handler {
isold, isnew bool
)

var ast = &AgentStore{
Addr: StripPort(r.RemoteAddr),
UA: r.UserAgent(),
}
uanew = ID_t(ast.Hash())
var addr, ua = StripPort(r.RemoteAddr), r.UserAgent()
uanew = CalcUAID(addr, ua)

// UAID at cookie
if uaold, _ = GetUAID(r); uaold == 0 {
Expand All @@ -532,12 +529,13 @@ func AjaxMiddleware(next http.Handler) http.Handler {
}
UaMap[uanew] = cid
go func() {
ast.CID = cid
ast.UAID = uanew
if lang, ok := r.Header["Accept-Language"]; ok {
ast.Lang = lang[0]
}
if _, err := xormUserlog.InsertOne(ast); err != nil {
if _, err := xormUserlog.InsertOne(&AgentStore{
UAID: uanew,
CID: cid,
Addr: addr,
UA: ua,
Lang: r.Header.Get("Accept-Language"),
}); err != nil {
panic(err.Error())
}
}()
Expand Down
20 changes: 13 additions & 7 deletions users.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

var xormUserlog *xorm.Engine

// AgentStore is storage record with user agent string and user host address.
type AgentStore struct {
UAID ID_t `xorm:"unique"` // user agent ID
CID ID_t // client ID
Expand All @@ -24,6 +25,7 @@ type AgentStore struct {
Time Time `xorm:"created"`
}

// OpenStore is storage record with some opened file or opened folder.
type OpenStore struct {
UAID ID_t // client ID
AID ID_t `xorm:"default 0"` // access profile ID
Expand All @@ -44,14 +46,18 @@ var (
uamux sync.Mutex
)

const ua_salt = "hms"

func (ast *AgentStore) Hash() uint64 {
// CalcUAID calculate user agent ID by xxhash from given strings.
func CalcUAID(addr, ua string) ID_t {
var h = xxhash.New()
h.Write(s2b(ua_salt))
h.Write(s2b(ast.Addr))
h.Write(s2b(ast.UA))
return h.Sum64() & 0x7fff_ffff_ffff_ffff
h.Write(s2b(cfg.UaidHmacKey))
h.Write(s2b(addr))
h.Write(s2b(ua))
return ID_t(h.Sum64() & 0x7fff_ffff_ffff_ffff) // clear highest bit for xorm compatibility
}

// RequestUAID calculate user agent ID from given request.
func RequestUAID(r *http.Request) ID_t {
return CalcUAID(StripPort(r.RemoteAddr), r.UserAgent())
}

// InitUserlog inits database user log engine.
Expand Down

0 comments on commit 729534b

Please sign in to comment.