From c56153c5f86b87a428935d506ac7aca75c55cac2 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 9 Dec 2024 23:14:02 +0200 Subject: [PATCH] Fix basic running on Windows and enable prebuild --- .github/workflows/build.yml | 10 +++++++- .github/workflows/prebuild.yml | 18 +++++++++++--- binding.gyp | 2 +- pcap_binding.cc | 24 ++++++++++++++----- pcap_session.cc | 43 +++++++++++++++++++++++++++++----- pcap_session.h | 4 ++++ 6 files changed, 84 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9cae4e..a052dc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-latest, macos-latest, windows-latest ] node: [ 18, 20, 22 ] fail-fast: false steps: @@ -29,10 +29,18 @@ jobs: brew update brew install libpcap shell: bash + - name: Add msbuild to PATH + if: matrix.os == 'windows' + uses: microsoft/setup-msbuild@v1.3 + - name: Install node-gyp + if: matrix.os == 'windows-latest' + run: | + npm install --global node-gyp@latest - name: Build run: | npm install --build-from-source - name: Test + if: matrix.os != 'windows-latest' run: | npm test timeout-minutes: 1 diff --git a/.github/workflows/prebuild.yml b/.github/workflows/prebuild.yml index ad0d921..4788270 100644 --- a/.github/workflows/prebuild.yml +++ b/.github/workflows/prebuild.yml @@ -6,9 +6,12 @@ on: workflow_dispatch: jobs: - prebuild-macos: - name: macOS - runs-on: macos-latest + prebuild: + strategy: + matrix: + os: [ macos, windows ] + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }}-latest permissions: id-token: write steps: @@ -19,10 +22,18 @@ jobs: node-version: latest registry-url: 'https://registry.npmjs.org' - name: Install dependencies + if: matrix.os == 'macos' run: | brew update brew install libpcap shell: bash + - name: Add msbuild to PATH + if: matrix.os == 'windows' + uses: microsoft/setup-msbuild@v1.3 + - name: Install node-gyp + if: matrix.os == 'windows-latest' + run: | + npm install --global node-gyp@latest - name: Dependencies run: | npm install --ignore-scripts @@ -35,6 +46,7 @@ jobs: env: MAKEFLAGS: -j4 - name: Publish + if: matrix.os == 'macos' run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/binding.gyp b/binding.gyp index cfa6db0..361d43c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,9 +2,9 @@ "targets": [ { "target_name": "pcap_binding", + "sources": [ "pcap_binding.cc", "pcap_session.cc" ], "conditions": [ ['OS!="win"', { - "sources": [ "pcap_binding.cc", "pcap_session.cc" ], "link_settings": { "libraries": [ "-lpcap" diff --git a/pcap_binding.cc b/pcap_binding.cc index 103666e..f821624 100644 --- a/pcap_binding.cc +++ b/pcap_binding.cc @@ -1,22 +1,24 @@ -#include #include -#include #include #include #include #include #include +#ifndef _WIN32 +#include #include #include #include +#endif #include "pcap_session.h" using namespace v8; +#ifndef _WIN32 // Helper method, convert a sockaddr* (AF_INET or AF_INET6) to a string, and set it as the property // named 'key' in the Address object you pass in. -void SetAddrStringHelper(const char* key, sockaddr *addr, Local Address){ +static void SetAddrStringHelper(const char* key, sockaddr *addr, Local Address){ if(key && addr){ char dst_addr[INET6_ADDRSTRLEN + 1] = {0}; char* src = 0; @@ -36,12 +38,15 @@ void SetAddrStringHelper(const char* key, sockaddr *addr, Local Address) } } } - +#endif NAN_METHOD(FindAllDevs) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else char errbuf[PCAP_ERRBUF_SIZE]; pcap_if_t *alldevs, *cur_dev; @@ -87,11 +92,15 @@ NAN_METHOD(FindAllDevs) pcap_freealldevs(alldevs); info.GetReturnValue().Set(DevsArray); +#endif } NAN_METHOD(DefaultDevice) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else char errbuf[PCAP_ERRBUF_SIZE]; // Look up the first device with an address, pcap_lookupdev() just returns the first non-loopback device. @@ -128,18 +137,21 @@ NAN_METHOD(DefaultDevice) } pcap_freealldevs(alldevs); - return; +#endif } NAN_METHOD(LibVersion) { +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else info.GetReturnValue().Set(Nan::New(pcap_lib_version()).ToLocalChecked()); +#endif } static void Initialize(Local exports, v8::Local, void*) { Nan::HandleScope scope; - PcapSession::Init(exports); Nan::Set(exports, Nan::New("findalldevs").ToLocalChecked(), Nan::New(FindAllDevs)->GetFunction(Nan::GetCurrentContext()).ToLocalChecked()); diff --git a/pcap_session.cc b/pcap_session.cc index 2c8b236..d8b940e 100644 --- a/pcap_session.cc +++ b/pcap_session.cc @@ -1,8 +1,10 @@ #include -#include -#include #include #include +#ifndef _WIN32 +#include +#include +#endif #include "pcap_session.h" @@ -61,7 +63,9 @@ void PcapSession::New(const Nan::FunctionCallbackInfo& info) { // void PcapSession::PacketReady(u_char *s, const struct pcap_pkthdr* pkthdr, const u_char* packet) { Nan::HandleScope scope; - +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else PcapSession* session = (PcapSession *)s; if (session->pcap_dump_handle != NULL) { @@ -89,12 +93,16 @@ void PcapSession::PacketReady(u_char *s, const struct pcap_pkthdr* pkthdr, const if (try_catch.HasCaught()) { Nan::FatalException(try_catch); } +#endif } void PcapSession::Dispatch(const Nan::FunctionCallbackInfo& info) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else if (info.Length() != 2) { Nan::ThrowTypeError("Dispatch takes exactly two arguments"); return; @@ -128,12 +136,12 @@ void PcapSession::Dispatch(const Nan::FunctionCallbackInfo& info) } while (packet_count > 0); info.GetReturnValue().Set(Nan::New(packet_count)); +#endif } void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo& info) { Nan::HandleScope scope; - char errbuf[PCAP_ERRBUF_SIZE]; if (info.Length() == 10) { if (!info[0]->IsString()) { @@ -190,8 +198,13 @@ void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo& info) PcapSession* session = Nan::ObjectWrap::Unwrap(info.This()); session->packet_ready_cb.SetFunction(info[5].As()); - session->pcap_dump_handle = NULL; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else + char errbuf[PCAP_ERRBUF_SIZE]; + + session->pcap_dump_handle = NULL; if (live) { if (pcap_lookupnet((char *) *device, &session->net, &session->mask, errbuf) == -1) { session->net = 0; @@ -325,6 +338,7 @@ void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo& info) break; } info.GetReturnValue().Set(ret); +#endif } void PcapSession::OpenLive(const Nan::FunctionCallbackInfo& info) @@ -340,6 +354,9 @@ void PcapSession::OpenOffline(const Nan::FunctionCallbackInfo& info) void PcapSession::Close(const Nan::FunctionCallbackInfo& info) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else PcapSession* session = Nan::ObjectWrap::Unwrap(info.Holder()); @@ -351,6 +368,7 @@ void PcapSession::Close(const Nan::FunctionCallbackInfo& info) if (session->pcap_handle != NULL) { pcap_breakloop(session->pcap_handle); } +#endif } void PcapSession::FinalizeClose(PcapSession * session) { @@ -361,8 +379,10 @@ void PcapSession::FinalizeClose(PcapSession * session) { delete session->poll_resource; } +#ifndef _WIN32 pcap_close(session->pcap_handle); session->pcap_handle = NULL; +#endif session->packet_ready_cb.Reset(); } @@ -389,6 +409,9 @@ void PcapSession::StartPolling(const Nan::FunctionCallbackInfo& info) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else PcapSession* session = Nan::ObjectWrap::Unwrap(info.Holder()); if (session->poll_init) return; @@ -417,12 +440,16 @@ void PcapSession::StartPolling(const Nan::FunctionCallbackInfo& info) uv_ref((uv_handle_t*) &session->poll_handle); session->poll_resource = new Nan::AsyncResource("pcap:PcapSession", info.Holder()); +#endif } void PcapSession::Stats(const Nan::FunctionCallbackInfo& info) { Nan::HandleScope scope; +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else struct pcap_stat ps; PcapSession* session = Nan::ObjectWrap::Unwrap(info.Holder()); @@ -446,6 +473,7 @@ void PcapSession::Stats(const Nan::FunctionCallbackInfo& info) // ps_ifdrop may not be supported on this platform, but there's no good way to tell, is there? info.GetReturnValue().Set(stats_obj); +#endif } void PcapSession::Inject(const Nan::FunctionCallbackInfo& info) @@ -464,6 +492,9 @@ void PcapSession::Inject(const Nan::FunctionCallbackInfo& info) PcapSession* session = Nan::ObjectWrap::Unwrap(info.Holder()); +#ifdef _WIN32 + Nan::ThrowError("Not supported on Windows"); +#else if (session->pcap_handle == NULL) { Nan::ThrowError("Error: pcap session already closed"); return; @@ -479,5 +510,5 @@ void PcapSession::Inject(const Nan::FunctionCallbackInfo& info) Nan::ThrowError("Pcap inject failed."); return; } - return; +#endif } diff --git a/pcap_session.h b/pcap_session.h index e9a458b..03e4e95 100644 --- a/pcap_session.h +++ b/pcap_session.h @@ -3,7 +3,9 @@ #include #include +#ifndef _WIN32 #include +#endif class PcapSession : public Nan::ObjectWrap { public: @@ -30,11 +32,13 @@ class PcapSession : public Nan::ObjectWrap { Nan::Callback packet_ready_cb; static Nan::Persistent constructor; +#ifndef _WIN32 struct bpf_program fp; bpf_u_int32 mask; bpf_u_int32 net; pcap_t *pcap_handle; pcap_dumper_t *pcap_dump_handle; +#endif char *buffer_data; size_t buffer_length; size_t snap_length;