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.6 by root, Thu Apr 9 05:56:36 2009 UTC

15#define ASN_UNSIGNED32 0x42 15#define ASN_UNSIGNED32 0x42
16#define ASN_TIMETICKS 0x43 16#define ASN_TIMETICKS 0x43
17#define ASN_OPAQUE 0x44 17#define ASN_OPAQUE 0x44
18#define ASN_COUNTER64 0x46 18#define ASN_COUNTER64 0x46
19 19
20#define BENCHMARK 20//#define BENCHMARK
21 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;
210 buf += sprintf (buf, "%u", (unsigned int)u); 210 buf += sprintf (buf, "%u", (unsigned int)u);
211 211
212 return buf; 212 return buf;
213} 213}
214 214
215static SV * 215static char *
216process_object_identifier_sv (void) 216process_object_identifier (int *len)
217{ 217{
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 244
247 while (cur < end) 245 *len = app - oid;
248 { 246 return oid;
249 w = getb (); 247}
250 buf += snprintf (buf, oid + sizeof (oid) - buf, ".%u", (unsigned int)w);
251 }
252#endif
253 248
249static SV *
250process_object_identifier_sv (void)
251{
252 int len;
253 char *oid = process_object_identifier (&len);
254
254 return newSVpvn (oid, app - oid); 255 return newSVpvn (oid, len);
255} 256}
256 257
257static AV *av_type; 258static AV *av_type;
259
260static SV *
261process_sv (int *found)
262{
263 int type = get8 ();
264
265 *found = type;
266
267 SV *res;
268
269 switch (type)
270 {
271 case ASN_OBJECT_IDENTIFIER:
272 res = process_object_identifier_sv ();
273 break;
274
275 case ASN_INTEGER32:
276 res = process_integer32_sv ();
277 break;
278
279 case ASN_UNSIGNED32:
280 case ASN_COUNTER32:
281 case ASN_TIMETICKS:
282 res = process_unsigned32_sv ();
283 break;
284
285 case ASN_SEQUENCE:
286 res = newSVuv (process_length ());
287 break;
288
289 case ASN_OCTET_STRING:
290 case ASN_OPAQUE:
291 res = process_octet_string_sv ();
292 break;
293
294 default:
295 {
296 if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
297 {
298 error ("Unknown ASN.1 type");
299 return &PL_sv_undef;
300 }
301
302 dSP;
303 PUSHMARK (SP);
304 EXTEND (SP, 2);
305 PUSHs (msg);
306 PUSHs (sv_2mortal (newSViv (type)));
307 PUTBACK;
308 int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
309 SPAGAIN;
310 res = count ? SvREFCNT_inc (TOPs) : &PL_sv_undef;
311 }
312 }
313
314 return errflag ? &PL_sv_undef : res;
315}
258 316
259MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS 317MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
260 318
261PROTOTYPES: ENABLE 319PROTOTYPES: ENABLE
262 320
387} 445}
388 OUTPUT: 446 OUTPUT:
389 RETVAL 447 RETVAL
390 448
391SV * 449SV *
392process (SV *self, SV *expected = 0, SV *found = 0) 450process (SV *self, SV *expected = &PL_sv_undef, SV *found = 0)
393 PPCODE: 451 CODE:
394{ 452{
395 U8 type = get8 (); 453 int type;
396 454
397 if (expected && SvOK (expected) && type != SvIV (expected)) 455 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 456
410 if (found) 457 if (found)
411 sv_setiv (found, type); 458 sv_setiv (found, type);
412 459
413 //TODO: switch based on type, to avoid calling overhead 460 if (SvOK (expected) && type != SvIV (expected))
414 SV *res; 461 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} 462}
457 463 OUTPUT:
458#if 0 464 RETVAL
459 465
460MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU 466MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::PDU
461 467
462SV * 468SV *
463_process_var_bind_list (SV *self) 469_process_var_bind_list (SV *self)
464 CODE: 470 CODE:
465{ 471{
466 # VarBindList::=SEQUENCE 472 if (get8 () != ASN_SEQUENCE)
467 if (!defined($value = $this->process(SEQUENCE))) { 473 error ("SEQUENCE expected at beginning of VarBindList");
468 return $this->_error; 474 int seqlen = process_length ();
469 } 475 U8 *end = cur + seqlen;
476
477 HV *list = newHV ();
478 AV *names = newAV ();
479 HV *types = newHV ();
480
481 hv_store ((HV *)SvRV (self), "_var_bind_list" , sizeof ("_var_bind_list" ) - 1, newRV_noinc ((SV *)list ), 0);
482 hv_store ((HV *)SvRV (self), "_var_bind_names", sizeof ("_var_bind_names") - 1, newRV_noinc ((SV *)names), 0);
483 hv_store ((HV *)SvRV (self), "_var_bind_types", sizeof ("_var_bind_types") - 1, newRV_noinc ((SV *)types), 0);
470 484
471 # Using the length of the VarBindList SEQUENCE, 485 while (cur < end && !errflag)
472 # calculate the end index. 486 {
487 // SEQUENCE ObjectName ObjectSyntax
488 if (get8 () != ASN_SEQUENCE)
489 error ("SEQUENCE expected at beginning of VarBind");
490 process_length ();
491
492 if (get8 () != ASN_OBJECT_IDENTIFIER)
493 error ("OBJECT IDENTIFIER expected at beginning of VarBind");
494 int type, oidlen;
495 char *oid = process_object_identifier (&oidlen);
496 SV *val = process_sv (&type);
473 497
474 my $end = $this->index + $value; 498 hv_store (types, oid, oidlen, newSViv (type), 0);
499 hv_store (list , oid, oidlen, val, 0);
500 av_push (names, newSVpvn (oid, oidlen));
501 }
475 502
476 $this->{_var_bind_list} = {}; 503 //return $this->_report_pdu_error if ($this->{_pdu_type} == REPORT);
477 $this->{_var_bind_names} = [];
478 $this->{_var_bind_types} = {};
479 504
480 my ($oid, $type); 505 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} 506}
507 OUTPUT:
508 RETVAL
527 509
528#endif
529 510

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines