Skip to content

Commit

Permalink
Fix basic running on Windows and enable prebuild
Browse files Browse the repository at this point in the history
  • Loading branch information
orgads committed Dec 10, 2024
1 parent 5a8f312 commit c56153c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 17 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -29,10 +29,18 @@ jobs:
brew update
brew install libpcap
shell: bash
- name: Add msbuild to PATH
if: matrix.os == 'windows'
uses: microsoft/[email protected]
- 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
Expand Down
18 changes: 15 additions & 3 deletions .github/workflows/prebuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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/[email protected]
- name: Install node-gyp
if: matrix.os == 'windows-latest'
run: |
npm install --global node-gyp@latest
- name: Dependencies
run: |
npm install --ignore-scripts
Expand All @@ -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 }}
Expand Down
2 changes: 1 addition & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
24 changes: 18 additions & 6 deletions pcap_binding.cc
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
#include <nan.h>
#include <assert.h>
#include <pcap/pcap.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifndef _WIN32
#include <pcap/pcap.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#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<Object> Address){
static void SetAddrStringHelper(const char* key, sockaddr *addr, Local<Object> Address){
if(key && addr){
char dst_addr[INET6_ADDRSTRLEN + 1] = {0};
char* src = 0;
Expand All @@ -36,12 +38,15 @@ void SetAddrStringHelper(const char* key, sockaddr *addr, Local<Object> 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;

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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<Object> exports, v8::Local<v8::Value>, void*)
{
Nan::HandleScope scope;

PcapSession::Init(exports);

Nan::Set(exports, Nan::New("findalldevs").ToLocalChecked(), Nan::New<FunctionTemplate>(FindAllDevs)->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());
Expand Down
43 changes: 37 additions & 6 deletions pcap_session.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <assert.h>
#include <pcap/pcap.h>
#include <sys/ioctl.h>
#include <cstring>
#include <string.h>
#ifndef _WIN32
#include <pcap/pcap.h>
#include <sys/ioctl.h>
#endif

#include "pcap_session.h"

Expand Down Expand Up @@ -61,7 +63,9 @@ void PcapSession::New(const Nan::FunctionCallbackInfo<Value>& 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) {
Expand Down Expand Up @@ -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<Value>& 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;
Expand Down Expand Up @@ -128,12 +136,12 @@ void PcapSession::Dispatch(const Nan::FunctionCallbackInfo<Value>& info)
} while (packet_count > 0);

info.GetReturnValue().Set(Nan::New<Integer>(packet_count));
#endif
}

void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo<Value>& info)
{
Nan::HandleScope scope;
char errbuf[PCAP_ERRBUF_SIZE];

if (info.Length() == 10) {
if (!info[0]->IsString()) {
Expand Down Expand Up @@ -190,8 +198,13 @@ void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo<Value>& info)
PcapSession* session = Nan::ObjectWrap::Unwrap<PcapSession>(info.This());

session->packet_ready_cb.SetFunction(info[5].As<Function>());
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;
Expand Down Expand Up @@ -325,6 +338,7 @@ void PcapSession::Open(bool live, const Nan::FunctionCallbackInfo<Value>& info)
break;
}
info.GetReturnValue().Set(ret);
#endif
}

void PcapSession::OpenLive(const Nan::FunctionCallbackInfo<Value>& info)
Expand All @@ -340,6 +354,9 @@ void PcapSession::OpenOffline(const Nan::FunctionCallbackInfo<Value>& info)
void PcapSession::Close(const Nan::FunctionCallbackInfo<Value>& info)
{
Nan::HandleScope scope;
#ifdef _WIN32
Nan::ThrowError("Not supported on Windows");
#else

PcapSession* session = Nan::ObjectWrap::Unwrap<PcapSession>(info.Holder());

Expand All @@ -351,6 +368,7 @@ void PcapSession::Close(const Nan::FunctionCallbackInfo<Value>& info)
if (session->pcap_handle != NULL) {
pcap_breakloop(session->pcap_handle);
}
#endif
}

void PcapSession::FinalizeClose(PcapSession * session) {
Expand All @@ -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();
}
Expand All @@ -389,6 +409,9 @@ void PcapSession::StartPolling(const Nan::FunctionCallbackInfo<Value>& info)
{
Nan::HandleScope scope;

#ifdef _WIN32
Nan::ThrowError("Not supported on Windows");
#else
PcapSession* session = Nan::ObjectWrap::Unwrap<PcapSession>(info.Holder());
if (session->poll_init) return;

Expand Down Expand Up @@ -417,12 +440,16 @@ void PcapSession::StartPolling(const Nan::FunctionCallbackInfo<Value>& 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<Value>& info)
{
Nan::HandleScope scope;

#ifdef _WIN32
Nan::ThrowError("Not supported on Windows");
#else
struct pcap_stat ps;

PcapSession* session = Nan::ObjectWrap::Unwrap<PcapSession>(info.Holder());
Expand All @@ -446,6 +473,7 @@ void PcapSession::Stats(const Nan::FunctionCallbackInfo<Value>& 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<Value>& info)
Expand All @@ -464,6 +492,9 @@ void PcapSession::Inject(const Nan::FunctionCallbackInfo<Value>& info)

PcapSession* session = Nan::ObjectWrap::Unwrap<PcapSession>(info.Holder());

#ifdef _WIN32
Nan::ThrowError("Not supported on Windows");
#else
if (session->pcap_handle == NULL) {
Nan::ThrowError("Error: pcap session already closed");
return;
Expand All @@ -479,5 +510,5 @@ void PcapSession::Inject(const Nan::FunctionCallbackInfo<Value>& info)
Nan::ThrowError("Pcap inject failed.");
return;
}
return;
#endif
}
4 changes: 4 additions & 0 deletions pcap_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include <nan.h>
#include <uv.h>
#ifndef _WIN32
#include <pcap/pcap.h>
#endif

class PcapSession : public Nan::ObjectWrap {
public:
Expand All @@ -30,11 +32,13 @@ class PcapSession : public Nan::ObjectWrap {
Nan::Callback packet_ready_cb;
static Nan::Persistent<v8::Function> 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;
Expand Down

0 comments on commit c56153c

Please sign in to comment.