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.5 by root, Thu Apr 9 04:49:16 2009 UTC vs.
Revision 1.7 by root, Thu Apr 9 07:10:23 2009 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
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
7#define BENCHMARK
6 8
7#define ASN_BOOLEAN 0x01 9#define ASN_BOOLEAN 0x01
8#define ASN_INTEGER32 0x02 10#define ASN_INTEGER32 0x02
9#define ASN_OCTET_STRING 0x04 11#define ASN_OCTET_STRING 0x04
10#define ASN_NULL 0x05 12#define ASN_NULL 0x05
15#define ASN_UNSIGNED32 0x42 17#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43 18#define ASN_TIMETICKS 0x43
17#define ASN_OPAQUE 0x44 19#define ASN_OPAQUE 0x44
18#define ASN_COUNTER64 0x46 20#define ASN_COUNTER64 0x46
19 21
20#define BENCHMARK
21
22#define MAX_OID_STRLEN 4096 22#define MAX_OID_STRLEN 4096
23 23
24static SV *msg; 24static SV *msg;
25static int errflag, leading_dot; 25static int errflag, leading_dot;
26static U8 *buf, *cur; 26static U8 *buf, *cur;
218 U32 length = process_length (); 218 U32 length = process_length ();
219 219
220 if (length <= 0) 220 if (length <= 0)
221 { 221 {
222 error ("OBJECT IDENTIFIER length equal to zero"); 222 error ("OBJECT IDENTIFIER length equal to zero");
223 return &PL_sv_undef; 223 return "";
224 } 224 }
225 225
226 U8 *end = cur + length; 226 U8 *end = cur + length;
227 U32 w = getb (); 227 U32 w = getb ();
228 228
229 static char oid[MAX_OID_STRLEN]; 229 static char oid[MAX_OID_STRLEN]; // must be static
230 char *app = oid; 230 char *app = oid;
231 231
232 *app = '.'; app += ! ! leading_dot; 232 *app = '.'; app += ! ! leading_dot;
233 app = write_uv (app, w / 40); 233 app = write_uv (app, (U8)w / 40);
234 *app++ = '.'; 234 *app++ = '.';
235 app = write_uv (app, w % 40); 235 app = write_uv (app, (U8)w % 40);
236 236
237 // we assume an oid component is never > 64 bytes 237 // we assume an oid component is never > 64 bytes
238 while (cur < end && oid + sizeof (oid) - app > 64) 238 while (cur < end && oid + sizeof (oid) - app > 64)
239 { 239 {
240 w = getb (); 240 w = getb ();
241 *app++ = '.'; 241 *app++ = '.';
242 app = write_uv (app, w); 242 app = write_uv (app, w);
243 } 243 }
244#if 0
245 buf += snprintf (buf, oid + sizeof (oid) - buf, "%d.%d", (int)w / 40, (int)w % 40);
246
247 while (cur < end)
248 {
249 w = getb ();
250 buf += snprintf (buf, oid + sizeof (oid) - buf, ".%u", (unsigned int)w);
251 }
252#endif
253 244
254 return newSVpvn (oid, app - oid); 245 return newSVpvn (oid, app - oid);
255} 246}
256 247
257static AV *av_type; 248static AV *av_type;
249
250static SV *
251process_sv (int *found)
252{
253 int type = get8 ();
254
255 *found = type;
256
257 SV *res;
258
259 switch (type)
260 {
261 case ASN_OBJECT_IDENTIFIER:
262 res = process_object_identifier_sv ();
263 break;
264
265 case ASN_INTEGER32:
266 res = process_integer32_sv ();
267 break;
268
269 case ASN_UNSIGNED32:
270 case ASN_COUNTER32:
271 case ASN_TIMETICKS:
272 res = process_unsigned32_sv ();
273 break;
274
275 case ASN_SEQUENCE:
276 res = newSVuv (process_length ());
277 break;
278
279 case ASN_OCTET_STRING:
280 case ASN_OPAQUE:
281 res = process_octet_string_sv ();
282 break;
283
284 default:
285 {
286 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
287 {
288 error ("Unknown ASN.1 type");
289 return &PL_sv_undef;
290 }
291
292 dSP;
293 PUSHMARK (SP);
294 EXTEND (SP, 2);
295 PUSHs (msg);
296 PUSHs (sv_2mortal (newSViv (type)));
297 PUTBACK;
298 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
299 SPAGAIN;
300 res = count ? SvREFCNT_inc (TOPs) : &PL_sv_undef;
301 }
302 }
303
304 return errflag ? &PL_sv_undef : res;
305}
258 306
259MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 307MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
260 308
261PROTOTYPES: ENABLE 309PROTOTYPES: ENABLE
262 310
387} 435}
388 OUTPUT: 436 OUTPUT:
389 RETVAL 437 RETVAL
390 438
391SV * 439SV *
392process (SV *self, SV *expected = 0, SV *found = 0) 440process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0)
393 PPCODE: 441 CODE:
394{ 442{
395 U8 type = get8 (); 443 int type;
396 444
397 if (expected && SvOK (expected) && type != SvIV (expected)) 445 RETVAL = process_sv (&type);
398 {
399 error ("Expected a different type than found");
400 XSRETURN_UNDEF;
401 }
402
403 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
404 {
405 sv_dump (AvARRAY (av_type)[type]);//D
406 error ("Unknown ASN.1 type");
407 XSRETURN_UNDEF;
408 }
409 446
410 if (found) 447 if (found)
411 sv_setiv (found, type); 448 sv_setiv (found, type);
412 449
413 //TODO: switch based on type, to avoid calling overhead 450 if (SvOK (expected) && type != SvIV (expected))
414 SV *res; 451 error ("Expected a different type than found");
415
416 switch (type)
417 {
418 case ASN_OBJECT_IDENTIFIER:
419 res = sv_2mortal (process_object_identifier_sv ());
420 break;
421
422 case ASN_INTEGER32:
423 res = sv_2mortal (process_integer32_sv ());
424 break;
425
426 case ASN_UNSIGNED32:
427 case ASN_COUNTER32:
428 case ASN_TIMETICKS:
429 res = sv_2mortal (process_unsigned32_sv ());
430 break;
431
432 case ASN_SEQUENCE:
433 res = sv_2mortal (newSVuv (process_length ()));
434 break;
435
436 case ASN_OCTET_STRING:
437 case ASN_OPAQUE:
438 res = sv_2mortal (process_octet_string_sv ());
439 break;
440
441 default:
442 {
443 dSP;
444 PUSHMARK (SP);
445 EXTEND (SP, 2);
446 PUSHs (self);
447 PUSHs (expected);
448 PUTBACK;
449 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
450 SPAGAIN;
451 res = count ? TOPs : &PL_sv_undef;
452 }
453 }
454
455 XPUSHs (errflag ? &PL_sv_undef : res);
456} 452}
457 453 OUTPUT:
458#if 0 454 RETVAL
459 455
460MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 456MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
461 457
462SV * 458SV *
463_process_var_bind_list (SV *self) 459_process_var_bind_list (SV *self)
464 CODE: 460 CODE:
465{ 461{
466 # VarBindList::=SEQUENCE 462 if (get8 () != ASN_SEQUENCE)
467 if (!defined($value = $this->process(SEQUENCE))) { 463 error ("SEQUENCE expected at beginning of VarBindList");
468 return $this->_error; 464 int seqlen = process_length ();
469 } 465 U8 *end = cur + seqlen;
466
467 HV *list = newHV ();
468 AV *names = newAV ();
469 HV *types = newHV ();
470
471 hv_store ((HV *)SvRV (self), "_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);
473 hv_store ((HV *)SvRV (self), "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
470 474
471 # Using the length of the VarBindList SEQUENCE, 475 while (cur < end && !errflag)
472 # calculate the end index. 476 {
477 // SEQUENCE ObjectName ObjectSyntax
478 if (get8 () != ASN_SEQUENCE)
479 error ("SEQUENCE expected at beginning of VarBind");
480 process_length ();
481
482 if (get8 () != ASN_OBJECT_IDENTIFIER)
483 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
484 int type, oidlen;
485 SV *oid = process_object_identifier_sv ();
486 SV *val = process_sv (&type);
473 487
474 my $end = $this->index + $value; 488 hv_store_ent (types, oid, newSViv (type), 0);
489 hv_store_ent (list , oid, val, 0);
490 av_push (names, oid);
491 }
475 492
476 $this->{_var_bind_list} = {}; 493 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
477 $this->{_var_bind_names} = [];
478 $this->{_var_bind_types} = {};
479 494
480 my ($oid, $type); 495 RETVAL = newRV_inc ((SV *)list);
481
482 while ($this->index < $end) {
483
484 # VarBind::=SEQUENCE
485 if (!defined($this->process(SEQUENCE))) {
486 return $this->_error;
487 }
488 # name::=ObjectName
489 if (!defined($oid = $this->process(OBJECT_IDENTIFIER))) {
490 return $this->_error;
491 }
492 # value::=ObjectSyntax
493 if (!defined($value = $this->process(undef, $type))) {
494 return $this->_error;
495 }
496
497 # Create a hash consisting of the OBJECT IDENTIFIER as a
498 # key and the ObjectSyntax as the value. If there is a
499 # duplicate OBJECT IDENTIFIER in the VarBindList, we pad
500 # that OBJECT IDENTIFIER with spaces to make a unique
501 # key in the hash.
502
503 while (exists($this->{_var_bind_list}->{$oid})) {
504 $oid .= ' '; # Pad with spaces
505 }
506
507 DEBUG_INFO('{ %s => %s: %s }', $oid, asn1_itoa($type), $value);
508 $this->{_var_bind_list}->{$oid} = $value;
509 $this->{_var_bind_types}->{$oid} = $type;
510
511 # Create an array with the ObjectName OBJECT IDENTIFIERs
512 # so that the order in which the VarBinds where encoded
513 # in the PDU can be retrieved later.
514
515 push(@{$this->{_var_bind_names}}, $oid);
516
517 }
518
519 # Return an error based on the contents of the VarBindList
520 # if we received a Report-PDU.
521
522 return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
523
524 # Return the var_bind_list hash
525 $this->{_var_bind_list};
526} 496}
497 OUTPUT:
498 RETVAL
527 499
528#endif
529 500

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines