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