@@ -15,26 +15,42 @@ class PcapFFI
1515{
1616 public const LIBPCAP_NAME = 'libpcap.so.1 ' ;
1717
18- private FFI $ ffi ;
18+ static private $ ffi = NULL ;
1919
2020 private ?string $ error = null ;
2121
2222 public function __construct ()
2323 {
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 ;
3026 }
3127
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+ }
3349 }
3450
3551 public function lib_version (): string
3652 {
37- return $ this -> ffi ->pcap_lib_version ();
53+ return self :: $ ffi ->pcap_lib_version ();
3854 }
3955
4056 /**
@@ -47,11 +63,11 @@ public function findalldevs(): ?array
4763 {
4864 $ this ->resetLastError ();
4965
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] ' );
5369
54- if ($ this -> ffi ->pcap_findalldevs (FFI ::addr ($ devs ), $ err ) < 0 ) {
70+ if (self :: $ ffi ->pcap_findalldevs (FFI ::addr ($ devs ), $ err ) < 0 ) {
5571 $ this ->setLastError (FFI ::string ($ err ));
5672
5773 return null ;
@@ -68,7 +84,7 @@ public function findalldevs(): ?array
6884 $ dev = $ dev ->next ;
6985 }
7086
71- $ this -> ffi ->pcap_freealldevs ($ devs );
87+ self :: $ ffi ->pcap_freealldevs ($ devs );
7288
7389 return $ ret ;
7490 }
@@ -77,8 +93,8 @@ public function create(string $dev): ?CData
7793 {
7894 $ this ->resetLastError ();
7995
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 );
8298
8399 if (is_null ($ ret )) {
84100 $ this ->setLastError (FFI ::string ($ err ));
@@ -93,7 +109,7 @@ public function set_snaplen(CData $pcap, int $snaplen): int
93109 {
94110 $ this ->resetLastError ();
95111
96- $ ret = $ this -> ffi ->pcap_set_snaplen ($ pcap , $ snaplen );
112+ $ ret = self :: $ ffi ->pcap_set_snaplen ($ pcap , $ snaplen );
97113
98114 if ($ ret < 0 ) {
99115 $ this ->setLastPcapError ($ pcap );
@@ -106,7 +122,7 @@ public function set_promisc(CData $pcap, int $promisc): int
106122 {
107123 $ this ->resetLastError ();
108124
109- $ ret = $ this -> ffi ->pcap_set_promisc ($ pcap , $ promisc );
125+ $ ret = self :: $ ffi ->pcap_set_promisc ($ pcap , $ promisc );
110126
111127 if ($ ret < 0 ) {
112128 $ this ->setLastPcapError ($ pcap );
@@ -119,7 +135,7 @@ public function set_immediate_mode(CData $pcap, int $immediate_mode): int
119135 {
120136 $ this ->resetLastError ();
121137
122- $ ret = $ this -> ffi ->pcap_set_immediate_mode ($ pcap , $ immediate_mode );
138+ $ ret = self :: $ ffi ->pcap_set_immediate_mode ($ pcap , $ immediate_mode );
123139
124140 if ($ ret < 0 ) {
125141 $ this ->setLastPcapError ($ pcap );
@@ -132,7 +148,7 @@ public function set_timeout(CData $pcap, int $to_ms): int
132148 {
133149 $ this ->resetLastError ();
134150
135- $ ret = $ this -> ffi ->pcap_set_timeout ($ pcap , $ to_ms );
151+ $ ret = self :: $ ffi ->pcap_set_timeout ($ pcap , $ to_ms );
136152
137153 if ($ ret < 0 ) {
138154 $ this ->setLastPcapError ($ pcap );
@@ -145,8 +161,8 @@ public function setnonblock(CData $pcap, int $nonblock): int
145161 {
146162 $ this ->resetLastError ();
147163
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 );
150166
151167 if ($ ret < 0 ) {
152168 $ this ->setLastError (FFI ::string ($ err ));
@@ -159,7 +175,7 @@ public function activate(CData $pcap): int
159175 {
160176 $ this ->resetLastError ();
161177
162- $ ret = $ this -> ffi ->pcap_activate ($ pcap );
178+ $ ret = self :: $ ffi ->pcap_activate ($ pcap );
163179
164180 if ($ ret < 0 ) {
165181 $ this ->setLastPcapError ($ pcap );
@@ -170,21 +186,21 @@ public function activate(CData $pcap): int
170186
171187 public function get_selectable_fd (CData $ pcap ): int
172188 {
173- return $ this -> ffi ->pcap_get_selectable_fd ($ pcap );
189+ return self :: $ ffi ->pcap_get_selectable_fd ($ pcap );
174190 }
175191
176192 public function inject (CData $ pcap , string $ data ): int
177193 {
178- return $ this -> ffi ->pcap_inject ($ pcap , $ data , strlen ($ data ));
194+ return self :: $ ffi ->pcap_inject ($ pcap , $ data , strlen ($ data ));
179195 }
180196
181197 public function next_ex (CData $ pcap ): string
182198 {
183199 $ this ->resetLastError ();
184200
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 ));
188204
189205 if ($ next < 0 ) {
190206 $ this ->setLastPcapError ($ pcap );
@@ -203,13 +219,13 @@ public function compile_setfilter(CData $pcap, string $filter): int
203219 {
204220 $ this ->resetLastError ();
205221
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 );
208224
209225 if ($ ret < 0 ) {
210226 $ this ->setLastPcapError ($ pcap );
211227 } else {
212- $ ret = $ this -> ffi ->pcap_setfilter ($ pcap , FFI ::addr ($ fp ));
228+ $ ret = self :: $ ffi ->pcap_setfilter ($ pcap , FFI ::addr ($ fp ));
213229
214230 if ($ ret < 0 ) {
215231 $ this ->setLastPcapError ($ pcap );
@@ -221,7 +237,7 @@ public function compile_setfilter(CData $pcap, string $filter): int
221237
222238 public function close (CData $ pcap ): void
223239 {
224- $ this -> ffi ->pcap_close ($ pcap );
240+ self :: $ ffi ->pcap_close ($ pcap );
225241 }
226242
227243 public function getLastError (): string
@@ -236,7 +252,7 @@ private function setLastError(string $error): void
236252
237253 private function setLastPcapError (CData $ pcap ): void
238254 {
239- $ err = $ this -> ffi ->pcap_geterr ($ pcap );
255+ $ err = self :: $ ffi ->pcap_geterr ($ pcap );
240256
241257 if (!is_null ($ err )) {
242258 $ this ->setLastError (FFI ::string ($ err ));
0 commit comments