From 5560af53107fce08a1954ed35264efd17d88d393 Mon Sep 17 00:00:00 2001
From: Vladislavs Sokurenko <vladislavs.sokurenko@gmail.com>
Date: Fri, 15 Jul 2022 18:06:25 +0300
Subject: [PATCH 1/6] avoid costly process info extraction if all necessary
 calculation was done in AcceptFn function

---
 netstat/netstat_linux.go | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/netstat/netstat_linux.go b/netstat/netstat_linux.go
index 05fb56d..bd4efbf 100644
--- a/netstat/netstat_linux.go
+++ b/netstat/netstat_linux.go
@@ -257,7 +257,11 @@ func doNetstat(path string, fn AcceptFn) ([]SockTabEntry, error) {
 	if err != nil {
 		return nil, err
 	}
-	extractProcInfo(tabs)
+
+	if len(tabs) != 0 {
+		extractProcInfo(tabs)
+	}
+
 	return tabs, nil
 }
 

From bfa11328cb72c450b8b57bd523bfc9d7ac31b0c7 Mon Sep 17 00:00:00 2001
From: Vladislavs Sokurenko <vladislavs.sokurenko@gmail.com>
Date: Tue, 8 Nov 2022 17:13:23 +0200
Subject: [PATCH 2/6] avoid costly process info extraction if all necessary
 calculation was done in AcceptFn function on Windows

---
 netstat/netstat_windows.go | 80 +++++++++++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 23 deletions(-)

diff --git a/netstat/netstat_windows.go b/netstat/netstat_windows.go
index 8e3b289..b785cbf 100644
--- a/netstat/netstat_windows.go
+++ b/netstat/netstat_windows.go
@@ -1,3 +1,4 @@
+//go:build amd64
 // +build amd64
 
 package netstat
