Skip to content

Commit

Permalink
Merge pull request #28 from woodbusy/mr_changes
Browse files Browse the repository at this point in the history
Last of mrakhmanov's changes
  • Loading branch information
woodbusy committed Oct 2, 2015
2 parents d89de0b + 2861e0c commit 013cae6
Show file tree
Hide file tree
Showing 32 changed files with 412 additions and 506 deletions.
2 changes: 2 additions & 0 deletions lib/net/tns/connection.rb
Expand Up @@ -5,6 +5,7 @@ module Net
module TNS
class Connection
attr_reader :tns_protocol_version
attr_reader :tns_sdu

def initialize(opts={})
@socket = nil
Expand Down Expand Up @@ -83,6 +84,7 @@ def connect(opts={})
return
end
@tns_protocol_version = response.version.to_i
@tns_sdu = response.sdu_size.to_i
negotiate_ano()
end

Expand Down
2 changes: 1 addition & 1 deletion lib/net/tns/packet.rb
Expand Up @@ -13,7 +13,7 @@ class Header < BinData::Record
end

class Packet < BinData::Record
SESSION_DATA_UNIT_SIZE = 2048
SESSION_DATA_UNIT_SIZE = 8192
MAX_PAYLOAD_SIZE = SESSION_DATA_UNIT_SIZE - Header::LENGTH

# BinData fields
Expand Down
2 changes: 1 addition & 1 deletion lib/net/tns/packets/connect_packet.rb
Expand Up @@ -9,7 +9,7 @@ class ConnectPacket < Packet
uint16be :minimum_version, :initial_value => Net::TNS::Version::ALL_VERSIONS.min
uint16be :service_flags
# session data unit size
uint16be :sdu_size, :initial_value => 0x0800
uint16be :sdu_size, :initial_value => Net::TNS::Packet::SESSION_DATA_UNIT_SIZE
# maximum transmission data unit size
uint16be :maximum_tdu_size, :initial_value => 0x7fff
uint16be :protocol_flags, :initial_value => 0xc608
Expand Down
40 changes: 40 additions & 0 deletions lib/net/tti/capabilities.rb
@@ -0,0 +1,40 @@

module Net
module TTI
class Capabilities
def initialize(caps_bytes=[])
@caps_bytes = caps_bytes
end

def self.from_byte_array(bytes)
Capabilities.new(bytes)
end

def self.from_binary_string(string)
Capabilities.new( string.unpack("C*") )
end

def [](index)
@caps_bytes[index]
end

def []=(index, value)
@caps_bytes[index] = value
end

def length
@caps_bytes.length
end

def to_binary_s
@caps_bytes.pack("C*")
end

# Returns hexified bytes, delimited by spaces
# e.g. [0x01,0x41,0x81,0xa1] -> "01 41 81 a1"
def to_hexified_s
to_binary_s.scan(/../).join(" ")
end
end
end
end
9 changes: 5 additions & 4 deletions lib/net/tti/client.rb
Expand Up @@ -56,8 +56,9 @@ def authenticate( username, password )
end

def get_pre_auth_request(username)
pre_auth_request = Authentication.create_pre_auth_request( @tti_conn.conn_params.architecture )
pre_auth_request = Authentication.create_pre_auth_request()
pre_auth_request.username = username
pre_auth_request.add_parameter("AUTH_TERMINAL", "unknown")
return pre_auth_request
end

Expand All @@ -81,11 +82,11 @@ def get_auth_request(username, password, pre_auth_response)
raise Exceptions::UnsupportedTNSVersion.new( @tti_conn.conn_params.tns_version )
end

auth_request = Authentication.create_auth_request( @tti_conn.conn_params.architecture )
auth_request = Authentication.create_auth_request()
auth_request.username = username
auth_request.enc_client_session_key = enc_client_session_key
auth_request.enc_password = enc_password

auth_request.enc_client_session_key = enc_client_session_key
auth_request.add_parameter("AUTH_TERMINAL", "unknown")
return auth_request
end

Expand Down
22 changes: 16 additions & 6 deletions lib/net/tti/connection.rb
Expand Up @@ -7,13 +7,23 @@ class ConnectionParameters
attr_accessor :platform
attr_accessor :architecture
attr_accessor :ttc_version
attr_accessor :ttc_server
attr_accessor :tns_version
attr_accessor :character_set
attr_accessor :server_flags
attr_accessor :server_compiletime_capabilities
attr_accessor :server_runtime_capabilities

def to_s
return "Platform: #{@platform||nil}" +
"; Architecture: #{@architecture||nil}" +
"; TTC? Version: #{@ttc_version||nil}" +
"; TNS Version: #{@tns_version||nil}"
"; TNS Version: #{@tns_version||nil}" +
"; TTC server version: #{@ttc_version||nil}" +
"; TTC server string: #{@ttc_server||nil}" +
"; Server character set: #{@character_set||nil}" +
"; Server flags: #{@server_flags||nil}" +
"; Server Compiletime Capabilities: #{@server_compiletime_capabilities.to_hexified_s}" +
"; Server Runtime Capabilities: #{@server_runtime_capabilities.to_hexified_s}"
end
end

Expand All @@ -39,7 +49,7 @@ def connect(opts={})
proto_nego_response.populate_connection_parameters( @conn_params )

Net::TTI.logger.debug("Sending data type negotiation request")
dt_nego_request = DataTypeNegotiationRequest.create_request( @conn_params.platform, @conn_params.architecture )
dt_nego_request = DataTypeNegotiationRequest.create_request( @conn_params )
dt_nego_response_raw = send_and_receive( dt_nego_request )

