ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-SNMP-XS/XS.xs
Revision: 1.3
Committed: Wed Apr 8 13:54:42 2009 UTC (15 years, 2 months ago) by root
Branch: MAIN
Changes since 1.2: +66 -2 lines
Log Message:
wow

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     // C99 required
6    
7     #define ASN_BOOLEAN 0x01
8     #define ASN_INTEGER 0x02
9     #define ASN_BIT_STR 0x03
10     #define ASN_OCTET_STR 0x04
11     #define ASN_NULL 0x05
12     #define ASN_OBJECT_ID 0x06
13     #define ASN_SEQUENCE 0x10
14     #define ASN_SET 0x11
15    
16     #define ASN_UNIVERSAL 0x00
17     #define ASN_APPLICATION 0x40
18     #define ASN_CONTEXT 0x80
19     #define ASN_PRIVATE 0xc0
20    
21     #define ASN_PRIMITIVE 0x00
22     #define ASN_CONSTRUCTOR 0x20
23    
24     #define ASN_LONG_LEN 0x80
25     #define ASN_EXTENSION_ID 0x1f
26     #define ASN_BIT8 0x80
27    
28 root 1.3 #define BENCHMARK
29 root 1.1
30     static SV *msg;
31     static int errflag;
32     static U8 *buf, *cur;
33     static STRLEN len, rem;
34    
35 root 1.3 static SV *
36     x_get_cv (SV *cb_sv)
37     {
38     HV *st;
39     GV *gvp;
40     CV *cv = sv_2cv (cb_sv, &st, &gvp, 0);
41    
42     if (!cv)
43     croak ("CODE reference expected");
44    
45     return (SV *)cv;
46     }
47    
48 root 1.1 static void
49     error (const char *msg)
50     {
51     errflag = 1;
52    
53     printf ("<<<%s>>>\n", msg);//D
54     }
55    
56     static int
57     need (int count)
58     {
59     if (count < 0 || (int)rem < count)
60     {
61     error ("Unexpected end of message buffer");
62     return 0;
63     }
64    
65     return 1;
66     }
67    
68     static U8 *
69     getn (int count, const U8 *errres)
70     {
71     if (!need (count))
72     return (U8 *)errres;
73    
74     U8 *res = cur;
75    
76     cur += count;
77     rem -= count;
78    
79     return res;
80     }
81    
82     static U8
83     get8 (void)
84     {
85     if (rem <= 0)
86     {
87     error ("Unexpected end of message buffer");
88     return 0;
89     }
90    
91     rem--;
92     return *cur++;
93     }
94    
95     static U32
96     getb (void)
97     {
98     U32 res = 0;
99    
100     for (;;)
101     {
102     U8 c = get8 ();
103     res = (res << 7) | (c & 0x7f);
104    
105     if (!(c & 0x80))
106     return res;
107     }
108     }
109    
110     #ifdef BENCHMARK
111     static double t1;
112    
113     static double
114     tstamp (void)
115     {
116     struct timeval tv;
117     gettimeofday (&tv, 0);
118     return tv.tv_sec + tv.tv_usec * 0.000001;
119     }
120     #endif
121    
122     static U32
123     process_length (void)
124     {
125     U32 res = get8 ();
126    
127     if (res & 0x80)
128     {
129     int cnt = res & 0x7f;
130     res = 0;
131    
132     switch (cnt)
133     {
134     case 0:
135     error ("Indefinite ASN.1 lengths not supported");
136     return 0;
137    
138     default:
139     error ("ASN.1 length too long");
140     return 0;
141    
142     case 4: res = (res << 8) | get8 ();
143     case 3: res = (res << 8) | get8 ();
144     case 2: res = (res << 8) | get8 ();
145     case 1: res = (res << 8) | get8 ();
146     }
147     }
148    
149     return res;
150     }
151    
152 root 1.3 static AV *av_type;
153    
154 root 1.1 MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
155    
156 root 1.3 PROTOTYPES: ENABLE
157    
158     BOOT:
159     av_type = newAV ();
160    
161     void
162     set_type (int type, SV *cv)
163     CODE:
164     av_store (av_type, type, SvREFCNT_inc (x_get_cv (cv)));
165    
166 root 1.1 void
167     set_msg (SV *msg_, SV *buf_)
168     CODE:
169     errflag = 0;
170     msg = SvREFCNT_inc (msg_);
171     buf = SvPVbyte (buf_, len);
172     cur = buf;
173     rem = len;
174 root 1.2 #ifdef BENCHMARK
175 root 1.1 t1 = tstamp ();
176 root 1.2 #endif
177 root 1.1
178     void
179     clr_msg ()
180     CODE:
181     SvREFCNT_dec (msg);
182     buf = cur = "";
183     len = rem = 0;
184 root 1.2 #ifdef BENCHMARK
185 root 1.1 printf ("%f\n", tstamp () - t1);//D
186 root 1.2 #endif
187 root 1.1
188     MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::Message
189    
190     void
191     _buffer_get (SV *self, int count = -1)
192     PPCODE:
193     {
194     // grrr.
195     if (count < 0)
196     {
197     hv_delete ((HV *)SvRV (self), "_index" , 6, G_DISCARD);
198     hv_delete ((HV *)SvRV (self), "_length", 7, G_DISCARD);
199     SV **svp = hv_fetch ((HV *)SvRV (self), "_buffer", 7, 1);
200     XPUSHs (sv_2mortal (newSVsv (*svp)));
201     sv_setpvn (*svp, "", 0);
202     XSRETURN (1);
203     }
204    
205     char *data = getn (count, 0);
206    
207     if (data)
208     XPUSHs (sv_2mortal (newSVpvn (data, count)));
209     }
210    
211     U32
212     index (SV *self, int ndx = -1)
213     CODE:
214     {
215     if (ndx >= 0 && ndx < len)
216     {
217     cur = buf + ndx;
218     rem = len - ndx;
219     }
220    
221     RETVAL = cur - buf;
222     }
223     OUTPUT:
224     RETVAL
225    
226     U32
227     _process_length (SV *self, ...)
228     ALIAS:
229 root 1.3 _process_sequence = 0
230 root 1.1 CODE:
231     RETVAL = process_length ();
232     OUTPUT:
233     RETVAL
234    
235     I32
236     _process_integer32 (SV *self, ...)
237     ALIAS:
238     _process_counter = 0
239     _process_gauge = 0
240     CODE:
241     {
242     U32 length = process_length ();
243    
244     if (length <= 0)
245     {
246     error ("INTEGER32 length equal to zero");
247     XSRETURN_UNDEF;
248     }
249    
250     U8 *data = getn (length, 0);
251    
252     if (!data)
253     XSRETURN_UNDEF;
254    
255     if (length > 5 || (length > 4 && data [0]))
256     {
257     error ("INTEGER32 length too long");
258     XSRETURN_UNDEF;
259     }
260    
261     U32 res = data [0] & 0x80 ? 0xffffffff : 0;
262    
263     while (length--)
264     res = (res << 8) | *data++;
265    
266     RETVAL = res;
267     }
268     OUTPUT:
269     RETVAL
270    
271     SV *
272     _process_object_identifier (SV *self, ...)
273     CODE:
274     {
275     U32 length = process_length ();
276    
277     if (length <= 0)
278     {
279     error ("OBJECT IDENTIFIER length equal to zero");
280     XSRETURN_UNDEF;
281     }
282    
283     U8 *end = cur + length;
284     U32 w = getb ();
285    
286     //TODO: leading_dots
287    
288     RETVAL = newSVpvf (".%d.%d", (int)w / 40, (int)w % 40);
289    
290     while (cur < end)
291     {
292     w = getb ();
293     sv_catpvf (RETVAL, ".%u", (unsigned int)w);
294     }
295     }
296     OUTPUT:
297     RETVAL
298    
299     SV *
300     _process_octet_string (SV *self, ...)
301     ALIAS:
302     _process_opaque = 0
303     CODE:
304     {
305     U32 length = process_length ();
306    
307     U8 *data = getn (length, 0);
308     if (!data)
309     {
310     error ("OCTET STRING too long");
311     XSRETURN_UNDEF;
312     }
313    
314     RETVAL = newSVpvn (data, length);
315     }
316     OUTPUT:
317     RETVAL
318    
319     SV *
320     _process_ipaddress (SV *self, ...)
321     CODE:
322     {
323     U32 length = process_length ();
324     if (length != 4)
325     {
326     error ("IP ADDRESS length not four");
327     XSRETURN_UNDEF;
328     }
329    
330     U8 *data = getn (4, "\x00\x00\x00\x00");
331     RETVAL = newSVpvf ("%d.%d.%d.%d", data [0], data [1], data [2], data [3]);
332     }
333     OUTPUT:
334     RETVAL
335    
336 root 1.3 SV *
337     process (SV *self, SV *expected = 0, SV *found = 0)
338     PPCODE:
339     {
340     U8 type = get8 ();
341    
342     if (expected && SvOK (expected) && type != SvIV (expected))
343     {
344     error ("Expected a different type than found");
345     XSRETURN_UNDEF;
346     }
347    
348     if (type > AvFILLp (av_type) || !SvTYPE (AvARRAY (av_type)[type]) == SVt_PVCV)
349     {
350     sv_dump (AvARRAY (av_type)[type]);//D
351     error ("Unknown ASN.1 type");
352     XSRETURN_UNDEF;
353     }
354    
355     if (found)
356     sv_setiv (found, type);
357    
358     SV *res;
359    
360     {
361     dSP;
362     PUSHMARK (SP);
363     EXTEND (SP, 2);
364     PUSHs (self);
365     PUSHs (expected);
366     PUTBACK;
367     int count = call_sv (AvARRAY (av_type)[type], G_SCALAR);
368     SPAGAIN;
369     res = count ? TOPs : &PL_sv_undef;
370     }
371    
372     XPUSHs (res);
373     }
374