1 /*
2 **
3 ** Copyright (C) 2011-2014 by Carnegie Mellon University
4 **
5 ** Use of the Net-Silk library and related source code is subject to the
6 ** terms of the following licenses:
7 **
8 ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
9 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
10 **
11 ** NO WARRANTY
12 **
13 ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
14 ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
15 ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
16 ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
17 ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
18 ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
19 ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
20 ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
21 ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
22 ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
23 ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
24 ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
25 ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
26 ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
27 ** DELIVERABLES UNDER THIS LICENSE.
28 **
29 ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
30 ** Mellon University, its trustees, officers, employees, and agents from
31 ** all claims or demands made against them (and any related losses,
32 ** expenses, or attorney's fees) arising out of, or relating to Licensee's
33 ** and/or its sub licensees' negligent use or willful misuse of or
34 ** negligent conduct or willful misconduct regarding the Software,
35 ** facilities, or other rights or assistance granted by Carnegie Mellon
36 ** University under this License, including, but not limited to, any
37 ** claims of product liability, personal injury, death, damage to
38 ** property, or violation of any laws or regulations.
39 **
40 ** Carnegie Mellon University Software Engineering Institute authored
41 ** documents are sponsored by the U.S. Department of Defense under
42 ** Contract FA8721-05-C-0003. Carnegie Mellon University retains
43 ** copyrights in all material produced under this contract. The U.S.
44 ** Government retains a non-exclusive, royalty-free license to publish or
45 ** reproduce these documents, or allow others to do so, for U.S.
46 ** Government purposes only pursuant to the copyright license under the
47 ** contract clause at 252.227.7013.
48 **
49 */
50
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54
55 #ifdef _CYGWIN
56 #include <windows.h>
57 #endif
58
59 #ifdef _WIN32
60 #include <windows.h>
61 #endif
62
63 #define PERL_NO_GET_CONTEXT
64
65 #include "EXTERN.h"
66 #include "perl.h"
67 #include "XSUB.h"
68
69 #define NEED_PL_signals 1
70 #include "ppport.h"
71
72 #include "pthread.h"
73
74 #define MATH_INT64_NATIVE_IF_AVAILABLE
75 #include "perl_math_int64.h"
76
77 #include <nmsg.h>
78 #include <pcap.h>
79
80 #ifdef _CYGWIN
81 #include <Win32-Extensions.h>
82 #endif
83
84 typedef nmsg_message_t Net__Nmsg__XS__msg;
85 typedef nmsg_io_t Net__Nmsg__XS__io;
86 typedef nmsg_input_t Net__Nmsg__XS__input;
87 typedef nmsg_input_t Net__Nmsg__XS__input_file;
88 typedef nmsg_input_t Net__Nmsg__XS__input_json;
89 typedef nmsg_input_t Net__Nmsg__XS__input_sock;
90 typedef nmsg_input_t Net__Nmsg__XS__input_pres;
91 typedef nmsg_input_t Net__Nmsg__XS__input_pcap;
92 typedef nmsg_output_t Net__Nmsg__XS__output;
93 typedef nmsg_output_t Net__Nmsg__XS__output_file;
94 typedef nmsg_output_t Net__Nmsg__XS__output_json;
95 typedef nmsg_output_t Net__Nmsg__XS__output_sock;
96 typedef nmsg_output_t Net__Nmsg__XS__output_pres;
97 typedef nmsg_output_t Net__Nmsg__XS__output_cb;
98 typedef nmsg_rate_t Net__Nmsg__XS__rate;
99
100 typedef nmsg_pcap_t Net__Nmsg__XS__nmsg_pcap;
101 typedef pcap_t *Net__Nmsg__XS__pcap;
102
103 typedef enum groknum_err_en {
104 GROKNUM_OK = 0, /* number ok */
105 GROKNUM_ERR_NVREF = -1, /* invalid reference */
106 GROKNUM_ERR_NAS = -2, /* not a string */
107 GROKNUM_ERR_NAN = -3, /* not a number */
108 GROKNUM_ERR_U16_OVERFLOW = -4, /* exceeds U16_MAX */
109 GROKNUM_ERR_U32_OVERFLOW = -5, /* exceeds U32_MAX */
110 GROKNUM_ERR_U64_OVERFLOW = -6, /* exceeds U64_MAX */
111 GROKNUM_ERR_I16_OVERFLOW = -7, /* lt I16_MIN or gt I16_MAX */
112 GROKNUM_ERR_I32_OVERFLOW = -8, /* lt I32_MIN or gt I32_MAX */
113 GROKNUM_ERR_I64_OVERFLOW = -9, /* lt I64_MIN or gt I64_MAX */
114 GROKNUM_ERR_UNKNOWN = -10, /* unknown */
115 } groknum_err_t;
116
117 typedef union {
118 uint64_t u64;
119 uint32_t u32;
120 uint16_t u16;
121 int64_t i64;
122 int32_t i32;
123 int16_t i16;
124 int en;
125 double dbl;
126 bool boo;
127 } nmsg_field_val_u;
128
129 #include "strtoint64.h"
130
131 #include <signal.h>
132 #include <assert.h>
133
134 #ifdef __cplusplus
135 }
136 #endif
137
138 #define NMSG_CLASS "Net::Nmsg"
139 #define MSG_CLASS "Net::Nmsg::Msg"
140 #define MSG_XS_CLASS "Net::Nmsg::XS::msg"
141 #define IPV4_CLASS "Net::Nmsg::Field::IPv4"
142 #define IPV6_CLASS "Net::Nmsg::Field::IPv6"
143
144 #define MSG_SUBCLASS(class, vid, mid) \
145 sprintf(class, MSG_CLASS "::%s::%s", \
146 nmsg_msgmod_vid_to_vname(vid), \
147 nmsg_msgmod_msgtype_to_mname(vid, mid))
148
149 #define NMSG_FF_REPEATED 0x01
150 #define NMSG_FF_REQUIRED 0x02
151 #define NMSG_FF_HIDDEN 0x04
152 #define NMSG_FF_NOPRINT 0x08
153
154 #define GROKNUM_CROAK(rv, msg) \
155 switch (rv) { \
156 case GROKNUM_ERR_NVREF: \
157 croak("%s: invalid reference", msg); \
158 case GROKNUM_ERR_NAS: \
159 croak("%s: not a string", msg); \
160 case GROKNUM_ERR_NAN: \
161 croak("%s: not an integer", msg); \
162 case GROKNUM_ERR_U16_OVERFLOW: \
163 croak("%s: uint16 overflow", msg); \
164 case GROKNUM_ERR_U32_OVERFLOW: \
165 croak("%s: uint32 overflow", msg); \
166 case GROKNUM_ERR_U64_OVERFLOW: \
167 croak("%s: uint64 overflow", msg); \
168 case GROKNUM_ERR_I16_OVERFLOW: \
169 croak("%s: int16 overflow", msg); \
170 case GROKNUM_ERR_I32_OVERFLOW: \
171 croak("%s: int32 overflow", msg); \
172 case GROKNUM_ERR_I64_OVERFLOW: \
173 croak("%s: int64 overflow", msg); \
174 case GROKNUM_ERR_UNKNOWN: \
175 croak("%s: unknown error", msg); \
176 default: \
177 croak("%s: invalid error code (%d)", rv); \
178 }
179
180 #define WRAP_MSG(m, msg) \
181 char class[100]; \
182 HV *msg_stash; \
183 AV *arr; \
184 MSG_SUBCLASS(class, nmsg_message_get_vid(m), nmsg_message_get_msgtype(m)); \
185 msg_stash = gv_stashpv(class, TRUE); \
186 arr = newAV(); \
187 av_push(arr, sv_setref_pv(newSV(0), MSG_XS_CLASS, (char *)m)); \
188 msg = sv_bless(newRV_noinc(MUTABLE_SV(arr)), msg_stash);
189
190 /* callback hooks */
191
192 static PerlInterpreter *orig_perl;
193 static pthread_mutex_t callback_lock = PTHREAD_MUTEX_INITIALIZER;
194 static pthread_mutex_t presentation_lock = PTHREAD_MUTEX_INITIALIZER;
195
196 SV *
_xs_wrap_msg(pTHX_ nmsg_message_t m)197 _xs_wrap_msg(pTHX_ nmsg_message_t m) {
198 char class[100];
199 int32_t vid, mtype;
200 const char *vname, *mname;
201 HV *msg_stash;
202 AV *arr;
203
204 vid = nmsg_message_get_vid(m);
205 vname = nmsg_msgmod_vid_to_vname(vid);
206 if (vname == NULL)
207 croak("unknown vendor id %d", vid);
208 mtype = nmsg_message_get_msgtype(m);
209 mname = nmsg_msgmod_msgtype_to_mname(vid, mtype);
210 if (mname == NULL)
211 croak("unknown vendor/message type %d/%d", vid, mtype);
212 sprintf(class, MSG_CLASS "::%s::%s", vname, mname);
213 msg_stash = gv_stashpv(class, TRUE);
214 arr = newAV();
215 av_push(arr, sv_setref_pv(newSV(0), MSG_XS_CLASS, (char *)m));
216 return(sv_bless(newRV_noinc(MUTABLE_SV(arr)), msg_stash));
217 }
218
219 void
output_callback(nmsg_message_t m,void * callback)220 output_callback(nmsg_message_t m, void *callback) {
221
222 //fprintf(stderr, "\n\nxs output_callback %p %p\n\n", m, callback);
223
224 if (callback == NULL || m == NULL)
225 return;
226
227 PERL_SET_CONTEXT(orig_perl);
228 pthread_mutex_lock(&callback_lock);
229
230 { // C99 compliance
231
232 dTHX;
233 dSP;
234
235 ENTER;
236 SAVETMPS;
237 // push args onto stack
238 PUSHMARK(sp);
239 mXPUSHs(_xs_wrap_msg(aTHX_ m));
240 PUTBACK;
241 // re-wrap our callback CV in a reference and invoke perl function
242 call_sv(sv_2mortal(newRV(MUTABLE_SV(callback))), G_DISCARD);
243 // clean up
244 FREETMPS;
245 LEAVE;
246 }
247
248 pthread_mutex_unlock(&callback_lock);
249
250 //fprintf(stderr, "leaving callback fn\n");
251 }
252
253 void
io_closed_callback(struct nmsg_io_close_event * ce)254 io_closed_callback(struct nmsg_io_close_event *ce) {
255
256 if (ce->user == NULL ||
257 ce->io_type != nmsg_io_io_type_output ||
258 ce->close_type == nmsg_io_close_type_eof)
259 return;
260
261 //fprintf(stderr, "io_closed_callback: 0x%x\n", (int)ce->user);
262
263 PERL_SET_CONTEXT(orig_perl);
264 pthread_mutex_lock(&callback_lock);
265
266 { // C99 compliance
267
268 int count;
269 IV tmp;
270 SV *ref;
271 void *ptr;
272
273 dTHX;
274 dSP;
275
276 ENTER;
277 SAVETMPS;
278 // push args onto stack
279 PUSHMARK(sp);
280 mXPUSHs(newSViv(ce->close_type));
281 //mXPUSHs(newSViv(ce->io_type));
282 PUTBACK;
283 // re-wrap callback CV in a reference and invoke perl function
284 count = call_sv(sv_2mortal(newRV(MUTABLE_SV(ce->user))), G_SCALAR);
285 SPAGAIN;
286 if (count != 1)
287 croak("single return value required from callback");
288 ref = POPs;
289 if (! SvROK(ref))
290 croak("not a reference");
291 tmp = SvIV(SvRV(ref));
292 ptr = INT2PTR(void *, tmp);
293 if (ptr != NULL) {
294 //fprintf(stderr, "xs reopen output %p\n", *(ce->output));
295 *(ce->output) = ptr;
296 //*(ce->output) = INT2PTR(nmsg_output_t, tmp);
297 //*(ce->output) = (nmsg_output_t)tmp;
298 //fprintf(stderr, "xs reopen output %p\n", *(ce->output));
299 }
300 PUTBACK;
301
302 // clean up
303 FREETMPS;
304 LEAVE;
305 }
306
307 pthread_mutex_unlock(&callback_lock);
308
309 //fprintf(stderr, "io_closed_callback complete\n");
310 }
311
312 groknum_err_t
_xs_pack_uint16_int(pTHX_ SV * sv,uint16_t * val)313 _xs_pack_uint16_int(pTHX_ SV *sv, uint16_t *val) {
314 UV uv;
315 IV iv;
316 NV nv;
317 int64_t i64;
318 uint64_t u64;
319 groknum_err_t rv = GROKNUM_OK;
320
321 if (SvIOK_UV(sv)) {
322 uv = SvUV(sv);
323 if (uv > UINT16_MAX)
324 rv = GROKNUM_ERR_U16_OVERFLOW;
325 *val = (uint16_t)uv;
326 }
327 else if (SvIOK(sv)) {
328 iv = SvIV(sv);
329 if (iv < 0 || iv > UINT16_MAX)
330 rv = GROKNUM_ERR_U16_OVERFLOW;
331 *val = (uint16_t)iv;
332 }
333 else if (SvNOK(sv)) {
334 nv = SvNV(sv);
335 if (nv < 0 || nv > UINT16_MAX)
336 rv = GROKNUM_ERR_U16_OVERFLOW;
337 *val = (uint16_t)SvUV(sv);
338 }
339 else if (SvU64OK(sv)) {
340 u64 = SvU64(sv);
341 if (u64 > UINT16_MAX)
342 rv = GROKNUM_ERR_U16_OVERFLOW;
343 *val = (uint16_t)u64;
344 }
345 else if (SvI64OK(sv)) {
346 i64 = SvI64(sv);
347 if (i64 < 0 || i64 > UINT16_MAX)
348 rv = GROKNUM_ERR_U16_OVERFLOW;
349 *val = (uint16_t)i64;
350 }
351 else
352 rv = GROKNUM_ERR_NAN;
353
354 return rv;
355 }
356
357 groknum_err_t
_xs_pack_uint16_strint(pTHX_ SV * sv,uint16_t * val)358 _xs_pack_uint16_strint(pTHX_ SV *sv, uint16_t *val) {
359 uint64_t u64;
360 groknum_err_t rv;
361
362 if (!SvPOK(sv))
363 return GROKNUM_ERR_NAS;
364 rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, &u64);
365 switch (rv) {
366 case GROKNUM_OK:
367 if (u64 > UINT16_MAX)
368 return GROKNUM_ERR_U16_OVERFLOW;
369 *val = (uint16_t)u64;
370 return GROKNUM_OK;
371 case GROKNUM_ERR_I64_OVERFLOW:
372 case GROKNUM_ERR_U64_OVERFLOW:
373 return GROKNUM_ERR_U16_OVERFLOW;
374 default:
375 return rv;
376 }
377 return GROKNUM_ERR_UNKNOWN;
378 }
379
380 uint16_t
_xs_make_uint16(pTHX_ SV * sv)381 _xs_make_uint16(pTHX_ SV *sv) {
382 uint16_t val;
383 groknum_err_t rv;
384
385 rv = _xs_pack_uint16_int(aTHX_ sv, &val);
386 switch (rv) {
387 case GROKNUM_OK:
388 return val;
389 case GROKNUM_ERR_NAN:
390 break;
391 default:
392 GROKNUM_CROAK(rv, "invalid uint16");
393 }
394 // check for number-like strings
395 if (SvPOK(sv)) {
396 rv = _xs_pack_uint16_strint(aTHX_ sv, &val);
397 if (rv == GROKNUM_OK)
398 return val;
399 GROKNUM_CROAK(rv, "invalid uint16");
400 }
401 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint16");
402 }
403
404 groknum_err_t
_xs_pack_int16_int(pTHX_ SV * sv,int16_t * val)405 _xs_pack_int16_int(pTHX_ SV *sv, int16_t *val) {
406 UV uv;
407 IV iv;
408 NV nv;
409 int64_t i64;
410 uint64_t u64;
411 groknum_err_t rv = GROKNUM_OK;
412
413 if (SvIOK_UV(sv)) {
414 uv = SvUV(sv);
415 if (uv > UINT16_MAX)
416 rv = GROKNUM_ERR_I16_OVERFLOW;
417 *val = (int16_t)uv;
418 }
419 else if (SvIOK(sv)) {
420 iv = SvIV(sv);
421 if (iv < INT16_MIN || iv > INT16_MAX)
422 rv = GROKNUM_ERR_I16_OVERFLOW;
423 *val = (int16_t)iv;
424 }
425 else if (SvNOK(sv)) {
426 nv = SvNV(sv);
427 if (nv < INT16_MIN || nv > INT16_MAX)
428 rv = GROKNUM_ERR_I16_OVERFLOW;
429 *val = (int16_t)SvIV(sv);
430 }
431 else if (SvU64OK(sv)) {
432 u64 = SvU64(sv);
433 if (u64 > INT16_MAX)
434 rv = GROKNUM_ERR_I16_OVERFLOW;
435 *val = (int16_t)u64;
436 }
437 else if (SvI64OK(sv)) {
438 i64 = SvI64(sv);
439 if (i64 < INT16_MIN || i64 > INT16_MAX)
440 rv = GROKNUM_ERR_I16_OVERFLOW;
441 *val = (int16_t)i64;
442 }
443 else
444 rv = GROKNUM_ERR_NAN;
445
446 return rv;
447 }
448
449 groknum_err_t
_xs_pack_int16_strint(pTHX_ SV * sv,uint16_t * val)450 _xs_pack_int16_strint(pTHX_ SV *sv, uint16_t *val) {
451 uint64_t i64;
452 groknum_err_t rv;
453
454 if (!SvPOK(sv))
455 return GROKNUM_ERR_NAS;
456 rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, &i64);
457 switch (rv) {
458 case GROKNUM_OK:
459 if (i64 < INT16_MIN || i64 > INT16_MAX)
460 return GROKNUM_ERR_I16_OVERFLOW;
461 *val = (int16_t)i64;
462 return GROKNUM_OK;
463 case GROKNUM_ERR_I64_OVERFLOW:
464 case GROKNUM_ERR_U64_OVERFLOW:
465 return GROKNUM_ERR_I16_OVERFLOW;
466 default:
467 return rv;
468 }
469 return GROKNUM_ERR_UNKNOWN;
470 }
471
472 int16_t
_xs_make_int16(pTHX_ SV * sv)473 _xs_make_int16(pTHX_ SV *sv) {
474 int16_t val;
475 groknum_err_t rv;
476
477 rv = _xs_pack_int16_int(aTHX_ sv, &val);
478 switch (rv) {
479 case GROKNUM_OK:
480 return val;
481 case GROKNUM_ERR_NAN:
482 break;
483 default:
484 GROKNUM_CROAK(rv, "invalid int16");
485 }
486 // check for number-like strings
487 if (SvPOK(sv)) {
488 rv = _xs_pack_int16_strint(aTHX_ sv, &val);
489 if (rv == GROKNUM_OK)
490 return val;
491 GROKNUM_CROAK(rv, "invalid int16");
492 }
493 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int16");
494 }
495
496 groknum_err_t
_xs_pack_uint32_int(pTHX_ SV * sv,uint32_t * val)497 _xs_pack_uint32_int(pTHX_ SV *sv, uint32_t *val) {
498 UV uv;
499 IV iv;
500 NV nv;
501 int64_t i64;
502 uint64_t u64;
503 groknum_err_t rv = GROKNUM_OK;
504
505 if (SvIOK_UV(sv)) {
506 uv = SvUV(sv);
507 if (uv > UINT32_MAX)
508 rv = GROKNUM_ERR_U32_OVERFLOW;
509 *val = (uint32_t)uv;
510 }
511 else if (SvIOK(sv)) {
512 iv = SvIV(sv);
513 if (iv < 0 || iv > UINT32_MAX)
514 rv = GROKNUM_ERR_U32_OVERFLOW;
515 *val = (uint32_t)iv;
516 }
517 else if (SvNOK(sv)) {
518 nv = SvNV(sv);
519 if (nv < 0 || nv > UINT32_MAX)
520 rv = GROKNUM_ERR_U32_OVERFLOW;
521 *val = (uint32_t)SvUV(sv);
522 }
523 else if (SvU64OK(sv)) {
524 u64 = SvU64(sv);
525 if (u64 > UINT32_MAX)
526 rv = GROKNUM_ERR_U32_OVERFLOW;
527 *val = (uint32_t)u64;
528 }
529 else if (SvI64OK(sv)) {
530 i64 = SvI64(sv);
531 if (i64 < 0 || i64 > UINT32_MAX)
532 rv = GROKNUM_ERR_U32_OVERFLOW;
533 *val = (uint32_t)i64;
534 }
535 else
536 rv = GROKNUM_ERR_NAN;
537
538 return rv;
539 }
540
541 groknum_err_t
_xs_pack_uint32_strint(pTHX_ SV * sv,uint32_t * val)542 _xs_pack_uint32_strint(pTHX_ SV *sv, uint32_t *val) {
543 uint64_t u64;
544 groknum_err_t rv;
545
546 if (!SvPOK(sv))
547 return GROKNUM_ERR_NAS;
548 rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, &u64);
549 switch (rv) {
550 case GROKNUM_OK:
551 if (u64 > UINT32_MAX)
552 return GROKNUM_ERR_U32_OVERFLOW;
553 *val = (uint32_t)u64;
554 return GROKNUM_OK;
555 case GROKNUM_ERR_I64_OVERFLOW:
556 case GROKNUM_ERR_U64_OVERFLOW:
557 return GROKNUM_ERR_U32_OVERFLOW;
558 default:
559 return rv;
560 }
561 return GROKNUM_ERR_UNKNOWN;
562 }
563
564 uint32_t
_xs_make_uint32(pTHX_ SV * sv)565 _xs_make_uint32(pTHX_ SV *sv) {
566 uint32_t val;
567 groknum_err_t rv;
568
569 rv = _xs_pack_uint32_int(aTHX_ sv, &val);
570 switch (rv) {
571 case GROKNUM_OK:
572 return val;
573 case GROKNUM_ERR_NAN:
574 break;
575 default:
576 GROKNUM_CROAK(rv, "invalid uint32");
577 }
578 // check for number-like strings
579 if (SvPOK(sv)) {
580 rv = _xs_pack_uint32_strint(aTHX_ sv, &val);
581 if (rv == GROKNUM_OK)
582 return val;
583 GROKNUM_CROAK(rv, "invalid uint32");
584 }
585 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint32");
586 }
587
588 groknum_err_t
_xs_pack_int32_int(pTHX_ SV * sv,int32_t * val)589 _xs_pack_int32_int(pTHX_ SV *sv, int32_t *val) {
590 UV uv;
591 IV iv;
592 NV nv;
593 int64_t i64;
594 uint64_t u64;
595 groknum_err_t rv = GROKNUM_OK;
596
597 if (SvIOK_UV(sv)) {
598 uv = SvUV(sv);
599 if (uv > INT32_MAX)
600 rv = GROKNUM_ERR_I32_OVERFLOW;
601 *val = (int32_t)uv;
602 }
603 else if (SvIOK(sv)) {
604 iv = SvIV(sv);
605 if (iv < INT32_MIN || iv > INT32_MAX)
606 rv = GROKNUM_ERR_I32_OVERFLOW;
607 *val = (int32_t)iv;
608 }
609 else if (SvNOK(sv)) {
610 nv = SvNV(sv);
611 if (nv < INT32_MIN || nv > INT32_MAX)
612 rv = GROKNUM_ERR_I32_OVERFLOW;
613 *val = (int32_t)SvIV(sv);
614 }
615 else if (SvU64OK(sv)) {
616 u64 = SvU64(sv);
617 if (u64 > INT32_MAX)
618 rv = GROKNUM_ERR_I32_OVERFLOW;
619 *val = (uint32_t)u64;
620 }
621 else if (SvI64OK(sv)) {
622 i64 = SvI64(sv);
623 if (i64 < INT32_MIN || i64 > INT32_MAX)
624 rv = GROKNUM_ERR_I32_OVERFLOW;
625 *val = (int32_t)i64;
626 }
627 else
628 rv = GROKNUM_ERR_NAN;
629
630 return rv;
631 }
632
633 groknum_err_t
_xs_pack_int32_strint(pTHX_ SV * sv,int32_t * val)634 _xs_pack_int32_strint(pTHX_ SV *sv, int32_t *val) {
635 int64_t i64;
636 groknum_err_t rv;
637
638 if (!SvPOK(sv))
639 return GROKNUM_ERR_NAS;
640 rv = strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, &i64);
641 switch (rv) {
642 case GROKNUM_OK:
643 if (i64 < INT32_MIN || i64 > INT32_MAX)
644 return GROKNUM_ERR_I32_OVERFLOW;
645 *val = (int32_t)i64;
646 return GROKNUM_OK;
647 case GROKNUM_ERR_I64_OVERFLOW:
648 case GROKNUM_ERR_U64_OVERFLOW:
649 return GROKNUM_ERR_I32_OVERFLOW;
650 default:
651 return rv;
652 }
653 return GROKNUM_ERR_UNKNOWN;
654 }
655
656 int32_t
_xs_make_int32(pTHX_ SV * sv)657 _xs_make_int32(pTHX_ SV *sv) {
658 int32_t val;
659 groknum_err_t rv;
660
661 rv = _xs_pack_int32_int(aTHX_ sv, &val);
662 switch (rv) {
663 case GROKNUM_OK:
664 return val;
665 case GROKNUM_ERR_NAN:
666 break;
667 default:
668 GROKNUM_CROAK(rv, "invalid int32");
669 }
670 // check for number-like strings
671 if (SvPOK(sv)) {
672 rv = _xs_pack_int32_strint(aTHX_ sv, &val);
673 if (rv == GROKNUM_OK)
674 return val;
675 GROKNUM_CROAK(rv, "invalid int32");
676 }
677 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int32");
678 }
679
680 groknum_err_t
_xs_pack_uint64_int(pTHX_ SV * sv,uint64_t * val)681 _xs_pack_uint64_int(pTHX_ SV *sv, uint64_t *val) {
682 IV iv;
683 NV nv;
684 int64_t i64;
685
686 if (SvIOK_UV(sv)) {
687 *val = (uint64_t)SvUV(sv);
688 }
689 else if (SvIOK(sv)) {
690 iv = SvIV(sv);
691 if (iv < 0)
692 return GROKNUM_ERR_U64_OVERFLOW;
693 *val = (uint64_t)iv;
694 }
695 else if (SvNOK(sv)) {
696 nv = SvNV(sv);
697 if (nv < 0 || nv > UINT64_MAX)
698 return GROKNUM_ERR_U64_OVERFLOW;
699 *val = (uint64_t)SvUV(sv);
700 }
701 else if (SvU64OK(sv)) {
702 *val = SvU64(sv);
703 }
704 else if (SvI64OK(sv)) {
705 i64 = SvI64(sv);
706 if (i64 < 0)
707 return GROKNUM_ERR_U64_OVERFLOW;
708 *val = (uint64_t)i64;
709 }
710 else
711 return GROKNUM_ERR_NAN;
712 return GROKNUM_OK;
713 }
714
715 groknum_err_t
_xs_pack_uint64_strint(pTHX_ SV * sv,uint64_t * val)716 _xs_pack_uint64_strint(pTHX_ SV *sv, uint64_t *val) {
717 if (!SvPOK(sv))
718 return GROKNUM_ERR_NAS;
719 return strtoint64(aTHX_ SvPV_nolen(sv), 0, 0, val);
720 }
721
722 uint64_t
_xs_make_uint64(pTHX_ SV * sv)723 _xs_make_uint64(pTHX_ SV *sv) {
724 uint64_t val;
725 groknum_err_t rv;
726
727 rv = _xs_pack_uint64_int(aTHX_ sv, &val);
728 switch (rv) {
729 case GROKNUM_OK:
730 return val;
731 case GROKNUM_ERR_NAN:
732 break;
733 default:
734 GROKNUM_CROAK(rv, "invalid uint64");
735 }
736 // check for number-like strings
737 if (SvPOK(sv)) {
738 rv = _xs_pack_uint64_strint(aTHX_ sv, &val);
739 if (rv == GROKNUM_OK)
740 return val;
741 GROKNUM_CROAK(rv, "invalid uint64");
742 }
743 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid uint64");
744 }
745
746 groknum_err_t
_xs_pack_int64_int(pTHX_ SV * sv,int64_t * i64)747 _xs_pack_int64_int(pTHX_ SV *sv, int64_t *i64) {
748 IV iv;
749 NV nv;
750 uint64_t u64;
751
752 if (SvIOK_UV(sv)) {
753 *i64 = (int64_t)SvUV(sv);
754 }
755 else if (SvIOK(sv)) {
756 iv = SvIV(sv);
757 *i64 = (int64_t)iv;
758 }
759 else if (SvNOK(sv)) {
760 nv = SvNV(sv);
761 if (nv < INT64_MIN || nv > INT64_MAX)
762 return GROKNUM_ERR_I64_OVERFLOW;
763 *i64 = (int64_t)SvUV(sv);
764 }
765 else if (SvU64OK(sv)) {
766 u64 = SvU64(sv);
767 if (u64 > INT64_MAX)
768 return GROKNUM_ERR_I64_OVERFLOW;
769 *i64 = (int64_t)u64;
770 }
771 else if (SvI64OK(sv)) {
772 *i64 = SvI64(sv);
773 }
774 else
775 return GROKNUM_ERR_NAN;
776 return GROKNUM_OK;
777 }
778
779 groknum_err_t
_xs_pack_int64_strint(pTHX_ SV * sv,int64_t * i64)780 _xs_pack_int64_strint(pTHX_ SV *sv, int64_t *i64) {
781 if (!SvPOK(sv))
782 return GROKNUM_ERR_NAS;
783 return strtoint64(aTHX_ SvPV_nolen(sv), 0, 1, i64);
784 }
785
786 int64_t
_xs_make_int64(pTHX_ SV * sv)787 _xs_make_int64(pTHX_ SV *sv) {
788 int64_t val;
789 groknum_err_t rv;
790
791 rv = _xs_pack_int64_int(aTHX_ sv, &val);
792 switch (rv) {
793 case GROKNUM_OK:
794 return val;
795 case GROKNUM_ERR_NAN:
796 break;
797 default:
798 GROKNUM_CROAK(rv, "invalid int64");
799 }
800 // check for number-like strings
801 if (SvPOK(sv)) {
802 rv = _xs_pack_int64_strint(aTHX_ sv, &val);
803 if (rv == GROKNUM_OK)
804 return val;
805 GROKNUM_CROAK(rv, "invalid int64");
806 }
807 GROKNUM_CROAK(GROKNUM_ERR_NAN, "invalid int64");
808 }
809
810 SV *
_xs_field_to_sv(pTHX_ void * data,size_t len,nmsg_msgmod_field_type type)811 _xs_field_to_sv(pTHX_ void *data, size_t len, nmsg_msgmod_field_type type) {
812
813 if (data == NULL)
814 croak("oops null data pointer");
815
816 switch (type) {
817
818 case nmsg_msgmod_ft_enum:
819 case nmsg_msgmod_ft_int16:
820 case nmsg_msgmod_ft_int32:
821 return newSViv(*(int *)data);
822 case nmsg_msgmod_ft_uint16:
823 case nmsg_msgmod_ft_uint32:
824 return newSVuv(*(unsigned *)data);
825 case nmsg_msgmod_ft_double:
826 return newSVnv(*(double *)data);
827 case nmsg_msgmod_ft_bool:
828 return boolSV(newSViv(*(int *)data));
829 case nmsg_msgmod_ft_int64:
830 return newSVi64(*(int64_t *)data);
831 case nmsg_msgmod_ft_uint64:
832 return newSVu64(*(uint64_t *)data);
833 case nmsg_msgmod_ft_string:
834 case nmsg_msgmod_ft_mlstring:
835 // len includes trailing null
836 return newSVpv((char *)data, len - 1);
837 // case nmsg_msgmod_ft_ip:
838 // case nmsg_msgmod_ft_bytes:
839 default:
840 return newSVpvn((char *)data, len);
841 }
842 }
843
844 uint8_t *
_xs_sv_to_field(pTHX_ SV * sv,nmsg_msgmod_field_type type,nmsg_field_val_u * data,size_t * len)845 _xs_sv_to_field(pTHX_ SV *sv, nmsg_msgmod_field_type type,
846 nmsg_field_val_u *data, size_t *len) {
847 switch (type) {
848 case nmsg_msgmod_ft_int16:
849 data->i16 = _xs_make_int16(aTHX_ sv);
850 *len = sizeof(int16_t);
851 break;
852 case nmsg_msgmod_ft_uint16:
853 data->u16 = _xs_make_uint16(aTHX_ sv);
854 *len = sizeof(uint16_t);
855 break;
856 case nmsg_msgmod_ft_int32:
857 data->i32 = _xs_make_int32(aTHX_ sv);
858 *len = sizeof(int32_t);
859 break;
860 case nmsg_msgmod_ft_uint32:
861 data->u32 = _xs_make_uint32(aTHX_ sv);
862 *len = sizeof(uint32_t);
863 break;
864 case nmsg_msgmod_ft_int64:
865 data->i64 = _xs_make_int64(aTHX_ sv);
866 *len = sizeof(int64_t);
867 break;
868 case nmsg_msgmod_ft_uint64:
869 data->u64 = _xs_make_uint64(aTHX_ sv);
870 *len = sizeof(uint64_t);
871 break;
872 case nmsg_msgmod_ft_enum:
873 data->en = (int)SvIV(sv);
874 *len = sizeof(int);
875 break;
876 case nmsg_msgmod_ft_double:
877 data->dbl = (double)SvNV(sv);
878 break;
879 case nmsg_msgmod_ft_bool:
880 data->boo = (bool)SvTRUE(sv);
881 break;
882 case nmsg_msgmod_ft_string:
883 case nmsg_msgmod_ft_mlstring:
884 data = (void *)SvPV(sv, *len);
885 *len += 1;
886 break;
887 //case nmsg_msgmod_ft_ip:
888 //case nmsg_msgmod_ft_bytes:
889 default:
890 data = (void *)SvPV(sv, *len);
891 break;
892 }
893 return((uint8_t *)data);
894 }
895
896
897 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util
898
899 BOOT:
900 #define MC(cc) \
901 newCONSTSUB(stash, #cc, newSViv( cc ))
902 //
903 #define MCE(name, ce) \
904 newCONSTSUB(stash, #name, newSViv( ce ))
905 //
906 #define MCPV(name, cc) \
907 newCONSTSUB(stash, #name, newSVpv( cc, sizeof(cc) ))
908 // BOOT ends after first blank line outside of a block
909 {
910 HV *stash;
911
912 stash = gv_stashpv("Net::Nmsg::Util", TRUE);
913
914 MC(NMSG_DEFAULT_SNAPLEN);
915 MC(NMSG_FLAG_FRAGMENT);
916 MC(NMSG_FLAG_ZLIB);
917 MC(NMSG_HDRLSZ_V2);
918 MC(NMSG_HDRSZ);
919 MC(NMSG_IPSZ_MAX);
920 MC(NMSG_LENHDRSZ_V1);
921 MC(NMSG_LENHDRSZ_V2);
922 MC(NMSG_PAYHDRSZ);
923 MC(NMSG_RBUFSZ);
924 MC(NMSG_RBUF_TIMEOUT);
925 MC(NMSG_VERSION);
926 MC(NMSG_WBUFSZ_ETHER);
927 MC(NMSG_WBUFSZ_JUMBO);
928 MC(NMSG_WBUFSZ_MAX);
929 MC(NMSG_WBUFSZ_MIN);
930
931 MCE(NMSG_INPUT_TYPE, nmsg_io_io_type_input );
932 MCE(NMSG_OUTPUT_TYPE, nmsg_io_io_type_output);
933
934 MCE(NMSG_INPUT_TYPE_STREAM, nmsg_input_type_stream);
935 MCE(NMSG_INPUT_TYPE_PRES, nmsg_input_type_pres );
936 MCE(NMSG_INPUT_TYPE_PCAP, nmsg_input_type_pcap );
937
938 MCE(NMSG_OUTPUT_TYPE_STREAM, nmsg_output_type_stream );
939 MCE(NMSG_OUTPUT_TYPE_PRES, nmsg_output_type_pres );
940 MCE(NMSG_OUTPUT_TYPE_CALLBACK, nmsg_output_type_callback);
941
942 MCE(NMSG_OUTPUT_MODE_STRIPE, nmsg_io_output_mode_stripe);
943 MCE(NMSG_OUTPUT_MODE_MIRROR, nmsg_io_output_mode_mirror);
944
945 MCE(NMSG_CLOSE_TYPE_EOF, nmsg_io_close_type_eof );
946 MCE(NMSG_CLOSE_TYPE_COUNT, nmsg_io_close_type_count );
947 MCE(NMSG_CLOSE_TYPE_INTERVAL, nmsg_io_close_type_interval);
948
949 MCE(NMSG_PCAP_TYPE_FILE, nmsg_pcap_type_file);
950 MCE(NMSG_PCAP_TYPE_LIVE, nmsg_pcap_type_live);
951
952 MCE(NMSG_RES_SUCCESS, nmsg_res_success );
953 MCE(NMSG_RES_FAILURE, nmsg_res_failure );
954 MCE(NMSG_RES_EOF, nmsg_res_eof );
955 MCE(NMSG_RES_MEMFAIL, nmsg_res_memfail );
956 MCE(NMSG_RES_PBUF_READY, nmsg_res_pbuf_ready );
957 MCE(NMSG_RES_NOTIMPL, nmsg_res_notimpl );
958 MCE(NMSG_RES_STOP, nmsg_res_stop );
959 MCE(NMSG_RES_AGAIN, nmsg_res_again );
960 MCE(NMSG_RES_PARSE_ERROR, nmsg_res_parse_error );
961 MCE(NMSG_RES_PCAP_ERROR, nmsg_res_pcap_error );
962 MCE(NMSG_RES_MAGIC_MISMATCH, nmsg_res_magic_mismatch );
963 MCE(NMSG_RES_VERSION_MISMATCH, nmsg_res_version_mismatch);
964
965 MC(NMSG_FF_REPEATED);
966 MC(NMSG_FF_REQUIRED);
967 MC(NMSG_FF_HIDDEN);
968 MC(NMSG_FF_NOPRINT);
969
970 MCE(NMSG_FT_ENUM, nmsg_msgmod_ft_enum );
971 MCE(NMSG_FT_BYTES, nmsg_msgmod_ft_bytes );
972 MCE(NMSG_FT_STRING, nmsg_msgmod_ft_string );
973 MCE(NMSG_FT_MLSTRING, nmsg_msgmod_ft_mlstring);
974 MCE(NMSG_FT_IP, nmsg_msgmod_ft_ip );
975 MCE(NMSG_FT_UINT16, nmsg_msgmod_ft_uint16 );
976 MCE(NMSG_FT_UINT32, nmsg_msgmod_ft_uint32 );
977 MCE(NMSG_FT_UINT64, nmsg_msgmod_ft_uint64 );
978 MCE(NMSG_FT_INT16, nmsg_msgmod_ft_int16 );
979 MCE(NMSG_FT_INT32, nmsg_msgmod_ft_int32 );
980 MCE(NMSG_FT_INT64, nmsg_msgmod_ft_int64 );
981 MCE(NMSG_FT_DOUBLE, nmsg_msgmod_ft_double );
982 MCE(NMSG_FT_BOOL, nmsg_msgmod_ft_bool );
983
984 MCE(NMSG_ALIAS_OPERATOR, nmsg_alias_operator);
985 MCE(NMSG_ALIAS_GROUP, nmsg_alias_group );
986
987 MATH_INT64_BOOT;
988 }
989
990
991 MODULE = Net::Nmsg PACKAGE = Net::Nmsg PREFIX = nmsg_
992
993 void
994 _nmsg_init_lib()
995 PREINIT:
996 nmsg_res res;
997 CODE:
998 if (NULL == orig_perl)
999 orig_perl = Perl_get_context();
1000 res = nmsg_init();
1001 if (res != nmsg_res_success)
1002 croak("nmsg_init failed: %s", nmsg_res_lookup(res));
1003
1004 void
1005 nmsg_set_autoclose(autoclose)
1006 _Bool autoclose
1007
1008 void
1009 nmsg_set_debug(debug)
1010 int debug
1011
1012
1013 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util PREFIX = nmsg_
1014
1015 void
1016 nmsg_chalias_lookup(ch)
1017 const char *ch
1018 PREINIT:
1019 char **alias = NULL;
1020 int num_aliases;
1021 int i;
1022 PPCODE:
1023 num_aliases = nmsg_chalias_lookup(ch, &alias);
1024 if (num_aliases > 0) {
1025 for (i = 0; i < num_aliases; i++)
1026 mXPUSHs(newSVpv(alias[i], 0));
1027 }
1028 if (alias != NULL)
1029 nmsg_chalias_free(&alias);
1030
1031 const char *
1032 nmsg_alias_by_key(ae, key)
1033 nmsg_alias_e ae
1034 unsigned key
1035
1036 unsigned
1037 nmsg_alias_by_value(ae, value)
1038 nmsg_alias_e ae
1039 const char *value
1040
1041 void
1042 find_all_devs()
1043 PREINIT:
1044 char err[PCAP_ERRBUF_SIZE];
1045 PPCODE:
1046 pcap_if_t *devs, *d;
1047
1048 if (pcap_findalldevs(&devs, err) == -1)
1049 croak("%s", err);
1050
1051 for (d=devs; d; d=d->next) {
1052 mXPUSHs(newSVpv(d->name, 0));
1053 if (d->description)
1054 mXPUSHs(newSVpv(d->description, 0));
1055 else {
1056 if ((strcmp(d->name,"lo") == 0) || (strcmp(d->name,"lo0") == 0))
1057 mXPUSHs(newSVpv("loopback device", 0));
1058 else
1059 mXPUSHs(newSVpv("unknown device", 0));
1060 }
1061 }
1062 pcap_freealldevs(devs);
1063
1064 const char *
1065 lookup_result(val)
1066 enum nmsg_res val
1067 CODE:
1068 RETVAL = nmsg_res_lookup(val);
1069 OUTPUT:
1070 RETVAL
1071
1072 void
1073 get_timestring()
1074 PREINIT:
1075 char now[32];
1076 struct timespec ts;
1077 struct tm *tm;
1078 time_t t;
1079 char *tstr;
1080 PPCODE:
1081 nmsg_timespec_get(&ts);
1082 t = (time_t) ts.tv_sec;
1083 tm = gmtime(&t);
1084 strftime(now, sizeof(now), "%Y%m%d.%H%M.%s", tm);
1085 nmsg_asprintf(&tstr, "%s.%09ld", now, ts.tv_nsec);
1086 if (tstr == NULL)
1087 croak("problem allocating time string");
1088 mXPUSHs(newSVpv(tstr, 0));
1089 Safefree(tstr);
1090
1091
1092 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::Util PREFIX = nmsg_msgmod_
1093
1094 PROTOTYPES: ENABLE
1095
1096 nmsg_msgmod_t
1097 _msgmod_lookup(vid, msgtype)
1098 unsigned vid
1099 unsigned msgtype
1100 CODE:
1101 RETVAL = nmsg_msgmod_lookup(vid, msgtype);
1102 OUTPUT:
1103 RETVAL
1104
1105 size_t
1106 nmsg_msgmod_get_max_vid()
1107
1108 size_t
1109 nmsg_msgmod_get_max_msgtype(vid)
1110 unsigned vid
1111
1112 unsigned
1113 nmsg_msgmod_mname_to_msgtype(vid, mname)
1114 unsigned vid
1115 const char *mname
1116
1117 const char *
1118 nmsg_msgmod_msgtype_to_mname(vid, msgtype)
1119 unsigned vid
1120 unsigned msgtype
1121
1122 const char *
1123 nmsg_msgmod_vid_to_vname(vid)
1124 unsigned vid
1125
1126 unsigned
1127 nmsg_msgmod_vname_to_vid(vname)
1128 char *vname
1129
1130
1131 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::io PREFIX = nmsg_io_
1132
1133 PROTOTYPES: ENABLE
1134
1135 Net::Nmsg::XS::io
1136 init(CLASS)
1137 const char *CLASS
1138 CODE:
1139 PERL_UNUSED_VAR(CLASS);
1140 RETVAL = nmsg_io_init();
1141 OUTPUT:
1142 RETVAL
1143
1144 void
1145 DESTROY(THIS)
1146 Net::Nmsg::XS::io THIS
1147 CODE:
1148 nmsg_io_destroy(&THIS);
1149
1150 void
1151 nmsg_io_breakloop(THIS)
1152 Net::Nmsg::XS::io THIS
1153
1154 void
1155 loop(THIS)
1156 Net::Nmsg::XS::io THIS
1157 PREINIT:
1158 nmsg_res res;
1159 U32 SAVE_signals;
1160 CODE:
1161 SAVE_signals = PL_signals;
1162 PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
1163 res = nmsg_io_loop(THIS);
1164 PL_signals = SAVE_signals;
1165 if (res != nmsg_res_success)
1166 croak("loop failure(%d): %s", res, nmsg_res_lookup(res));
1167
1168 void
1169 _add_input(THIS, input, ...)
1170 Net::Nmsg::XS::io THIS
1171 Net::Nmsg::XS::input input
1172 PREINIT:
1173 void *user = NULL;
1174 nmsg_res res;
1175 CODE:
1176 if (items > 2) {
1177 if SvROK(ST(2))
1178 user = SvRV(ST(2));
1179 else if SvOK(ST(2))
1180 croak("not a reference");
1181 }
1182 res = nmsg_io_add_input(THIS, input, user);
1183 if (res != nmsg_res_success)
1184 croak("nmsg_io_add_input failed: %s", nmsg_res_lookup(res));
1185 if (user != NULL)
1186 nmsg_io_set_close_fp(THIS, io_closed_callback);
1187
1188 void
1189 _add_output(THIS, output, ...)
1190 Net::Nmsg::XS::io THIS
1191 Net::Nmsg::XS::output output
1192 PREINIT:
1193 void *user = NULL;
1194 nmsg_res res;
1195 CODE:
1196 if (items > 2) {
1197 if SvROK(ST(2))
1198 user = SvRV(ST(2));
1199 else if SvOK(ST(2))
1200 croak("not a reference");
1201 }
1202 res = nmsg_io_add_output(THIS, output, user);
1203 if (res != nmsg_res_success)
1204 croak("nmsg_io_add_output failed: %s", nmsg_res_lookup(res));
1205 if (user != NULL)
1206 nmsg_io_set_close_fp(THIS, io_closed_callback);
1207
1208 void
1209 nmsg_io_set_count(THIS, value)
1210 Net::Nmsg::XS::io THIS
1211 unsigned value
1212
1213 void
1214 nmsg_io_set_debug(THIS, value)
1215 Net::Nmsg::XS::io THIS
1216 unsigned value
1217
1218 void
1219 nmsg_io_set_interval(THIS, value)
1220 Net::Nmsg::XS::io THIS
1221 unsigned value
1222
1223 void
1224 nmsg_io_set_interval_randomized(THIS, value)
1225 Net::Nmsg::XS::io THIS
1226 bool value
1227
1228 void
1229 nmsg_io_set_output_mode(THIS, value)
1230 Net::Nmsg::XS::io THIS
1231 nmsg_io_output_mode value
1232
1233 void
1234 set_mirror(THIS, value)
1235 Net::Nmsg::XS::io THIS
1236 unsigned value
1237 CODE:
1238 if (value > 0)
1239 nmsg_io_set_output_mode(THIS, nmsg_io_output_mode_mirror);
1240 else
1241 nmsg_io_set_output_mode(THIS, nmsg_io_output_mode_stripe);
1242
1243
1244 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::nmsg_pcap PREFIX=nmsg_pcap_
1245
1246 PROTOTYPES: ENABLE
1247
1248 Net::Nmsg::XS::nmsg_pcap
1249 _input_open(CLASS, pcap)
1250 const char *CLASS
1251 Net::Nmsg::XS::pcap pcap
1252 CODE:
1253 PERL_UNUSED_VAR(CLASS);
1254 RETVAL = nmsg_pcap_input_open(pcap);
1255 if (RETVAL == NULL)
1256 croak("nmsg_pcap_input_open() failed");
1257 OUTPUT:
1258 RETVAL
1259
1260 void
1261 destroy(THIS)
1262 Net::Nmsg::XS::nmsg_pcap THIS
1263 PREINIT:
1264 nmsg_res res;
1265 CODE:
1266 res = nmsg_pcap_input_close(&THIS);
1267 if (res != nmsg_res_success)
1268 fprintf(stderr, "nmsg_pcap_input_close failed: %s", nmsg_res_lookup(res));
1269
1270 void
1271 set_bpf(THIS, bpf)
1272 Net::Nmsg::XS::nmsg_pcap THIS
1273 char *bpf
1274 PREINIT:
1275 nmsg_res res;
1276 CODE:
1277 res = nmsg_pcap_input_setfilter(THIS, bpf);
1278 if (res != nmsg_res_success)
1279 croak("nmsg_pcap_input_setfilter failed: %s", nmsg_res_lookup(res));
1280
1281 nmsg_pcap_type
1282 nmsg_pcap_get_type(THIS)
1283 Net::Nmsg::XS::nmsg_pcap THIS
1284
1285
1286 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::pcap PREFIX = pcap_
1287
1288 PROTOTYPES: ENABLE
1289
1290 Net::Nmsg::XS::pcap
1291 open_offline(CLASS, fname)
1292 const char *CLASS
1293 const char *fname
1294 PREINIT:
1295 char err[PCAP_ERRBUF_SIZE];
1296 CODE:
1297 PERL_UNUSED_VAR(CLASS);
1298 RETVAL = pcap_open_offline(fname, err);
1299 if (RETVAL == NULL)
1300 croak("pcap_open_offline() failed: %s", err);
1301 OUTPUT:
1302 RETVAL
1303
1304 Net::Nmsg::XS::pcap
1305 open_live(CLASS, iface, snaplen, promisc)
1306 const char *CLASS
1307 const char *iface
1308 int snaplen
1309 int promisc
1310 PREINIT:
1311 char err[PCAP_ERRBUF_SIZE];
1312 CODE:
1313 PERL_UNUSED_VAR(CLASS);
1314 RETVAL = pcap_open_live(iface, snaplen, promisc, 0, err);
1315 if (RETVAL == NULL)
1316 croak("pcap_open_offline() failed: %s", err);
1317 OUTPUT:
1318 RETVAL
1319
1320 void
1321 destroy(THIS)
1322 Net::Nmsg::XS::pcap THIS
1323 CODE:
1324 pcap_close(THIS);
1325
1326 int
1327 set_snaplen(THIS, snaplen)
1328 Net::Nmsg::XS::pcap THIS
1329 int snaplen
1330 CODE:
1331 #ifdef LIMITED_PCAP
1332 PERL_UNUSED_VAR(snaplen);
1333 croak("pcap_set_snaplen unavailable in this version of libpcap");
1334 #else
1335 RETVAL = pcap_set_snaplen(THIS, snaplen);
1336 #endif /* LIMITED_PCAP */
1337 OUTPUT:
1338 RETVAL
1339
1340 int
1341 set_promisc(THIS, promisc)
1342 Net::Nmsg::XS::pcap THIS
1343 int promisc
1344 CODE:
1345 #ifdef LIMITED_PCAP
1346 PERL_UNUSED_VAR(promisc);
1347 croak("pcap_set_promisc unavailable in this version of libpcap");
1348 #else
1349 RETVAL = pcap_set_promisc(THIS, promisc);
1350 #endif /* LIMITED_PCAP */
1351 OUTPUT:
1352 RETVAL
1353
1354 void
1355 get_selectable_fd(THIS)
1356 Net::Nmsg::XS::pcap THIS
1357 PREINIT:
1358 int res;
1359 PPCODE:
1360 res = pcap_get_selectable_fd(THIS);
1361 if (res != -1)
1362 mXPUSHi(res);
1363
1364 int
1365 pcap_fileno(THIS)
1366 Net::Nmsg::XS::pcap THIS
1367
1368 char *
1369 pcap_geterr(THIS)
1370 Net::Nmsg::XS::pcap THIS
1371
1372
1373 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::input PREFIX = nmsg_input_
1374
1375 PROTOTYPES: ENABLE
1376
1377 void
1378 destroy(THIS)
1379 Net::Nmsg::XS::input THIS
1380 CODE:
1381 nmsg_input_close(&THIS);
1382
1383 Net::Nmsg::XS::input_file
1384 nmsg_input_open_file(CLASS, fh)
1385 const char *CLASS
1386 PerlIO *fh
1387 CODE:
1388 PERL_UNUSED_VAR(CLASS);
1389 RETVAL = nmsg_input_open_file(PerlIO_fileno(fh));
1390 if (RETVAL == NULL)
1391 croak("nmsg_input_open_file() failed");
1392 OUTPUT:
1393 RETVAL
1394
1395 Net::Nmsg::XS::input_json
1396 nmsg_input_open_json(CLASS, fh)
1397 const char *CLASS
1398 PerlIO *fh
1399 CODE:
1400 PERL_UNUSED_VAR(CLASS);
1401 RETVAL = nmsg_input_open_json(PerlIO_fileno(fh));
1402 if (RETVAL == NULL)
1403 croak("nmsg_input_open_json() failed");
1404 OUTPUT:
1405 RETVAL
1406
1407 Net::Nmsg::XS::input_sock
1408 nmsg_input_open_sock(CLASS, fh)
1409 const char *CLASS
1410 PerlIO *fh
1411 CODE:
1412 PERL_UNUSED_VAR(CLASS);
1413 RETVAL = nmsg_input_open_sock(PerlIO_fileno(fh));
1414 if (RETVAL == NULL)
1415 croak("nmsg_input_open_sock() failed");
1416 OUTPUT:
1417 RETVAL
1418
1419 Net::Nmsg::XS::input_pres
1420 _open_pres(CLASS, fh, vid, mid)
1421 const char *CLASS
1422 PerlIO *fh
1423 unsigned vid
1424 unsigned mid
1425 PREINIT:
1426 nmsg_msgmod_t mod;
1427 CODE:
1428 PERL_UNUSED_VAR(CLASS);
1429 mod = nmsg_msgmod_lookup(vid, mid);
1430 if (mod == NULL)
1431 croak("unknown vendor id '%d' or message type '%d'", vid, mid);
1432 RETVAL = nmsg_input_open_pres(PerlIO_fileno(fh), mod);
1433 if (RETVAL == NULL)
1434 croak("nmsg_input_open_pres() failed");
1435 OUTPUT:
1436 RETVAL
1437
1438 Net::Nmsg::XS::input_pcap
1439 _open_pcap(CLASS, pcap, vid, mid)
1440 const char *CLASS
1441 Net::Nmsg::XS::nmsg_pcap pcap
1442 unsigned vid
1443 unsigned mid
1444 PREINIT:
1445 nmsg_msgmod_t mod;
1446 CODE:
1447 PERL_UNUSED_VAR(CLASS);
1448 mod = nmsg_msgmod_lookup(vid, mid);
1449 if (mod == NULL)
1450 croak("unknown vendor id '%d' or message type '%d'", vid, mid);
1451 RETVAL = nmsg_input_open_pcap(pcap, mod);
1452 if (RETVAL == NULL)
1453 croak("nmsg_input_open_pcap() failed");
1454 OUTPUT:
1455 RETVAL
1456
1457 void
1458 nmsg_input_set_filter_source(THIS, value)
1459 Net::Nmsg::XS::input THIS
1460 unsigned value
1461
1462 void
1463 _set_filter_group(THIS, value)
1464 Net::Nmsg::XS::input THIS
1465 unsigned value
1466 CODE:
1467 nmsg_input_set_filter_group(THIS, value);
1468
1469 void
1470 _set_filter_operator(THIS, value)
1471 Net::Nmsg::XS::input THIS
1472 unsigned value
1473 CODE:
1474 nmsg_input_set_filter_operator(THIS, value);
1475
1476 void
1477 _set_filter_msgtype(THIS, vid, mid)
1478 Net::Nmsg::XS::input THIS
1479 unsigned vid
1480 unsigned mid
1481 CODE:
1482 nmsg_input_set_filter_msgtype(THIS, vid, mid);
1483
1484 void
1485 nmsg_input_set_blocking_io(THIS, flag)
1486 Net::Nmsg::XS::input THIS
1487 bool flag
1488 PREINIT:
1489 nmsg_res res;
1490 PPCODE:
1491 res = nmsg_input_set_blocking_io(THIS, flag);
1492 if (res == nmsg_res_success)
1493 mXPUSHi(flag);
1494
1495 void
1496 read(THIS, blocking_io=true)
1497 Net::Nmsg::XS::input THIS
1498 bool blocking_io
1499 PREINIT:
1500 nmsg_message_t m;
1501 nmsg_res res;
1502 U32 SAVE_signals;
1503 PPCODE:
1504 res = nmsg_res_failure;
1505 while (res != nmsg_res_success) {
1506 SAVE_signals = PL_signals;
1507 PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
1508 res = nmsg_input_read(THIS, &m);
1509 PL_signals = SAVE_signals;
1510 switch (res) {
1511 case (nmsg_res_success):
1512 mXPUSHs(_xs_wrap_msg(aTHX_ m));
1513 goto last_read;
1514 case (nmsg_res_again):
1515 if (blocking_io != true)
1516 goto last_read;
1517 break;
1518 case (nmsg_res_eof):
1519 goto last_read;
1520 default:
1521 croak("nmsg_input_read() failed: %s", nmsg_res_lookup(res));
1522 }
1523 }
1524 last_read:
1525 // return
1526
1527 nmsg_res
1528 loop(THIS, cb, count)
1529 Net::Nmsg::XS::input THIS
1530 int count
1531 CV *cb
1532 PREINIT:
1533 nmsg_res res;
1534 U32 SAVE_signals;
1535 CODE:
1536 SAVE_signals = PL_signals;
1537 PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
1538 res = nmsg_input_loop(THIS, count, output_callback, (void *)cb);
1539 PL_signals = SAVE_signals;
1540 if (res != nmsg_res_success && res != nmsg_res_eof)
1541 croak("nmsg_input_loop() failed(%d): %s", res, nmsg_res_lookup(res));
1542 RETVAL = res;
1543 OUTPUT:
1544 RETVAL
1545
1546
1547 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::output PREFIX = nmsg_output_
1548
1549 PROTOTYPES: ENABLE
1550
1551 void
1552 destroy(THIS)
1553 Net::Nmsg::XS::output THIS
1554 CODE:
1555 nmsg_output_close(&THIS);
1556
1557 Net::Nmsg::XS::output_file
1558 open_file(CLASS, fh, bufsz)
1559 const char *CLASS
1560 PerlIO *fh
1561 size_t bufsz
1562 CODE:
1563 PERL_UNUSED_VAR(CLASS);
1564 RETVAL = nmsg_output_open_file(PerlIO_fileno(fh), bufsz);
1565 OUTPUT:
1566 RETVAL
1567
1568 Net::Nmsg::XS::output_json
1569 open_json(CLASS, fh)
1570 const char *CLASS
1571 PerlIO *fh
1572 CODE:
1573 PERL_UNUSED_VAR(CLASS);
1574 RETVAL = nmsg_output_open_json(PerlIO_fileno(fh));
1575 OUTPUT:
1576 RETVAL
1577
1578 Net::Nmsg::XS::output_sock
1579 open_sock(CLASS, fh, bufsz)
1580 const char *CLASS
1581 PerlIO *fh
1582 size_t bufsz
1583 CODE:
1584 PERL_UNUSED_VAR(CLASS);
1585 RETVAL = nmsg_output_open_sock(PerlIO_fileno(fh), bufsz);
1586 OUTPUT:
1587 RETVAL
1588
1589 Net::Nmsg::XS::output_pres
1590 open_pres(CLASS, fh)
1591 const char *CLASS
1592 PerlIO *fh
1593 CODE:
1594 PERL_UNUSED_VAR(CLASS);
1595 RETVAL = nmsg_output_open_pres(PerlIO_fileno(fh));
1596 OUTPUT:
1597 RETVAL
1598
1599 Net::Nmsg::XS::output_cb
1600 open_callback(CLASS, cb)
1601 const char *CLASS
1602 CV *cb
1603 CODE:
1604 PERL_UNUSED_VAR(CLASS);
1605 RETVAL = nmsg_output_open_callback(output_callback, (void *)cb);
1606 OUTPUT:
1607 RETVAL
1608
1609 void
1610 nmsg_output_set_buffered(THIS, value)
1611 Net::Nmsg::XS::output THIS
1612 bool value
1613
1614 void
1615 nmsg_output_set_endline(THIS, value)
1616 Net::Nmsg::XS::output THIS
1617 const char *value
1618
1619 void
1620 nmsg_output_set_rate(THIS, rate, freq, rate_obj)
1621 Net::Nmsg::XS::output THIS
1622 unsigned rate
1623 unsigned freq
1624 Net::Nmsg::XS::rate rate_obj
1625 CODE:
1626 PERL_UNUSED_VAR(rate);
1627 PERL_UNUSED_VAR(freq);
1628 nmsg_output_set_rate(THIS, rate_obj);
1629
1630 void
1631 nmsg_output_set_zlibout(THIS, value)
1632 Net::Nmsg::XS::output THIS
1633 bool value
1634
1635 void
1636 nmsg_output_set_group(THIS, value)
1637 Net::Nmsg::XS::output THIS
1638 unsigned value
1639
1640 void
1641 nmsg_output_set_operator(THIS, value)
1642 Net::Nmsg::XS::output THIS
1643 unsigned value
1644
1645 void
1646 nmsg_output_set_source(THIS, value)
1647 Net::Nmsg::XS::output THIS
1648 unsigned value
1649
1650 void
1651 nmsg_output_set_filter_msgtype(THIS, vid, mid)
1652 Net::Nmsg::XS::output THIS
1653 unsigned vid
1654 unsigned mid
1655
1656 void
1657 _write(THIS, msg)
1658 Net::Nmsg::XS::output THIS
1659 Net::Nmsg::XS::msg msg
1660 PREINIT:
1661 nmsg_res res;
1662 U32 SAVE_signals;
1663 CODE:
1664 SAVE_signals = PL_signals;
1665 PL_signals |= PERL_SIGNALS_UNSAFE_FLAG;
1666 res = nmsg_output_write(THIS, msg);
1667 PL_signals = SAVE_signals;
1668 if (res != nmsg_res_success)
1669 croak("nmsg_output_write() failed: %s", nmsg_res_lookup(res));
1670
1671
1672 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::rate PREFIX = nmsg_rate_
1673
1674 PROTOTYPES: ENABLE
1675
1676 Net::Nmsg::XS::rate
1677 nmsg_rate_init(CLASS, rate, freq)
1678 char *CLASS
1679 unsigned rate
1680 unsigned freq
1681 CODE:
1682 PERL_UNUSED_VAR(CLASS);
1683 RETVAL = nmsg_rate_init(rate, freq);
1684 if (RETVAL == NULL)
1685 croak("rate error %d/%d", rate, freq);
1686 OUTPUT:
1687 RETVAL
1688
1689 void
1690 DESTROY(THIS)
1691 Net::Nmsg::XS::rate THIS
1692 CODE:
1693 nmsg_rate_destroy(&THIS);
1694
1695
1696 MODULE = Net::Nmsg PACKAGE = Net::Nmsg::XS::msg PREFIX = nmsg_message_
1697
1698 PROTOTYPES: ENABLE
1699
1700 Net::Nmsg::XS::msg
1701 nmsg_message_init(CLASS, mod)
1702 char *CLASS
1703 nmsg_msgmod_t mod
1704 CODE:
1705 PERL_UNUSED_VAR(CLASS);
1706 RETVAL = nmsg_message_init(mod);
1707 OUTPUT:
1708 RETVAL
1709
1710 void
1711 DESTROY(THIS)
1712 Net::Nmsg::XS::msg THIS
1713 CODE:
1714 nmsg_message_destroy(&THIS);
1715
1716 uint32_t
1717 nmsg_message_get_source(THIS)
1718 Net::Nmsg::XS::msg THIS
1719
1720 uint32_t
1721 nmsg_message_get_operator(THIS)
1722 Net::Nmsg::XS::msg THIS
1723
1724 uint32_t
1725 nmsg_message_get_group(THIS)
1726 Net::Nmsg::XS::msg THIS
1727
1728 void
1729 get_time(THIS)
1730 Net::Nmsg::XS::msg THIS
1731 PREINIT:
1732 struct timespec ts;
1733 PPCODE:
1734 nmsg_message_get_time(THIS, &ts);
1735 mXPUSHi(ts.tv_sec);
1736 mXPUSHi(ts.tv_nsec);
1737
1738 void
1739 get_num_fields(THIS)
1740 Net::Nmsg::XS::msg THIS
1741 PREINIT:
1742 nmsg_res res;
1743 size_t len;
1744 PPCODE:
1745 res = nmsg_message_get_num_fields(THIS, &len);
1746 if (res == nmsg_res_success)
1747 mXPUSHu(len);
1748
1749 void
1750 get_num_field_values(THIS, field)
1751 Net::Nmsg::XS::msg THIS
1752 const char *field
1753 PREINIT:
1754 nmsg_res res;
1755 size_t len;
1756 PPCODE:
1757 res = nmsg_message_get_num_field_values(THIS, field, &len);
1758 if (res == nmsg_res_success)
1759 mXPUSHu(len);
1760
1761 void
1762 get_num_field_values_by_idx(THIS, idx)
1763 Net::Nmsg::XS::msg THIS
1764 unsigned idx
1765 PREINIT:
1766 nmsg_res res;
1767 size_t len;
1768 PPCODE:
1769 res = nmsg_message_get_num_field_values_by_idx(THIS, idx, &len);
1770 if (res == nmsg_res_success)
1771 mXPUSHu(len);
1772
1773 void
1774 get_field(THIS, field, v_idx = 0)
1775 Net::Nmsg::XS::msg THIS
1776 const char *field
1777 unsigned v_idx
1778 PREINIT:
1779 nmsg_res res;
1780 size_t len;
1781 void *data;
1782 nmsg_msgmod_field_type type;
1783 PPCODE:
1784 res = nmsg_message_get_field(THIS, field, v_idx, &data, &len);
1785 if (res == nmsg_res_success && data != NULL) {
1786 res = nmsg_message_get_field_type(THIS, field, &type);
1787 if (res == nmsg_res_success) {
1788 mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
1789 }
1790 else
1791 croak("nmsg_message_get_field_type failed: %s",
1792 nmsg_res_lookup(res));
1793 }
1794
1795 void
1796 get_field_vals(THIS, field)
1797 Net::Nmsg::XS::msg THIS
1798 const char *field
1799 PREINIT:
1800 nmsg_res res;
1801 size_t len;
1802 void *data;
1803 nmsg_msgmod_field_type type;
1804 int i;
1805 PPCODE:
1806 res = nmsg_message_get_field_type(THIS, field, &type);
1807 if (res != nmsg_res_success)
1808 croak("nmsg_message_get_field_type failed: %s", nmsg_res_lookup(res));
1809 for (i = 0; ; i++) {
1810 res = nmsg_message_get_field(THIS, field, i, &data, &len);
1811 if (res != nmsg_res_success || data == NULL)
1812 break;
1813 mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
1814 }
1815
1816 void
1817 get_field_by_idx(THIS, f_idx, v_idx = 0)
1818 Net::Nmsg::XS::msg THIS
1819 unsigned f_idx
1820 unsigned v_idx
1821 PREINIT:
1822 nmsg_res res;
1823 nmsg_msgmod_field_type type;
1824 size_t len;
1825 void *data;
1826 PPCODE:
1827 res = nmsg_message_get_field_by_idx(THIS, f_idx, v_idx, &data, &len);
1828 if (res == nmsg_res_success) {
1829 res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
1830 if (res == nmsg_res_success && data != NULL) {
1831 mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
1832 }
1833 else if (res != nmsg_res_success)
1834 croak("nmsg_message_get_field_type_by_idx failed: %s",
1835 nmsg_res_lookup(res));
1836 }
1837
1838 void
1839 get_field_vals_by_idx(THIS, f_idx)
1840 Net::Nmsg::XS::msg THIS
1841 unsigned f_idx
1842 PREINIT:
1843 nmsg_res res;
1844 nmsg_msgmod_field_type type;
1845 size_t len;
1846 void *data;
1847 int i;
1848 PPCODE:
1849 res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
1850 if (res == nmsg_res_success) {
1851 for (i = 0; ; i++) {
1852 res = nmsg_message_get_field_by_idx(THIS, f_idx, i, &data, &len);
1853 if (res != nmsg_res_success || data == NULL)
1854 break;
1855 mXPUSHs(_xs_field_to_sv(aTHX_ data, len, type));
1856 }
1857 }
1858
1859 void
1860 get_field_flags(THIS, field)
1861 Net::Nmsg::XS::msg THIS
1862 const char *field
1863 PREINIT:
1864 nmsg_res res;
1865 unsigned flags;
1866 PPCODE:
1867 res = nmsg_message_get_field_flags(THIS, field, &flags);
1868 if (res == nmsg_res_success)
1869 mXPUSHu(flags);
1870
1871 void
1872 get_field_flags_by_idx(THIS, f_idx)
1873 Net::Nmsg::XS::msg THIS
1874 unsigned f_idx
1875 PREINIT:
1876 nmsg_res res;
1877 unsigned flags;
1878 PPCODE:
1879 res = nmsg_message_get_field_flags_by_idx(THIS, f_idx, &flags);
1880 if (res == nmsg_res_success)
1881 mXPUSHu(flags);
1882
1883 void
1884 get_field_idx(THIS, name)
1885 Net::Nmsg::XS::msg THIS
1886 const char *name
1887 PREINIT:
1888 nmsg_res res;
1889 unsigned idx;
1890 PPCODE:
1891 res = nmsg_message_get_field_idx(THIS, name, &idx);
1892 if (res == nmsg_res_success)
1893 mXPUSHu(idx);
1894
1895 void
1896 get_field_name(THIS, idx)
1897 Net::Nmsg::XS::msg THIS
1898 unsigned idx
1899 PREINIT:
1900 nmsg_res res;
1901 const char *name;
1902 PPCODE:
1903 res = nmsg_message_get_field_name(THIS, idx, &name);
1904 if (res == nmsg_res_success)
1905 mXPUSHs(newSVpv(name, 0));
1906
1907 void
1908 get_field_type(THIS, name)
1909 Net::Nmsg::XS::msg THIS
1910 const char *name;
1911 PREINIT:
1912 nmsg_res res;
1913 nmsg_msgmod_field_type type;
1914 PPCODE:
1915 res = nmsg_message_get_field_type(THIS, name, &type);
1916 if (res == nmsg_res_success)
1917 mXPUSHi(type);
1918
1919 void
1920 get_field_type_by_idx(THIS, idx)
1921 Net::Nmsg::XS::msg THIS
1922 unsigned idx
1923 PREINIT:
1924 nmsg_res res;
1925 nmsg_msgmod_field_type type;
1926 PPCODE:
1927 res = nmsg_message_get_field_type_by_idx(THIS, idx, &type);
1928 if (res == nmsg_res_success)
1929 mXPUSHi(type);
1930
1931 void
1932 enum_name_to_value(THIS, field, name)
1933 Net::Nmsg::XS::msg THIS
1934 const char *field
1935 const char *name
1936 PREINIT:
1937 nmsg_res res;
1938 unsigned value;
1939 PPCODE:
1940 res = nmsg_message_enum_name_to_value(THIS, field, name, &value);
1941 if (res == nmsg_res_success)
1942 mXPUSHu(value);
1943
1944 void
1945 enum_name_to_value_by_idx(THIS, f_idx, name)
1946 Net::Nmsg::XS::msg THIS
1947 unsigned f_idx
1948 const char *name
1949 PREINIT:
1950 nmsg_res res;
1951 unsigned value;
1952 PPCODE:
1953 res = nmsg_message_enum_name_to_value_by_idx(THIS, f_idx, name, &value);
1954 if (res == nmsg_res_success)
1955 mXPUSHu(value);
1956
1957 void
1958 enum_value_to_name(THIS, field, value)
1959 Net::Nmsg::XS::msg THIS
1960 const char *field
1961 unsigned value
1962 PREINIT:
1963 nmsg_res res;
1964 const char *name;
1965 PPCODE:
1966 res = nmsg_message_enum_value_to_name(THIS, field, value, &name);
1967 if (res == nmsg_res_success)
1968 mXPUSHs(newSVpv(name, 0));
1969
1970 void
1971 enum_value_to_name_by_idx(THIS, f_idx, value)
1972 Net::Nmsg::XS::msg THIS
1973 unsigned f_idx
1974 unsigned value
1975 PREINIT:
1976 nmsg_res res;
1977 const char *name;
1978 PPCODE:
1979 res = nmsg_message_enum_value_to_name_by_idx(THIS, f_idx, value, &name);
1980 if (res == nmsg_res_success)
1981 mXPUSHs(newSVpv(name, 0));
1982
1983 void
1984 set_field(THIS, field, v_idx, sv)
1985 Net::Nmsg::XS::msg THIS
1986 const char *field
1987 unsigned v_idx
1988 SV *sv
1989 PREINIT:
1990 nmsg_res res;
1991 nmsg_msgmod_field_type type;
1992 nmsg_field_val_u data;
1993 uint8_t *bp;
1994 size_t len;
1995 CODE:
1996 res = nmsg_message_get_field_type(THIS, field, &type);
1997 if (res == nmsg_res_success) {
1998 bp = _xs_sv_to_field(aTHX_ sv, type, &data, &len);
1999 res = nmsg_message_set_field(THIS, field, v_idx, bp, len);
2000 if (res != nmsg_res_success)
2001 croak("nmsg_message_set_field failed: %s", nmsg_res_lookup(res));
2002 }
2003 else
2004 croak("nmsg_message_get_field_type failed: %s", nmsg_res_lookup(res));
2005
2006 void
2007 set_field_by_idx(THIS, f_idx, v_idx, sv)
2008 Net::Nmsg::XS::msg THIS
2009 unsigned f_idx
2010 unsigned v_idx
2011 SV *sv;
2012 PREINIT:
2013 nmsg_res res;
2014 nmsg_msgmod_field_type type;
2015 nmsg_field_val_u data;
2016 uint8_t *bp;
2017 size_t len;
2018 CODE:
2019 res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
2020 if (res == nmsg_res_success) {
2021 bp = _xs_sv_to_field(aTHX_ sv, type, &data, &len);
2022 res = nmsg_message_set_field_by_idx(THIS, f_idx, v_idx, bp, len);
2023 if (res != nmsg_res_success)
2024 croak("nmsg_message_set_field_by_idx failed: %s",
2025 nmsg_res_lookup(res));
2026 }
2027 else
2028 croak("nmsg_message_get_field_type_by_idx failed: %s",
2029 nmsg_res_lookup(res));
2030
2031 void
2032 nmsg_message_set_source(THIS, source)
2033 Net::Nmsg::XS::msg THIS
2034 uint32_t source
2035
2036 void
2037 nmsg_message_set_operator(THIS, operator)
2038 Net::Nmsg::XS::msg THIS
2039 uint32_t operator
2040
2041 void
2042 nmsg_message_set_group(THIS, group)
2043 Net::Nmsg::XS::msg THIS
2044 uint32_t group
2045
2046 void
2047 set_time(THIS, time_sec, time_nsec)
2048 Net::Nmsg::XS::msg THIS
2049 long time_sec
2050 int time_nsec
2051 PREINIT:
2052 struct timespec ts;
2053 PPCODE:
2054 ts.tv_sec = time_sec;
2055 ts.tv_nsec = time_nsec;
2056 nmsg_message_set_time(THIS, &ts);
2057
2058 void
2059 message_to_pres(THIS, endline)
2060 Net::Nmsg::XS::msg THIS
2061 const char *endline
2062 PREINIT:
2063 nmsg_res res;
2064 char *pres;
2065 PPCODE:
2066 pthread_mutex_lock(&presentation_lock);
2067 res = nmsg_message_to_pres(THIS, &pres, endline);
2068 if (res != nmsg_res_success)
2069 goto out;
2070 mXPUSHs(newSVpv(pres, 0));
2071 Safefree(pres);
2072 out:
2073 pthread_mutex_unlock(&presentation_lock);
2074 if (res != nmsg_res_success)
2075 croak("nmsg_message_to_pres failed: %s", nmsg_res_lookup(res));
2076
2077 void
2078 get_field_type_descr_by_idx(THIS, f_idx)
2079 Net::Nmsg::XS::msg THIS
2080 unsigned f_idx
2081 PREINIT:
2082 nmsg_res res;
2083 nmsg_msgmod_field_type type;
2084 PPCODE:
2085 res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
2086 if (res == nmsg_res_success) {
2087 mXPUSHs(newSViv(type));
2088
2089 switch (type) {
2090
2091 case nmsg_msgmod_ft_enum:
2092 mXPUSHs(newSVpvs("enum"));
2093 break;
2094 case nmsg_msgmod_ft_int16:
2095 mXPUSHs(newSVpvs("int16"));
2096 break;
2097 case nmsg_msgmod_ft_int32:
2098 mXPUSHs(newSVpvs("int32"));
2099 break;
2100 case nmsg_msgmod_ft_uint16:
2101 mXPUSHs(newSVpvs("uint16"));
2102 break;
2103 case nmsg_msgmod_ft_uint32:
2104 mXPUSHs(newSVpvs("uint32"));
2105 break;
2106 case nmsg_msgmod_ft_uint64:
2107 mXPUSHs(newSVpvs("uint64"));
2108 break;
2109 case nmsg_msgmod_ft_int64:
2110 mXPUSHs(newSVpvs("int64"));
2111 break;
2112 case nmsg_msgmod_ft_string:
2113 mXPUSHs(newSVpvs("string"));
2114 break;
2115 case nmsg_msgmod_ft_mlstring:
2116 mXPUSHs(newSVpvs("mlstring"));
2117 break;
2118 case nmsg_msgmod_ft_bytes:
2119 mXPUSHs(newSVpvs("bytes"));
2120 break;
2121 case nmsg_msgmod_ft_ip:
2122 mXPUSHs(newSVpvs("ip"));
2123 break;
2124 default:
2125 mXPUSHs(newSVpvs("unknown"));
2126 }
2127 }
2128
2129 void
2130 get_field_flag_descr_by_idx(THIS, f_idx)
2131 Net::Nmsg::XS::msg THIS
2132 unsigned f_idx
2133 PREINIT:
2134 nmsg_res res;
2135 unsigned flags;
2136 PPCODE:
2137 res = nmsg_message_get_field_flags_by_idx(THIS, f_idx, &flags);
2138 if (res == nmsg_res_success) {
2139 if (flags & NMSG_FF_REPEATED)
2140 mXPUSHs(newSViv(NMSG_FF_REPEATED));
2141 mXPUSHs(newSVpvs("repeated"));
2142 if (flags & NMSG_FF_REQUIRED)
2143 mXPUSHs(newSViv(NMSG_FF_REQUIRED));
2144 mXPUSHs(newSVpvs("required"));
2145 if (flags & NMSG_FF_HIDDEN)
2146 mXPUSHs(newSViv(NMSG_FF_HIDDEN));
2147 mXPUSHs(newSVpvs("hidden"));
2148 if (flags & NMSG_FF_NOPRINT)
2149 mXPUSHs(newSViv(NMSG_FF_NOPRINT));
2150 mXPUSHs(newSVpvs("noprint"));
2151 }
2152
2153 void
2154 get_field_enum_descr_by_idx(THIS, f_idx)
2155 Net::Nmsg::XS::msg THIS
2156 unsigned f_idx
2157 PREINIT:
2158 nmsg_res res;
2159 nmsg_msgmod_field_type type;
2160 unsigned v;
2161 const char *name;
2162 PPCODE:
2163 res = nmsg_message_get_field_type_by_idx(THIS, f_idx, &type);
2164 if (res == nmsg_res_success && type == nmsg_msgmod_ft_enum) {
2165 for (v = 0; ; v++) {
2166 res = nmsg_message_enum_value_to_name_by_idx(
2167 THIS, f_idx, v, &name);
2168 if (res != nmsg_res_success)
2169 break;
2170 mXPUSHu(v);
2171 mXPUSHs(newSVpv(name, 0));
2172 }
2173 }
2174