Skip to content

Commit

Permalink
Merge pull request #201 from projectdiscovery/feat-onetimepool
Browse files Browse the repository at this point in the history
Moving Jarm Calculation with one time connection pool
  • Loading branch information
Mzack9999 authored Jul 14, 2023
2 parents ec0efa2 + 4716536 commit 4c3e1e5
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.19
go-version: 1.20.x

- name: Check out code
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.19
go-version: 1.20.x
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3.6.0
with:
Expand Down
45 changes: 45 additions & 0 deletions conn/connpool/inflight.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package connpool

import (
"errors"
"net"

mapsutil "github.com/projectdiscovery/utils/maps"
"go.uber.org/multierr"
)

type InFlightConns struct {
inflightConns *mapsutil.SyncLockMap[net.Conn, struct{}]
}

func NewInFlightConns() (*InFlightConns, error) {
m := &mapsutil.SyncLockMap[net.Conn, struct{}]{
Map: mapsutil.Map[net.Conn, struct{}]{},
}
return &InFlightConns{inflightConns: m}, nil
}

func (i *InFlightConns) Add(conn net.Conn) {
_ = i.inflightConns.Set(conn, struct{}{})
}

func (i *InFlightConns) Remove(conn net.Conn) {
i.inflightConns.Delete(conn)
}

func (i *InFlightConns) Close() error {
var errs []error

_ = i.inflightConns.Iterate(func(conn net.Conn, _ struct{}) error {
if err := conn.Close(); err != nil {
errs = append(errs, err)
}
return nil
})

if ok := i.inflightConns.Clear(); !ok {
errs = append(errs, errors.New("couldn't empty in flight connections"))
}

return multierr.Combine(errs...)
}
81 changes: 81 additions & 0 deletions conn/connpool/onetimepool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package connpool

import (
"context"
"net"
)

type Dialer interface {
Dial(ctx context.Context, network, address string) (net.Conn, error)
}

// OneTimePool is a pool designed to create continous bare connections that are for one time only usage
type OneTimePool struct {
address string
idleConnections chan net.Conn
InFlightConns *InFlightConns
ctx context.Context
cancel context.CancelFunc
Dialer Dialer
}

func NewOneTimePool(ctx context.Context, address string, poolSize int) (*OneTimePool, error) {
idleConnections := make(chan net.Conn, poolSize)
inFlightConns, err := NewInFlightConns()
if err != nil {
return nil, err
}
pool := &OneTimePool{
address: address,
idleConnections: idleConnections,
InFlightConns: inFlightConns,
}
if ctx == nil {
ctx = context.Background()
}
pool.ctx, pool.cancel = context.WithCancel(ctx)
return pool, nil
}

// Acquire acquires an idle connection from the pool
func (p *OneTimePool) Acquire(c context.Context) (net.Conn, error) {
select {
case <-p.ctx.Done():
return nil, p.ctx.Err()
case <-c.Done():
return nil, c.Err()
case conn := <-p.idleConnections:
p.InFlightConns.Remove(conn)
return conn, nil
}
}

func (p *OneTimePool) Run() error {
for {
select {
case <-p.ctx.Done():
return p.ctx.Err()
default:
var (
conn net.Conn
err error
)
if p.Dialer != nil {
conn, err = p.Dialer.Dial(p.ctx, "tcp", p.address)
} else {
conn, err = net.Dial("tcp", p.address)
}
if err == nil {
p.InFlightConns.Add(conn)
p.idleConnections <- conn
}
}
}
}

func (p *OneTimePool) Close() error {
p.cancel()
// remove dialer references
p.Dialer = nil
return p.InFlightConns.Close()
}
64 changes: 64 additions & 0 deletions crypto/jarm/jarm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package jarm

import (
"context"
"fmt"
"net"
"strings"
"time"

gojarm "github.com/hdm/jarm-go"
connpool "github.com/projectdiscovery/utils/conn/connpool"
)

// PoolCount defines how many connection are kept in the pool
var PoolCount = 3

