This patch makes pcap.next non-blocking from a Ruby thread perspective. It does eat more CPU if there are no select() loops in the calling Ruby parent, but this isnt too common and never an issue for MSF

git-svn-id: file:///home/svn/framework3/trunk@5534 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2008-06-22 17:14:11 +00:00
parent 13859c23d9
commit 8c244f4422
3 changed files with 42 additions and 11 deletions

View File

@ -8,8 +8,10 @@ if /i386-mswin32/ =~ RUBY_PLATFORM
$CFLAGS = "-DWIN32 -I#{pcap_includedir}"
$LDFLAGS = "/link /LIBPATH:#{pcap_libdir}"
have_library("wpcap", "pcap_open_live")
have_library("wpcap", "pcap_setnonblock")
else
have_library("pcap", "pcap_open_live")
have_library("pcap", "pcap_setnonblock")
end
create_makefile("pcaprub")

View File

@ -10,7 +10,7 @@
static VALUE rb_cPcap;
#define PCAPRUB_VERSION "0.7-dev"
#define PCAPRUB_VERSION "0.8-dev"
#define OFFLINE 1
#define LIVE 2
@ -21,6 +21,13 @@ typedef struct rbpcap {
char type;
} rbpcap_t;
typedef struct rbpcapjob {
struct pcap_pkthdr hdr;
char *pkt;
int wtf;
} rbpcapjob_t;
static VALUE
rbpcap_s_version(VALUE class)
{
@ -259,25 +266,35 @@ rbpcap_inject(VALUE self, VALUE payload)
#endif
}
static void rbpcap_handler(rbpcapjob_t *job, struct pcap_pkthdr *hdr, u_char *pkt){
job->pkt = pkt;
job->hdr = *hdr;
}
static VALUE
rbpcap_next(VALUE self)
{
char *pkt;
rbpcap_t *rbp;
struct pcap_pkthdr pkthdr;
rbpcapjob_t job;
char eb[PCAP_ERRBUF_SIZE];
int ret;
Data_Get_Struct(self, rbpcap_t, rbp);
if(! rbpcap_ready(rbp)) return self;
memset(&pkthdr, 0, sizeof(pkthdr));
pcap_setnonblock(rbp->pd, 1, eb);
TRAP_BEG;
pkt = (char *)pcap_next(rbp->pd, &pkthdr);
while(! (ret = pcap_dispatch(rbp->pd, 1, (pcap_handler) rbpcap_handler, (u_char *)&job))) {
rb_thread_schedule();
}
TRAP_END;
if(pkthdr.caplen > 0)
return rb_str_new(pkt, pkthdr.caplen);
if(job.hdr.caplen > 0)
return rb_str_new(job.pkt, job.hdr.caplen);
return Qnil;
}

View File

@ -79,5 +79,17 @@ class Pcap::UnitTest < Test::Unit::TestCase
r = o.stats
assert_equal(Hash, r.class)
end
def test_pcap_next
=begin
d = Pcap.lookupdev
o = Pcap.open_live(d, 1344, true, 1)
@c = 0
t = Thread.new { while(true); @c += 1; end; }
x = o.next
t.kill
=end
true
end
end