1212#include " pcap_session.h"
1313
1414using namespace v8 ;
15+ using Nan::Callback;
16+ using Nan::AsyncQueueWorker;
17+ using Nan::AsyncWorker;
18+ using Nan::Callback;
19+ using Nan::HandleScope;
20+ using Nan::New;
21+ using Nan::Null;
22+ using Nan::To;
23+
24+ class PiWorker : public AsyncWorker {
25+ public:
26+ PiWorker (
27+ Callback *callback,
28+ std::string device,
29+ std::string filter,
30+ int buffer_size,
31+ std::string pcap_output_filename,
32+ int num_packets
33+ )
34+ :
35+ AsyncWorker (callback),
36+ device (device),
37+ filter (filter),
38+ buffer_size (buffer_size),
39+ pcap_output_filename (pcap_output_filename),
40+ num_packets (num_packets)
41+ {}
42+ ~PiWorker () {}
43+
44+ // Executed inside the worker-thread.
45+ // It is not safe to access V8, or V8 data structures
46+ // here, so everything we need for input and output
47+ // should go on `this`.
48+ void Execute () {
49+ if (pcap_lookupnet (device.c_str (), &net, &mask, errbuf) == -1 ) {
50+ net = 0 ;
51+ mask = 0 ;
52+ fprintf (stderr, " warning: %s - this may not actually work\n " , errbuf);
53+ }
54+ pcap_handle = pcap_create (device.c_str (), errbuf);
55+ if (pcap_handle == NULL ) {
56+ Nan::ThrowError (errbuf);
57+ return ;
58+ }
59+
60+ // 64KB is the max IPv4 packet size
61+ if (pcap_set_snaplen (pcap_handle, 65535 ) != 0 ) {
62+ Nan::ThrowError (" error setting snaplen" );
63+ return ;
64+ }
65+
66+ // always use promiscuous mode
67+ if (pcap_set_promisc (pcap_handle, 1 ) != 0 ) {
68+ Nan::ThrowError (" error setting promiscuous mode" );
69+ return ;
70+ }
71+
72+ // Try to set buffer size. Sometimes the OS has a lower limit that it will silently enforce.
73+ if (pcap_set_buffer_size (pcap_handle, buffer_size) != 0 ) {
74+ Nan::ThrowError (" error setting buffer size" );
75+ return ;
76+ }
77+
78+
79+ // set "timeout" on read, even though we are also setting nonblock below. On Linux this is required.
80+ if (pcap_set_timeout (pcap_handle, 1000 ) != 0 ) {
81+ Nan::ThrowError (" error setting read timeout" );
82+ return ;
83+ }
84+
85+ if (pcap_activate (pcap_handle) != 0 ) {
86+ Nan::ThrowError (pcap_geterr (pcap_handle));
87+ return ;
88+ }
89+ if ((pcap_output_filename.size ()) > 0 ) {
90+ pcap_dump_handle = pcap_dump_open (pcap_handle,pcap_output_filename.c_str ());
91+ if (pcap_dump_handle == NULL ) {
92+ Nan::ThrowError (" error opening dump" );
93+ return ;
94+ }
95+ }
96+
97+
98+ if (filter.size () != 0 ) {
99+ if (pcap_compile (pcap_handle, &fp, filter.c_str (), 1 , net) == -1 ) {
100+ Nan::ThrowError (pcap_geterr (pcap_handle));
101+ return ;
102+ }
103+
104+ if (pcap_setfilter (pcap_handle, &fp) == -1 ) {
105+ Nan::ThrowError (pcap_geterr (pcap_handle));
106+ return ;
107+ }
108+
109+ pcap_loop (pcap_handle, num_packets, OnPacketReady, (unsigned char *)pcap_dump_handle);
110+ pcap_freecode (&fp);
111+ }
112+ }
113+
114+ void HandleErrorCallback (){
115+ std::string error = std::string (errbuf);
116+ Local<Value> argv[] = {
117+ Nan::EmptyString ()// TODO convert errbuf to error Message
118+ , Null ()
119+ };
120+
121+ callback->Call (2 , argv);
122+ }
123+
124+ // Executed when the async work is complete
125+ // this function will be run inside the main event loop
126+ // so it is safe to use V8 again
127+ void HandleOKCallback () {
128+
129+ Nan::HandleScope scope;
130+
131+ Local<Value> argv[] = {
132+ Null ()
133+ , New<Number>(num_packets)
134+ };
135+
136+ callback->Call (2 , argv);
137+ }
138+
139+
140+
141+ static void OnPacketReady (u_char *s, const struct pcap_pkthdr * pkthdr, const u_char* packet) {
142+ pcap_dump (s, pkthdr, packet);
143+ }
144+
145+ private:
146+
147+ std::string device;
148+ std::string filter;
149+ int buffer_size;
150+ std::string pcap_output_filename;
151+ int num_packets;
152+ struct bpf_program fp;
153+ bpf_u_int32 mask;
154+ bpf_u_int32 net;
155+ pcap_t *pcap_handle;
156+ pcap_dumper_t *pcap_dump_handle;
157+ char * errbuf;
158+
159+
160+
161+
162+ };
163+
15164
16165// Helper method, convert a sockaddr* (AF_INET or AF_INET6) to a string, and set it as the property
17166// named 'key' in the Address object you pass in.
@@ -135,6 +284,57 @@ NAN_METHOD(LibVersion)
135284 info.GetReturnValue ().Set (Nan::New (pcap_lib_version ()).ToLocalChecked ());
136285}
137286
287+ // Asynchronous access to the `Estimate()` function
288+ NAN_METHOD (PcapDumpAsync) {
289+
290+ if (info.Length () == 8 ) {
291+ if (!info[0 ]->IsString ()) {
292+ Nan::ThrowTypeError (" pcap Open: info[0] must be a String" );
293+ return ;
294+ }
295+ if (!info[1 ]->IsString ()) {
296+ Nan::ThrowTypeError (" pcap Open: info[1] must be a String" );
297+ return ;
298+ }
299+ if (!info[2 ]->IsInt32 ()) {
300+ Nan::ThrowTypeError (" pcap Open: info[2] must be a Number" );
301+ return ;
302+ }
303+ if (!info[3 ]->IsString ()) {
304+ Nan::ThrowTypeError (" pcap Open: info[3] must be a String" );
305+ return ;
306+ }
307+ if (!info[4 ]->IsFunction ()) {
308+ Nan::ThrowTypeError (" pcap Open: info[4] must be a Function" );
309+ return ;
310+ }
311+ if (!info[5 ]->IsBoolean ()) {
312+ Nan::ThrowTypeError (" pcap Open: info[5] must be a Boolean" );
313+ return ;
314+ }
315+ if (!info[6 ]->IsInt32 ()) {
316+ Nan::ThrowTypeError (" pcap Open: info[6] must be a Number" );
317+ return ;
318+ }
319+ if (!info[7 ]->IsFunction ()) {
320+ Nan::ThrowTypeError (" pcap Open: info[7] must be a Function" );
321+ return ;
322+ }
323+ } else {
324+ Nan::ThrowTypeError (" pcap CreatePcapDump: expecting 7 arguments" );
325+ return ;
326+ }
327+ Nan::Utf8String device (info[0 ]->ToString ());
328+ Nan::Utf8String filter (info[1 ]->ToString ());
329+ int buffer_size = info[2 ]->Int32Value ();
330+ Nan::Utf8String pcap_output_filename (info[3 ]->ToString ());
331+ int num_packets = info[6 ]->Int32Value ();
332+ Callback *callback = new Callback (info[7 ].As <Function>());
333+
334+ AsyncQueueWorker (new PiWorker (callback, std::string (*device),std::string (*filter),buffer_size, std::string (*pcap_output_filename),num_packets));
335+ }
336+
337+
138338void Initialize (Handle<Object> exports)
139339{
140340 Nan::HandleScope scope;
@@ -144,6 +344,7 @@ void Initialize(Handle<Object> exports)
144344 exports->Set (Nan::New (" findalldevs" ).ToLocalChecked (), Nan::New<FunctionTemplate>(FindAllDevs)->GetFunction ());
145345 exports->Set (Nan::New (" default_device" ).ToLocalChecked (), Nan::New<FunctionTemplate>(DefaultDevice)->GetFunction ());
146346 exports->Set (Nan::New (" lib_version" ).ToLocalChecked (), Nan::New<FunctionTemplate>(LibVersion)->GetFunction ());
347+ exports->Set (Nan::New (" create_pcap_dump_async" ).ToLocalChecked (), Nan::New<FunctionTemplate>(PcapDumpAsync)->GetFunction ());
147348}
148349
149350NODE_MODULE (pcap_binding, Initialize)
0 commit comments