added a compiler for ASN/BER syntax, avoids interpreting it for
every packet we parse.
This commit is contained in:
parent
7fd1089115
commit
bc54a9c826
2 changed files with 34 additions and 12 deletions
|
@ -29,8 +29,6 @@
|
|||
#
|
||||
|
||||
|
||||
|
||||
|
||||
module Net
|
||||
|
||||
module BER
|
||||
|
@ -52,6 +50,26 @@ module Net
|
|||
end
|
||||
end
|
||||
|
||||
#--
|
||||
# This condenses our nicely self-documenting ASN hashes down
|
||||
# to an array for fast lookups.
|
||||
# Scoped to be called as a module method, but not intended for
|
||||
# user code to call.
|
||||
#
|
||||
def self.compile_syntax syn
|
||||
out = [nil] * 256
|
||||
syn.each {|tclass,tclasses|
|
||||
tagclass = {:universal=>0, :application=>64, :context_specific=>128, :private=>192} [tclass]
|
||||
tclasses.each {|codingtype,codings|
|
||||
encoding = {:primitive=>0, :constructed=>32} [codingtype]
|
||||
codings.each {|tag,objtype|
|
||||
out[tagclass + encoding + tag] = objtype
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
end
|
||||
|
||||
# This module is for mixing into IO and IO-like objects.
|
||||
module BERParser
|
||||
|
||||
|
@ -59,7 +77,7 @@ module Net
|
|||
# Maybe this should have been a hash.
|
||||
TagClasses = [:universal, :application, :context_specific, :private]
|
||||
|
||||
BuiltinSyntax = {
|
||||
BuiltinSyntax = BER.compile_syntax( {
|
||||
:universal => {
|
||||
:primitive => {
|
||||
1 => :boolean,
|
||||
|
@ -72,7 +90,7 @@ module Net
|
|||
17 => :array
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
#
|
||||
# read_ber
|
||||
|
@ -86,10 +104,10 @@ module Net
|
|||
#return nil if eof?
|
||||
|
||||
id = getc or return nil # don't trash this value, we'll use it later
|
||||
tag = id & 31
|
||||
tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
|
||||
tagclass = TagClasses[ id >> 6 ]
|
||||
encoding = (id & 0x20 != 0) ? :constructed : :primitive
|
||||
#tag = id & 31
|
||||
#tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
|
||||
#tagclass = TagClasses[ id >> 6 ]
|
||||
#encoding = (id & 0x20 != 0) ? :constructed : :primitive
|
||||
|
||||
n = getc
|
||||
lengthlength,contentlength = if n <= 127
|
||||
|
@ -105,6 +123,7 @@ module Net
|
|||
newobj = read contentlength
|
||||
|
||||
# This exceptionally clever and clear bit of code is verrrry slow.
|
||||
=begin
|
||||
objtype = nil
|
||||
[syntax, BuiltinSyntax].each {|syn|
|
||||
if syn && (ot = syn[tagclass]) && (ot = ot[encoding]) && ot[tag]
|
||||
|
@ -112,7 +131,9 @@ module Net
|
|||
break
|
||||
end
|
||||
}
|
||||
|
||||
=end
|
||||
objtype = (syntax && syntax[id]) || BuiltinSyntax[id]
|
||||
|
||||
=begin
|
||||
Replaced this case with if/else because Symbol#=== profiled surprisingly hot.
|
||||
obj = case objtype
|
||||
|
@ -164,7 +185,8 @@ module Net
|
|||
elsif objtype == :boolean
|
||||
newobj != "\000"
|
||||
else
|
||||
raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
|
||||
#raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
|
||||
raise BerError.new( "unsupported object type: id=#{id}" )
|
||||
end
|
||||
|
||||
# Add the identifier bits into the object if it's a String or an Array.
|
||||
|
|
|
@ -271,7 +271,7 @@ module Net
|
|||
SearchScope_WholeSubtree = 2
|
||||
SearchScopes = [SearchScope_BaseObject, SearchScope_SingleLevel, SearchScope_WholeSubtree]
|
||||
|
||||
AsnSyntax = {
|
||||
AsnSyntax = BER.compile_syntax({
|
||||
:application => {
|
||||
:constructed => {
|
||||
0 => :array, # BindRequest
|
||||
|
@ -306,7 +306,7 @@ module Net
|
|||
3 => :array, # Seach referral
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
DefaultHost = "127.0.0.1"
|
||||
DefaultPort = 389
|
||||
|
|
Loading…
Reference in a new issue