return nil
Expand All @@ -61,7 +71,7 @@ def send_tti_message( tti_message )
Net::TTI.logger.debug( "Connection#send_tti_message called with #{raw_message.length}-byte #{tti_message.class} message" )

# Split the message into multiple packets if necessary
max_data = Net::TNS::DataPacket.max_data_length
max_data = @tns_connection.tns_sdu - 12 # 12 = 10 (HEADER) + 2 (FLAGS)
raw_message.scan(/.{1,#{max_data}}/m).each do |raw_message_part|
tns_packet = Net::TNS::DataPacket.new()
tns_packet.data = raw_message_part
Expand All @@ -79,7 +89,7 @@ def receive_tti_message( waiting_for_error_message = false, max_message_length=1
while ( true )
receive_count += 1
if ( receive_count >= 3 )
raise Exceptions::TNSException.new( "Maximum receive attempts exceeded - too many Markers received." )
raise Exceptions::ProtocolException.new( "Maximum receive attempts exceeded - too many Markers received." )
end

Net::TTI.logger.debug("Attempting to receive packet (try ##{receive_count})")
Expand All @@ -90,7 +100,7 @@ def receive_tti_message( waiting_for_error_message = false, max_message_length=1
# carried into an additional packet. We wouldn't need to do this if
# we could fully parse every message (or at least know lengths to
# read). I'm looking at you, DataTypeNegotiationResponse.
if tns_packet.num_bytes > 2000
if @tns_connection.tns_protocol_version <= 313 && tns_packet.num_bytes > 1900
begin
max_message_length -= message_data.length
message_data += receive_tti_message(waiting_for_error_message, max_message_length)
Expand Down
1 change: 1 addition & 0 deletions lib/net/tti/data_types/chunked_string.rb
Expand Up @@ -47,6 +47,7 @@ def value_to_binary_string(value)
value_index += MAX_CHUNK_LENGTH
end
binary_string << [MULTI_CHUNK_TERMINATOR].pack("C")
return binary_string
else
return [value.length, value].pack("Ca*")
end
Expand Down
36 changes: 36 additions & 0 deletions lib/net/tti/data_types/flags.rb
@@ -0,0 +1,36 @@
require "bindata"

module Net
module TTI
module DataTypes
class Flags < BinData::Primitive
uint8 :value_length
choice :flag_value, :selection => :value_length do
virtual 0, :value => 0
uint8 1
uint16be 2
uint32be 4
end

def get
self.flag_value.to_i
end

def set(new_value)
if new_value > 0xffff
self.value_length = 4
self.flag_value = new_value
elsif new_value > 0xff
self.value_length = 2
self.flag_value = new_value
elsif new_value > 0
self.value_length = 1
self.flag_value = new_value
else
self.value_length = 0
end
end
end
end
end
end
28 changes: 14 additions & 14 deletions lib/net/tti/data_types/key_value_pair.rb
@@ -1,24 +1,24 @@
require "bindata"
require "net/tti/data_types/chunked_string"
require "net/tti/data_types/flags"

module Net
module TTI
module DataTypes
class KeyValuePair < BinData::Record
# In earlier dialects, the 4 bytes before the strings appeared to contain
# the total length of the string. In more recent dialects, this no longer
# seems to be the case. However, a 32-bit null here still appears to
# signal that there is no value.
uint32le :unknown1, :value => lambda {kvp_key.length}
chunked_string :kvp_key, :onlyif => lambda {unknown1 != 0}
uint32le :unknown2, :value => lambda {kvp_value.length}
chunked_string :kvp_value, :onlyif => lambda {unknown2 != 0}
uint32le :flags

def set(key, value)
self.kvp_key.data = key
self.kvp_value.data = value
end
# Follows (simplified) format used by JDBC driver; other clients send
# KVPs with a longer, more opaque structure (e.g. each chunked string
# was preceded by a 4-byte value that, in earlier dialects appeared to
# contain the total length of the string, but in later dialects did not
# seem related to string length at all).
uint8 :unknown1, :initial_value => 0x01 # size in bytes of kvp_key_length OR boolean
uint8 :kvp_key_length, :onlyif => lambda {unknown1 != 0x00}, :value => lambda {kvp_key.length}
chunked_string :kvp_key, :onlyif => lambda {unknown1 != 0x00 && kvp_key_length != 0x00}
uint8 :unknown2, :initial_value => 0x01 # size in bytes of kvp_value_length
uint8 :kvp_value_length, :onlyif => lambda {unknown2 != 0x00}, :value => lambda {kvp_value.length}
chunked_string :kvp_value, :onlyif => lambda {unknown2 != 0x00 && kvp_value_length != 0x00}
# flags are used when AUTH_SESSKEY and AUTH_ALTER_SESSION are sent to the server
flags :flags
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/net/tti/message.rb
Expand Up @@ -32,8 +32,8 @@ def self.handles_response_for_ttc_code(ttc_code)

def self.from_data_string( raw_message )
ttc_code = raw_message[0].unpack("C").first

unless message_class = @@ttc_classes[ ttc_code ]
unless message_class = @@ttc_classes[ttc_code]
raise Net::TNS::Exceptions::TNSException.new( "Unknown TTC code: #{ttc_code}" )
end

Expand Down

0 comments on commit 013cae6

Please sign in to comment.