Net-Nmsg/Nmsg.xs
/*
**
** Copyright (C) 2011-2014 by Carnegie Mellon University
**
** Use of the Net-Silk library and related source code is subject to the
** terms of the following licenses:
**
** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
**
** NO WARRANTY
**
** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
** DELIVERABLES UNDER THIS LICENSE.
**
** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
** Mellon University, its trustees, officers, employees, and agents from
** all claims or demands made against them (and any related losses,
** expenses, or attorney's fees) arising out of, or relating to Licensee's
** and/or its sub licensees' negligent use or willful misuse of or
** negligent conduct or willful misconduct regarding the Software,
** facilities, or other rights or assistance granted by Carnegie Mellon
** University under this License, including, but not limited to, any
** claims of product liability, personal injury, death, damage to
** property, or violation of any laws or regulations.
**
** Carnegie Mellon University Software Engineering Institute authored
** documents are sponsored by the U.S. Department of Defense under
** Contract FA8721-05-C-0003. Carnegie Mellon University retains
** copyrights in all material produced under this contract. The U.S.
** Government retains a non-exclusive, royalty-free license to publish or
** reproduce these documents, or allow others to do so, for U.S.
** Government purposes only pursuant to the copyright license under the
** contract clause at 252.227.7013.
**
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _CYGWIN
#include <windows.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define NEED_PL_signals 1
#include "ppport.h"
#include "pthread.h"
#define MATH_INT64_NATIVE_IF_AVAILABLE
#include "perl_math_int64.h"
#include <nmsg.h>
#include <pcap.h>
#ifdef _CYGWIN
#include <Win32-Extensions.h>
#endif
typedef nmsg_message_t Net__Nmsg__XS__msg;
typedef nmsg_io_t Net__Nmsg__XS__io;
typedef nmsg_input_t Net__Nmsg__XS__input;
typedef nmsg_input_t Net__Nmsg__XS__input_file;
typedef nmsg_input_t Net__Nmsg__XS__input_json;
typedef nmsg_input_t Net__Nmsg__XS__input_sock;
typedef nmsg_input_t Net__Nmsg__XS__input_pres;
typedef nmsg_input_t Net__Nmsg__XS__input_pcap;
typedef nmsg_output_t Net__Nmsg__XS__output;
typedef nmsg_output_t Net__Nmsg__XS__output_file;
typedef nmsg_output_t Net__Nmsg__XS__output_json;
typedef nmsg_output_t Net__Nmsg__XS__output_sock;
typedef nmsg_output_t Net__Nmsg__XS__output_pres;
typedef nmsg_output_t Net__Nmsg__XS__output_cb;
typedef nmsg_rate_t Net__Nmsg__XS__rate;
typedef nmsg_pcap_t Net__Nmsg__XS__nmsg_pcap;
typedef pcap_t *Net__Nmsg__XS__pcap;
typedef enum groknum_err_en {
GROKNUM_OK = 0, /* number ok */
GROKNUM_ERR_NVREF = -1, /* invalid reference */
GROKNUM_ERR_NAS = -2, /* not a string */
GROKNUM_ERR_NAN = -3, /* not a number */
GROKNUM_ERR_U16_OVERFLOW = -4, /* exceeds U16_MAX */
GROKNUM_ERR_U32_OVERFLOW = -5, /* exceeds U32_MAX */
GROKNUM_ERR_U64_OVERFLOW = -6, /* exceeds U64_MAX */
GROKNUM_ERR_I16_OVERFLOW = -7, /* lt I16_MIN or gt I16_MAX */
GROKNUM_ERR_I32_OVERFLOW = -8, /* lt I32_MIN or gt I32_MAX */
GROKNUM_ERR_I64_OVERFLOW = -9, /* lt I64_MIN or gt I64_MAX */
GROKNUM_ERR_UNKNOWN = -10, /* unknown */
} groknum_err_t;
typedef union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
int64_t i64;
int32_t i32;
int16_t i16;
int en;
double dbl;
bool boo;
} nmsg_field_val_u;
#include "strtoint64.h"
#include <signal.h>
#include <assert.h>
#ifdef __cplusplus
}
#endif
#define NMSG_CLASS "Net::Nmsg"
#define MSG_CLASS "Net::Nmsg::Msg"
#define MSG_XS_CLASS "Net::Nmsg::XS::msg"
#define IPV4_CLASS "Net::Nmsg::Field::IPv4"
#define IPV6_CLASS "Net::Nmsg::Field::IPv6"
#define MSG_SUBCLASS(class, vid, mid) \
sprintf(class, MSG_CLASS "::%s::%s", \
nmsg_msgmod_vid_to_vname(vid), \
nmsg_msgmod_msgtype_to_mname(vid, mid))
#define NMSG_FF_REPEATED 0x01
#define NMSG_FF_REQUIRED 0x02
#define NMSG_FF_HIDDEN 0x04
#define NMSG_FF_NOPRINT 0x08
#define GROKNUM_CROAK(rv, msg) \
switch (rv) { \
case GROKNUM_ERR_NVREF: \
croak("%s: invalid reference", msg); \
case GROKNUM_ERR_NAS: \
croak("%s: not a string", msg); \
case GROKNUM_ERR_NAN: \
croak("%s: not an integer", msg); \
case GROKNUM_ERR_U16_OVERFLOW: \
croak("%s: uint16 overflow", msg); \
case GROKNUM_ERR_U32_OVERFLOW: \
croak("%s: uint32 overflow", msg); \
case GROKNUM_ERR_U64_OVERFLOW: \
croak("%s: uint64 overflow", msg); \
case GROKNUM_ERR_I16_OVERFLOW: \
croak("%s: int16 overflow", msg); \
case GROKNUM_ERR_I32_OVERFLOW: \
croak("%s: int32 overflow", msg); \
case GROKNUM_ERR_I64_OVERFLOW: \
croak("%s: int64 overflow", msg); \
case GROKNUM_ERR_UNKNOWN: \
croak("%s: unknown error", msg); \
default: \
croak("%s: invalid error code (%d)", rv); \
}
#define WRAP_MSG(m, msg) \
char class[100]; \
HV *msg_stash; \
AV *arr; \
MSG_SUBCLASS(class, nmsg_message_get_vid(m), nmsg_message_get_msgtype(m)); \
msg_stash = gv_stashpv(class, TRUE); \
arr = newAV(); \
av_push(arr, sv_setref_pv(newSV(0), MSG_XS_CLASS, (char *)m)); \
msg = sv_bless(newRV_noinc(MUTABLE_SV(arr)), msg_stash);
/* callback hooks */
static PerlInterpreter *orig_perl;
static pthread_mutex_t callback_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t presentation_lock = PTHREAD_MUTEX_INITIALIZER;
SV *
_xs_wrap_msg(pTHX_ nmsg_message_t m) {
char class[100];
int32_t vid, mtype;
const char *vname, *mname;
HV *msg_stash;
AV *arr;
vid = nmsg_message_get_vid(m);
vname = nmsg_msgmod_vid_to_vname(vid);
if (vname == NULL)
croak("unknown vendor id %d", vid);
mtype = nmsg_message_get_msgtype(m);
mname = nmsg_msgmod_msgtype_to_mname(vid, mtype);
if (mname == NULL)
croak("unknown vendor/message type %d/%d", vid, mtype);
sprintf(class, MSG_CLASS "::%s::%s", vname, mname);
msg_stash = gv_stashpv(class, TRUE);
arr = newAV();
av_push(arr, sv_setref_pv(newSV(0), MSG_XS_CLASS, (char *)m));
return(sv_bless(newRV_noinc(MUTABLE_SV(arr)), msg_stash));
}
void
output_callback(nmsg_message_t m, void *callback) {
//fprintf(stderr, "\n\nxs output_callback %p %p\n\n", m, callback);
if (callback == NULL || m == NULL)
return;
PERL_SET_CONTEXT(orig_perl);
pthread_mutex_lock(&callback_lock);
{ // C99 compliance
dTHX;
dSP;
ENTER;
SAVETMPS;
// push args onto stack
PUSHMARK(sp);
mXPUSHs(_xs_wrap_msg(aTHX_ m));
PUTBACK;
// re-wrap our callback CV in a reference and invoke perl function
call_sv(sv_2mortal(newRV(MUTABLE_SV(callback))), G_DISCARD);
// clean up
FREETMPS;
LEAVE;
}
pthread_mutex_unlock(&callback_lock);
//fprintf(stderr, "leaving callback fn\n");
}
void
io_closed_callback(struct nmsg_io_close_event *ce) {
if (ce->user == NULL ||
ce->io_type != nmsg_io_io_type_output ||
ce->close_type == nmsg_io_close_type_eof)
return;
//fprintf(stderr, "io_closed_callback: 0x%x\n", (int)ce->user);
PERL_SET_CONTEXT(orig_perl);
pthread_mutex_lock(&callback_lock);
{ // C99 compliance
int count;
IV tmp;
SV *ref;
void *ptr;
dTHX;
dSP;
ENTER;
SAVETMPS;
// push args onto stack
PUSHMARK(sp);
mXPUSHs(newSViv(ce->close_type));
//mXPUSHs(newSViv(ce->io_type));
PUTBACK;
// re-wrap callback CV in a reference and invoke perl function
count = call_sv(sv_2mortal(newRV(MUTABLE_SV(ce->user))), G_SCALAR);
SPAGAIN;
if (count != 1)
croak("single return value required from callback");
ref = POPs;
if (! SvROK(ref))
croak("not a reference");
tmp = SvIV(SvRV(ref));
ptr = INT2PTR(void *, tmp);
if (ptr != NULL) {
//fprintf(stderr, "xs reopen output %p\n", *(ce->output));
*(ce->output) = ptr;
//*(ce->output) = INT2PTR(nmsg_output_t, tmp);
//*(ce->output) = (nmsg_output_t)tmp;
//fprintf(stderr, "xs reopen output %p\n", *(ce->output));
}
PUTBACK;
// clean up
FREETMPS;
LEAVE;
}
pthread_mutex_unlock(&callback_lock);
//fprintf(stderr, "io_closed_callback complete\n");
}
groknum_err_t
_xs_pack_uint16_int(pTHX_ SV *sv, uint16_t *val) {
UV uv;
IV iv;
NV nv;
int64_t i64;
uint64_t u64;
groknum_err_t rv = GROKNUM_OK;
if (SvIOK_UV(sv)) {
uv = SvUV(sv);
if (uv > UINT16_MAX)
rv = GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)uv;
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
if (iv < 0 || iv > UINT16_MAX)
rv = GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < 0 || nv > UINT16_MAX)
rv = GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)SvUV(sv);
}
else if (SvU64OK(sv)) {
u64 = SvU64(sv);
if (u64 > UINT16_MAX)
rv = GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)u64;
}
else if (SvI64OK(sv)) {
i64 = SvI64(sv);
if (i64 < 0 || i64 > UINT16_MAX)
rv = GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)i64;
}
else
rv = GROKNUM_ERR_NAN;
return rv;
}
groknum_err_t
_xs_pack_uint16_strint(pTHX_ SV *sv, uint16_t *val) {
uint64_t u64;
groknum_err_t rv;
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, &u64);
switch (rv) {
case GROKNUM_OK:
if (u64 > UINT16_MAX)
return GROKNUM_ERR_U16_OVERFLOW;
*val = (uint16_t)u64;
return GROKNUM_OK;
case GROKNUM_ERR_I64_OVERFLOW:
case GROKNUM_ERR_U64_OVERFLOW:
return GROKNUM_ERR_U16_OVERFLOW;
default:
return rv;
}
return GROKNUM_ERR_UNKNOWN;
}
uint16_t
_xs_make_uint16(pTHX_ SV *sv) {
uint16_t val;
groknum_err_t rv;
rv = _xs_pack_uint16_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid uint16");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_uint16_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid uint16");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint16");
}
groknum_err_t
_xs_pack_int16_int(pTHX_ SV *sv, int16_t *val) {
UV uv;
IV iv;
NV nv;
int64_t i64;
uint64_t u64;
groknum_err_t rv = GROKNUM_OK;
if (SvIOK_UV(sv)) {
uv = SvUV(sv);
if (uv > UINT16_MAX)
rv = GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)uv;
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
if (iv < INT16_MIN || iv > INT16_MAX)
rv = GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < INT16_MIN || nv > INT16_MAX)
rv = GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)SvIV(sv);
}
else if (SvU64OK(sv)) {
u64 = SvU64(sv);
if (u64 > INT16_MAX)
rv = GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)u64;
}
else if (SvI64OK(sv)) {
i64 = SvI64(sv);
if (i64 < INT16_MIN || i64 > INT16_MAX)
rv = GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)i64;
}
else
rv = GROKNUM_ERR_NAN;
return rv;
}
groknum_err_t
_xs_pack_int16_strint(pTHX_ SV *sv, uint16_t *val) {
uint64_t i64;
groknum_err_t rv;
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, &i64);
switch (rv) {
case GROKNUM_OK:
if (i64 < INT16_MIN || i64 > INT16_MAX)
return GROKNUM_ERR_I16_OVERFLOW;
*val = (int16_t)i64;
return GROKNUM_OK;
case GROKNUM_ERR_I64_OVERFLOW:
case GROKNUM_ERR_U64_OVERFLOW:
return GROKNUM_ERR_I16_OVERFLOW;
default:
return rv;
}
return GROKNUM_ERR_UNKNOWN;
}
int16_t
_xs_make_int16(pTHX_ SV *sv) {
int16_t val;
groknum_err_t rv;
rv = _xs_pack_int16_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid int16");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_int16_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid int16");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int16");
}
groknum_err_t
_xs_pack_uint32_int(pTHX_ SV *sv, uint32_t *val) {
UV uv;
IV iv;
NV nv;
int64_t i64;
uint64_t u64;
groknum_err_t rv = GROKNUM_OK;
if (SvIOK_UV(sv)) {
uv = SvUV(sv);
if (uv > UINT32_MAX)
rv = GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)uv;
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
if (iv < 0 || iv > UINT32_MAX)
rv = GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < 0 || nv > UINT32_MAX)
rv = GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)SvUV(sv);
}
else if (SvU64OK(sv)) {
u64 = SvU64(sv);
if (u64 > UINT32_MAX)
rv = GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)u64;
}
else if (SvI64OK(sv)) {
i64 = SvI64(sv);
if (i64 < 0 || i64 > UINT32_MAX)
rv = GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)i64;
}
else
rv = GROKNUM_ERR_NAN;
return rv;
}
groknum_err_t
_xs_pack_uint32_strint(pTHX_ SV *sv, uint32_t *val) {
uint64_t u64;
groknum_err_t rv;
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, &u64);
switch (rv) {
case GROKNUM_OK:
if (u64 > UINT32_MAX)
return GROKNUM_ERR_U32_OVERFLOW;
*val = (uint32_t)u64;
return GROKNUM_OK;
case GROKNUM_ERR_I64_OVERFLOW:
case GROKNUM_ERR_U64_OVERFLOW:
return GROKNUM_ERR_U32_OVERFLOW;
default:
return rv;
}
return GROKNUM_ERR_UNKNOWN;
}
uint32_t
_xs_make_uint32(pTHX_ SV *sv) {
uint32_t val;
groknum_err_t rv;
rv = _xs_pack_uint32_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid uint32");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_uint32_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid uint32");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint32");
}
groknum_err_t
_xs_pack_int32_int(pTHX_ SV *sv, int32_t *val) {
UV uv;
IV iv;
NV nv;
int64_t i64;
uint64_t u64;
groknum_err_t rv = GROKNUM_OK;
if (SvIOK_UV(sv)) {
uv = SvUV(sv);
if (uv > INT32_MAX)
rv = GROKNUM_ERR_I32_OVERFLOW;
*val = (int32_t)uv;
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
if (iv < INT32_MIN || iv > INT32_MAX)
rv = GROKNUM_ERR_I32_OVERFLOW;
*val = (int32_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < INT32_MIN || nv > INT32_MAX)
rv = GROKNUM_ERR_I32_OVERFLOW;
*val = (int32_t)SvIV(sv);
}
else if (SvU64OK(sv)) {
u64 = SvU64(sv);
if (u64 > INT32_MAX)
rv = GROKNUM_ERR_I32_OVERFLOW;
*val = (uint32_t)u64;
}
else if (SvI64OK(sv)) {
i64 = SvI64(sv);
if (i64 < INT32_MIN || i64 > INT32_MAX)
rv = GROKNUM_ERR_I32_OVERFLOW;
*val = (int32_t)i64;
}
else
rv = GROKNUM_ERR_NAN;
return rv;
}
groknum_err_t
_xs_pack_int32_strint(pTHX_ SV *sv, int32_t *val) {
int64_t i64;
groknum_err_t rv;
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, &i64);
switch (rv) {
case GROKNUM_OK:
if (i64 < INT32_MIN || i64 > INT32_MAX)
return GROKNUM_ERR_I32_OVERFLOW;
*val = (int32_t)i64;
return GROKNUM_OK;
case GROKNUM_ERR_I64_OVERFLOW:
case GROKNUM_ERR_U64_OVERFLOW:
return GROKNUM_ERR_I32_OVERFLOW;
default:
return rv;
}
return GROKNUM_ERR_UNKNOWN;
}
int32_t
_xs_make_int32(pTHX_ SV *sv) {
int32_t val;
groknum_err_t rv;
rv = _xs_pack_int32_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid int32");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_int32_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid int32");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int32");
}
groknum_err_t
_xs_pack_uint64_int(pTHX_ SV *sv, uint64_t *val) {
IV iv;
NV nv;
int64_t i64;
if (SvIOK_UV(sv)) {
*val = (uint64_t)SvUV(sv);
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
if (iv < 0)
return GROKNUM_ERR_U64_OVERFLOW;
*val = (uint64_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < 0 || nv > UINT64_MAX)
return GROKNUM_ERR_U64_OVERFLOW;
*val = (uint64_t)SvUV(sv);
}
else if (SvU64OK(sv)) {
*val = SvU64(sv);
}
else if (SvI64OK(sv)) {
i64 = SvI64(sv);
if (i64 < 0)
return GROKNUM_ERR_U64_OVERFLOW;
*val = (uint64_t)i64;
}
else
return GROKNUM_ERR_NAN;
return GROKNUM_OK;
}
groknum_err_t
_xs_pack_uint64_strint(pTHX_ SV *sv, uint64_t *val) {
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
return strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, val);
}
uint64_t
_xs_make_uint64(pTHX_ SV *sv) {
uint64_t val;
groknum_err_t rv;
rv = _xs_pack_uint64_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid uint64");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_uint64_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid uint64");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint64");
}
groknum_err_t
_xs_pack_int64_int(pTHX_ SV *sv, int64_t *i64) {
IV iv;
NV nv;
uint64_t u64;
if (SvIOK_UV(sv)) {
*i64 = (int64_t)SvUV(sv);
}
else if (SvIOK(sv)) {
iv = SvIV(sv);
*i64 = (int64_t)iv;
}
else if (SvNOK(sv)) {
nv = SvNV(sv);
if (nv < INT64_MIN || nv > INT64_MAX)
return GROKNUM_ERR_I64_OVERFLOW;
*i64 = (int64_t)SvUV(sv);
}
else if (SvU64OK(sv)) {
u64 = SvU64(sv);
if (u64 > INT64_MAX)
return GROKNUM_ERR_I64_OVERFLOW;
*i64 = (int64_t)u64;
}
else if (SvI64OK(sv)) {
*i64 = SvI64(sv);
}
else
return GROKNUM_ERR_NAN;
return GROKNUM_OK;
}
groknum_err_t
_xs_pack_int64_strint(pTHX_ SV *sv, int64_t *i64) {
if (!SvPOK(sv))
return GROKNUM_ERR_NAS;
return strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, i64);
}
int64_t
_xs_make_int64(pTHX_ SV *sv) {
int64_t val;
groknum_err_t rv;
rv = _xs_pack_int64_int(aTHX_ sv, &val);
switch (rv) {
case GROKNUM_OK:
return val;
case GROKNUM_ERR_NAN:
break;
default:
GROKNUM_CROAK(rv, "invalid int64");
}
// check for number-like strings
if (SvPOK(sv)) {
rv = _xs_pack_int64_strint(aTHX_ sv, &val);
if (rv == GROKNUM_OK)
return val;
GROKNUM_CROAK(rv, "invalid int64");
}
GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int64");
}
SV *
_xs_field_to_sv(pTHX_ void *data, size_t len, nmsg_msgmod_field_type type) {
if (data == NULL)
croak("oops null data pointer");
switch (type) {
case nmsg_msgmod_ft_enum:
case nmsg_msgmod_ft_int16:
case nmsg_msgmod_ft_int32:
return newSViv(*(int *)data);
case nmsg_msgmod_ft_uint16:
case nmsg_msgmod_ft_uint32:
return newSVuv(*(unsigned *)data);
case nmsg_msgmod_ft_double:
return newSVnv(*(double *)data);
case nmsg_msgmod_ft_bool:
return boolSV(newSViv(*(int *)data));
case nmsg_msgmod_ft_int64:
return newSVi64(*(int64_t *)data);
case nmsg_msgmod_ft_uint64:
return newSVu64(*(uint64_t *)data);
case nmsg_msgmod_ft_string:
case nmsg_msgmod_ft_mlstring:
// len includes trailing null
return newSVpv((char *)data, len - 1);
// case nmsg_msgmod_ft_ip:
// case nmsg_msgmod_ft_bytes:
default:
return newSVpvn((char *)data, len);
}
}
uint8_t *
_xs_sv_to_field(pTHX_ SV *sv, nmsg_msgmod_field_type type,
nmsg_field_val_u *data, size_t *len) {
switch (type) {
case nmsg_msgmod_ft_int16:
data->i16 = _xs_make_int16(aTHX_ sv);
*len = sizeof(int16_t);
break;
case nmsg_msgmod_ft_uint16:
data->u16 = _xs_make_uint16(aTHX_ sv);
*len = sizeof(uint16_t);
break;
case nmsg_msgmod_ft_int32:
data->i32 = _xs_make_int32(aTHX_ sv);
*len = sizeof(int32_t);
break;
case nmsg_msgmod_ft_uint32:
data->u32 = _xs_make_uint32(aTHX_ sv);
*len = sizeof(uint32_t);
break;
case nmsg_msgmod_ft_int64:
data->i64 = _xs_make_int64(aTHX_ sv);
*len = sizeof(int64_t);
break;
case nmsg_msgmod_ft_uint64:
data->u64 = _xs_make_uint64(aTHX_ sv);
*len = sizeof(uint64_t);
break;
case nmsg_msgmod_ft_enum:
data->en = (int)SvIV(sv);
*len = sizeof(int);
break;
case nmsg_msgmod_ft_double:
data->dbl = (double)SvNV(sv);
break;
case nmsg_msgmod_ft_bool:
data->boo = (bool)SvTRUE(sv);
break;
case nmsg_msgmod_ft_string:
case nmsg_msgmod_ft_mlstring:
data = (void *)SvPV(sv, *len);
*len += 1;
break;
//case nmsg_msgmod_ft_ip:
//case nmsg_msgmod_ft_bytes:
default:
data = (void *)SvPV(sv, *len);
break;
}
return((uint8_t *)data);
}
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util
BOOT:
#define MC(cc) \
newCONSTSUB(stash, #cc, newSViv( cc ))
//
#define MCE(name, ce) \
newCONSTSUB(stash, #name, newSViv( ce ))
//
#define MCPV(name, cc) \
newCONSTSUB(stash, #name, newSVpv( cc, sizeof(cc) ))
// BOOT ends after first blank line outside of a block
{
HV *stash;
stash = gv_stashpv("Net::Nmsg::Util", TRUE);
MC(NMSG_DEFAULT_SNAPLEN);
MC(NMSG_FLAG_FRAGMENT);
MC(NMSG_FLAG_ZLIB);
MC(NMSG_HDRLSZ_V2);
MC(NMSG_HDRSZ);
MC(NMSG_IPSZ_MAX);
MC(NMSG_LENHDRSZ_V1);
MC(NMSG_LENHDRSZ_V2);
MC(NMSG_PAYHDRSZ);
MC(NMSG_RBUFSZ);
MC(NMSG_RBUF_TIMEOUT);
MC(NMSG_VERSION);
MC(NMSG_WBUFSZ_ETHER);
MC(NMSG_WBUFSZ_JUMBO);
MC(NMSG_WBUFSZ_MAX);
MC(NMSG_WBUFSZ_MIN);
MCE(NMSG_INPUT_TYPE, nmsg_io_io_type_input );
MCE(NMSG_OUTPUT_TYPE, nmsg_io_io_type_output);
MCE(NMSG_INPUT_TYPE_STREAM, nmsg_input_type_stream);
MCE(NMSG_INPUT_TYPE_PRES, nmsg_input_type_pres );
MCE(NMSG_INPUT_TYPE_PCAP, nmsg_input_type_pcap );
MCE(NMSG_OUTPUT_TYPE_STREAM, nmsg_output_type_stream );
MCE(NMSG_OUTPUT_TYPE_PRES, nmsg_output_type_pres );
MCE(NMSG_OUTPUT_TYPE_CALLBACK, nmsg_output_type_callback);
MCE(NMSG_OUTPUT_MODE_STRIPE, nmsg_io_output_mode_stripe);
MCE(NMSG_OUTPUT_MODE_MIRROR, nmsg_io_output_mode_mirror);
MCE(NMSG_CLOSE_TYPE_EOF, nmsg_io_close_type_eof );
MCE(NMSG_CLOSE_TYPE_COUNT, nmsg_io_close_type_count );
MCE(NMSG_CLOSE_TYPE_INTERVAL, nmsg_io_close_type_interval);
MCE(NMSG_PCAP_TYPE_FILE, nmsg_pcap_type_file);
MCE(NMSG_PCAP_TYPE_LIVE, nmsg_pcap_type_live);
MCE(NMSG_RES_SUCCESS, nmsg_res_success );
MCE(NMSG_RES_FAILURE, nmsg_res_failure );
MCE(NMSG_RES_EOF, nmsg_res_eof );
MCE(NMSG_RES_MEMFAIL, nmsg_res_memfail );
MCE(NMSG_RES_PBUF_READY, nmsg_res_pbuf_ready );
MCE(NMSG_RES_NOTIMPL, nmsg_res_notimpl );
MCE(NMSG_RES_STOP, nmsg_res_stop );
MCE(NMSG_RES_AGAIN, nmsg_res_again );
MCE(NMSG_RES_PARSE_ERROR, nmsg_res_parse_error );
MCE(NMSG_RES_PCAP_ERROR, nmsg_res_pcap_error );
MCE(NMSG_RES_MAGIC_MISMATCH, nmsg_res_magic_mismatch );
MCE(NMSG_RES_VERSION_MISMATCH, nmsg_res_version_mismatch);
MC(NMSG_FF_REPEATED);
MC(NMSG_FF_REQUIRED);
MC(NMSG_FF_HIDDEN);
MC(NMSG_FF_NOPRINT);
MCE(NMSG_FT_ENUM, nmsg_msgmod_ft_enum );
MCE(NMSG_FT_BYTES, nmsg_msgmod_ft_bytes );
MCE(NMSG_FT_STRING, nmsg_msgmod_ft_string );
MCE(NMSG_FT_MLSTRING, nmsg_msgmod_ft_mlstring);
MCE(NMSG_FT_IP, nmsg_msgmod_ft_ip );
MCE(NMSG_FT_UINT16, nmsg_msgmod_ft_uint16 );
MCE(NMSG_FT_UINT32, nmsg_msgmod_ft_uint32 );
MCE(NMSG_FT_UINT64, nmsg_msgmod_ft_uint64 );
MCE(NMSG_FT_INT16, nmsg_msgmod_ft_int16 );
MCE(NMSG_FT_INT32, nmsg_msgmod_ft_int32 );
MCE(NMSG_FT_INT64, nmsg_msgmod_ft_int64 );
MCE(NMSG_FT_DOUBLE, nmsg_msgmod_ft_double );
MCE(NMSG_FT_BOOL, nmsg_msgmod_ft_bool );
MCE(NMSG_ALIAS_OPERATOR, nmsg_alias_operator);
MCE(NMSG_ALIAS_GROUP, nmsg_alias_group );
MATH_INT64_BOOT;
}
MODULE = Net::Nmsg PACKAGE = Net::Nmsg PREFIX = nmsg_
void
_nmsg_init_lib()
PREINIT:
nmsg_res res;
CODE:
if (NULL == orig_perl)
orig_perl = Perl_get_context();
res = nmsg_init();
if (res != nmsg_res_success)
croak("nmsg_init failed: %s", nmsg_res_lookup(res));
void
nmsg_set_autoclose(autoclose)
_Bool autoclose
void
nmsg_set_debug(debug)
int debug
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util PREFIX = nmsg_
void
nmsg_chalias_lookup(ch)
const char *ch
PREINIT:
char **alias = NULL;
int num_aliases;
int i;
PPCODE:
num_aliases = nmsg_chalias_lookup(ch, &alias);
if (num_aliases > 0) {
for (i = 0; i < num_aliases; i++)
mXPUSHs(newSVpv(alias[i], 0));
}
if (alias != NULL)
nmsg_chalias_free(&alias);
const char *
nmsg_alias_by_key(ae, key)
nmsg_alias_e ae
unsigned key
unsigned
nmsg_alias_by_value(ae, value)
nmsg_alias_e ae
const char *value
void
find_all_devs()
PREINIT:
char err[PCAP_ERRBUF_SIZE];
PPCODE:
pcap_if_t *devs, *d;
if (pcap_findalldevs(&devs, err) == -1)
croak("%s", err);
for (d=devs; d; d=d->next) {
mXPUSHs(newSVpv(d->name, 0));
if (d->description)
mXPUSHs(newSVpv(d->description, 0));
else {
if ((strcmp(d->name,"lo") == 0) || (strcmp(d->name,"lo0") == 0))
mXPUSHs(newSVpv("loopback device", 0));
else
mXPUSHs(newSVpv("unknown device", 0));
}
}
pcap_freealldevs(devs);
const char *
lookup_result(val)
enum nmsg_res val
CODE:
RETVAL = nmsg_res_lookup(val);
OUTPUT:
RETVAL
void
get_timestring()
PREINIT:
char now[32];
struct timespec ts;
struct tm *tm;
time_t t;
char *tstr;
PPCODE:
nmsg_timespec_get(&ts);
t = (time_t) ts.tv_sec;
tm = gmtime(&t);
strftime(now, sizeof(now), "%Y%m%d.%H%M.%s", tm);
nmsg_asprintf(&tstr, "%s.%09ld", now, ts.tv_nsec);
if (tstr == NULL)
croak("problem allocating time string");
mXPUSHs(newSVpv(tstr, 0));
Safefree(tstr);
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util PREFIX = nmsg_msgmod_
PROTOTYPES: ENABLE
nmsg_msgmod_t
_msgmod_lookup(vid, msgtype)
unsigned vid
unsigned msgtype
CODE:
RETVAL = nmsg_msgmod_lookup(vid, msgtype);
OUTPUT:
RETVAL
size_t
nmsg_msgmod_get_max_vid()
size_t
nmsg_msgmod_get_max_msgtype(vid)
unsigned vid
unsigned
nmsg_msgmod_mname_to_msgtype(vid, mname)
unsigned vid
const char *mname
const char *
nmsg_msgmod_msgtype_to_mname(vid, msgtype)
unsigned vid
unsigned msgtype
const char *
nmsg_msgmod_vid_to_vname(vid)
unsigned vid
unsigned
nmsg_msgmod_vname_to_vid(vname)
char *vname
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::io PREFIX = nmsg_io_
PROTOTYPES: ENABLE
Net::Nmsg::XS::io
init(CLASS)
const char *CLASS
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_io_init();
OUTPUT:
RETVAL
void
DESTROY(THIS)
Net::Nmsg::XS::io THIS
CODE:
nmsg_io_destroy(&THIS);
void
nmsg_io_breakloop(THIS)
Net::Nmsg::XS::io THIS
void
loop(THIS)
Net::Nmsg::XS::io THIS
PREINIT:
nmsg_res res;
U32 SAVE_signals;
CODE:
SAVE_signals = PL_signals;
PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
res = nmsg_io_loop(THIS);
PL_signals = SAVE_signals;
if (res != nmsg_res_success)
croak("loop failure(%d): %s", res, nmsg_res_lookup(res));
void
_add_input(THIS, input, ...)
Net::Nmsg::XS::io THIS
Net::Nmsg::XS::input input
PREINIT:
void *user = NULL;
nmsg_res res;
CODE:
if (items > 2) {
if SvROK(ST(2))
user = SvRV(ST(2));
else if SvOK(ST(2))
croak("not a reference");
}
res = nmsg_io_add_input(THIS, input, user);
if (res != nmsg_res_success)
croak("nmsg_io_add_input failed: %s", nmsg_res_lookup(res));
if (user != NULL)
nmsg_io_set_close_fp(THIS, io_closed_callback);
void
_add_output(THIS, output, ...)
Net::Nmsg::XS::io THIS
Net::Nmsg::XS::output output
PREINIT:
void *user = NULL;
nmsg_res res;
CODE:
if (items > 2) {
if SvROK(ST(2))
user = SvRV(ST(2));
else if SvOK(ST(2))
croak("not a reference");
}
res = nmsg_io_add_output(THIS, output, user);
if (res != nmsg_res_success)
croak("nmsg_io_add_output failed: %s", nmsg_res_lookup(res));
if (user != NULL)
nmsg_io_set_close_fp(THIS, io_closed_callback);
void
nmsg_io_set_count(THIS, value)
Net::Nmsg::XS::io THIS
unsigned value
void
nmsg_io_set_debug(THIS, value)
Net::Nmsg::XS::io THIS
unsigned value
void
nmsg_io_set_interval(THIS, value)
Net::Nmsg::XS::io THIS
unsigned value
void
nmsg_io_set_interval_randomized(THIS, value)
Net::Nmsg::XS::io THIS
bool value
void
nmsg_io_set_output_mode(THIS, value)
Net::Nmsg::XS::io THIS
nmsg_io_output_mode value
void
set_mirror(THIS, value)
Net::Nmsg::XS::io THIS
unsigned value
CODE:
if (value > 0)
nmsg_io_set_output_mode(THIS, nmsg_io_output_mode_mirror);
else
nmsg_io_set_output_mode(THIS, nmsg_io_output_mode_stripe);
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::nmsg_pcap PREFIX=nmsg_pcap_
PROTOTYPES: ENABLE
Net::Nmsg::XS::nmsg_pcap
_input_open(CLASS, pcap)
const char *CLASS
Net::Nmsg::XS::pcap pcap
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_pcap_input_open(pcap);
if (RETVAL == NULL)
croak("nmsg_pcap_input_open() failed");
OUTPUT:
RETVAL
void
destroy(THIS)
Net::Nmsg::XS::nmsg_pcap THIS
PREINIT:
nmsg_res res;
CODE:
res = nmsg_pcap_input_close(&THIS);
if (res != nmsg_res_success)
fprintf(stderr, "nmsg_pcap_input_close failed: %s", nmsg_res_lookup(res));
void
set_bpf(THIS, bpf)
Net::Nmsg::XS::nmsg_pcap THIS
char *bpf
PREINIT:
nmsg_res res;
CODE:
res = nmsg_pcap_input_setfilter(THIS, bpf);
if (res != nmsg_res_success)
croak("nmsg_pcap_input_setfilter failed: %s", nmsg_res_lookup(res));
nmsg_pcap_type
nmsg_pcap_get_type(THIS)
Net::Nmsg::XS::nmsg_pcap THIS
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::pcap PREFIX = pcap_
PROTOTYPES: ENABLE
Net::Nmsg::XS::pcap
open_offline(CLASS, fname)
const char *CLASS
const char *fname
PREINIT:
char err[PCAP_ERRBUF_SIZE];
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = pcap_open_offline(fname, err);
if (RETVAL == NULL)
croak("pcap_open_offline() failed: %s", err);
OUTPUT:
RETVAL
Net::Nmsg::XS::pcap
open_live(CLASS, iface, snaplen, promisc)
const char *CLASS
const char *iface
int snaplen
int promisc
PREINIT:
char err[PCAP_ERRBUF_SIZE];
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = pcap_open_live(iface, snaplen, promisc, 0, err);
if (RETVAL == NULL)
croak("pcap_open_offline() failed: %s", err);
OUTPUT:
RETVAL
void
destroy(THIS)
Net::Nmsg::XS::pcap THIS
CODE:
pcap_close(THIS);
int
set_snaplen(THIS, snaplen)
Net::Nmsg::XS::pcap THIS
int snaplen
CODE:
#ifdef LIMITED_PCAP
PERL_UNUSED_VAR(snaplen);
croak("pcap_set_snaplen unavailable in this version of libpcap");
#else
RETVAL = pcap_set_snaplen(THIS, snaplen);
#endif /* LIMITED_PCAP */
OUTPUT:
RETVAL
int
set_promisc(THIS, promisc)
Net::Nmsg::XS::pcap THIS
int promisc
CODE:
#ifdef LIMITED_PCAP
PERL_UNUSED_VAR(promisc);
croak("pcap_set_promisc unavailable in this version of libpcap");
#else
RETVAL = pcap_set_promisc(THIS, promisc);
#endif /* LIMITED_PCAP */
OUTPUT:
RETVAL
void
get_selectable_fd(THIS)
Net::Nmsg::XS::pcap THIS
PREINIT:
int res;
PPCODE:
res = pcap_get_selectable_fd(THIS);
if (res != -1)
mXPUSHi(res);
int
pcap_fileno(THIS)
Net::Nmsg::XS::pcap THIS
char *
pcap_geterr(THIS)
Net::Nmsg::XS::pcap THIS
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::input PREFIX = nmsg_input_
PROTOTYPES: ENABLE
void
destroy(THIS)
Net::Nmsg::XS::input THIS
CODE:
nmsg_input_close(&THIS);
Net::Nmsg::XS::input_file
nmsg_input_open_file(CLASS, fh)
const char *CLASS
PerlIO *fh
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_input_open_file(PerlIO_fileno(fh));
if (RETVAL == NULL)
croak("nmsg_input_open_file() failed");
OUTPUT:
RETVAL
Net::Nmsg::XS::input_json
nmsg_input_open_json(CLASS, fh)
const char *CLASS
PerlIO *fh
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_input_open_json(PerlIO_fileno(fh));
if (RETVAL == NULL)
croak("nmsg_input_open_json() failed");
OUTPUT:
RETVAL
Net::Nmsg::XS::input_sock
nmsg_input_open_sock(CLASS, fh)
const char *CLASS
PerlIO *fh
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_input_open_sock(PerlIO_fileno(fh));
if (RETVAL == NULL)
croak("nmsg_input_open_sock() failed");
OUTPUT:
RETVAL
Net::Nmsg::XS::input_pres
_open_pres(CLASS, fh, vid, mid)
const char *CLASS
PerlIO *fh
unsigned vid
unsigned mid
PREINIT:
nmsg_msgmod_t mod;
CODE:
PERL_UNUSED_VAR(CLASS);
mod = nmsg_msgmod_lookup(vid, mid);
if (mod == NULL)
croak("unknown vendor id '%d' or message type '%d'", vid, mid);
RETVAL = nmsg_input_open_pres(PerlIO_fileno(fh), mod);
if (RETVAL == NULL)
croak("nmsg_input_open_pres() failed");
OUTPUT:
RETVAL
Net::Nmsg::XS::input_pcap
_open_pcap(CLASS, pcap, vid, mid)
const char *CLASS
Net::Nmsg::XS::nmsg_pcap pcap
unsigned vid
unsigned mid
PREINIT:
nmsg_msgmod_t mod;
CODE:
PERL_UNUSED_VAR(CLASS);
mod = nmsg_msgmod_lookup(vid, mid);
if (mod == NULL)
croak("unknown vendor id '%d' or message type '%d'", vid, mid);
RETVAL = nmsg_input_open_pcap(pcap, mod);
if (RETVAL == NULL)
croak("nmsg_input_open_pcap() failed");
OUTPUT:
RETVAL
void
nmsg_input_set_filter_source(THIS, value)
Net::Nmsg::XS::input THIS
unsigned value
void
_set_filter_group(THIS, value)
Net::Nmsg::XS::input THIS
unsigned value
CODE:
nmsg_input_set_filter_group(THIS, value);
void
_set_filter_operator(THIS, value)
Net::Nmsg::XS::input THIS
unsigned value
CODE:
nmsg_input_set_filter_operator(THIS, value);
void
_set_filter_msgtype(THIS, vid, mid)
Net::Nmsg::XS::input THIS
unsigned vid
unsigned mid
CODE:
nmsg_input_set_filter_msgtype(THIS, vid, mid);
void
nmsg_input_set_blocking_io(THIS, flag)
Net::Nmsg::XS::input THIS
bool flag
PREINIT:
nmsg_res res;
PPCODE:
res = nmsg_input_set_blocking_io(THIS, flag);
if (res == nmsg_res_success)
mXPUSHi(flag);
void
read(THIS, blocking_io=true)
Net::Nmsg::XS::input THIS
bool blocking_io
PREINIT:
nmsg_message_t m;
nmsg_res res;
U32 SAVE_signals;
PPCODE:
res = nmsg_res_failure;
while (res != nmsg_res_success) {
SAVE_signals = PL_signals;
PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
res = nmsg_input_read(THIS, &m);
PL_signals = SAVE_signals;
switch (res) {
case (nmsg_res_success):
mXPUSHs(_xs_wrap_msg(aTHX_ m));
goto last_read;
case (nmsg_res_again):
if (blocking_io != true)
goto last_read;
break;
case (nmsg_res_eof):
goto last_read;
default:
croak("nmsg_input_read() failed: %s", nmsg_res_lookup(res));
}
}
last_read:
// return
nmsg_res
loop(THIS, cb, count)
Net::Nmsg::XS::input THIS
int count
CV *cb
PREINIT:
nmsg_res res;
U32 SAVE_signals;
CODE:
SAVE_signals = PL_signals;
PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
res = nmsg_input_loop(THIS, count, output_callback, (void *)cb);
PL_signals = SAVE_signals;
if (res != nmsg_res_success && res != nmsg_res_eof)
croak("nmsg_input_loop() failed(%d): %s", res, nmsg_res_lookup(res));
RETVAL = res;
OUTPUT:
RETVAL
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::output PREFIX = nmsg_output_
PROTOTYPES: ENABLE
void
destroy(THIS)
Net::Nmsg::XS::output THIS
CODE:
nmsg_output_close(&THIS);
Net::Nmsg::XS::output_file
open_file(CLASS, fh, bufsz)
const char *CLASS
PerlIO *fh
size_t bufsz
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_output_open_file(PerlIO_fileno(fh), bufsz);
OUTPUT:
RETVAL
Net::Nmsg::XS::output_json
open_json(CLASS, fh)
const char *CLASS
PerlIO *fh
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_output_open_json(PerlIO_fileno(fh));
OUTPUT:
RETVAL
Net::Nmsg::XS::output_sock
open_sock(CLASS, fh, bufsz)
const char *CLASS
PerlIO *fh
size_t bufsz
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_output_open_sock(PerlIO_fileno(fh), bufsz);
OUTPUT:
RETVAL
Net::Nmsg::XS::output_pres
open_pres(CLASS, fh)
const char *CLASS
PerlIO *fh
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_output_open_pres(PerlIO_fileno(fh));
OUTPUT:
RETVAL
Net::Nmsg::XS::output_cb
open_callback(CLASS, cb)
const char *CLASS
CV *cb
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_output_open_callback(output_callback, (void *)cb);
OUTPUT:
RETVAL
void
nmsg_output_set_buffered(THIS, value)
Net::Nmsg::XS::output THIS
bool value
void
nmsg_output_set_endline(THIS, value)
Net::Nmsg::XS::output THIS
const char *value
void
nmsg_output_set_rate(THIS, rate, freq, rate_obj)
Net::Nmsg::XS::output THIS
unsigned rate
unsigned freq
Net::Nmsg::XS::rate rate_obj
CODE:
PERL_UNUSED_VAR(rate);
PERL_UNUSED_VAR(freq);
nmsg_output_set_rate(THIS, rate_obj);
void
nmsg_output_set_zlibout(THIS, value)
Net::Nmsg::XS::output THIS
bool value
void
nmsg_output_set_group(THIS, value)
Net::Nmsg::XS::output THIS
unsigned value
void
nmsg_output_set_operator(THIS, value)
Net::Nmsg::XS::output THIS
unsigned value
void
nmsg_output_set_source(THIS, value)
Net::Nmsg::XS::output THIS
unsigned value
void
nmsg_output_set_filter_msgtype(THIS, vid, mid)
Net::Nmsg::XS::output THIS
unsigned vid
unsigned mid
void
_write(THIS, msg)
Net::Nmsg::XS::output THIS
Net::Nmsg::XS::msg msg
PREINIT:
nmsg_res res;
U32 SAVE_signals;
CODE:
SAVE_signals = PL_signals;
PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
res = nmsg_output_write(THIS, msg);
PL_signals = SAVE_signals;
if (res != nmsg_res_success)
croak("nmsg_output_write() failed: %s", nmsg_res_lookup(res));
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::rate PREFIX = nmsg_rate_
PROTOTYPES: ENABLE
Net::Nmsg::XS::rate
nmsg_rate_init(CLASS, rate, freq)
char *CLASS
unsigned rate
unsigned freq
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_rate_init(rate, freq);
if (RETVAL == NULL)
croak("rate error %d/%d", rate, freq);
OUTPUT:
RETVAL
void
DESTROY(THIS)
Net::Nmsg::XS::rate THIS
CODE:
nmsg_rate_destroy(&THIS);
MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::msg PREFIX = nmsg_message_
PROTOTYPES: ENABLE
Net::Nmsg::XS::msg
nmsg_message_init(CLASS, mod)
char *CLASS
nmsg_msgmod_t mod
CODE:
PERL_UNUSED_VAR(CLASS);
RETVAL = nmsg_message_init(mod);
OUTPUT:
RETVAL
void
DESTROY(THIS)
Net::Nmsg::XS::msg THIS
CODE:
nmsg_message_destroy(&THIS);
uint32_t
nmsg_message_get_source(THIS)
Net::Nmsg::XS::msg THIS
uint32_t
nmsg_message_get_operator(THIS)
Net::Nmsg::XS::msg THIS
uint32_t
nmsg_message_get_group(THIS)
Net::Nmsg::XS::msg THIS
void
get_time(THIS)
Net::Nmsg::XS::msg THIS
PREINIT:
struct timespec ts;
PPCODE:
nmsg_message_get_time(THIS, &ts);
mXPUSHi(ts.tv_sec);
mXPUSHi(ts.tv_nsec);
void
get_num_fields(THIS)
Net::Nmsg::XS::msg THIS
PREINIT:
nmsg_res res;
size_t len;
PPCODE:
res = nmsg_message_get_num_fields(THIS, &len);
if (res == nmsg_res_success)
mXPUSHu(len);
void
get_num_field_values(THIS, field)
Net::Nmsg::XS::msg THIS
const char *field
PREINIT:
nmsg_res res;
size_t len;
PPCODE:
res = nmsg_message_get_num_field_values(THIS, field, &len);
if (res == nmsg_res_success)
mXPUSHu(len);
void
get_num_field_values_by_idx(THIS, idx)
Net::Nmsg::XS::msg THIS
unsigned idx
PREINIT:
nmsg_res res;
size_t len;
PPCODE:
res = nmsg_message_get_num_field_values_by_idx(THIS, idx, &len);
if (res == nmsg_res_success)
mXPUSHu(len);
void
get_field(THIS, field, v_idx = 0)
Net::Nmsg::XS::msg THIS
const char *field
unsigned v_idx
PREINIT:
nmsg_res res;
size_t len;
void *data;
nmsg_msgmod_field_type type;
PPCODE:
res = nmsg_message_get_field(THIS, field, v_idx, &data, &len);
if (res == nmsg_res_success && data != NULL) {
res = nmsg_message_get_field_type(THIS, field, &type);
if (res == nmsg_res_success) {
mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
}
else
croak("nmsg_message_get_field_type failed: %s",
nmsg_res_lookup(res));
}
void
get_field_vals(THIS, field)
Net::Nmsg::XS::msg THIS
const char *field
PREINIT:
nmsg_res res;
size_t len;
void *data;
nmsg_msgmod_field_type type;
int i;
PPCODE:
res = nmsg_message_get_field_type(THIS, field, &type);
if (res != nmsg_res_success)
croak("nmsg_message_get_field_type failed: %s", nmsg_res_lookup(res));
for (i = 0; ; i++) {
res = nmsg_message_get_field(THIS, field, i, &data, &len);
if (res != nmsg_res_success || data == NULL)
break;
mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
}
void
get_field_by_idx(THIS, f_idx, v_idx = 0)
Net::Nmsg::XS::msg THIS
unsigned f_idx
unsigned v_idx
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
size_t len;
void *data;
PPCODE:
res = nmsg_message_get_field_by_idx(THIS, f_idx, v_idx, &data, &len);
if (res == nmsg_res_success) {
res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
if (res == nmsg_res_success && data != NULL) {
mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
}
else if (res != nmsg_res_success)
croak("nmsg_message_get_field_type_by_idx failed: %s",
nmsg_res_lookup(res));
}
void
get_field_vals_by_idx(THIS, f_idx)
Net::Nmsg::XS::msg THIS
unsigned f_idx
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
size_t len;
void *data;
int i;
PPCODE:
res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
if (res == nmsg_res_success) {
for (i = 0; ; i++) {
res = nmsg_message_get_field_by_idx(THIS, f_idx, i, &data, &len);
if (res != nmsg_res_success || data == NULL)
break;
mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
}
}
void
get_field_flags(THIS, field)
Net::Nmsg::XS::msg THIS
const char *field
PREINIT:
nmsg_res res;
unsigned flags;
PPCODE:
res = nmsg_message_get_field_flags(THIS, field, &flags);
if (res == nmsg_res_success)
mXPUSHu(flags);
void
get_field_flags_by_idx(THIS, f_idx)
Net::Nmsg::XS::msg THIS
unsigned f_idx
PREINIT:
nmsg_res res;
unsigned flags;
PPCODE:
res = nmsg_message_get_field_flags_by_idx(THIS, f_idx, &flags);
if (res == nmsg_res_success)
mXPUSHu(flags);
void
get_field_idx(THIS, name)
Net::Nmsg::XS::msg THIS
const char *name
PREINIT:
nmsg_res res;
unsigned idx;
PPCODE:
res = nmsg_message_get_field_idx(THIS, name, &idx);
if (res == nmsg_res_success)
mXPUSHu(idx);
void
get_field_name(THIS, idx)
Net::Nmsg::XS::msg THIS
unsigned idx
PREINIT:
nmsg_res res;
const char *name;
PPCODE:
res = nmsg_message_get_field_name(THIS, idx, &name);
if (res == nmsg_res_success)
mXPUSHs(newSVpv(name, 0));
void
get_field_type(THIS, name)
Net::Nmsg::XS::msg THIS
const char *name;
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
PPCODE:
res = nmsg_message_get_field_type(THIS, name, &type);
if (res == nmsg_res_success)
mXPUSHi(type);
void
get_field_type_by_idx(THIS, idx)
Net::Nmsg::XS::msg THIS
unsigned idx
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
PPCODE:
res = nmsg_message_get_field_type_by_idx(THIS, idx, &type);
if (res == nmsg_res_success)
mXPUSHi(type);
void
enum_name_to_value(THIS, field, name)
Net::Nmsg::XS::msg THIS
const char *field
const char *name
PREINIT:
nmsg_res res;
unsigned value;
PPCODE:
res = nmsg_message_enum_name_to_value(THIS, field, name, &value);
if (res == nmsg_res_success)
mXPUSHu(value);
void
enum_name_to_value_by_idx(THIS, f_idx, name)
Net::Nmsg::XS::msg THIS
unsigned f_idx
const char *name
PREINIT:
nmsg_res res;
unsigned value;
PPCODE:
res = nmsg_message_enum_name_to_value_by_idx(THIS, f_idx, name, &value);
if (res == nmsg_res_success)
mXPUSHu(value);
void
enum_value_to_name(THIS, field, value)
Net::Nmsg::XS::msg THIS
const char *field
unsigned value
PREINIT:
nmsg_res res;
const char *name;
PPCODE:
res = nmsg_message_enum_value_to_name(THIS, field, value, &name);
if (res == nmsg_res_success)
mXPUSHs(newSVpv(name, 0));
void
enum_value_to_name_by_idx(THIS, f_idx, value)
Net::Nmsg::XS::msg THIS
unsigned f_idx
unsigned value
PREINIT:
nmsg_res res;
const char *name;
PPCODE:
res = nmsg_message_enum_value_to_name_by_idx(THIS, f_idx, value, &name);
if (res == nmsg_res_success)
mXPUSHs(newSVpv(name, 0));
void
set_field(THIS, field, v_idx, sv)
Net::Nmsg::XS::msg THIS
const char *field
unsigned v_idx
SV *sv
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
nmsg_field_val_u data;
uint8_t *bp;
size_t len;
CODE:
res = nmsg_message_get_field_type(THIS, field, &type);
if (res == nmsg_res_success) {
bp = _xs_sv_to_field(aTHX_ sv, type, &data, &len);
res = nmsg_message_set_field(THIS, field, v_idx, bp, len);
if (res != nmsg_res_success)
croak("nmsg_message_set_field failed: %s", nmsg_res_lookup(res));
}
else
croak("nmsg_message_get_field_type failed: %s", nmsg_res_lookup(res));
void
set_field_by_idx(THIS, f_idx, v_idx, sv)
Net::Nmsg::XS::msg THIS
unsigned f_idx
unsigned v_idx
SV *sv;
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
nmsg_field_val_u data;
uint8_t *bp;
size_t len;
CODE:
res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
if (res == nmsg_res_success) {
bp = _xs_sv_to_field(aTHX_ sv, type, &data, &len);
res = nmsg_message_set_field_by_idx(THIS, f_idx, v_idx, bp, len);
if (res != nmsg_res_success)
croak("nmsg_message_set_field_by_idx failed: %s",
nmsg_res_lookup(res));
}
else
croak("nmsg_message_get_field_type_by_idx failed: %s",
nmsg_res_lookup(res));
void
nmsg_message_set_source(THIS, source)
Net::Nmsg::XS::msg THIS
uint32_t source
void
nmsg_message_set_operator(THIS, operator)
Net::Nmsg::XS::msg THIS
uint32_t operator
void
nmsg_message_set_group(THIS, group)
Net::Nmsg::XS::msg THIS
uint32_t group
void
set_time(THIS, time_sec, time_nsec)
Net::Nmsg::XS::msg THIS
long time_sec
int time_nsec
PREINIT:
struct timespec ts;
PPCODE:
ts.tv_sec = time_sec;
ts.tv_nsec = time_nsec;
nmsg_message_set_time(THIS, &ts);
void
message_to_pres(THIS, endline)
Net::Nmsg::XS::msg THIS
const char *endline
PREINIT:
nmsg_res res;
char *pres;
PPCODE:
pthread_mutex_lock(&presentation_lock);
res = nmsg_message_to_pres(THIS, &pres, endline);
if (res != nmsg_res_success)
goto out;
mXPUSHs(newSVpv(pres, 0));
Safefree(pres);
out:
pthread_mutex_unlock(&presentation_lock);
if (res != nmsg_res_success)
croak("nmsg_message_to_pres failed: %s", nmsg_res_lookup(res));
void
get_field_type_descr_by_idx(THIS, f_idx)
Net::Nmsg::XS::msg THIS
unsigned f_idx
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
PPCODE:
res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
if (res == nmsg_res_success) {
mXPUSHs(newSViv(type));
switch (type) {
case nmsg_msgmod_ft_enum:
mXPUSHs(newSVpvs("enum"));
break;
case nmsg_msgmod_ft_int16:
mXPUSHs(newSVpvs("int16"));
break;
case nmsg_msgmod_ft_int32:
mXPUSHs(newSVpvs("int32"));
break;
case nmsg_msgmod_ft_uint16:
mXPUSHs(newSVpvs("uint16"));
break;
case nmsg_msgmod_ft_uint32:
mXPUSHs(newSVpvs("uint32"));
break;
case nmsg_msgmod_ft_uint64:
mXPUSHs(newSVpvs("uint64"));
break;
case nmsg_msgmod_ft_int64:
mXPUSHs(newSVpvs("int64"));
break;
case nmsg_msgmod_ft_string:
mXPUSHs(newSVpvs("string"));
break;
case nmsg_msgmod_ft_mlstring:
mXPUSHs(newSVpvs("mlstring"));
break;
case nmsg_msgmod_ft_bytes:
mXPUSHs(newSVpvs("bytes"));
break;
case nmsg_msgmod_ft_ip:
mXPUSHs(newSVpvs("ip"));
break;
default:
mXPUSHs(newSVpvs("unknown"));
}
}
void
get_field_flag_descr_by_idx(THIS, f_idx)
Net::Nmsg::XS::msg THIS
unsigned f_idx
PREINIT:
nmsg_res res;
unsigned flags;
PPCODE:
res = nmsg_message_get_field_flags_by_idx(THIS, f_idx, &flags);
if (res == nmsg_res_success) {
if (flags & NMSG_FF_REPEATED)
mXPUSHs(newSViv(NMSG_FF_REPEATED));
mXPUSHs(newSVpvs("repeated"));
if (flags & NMSG_FF_REQUIRED)
mXPUSHs(newSViv(NMSG_FF_REQUIRED));
mXPUSHs(newSVpvs("required"));
if (flags & NMSG_FF_HIDDEN)
mXPUSHs(newSViv(NMSG_FF_HIDDEN));
mXPUSHs(newSVpvs("hidden"));
if (flags & NMSG_FF_NOPRINT)
mXPUSHs(newSViv(NMSG_FF_NOPRINT));
mXPUSHs(newSVpvs("noprint"));
}
void
get_field_enum_descr_by_idx(THIS, f_idx)
Net::Nmsg::XS::msg THIS
unsigned f_idx
PREINIT:
nmsg_res res;
nmsg_msgmod_field_type type;
unsigned v;
const char *name;
PPCODE:
res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
if (res == nmsg_res_success && type == nmsg_msgmod_ft_enum) {
for (v = 0; ; v++) {
res = nmsg_message_enum_value_to_name_by_idx(
THIS, f_idx, v, &name);
if (res != nmsg_res_success)
break;
mXPUSHu(v);
mXPUSHs(newSVpv(name, 0));
}
}