@@ -6,19 +6,21 @@ import (
6
6
"sync"
7
7
"syscall"
8
8
"time"
9
- "unsafe"
10
9
11
10
"github.com/kubeshark/gopacket"
11
+ "github.com/kubeshark/tracer/pkg/unixpacket"
12
12
"github.com/rs/zerolog/log"
13
13
)
14
14
15
15
const (
16
16
maxUnixPacketClients = 10
17
- packetHeaderSize = int (unsafe .Sizeof (PacketHeader {}))
18
17
)
19
18
20
19
type SocketPcapConnection struct {
21
20
packetCounter uint64
21
+ writeChannel chan []byte
22
+ packetSent uint64
23
+ packetDropped uint64
22
24
}
23
25
24
26
type SocketPcap struct {
@@ -28,9 +30,81 @@ type SocketPcap struct {
28
30
sync.Mutex
29
31
}
30
32
31
- type PacketHeader struct {
32
- packetCounter uint64
33
- timestamp uint64
33
+ func (s * SocketPcapConnection ) Run (conn * net.UnixConn , sock * SocketPcap ) {
34
+ for {
35
+ select {
36
+ case buf := <- s .writeChannel :
37
+ _ , err := conn .Write (buf )
38
+ if err != nil {
39
+ if errors .Is (err , syscall .EPIPE ) {
40
+ log .Info ().Str ("Address" , conn .RemoteAddr ().String ()).Msg ("Unix socket connection closed:" )
41
+ } else {
42
+ log .Error ().Err (err ).Str ("Address" , conn .RemoteAddr ().String ()).Msg ("Unix socket connection error:" )
43
+ }
44
+ sock .Disconnected (conn )
45
+ return
46
+ }
47
+
48
+ }
49
+ }
50
+ }
51
+
52
+ func (s * SocketPcap ) WritePacket (pkt gopacket.SerializeBuffer ) error {
53
+ s .Lock ()
54
+ defer s .Unlock ()
55
+ defer func () {
56
+ s .packetCounter ++
57
+ }()
58
+ if len (s .connections ) == 0 {
59
+ return nil
60
+ }
61
+
62
+ hdrBytes , err := pkt .PrependBytes (unixpacket .PacketHeaderSize )
63
+ if err != nil {
64
+ return err
65
+ }
66
+
67
+ p := unixpacket .PacketUnixSocket (hdrBytes )
68
+ hdr := p .GetHeader ()
69
+ hdr .Timestamp = uint64 (time .Now ().UnixNano ())
70
+ // clear buffer at the end as soon as it is prepended with specific data
71
+ defer func () {
72
+ _ = pkt .Clear ()
73
+ }()
74
+
75
+ buf := pkt .Bytes ()
76
+ for _ , conn := range s .connections {
77
+ copyBuf := make ([]byte , len (buf ))
78
+ copy (copyBuf , buf )
79
+ p = unixpacket .PacketUnixSocket (copyBuf )
80
+ hdr = p .GetHeader ()
81
+ hdr .PacketCounter = conn .packetCounter
82
+ conn .packetCounter ++
83
+ select {
84
+ case conn .writeChannel <- copyBuf :
85
+ conn .packetSent ++
86
+ default :
87
+ conn .packetDropped ++
88
+ }
89
+ }
90
+ return nil
91
+ }
92
+
93
+ func (s * SocketPcap ) Connected (conn * net.UnixConn ) {
94
+ ch := make (chan []byte , 8 )
95
+ s .Lock ()
96
+ defer s .Unlock ()
97
+ c := & SocketPcapConnection {
98
+ writeChannel : ch ,
99
+ }
100
+ s .connections [conn ] = c
101
+ go c .Run (conn , s )
102
+ }
103
+
104
+ func (s * SocketPcap ) Disconnected (conn * net.UnixConn ) {
105
+ s .Lock ()
106
+ defer s .Unlock ()
107
+ delete (s .connections , conn )
34
108
}
35
109
36
110
func NewSocketPcap (unixSocketFileName string ) * SocketPcap {
@@ -61,47 +135,10 @@ func (c *SocketPcap) acceptClients(l *net.UnixListener) {
61
135
if c .clientsConnected == maxUnixPacketClients {
62
136
log .Info ().Str ("Address" , conn .RemoteAddr ().String ()).Msg ("Unix socket max connections exceeded, closing:" )
63
137
conn .Close ()
64
- } else {
65
- c .connections [conn ] = & SocketPcapConnection {}
66
- c .clientsConnected ++
67
- }
68
- c .Unlock ()
69
- }
70
- }
71
-
72
- func (c * SocketPcap ) WritePacket (buf gopacket.SerializeBuffer ) error {
73
- var err error
74
- var hdrBytes []byte
75
- c .Lock ()
76
- defer c .Unlock ()
77
- c .packetCounter ++
78
- if len (c .connections ) > 0 {
79
- hdrBytes , err = buf .PrependBytes (packetHeaderSize )
80
- if err != nil {
81
- return err
82
- }
83
- // clear buffer at the end as soon as it is prepended with specific data
84
- defer func () {
85
- _ = buf .Clear ()
86
- }()
87
- }
88
- for sock , conn := range c .connections {
89
- hdr := (* PacketHeader )(unsafe .Pointer (& hdrBytes ))
90
- hdr .packetCounter = conn .packetCounter
91
-
92
- _ , err = sock .Write (buf .Bytes ())
93
-
94
- if err != nil {
95
- if errors .Is (err , syscall .EPIPE ) {
96
- log .Info ().Str ("Address" , sock .RemoteAddr ().String ()).Msg ("Unix socket connection closed:" )
97
- } else {
98
- log .Error ().Err (err ).Str ("Address" , sock .RemoteAddr ().String ()).Msg ("Unix socket connection error:" )
99
- }
100
- delete (c .connections , sock )
138
+ c .Unlock ()
101
139
continue
102
140
}
103
- conn .packetCounter ++
141
+ c .Unlock ()
142
+ c .Connected (conn )
104
143
}
105
-
106
- return nil
107
144
}
0 commit comments