ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-SNMP-XS/XS.xs
(Generate patch)

Comparing Net-SNMP-XS/XS.xs (file contents):
Revision 1.7 by root, Thu Apr 9 07:10:23 2009 UTC vs.
Revision 1.12 by root, Wed May 5 20:46:09 2010 UTC

2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5// C99 required 5// C99 required
6 6
7#define BENCHMARK 7//#define BENCHMARK
8 8
9#define ASN_BOOLEAN 0x01 9#define ASN_BOOLEAN 0x01
10#define ASN_INTEGER32 0x02 10#define ASN_INTEGER32 0x02
11#define ASN_OCTET_STRING 0x04 11#define ASN_OCTET_STRING 0x04
12#define ASN_NULL 0x05 12#define ASN_NULL 0x05
19#define ASN_OPAQUE 0x44 19#define ASN_OPAQUE 0x44
20#define ASN_COUNTER64 0x46 20#define ASN_COUNTER64 0x46
21 21
22#define MAX_OID_STRLEN 4096 22#define MAX_OID_STRLEN 4096
23 23
24#define HAVE_VERSIONSORT defined (_GNU_SOURCE) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
25
26static SV *cur_bufobj;
24static SV *msg; 27static SV *msg;
25static int errflag, leading_dot; 28static int errflag, leading_dot;
26static U8 *buf, *cur; 29static U8 *buf, *cur;
27static STRLEN len, rem; 30static STRLEN len, rem;
28 31
32typedef SV *BUFOBJ;
33
34/////////////////////////////////////////////////////////////////////////////
35
36#if 0
37 if (msg)
38 croak ("recursive invocation of Net::SNMP::XS parser is not supported");
39
40
41void
42clr_msg ()
43 CODE:
44 SvREFCNT_dec (msg); msg = 0;
45 buf = cur = (U8 *)"";
46 len = rem = 0;
47#endif
48
49static void
50switch_bufobj (BUFOBJ neu)
51{
52 // serialise our state back
53 if (msg && SvROK (msg))
54 {
55 SV *idx_sv = *hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1);
56 sv_setiv (idx_sv, cur - buf);
57 }
58
59 SvREFCNT_dec (msg);
60 msg = newSVsv (neu);
61 cur_bufobj = SvRV (msg);
62 sv_rvweaken (msg);
63
64 SV *bufsv = *hv_fetch ((HV *)cur_bufobj, "_buffer", sizeof ("_buffer") - 1, 1);
65 IV index = SvIV (*hv_fetch ((HV *)cur_bufobj, "_index" , sizeof ("_index" ) - 1, 1));
66
67 errflag = 0;
68 leading_dot = -1;
69 buf = SvPVbyte (bufsv, len);
70 cur = buf + index;
71 rem = len - index;
72}
73
74/////////////////////////////////////////////////////////////////////////////
75
29static SV * 76static SV *
30x_get_cv (SV *cb_sv) 77x_get_cv (SV *cb_sv)
31{ 78{
32 HV *st; 79 HV *st;
33 GV *gvp; 80 GV *gvp;
38 85
39 return (SV *)cv; 86 return (SV *)cv;
40} 87}
41 88
42static void 89static void
43error (const char *msg) 90error (const char *errmsg)
44{ 91{
45 errflag = 1; 92 errflag = 1;
46 93
47 printf ("<<<%s>>>\n", msg);//D 94 if (!msg)
95 croak ("Net::SNMP::XS fatal error, parser called without parsing context");
96
97 dSP;
98 PUSHMARK (SP);
99 EXTEND (SP, 2);
100 PUSHs (msg);
101 PUSHs (sv_2mortal (newSVpv (errmsg, 0)));
102 PUTBACK;
103 call_method ("_error", G_VOID | G_DISCARD);
48} 104}
49 105
50static int 106static int
51need (int count) 107need (int count)
52{ 108{
183process_unsigned32_sv (void) 239process_unsigned32_sv (void)
184{ 240{
185 return newSVuv ((U32)process_integer32 ()); 241 return newSVuv ((U32)process_integer32 ());
186} 242}
187 243
244#if IVSIZE >= 8
245
246static U64TYPE
247process_integer64 (void)
248{
249 U32 length = process_length ();
250
251 if (length <= 0)
252 {
253 error ("INTEGER64 length equal to zero");
254 return 0;
255 }
256
257 U8 *data = getn (length, 0);
258
259 if (!data)
260 return 0;
261
262 if (length > 9 || (length > 8 && data [0]))
263 {
264 error ("INTEGER64 length too long");
265 return 0;
266 }
267
268 U64TYPE res = data [0] & 0x80 ? 0xffffffffffffffff : 0;
269
270 while (length--)
271 res = (res << 8) | *data++;
272
273 return res;
274}
275
276static SV *
277process_integer64_sv (void)
278{
279 return newSViv ((I64TYPE)process_integer64 ());
280}
281
282static SV *
283process_unsigned64_sv (void)
284{
285 return newSVuv ((U64TYPE)process_integer64 ());
286}
287
288#endif
289
188static SV * 290static SV *
189process_octet_string_sv (void) 291process_octet_string_sv (void)
190{ 292{
191 U32 length = process_length (); 293 U32 length = process_length ();
192 294
218 U32 length = process_length (); 320 U32 length = process_length ();
219 321
220 if (length <= 0) 322 if (length <= 0)
221 { 323 {
222 error ("OBJECT IDENTIFIER length equal to zero"); 324 error ("OBJECT IDENTIFIER length equal to zero");
223 return ""; 325 return &PL_sv_undef;
224 } 326 }
225 327
226 U8 *end = cur + length; 328 U8 *end = cur + length;
227 U32 w = getb (); 329 U32 w = getb ();
228 330
229 static char oid[MAX_OID_STRLEN]; // must be static 331 static char oid[MAX_OID_STRLEN]; // must be static
230 char *app = oid; 332 char *app = oid;
333
334 if (leading_dot < 0)
335 leading_dot = SvTRUE (*hv_fetch ((HV *)SvRV (msg), "_leading_dot", sizeof ("_leading_dot") - 1, 1));
231 336
232 *app = '.'; app += ! ! leading_dot; 337 *app = '.'; app += ! ! leading_dot;
233 app = write_uv (app, (U8)w / 40); 338 app = write_uv (app, (U8)w / 40);
234 *app++ = '.'; 339 *app++ = '.';
235 app = write_uv (app, (U8)w % 40); 340 app = write_uv (app, (U8)w % 40);
302 } 407 }
303 408
304 return errflag ? &PL_sv_undef : res; 409 return errflag ? &PL_sv_undef : res;
305} 410}
306 411
412/////////////////////////////////////////////////////////////////////////////
413
414#if HAVE_VERSIONSORT
415
416static int
417oid_lex_cmp (const void *a_, const void *b_)
418{
419 const char *a = SvPVX (*(SV **)a_);
420 const char *b = SvPVX (*(SV **)b_);
421
422 a += *a == '.';
423 b += *b == '.';
424
425 return strverscmp (a, b);
426}
427
428#endif
429
307MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 430MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
308 431
309PROTOTYPES: ENABLE 432PROTOTYPES: ENABLE
310 433
311BOOT: 434BOOT:
317 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv))); 440 av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv)));
318 441
319void 442void
320set_msg (SV *msg_, SV *buf_) 443set_msg (SV *msg_, SV *buf_)
321 CODE: 444 CODE:
322 errflag = 0;
323 leading_dot = -1;
324 msg = SvREFCNT_inc (msg_);
325 buf = SvPVbyte (buf_, len);
326 cur = buf;
327 rem = len;
328#ifdef BENCHMARK
329 t1 = tstamp ();
330#endif
331 445
332void 446void
333clr_msg () 447clr_msg ()
334 CODE: 448 CODE:
335 SvREFCNT_dec (msg);
336 buf = cur = "";
337 len = rem = 0;
338#ifdef BENCHMARK
339 printf ("%f\n", tstamp () - t1);//D
340#endif
341 449
342MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message 450MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
343 451
344void 452void
345_buffer_get (SV *self, int count = -1) 453_buffer_get (BUFOBJ self, int count = -1)
346 PPCODE: 454 PPCODE:
347{ 455{
348 // grrr. 456 // grrr.
349 if (count < 0) 457 if (count < 0)
350 { 458 {
361 if (data) 469 if (data)
362 XPUSHs (sv_2mortal (newSVpvn (data, count))); 470 XPUSHs (sv_2mortal (newSVpvn (data, count)));
363} 471}
364 472
365U32 473U32
366index (SV *self, int ndx = -1) 474index (BUFOBJ self, int ndx = -1)
367 CODE: 475 CODE:
368{ 476{
369 if (ndx >= 0 && ndx < len) 477 if (ndx >= 0 && ndx < len)
370 { 478 {
371 cur = buf + ndx; 479 cur = buf + ndx;
376} 484}
377 OUTPUT: 485 OUTPUT:
378 RETVAL 486 RETVAL
379 487
380U32 488U32
381_process_length (SV *self, ...) 489_process_length (BUFOBJ self, ...)
382 ALIAS: 490 ALIAS:
383 _process_sequence = 0 491 _process_sequence = 0
384 CODE: 492 CODE:
385 RETVAL = process_length (); 493 RETVAL = process_length ();
386 OUTPUT: 494 OUTPUT:
387 RETVAL 495 RETVAL
388 496
389SV * 497SV *
390_process_integer32 (SV *self, ...) 498_process_integer32 (BUFOBJ self, ...)
391 CODE: 499 CODE:
392 RETVAL = process_integer32_sv (); 500 RETVAL = process_integer32_sv ();
393 OUTPUT: 501 OUTPUT:
394 RETVAL 502 RETVAL
395 503
396SV * 504SV *
397_process_counter (SV *self, ...) 505_process_counter (BUFOBJ self, ...)
398 ALIAS: 506 ALIAS:
399 _process_gauge = 0 507 _process_gauge = 0
400 _process_timeticks = 0 508 _process_timeticks = 0
401 CODE: 509 CODE:
402 RETVAL = process_unsigned32_sv (); 510 RETVAL = process_unsigned32_sv ();
403 OUTPUT: 511 OUTPUT:
404 RETVAL 512 RETVAL
405 513
514#if IVSIZE >= 8
515
406SV * 516SV *
517_process_counter64 (BUFOBJ self, ...)
518 CODE:
519 RETVAL = process_unsigned64_sv ();
520 OUTPUT:
521 RETVAL
522
523#endif
524
525SV *
407_process_object_identifier (SV *self, ...) 526_process_object_identifier (BUFOBJ self, ...)
408 CODE: 527 CODE:
409 RETVAL = process_object_identifier_sv (); 528 RETVAL = process_object_identifier_sv ();
410 OUTPUT: 529 OUTPUT:
411 RETVAL 530 RETVAL
412 531
413SV * 532SV *
414_process_octet_string (SV *self, ...) 533_process_octet_string (BUFOBJ self, ...)
415 ALIAS: 534 ALIAS:
416 _process_opaque = 0 535 _process_opaque = 0
417 CODE: 536 CODE:
418 RETVAL = process_octet_string_sv (); 537 RETVAL = process_octet_string_sv ();
419 OUTPUT: 538 OUTPUT:
420 RETVAL 539 RETVAL
421 540
422SV * 541SV *
423_process_ipaddress (SV *self, ...) 542_process_ipaddress (BUFOBJ self, ...)
424 CODE: 543 CODE:
425{ 544{
426 U32 length = process_length (); 545 U32 length = process_length ();
427 if (length != 4) 546 if (length != 4)
428 { 547 {
435} 554}
436 OUTPUT: 555 OUTPUT:
437 RETVAL 556 RETVAL
438 557
439SV * 558SV *
440process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0) 559process (BUFOBJ self, SV *expected = &PL_sv_undef, SV *found = 0)
441 CODE: 560 CODE:
442{ 561{
443 int type; 562 int type;
444 563
445 RETVAL = process_sv (&type); 564 RETVAL = process_sv (&type);
454 RETVAL 573 RETVAL
455 574
456MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 575MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
457 576
458SV * 577SV *
459_process_var_bind_list (SV *self) 578_process_var_bind_list (BUFOBJ self)
460 CODE: 579 CODE:
461{ 580{
462 if (get8 () != ASN_SEQUENCE) 581 if (get8 () != ASN_SEQUENCE)
463 error ("SEQUENCE expected at beginning of VarBindList"); 582 error ("SEQUENCE expected at beginning of VarBindList");
464 int seqlen = process_length (); 583 int seqlen = process_length ();
466 585
467 HV *list = newHV (); 586 HV *list = newHV ();
468 AV *names = newAV (); 587 AV *names = newAV ();
469 HV *types = newHV (); 588 HV *types = newHV ();
470 589
471 hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0); 590 hv_store ((HV *)cur_bufobj, "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
472 hv_store ((HV *)SvRV (self), "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0); 591 hv_store ((HV *)cur_bufobj, "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
473 hv_store ((HV *)SvRV (self), "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0); 592 hv_store ((HV *)cur_bufobj, "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
474 593
475 while (cur < end && !errflag) 594 while (cur < end && !errflag)
476 { 595 {
477 // SEQUENCE ObjectName ObjectSyntax 596 // SEQUENCE ObjectName ObjectSyntax
478 if (get8 () != ASN_SEQUENCE) 597 if (get8 () != ASN_SEQUENCE)
488 hv_store_ent (types, oid, newSViv (type), 0); 607 hv_store_ent (types, oid, newSViv (type), 0);
489 hv_store_ent (list , oid, val, 0); 608 hv_store_ent (list , oid, val, 0);
490 av_push (names, oid); 609 av_push (names, oid);
491 } 610 }
492 611
493 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT); 612 // sigh - great design to do it here
613 SV *pdu_type = *hv_fetch ((HV *)cur_bufobj, "_pdu_type" , sizeof ("_pdu_type" ) - 1, 1);
614
615 if (SvIV (pdu_type) == 0xa8) // REPORT
616 {
617 PUSHMARK (SP);
618 XPUSHs (msg);
619 PUTBACK;
620 call_method ("_report_pdu_error", G_VOID | G_DISCARD);
621 SPAGAIN;
622 XSRETURN_EMPTY;
623 }
494 624
495 RETVAL = newRV_inc ((SV *)list); 625 RETVAL = newRV_inc ((SV *)list);
496} 626}
497 OUTPUT: 627 OUTPUT:
498 RETVAL 628 RETVAL
499 629
630MODULE = Net::SNMP::XS PACKAGE = Net::SNMP
500 631
632void
633oid_base_match (SV *base_, SV *oid_)
634 PROTOTYPE: $$
635 ALIAS:
636 oid_context_match = 0
637 PPCODE:
638{
639 if (!SvOK (base_) || !SvOK (oid_))
640 XSRETURN_NO;
641
642 STRLEN blen, olen;
643 char *base = SvPV (base_, blen);
644 char *oid = SvPV (oid_ , olen);
645
646 blen -= *base == '.'; base += *base == '.';
647 olen -= *base == '.'; oid += *oid == '.';
648
649 if (olen < blen)
650 XSRETURN_NO;
651
652 if (memcmp (base, oid, blen))
653 XSRETURN_NO;
654
655 if (oid [blen] && oid [blen] != '.')
656 XSRETURN_NO;
657
658 XSRETURN_YES;
659}
660
661#if HAVE_VERSIONSORT
662
663void
664oid_lex_sort (...)
665 PROTOTYPE: @
666 PPCODE:
667{
668 // make sure SvPVX is valid
669 int i;
670 for (i = items; i--; )
671 {
672 SV *sv = ST (i);
673
674 if (SvTYPE (sv) < SVt_PV || SvTYPE (sv) == SVt_PVAV && SvTYPE (sv) == SVt_PVHV)
675 SvPV_force_nolen (sv);
676 }
677
678 qsort (&ST (0), items, sizeof (SV *), oid_lex_cmp);
679
680 EXTEND (SP, items);
681 // we cheat somewhat by not returning copies here
682 for (i = 0; i < items; ++i)
683 PUSHs (sv_2mortal (SvREFCNT_inc (ST (i))));
684}
685
686int
687_index_cmp (const char *a, const char *b)
688 PROTOTYPE: $$
689 CODE:
690 RETVAL = strverscmp (a, b);
691 OUTPUT:
692 RETVAL
693
694#endif
695

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines