Package Archives:

- fix security arbitrary path
- fix linter

Package AWS:
- implement resolver v2

Package Cobra:
- fix linter

Package Config/component:
- fix linter

Package Context/Config:
- Add function to set context

Package Database/KV...:
- Fix error
- Fix collision pointer
- Fix models
- Fix circular dependencies
- Add function Delete on driver, table and item
- Add function new on drvier to prevent collision data when create item on table get / walk

Package Duration:
- Add type Duration based on time.Duration to allow transform duration to string instead of int64 nanosecond
- Add function to parse in json, yaml, toml, text, cbor
- Add function to allow convert type into mapstructure (spf13 viper, cobra...)

Package File/Perm:
- Add type Perm based on os.FileMode to allow marshall / unmashall it into octal form instead of string representation (-rwxrwxrwx)
- Add function to marshall / unmarshall in json, yaml, toml, text, cbor
- Add function to allow convert type into mapstructure (spf13 viper, cobra...)

Package File/progress:
- Fix linter

Package HTTPServer :
- Fix linter
- Fix security by adding a default value if not set on config

Package ioutils:
- Fix Linter

Package LDAP:
- Add Clone function

Package logger/hookfile:
- Fix linter

Package nats:
- Fix linter

Package Network/Protocol:
- Fix bug with quote / Dbl Quote on unmarshall

Package Password:
- Replace password with crypto rand instead of math rand

Package Size:
- Fix potential overflow
- Add function to format value into Int32, Int, Uint32, Uint, Float32
- Add function to parse Float64 into type Size

Package Socket:
- change config uint32 to golib Size, time.Duration to golib Duration
- add TLS managment to server TCP, discard for UDP & Unix file Local Domain
- add function Info Server to print information of server when listen is starting
This commit is contained in:
Nicolas JUHEL
2023-11-16 10:07:16 +01:00
committed by nabbar
parent b07fafb2f2
commit 97e70d063f
69 changed files with 1643 additions and 445 deletions

View File

@@ -96,17 +96,17 @@ jobs:
continue-on-error: false
run: |
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|')
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 GOAMD64=v4 go build -a -v -race -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 GOAMD64=v4 go build -a -race -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
- name: Test Build Windows/amd64 with CGO
continue-on-error: false
run: |
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|')
CC=/usr/bin/x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOAMD64=v4 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CC=/usr/bin/x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOAMD64=v4 go build -a -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
- name: Test Build Darwin/arm64 with suffix/CGO
continue-on-error: false
run: |
IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|')
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOAMD64=v1 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOAMD64=v1 go build -a -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1})

View File