// fingerprint probes a single host/port
func HashWithDialer(dialer connpool.Dialer, host string, port int, duration int) (string, error) {
var results []string
addr := net.JoinHostPort(host, fmt.Sprintf("%d", port))

timeout := time.Duration(duration) * time.Second
ctx, cancel := context.WithTimeout(context.Background(), (time.Duration(duration*PoolCount) * time.Second))
defer cancel()

// using connection pool as we need multiple probes
pool, err := connpool.NewOneTimePool(ctx, addr, PoolCount)
if err != nil {
return "", err
}
pool.Dialer = dialer

defer func() { _ = pool.Close() }()
go func() { _ = pool.Run() }()

for _, probe := range gojarm.GetProbes(host, port) {
conn, err := pool.Acquire(ctx)
if err != nil {
continue
}
if conn == nil {
continue
}
_ = conn.SetWriteDeadline(time.Now().Add(timeout))
_, err = conn.Write(gojarm.BuildProbe(probe))
if err != nil {
results = append(results, "")
_ = conn.Close()
continue
}
_ = conn.SetReadDeadline(time.Now().Add(timeout))
buff := make([]byte, 1484)
_, _ = conn.Read(buff)
_ = conn.Close()
ans, err := gojarm.ParseServerHello(buff, probe)
if err != nil {
results = append(results, "")
continue
}
results = append(results, ans)
}
hash := gojarm.RawHashToFuzzyHash(strings.Join(results, ","))
return hash, nil
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
module github.com/projectdiscovery/utils

go 1.19
go 1.20

require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/charmbracelet/glamour v0.6.0
github.com/google/go-github/v30 v30.1.0
github.com/hdm/jarm-go v0.0.7
github.com/kljensen/snowball v0.8.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/microcosm-cc/bluemonday v1.0.24
Expand Down
20 changes: 19 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/RumbleDiscovery/rumble-tools v0.0.0-20201105153123-f2adbb3244d2/go.mod h1:jD2+mU+E2SZUuAOHZvZj4xP4frlOo+N/YrXDvASFhkE=
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
Expand Down Expand Up @@ -33,6 +34,7 @@ github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBD
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
Expand All @@ -54,6 +56,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A=
github.com/hdm/jarm-go v0.0.7/go.mod h1:kinGoS0+Sdn1Rr54OtanET5E5n7AlD6T6CrJAKDjJSQ=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
Expand Down Expand Up @@ -86,6 +90,7 @@ github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
github.com/microcosm-cc/bluemonday v1.0.24 h1:NGQoPtwGVcbGkKfvyYk1yRqknzBuoMiUrO6R7uFTPlw=
github.com/microcosm-cc/bluemonday v1.0.24/go.mod h1:ArQySAMps0790cHSkdPEJ7bGkF2VePWH773hsJNSHf8=
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
Expand Down Expand Up @@ -135,6 +140,7 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
Expand Down Expand Up @@ -177,6 +183,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
Expand All @@ -185,26 +193,34 @@ golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20221019170559-20944726eadf h1:nFVjjKDgNY37+ZSYCJmtYf7tOlfQswHqplG2eosjOMg=
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -229,8 +245,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
Expand Down
7 changes: 5 additions & 2 deletions ip/iputil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
)

func TestTryExtendIP(t *testing.T) {
if osutils.IsLinux() {
return
}
if osutils.IsWindows() {
i, err := TryExtendIP("localhost")
require.Nil(t, i)
Expand Down Expand Up @@ -58,13 +61,13 @@ func TestTryExtendIP(t *testing.T) {

for _, tc := range testCases {
ip, err := TryExtendIP(tc.input)
require.Equal(t, tc.expectedError, err != nil)
require.Equal(t, tc.expectedError, err != nil, "input: %v, error: %v", tc.input, err)
require.True(t, ip.Equal(tc.expectedIP), "Expected IP: %v, got: %v", tc.expectedIP, ip)
}
}

func TestCanExtend(t *testing.T) {
if osutils.IsWindows() {
if osutils.IsWindows() || osutils.IsLinux() {
return
}

Expand Down
6 changes: 6 additions & 0 deletions maps/generic_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,9 @@ func (m Map[K, V]) Clone() Map[K, V] {
func (m Map[K, V]) Set(key K, value V) {
m[key] = value
}

// Clear the map
func (m Map[K, V]) Clear() bool {
maps.Clear(m)
return m.IsEmpty()
}
16 changes: 16 additions & 0 deletions maps/synclock_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ func (s *SyncLockMap[K, V]) Get(k K) (V, bool) {
return v, ok
}

// Get an item with syncronous access
func (s *SyncLockMap[K, V]) Delete(k K) {
s.mu.RLock()
defer s.mu.RUnlock()

delete(s.Map, k)
}

// Iterate with a callback function synchronously
func (s *SyncLockMap[K, V]) Iterate(f func(k K, v V) error) error {
s.mu.RLock()
Expand Down Expand Up @@ -95,6 +103,14 @@ func (s *SyncLockMap[K, V]) IsEmpty() bool {
return s.Map.IsEmpty()
}

// IsEmpty checks if the current map is empty
func (s *SyncLockMap[K, V]) Clear() bool {
s.mu.Lock()
defer s.mu.Unlock()

return s.Map.Clear()
}

// GetKeywithValue returns the first key having value
func (s *SyncLockMap[K, V]) GetKeyWithValue(value V) (K, bool) {
s.mu.RLock()
Expand Down
Loading

0 comments on commit 4c3e1e5

Please sign in to comment.