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

# Content
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 #define BENCHMARK
29
30 static SV *msg;
31 static int errflag;
32 static U8 *buf, *cur;
33 static STRLEN len, rem;
34
35 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 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 static AV *av_type;
153
154 MODULE = Net::SNMP::XS PACKAGE = Net::SNMP::XS
155
156 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 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 #ifdef BENCHMARK
175 t1 = tstamp ();
176 #endif
177
178 void
179 clr_msg ()
180 CODE:
181 SvREFCNT_dec (msg);
182 buf = cur = "";
183 len = rem = 0;
184 #ifdef BENCHMARK
185 printf ("%f\n", tstamp () - t1);//D
186 #endif
187
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 _process_sequence = 0
230 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 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