@@ -15,26 +15,42 @@ class PcapFFI
15
15
{
16
16
public const LIBPCAP_NAME = 'libpcap.so.1 ' ;
17
17
18
- private FFI $ ffi ;
18
+ static private $ ffi = NULL ;
19
19
20
20
private ?string $ error = null ;
21
21
22
22
public function __construct ()
23
23
{
24
- $ env = getenv ('LIBPCAP_NAME ' );
25
- $ lib = ($ env !== false ) ? $ env : self ::LIBPCAP_NAME ;
26
- $ code = file_get_contents (__DIR__ . '/pcap.h ' );
27
-
28
- if ($ code === false ) {
29
- throw new Exception ('Cannot load pcap C definitions ' );
24
+ if (self ::$ ffi ) {
25
+ return ;
30
26
}
31
27
32
- $ this ->ffi = FFI ::cdef ($ code , $ lib );
28
+ $ lib = getenv ('LIBPCAP_NAME ' );
29
+ if ($ lib ) {
30
+ // old way
31
+ $ code = file_get_contents (__DIR__ . '/pcap.h ' );
32
+
33
+ if ($ code === false ) {
34
+ throw new Exception ('Cannot load pcap C definitions ' );
35
+ }
36
+ self ::$ ffi = FFI ::cdef ($ code , $ lib );
37
+ } else {
38
+ try {
39
+ // Try preload
40
+ self ::$ ffi = \FFI ::scope ("_RTCKIT_PCAP_FFI_ " );
41
+ } catch (\FFI \Exception $ e ) {
42
+ // Try direct load
43
+ self ::$ ffi = \FFI ::load (__DIR__ . '/pcap.h ' );
44
+ }
45
+ }
46
+ if (!self ::$ ffi ) {
47
+ throw new \RuntimeException ("FFI parse fails " );
48
+ }
33
49
}
34
50
35
51
public function lib_version (): string
36
52
{
37
- return $ this -> ffi ->pcap_lib_version ();
53
+ return self :: $ ffi ->pcap_lib_version ();
38
54
}
39
55
40
56
/**
@@ -47,11 +63,11 @@ public function findalldevs(): ?array
47
63
{
48
64
$ this ->resetLastError ();
49
65
50
- $ devs = $ this -> ffi ->new ('pcap_if_t * ' );
51
- $ dev = $ this -> ffi ->new ('pcap_if_t * ' );
52
- $ err = $ this -> ffi ->new ('char[257] ' );
66
+ $ devs = self :: $ ffi ->new ('pcap_if_t * ' );
67
+ $ dev = self :: $ ffi ->new ('pcap_if_t * ' );
68
+ $ err = self :: $ ffi ->new ('char[257] ' );
53
69
54
- if ($ this -> ffi ->pcap_findalldevs (FFI ::addr ($ devs ), $ err ) < 0 ) {
70
+ if (self :: $ ffi ->pcap_findalldevs (FFI ::addr ($ devs ), $ err ) < 0 ) {
55
71
$ this ->setLastError (FFI ::string ($ err ));
56
72
57
73
return null ;
@@ -68,7 +84,7 @@ public function findalldevs(): ?array
68
84
$ dev = $ dev ->next ;
69
85
}
70
86
71
- $ this -> ffi ->pcap_freealldevs ($ devs );
87
+ self :: $ ffi ->pcap_freealldevs ($ devs );
72
88
73
89
return $ ret ;
74
90
}
@@ -77,8 +93,8 @@ public function create(string $dev): ?CData
77
93
{
78
94
$ this ->resetLastError ();
79
95
80
- $ err = $ this -> ffi ->new ('char[257] ' );
81
- $ ret = $ this -> ffi ->pcap_create ($ dev , $ err );
96
+ $ err = self :: $ ffi ->new ('char[257] ' );
97
+ $ ret = self :: $ ffi ->pcap_create ($ dev , $ err );
82
98
83
99
if (is_null ($ ret )) {
84
100
$ this ->setLastError (FFI ::string ($ err ));
@@ -93,7 +109,7 @@ public function set_snaplen(CData $pcap, int $snaplen): int
93
109
{
94
110
$ this ->resetLastError ();
95
111
96
- $ ret = $ this -> ffi ->pcap_set_snaplen ($ pcap , $ snaplen );
112
+ $ ret = self :: $ ffi ->pcap_set_snaplen ($ pcap , $ snaplen );
97
113
98
114
if ($ ret < 0 ) {
99
115
$ this ->setLastPcapError ($ pcap );
@@ -106,7 +122,7 @@ public function set_promisc(CData $pcap, int $promisc): int
106
122
{
107
123
$ this ->resetLastError ();
108
124
109
- $ ret = $ this -> ffi ->pcap_set_promisc ($ pcap , $ promisc );
125
+ $ ret = self :: $ ffi ->pcap_set_promisc ($ pcap , $ promisc );
110
126
111
127
if ($ ret < 0 ) {
112
128
$ this ->setLastPcapError ($ pcap );
@@ -119,7 +135,7 @@ public function set_immediate_mode(CData $pcap, int $immediate_mode): int
119
135
{
120
136
$ this ->resetLastError ();
121
137
122
- $ ret = $ this -> ffi ->pcap_set_immediate_mode ($ pcap , $ immediate_mode );
138
+ $ ret = self :: $ ffi ->pcap_set_immediate_mode ($ pcap , $ immediate_mode );
123
139
124
140
if ($ ret < 0 ) {
125
141
$ this ->setLastPcapError ($ pcap );
@@ -132,7 +148,7 @@ public function set_timeout(CData $pcap, int $to_ms): int
132
148
{
133
149
$ this ->resetLastError ();
134
150
135
- $ ret = $ this -> ffi ->pcap_set_timeout ($ pcap , $ to_ms );
151
+ $ ret = self :: $ ffi ->pcap_set_timeout ($ pcap , $ to_ms );
136
152
137
153
if ($ ret < 0 ) {
138
154
$ this ->setLastPcapError ($ pcap );
@@ -145,8 +161,8 @@ public function setnonblock(CData $pcap, int $nonblock): int
145
161
{
146
162
$ this ->resetLastError ();
147
163
148
- $ err = $ this -> ffi ->new ('char[257] ' );
149
- $ ret = $ this -> ffi ->pcap_setnonblock ($ pcap , $ nonblock , $ err );
164
+ $ err = self :: $ ffi ->new ('char[257] ' );
165
+ $ ret = self :: $ ffi ->pcap_setnonblock ($ pcap , $ nonblock , $ err );
150
166
151
167
if ($ ret < 0 ) {
152
168
$ this ->setLastError (FFI ::string ($ err ));
@@ -159,7 +175,7 @@ public function activate(CData $pcap): int
159
175
{
160
176
$ this ->resetLastError ();
161
177
162
- $ ret = $ this -> ffi ->pcap_activate ($ pcap );
178
+ $ ret = self :: $ ffi ->pcap_activate ($ pcap );
163
179
164
180
if ($ ret < 0 ) {
165
181
$ this ->setLastPcapError ($ pcap );
@@ -170,21 +186,21 @@ public function activate(CData $pcap): int
170
186
171
187
public function get_selectable_fd (CData $ pcap ): int
172
188
{
173
- return $ this -> ffi ->pcap_get_selectable_fd ($ pcap );
189
+ return self :: $ ffi ->pcap_get_selectable_fd ($ pcap );
174
190
}
175
191
176
192
public function inject (CData $ pcap , string $ data ): int
177
193
{
178
- return $ this -> ffi ->pcap_inject ($ pcap , $ data , strlen ($ data ));
194
+ return self :: $ ffi ->pcap_inject ($ pcap , $ data , strlen ($ data ));
179
195
}
180
196
181
197
public function next_ex (CData $ pcap ): string
182
198
{
183
199
$ this ->resetLastError ();
184
200
185
- $ header = $ this -> ffi ->new ('struct pcap_pkthdr * ' );
186
- $ data = $ this -> ffi ->new ('const u_char * ' );
187
- $ next = $ this -> ffi ->pcap_next_ex ($ pcap , FFI ::addr ($ header ), FFI ::addr ($ data ));
201
+ $ header = self :: $ ffi ->new ('struct pcap_pkthdr * ' );
202
+ $ data = self :: $ ffi ->new ('const u_char * ' );
203
+ $ next = self :: $ ffi ->pcap_next_ex ($ pcap , FFI ::addr ($ header ), FFI ::addr ($ data ));
188
204
189
205
if ($ next < 0 ) {
190
206
$ this ->setLastPcapError ($ pcap );
@@ -203,13 +219,13 @@ public function compile_setfilter(CData $pcap, string $filter): int
203
219
{
204
220
$ this ->resetLastError ();
205
221
206
- $ fp = $ this -> ffi ->new ('struct bpf_program ' );
207
- $ ret = $ this -> ffi ->pcap_compile ($ pcap , FFI ::addr ($ fp ), $ filter , 0 , 0 );
222
+ $ fp = self :: $ ffi ->new ('struct bpf_program ' );
223
+ $ ret = self :: $ ffi ->pcap_compile ($ pcap , FFI ::addr ($ fp ), $ filter , 0 , 0 );
208
224
209
225
if ($ ret < 0 ) {
210
226
$ this ->setLastPcapError ($ pcap );
211
227
} else {
212
- $ ret = $ this -> ffi ->pcap_setfilter ($ pcap , FFI ::addr ($ fp ));
228
+ $ ret = self :: $ ffi ->pcap_setfilter ($ pcap , FFI ::addr ($ fp ));
213
229
214
230
if ($ ret < 0 ) {
215
231
$ this ->setLastPcapError ($ pcap );
@@ -221,7 +237,7 @@ public function compile_setfilter(CData $pcap, string $filter): int
221
237
222
238
public function close (CData $ pcap ): void
223
239
{
224
- $ this -> ffi ->pcap_close ($ pcap );
240
+ self :: $ ffi ->pcap_close ($ pcap );
225
241
}
226
242
227
243
public function getLastError (): string
@@ -236,7 +252,7 @@ private function setLastError(string $error): void
236
252
237
253
private function setLastPcapError (CData $ pcap ): void
238
254
{
239
- $ err = $ this -> ffi ->pcap_geterr ($ pcap );
255
+ $ err = self :: $ ffi ->pcap_geterr ($ pcap );
240
256
241
257
if (!is_null ($ err )) {
242
258
$ this ->setLastError (FFI ::string ($ err ));
0 commit comments