@@ -41,9 +41,10 @@ func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error {
r := bzip2.NewReader(src)
//nolint #nosec
/* #nosec */
if _, e := io.Copy(dst, r); e != nil {
// #nosec
_, e := io.Copy(dst, r)
if e != nil {
return ErrorIOCopy.Error(e)
} else if _, e = dst.Seek(0, io.SeekStart); e != nil {
return ErrorFileSeek.Error(e)

View File

@@ -29,9 +29,8 @@ import (
gz "compress/gzip"
"io"
libfpg "github.com/nabbar/golib/file/progress"
"github.com/nabbar/golib/errors"
libfpg "github.com/nabbar/golib/file/progress"
)
func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error {
@@ -50,9 +49,10 @@ func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error {
_ = r.Close()
}()
//nolint #nosec
/* #nosec */
if _, e = io.Copy(dst, r); e != nil {
// #nosec
_, e = io.Copy(dst, r)
if e != nil {
return ErrorIOCopy.Error(e)
} else if _, e = dst.Seek(0, io.SeekStart); e != nil {
return ErrorFileSeek.Error(e)
@@ -88,6 +88,7 @@ func GetGunZipSize(src io.ReadSeeker) int64 {
}
var n int64
// #nosec
n, e = io.Copy(io.Discard, r)
if e != nil {

View File

@@ -33,10 +33,9 @@ import (
"runtime"
"strings"
libfpg "github.com/nabbar/golib/file/progress"
libarc "github.com/nabbar/golib/archive/archive"
liberr "github.com/nabbar/golib/errors"
libfpg "github.com/nabbar/golib/file/progress"
)
func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error {
@@ -93,9 +92,11 @@ func GetAll(src io.ReadSeeker, outputFolder string, defaultDirPerm os.FileMode)
return ErrorTarNext.Error(e)
}
dst := filepath.Join(outputFolder, libarc.CleanPath(strings.Replace(h.Name, ".."+string(filepath.Separator), "", -1)))
//nolint #nosec
/* #nosec */
if err := writeContent(r, h, filepath.Join(outputFolder, libarc.CleanPath(h.Name)), defaultDirPerm); err != nil {
if err := writeContent(r, h, dst, defaultDirPerm); err != nil {
return err
}
}

View File

@@ -30,11 +30,11 @@ import (
"io"
"os"
"path/filepath"
libfpg "github.com/nabbar/golib/file/progress"
"strings"
arcmod "github.com/nabbar/golib/archive/archive"
liberr "github.com/nabbar/golib/errors"
libfpg "github.com/nabbar/golib/file/progress"
)
func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error {
@@ -119,9 +119,10 @@ func GetAll(src libfpg.Progress, outputFolder string, defaultDirPerm os.FileMode
continue
}
//nolint #nosec
/* #nosec */
if err := writeContent(f, filepath.Join(outputFolder, arcmod.CleanPath(f.Name)), defaultDirPerm); err != nil {
dst := filepath.Join(outputFolder, arcmod.CleanPath(strings.Replace(f.Name, ".."+string(filepath.Separator), "..", -1)))
// #nosec
if err := writeContent(f, dst, defaultDirPerm); err != nil {
return err
}
}
@@ -175,9 +176,10 @@ func writeContent(f *zip.File, out string, defaultDirPerm os.FileMode) (err libe
return ErrorZipFileOpen.Error(e)
}
//nolint #nosec
/* #nosec */
if _, e = io.Copy(dst, r); e != nil {
// #nosec
_, e = io.Copy(dst, r)
if e != nil {
return ErrorIOCopy.Error(e)
} else if e = dst.Close(); e != nil {
return ErrorFileClose.Error(e)

View File

@@ -28,6 +28,7 @@ package bucket
import (
"fmt"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
sdksss "github.com/aws/aws-sdk-go-v2/service/s3"
sdkstp "github.com/aws/aws-sdk-go-v2/service/s3/types"
libhlp "github.com/nabbar/golib/aws/helper"
@@ -64,10 +65,12 @@ func (cli *client) _create(RegionConstraint string, lockEnable bool) error {
if RegionConstraint != "" {
in.CreateBucketConfiguration.LocationConstraint = sdkstp.BucketLocationConstraint(RegionConstraint)
} else {
in.CreateBucketConfiguration.LocationConstraint = sdkstp.BucketLocationConstraint(cli.GetRegion())
}
if lockEnable {
in.ObjectLockEnabledForBucket = true
in.ObjectLockEnabledForBucket = sdkaws.Bool(true)
}
out, err := cli.s3.CreateBucket(cli.GetContext(), in)

View File

@@ -118,11 +118,13 @@ func (c *client) _NewClientIAM(ctx context.Context, httpClient *http.Client) (*s
EndpointOptions: sdkiam.EndpointResolverOptions{
DisableHTTPS: !c.c.IsHTTPs(),
},
EndpointResolver: c._NewIAMResolver(cfg),
HTTPSignerV4: sig,
Region: cfg.Region,
Retryer: ret,
HTTPClient: httpClient,
BaseEndpoint: sdkaws.String(c.c.GetEndpoint().String()),
EndpointResolver: c._NewIAMResolver(cfg),
EndpointResolverV2: c._NewIAMResolverV2(c.c),
HTTPSignerV4: sig,
Region: cfg.Region,
Retryer: ret,
HTTPClient: httpClient,
})
return iam, nil
@@ -161,12 +163,14 @@ func (c *client) _NewClientS3(ctx context.Context, httpClient *http.Client) (*sd
EndpointOptions: sdksss.EndpointResolverOptions{
DisableHTTPS: !c.c.IsHTTPs(),
},
EndpointResolver: c._NewS3Resolver(cfg),
HTTPSignerV4: sig,
Region: cfg.Region,
Retryer: ret,
HTTPClient: httpClient,
UsePathStyle: c.p,
BaseEndpoint: sdkaws.String(c.c.GetEndpoint().String()),
EndpointResolver: c._NewS3Resolver(cfg),
EndpointResolverV2: c._NewS3ResolverV2(c.c),
HTTPSignerV4: sig,
Region: cfg.Region,
Retryer: ret,
HTTPClient: httpClient,
UsePathStyle: c.p,
})
return sss, nil

View File

@@ -65,7 +65,7 @@ func (m *mpu) Copy(fromBucket, fromObject, fromVersionId string) error {
Bucket: sdkaws.String(bck),
CopySource: sdkaws.String(src),
Key: sdkaws.String(obj),
PartNumber: m.Counter() + 1,
PartNumber: sdkaws.Int32(m.Counter() + 1),
UploadId: sdkaws.String(mid),
CopySourceRange: sdkaws.String("bytes=" + p),
RequestPayer: sdktyp.RequestPayerRequester,
@@ -121,7 +121,9 @@ func (m *mpu) getCopyPart(fromBucket, fromObject, fromVersionId string) []string
return res
} else if hdo == nil || hdo.ETag == nil || len(*hdo.ETag) < 1 {
return res
} else if size := hdo.ContentLength; size < 1 {
} else if s := hdo.ContentLength; s == nil {
return res
} else if size := *s; size < 1 {
return res
} else {
var i int64 = 0

View File

@@ -98,7 +98,7 @@ func (m *mpu) RegisterPart(etag string) {
m.n++
m.l = append(m.l, sdktyp.CompletedPart{
ETag: sdkaws.String(strings.Replace(etag, "\"", "", -1)),
PartNumber: m.n,
PartNumber: sdkaws.Int32(m.n),
})
}
@@ -154,8 +154,8 @@ func (m *mpu) AddPart(r io.Reader) (n int64, e error) {
Bucket: sdkaws.String(bck),
Key: sdkaws.String(obj),
UploadId: sdkaws.String(mid),
PartNumber: m.Counter() + 1,
ContentLength: n,
PartNumber: sdkaws.Int32(m.Counter() + 1),
ContentLength: sdkaws.Int64(n),
Body: tmp,
RequestPayer: sdktyp.RequestPayerRequester,
ContentMD5: sdkaws.String(hss),

View File

@@ -75,7 +75,7 @@ func (cli *client) SetRetention(object, version string, bypass bool, until time.
}
if bypass {
in.BypassGovernanceRetention = true
in.BypassGovernanceRetention = sdkaws.Bool(true)
}
switch {

View File

@@ -42,7 +42,7 @@ import (
func (cli *client) MultipartList(keyMarker, markerId string) (uploads []sdktyp.MultipartUpload, nextKeyMarker string, nextIdMarker string, count int64, e error) {
in := &sdksss.ListMultipartUploadsInput{
Bucket: sdkaws.String(cli.GetBucketName()),
MaxUploads: 1000,
MaxUploads: sdkaws.Int32(1000),
}
if keyMarker != "" && markerId != "" {
@@ -54,10 +54,17 @@ func (cli *client) MultipartList(keyMarker, markerId string) (uploads []sdktyp.M
if err != nil {
return nil, "", "", 0, cli.GetError(err)
} else if out.IsTruncated {
return out.Uploads, *out.NextKeyMarker, *out.NextUploadIdMarker, int64(out.MaxUploads), nil
}
var maxKeys int32
if out != nil && out.MaxUploads != nil {
maxKeys = *out.MaxUploads
}
if out != nil && out.IsTruncated != nil && *out.IsTruncated {
return out.Uploads, *out.NextKeyMarker, *out.NextUploadIdMarker, int64(maxKeys), nil
} else {
return out.Uploads, "", "", int64(out.MaxUploads), nil
return out.Uploads, "", "", int64(maxKeys), nil
}
}

View File

@@ -30,9 +30,8 @@ import (
"mime"
"path/filepath"
sdksss "github.com/aws/aws-sdk-go-v2/service/s3"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
sdksss "github.com/aws/aws-sdk-go-v2/service/s3"
sdktps "github.com/aws/aws-sdk-go-v2/service/s3/types"
libhlp "github.com/nabbar/golib/aws/helper"
)
@@ -58,10 +57,17 @@ func (cli *client) ListPrefix(continuationToken string, prefix string) ([]sdktps
if err != nil {
return nil, "", 0, cli.GetError(err)
} else if out.IsTruncated {
return out.Contents, *out.NextContinuationToken, int64(out.KeyCount), nil
}
var maxKeys int32
if out != nil && out.MaxKeys != nil {
maxKeys = *out.MaxKeys
}
if out != nil && out.IsTruncated != nil && *out.IsTruncated {
return out.Contents, *out.NextContinuationToken, int64(maxKeys), nil
} else {
return out.Contents, "", int64(out.KeyCount), nil
return out.Contents, "", int64(maxKeys), nil
}
}
@@ -104,7 +110,7 @@ func (cli *client) WalkPrefix(prefix string, f WalkFunc) error {
}
}
if out.IsTruncated {
if out != nil && out.IsTruncated != nil && *out.IsTruncated {
t = out.NextContinuationToken
} else {
return e

View File

@@ -38,7 +38,7 @@ import (
func (cli *client) VersionList(prefix, keyMarker, markerId string) (version []sdktps.ObjectVersion, delMarker []sdktps.DeleteMarkerEntry, nextKeyMarker, nextMarkerId string, count int64, err error) {
in := sdksss.ListObjectVersionsInput{
Bucket: cli.GetBucketAws(),
MaxKeys: 1000,
MaxKeys: sdkaws.Int32(1000),
}
if prefix != "" {
@@ -54,10 +54,17 @@ func (cli *client) VersionList(prefix, keyMarker, markerId string) (version []sd
if e != nil {
return nil, nil, "", "", 0, cli.GetError(e)
} else if out.IsTruncated {
return out.Versions, out.DeleteMarkers, *out.NextKeyMarker, *out.NextVersionIdMarker, int64(out.MaxKeys), nil
}
var maxKeys int32
if out != nil && out.MaxKeys != nil {
maxKeys = *out.MaxKeys
}
if out != nil && out.IsTruncated != nil && *out.IsTruncated {
return out.Versions, out.DeleteMarkers, *out.NextKeyMarker, *out.NextVersionIdMarker, int64(maxKeys), nil
} else {
return out.Versions, out.DeleteMarkers, "", "", int64(out.MaxKeys), nil
return out.Versions, out.DeleteMarkers, "", "", int64(maxKeys), nil
}
}
@@ -68,7 +75,7 @@ func (cli *client) VersionWalk(fv VersionWalkFunc, fd DelMakWalkFunc) error {
func (cli *client) VersionWalkPrefix(prefix string, fv VersionWalkFunc, fd DelMakWalkFunc) error {
in := sdksss.ListObjectVersionsInput{
Bucket: cli.GetBucketAws(),
MaxKeys: 1000,
MaxKeys: sdkaws.Int32(1000),
}
if prefix != "" {
@@ -117,7 +124,7 @@ func (cli *client) VersionWalkPrefix(prefix string, fv VersionWalkFunc, fd DelMa
}
}
if out.IsTruncated {
if out != nil && out.IsTruncated != nil && *out.IsTruncated {
km = out.NextKeyMarker
mi = out.NextVersionIdMarker
} else {
@@ -181,8 +188,10 @@ func (cli *client) VersionSize(object, version string) (size int64, err error) {
if h, err = cli.VersionHead(object, version); err != nil {
return
} else if h != nil && h.ContentLength != nil {
return *h.ContentLength, nil
} else {
return h.ContentLength, nil
return 0, nil
}
}
@@ -207,7 +216,7 @@ func (cli *client) VersionDeleteLock(check bool, object, version string, byPassG
}
if byPassGovernance {
in.BypassGovernanceRetention = true
in.BypassGovernanceRetention = sdkaws.Bool(true)
}
_, err := cli.s3.DeleteObject(cli.GetContext(), &in)

View File

@@ -26,9 +26,13 @@
package aws
import (
"context"
"net/url"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
sdkiam "github.com/aws/aws-sdk-go-v2/service/iam"
sdksss "github.com/aws/aws-sdk-go-v2/service/s3"
awsedp "github.com/aws/smithy-go/endpoints"
)
type resolverIam struct {
@@ -39,6 +43,14 @@ func (r *resolverIam) ResolveEndpoint(region string, options sdkiam.EndpointReso
return r.r("iam", region)
}
type resolverIamV2 struct {
r func(service, region string) (awsedp.Endpoint, error)
}
func (r *resolverIamV2) ResolveEndpoint(ctx context.Context, params sdkiam.EndpointParameters) (awsedp.Endpoint, error) {
return r.r("iam", *params.Region)
}
type resolverS3 struct {
r func(service, region string) (sdkaws.Endpoint, error)
}
@@ -47,14 +59,62 @@ func (r *resolverS3) ResolveEndpoint(region string, options sdksss.EndpointResol
return r.r("s3", region)
}
type resolverS3V2 struct {
r func(service, region string) (awsedp.Endpoint, error)
}
func (r *resolverS3V2) ResolveEndpoint(ctx context.Context, params sdksss.EndpointParameters) (awsedp.Endpoint, error) {
return r.r("s3", *params.Region)
}
func (c *client) _NewIAMResolver(cfg *sdkaws.Config) sdkiam.EndpointResolver {
return &resolverIam{
r: cfg.EndpointResolver.ResolveEndpoint,
}
}
func (c *client) _NewIAMResolverV2(cfg Config) sdkiam.EndpointResolverV2 {
return &resolverIamV2{
r: func(service, region string) (awsedp.Endpoint, error) {
edp, err := cfg.ResolveEndpoint(service, region)
if err != nil {
return awsedp.Endpoint{}, err
}
uri, err := url.Parse(edp.URL)
if err != nil {
return awsedp.Endpoint{}, err
}
return awsedp.Endpoint{
URI: *uri,
}, nil
},
}
}
func (c *client) _NewS3Resolver(cfg *sdkaws.Config) sdksss.EndpointResolver {
return &resolverS3{
r: cfg.EndpointResolver.ResolveEndpoint,
}
}
func (c *client) _NewS3ResolverV2(cfg Config) sdksss.EndpointResolverV2 {
return &resolverS3V2{
r: func(service, region string) (awsedp.Endpoint, error) {
edp, err := cfg.ResolveEndpoint(service, region)
if err != nil {
return awsedp.Endpoint{}, err
}
uri, err := url.Parse(edp.URL)
if err != nil {
return awsedp.Endpoint{}, err
}
return awsedp.Endpoint{
URI: *uri,
}, nil
},
}
}

View File

@@ -61,7 +61,9 @@ func (c *cobra) AddCommandCompletion() {
os.Exit(1)
} else if len(args) >= 2 {
file = filepath.Clean(args[1])
c.getLog().CheckError(loglvl.ErrorLevel, loglvl.NilLevel, "create file path", os.MkdirAll(filepath.Dir(file), 0755))
// #nosec
e := os.MkdirAll(filepath.Dir(file), 0755)
c.getLog().CheckError(loglvl.ErrorLevel, loglvl.NilLevel, "create file path", e)
}
switch strings.ToLower(args[0]) {

View File

@@ -110,6 +110,7 @@ func (c *cobra) ConfigureWriteConfig(basename string, defaultConfig func() io.Re
cfgFile = strings.TrimRight(cfgFile, ext) + ".json"
}
// #nosec
fs, err = os.OpenFile(cfgFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
return err

View File

@@ -147,6 +147,7 @@ func (o *componentSmtp) _GetTLS() libtls.TLSConfig {
func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config {
if i, e := cfg.NewFrom(o._GetTLS()); e != nil {
// #nosec
return &tls.Config{}
} else {
return i.TlsConfig("")

View File

@@ -52,6 +52,7 @@ type Config[T comparable] interface {
MapManage[T]
Context
SetContext(ctx FuncContext)
Clone(ctx context.Context) Config[T]
Merge(cfg Config[T]) bool
Walk(fct FuncWalk[T]) bool
@@ -81,6 +82,18 @@ type configContext[T comparable] struct {
x FuncContext
}
func (c *configContext[T]) SetContext(ctx FuncContext) {
c.n.Lock()
defer c.n.Unlock()
if ctx == nil {
ctx = context.Background
}
c.Context = ctx()
c.x = ctx
}
func (c *configContext[T]) Delete(key T) {
if c.Err() != nil {
c.Clean()

View File

@@ -39,6 +39,7 @@ const (
ErrorBadInstance
ErrorGetFunction
ErrorSetFunction
ErrorDelFunction
ErrorListFunction
ErrorFunctionParams
)
@@ -62,6 +63,8 @@ func getMessage(code liberr.CodeError) (message string) {
return "missing get function of " + pkgName
case ErrorSetFunction:
return "missing set function of " + pkgName
case ErrorDelFunction:
return "missing del function of " + pkgName
case ErrorListFunction:
return "missing list function of " + pkgName
case ErrorFunctionParams:

View File

@@ -26,25 +26,33 @@
package kvdriver
type FctWalk[K comparable, M any] func(key K, model M) bool
type KVDriver[K comparable, M any] interface {
Get(key K, model *M) error
Set(key K, model M) error
List() ([]K, error)
Walk(fct FctWalk[K, M]) error
}
import (
libkvt "github.com/nabbar/golib/database/kvtypes"
)
type FuncNew[K comparable, M any] func() libkvt.KVDriver[K, M]
type FuncGet[K comparable, M any] func(key K) (M, error)
type FuncSet[K comparable, M any] func(key K, model M) error
type FuncDel[K comparable] func(key K) error
type FuncList[K comparable, M any] func() ([]K, error)
type FuncWalk[K comparable, M any] func(fct FctWalk[K, M]) error
type Driver[K comparable, M any] struct {
KVDriver[K, M]
type FuncWalk[K comparable, M any] func(fct libkvt.FctWalk[K, M]) error
type drv[K comparable, M any] struct {
FctNew FuncNew[K, M]
FctGet FuncGet[K, M]
FctSet FuncSet[K, M]
FctDel FuncDel[K]
FctList FuncList[K, M]
FctWalk FuncWalk[K, M] // optional
}
func New[K comparable, M any](fn FuncNew[K, M], fg FuncGet[K, M], fs FuncSet[K, M], fd FuncDel[K], fl FuncList[K, M], fw FuncWalk[K, M]) libkvt.KVDriver[K, M] {
return &drv[K, M]{
FctNew: fn,
FctGet: fg,
FctSet: fs,
FctDel: fd,
FctList: fl,
FctWalk: fw,
}
}

View File

@@ -26,7 +26,26 @@
package kvdriver
func (o *Driver[K, M]) Get(key K, model *M) error {
import (
libkvt "github.com/nabbar/golib/database/kvtypes"
)
func (o *drv[K, M]) New() libkvt.KVDriver[K, M] {
if o.FctNew != nil {
return o.FctNew()
}
return &drv[K, M]{
FctNew: o.FctNew,
FctGet: o.FctGet,
FctSet: o.FctSet,
FctDel: o.FctDel,
FctList: o.FctList,
FctWalk: o.FctWalk,
}
}
func (o *drv[K, M]) Get(key K, model *M) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if o.FctGet == nil {
@@ -38,7 +57,7 @@ func (o *Driver[K, M]) Get(key K, model *M) error {
}
}
func (o *Driver[K, M]) Set(key K, model M) error {
func (o *drv[K, M]) Set(key K, model M) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if o.FctSet == nil {
@@ -48,7 +67,17 @@ func (o *Driver[K, M]) Set(key K, model M) error {
}
}
func (o *Driver[K, M]) List() ([]K, error) {
func (o *drv[K, M]) Del(key K) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if o.FctDel == nil {
return ErrorSetFunction.Error(nil)
} else {
return o.FctDel(key)
}
}
func (o *drv[K, M]) List() ([]K, error) {
if o == nil {
return nil, ErrorBadInstance.Error(nil)
} else if o.FctList == nil {
@@ -58,7 +87,7 @@ func (o *Driver[K, M]) List() ([]K, error) {
}
}
func (o *Driver[K, M]) Walk(fct FctWalk[K, M]) error {
func (o *drv[K, M]) Walk(fct libkvt.FctWalk[K, M]) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if fct == nil {
@@ -70,7 +99,7 @@ func (o *Driver[K, M]) Walk(fct FctWalk[K, M]) error {
}
}
func (o *Driver[K, M]) fakeWalk(fct FctWalk[K, M]) error {
func (o *drv[K, M]) fakeWalk(fct libkvt.FctWalk[K, M]) error {
if l, e := o.List(); e != nil {
return e
} else {

View File

@@ -38,6 +38,7 @@ const (
ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgDatabaseKVItm
ErrorLoadFunction
ErrorStoreFunction
ErrorRemoveFunction
)
func init() {
@@ -57,6 +58,8 @@ func getMessage(code liberr.CodeError) (message string) {
return "missing load function of " + pkgName
case ErrorStoreFunction:
return "missing store function of " + pkgName
case ErrorRemoveFunction:
return "missing remove function of " + pkgName
}
return liberr.NullMessage

View File

@@ -26,40 +26,21 @@
package kvitem
import "sync/atomic"
import (
"sync/atomic"
type FuncLoad[K comparable, M any] func(key K, model *M) error
type FuncStore[K comparable, M any] func(key K, model M) error
type KVItem[K comparable, M any] interface {
Set(model M)
Get() M
Load() error
Store(force bool) error
Clean()
HasChange() bool
RegisterFctLoad(fct FuncLoad[K, M])
RegisterFctStore(fct FuncStore[K, M])
}
func New[K comparable, M any](key K) KVItem[K, M] {
var (
ml = new(atomic.Value)
mw = new(atomic.Value)
)
ml.Store(nil)
mw.Store(nil)
libkvt "github.com/nabbar/golib/database/kvtypes"
)
func New[K comparable, M any](drv libkvt.KVDriver[K, M], key K) libkvt.KVItem[K, M] {
return &itm[K, M]{
k: key,
ml: ml,
ms: mw,
fl: nil,
fs: nil,
d: drv,
ml: new(atomic.Value),
ms: new(atomic.Value),
fl: new(atomic.Value),
fs: new(atomic.Value),
fr: new(atomic.Value),
}
}

View File

@@ -29,9 +29,12 @@ package kvitem
import (
"reflect"
"sync/atomic"
libkvt "github.com/nabbar/golib/database/kvtypes"
)
type itm[K comparable, M any] struct {
d libkvt.KVDriver[K, M]
k K // key
ml *atomic.Value // model read
@@ -39,165 +42,145 @@ type itm[K comparable, M any] struct {
fl *atomic.Value
fs *atomic.Value
fr *atomic.Value
}
func (o *itm[K, M]) RegisterFctLoad(fct FuncLoad[K, M]) {
o.fl.Store(fct)
}
func (o *itm[K, M]) getFctLoad() FuncLoad[K, M] {
func (o *itm[K, M]) getDriver() libkvt.KVDriver[K, M] {
if o == nil {
return nil
}
i := o.fs.Load()
if i == nil {
return nil
} else if f, k := i.(FuncLoad[K, M]); !k {
return nil
} else {
return f
}
}
func (o *itm[K, M]) RegisterFctStore(fct FuncStore[K, M]) {
o.fs.Store(fct)
}
func (o *itm[K, M]) getFctStore() FuncStore[K, M] {
if o == nil {
return nil
}
i := o.fs.Load()
if i == nil {
return nil
} else if f, k := i.(FuncStore[K, M]); !k {
return nil
} else {
return f
}
return o.d
}
func (o *itm[K, M]) Set(model M) {
if o == nil {
return
}
var val = reflect.ValueOf(model)
o.ms.Store(val.Interface())
}
m := o.ml.Load()
func (o *itm[K, M]) setModelLoad(mod M) {
var val = reflect.ValueOf(mod)
o.ml.Store(val.Interface())
}
// model not loaded, so store new model
if m == nil {
o.ms.Store(model)
// model loaded and new model given not same, so store new model
} else if !reflect.DeepEqual(m.(M), model) {
o.ms.Store(model)
// model loaded and given model are same, so don't store new model
func (o *itm[K, M]) getModelLoad() M {
var mod M
if i := o.ml.Load(); i == nil {
return mod
} else if v, k := i.(M); !k {
return mod
} else {
o.ms.Store(nil)
return v
}
}
func (o *itm[K, M]) getModelStore() M {
var mod M
if i := o.ms.Load(); i == nil {
return mod
} else if v, k := i.(M); !k {
return mod
} else {
return v
}
}
func (o *itm[K, M]) Key() K {
if o == nil {
var k K
return k
}
return o.k
}
func (o *itm[K, M]) Get() M {
var (
tmp M
mod M
)
if o == nil {
return *(new(M))
return mod
}
// update exist so latest fresh value
m := o.ms.Load()
if m != nil {
if v, k := m.(M); k {
return v
}
}
mod = o.getModelStore()
// load model exist so return last model load
m = o.ml.Load()
if m != nil {
if v, k := m.(M); k {
return v
}
if reflect.DeepEqual(mod, tmp) {
mod = o.getModelLoad()
}
// nothing load, so return new instance
return *(new(M))
return mod
}
func (o *itm[K, M]) Load() error {
var fct FuncLoad[K, M]
var (
mod M
drv = o.getDriver()
)
if fct = o.getFctLoad(); fct == nil {
if drv == nil {
return ErrorLoadFunction.Error(nil)
}
m := *(new(M))
e := fct(o.k, &m)
if e == nil {
o.ml.Store(m)
if e := drv.Get(o.k, &mod); e == nil {
o.setModelLoad(mod)
} else {
return e
}
return e
return nil
}
func (o *itm[K, M]) Store(force bool) error {
var fct FuncStore[K, M]
var drv = o.getDriver()
if fct = o.getFctStore(); fct == nil {
if drv == nil {
return ErrorStoreFunction.Error(nil)
}
m := o.ms.Load()
if m != nil {
return fct(o.k, m.(M))
} else if !force {
return nil
var (
lod M
str M
)
_ = o.Load()
str = o.getModelStore()
if reflect.DeepEqual(lod, str) {
str = o.getModelLoad()
}
// no update, but force store, so use load model
m = o.ml.Load()
if m != nil {
return fct(o.k, m.(M))
lod = o.getModelLoad()
if !reflect.DeepEqual(lod, str) {
return drv.Set(o.k, str)
} else if force {
return drv.Set(o.k, lod)
}
// no update and no load, but force store, so use new instance of model
m = *(new(M))
return fct(o.k, m.(M))
return nil
}
func (o *itm[K, M]) Remove() error {
drv := o.getDriver()
if drv == nil {
return ErrorStoreFunction.Error(nil)
}
return drv.Del(o.k)
}
func (o *itm[K, M]) Clean() {
o.ml.Store(nil)
o.ms.Store(nil)
var tmp M
o.setModelLoad(tmp)
o.Set(tmp)
}
func (o *itm[K, M]) HasChange() bool {
r := o.ml.Load()
w := o.ms.Load()
r := o.getModelLoad()
w := o.getModelStore()
if r == nil && w == nil {
// not loaded and not store, so no change
return false
} else if r == nil {
// not loaded but store is set, so has been updated
return true
} else if w == nil {
// loaded and not store, so no change
return false
}
mr, kr := r.(M)
mw, kw := w.(M)
if !kr && !kw {
// no valid model, so no change
return false
} else if !kr {
// not valid model for load, but valid for store, so has been updated
return true
} else if !kw {
// valid model for load, but not valid for store, so like no change
return false
}
return !reflect.DeepEqual(mr, mw)
return !reflect.DeepEqual(r, w)
}

View File

@@ -39,6 +39,7 @@ const (
ErrorBadInstance
ErrorGetFunction
ErrorSetFunction
ErrorDelFunction
ErrorListFunction
ErrorFunctionParams
)
@@ -62,6 +63,8 @@ func getMessage(code liberr.CodeError) (message string) {
return "missing get function of " + pkgName
case ErrorSetFunction:
return "missing set function of " + pkgName
case ErrorDelFunction:
return "missing del function of " + pkgName
case ErrorListFunction:
return "missing list function of " + pkgName
case ErrorFunctionParams:

View File

@@ -27,17 +27,29 @@
package kvmap
import (
libkvd "github.com/nabbar/golib/database/kvdriver"
libkvt "github.com/nabbar/golib/database/kvtypes"
)
type FuncNew[K comparable, M any] func() libkvt.KVDriver[K, M]
type FuncGet[K comparable, MK comparable] func(key K) (map[MK]any, error)
type FuncSet[K comparable, MK comparable] func(key K, model map[MK]any) error
type FuncDel[K comparable] func(key K) error
type FuncList[K comparable, MK comparable] func() ([]K, error)
type Driver[K comparable, MK comparable, M any] struct {
libkvd.KVDriver[K, M]
type drv[K comparable, MK comparable, M any] struct {
FctNew FuncNew[K, M]
FctGet FuncGet[K, MK]
FctSet FuncSet[K, MK]
FctDel FuncDel[K]
FctList FuncList[K, MK]
}
func New[K comparable, MK comparable, M any](fn FuncNew[K, M], fg FuncGet[K, MK], fs FuncSet[K, MK], fd FuncDel[K], fl FuncList[K, MK]) libkvt.KVDriver[K, M] {
return &drv[K, MK, M]{
FctNew: fn,
FctGet: fg,
FctSet: fs,
FctDel: fd,
FctList: fl,
}
}

View File

@@ -29,10 +29,10 @@ package kvmap
import (
"encoding/json"
libkvd "github.com/nabbar/golib/database/kvdriver"
libkvt "github.com/nabbar/golib/database/kvtypes"
)
func (o *Driver[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error {
func (o *drv[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error {
if p, e := json.Marshal(model); e != nil {
return e
} else {
@@ -40,7 +40,7 @@ func (o *Driver[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error {
}
}
func (o *Driver[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error {
func (o *drv[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error {
if p, e := json.Marshal(modelMap); e != nil {
return e
} else {
@@ -48,7 +48,16 @@ func (o *Driver[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error {
}
}
func (o *Driver[K, MK, M]) Get(key K, model *M) error {
func (o *drv[K, MK, M]) New() libkvt.KVDriver[K, M] {
return &drv[K, MK, M]{
FctGet: o.FctGet,
FctSet: o.FctSet,
FctDel: o.FctDel,
FctList: o.FctList,
}
}
func (o *drv[K, MK, M]) Get(key K, model *M) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if o.FctGet == nil {
@@ -60,7 +69,7 @@ func (o *Driver[K, MK, M]) Get(key K, model *M) error {
}
}
func (o *Driver[K, MK, M]) Set(key K, model M) error {
func (o *drv[K, MK, M]) Set(key K, model M) error {
var m = make(map[MK]any)
if o == nil {
@@ -74,7 +83,17 @@ func (o *Driver[K, MK, M]) Set(key K, model M) error {
}
}
func (o *Driver[K, MK, M]) List() ([]K, error) {
func (o *drv[K, MK, M]) Del(key K) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if o.FctDel == nil {
return ErrorDelFunction.Error(nil)
} else {
return o.FctDel(key)
}
}
func (o *drv[K, MK, M]) List() ([]K, error) {
if o == nil {
return nil, ErrorBadInstance.Error(nil)
} else if o.FctList == nil {
@@ -84,7 +103,7 @@ func (o *Driver[K, MK, M]) List() ([]K, error) {
}
}
func (o *Driver[K, MK, M]) Walk(fct libkvd.FctWalk[K, M]) error {
func (o *drv[K, MK, M]) Walk(fct libkvt.FctWalk[K, M]) error {
if o == nil {
return ErrorBadInstance.Error(nil)
} else if fct == nil {

View File

@@ -27,25 +27,11 @@
package kvtable
import (
"sync/atomic"
libkvd "github.com/nabbar/golib/database/kvdriver"
libkvi "github.com/nabbar/golib/database/kvitem"
libkvt "github.com/nabbar/golib/database/kvtypes"
)
type FuncWalk[K comparable, M any] func(kv libkvi.KVItem[K, M]) bool
type KVTable[K comparable, M any] interface {
Get(key K) (libkvi.KVItem[K, M], error)
List() ([]libkvi.KVItem[K, M], error)
Walk(fct FuncWalk[K, M]) error
}
func New[K comparable, M any](drv libkvd.KVDriver[K, M]) KVTable[K, M] {
d := new(atomic.Value)
d.Store(drv)
func New[K comparable, M any](drv libkvt.KVDriver[K, M]) libkvt.KVTable[K, M] {
return &tbl[K, M]{
d: d,
d: drv,
}
}

View File

@@ -27,66 +27,58 @@
package kvtable
import (
"sync/atomic"
libkvd "github.com/nabbar/golib/database/kvdriver"
libkvs "github.com/nabbar/golib/database/kvitem"
libkvt "github.com/nabbar/golib/database/kvtypes"
)
type tbl[K comparable, M any] struct {
d *atomic.Value
d libkvt.KVDriver[K, M]
}
func (o *tbl[K, M]) getDriver() libkvd.KVDriver[K, M] {
func (o *tbl[K, M]) getDriver() libkvt.KVDriver[K, M] {
if o == nil {
return nil
}
i := o.d.Load()
if i == nil {
return nil
} else if d, k := i.(libkvd.KVDriver[K, M]); !k {
if o.d == nil {
return nil
} else {
return d
return o.d
}
}
func (o *tbl[K, M]) Get(key K) (libkvs.KVItem[K, M], error) {
var kvs = libkvs.New[K, M](key)
func (o *tbl[K, M]) Get(key K) (libkvt.KVItem[K, M], error) {
if drv := o.getDriver(); drv == nil {
return nil, ErrorBadDriver.Error(nil)
} else {
kvs.RegisterFctLoad(drv.Get)
kvs.RegisterFctStore(drv.Set)
var kvi = libkvs.New[K, M](drv.New(), key)
e := kvi.Load()
return kvi, e
}
return kvs, kvs.Load()
}
func (o *tbl[K, M]) Walk(fct FuncWalk[K, M]) error {
func (o *tbl[K, M]) Del(key K) error {
if drv := o.getDriver(); drv == nil {
return ErrorBadDriver.Error(nil)
} else {
return drv.Del(key)
}
}
func (o *tbl[K, M]) Walk(fct libkvt.FuncWalk[K, M]) error {
if drv := o.getDriver(); drv == nil {
return ErrorBadDriver.Error(nil)
} else {
return drv.Walk(func(key K, model M) bool {
var kvs = libkvs.New[K, M](key)
kvs.RegisterFctStore(drv.Set)
kvs.RegisterFctLoad(func(k K, m *M) error {
*m = model
return nil
})
_ = kvs.Load()
kvs.RegisterFctLoad(drv.Get)
return fct(kvs)
kvi := libkvs.New[K, M](drv.New(), key)
kvi.Set(model)
return fct(kvi)
})
}
}
func (o *tbl[K, M]) List() ([]libkvs.KVItem[K, M], error) {
var res = make([]libkvs.KVItem[K, M], 0)
func (o *tbl[K, M]) List() ([]libkvt.KVItem[K, M], error) {
var res = make([]libkvt.KVItem[K, M], 0)
if drv := o.getDriver(); drv == nil {
return nil, ErrorBadDriver.Error(nil)
@@ -94,12 +86,7 @@ func (o *tbl[K, M]) List() ([]libkvs.KVItem[K, M], error) {
return nil, e
} else {
for _, k := range l {
var kvs = libkvs.New[K, M](k)
kvs.RegisterFctLoad(drv.Get)
kvs.RegisterFctStore(drv.Set)
res = append(res, kvs)
res = append(res, libkvs.New[K, M](drv.New(), k))
}
return res, nil

View File

@@ -0,0 +1,38 @@
/*
* MIT License
*
* Copyright (c) 2023 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package kvtypes
type FctWalk[K comparable, M any] func(key K, model M) bool
type KVDriver[K comparable, M any] interface {
New() KVDriver[K, M]
Get(key K, model *M) error
Set(key K, model M) error
Del(key K) error
List() ([]K, error)
Walk(fct FctWalk[K, M]) error
}

40
database/kvtypes/item.go Normal file
View File

@@ -0,0 +1,40 @@
/*
* MIT License
*
* Copyright (c) 2023 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package kvtypes
type KVItem[K comparable, M any] interface {
Set(model M)
Get() M
Key() K
Load() error
Store(force bool) error
Remove() error
Clean()
HasChange() bool
}

36
database/kvtypes/table.go Normal file
View File

@@ -0,0 +1,36 @@
/*
* MIT License
*
* Copyright (c) 2023 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
package kvtypes
type FuncWalk[K comparable, M any] func(kv KVItem[K, M]) bool
type KVTable[K comparable, M any] interface {
Get(key K) (KVItem[K, M], error)
Del(key K) error
List() ([]KVItem[K, M], error)
Walk(fct FuncWalk[K, M]) error
}

87
duration/encode.go Normal file
View File

@@ -0,0 +1,87 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package duration
import (
"fmt"
"gopkg.in/yaml.v3"
)
func (d Duration) MarshalJSON() ([]byte, error) {
t := d.String()
b := make([]byte, 0, len(t)+2)
b = append(b, '"')
b = append(b, []byte(t)...)
b = append(b, '"')
return b, nil
}
func (d *Duration) UnmarshalJSON(bytes []byte) error {
return d.unmarshall(bytes)
}
func (d Duration) MarshalYAML() (interface{}, error) {
return d.MarshalJSON()
}
func (d *Duration) UnmarshalYAML(value *yaml.Node) error {
return d.unmarshall([]byte(value.Value))
}
func (d Duration) MarshalTOML() ([]byte, error) {
return d.MarshalJSON()
}
func (d *Duration) UnmarshalTOML(i interface{}) error {
if b, k := i.([]byte); k {
return d.unmarshall(b)
}
if b, k := i.(string); k {
return d.parseString(b)
}
return fmt.Errorf("size: value not in valid format")
}
func (d Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
func (d *Duration) UnmarshalText(bytes []byte) error {
return d.unmarshall(bytes)
}
func (d Duration) MarshalCBOR() ([]byte, error) {
return []byte(d.String()), nil
}
func (d *Duration) UnmarshalCBOR(bytes []byte) error {
return d.unmarshall(bytes)
}

51
duration/format.go Normal file
View File

@@ -0,0 +1,51 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package duration
import (
"math"
"time"
)
func (d Duration) Time() time.Duration {
return time.Duration(d)
}
func (d Duration) String() string {
return time.Duration(d).String()
}
func (d Duration) Days() int64 {
t := math.Floor(d.Time().Hours())
if t > math.MaxInt64 {
return math.MaxInt64
}
return int64(t)
}

62
duration/interface.go Normal file
View File

@@ -0,0 +1,62 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package duration
import (
"time"
)
type Duration time.Duration
func Parse(s string) (Duration, error) {
return parseString(s)
}
func ParseByte(p []byte) (Duration, error) {
return parseString(string(p))
}
func Seconds(i int64) Duration {
return Duration(time.Duration(i) * time.Second)
}
func Minutes(i int64) Duration {
return Duration(time.Duration(i) * time.Minute)
}
func Hours(i int64) Duration {
return Duration(time.Duration(i) * time.Hour)
}
func Days(i int64) Duration {
return Duration(time.Duration(i) * time.Hour * 24)
}
func ParseDuration(d time.Duration) Duration {
return Duration(d)
}

59
duration/model.go Normal file
View File

@@ -0,0 +1,59 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package duration
import (
"reflect"
libmap "github.com/mitchellh/mapstructure"
)
func ViperDecoderHook() libmap.DecodeHookFuncType {
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
var (
z = Duration(0)
t string
k bool
)
// Check if the data type matches the expected one
if from.Kind() != reflect.String {
return data, nil
} else if t, k = data.(string); !k {
return data, nil
}
// Check if the target type matches the expected one
if to != reflect.TypeOf(z) {
return data, nil
}
// Format/decode/parse the data and return the new value
return parseString(t)
}
}

61
duration/parse.go Normal file
View File

@@ -0,0 +1,61 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package duration
import (
"strings"
"time"
)
func parseString(s string) (Duration, error) {
s = strings.Replace(s, "\"", "", -1)
s = strings.Replace(s, "'", "", -1)
if v, e := time.ParseDuration(s); e != nil {
return 0, e
} else {
return Duration(v), nil
}
}
func (d *Duration) parseString(s string) error {
if v, e := parseString(s); e != nil {
return e
} else {
*d = v
return nil
}
}
func (d *Duration) unmarshall(val []byte) error {
if tmp, err := ParseByte(val); err != nil {
return err
} else {
*d = tmp
return nil
}
}

87
file/perm/encode.go Normal file
View File

@@ -0,0 +1,87 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package perm
import (
"fmt"
"gopkg.in/yaml.v3"
)
func (p Perm) MarshalJSON() ([]byte, error) {
t := p.String()
b := make([]byte, 0, len(t)+2)
b = append(b, '"')
b = append(b, []byte(t)...)
b = append(b, '"')
return b, nil
}
func (p *Perm) UnmarshalJSON(bytes []byte) error {
return p.unmarshall(bytes)
}
func (p Perm) MarshalYAML() (interface{}, error) {
return p.MarshalJSON()
}
func (p *Perm) UnmarshalYAML(value *yaml.Node) error {
return p.unmarshall([]byte(value.Value))
}
func (p Perm) MarshalTOML() ([]byte, error) {
return p.MarshalJSON()
}
func (p *Perm) UnmarshalTOML(i interface{}) error {
if b, k := i.([]byte); k {
return p.unmarshall(b)
}
if b, k := i.(string); k {
return p.parseString(b)
}
return fmt.Errorf("size: value not in valid format")
}
func (p Perm) MarshalText() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *Perm) UnmarshalText(bytes []byte) error {
return p.unmarshall(bytes)
}
func (p Perm) MarshalCBOR() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *Perm) UnmarshalCBOR(bytes []byte) error {
return p.unmarshall(bytes)
}

91
file/perm/format.go Normal file
View File

@@ -0,0 +1,91 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package perm
import (
"fmt"
"math"
"os"
)
func (p Perm) FileMode() os.FileMode {
return os.FileMode(p.Uint64())
}
func (p Perm) String() string {
return fmt.Sprintf("%#o", p.Uint64())
}
func (p Perm) Int64() int64 {
if uint64(p) > math.MaxInt64 {
// overflow
return math.MaxInt64
}
return int64(p)
}
func (p Perm) Int32() int32 {
if uint64(p) > math.MaxInt32 {
// overflow
return math.MaxInt32
}
return int32(p)
}
func (p Perm) Int() int {
if uint64(p) > math.MaxInt {
// overflow
return math.MaxInt
}
return int(p)
}
func (p Perm) Uint64() uint64 {
return uint64(p)
}
func (p Perm) Uint32() uint32 {
if uint64(p) > math.MaxUint32 {
// overflow
return math.MaxUint32
}
return uint32(p)
}
func (p Perm) Uint() uint {
if uint64(p) > math.MaxUint {
// overflow
return math.MaxUint
}
return uint(p)
}

51
file/perm/interface.go Normal file
View File

@@ -0,0 +1,51 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package perm
import (
"os"
"strconv"
)
type Perm os.FileMode
func Parse(s string) (Perm, error) {
return parseString(s)
}
func ParseInt(i int) (Perm, error) {
return parseString(strconv.FormatInt(int64(i), 8))
}
func ParseInt64(i int64) (Perm, error) {
return parseString(strconv.FormatInt(i, 8))
}
func ParseByte(p []byte) (Perm, error) {
return parseString(string(p))
}

59
file/perm/model.go Normal file
View File

@@ -0,0 +1,59 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package perm
import (
"reflect"
libmap "github.com/mitchellh/mapstructure"
)
func ViperDecoderHook() libmap.DecodeHookFuncType {
return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
var (
z = Perm(0)
t string
k bool
)
// Check if the data type matches the expected one
if from.Kind() != reflect.String {
return data, nil
} else if t, k = data.(string); !k {
return data, nil
}
// Check if the target type matches the expected one
if to != reflect.TypeOf(z) {
return data, nil
}
// Format/decode/parse the data and return the new value
return parseString(t)
}
}

66
file/perm/parse.go Normal file
View File

@@ -0,0 +1,66 @@
/***********************************************************************************************************************
*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
**********************************************************************************************************************/
package perm
import (
"fmt"
"math"
"strconv"
"strings"
)
func parseString(s string) (Perm, error) {
s = strings.Replace(s, "\"", "", -1)
s = strings.Replace(s, "'", "", -1)
if v, e := strconv.ParseUint(s, 8, 32); e != nil {
return 0, e
} else if v > math.MaxUint32 {
return Perm(0), fmt.Errorf("invalid permission")
} else {
return Perm(v), nil
}
}
func (p *Perm) parseString(s string) error {
if v, e := parseString(s); e != nil {
return e
} else {
*p = v
return nil
}
}
func (p *Perm) unmarshall(val []byte) error {
if tmp, err := ParseByte(val); err != nil {
return err
} else {
*p = tmp
return nil
}
}

View File

@@ -85,7 +85,10 @@ type Progress interface {
}
func New(name string, flags int, perm os.FileMode) (Progress, error) {
if f, e := os.OpenFile(name, flags, perm); e != nil {
// #nosec
f, e := os.OpenFile(name, flags, perm)
if e != nil {
return nil, e
} else {
return &progress{
@@ -99,7 +102,10 @@ func New(name string, flags int, perm os.FileMode) (Progress, error) {
}
func Unique(basePath, pattern string) (Progress, error) {
if f, e := os.CreateTemp(basePath, pattern); e != nil {
// #nosec
f, e := os.CreateTemp(basePath, pattern)
if e != nil {
return nil, e
} else {
return &progress{
@@ -113,7 +119,10 @@ func Unique(basePath, pattern string) (Progress, error) {
}
func Temp(pattern string) (Progress, error) {
if f, e := os.CreateTemp("", pattern); e != nil {
// #nosec
f, e := os.CreateTemp("", pattern)
if e != nil {
return nil, e
} else {
return &progress{
@@ -127,7 +136,10 @@ func Temp(pattern string) (Progress, error) {
}
func Open(name string) (Progress, error) {
if f, e := os.Open(name); e != nil {
// #nosec
f, e := os.Open(name)
if e != nil {
return nil, e
} else {
return &progress{
@@ -141,7 +153,10 @@ func Open(name string) (Progress, error) {
}
func Create(name string) (Progress, error) {
if f, e := os.Create(name); e != nil {
// #nosec
f, e := os.Create(name)
if e != nil {
return nil, e
} else {
return &progress{

132
go.mod
View File

@@ -2,25 +2,26 @@ module github.com/nabbar/golib
go 1.21
toolchain go1.21.1
toolchain go1.21.3
require (
github.com/aws/aws-sdk-go-v2 v1.21.2
github.com/aws/aws-sdk-go-v2/config v1.18.45
github.com/aws/aws-sdk-go-v2/credentials v1.13.43
github.com/aws/aws-sdk-go-v2/service/iam v1.22.7
github.com/aws/aws-sdk-go-v2/service/s3 v1.40.2
github.com/bits-and-blooms/bitset v1.10.0
github.com/aws/aws-sdk-go-v2 v1.23.1
github.com/aws/aws-sdk-go-v2/config v1.25.4
github.com/aws/aws-sdk-go-v2/credentials v1.16.3
github.com/aws/aws-sdk-go-v2/service/iam v1.27.3
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1
github.com/aws/smithy-go v1.17.0
github.com/bits-and-blooms/bitset v1.11.0
github.com/c-bata/go-prompt v0.2.6
github.com/fatih/color v1.15.0
github.com/fsnotify/fsnotify v1.6.0
github.com/fatih/color v1.16.0
github.com/fsnotify/fsnotify v1.7.0
github.com/fxamacker/cbor/v2 v2.5.0
github.com/gin-gonic/gin v1.9.1
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-playground/validator/v10 v10.15.5
github.com/go-playground/validator/v10 v10.16.0
github.com/google/go-github/v33 v33.0.0
github.com/hashicorp/go-hclog v1.5.0
github.com/hashicorp/go-retryablehttp v0.7.4
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/jlaffaye/ftp v0.2.0
@@ -29,34 +30,34 @@ require (
github.com/mattn/go-colorable v0.1.13
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/nats-io/jwt/v2 v2.5.2
github.com/nats-io/nats-server/v2 v2.10.3
github.com/nats-io/nats.go v1.30.2
github.com/nutsdb/nutsdb v0.14.1
github.com/onsi/ginkgo/v2 v2.13.0
github.com/onsi/gomega v1.28.0
github.com/nats-io/jwt/v2 v2.5.3
github.com/nats-io/nats-server/v2 v2.10.5
github.com/nats-io/nats.go v1.31.0
github.com/nutsdb/nutsdb v0.14.3
github.com/onsi/ginkgo/v2 v2.13.1
github.com/onsi/gomega v1.30.0
github.com/pelletier/go-toml v1.9.5
github.com/prometheus/client_golang v1.17.0
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/cobra v1.8.0
github.com/spf13/jwalterweatherman v1.1.0
github.com/spf13/viper v1.17.0
github.com/ugorji/go/codec v1.2.11
github.com/vbauerster/mpb/v8 v8.6.2
github.com/xanzy/go-gitlab v0.93.1
github.com/xanzy/go-gitlab v0.94.0
github.com/xhit/go-simple-mail v2.2.2+incompatible
github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.13.0
golang.org/x/sync v0.4.0
golang.org/x/sys v0.13.0
golang.org/x/term v0.13.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/net v0.18.0
golang.org/x/oauth2 v0.14.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.14.0
golang.org/x/term v0.14.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/clickhouse v0.5.1
gorm.io/driver/mysql v1.5.2
gorm.io/driver/postgres v1.5.3
gorm.io/driver/postgres v1.5.4
gorm.io/driver/sqlite v1.5.4
gorm.io/driver/sqlserver v1.5.2
gorm.io/gorm v1.25.5
@@ -65,7 +66,7 @@ require (
require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/ClickHouse/ch-go v0.58.2 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.14.3 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.15.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
@@ -78,38 +79,36 @@ require (
github.com/antlabs/stl v0.0.1 // indirect
github.com/antlabs/timer v0.0.11 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.15 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.38 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect
github.com/aws/smithy-go v1.15.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/bytedance/sonic v1.10.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/getsentry/sentry-go v0.25.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-faster/city v1.0.1 // indirect
github.com/go-faster/errors v0.6.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-faster/errors v0.7.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -125,15 +124,15 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-sockaddr v1.0.5 // indirect
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/memberlist v0.5.0 // indirect
@@ -142,32 +141,33 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jackc/pgx/v5 v5.5.0 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/ratelimit v1.0.2 // indirect
github.com/klauspost/compress v1.17.1 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/klauspost/compress v1.17.3 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lni/goutils v1.3.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/mattn/go-sqlite3 v1.14.18 // indirect
github.com/mattn/go-tty v0.0.5 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/microsoft/go-mssqldb v1.6.0 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/miekg/dns v1.1.57 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nats-io/nkeys v0.4.5 // indirect
github.com/nats-io/nkeys v0.4.6 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/paulmach/orb v0.10.0 // indirect
@@ -176,7 +176,7 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
@@ -201,15 +201,15 @@ require (
github.com/x448/float16 v0.8.4 // indirect
github.com/xujiajun/mmap-go v1.0.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.org/x/arch v0.6.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.4.0 // indirect
golang.org/x/tools v0.15.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

View File

@@ -93,6 +93,7 @@ func (o *srv) setServer(ctx context.Context) error {
var stdlog = o.logger()
// #nosec
s := &http.Server{
Addr: bind,
Handler: o.HandlerLoadFct(),

View File

@@ -56,6 +56,8 @@ func (o *optServer) initServer(s *http.Server) liberr.Error {
if o.ReadHeaderTimeout > 0 {
s.ReadHeaderTimeout = o.ReadHeaderTimeout
} else {
s.ReadHeaderTimeout = 30 * time.Second
}
if o.WriteTimeout > 0 {

View File

@@ -57,7 +57,11 @@ func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os.
return os.MkdirAll(path, permDir)
} else if err = PathCheckCreate(false, filepath.Dir(path), permFile, permDir); err != nil {
return err
} else if hf, e := os.Create(path); e != nil {
}
// #nosec
hf, e := os.Create(path)
if e != nil {
return e
} else {
_ = hf.Close()

View File

@@ -72,6 +72,23 @@ func NewLDAP(ctx context.Context, cnf *Config, attributes []string) (*HelperLDAP
}, nil
}
func (lc *HelperLDAP) Clone() *HelperLDAP {
var att = make([]string, 0)
copy(att, lc.Attributes)
return &HelperLDAP{
Attributes: att,
conn: nil,
config: lc.config.Clone(),
tlsConfig: lc.tlsConfig.Clone(),
tlsMode: lc.tlsMode,
bindDN: lc.bindDN,
bindPass: lc.bindPass,
ctx: lc.ctx,
log: lc.log,
}
}
// SetLogger is used to specify the logger to be used for debug messgae
func (lc *HelperLDAP) SetLogger(fct liblog.FuncLog) {
lc.log = fct
@@ -242,7 +259,7 @@ func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
defer func() {
if l != nil {
l.Close()
_ = l.Close()
}
}()
@@ -306,7 +323,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
l, err = lc.dialTLS()
if err != nil {
if l != nil {
l.Close()
_ = l.Close()
}
return err
}
@@ -316,7 +333,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
l, err = lc.dial()
if err != nil {
if l != nil {
l.Close()
_ = l.Close()
}
return err
}
@@ -326,7 +343,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
err = lc.starttls(l)
if err != nil {
if l != nil {
l.Close()
_ = l.Close()
}
return err
}
@@ -348,7 +365,7 @@ func (lc *HelperLDAP) Check() liberr.Error {
if lc.conn == nil {
defer func() {
if lc.conn != nil {
lc.conn.Close()
_ = lc.conn.Close()
lc.conn = nil
}
}()
@@ -369,7 +386,7 @@ func (lc *HelperLDAP) Close() {
}
if lc.conn != nil {
lc.conn.Close()
_ = lc.conn.Close()
lc.conn = nil
}
}

View File

@@ -99,7 +99,10 @@ func New(opt logcfg.OptionsFile, format logrus.Formatter) (HookFile, error) {
}
}
if h, e := os.OpenFile(opt.Filepath, flags, opt.FileMode); e != nil {
// #nosec
h, e := os.OpenFile(opt.Filepath, flags, opt.FileMode)
if e != nil {
return nil, e
} else if _, e = h.Seek(0, io.SeekEnd); e != nil {
_ = h.Close()

View File

@@ -74,7 +74,10 @@ func (o *hkf) writeBuffer(buf *bytes.Buffer) error {
}
}()
if h, e = os.OpenFile(p, f, m); e != nil {
// #nosec
h, e = os.OpenFile(p, f, m)
if e != nil {
return e
} else if _, e = h.Seek(0, io.SeekEnd); e != nil {
return e

View File

@@ -104,6 +104,7 @@ func (c Config) LogConfigJson() liberr.Error {
return ErrorConfigInvalidFilePath.Error(e)
}
// #nosec
f, e := os.OpenFile(c.Logs.LogFile, os.O_APPEND|os.O_WRONLY, permFile)
if e != nil {
return ErrorConfigInvalidFilePath.Error(e)
@@ -1054,6 +1055,7 @@ func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts,
}
} else {
cfg.NoTLS = true
// #nosec
cfg.TLSConfig = &tls.Config{}
cfg.HandshakeTimeout = 0
}
@@ -1092,6 +1094,7 @@ func (c ConfigMQTT) makeOpt(defTls libtls.TLSConfig) (natsrv.MQTTOpts, liberr.Er
cfg.TLSTimeout = float64(c.TLSTimeout) / float64(time.Second)
}
} else {
// #nosec
cfg.TLSConfig = &tls.Config{}
cfg.TLSTimeout = 0
}

View File

@@ -28,12 +28,19 @@
package protocol
import (
"bytes"
"fmt"
"gopkg.in/yaml.v3"
)
const (
dblQuote = "\""
smpQuote = "'"
)
func (s *NetworkProtocol) unmarshall(val []byte) error {
val = bytes.Trim(bytes.Trim(val, smpQuote), dblQuote)
*s = ParseBytes(val)
return nil
}

View File

@@ -26,8 +26,8 @@
package password
import (
"math/rand"
"time"
"crypto/rand"
"math/big"
)
const letterBytes = "abcdefghijklmnopqrstuvwxyz,;:!?./*%^$&\"'(-_)=+~#{[|`\\^@]}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -41,36 +41,32 @@ const (
loopRandMaxLen = 10
)
func randStringBytesMaskImprSrc(n int) string {
var src = rand.NewSource(time.Now().UnixNano())
func randIdx() int {
size := int64(len(letterBytes))
for n := 0; n < 100; n++ {
if i, e := rand.Int(rand.Reader, big.NewInt(size+1)); e != nil {
return 0
} else {
j := i.Int64()
if j > 0 && j < size {
return int(j)
}
}
}
return 0
}
func Generate(n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
for i := n - 1; i >= 0; {
b[i] = letterBytes[randIdx()]
i--
}
return string(b)
}
// Generate Generate a random string could be used as password.
// The len is defined by given 'n' parameters.
func Generate(n int) string {
if n > loopRandMaxLen {
var s = ""
for i := n; i > 0; i -= loopRandMaxLen {
s += randStringBytesMaskImprSrc(loopRandMaxLen)
}
return s[0 : n-1]
}
return randStringBytesMaskImprSrc(n)
}

View File

@@ -41,7 +41,8 @@ const (
)
var (
_maxFloat = uint64(math.Ceil(math.MaxFloat64))
_maxFloat64 = uint64(math.Ceil(math.MaxFloat64))
_maxFloat32 = uint64(math.Ceil(math.MaxFloat32))
)
func (s Size) String() string {
@@ -63,12 +64,48 @@ func (s Size) Int64() int64 {
return int64(s)
}
func (s Size) Int32() int32 {
if uint64(s) > math.MaxInt32 {
// overflow
return math.MaxInt32
}
return int32(s)
}
func (s Size) Int() int {
if uint64(s) > math.MaxInt {
// overflow
return math.MaxInt
}
return int(s)
}
func (s Size) Uint64() uint64 {
return uint64(s)
}
func (s Size) Uint32() uint32 {
if uint64(s) > math.MaxUint32 {
// overflow
return math.MaxUint32
}
return uint32(s)
}
func (s Size) Uint() uint {
if uint64(s) > math.MaxUint {
// overflow
return math.MaxUint
}
return uint(s)
}
func (s Size) Float64() float64 {
if uint64(s) > _maxFloat {
if uint64(s) > _maxFloat64 {
// overflow
return math.MaxFloat64
}
@@ -76,6 +113,15 @@ func (s Size) Float64() float64 {
return float64(s)
}
func (s Size) Float32() float32 {
if uint64(s) > _maxFloat32 {
// overflow
return math.MaxFloat32
}
return float32(s)
}
func (s Size) Format(format string) string {
switch {
case SizeExa.isMax(s):

View File

@@ -27,6 +27,8 @@
package bytes
import "math"
type Size uint64
const (
@@ -65,6 +67,18 @@ func SizeFromInt64(val int64) Size {
return Size(v)
}
func SizeFromFloat64(val float64) Size {
val = math.Floor(val)
if val > math.MaxUint64 {
return Size(uint64(math.MaxUint64))
} else if -val > math.MaxUint64 {
return Size(uint64(math.MaxUint64))
} else {
return Size(uint64(val))
}
}
func Parse(s string) (Size, error) {
return parseString(s)
}

View File

@@ -69,10 +69,10 @@ func (s Size) isMax(size Size) bool {
}
func (s Size) sizeByUnit(unit Size) float64 {
if s > 0 && uint64(s/unit) > _maxFloat {
if s > 0 && uint64(s/unit) > _maxFloat64 {
// overflow
return math.MaxFloat64
} else if s < 0 && uint64(-s/unit) > _maxFloat {
} else if s < 0 && uint64(-s/unit) > _maxFloat64 {
// overflow
return -math.MaxFloat64
} else {

View File

@@ -28,9 +28,10 @@ package config
import (
"os"
"time"
libdur "github.com/nabbar/golib/duration"
libptc "github.com/nabbar/golib/network/protocol"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
scksrv "github.com/nabbar/golib/socket/server"
)
@@ -39,17 +40,17 @@ type ServerConfig struct {
Network libptc.NetworkProtocol ``
Address string
PermFile os.FileMode
BuffSizeRead int32
TimeoutRead time.Duration
TimeoutWrite time.Duration
BuffSizeRead libsiz.Size
TimeoutRead libdur.Duration
TimeoutWrite libdur.Duration
}
func (o ServerConfig) New(handler libsck.Handler) (libsck.Server, error) {
s, e := scksrv.New(handler, o.Network, o.BuffSizeRead, o.Address, o.PermFile)
if e != nil {
s.SetReadTimeout(o.TimeoutRead)
s.SetWriteTimeout(o.TimeoutWrite)
s.SetReadTimeout(o.TimeoutRead.Time())
s.SetWriteTimeout(o.TimeoutWrite.Time())
}
return s, e

View File

@@ -31,6 +31,8 @@ import (
"io"
"net"
"time"
libtls "github.com/nabbar/golib/certificates"
)
const DefaultBufferSize = 32 * 1024
@@ -48,7 +50,31 @@ const (
ConnectionClose
)
func (c ConnState) String() string {
switch c {
case ConnectionDial:
return "Dial Connection"
case ConnectionNew:
return "New Connection"
case ConnectionRead:
return "Read Incoming Stream"
case ConnectionCloseRead:
return "Close Incoming Stream"
case ConnectionHandler:
return "Run Handler"
case ConnectionWrite:
return "Write Outgoing Steam"
case ConnectionCloseWrite:
return "Close Outgoing Stream"
case ConnectionClose:
return "Close Connection"
}
return "unknown connection state"
}
type FuncError func(e error)
type FuncInfoSrv func(msg string)
type FuncInfo func(local, remote net.Addr, state ConnState)
type Handler func(request io.Reader, response io.Writer)
type Response func(r io.Reader)
@@ -56,10 +82,12 @@ type Response func(r io.Reader)
type Server interface {
RegisterFuncError(f FuncError)
RegisterFuncInfo(f FuncInfo)
RegisterFuncInfoServer(f FuncInfoSrv)
SetReadTimeout(d time.Duration)
SetWriteTimeout(d time.Duration)
SetTLS(enable bool, config libtls.TLSConfig) error
Listen(ctx context.Context) error
Shutdown()
Done() <-chan struct{}

View File

@@ -36,13 +36,14 @@ import (
"strings"
libptc "github.com/nabbar/golib/network/protocol"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
scksrt "github.com/nabbar/golib/socket/server/tcp"
scksru "github.com/nabbar/golib/socket/server/udp"
scksrx "github.com/nabbar/golib/socket/server/unix"
)
func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead int32, address string, perm os.FileMode) (libsck.Server, error) {
func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead libsiz.Size, address string, perm os.FileMode) (libsck.Server, error) {
switch proto {
case libptc.NetworkUnix:
if strings.EqualFold(runtime.GOOS, "linux") {

View File

@@ -34,12 +34,13 @@ import (
"os"
libptc "github.com/nabbar/golib/network/protocol"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
scksrt "github.com/nabbar/golib/socket/server/tcp"
scksru "github.com/nabbar/golib/socket/server/udp"
)
func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead int32, address string, perm os.FileMode) (libsck.Server, error) {
func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead libsiz.Size, address string, perm os.FileMode) (libsck.Server, error) {
switch proto {
case libptc.NetworkTCP, libptc.NetworkTCP4, libptc.NetworkTCP6:
s := scksrt.New(handler, sizeBufferRead)

View File

@@ -29,6 +29,7 @@ package tcp
import (
"sync/atomic"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
)
@@ -37,7 +38,7 @@ type ServerTcp interface {
RegisterServer(address string) error
}
func New(h libsck.Handler, sizeBuffRead int32) ServerTcp {
func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerTcp {
c := new(atomic.Value)
c.Store(make(chan []byte))
@@ -48,17 +49,20 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerTcp {
f.Store(h)
sr := new(atomic.Int32)
sr.Store(sizeBuffRead)
sr.Store(sizeBuffRead.Int32())
return &srv{
l: nil,
t: new(atomic.Value),
h: f,
c: c,
s: s,
e: new(atomic.Value),
i: new(atomic.Value),
fe: new(atomic.Value),
fi: new(atomic.Value),
fs: new(atomic.Value),
tr: new(atomic.Value),
tw: new(atomic.Value),
sr: sr,
ad: new(atomic.Value),
}
}

View File

@@ -29,6 +29,7 @@ package tcp
import (
"bytes"
"context"
"crypto/tls"
"io"
"net"
"net/url"
@@ -83,7 +84,16 @@ func (o *srv) Listen(ctx context.Context) error {
if a == nil {
return ErrInvalidAddress
} else if l, e = net.Listen(libptc.NetworkTCP.Code(), a.Host); e != nil {
} else if t := o.getTLS(); t == nil {
o.fctInfoSrv("starting listening socket '%s %s'", libptc.NetworkTCP.String(), a.Host)
l, e = net.Listen(libptc.NetworkTCP.Code(), a.Host)
} else {
o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkTCP.String(), a.Host)
l, e = tls.Listen(libptc.NetworkTCP.Code(), a.Host, t)
}
if e != nil {
o.fctError(e)
return e
}

View File

@@ -27,12 +27,15 @@
package tcp
import (
"crypto/tls"
"fmt"
"net"
"net/url"
"strconv"
"sync/atomic"
"time"
libtls "github.com/nabbar/golib/certificates"
libsck "github.com/nabbar/golib/socket"
)
@@ -45,14 +48,21 @@ func init() {
close(closedChanStruct)
}
type data struct {
data any
}
type srv struct {
l net.Listener
t *atomic.Value // tls config
h *atomic.Value // handler
c *atomic.Value // chan []byte
s *atomic.Value // chan struct{}
e *atomic.Value // function error
i *atomic.Value // function info
fe *atomic.Value // function error
fi *atomic.Value // function info
fs *atomic.Value // function info server
tr *atomic.Value // connection read timeout
tw *atomic.Value // connection write timeout
@@ -81,12 +91,31 @@ func (o *srv) Shutdown() {
}
}
func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error {
if !enable {
// #nosec
o.t.Store(&tls.Config{})
return nil
}
if config == nil {
return fmt.Errorf("invalid tls config")
} else if l := config.GetCertificatePair(); len(l) < 1 {
return fmt.Errorf("invalid tls config, missing certificates pair")
} else if t := config.TlsConfig(""); t == nil {
return fmt.Errorf("invalid tls config")
} else {
o.t.Store(t)
return nil
}
}
func (o *srv) RegisterFuncError(f libsck.FuncError) {
if o == nil {
return
}
o.e.Store(f)
o.fe.Store(f)
}
func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
@@ -94,7 +123,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
return
}
o.i.Store(f)
o.fi.Store(f)
}
func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) {
if o == nil {
return
}
o.fs.Store(f)
}
func (o *srv) SetReadTimeout(d time.Duration) {
@@ -137,7 +174,7 @@ func (o *srv) fctError(e error) {
return
}
v := o.e.Load()
v := o.fe.Load()
if v != nil {
v.(libsck.FuncError)(e)
}
@@ -148,12 +185,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) {
return
}
v := o.i.Load()
v := o.fi.Load()
if v != nil {
v.(libsck.FuncInfo)(local, remote, state)
}
}
func (o *srv) fctInfoSrv(msg string, args ...interface{}) {
if o == nil {
return
}
v := o.fs.Load()
if v != nil {
v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...))
}
}
func (o *srv) handler() libsck.Handler {
if o == nil {
return nil
@@ -166,3 +214,17 @@ func (o *srv) handler() libsck.Handler {
return nil
}
func (o *srv) getTLS() *tls.Config {
i := o.t.Load()
if i == nil {
return nil
} else if t, k := i.(*tls.Config); !k {
return nil
} else if len(t.Certificates) < 1 {
return nil
} else {
return t
}
}

View File

@@ -29,6 +29,7 @@ package udp
import (
"sync/atomic"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
)
@@ -37,7 +38,7 @@ type ServerTcp interface {
RegisterServer(address string) error
}
func New(h libsck.Handler, sizeBuffRead int32) ServerTcp {
func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerTcp {
c := new(atomic.Value)
c.Store(make(chan []byte))
@@ -48,17 +49,19 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerTcp {
f.Store(h)
sr := new(atomic.Int32)
sr.Store(sizeBuffRead)
sr.Store(sizeBuffRead.Int32())
return &srv{
l: nil,
h: f,
c: c,
s: s,
e: new(atomic.Value),
i: new(atomic.Value),
fe: new(atomic.Value),
fi: new(atomic.Value),
fs: new(atomic.Value),
tr: new(atomic.Value),
tw: new(atomic.Value),
sr: sr,
ad: new(atomic.Value),
}
}

View File

@@ -93,6 +93,7 @@ func (o *srv) Listen(ctx context.Context) error {
}
}
o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkUDP.String(), a.Host)
defer fctClose()
// Accept new connection or stop if context or shutdown trigger

View File

@@ -27,12 +27,14 @@
package udp
import (
"fmt"
"net"
"net/url"
"strconv"
"sync/atomic"
"time"
libtls "github.com/nabbar/golib/certificates"
libsck "github.com/nabbar/golib/socket"
)
@@ -51,8 +53,10 @@ type srv struct {
h *atomic.Value // handler
c *atomic.Value // chan []byte
s *atomic.Value // chan struct{}
e *atomic.Value // function error
i *atomic.Value // function info
fe *atomic.Value // function error
fi *atomic.Value // function info
fs *atomic.Value // function info server
tr *atomic.Value // connection read timeout
tw *atomic.Value // connection write timeout
@@ -81,12 +85,16 @@ func (o *srv) Shutdown() {
}
}
func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error {
return nil
}
func (o *srv) RegisterFuncError(f libsck.FuncError) {
if o == nil {
return
}
o.e.Store(f)
o.fe.Store(f)
}
func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
@@ -94,7 +102,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
return
}
o.i.Store(f)
o.fi.Store(f)
}
func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) {
if o == nil {
return
}
o.fs.Store(f)
}
func (o *srv) SetReadTimeout(d time.Duration) {
@@ -137,7 +153,7 @@ func (o *srv) fctError(e error) {
return
}
v := o.e.Load()
v := o.fe.Load()
if v != nil {
v.(libsck.FuncError)(e)
}
@@ -148,12 +164,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) {
return
}
v := o.i.Load()
v := o.fi.Load()
if v != nil {
v.(libsck.FuncInfo)(local, remote, state)
}
}
func (o *srv) fctInfoSrv(msg string, args ...interface{}) {
if o == nil {
return
}
v := o.fs.Load()
if v != nil {
v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...))
}
}
func (o *srv) handler() libsck.Handler {
if o == nil {
return nil

View File

@@ -33,6 +33,7 @@ import (
"os"
"sync/atomic"
libsiz "github.com/nabbar/golib/size"
libsck "github.com/nabbar/golib/socket"
)
@@ -41,7 +42,7 @@ type ServerUnix interface {
RegisterSocket(unixFile string, perm os.FileMode)
}
func New(h libsck.Handler, sizeBuffRead int32) ServerUnix {
func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerUnix {
c := new(atomic.Value)
c.Store(make(chan []byte))
@@ -51,26 +52,30 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerUnix {
f := new(atomic.Value)
f.Store(h)
// socket read buff size
sr := new(atomic.Int32)
sr.Store(sizeBuffRead)
sr.Store(sizeBuffRead.Int32())
fp := new(atomic.Value)
fp.Store("")
// socket file
sf := new(atomic.Value)
sf.Store("")
pe := new(atomic.Int64)
pe.Store(0)
// socket permission
sp := new(atomic.Int64)
sp.Store(0)
return &srv{
l: nil,
h: f,
c: c,
s: s,
e: new(atomic.Value),
i: new(atomic.Value),
fe: new(atomic.Value),
fi: new(atomic.Value),
fs: new(atomic.Value),
tr: new(atomic.Value),
tw: new(atomic.Value),
sr: sr,
fs: fp,
fp: pe,
sf: sf,
sp: sp,
}
}

View File

@@ -82,7 +82,7 @@ func (o *srv) buffRead() *bytes.Buffer {
}
func (o *srv) getSocketFile() (string, error) {
f := o.fs.Load()
f := o.sf.Load()
if f != nil {
return o.checkFile(f.(string))
}
@@ -91,7 +91,7 @@ func (o *srv) getSocketFile() (string, error) {
}
func (o *srv) getSocketPerm() os.FileMode {
p := o.fp.Load()
p := o.sp.Load()
if p > 0 {
return os.FileMode(p)
}
@@ -149,6 +149,7 @@ func (o *srv) Listen(ctx context.Context) error {
}
}
o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkUnix.String(), unixFile)
defer fctClose()
if i.Mode() != perm {

View File

@@ -30,11 +30,13 @@
package unix
import (
"fmt"
"net"
"os"
"sync/atomic"
"time"
libtls "github.com/nabbar/golib/certificates"
libsck "github.com/nabbar/golib/socket"
)
@@ -53,14 +55,17 @@ type srv struct {
h *atomic.Value // handler
c *atomic.Value // chan []byte
s *atomic.Value // chan struct{}
e *atomic.Value // function error
i *atomic.Value // function info
fe *atomic.Value // function error
fi *atomic.Value // function info
fs *atomic.Value // function info server
tr *atomic.Value // connection read timeout
tw *atomic.Value // connection write timeout
sr *atomic.Int32 // read buffer size
fs *atomic.Value // file unix socket
fp *atomic.Int64 // file unix perm
sf *atomic.Value // file unix socket
sp *atomic.Int64 // file unix perm
}
func (o *srv) Done() <-chan struct{} {
@@ -83,12 +88,16 @@ func (o *srv) Shutdown() {
}
}
func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error {
return nil
}
func (o *srv) RegisterFuncError(f libsck.FuncError) {
if o == nil {
return
}
o.e.Store(f)
o.fe.Store(f)
}
func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
@@ -96,7 +105,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) {
return
}
o.i.Store(f)
o.fi.Store(f)
}
func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) {
if o == nil {
return
}
o.fs.Store(f)
}
func (o *srv) SetReadTimeout(d time.Duration) {
@@ -116,8 +133,8 @@ func (o *srv) SetWriteTimeout(d time.Duration) {
}
func (o *srv) RegisterSocket(unixFile string, perm os.FileMode) {
o.fs.Store(unixFile)
o.fp.Store(int64(perm))
o.sf.Store(unixFile)
o.sp.Store(int64(perm))
}
func (o *srv) fctError(e error) {
@@ -125,7 +142,7 @@ func (o *srv) fctError(e error) {
return
}
v := o.e.Load()
v := o.fe.Load()
if v != nil {
v.(libsck.FuncError)(e)
}
@@ -136,12 +153,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) {
return
}
v := o.i.Load()
v := o.fi.Load()
if v != nil {
v.(libsck.FuncInfo)(local, remote, state)
}
}
func (o *srv) fctInfoSrv(msg string, args ...interface{}) {
if o == nil {
return
}
v := o.fs.Load()
if v != nil {
v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...))
}
}
func (o *srv) handler() libsck.Handler {
if o == nil {
return nil