@@ -118,7 +119,7 @@ type MibTCPRow2 struct {
 
 type WinPid uint32
 
-func (pid WinPid) Process(snp ProcessSnapshot) *Process {
+func sockProcess(snp ProcessSnapshot, pid uint32) *Process {
 	if pid < 1 {
 		return nil
 	}
@@ -131,6 +132,7 @@ func (pid WinPid) Process(snp ProcessSnapshot) *Process {
 func (m *MibTCPRow2) LocalSock() *SockAddr  { return m.LocalAddr.Sock() }
 func (m *MibTCPRow2) RemoteSock() *SockAddr { return m.RemoteAddr.Sock() }
 func (m *MibTCPRow2) SockState() SkState    { return SkState(m.State) }
+func (m *MibTCPRow2) UID() uint32           { return uint32(m.WinPid) }
 
 type MibTCPTable2 struct {
 	NumEntries uint32
@@ -159,6 +161,7 @@ type MibTCP6Row2 struct {
 func (m *MibTCP6Row2) LocalSock() *SockAddr  { return m.LocalAddr.Sock() }
 func (m *MibTCP6Row2) RemoteSock() *SockAddr { return m.RemoteAddr.Sock() }
 func (m *MibTCP6Row2) SockState() SkState    { return SkState(m.State) }
+func (m *MibTCP6Row2) UID() uint32           { return uint32(m.WinPid) }
 
 // MibTCP6Table2 structure contains a table of IPv6 TCP connections on the
 // local computer.
@@ -188,6 +191,7 @@ type MibUDPRowOwnerPID struct {
 func (m *MibUDPRowOwnerPID) LocalSock() *SockAddr  { return m.Sock() }
 func (m *MibUDPRowOwnerPID) RemoteSock() *SockAddr { return &SockAddr{net.IPv4zero, 0} }
 func (m *MibUDPRowOwnerPID) SockState() SkState    { return Close }
+func (m *MibUDPRowOwnerPID) UID() uint32           { return uint32(m.WinPid) }
 
 // MibUDPTableOwnerPID structure contains the User Datagram Protocol (UDP)
 // listener table for IPv4 on the local computer. The table also includes the
@@ -217,6 +221,7 @@ type MibUDP6RowOwnerPID struct {
 func (m *MibUDP6RowOwnerPID) LocalSock() *SockAddr  { return m.Sock() }
 func (m *MibUDP6RowOwnerPID) RemoteSock() *SockAddr { return &SockAddr{net.IPv4zero, 0} }
 func (m *MibUDP6RowOwnerPID) SockState() SkState    { return Close }
+func (m *MibUDP6RowOwnerPID) UID() uint32           { return uint32(m.WinPid) }
 
 // MibUDP6TableOwnerPID serves the same purpose as MibUDPTableOwnerPID for IPv6
 type MibUDP6TableOwnerPID struct {
@@ -468,15 +473,15 @@ type winSockEnt interface {
 	LocalSock() *SockAddr
 	RemoteSock() *SockAddr
 	SockState() SkState
-	Process(snp ProcessSnapshot) *Process
+	UID() uint32
 }
 
-func toSockTabEntry(ws winSockEnt, snp ProcessSnapshot) SockTabEntry {
+func toSockTabEntry(ws winSockEnt) SockTabEntry {
 	return SockTabEntry{
 		LocalAddr:  ws.LocalSock(),
 		RemoteAddr: ws.RemoteSock(),
 		State:      ws.SockState(),
-		Process:    ws.Process(snp),
+		UID:        uint32(ws.UID()),
 	}
 }
 
@@ -485,19 +490,28 @@ func osTCPSocks(accept AcceptFn) ([]SockTabEntry, error) {
 	if err != nil {
 		return nil, err
 	}
-	snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
-	if err != nil {
-		return nil, err
-	}
+
 	var sktab []SockTabEntry
 	s := tbl.Rows()
 	for i := range s {
-		ent := toSockTabEntry(&s[i], snp)
+		ent := toSockTabEntry(&s[i])
 		if accept(&ent) {
 			sktab = append(sktab, ent)
 		}
 	}
-	snp.Close()
+	if len(sktab) != 0 {
+		snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
+		if err != nil {
+			return nil, err
+		}
+
+		for i := range sktab {
+			sktab[i].Process = sockProcess(snp, sktab[i].UID)
+		}
+
+		snp.Close()
+	}
+
 	return sktab, nil
 }
 
@@ -513,7 +527,7 @@ func osTCP6Socks(accept AcceptFn) ([]SockTabEntry, error) {
 	var sktab []SockTabEntry
 	s := tbl.Rows()
 	for i := range s {
-		ent := toSockTabEntry(&s[i], snp)
+		ent := toSockTabEntry(&s[i])
 		if accept(&ent) {
 			sktab = append(sktab, ent)
 		}
@@ -527,19 +541,29 @@ func osUDPSocks(accept AcceptFn) ([]SockTabEntry, error) {
 	if err != nil {
 		return nil, err
 	}
-	snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
-	if err != nil {
-		return nil, err
-	}
+
 	var sktab []SockTabEntry
 	s := tbl.Rows()
 	for i := range s {
-		ent := toSockTabEntry(&s[i], snp)
+		ent := toSockTabEntry(&s[i])
 		if accept(&ent) {
 			sktab = append(sktab, ent)
 		}
 	}
-	snp.Close()
+
+	if len(sktab) != 0 {
+		snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
+		if err != nil {
+			return nil, err
+		}
+
+		for i := range sktab {
+			sktab[i].Process = sockProcess(snp, sktab[i].UID)
+		}
+
+		snp.Close()
+	}
+
 	return sktab, nil
 }
 
@@ -548,18 +572,28 @@ func osUDP6Socks(accept AcceptFn) ([]SockTabEntry, error) {
 	if err != nil {
 		return nil, err
 	}
-	snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
-	if err != nil {
-		return nil, err
-	}
+
 	var sktab []SockTabEntry
 	s := tbl.Rows()
 	for i := range s {
-		ent := toSockTabEntry(&s[i], snp)
+		ent := toSockTabEntry(&s[i])
 		if accept(&ent) {
 			sktab = append(sktab, ent)
 		}
 	}
-	snp.Close()
+
+	if len(sktab) != 0 {
+		snp, err := CreateToolhelp32Snapshot(Th32csSnapProcess, 0)
+		if err != nil {
+			return nil, err
+		}
+
+		for i := range sktab {
+			sktab[i].Process = sockProcess(snp, sktab[i].UID)
+		}
+
+		snp.Close()
+	}
+
 	return sktab, nil
 }

From 3044eedb1533ad502c7b80f329256c5e285cdd8e Mon Sep 17 00:00:00 2001
From: Vladislavs Sokurenko <vladislavs.sokurenko@gmail.com>
Date: Tue, 8 Nov 2022 18:07:50 +0200
Subject: [PATCH 3/6] temporary change to go.mod

---
 go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 86c4a3c..2cd2da7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module github.com/cakturk/go-netstat
+module github.com/sokurenko/go-netstat
 
 go 1.13

From 4a3d3bb08120bc19be5941c317ba05056eaadad3 Mon Sep 17 00:00:00 2001
From: sokurenko <vladislavs.sokurenko@gmail.com>
Date: Tue, 8 Nov 2022 18:46:57 +0200
Subject: [PATCH 4/6] Update README.md

---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
index ce78dc2..aa04ee1 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+###  This fork avoids costly process info extraction if all necessary calculation was done in AcceptFn function and it always returns false.
 ### Usage:
 
 ```

From 9b597552c5625a39288f45ebb02fae9ada0fee22 Mon Sep 17 00:00:00 2001
From: sokurenko <vladislavs.sokurenko@gmail.com>
Date: Wed, 30 Nov 2022 16:12:29 +0200
Subject: [PATCH 5/6] Update README.md

---
 README.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/README.md b/README.md
index aa04ee1..ce78dc2 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-###  This fork avoids costly process info extraction if all necessary calculation was done in AcceptFn function and it always returns false.
 ### Usage:
 
 ```

From 2a51be9e72a5c8012804e859b11814cfc345618d Mon Sep 17 00:00:00 2001
From: sokurenko <vladislavs.sokurenko@gmail.com>
Date: Wed, 30 Nov 2022 16:14:56 +0200
Subject: [PATCH 6/6] Update go.mod

---
 go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 2cd2da7..86c4a3c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module github.com/sokurenko/go-netstat
+module github.com/cakturk/go-netstat
 
 go 1.13