From 6a63b4763380ff52008e9cd55a18b99bd08d86cc Mon Sep 17 00:00:00 2001 From: Mikhail Knyazhev Date: Fri, 21 Aug 2026 00:41:05 +0300 Subject: [PATCH] upgrade vendors && refactoring --- .github/workflows/ci.yml | 2 +- .golangci.yml | 216 ++++++-------------------------- LICENSE | 2 +- Makefile | 2 +- address/common.go | 2 +- address/common_test.go | 2 +- client/adapter.go | 2 +- client/client.go | 12 +- client/config.go | 2 +- client/tls.go | 10 +- epoll/common.go | 38 ------ epoll/epoll.go | 229 ---------------------------------- epoll/epoll_net.go | 37 ------ epoll/options.go | 33 ----- epoll/server_tcp.go | 118 ------------------ errs/errs.go | 2 +- examples/client/main.go | 17 +-- examples/epoll-server/main.go | 37 ------ examples/server/main.go | 10 +- fd/fd.go | 2 +- go.mod | 35 ++---- go.sum | 86 +++++-------- internal/datapool.go | 8 +- internal/deadline.go | 16 ++- internal/errors.go | 2 +- internal/network.go | 2 +- internal/packet.go | 2 +- internal/packet_test.go | 8 +- internal/tls.go | 2 +- listen/listener.go | 2 +- listen/tls.go | 12 +- server/config.go | 12 +- server/server.go | 38 +++--- 33 files changed, 174 insertions(+), 826 deletions(-) delete mode 100644 epoll/common.go delete mode 100644 epoll/epoll.go delete mode 100644 epoll/epoll_net.go delete mode 100644 epoll/options.go delete mode 100644 epoll/server_tcp.go delete mode 100644 examples/epoll-server/main.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bea49eb..7270150 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: [ '1.23.6' ] + go: [ '1.26' ] steps: - uses: actions/checkout@v3 diff --git a/.golangci.yml b/.golangci.yml index 9c6a954..f2b16a7 100755 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,201 +1,61 @@ +version: "2" run: - go: "1.23.6" - concurrency: 4 + go: "1.26" timeout: 5m tests: false issues-exit-code: 1 modules-download-mode: readonly + allow-parallel-runners: true issues: - exclude-use-default: false - max-issues-per-linter: 100 - max-same-issues: 4 + max-issues-per-linter: 0 + max-same-issues: 0 new: false - exclude-files: - - ".+_test.go" - exclude-dirs: - - "vendor$" + fix: false output: formats: - - format: line-number - sort-results: true + text: + print-linter-name: true + print-issued-lines: true -linters-settings: - govet: - check-shadowing: true - enable: - - asmdecl - - assign - - atomic - - atomicalign - - bools - - buildtag - - cgocall - - composites - - copylocks - - deepequalerrors - - errorsas - - findcall - - framepointer - - httpresponse - - ifaceassert - - loopclosure - - lostcancel - - nilfunc - - nilness - - printf - - reflectvaluecompare - - shadow - - shift - - sigchanyzer - - sortslice - - stdmethods - - stringintconv - - structtag - - testinggoroutine - - tests - - unmarshal - - unreachable - - unsafeptr - - unusedresult - - unusedwrite - disable: - - fieldalignment - gofmt: - simplify: true - errcheck: - check-type-assertions: true - check-blank: true - gocyclo: - min-complexity: 30 - misspell: - locale: US - prealloc: - simple: true - range-loops: true - for-loops: true - unparam: - check-exported: false - gci: - skip-generated: true - custom-order: false - gosec: - includes: - - G101 # Look for hard coded credentials - - G102 # Bind to all interfaces - - G103 # Audit the use of unsafe block - - G104 # Audit errors not checked - - G106 # Audit the use of ssh.InsecureIgnoreHostKey - - G107 # Url provided to HTTP request as taint input - - G108 # Profiling endpoint automatically exposed on /debug/pprof - - G109 # Potential Integer overflow made by strconv.Atoi result conversion to int16/32 - - G110 # Potential DoS vulnerability via decompression bomb - - G111 # Potential directory traversal - - G112 # Potential slowloris attack - - G113 # Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772) - - G114 # Use of net/http serve function that has no support for setting timeouts - - G201 # SQL query construction using format string - - G202 # SQL query construction using string concatenation - - G203 # Use of unescaped data in HTML templates - - G204 # Audit use of command execution - - G301 # Poor file permissions used when creating a directory - - G302 # Poor file permissions used with chmod - - G303 # Creating tempfile using a predictable path - - G304 # File path provided as taint input - - G305 # File traversal when extracting zip/tar archive - - G306 # Poor file permissions used when writing to a new file - - G307 # Deferring a method which returns an error - - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - - G402 # Look for bad TLS connection settings - - G403 # Ensure minimum RSA key length of 2048 bits - - G404 # Insecure random number source (rand) - - G501 # Import blocklist: crypto/md5 - - G502 # Import blocklist: crypto/des - - G503 # Import blocklist: crypto/rc4 - - G504 # Import blocklist: net/http/cgi - - G505 # Import blocklist: crypto/sha1 - - G601 # Implicit memory aliasing of items from a range statement - excludes: - - G101 # Look for hard coded credentials - - G102 # Bind to all interfaces - - G103 # Audit the use of unsafe block - - G104 # Audit errors not checked - - G106 # Audit the use of ssh.InsecureIgnoreHostKey - - G107 # Url provided to HTTP request as taint input - - G108 # Profiling endpoint automatically exposed on /debug/pprof - - G109 # Potential Integer overflow made by strconv.Atoi result conversion to int16/32 - - G110 # Potential DoS vulnerability via decompression bomb - - G111 # Potential directory traversal - - G112 # Potential slowloris attack - - G113 # Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772) - - G114 # Use of net/http serve function that has no support for setting timeouts - - G201 # SQL query construction using format string - - G202 # SQL query construction using string concatenation - - G203 # Use of unescaped data in HTML templates - - G204 # Audit use of command execution - - G301 # Poor file permissions used when creating a directory - - G302 # Poor file permissions used with chmod - - G303 # Creating tempfile using a predictable path - - G304 # File path provided as taint input - - G305 # File traversal when extracting zip/tar archive - - G306 # Poor file permissions used when writing to a new file - - G307 # Deferring a method which returns an error - - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - - G402 # Look for bad TLS connection settings - - G403 # Ensure minimum RSA key length of 2048 bits - - G404 # Insecure random number source (rand) - - G501 # Import blocklist: crypto/md5 - - G502 # Import blocklist: crypto/des - - G503 # Import blocklist: crypto/rc4 - - G504 # Import blocklist: net/http/cgi - - G505 # Import blocklist: crypto/sha1 - - G601 # Implicit memory aliasing of items from a range statement - exclude-generated: true - severity: medium - confidence: medium - concurrency: 12 - config: - global: - nosec: true - "#nosec": "#my-custom-nosec" - show-ignored: true - audit: true - G101: - pattern: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" - ignore_entropy: false - entropy_threshold: "80.0" - per_char_threshold: "3.0" - truncate: "32" - G104: - fmt: - - Fscanf - G111: - pattern: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" - G301: "0750" - G302: "0600" - G306: "0600" - - lll: - line-length: 130 - tab-width: 1 - staticcheck: - go: "1.15" - # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks - # Default: ["*"] - checks: [ "*", "-SA1019" ] +formatters: + exclusions: + paths: + - vendors/ + enable: + - gofmt + - goimports linters: - disable-all: true + settings: + staticcheck: + checks: + - all + - -S1023 + - -ST1000 + - -ST1003 + - -ST1020 + gosec: + excludes: + - G104 + - G115 + - G301 + - G304 + - G306 + - G501 + - G505 + exclusions: + paths: + - vendors/ + default: none enable: - govet - - gofmt - errcheck - misspell - gocyclo - ineffassign - - goimports - unparam - unused - prealloc @@ -206,5 +66,3 @@ linters: - errorlint - bodyclose - gosec - - lll - fast: false diff --git a/LICENSE b/LICENSE index 93caddc..09b2131 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2024-2025, Mikhail Knyazhev +Copyright (c) 2024-2026, Mikhail Knyazhev Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/Makefile b/Makefile index 6c679e3..c0c5913 100755 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ SHELL=/bin/bash .PHONY: install install: - go install go.osspkg.com/goppy/v2/cmd/goppy@latest + go install go.osspkg.com/goppy/v3/cmd/goppy@latest goppy setup-lib .PHONY: lint diff --git a/address/common.go b/address/common.go index 15347b6..ecf5c04 100644 --- a/address/common.go +++ b/address/common.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/address/common_test.go b/address/common_test.go index 48decfc..d59f254 100644 --- a/address/common_test.go +++ b/address/common_test.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/client/adapter.go b/client/adapter.go index 49cb8c7..ce1126b 100644 --- a/client/adapter.go +++ b/client/adapter.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/client/client.go b/client/client.go index 3ebbc28..ccf6da3 100644 --- a/client/client.go +++ b/client/client.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -13,8 +13,8 @@ import ( "net" "github.com/quic-go/quic-go" - "go.osspkg.com/algorithms/control" "go.osspkg.com/errors" + "go.osspkg.com/syncing" "go.osspkg.com/network/internal" ) @@ -27,7 +27,7 @@ type ( _client struct { conf Config tls *tls.Config - sem control.Semaphore + sem syncing.Control } ) @@ -50,7 +50,7 @@ func New(c Config) (Client, error) { cli := &_client{ conf: c, - sem: control.NewSemaphore(c.MaxConns), + sem: syncing.NewControl(c.MaxConns), tls: tlsc, } @@ -98,7 +98,7 @@ func (v *_client) conn(ctx context.Context) (internal.Conn, error) { } func (v *_client) Call(ctx context.Context, handler func(ctx context.Context, w io.Writer, r io.Reader) error) (e error) { - v.sem.Acquire() + v.sem.Acquire(ctx) defer func() { v.sem.Release() }() conn, err := v.conn(ctx) @@ -106,7 +106,7 @@ func (v *_client) Call(ctx context.Context, handler func(ctx context.Context, w return err } - stop := internal.DeadlineUpdate(conn) + stop := internal.AutoUpdateDeadline(conn, 0) defer func() { stop() diff --git a/client/config.go b/client/config.go index f9b58fa..c1a80a8 100644 --- a/client/config.go +++ b/client/config.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/client/tls.go b/client/tls.go index 7c294de..779a9fc 100644 --- a/client/tls.go +++ b/client/tls.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -15,10 +15,10 @@ import ( ) type Certificate struct { - CAFile string `yaml:"ca_file"` - CertFile string `yaml:"cert_file"` - KeyFile string `yaml:"key_file"` - InsecureSkipVerify bool `yaml:"insecure_skip_verify"` + CAFile string `yaml:"ca_file,omitempty" unic:"ca_file,omitempty,desc='Адрес корневого сертификата'"` + CertFile string `yaml:"cert_file,omitempty" unic:"cert_file,omitempty,desc='Адрес публичного сертификата'"` + KeyFile string `yaml:"key_file,omitempty" unic:"key_file,omitempty,desc='Адрес приватного ключа'"` + InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty" unic:"insecure_skip_verify,omitempty,default='false',desc='Пропускать проверку корневых сертификатов'"` } func (c *Certificate) parse() (cert tls.Certificate, ca *x509.CertPool, err error) { diff --git a/epoll/common.go b/epoll/common.go deleted file mode 100644 index 6d496b0..0000000 --- a/epoll/common.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package epoll - -import ( - "bytes" - "io" - "strings" - - "go.osspkg.com/errors" - "go.osspkg.com/ioutils/pool" - "golang.org/x/sys/unix" -) - -const ( - epollEvents = unix.POLLIN | unix.POLLRDHUP | unix.POLLERR | unix.POLLHUP | unix.POLLNVAL -) - -var ( - connPool = pool.NewSlicePool[int32](0, 30) - buffPool = pool.New[*bytes.Buffer](func() *bytes.Buffer { - return bytes.NewBuffer(make([]byte, 0, 1024)) - }) -) - -func isClosedError(err error) bool { - if err == nil { - return false - } - if strings.Contains(err.Error(), "use of closed network connection") || - errors.Is(err, io.EOF) { - return true - } - return false -} diff --git a/epoll/epoll.go b/epoll/epoll.go deleted file mode 100644 index 711213a..0000000 --- a/epoll/epoll.go +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package epoll - -import ( - "context" - "fmt" - "net" - "sync" - "syscall" - - "go.osspkg.com/do" - "go.osspkg.com/errors" - "go.osspkg.com/ioutils" - "go.osspkg.com/logx" - "golang.org/x/sys/unix" - - netfd "go.osspkg.com/network/fd" -) - -type ( - _epoll struct { - fd int - pipe chan TConnect - conn map[int32]TConnect - events []unix.EpollEvent - cfg Option - mux sync.RWMutex - } - TEpoll interface { - Accept(c net.Conn) error - Listen(ctx context.Context) (err error) - } -) - -func New(c Option) (TEpoll, error) { - if err := c.Validate(); err != nil { - return nil, fmt.Errorf("validate config: %w", err) - } - v, err := unix.EpollCreate1(0) - if err != nil { - return nil, err - } - return &_epoll{ - fd: v, - cfg: c, - pipe: make(chan TConnect, c.CountEvents), - conn: make(map[int32]TConnect, c.CountEvents), - events: make([]unix.EpollEvent, c.WaitIntervalMS), - }, nil -} - -func (v *_epoll) Accept(c net.Conn) error { - fd64 := netfd.ByConnect(c) - fd32 := int32(fd64) - err := unix.EpollCtl(v.fd, syscall.EPOLL_CTL_ADD, int(fd64), &unix.EpollEvent{Events: epollEvents, Fd: fd32}) - if err != nil { - return errors.Wrap(err, c.Close()) - } - v.mux.Lock() - v.conn[fd32] = newConnect(c, fd32) - v.mux.Unlock() - return nil -} - -func (v *_epoll) removeFD(fd int32) error { - return unix.EpollCtl(v.fd, syscall.EPOLL_CTL_DEL, int(fd), nil) -} - -func (v *_epoll) getConn(fd int32) (TConnect, bool) { - v.mux.Lock() - defer v.mux.Unlock() - - conn, ok := v.conn[fd] - delete(v.conn, fd) - return conn, ok -} - -func (v *_epoll) setConn(c TConnect) { - v.mux.Lock() - defer v.mux.Unlock() - - v.conn[c.FD()] = c -} - -func (v *_epoll) closeConn(fd int32) error { - v.mux.Lock() - defer v.mux.Unlock() - - conn, ok := v.conn[fd] - if !ok { - return nil - } - - delete(v.conn, fd) - - return errors.Wrap( - v.removeFD(fd), - conn.Conn().Close(), - ) -} - -func (v *_epoll) closeAll() (err error) { - v.mux.Lock() - defer v.mux.Unlock() - - for c := range v.pipe { - if err0 := v.closeConn(c.FD()); err0 != nil { - err = errors.Wrap(err, err0) - } - } - - for fd := range v.conn { - if err0 := v.closeConn(fd); err0 != nil { - err = errors.Wrap(err, err0) - } - } - return -} - -func (v *_epoll) getWaited(list *[]int32) (int, error) { - n, err := unix.EpollWait(v.fd, v.events, int(v.cfg.WaitIntervalMS)) - if err != nil && !errors.Is(err, unix.EINTR) { - return 0, err - } - if n <= 0 { - return 0, nil - } - for i := 0; i < n; i++ { - switch v.events[i].Events { - case unix.POLLIN: - *list = append(*list, v.events[i].Fd) - default: - if err = v.closeConn(v.events[i].Fd); err != nil { - logx.Error("Epoll close connect", "err", err) - } - } - } - - return len(*list), nil -} - -func (v *_epoll) Listen(ctx context.Context) (err error) { - defer func() { - close(v.pipe) - err = errors.Wrap(err, v.closeAll()) - }() - - go v.piping(ctx) - - for { - select { - case <-ctx.Done(): - return - default: - } - - list := connPool.Get() - n, err0 := v.getWaited(&list.B) - if err0 != nil { - err = err0 - return - } - if n <= 0 { - continue - } - - for _, fd := range list.B { - conn, ok := v.getConn(fd) - if !ok { - continue - } - v.pipe <- conn - } - - connPool.Put(list) - } - -} - -func (v *_epoll) piping(ctx context.Context) { - for { - select { - case <-ctx.Done(): - return - - case conn := <-v.pipe: - do.Async(func() { - defer func() { - v.setConn(conn) - }() - - e := v.handlingConnect(ctx, conn) - if e == nil { - return - } - if !isClosedError(e) { - logx.Warn("Epoll handling connect", "err", e, "ip", conn.Conn().RemoteAddr()) - return - } - e = v.closeConn(conn.FD()) - if e == nil || isClosedError(e) { - return - } - logx.Error("Epoll close connect", "err", e) - }, func(e error) { - logx.Error("Epoll pipe panic", "err", errors.Unwrap(e), "full", e) - }) - } - } -} - -func (v *_epoll) handlingConnect(ctx context.Context, conn TConnect) error { - buff := buffPool.Get() - defer func() { - buffPool.Put(buff) - }() - n, err := ioutils.Copy(buff, conn.Conn()) - if err != nil { - return err - } - if n == 0 { - return nil - } - return v.cfg.Handler(context.WithoutCancel(ctx), conn.Conn(), buff) -} diff --git a/epoll/epoll_net.go b/epoll/epoll_net.go deleted file mode 100644 index e48f9d7..0000000 --- a/epoll/epoll_net.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package epoll - -import ( - "net" -) - -type ( - connect struct { - conn net.Conn - fd int32 - } - - TConnect interface { - FD() int32 - Conn() net.Conn - } -) - -func newConnect(c net.Conn, fd int32) TConnect { - return &connect{ - conn: c, - fd: fd, - } -} - -func (v *connect) Conn() net.Conn { - return v.conn -} - -func (v *connect) FD() int32 { - return v.fd -} diff --git a/epoll/options.go b/epoll/options.go deleted file mode 100644 index 1e71602..0000000 --- a/epoll/options.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package epoll - -import ( - "context" - "fmt" - "io" -) - -type ( - Option struct { - Handler func(ctx context.Context, w io.Writer, r io.Reader) error - CountEvents uint - WaitIntervalMS uint - } -) - -func (c Option) Validate() error { - if c.Handler == nil { - return fmt.Errorf("epoll handler is empty") - } - if c.CountEvents == 0 { - return fmt.Errorf("epoll count events is empty") - } - if c.WaitIntervalMS == 0 { - return fmt.Errorf("epoll wait interval is empty") - } - return nil -} diff --git a/epoll/server_tcp.go b/epoll/server_tcp.go deleted file mode 100644 index eaac02f..0000000 --- a/epoll/server_tcp.go +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package epoll - -import ( - "context" - "fmt" - "io" - "net" - "time" - - "go.osspkg.com/errors" - "go.osspkg.com/logx" - "go.osspkg.com/syncing" - "go.osspkg.com/xc" - - "go.osspkg.com/network/address" -) - -type ( - ConfigTCP struct { - Addr string `yaml:"addr"` - ReadTimeout time.Duration `yaml:"read_timeout,omitempty"` - WriteTimeout time.Duration `yaml:"write_timeout,omitempty"` - IdleTimeout time.Duration `yaml:"idle_timeout,omitempty"` - ShutdownTimeout time.Duration `yaml:"shutdown_timeout,omitempty"` - CountEvents uint `yaml:"count_events,omitempty"` - WaitIntervalMS uint `yaml:"wait_interval_ms,omitempty"` - } - - ServerTCP struct { - wg syncing.Group - Handler func(ctx context.Context, w io.Writer, r io.Reader) error - Config ConfigTCP - listener net.Listener - epoll TEpoll - } -) - -func (s *ServerTCP) init() (err error) { - if s.Handler == nil { - return fmt.Errorf("epoll tcp: handler is empty") - } - s.wg = syncing.NewGroup() - s.Config.Addr = address.ResolveIPPort(s.Config.Addr) - if s.Config.CountEvents == 0 { - s.Config.CountEvents = 100 - } - if s.Config.WaitIntervalMS == 0 { - s.Config.WaitIntervalMS = 500 - } - s.epoll, err = New(Option{ - Handler: s.Handler, - CountEvents: s.Config.CountEvents, - WaitIntervalMS: s.Config.WaitIntervalMS, - }) - return -} - -func (s *ServerTCP) ListenAndServe(ctx xc.Context) (err error) { - defer func() { - ctx.Close() - logx.Error("Epoll server stopped", "err", err, "ip", s.Config.Addr) - }() - - if err = s.init(); err != nil { - return - } - if s.listener, err = net.Listen("tcp", s.Config.Addr); err != nil { - return - } - defer func() { - err = errors.Wrap(err, s.listener.Close()) - }() - s.wg.Background(func() { - s.connAccept(ctx) - }) - s.wg.Background(func() { - s.epollListen(ctx) - }) - logx.Info("Epoll server started", "ip", s.Config.Addr) - s.wg.Wait() - return -} - -func (s *ServerTCP) connAccept(ctx xc.Context) { - defer func() { - ctx.Close() - }() - for { - conn, err := s.listener.Accept() - if err != nil { - select { - case <-ctx.Done(): - return - default: - logx.Error("Epoll conn accept", "err", err) - return - } - } - if err = s.epoll.Accept(conn); err != nil { - logx.Error("Epoll append connect", "err", err, "ip", conn.RemoteAddr()) - } - } -} - -func (s *ServerTCP) epollListen(ctx xc.Context) { - defer func() { - ctx.Close() - }() - - if err := s.epoll.Listen(ctx.Context()); err != nil { - logx.Error("Epoll listen connects", "err", err) - } -} diff --git a/errs/errs.go b/errs/errs.go index 1626570..4e3116d 100644 --- a/errs/errs.go +++ b/errs/errs.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/examples/client/main.go b/examples/client/main.go index 3243818..2302ef4 100644 --- a/examples/client/main.go +++ b/examples/client/main.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -13,7 +13,7 @@ import ( "sync/atomic" "time" - "go.osspkg.com/ioutils/data" + "go.osspkg.com/bb" "go.osspkg.com/syncing" "go.osspkg.com/network/client" @@ -35,6 +35,9 @@ func main() { panic(err) } + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + var ( good int64 fail int64 @@ -42,13 +45,13 @@ func main() { for i := 0; i < 3; i++ { fmt.Println("------------ STEP", i, "---------------") - wg := syncing.NewGroup() + wg := syncing.NewGroup(ctx) for i := 0; i < 10000; i++ { i := i - wg.Background(func() { - buff := data.NewBuffer(1024) - buff.WriteString(fmt.Sprintf("<- %d ->", i)) - err := cli.Call(context.TODO(), func(ctx context.Context, w io.Writer, r io.Reader) error { + wg.Background("", func(ctx context.Context) { + buff := bb.New(1024) + buff.WriteString(fmt.Sprintf("<- %d ->", i)) //nolint:errcheck,staticcheck + err := cli.Call(ctx, func(ctx context.Context, w io.Writer, r io.Reader) error { if _, err := buff.WriteTo(w); err != nil { return err } diff --git a/examples/epoll-server/main.go b/examples/epoll-server/main.go deleted file mode 100644 index e17d44c..0000000 --- a/examples/epoll-server/main.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package main - -import ( - "context" - "io" - - "go.osspkg.com/xc" - - "go.osspkg.com/network/epoll" -) - -func main() { - serv := &epoll.ServerTCP{ - Handler: func(_ context.Context, w io.Writer, r io.Reader) error { - b, err := io.ReadAll(r) - if err != nil { - return err - } - _, err = w.Write(append([]byte(">> "), b...)) - return err - }, - Config: epoll.ConfigTCP{ - Addr: "127.0.0.1:8888", - CountEvents: 100, - WaitIntervalMS: 300, - }, - } - - if err := serv.ListenAndServe(xc.New()); err != nil { - panic(err) - } -} diff --git a/examples/server/main.go b/examples/server/main.go index 62567fa..412648d 100644 --- a/examples/server/main.go +++ b/examples/server/main.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -12,7 +12,7 @@ import ( "net" "os" - "go.osspkg.com/ioutils/data" + "go.osspkg.com/bb" "go.osspkg.com/logx" "go.osspkg.com/network/listen" @@ -38,11 +38,11 @@ func main() { srv := server.New(config) srv.HandleFunc(func(ctx context.Context, w io.Writer, r io.Reader, addr net.Addr) { - buff := data.NewBuffer(1024) + buff := bb.New(1024) _, err := buff.ReadFrom(r) fmt.Println("[------", addr.String(), "------]", err, buff.String()) - buff.Seek(0, 0) - buff.WriteTo(w) + buff.Seek(0, 0) //nolint:errcheck + buff.WriteTo(w) //nolint:errcheck }) if err := srv.ListenAndServe(context.TODO()); err != nil { diff --git a/fd/fd.go b/fd/fd.go index 619a692..b55b1f1 100644 --- a/fd/fd.go +++ b/fd/fd.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/go.mod b/go.mod index 293b7f7..68058e9 100644 --- a/go.mod +++ b/go.mod @@ -1,31 +1,22 @@ module go.osspkg.com/network -go 1.23.6 +go 1.26.0 require ( - github.com/quic-go/quic-go v0.50.1 - go.osspkg.com/algorithms v1.5.0 - go.osspkg.com/casecheck v0.3.0 - go.osspkg.com/do v0.1.3 - go.osspkg.com/errors v0.3.1 - go.osspkg.com/ioutils v0.5.1 - go.osspkg.com/logx v0.4.2 - go.osspkg.com/syncing v0.3.1 - go.osspkg.com/xc v0.4.0 - golang.org/x/sys v0.31.0 + github.com/quic-go/quic-go v0.61.0 + go.osspkg.com/bb v1.0.1 + go.osspkg.com/casecheck v0.3.1 + go.osspkg.com/errors v0.4.0 + go.osspkg.com/ioutils v0.8.0 + go.osspkg.com/logx v0.6.2 + go.osspkg.com/syncing v0.5.0 ) require ( - github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/mailru/easyjson v0.9.0 // indirect - github.com/onsi/ginkgo/v2 v2.22.2 // indirect - go.uber.org/mock v0.5.0 // indirect - golang.org/x/crypto v0.32.0 // indirect - golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/tools v0.29.0 // indirect + github.com/mailru/easyjson v0.9.2 // indirect + go.uber.org/mock v0.6.0 // indirect + golang.org/x/crypto v0.54.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/sys v0.47.0 // indirect ) diff --git a/go.sum b/go.sum index bc4233a..3f4facd 100644 --- a/go.sum +++ b/go.sum @@ -1,66 +1,36 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M= +github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= -github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.osspkg.com/algorithms v1.5.0 h1:JGmZh+keG0c019K174KggmxeKQ8HzkqnZzYebjS/xi0= -go.osspkg.com/algorithms v1.5.0/go.mod h1:zgjWqmR5KQG/mJSrGLsPug75CzHRZHXj2Ri6UZv4xV8= -go.osspkg.com/casecheck v0.3.0 h1:x15blEszElbrHrEH5H02JIIhGIg/lGZzIt1kQlD3pwM= -go.osspkg.com/casecheck v0.3.0/go.mod h1:TRFXDMFJEOtnlp3ET2Hix3osbxwPWhvaiT/HfD3+gBA= -go.osspkg.com/do v0.1.3 h1:oNXeWZOQUv73LQLawKxfAyN1wacTtRZQVlrkN8nj+sw= -go.osspkg.com/do v0.1.3/go.mod h1:hOQEum85f8Kc4m8PWUAECDQ/mTtQ4362ABLD+KW5/vk= -go.osspkg.com/errors v0.3.1 h1:F9m/EEd/Ot2jba/TV7tvVRIpWXzIpNLc7vRJKcBD86A= -go.osspkg.com/errors v0.3.1/go.mod h1:dKXe6Rt07nzY7OyKQNZ8HGBicZ2uQ5TKEoVFnVFOK44= -go.osspkg.com/ioutils v0.5.0 h1:oCNOJS5AN8pS9hzgi0gOGQRpUp9R6D+UW+5eDpqSdqg= -go.osspkg.com/ioutils v0.5.0/go.mod h1:58HhG2NHf9JUtixAH3R2XISlUmJruwVIUZ3039QVjOY= -go.osspkg.com/ioutils v0.5.1 h1:qzoOECBxChZUxmp6p72XvQRHjDFsVw1kJ2oaFZycNv8= -go.osspkg.com/ioutils v0.5.1/go.mod h1:XRASOo5GKzVaJMCXXZQ4//ymPWq90iyKm1qTQcBEsyo= -go.osspkg.com/logx v0.4.2 h1:3kqG7EaaT/DxpHytQm4MfcrmDhYf8ha9/iRpVjpRt88= -go.osspkg.com/logx v0.4.2/go.mod h1:mGbH9hdkeC0h9Gw1uWgQfi9MmlANcqNLffB0wxIDpsQ= -go.osspkg.com/syncing v0.3.1 h1:zt5o/X5DQ/GE5OQTKkq1nNWJMg7EcYhw0YiwMGuA0f8= -go.osspkg.com/syncing v0.3.1/go.mod h1:Dpe0ljlEG6cI2Y9PxEjKiYEX2sgs1eUjWNVjFu4/iB0= -go.osspkg.com/xc v0.4.0 h1:MGntRGa3EPCpfrTbWEN7x475BAsAtRYGpYEYJ5mE0I8= -go.osspkg.com/xc v0.4.0/go.mod h1:HWDrUQOKMkQser1teXqnFNMB1WVD0YsyIuM1vIKny7U= -go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= -go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= -golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0= +github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk= +github.com/quic-go/quic-go v0.61.0 h1:ui88A53s8MSVYLC56en0KQ17HARk+9986Dn0SBfKNvA= +github.com/quic-go/quic-go v0.61.0/go.mod h1:9So2anK4Tp22URSQq00k+Vo2PNkle96ycDPDHL4s9vs= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.osspkg.com/bb v1.0.1 h1:AWyt2WUyHcyxbkAbiKHo69IPbm4Cvt9fWAcU0rpyRAs= +go.osspkg.com/bb v1.0.1/go.mod h1:bh7v2dIXJC0ge8BZLsh10EFRbJSLjXCmxq4IwSogc58= +go.osspkg.com/casecheck v0.3.1 h1:mxg1WaWy/tv7J05jvf5Idy3ydDYbac3gOOV9NPdjxvU= +go.osspkg.com/casecheck v0.3.1/go.mod h1:TRFXDMFJEOtnlp3ET2Hix3osbxwPWhvaiT/HfD3+gBA= +go.osspkg.com/errors v0.4.0 h1:E17+WyUzTXEHCTxGm8lOMPOOojzHG1lsOuQtTVGoATQ= +go.osspkg.com/errors v0.4.0/go.mod h1:s75ZovPemYtrCtRPVsbQNq9MgMbmLMK1NEypr+uwjXI= +go.osspkg.com/ioutils v0.8.0 h1:19RQ2dEw+7uAjPC2FiIM/vqplocpVLD8FLVd1+bJRpE= +go.osspkg.com/ioutils v0.8.0/go.mod h1:afZbM1uMrtfqSJS8OdQgSKfwQm50nHcCAHBSOMZYArE= +go.osspkg.com/logx v0.6.2 h1:nEapD8nPPKJumF1ebm2M/mHYlEGZ5GAb4trYD/xS4vo= +go.osspkg.com/logx v0.6.2/go.mod h1:8ceGCbLwpMAmxfbwL0dD4jHU85pbjlSKNAxneT7c8x4= +go.osspkg.com/syncing v0.5.0 h1:mgrwnn6381GiLZsuAXGWKk3AnBdm9HbaYwPyBMPoa/k= +go.osspkg.com/syncing v0.5.0/go.mod h1:/LBmgCAHFW6nQgVDILpEuo6eRCFK1yyFeNbDs4eVNls= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/datapool.go b/internal/datapool.go index ec815a3..a2f416b 100644 --- a/internal/datapool.go +++ b/internal/datapool.go @@ -1,15 +1,15 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ package internal import ( - "go.osspkg.com/ioutils/data" + "go.osspkg.com/bb" "go.osspkg.com/ioutils/pool" ) -var DataPool = pool.New[*data.Buffer](func() *data.Buffer { - return data.NewBuffer(512) +var DataPool = pool.New[*bb.Buffer](func() *bb.Buffer { + return bb.New(512) }) diff --git a/internal/deadline.go b/internal/deadline.go index 1015057..e5fea3d 100644 --- a/internal/deadline.go +++ b/internal/deadline.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -10,6 +10,10 @@ import ( "time" ) +const ( + minimalInterval = time.Millisecond * 200 +) + type Conn interface { io.ReadWriteCloser Deadline @@ -19,8 +23,12 @@ type Deadline interface { SetDeadline(t time.Time) error } -func DeadlineUpdate(conn Deadline) func() { - tik := time.NewTicker(time.Second * 5) +func AutoUpdateDeadline(conn Deadline, interval time.Duration) func() { + if interval <= minimalInterval { + interval = minimalInterval + } + + tik := time.NewTicker(interval / 2) closeC := make(chan struct{}) go func() { @@ -29,7 +37,7 @@ func DeadlineUpdate(conn Deadline) func() { case <-closeC: return case v := <-tik.C: - if err := conn.SetDeadline(v.Add(time.Second * 10)); err != nil { + if err := conn.SetDeadline(v.Add(interval)); err != nil { return } } diff --git a/internal/errors.go b/internal/errors.go index da7dbb6..c23b23c 100644 --- a/internal/errors.go +++ b/internal/errors.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/network.go b/internal/network.go index 10f2226..fc789b7 100644 --- a/internal/network.go +++ b/internal/network.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/packet.go b/internal/packet.go index 94e510a..c010313 100644 --- a/internal/packet.go +++ b/internal/packet.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/packet_test.go b/internal/packet_test.go index 2308e3a..7f43bc6 100644 --- a/internal/packet_test.go +++ b/internal/packet_test.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -9,14 +9,14 @@ import ( "net" "testing" + "go.osspkg.com/bb" "go.osspkg.com/casecheck" - "go.osspkg.com/ioutils/data" "go.osspkg.com/network/internal" ) type mockConn struct { - B *data.Buffer + B *bb.Buffer } func (m *mockConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { @@ -27,7 +27,7 @@ func TestUnit_PacketWrite(t *testing.T) { a := internal.PacketWrite{ Addr: nil, Conn: &mockConn{ - B: data.NewBuffer(0), + B: bb.New(0), }, } diff --git a/internal/tls.go b/internal/tls.go index 57743f4..5ca6990 100644 --- a/internal/tls.go +++ b/internal/tls.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/listen/listener.go b/listen/listener.go index 99026a5..f249d2c 100644 --- a/listen/listener.go +++ b/listen/listener.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/listen/tls.go b/listen/tls.go index 3509a8d..92773ed 100644 --- a/listen/tls.go +++ b/listen/tls.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -26,11 +26,11 @@ type SSL struct { } type Certificate struct { - CAFile string `yaml:"ca_file"` - CertFile string `yaml:"cert_file"` - KeyFile string `yaml:"key_file"` - Addresses []string `yaml:"addresses"` - AutoGenerate bool `yaml:"auto_generate"` + CAFile string `yaml:"ca_file,omitempty" unic:"ca_file,omitempty,desc='Адрес корневого сертификата'"` + CertFile string `yaml:"cert_file,omitempty" unic:"cert_file,omitempty,desc='Адрес публичного сертификата'"` + KeyFile string `yaml:"key_file,omitempty" unic:"key_file,omitempty,desc='Адрес приватного ключа'"` + Addresses []string `yaml:"addresses,omitempty" unic:"addresses,omitempty,desc='Список адресов для автогенерации сертификатов'"` + AutoGenerate bool `yaml:"auto_generate,omitempty" unic:"auto_generate,omitempty,desc='Автогенерация сертификатов для списка адресов'"` } func NewTLSConfig(ssl *SSL) (*tls.Config, error) { diff --git a/server/config.go b/server/config.go index 1a020b1..98a63b0 100644 --- a/server/config.go +++ b/server/config.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -9,12 +9,12 @@ import "go.osspkg.com/network/listen" type ( Config struct { - Address string `yaml:"address"` - Network string `yaml:"network"` - SSL *SSL `yaml:"ssl,omitempty"` + Address string `yaml:"address" unic:"address,default='127.0.0.1:80',desc='ip:port для прослушивания сервером'"` + Network string `yaml:"network" unic:"network,default='tcp',desc='Тип сетевого протокола (tcp,udp,unix,quic)'"` + SSL *SSL `yaml:"ssl,omitempty" unic:"ssl,omitempty,desc='Настройки шифрования соединения'"` } SSL struct { - Certs []listen.Certificate `yaml:"certs,omitempty"` - NextProtos []string `yaml:"next_protos,omitempty"` + Certs []listen.Certificate `yaml:"certs,omitempty" unic:"certs,omitempty,desc='Список сертификатов'"` + NextProtos []string `yaml:"next_protos,omitempty" unic:"next_protos,omitempty,desc='Поддерживаемые уровни протоколов'"` } ) diff --git a/server/server.go b/server/server.go index 4cfbcbd..9eecdc5 100644 --- a/server/server.go +++ b/server/server.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2024-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -42,7 +42,7 @@ func New(conf Config) Server { return &_server{ conf: conf, sync: syncing.NewSwitch(), - wg: syncing.NewGroup(), + wg: syncing.NewGroup(context.Background()), } } @@ -119,7 +119,7 @@ func (v *_server) build(ctx context.Context) error { func (v *_server) handlingPacketConn(ctx context.Context, l net.PacketConn) error { ctx, cancel := context.WithCancel(ctx) - stop := internal.DeadlineUpdate(l) + stop := internal.AutoUpdateDeadline(l, 0) defer func() { stop() @@ -127,8 +127,12 @@ func (v *_server) handlingPacketConn(ctx context.Context, l net.PacketConn) erro v.wg.Wait() }() - v.wg.Background(func() { - <-ctx.Done() + v.wg.Background("", func(wc context.Context) { + select { + case <-wc.Done(): + case <-ctx.Done(): + } + v.close() }) @@ -154,7 +158,7 @@ func (v *_server) handlingPacketConn(ctx context.Context, l net.PacketConn) erro return err } - v.wg.Background(func() { + v.wg.Background("", func(wc context.Context) { defer func() { if e := recover(); e != nil { internal.Log("PacketConn: panic", fmt.Errorf("%+v", e), addr) @@ -171,8 +175,11 @@ func (v *_server) handlingPacketConn(ctx context.Context, l net.PacketConn) erro func (v *_server) handlingConn(ctx context.Context, l net.Listener) error { ctx, cancel := context.WithCancel(ctx) - v.wg.Background(func() { - <-ctx.Done() + v.wg.Background("", func(wc context.Context) { + select { + case <-wc.Done(): + case <-ctx.Done(): + } v.close() }) @@ -204,8 +211,8 @@ func (v *_server) handlingConn(ctx context.Context, l net.Listener) error { } } - v.wg.Background(func() { - stop := internal.DeadlineUpdate(conn) + v.wg.Background("", func(wc context.Context) { + stop := internal.AutoUpdateDeadline(conn, 0) defer func() { if e := recover(); e != nil { @@ -225,8 +232,11 @@ func (v *_server) handlingConn(ctx context.Context, l net.Listener) error { func (v *_server) handlingQUIC(ctx context.Context, l *quic.Listener) error { ctx, cancel := context.WithCancel(ctx) - v.wg.Background(func() { - <-ctx.Done() + v.wg.Background("", func(wc context.Context) { + select { + case <-wc.Done(): + case <-ctx.Done(): + } v.close() }) @@ -250,7 +260,7 @@ func (v *_server) handlingQUIC(ctx context.Context, l *quic.Listener) error { addr := conn.RemoteAddr() - v.wg.Background(func() { + v.wg.Background("", func(wc context.Context) { defer func() { if e := recover(); e != nil { internal.Log("QUIC: panic", fmt.Errorf("%+v", e), addr) @@ -265,7 +275,7 @@ func (v *_server) handlingQUIC(ctx context.Context, l *quic.Listener) error { return } - stop := internal.DeadlineUpdate(stream) + stop := internal.AutoUpdateDeadline(stream, 0) defer func() { stop()