Skip to content

Commit bc54a9c

Browse files
author
blackhedd
committed
added a compiler for ASN/BER syntax, avoids interpreting it for
every packet we parse.
1 parent 7fd1089 commit bc54a9c

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

lib/net/ber.rb

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
#
3030

3131

32-
33-
3432
module Net
3533

3634
module BER
@@ -52,14 +50,34 @@ def initialize
5250
end
5351
end
5452

53+
#--
54+
# This condenses our nicely self-documenting ASN hashes down
55+
# to an array for fast lookups.
56+
# Scoped to be called as a module method, but not intended for
57+
# user code to call.
58+
#
59+
def self.compile_syntax syn
60+
out = [nil] * 256
61+
syn.each {|tclass,tclasses|
62+
tagclass = {:universal=>0, :application=>64, :context_specific=>128, :private=>192} [tclass]
63+
tclasses.each {|codingtype,codings|
64+
encoding = {:primitive=>0, :constructed=>32} [codingtype]
65+
codings.each {|tag,objtype|
66+
out[tagclass + encoding + tag] = objtype
67+
}
68+
}
69+
}
70+
out
71+
end
72+
5573
# This module is for mixing into IO and IO-like objects.
5674
module BERParser
5775

5876
# The order of these follows the class-codes in BER.
5977
# Maybe this should have been a hash.
6078
TagClasses = [:universal, :application, :context_specific, :private]
6179

62-
BuiltinSyntax = {
80+
BuiltinSyntax = BER.compile_syntax( {
6381
:universal => {
6482
:primitive => {
6583
1 => :boolean,
@@ -72,7 +90,7 @@ module BERParser
7290
17 => :array
7391
}
7492
}
75-
}
93+
})
7694

7795
#
7896
# read_ber
@@ -86,10 +104,10 @@ def read_ber syntax=nil
86104
#return nil if eof?
87105

88106
id = getc or return nil # don't trash this value, we'll use it later
89-
tag = id & 31
90-
tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
91-
tagclass = TagClasses[ id >> 6 ]
92-
encoding = (id & 0x20 != 0) ? :constructed : :primitive
107+
#tag = id & 31
108+
#tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
109+
#tagclass = TagClasses[ id >> 6 ]
110+
#encoding = (id & 0x20 != 0) ? :constructed : :primitive
93111

94112
n = getc
95113
lengthlength,contentlength = if n <= 127
@@ -105,14 +123,17 @@ def read_ber syntax=nil
105123
newobj = read contentlength
106124

107125
# This exceptionally clever and clear bit of code is verrrry slow.
126+
=begin
108127
objtype = nil
109128
[syntax, BuiltinSyntax].each {|syn|
110129
if syn && (ot = syn[tagclass]) && (ot = ot[encoding]) && ot[tag]
111130
objtype = ot[tag]
112131
break
113132
end
114133
}
115-
134+
=end
135+
objtype = (syntax && syntax[id]) || BuiltinSyntax[id]
136+
116137
=begin
117138
Replaced this case with if/else because Symbol#=== profiled surprisingly hot.
118139
obj = case objtype
@@ -164,7 +185,8 @@ def read_ber syntax=nil
164185
elsif objtype == :boolean
165186
newobj != "\000"
166187
else
167-
raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
188+
#raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
189+
raise BerError.new( "unsupported object type: id=#{id}" )
168190
end
169191

170192
# Add the identifier bits into the object if it's a String or an Array.

lib/net/ldap.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ class LdapError < Exception; end
271271
SearchScope_WholeSubtree = 2
272272
SearchScopes = [SearchScope_BaseObject, SearchScope_SingleLevel, SearchScope_WholeSubtree]
273273

274-
AsnSyntax = {
274+
AsnSyntax = BER.compile_syntax({
275275
:application => {
276276
:constructed => {
277277
0 => :array, # BindRequest
@@ -306,7 +306,7 @@ class LdapError < Exception; end
306306
3 => :array, # Seach referral
307307
}
308308
}
309-
}
309+
})
310310

311311
DefaultHost = "127.0.0.1"
312312
DefaultPort = 389

0 commit comments

Comments
 (0)