Class: Net::TNS::Connection
- Inherits:
-
Object
- Object
- Net::TNS::Connection
- Defined in:
- lib/net/tns/connection.rb
Instance Attribute Summary collapse
-
#tns_protocol_version ⇒ Object
readonly
Returns the value of attribute tns_protocol_version.
-
#tns_sdu ⇒ Object
readonly
Returns the value of attribute tns_sdu.
Instance Method Summary collapse
-
#close_socket ⇒ Object
This is a low-level function to directly close the socket for this connection.
- #connect(opts = {}) ⇒ Object
- #disconnect ⇒ Object
-
#initialize(opts = {}) ⇒ Connection
constructor
A new instance of Connection.
-
#open_socket ⇒ Object
This is a low-level function to directly open a socket for this connection.
-
#receive_tns_packet(waiting_for_error_message = false) ⇒ Net::TNS::Packet
Attempts to receive a TNS message.
- #send_and_receive(packet) ⇒ Object
- #send_tns_packet(packet) ⇒ Object
Constructor Details
#initialize(opts = {}) ⇒ Connection
Returns a new instance of Connection.
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/net/tns/connection.rb', line 10 def initialize(opts={}) @socket = nil @host = opts.delete(:host) @port = opts.delete(:port) || 1521 @new_socket_proc = opts.delete(:new_socket_proc) raise ArgumentError.new("Unrecognized options: #{opts.keys}") unless opts.empty? if @host.nil? == @new_socket_proc.nil? raise ArgumentError.new("Invalid socket options. Need :host and :port, OR :new_socket_proc") end end |
Instance Attribute Details
#tns_protocol_version ⇒ Object (readonly)
Returns the value of attribute tns_protocol_version.
7 8 9 |
# File 'lib/net/tns/connection.rb', line 7 def tns_protocol_version @tns_protocol_version end |
#tns_sdu ⇒ Object (readonly)
Returns the value of attribute tns_sdu.
8 9 10 |
# File 'lib/net/tns/connection.rb', line 8 def tns_sdu @tns_sdu end |
Instance Method Details
#close_socket ⇒ Object
This is a low-level function to directly close the socket for this connection. Most callers should use #disconnect instead, which will disconnect the TNS connection before closing the socket.
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/net/tns/connection.rb', line 48 def close_socket Net::TNS.logger.debug("Connection#close_socket called") begin unless @socket.nil? or @socket.closed? Net::TNS.logger.info("Closing socket") @socket.close end ensure @socket = nil end end |
#connect(opts = {}) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/net/tns/connection.rb', line 60 def connect(opts={}) sid = opts.delete(:sid) if opts.has_key?(:sid) service_name = opts.delete(:service_name) if opts.has_key?(:service_name) raise ArgumentError.new("Unrecognized opts: #{opts.keys}") unless opts.empty? raise ArgumentError.new("Must specify :sid or :service_name") unless sid.nil? != service_name.nil? open_socket() if @socket.nil? dst_host = @socket.peeraddr[3] dst_port = @socket.peeraddr[1] if sid Net::TNS.logger.debug("Connecting to target by SID (""#{sid}"")") connect_packet = ConnectPacket.make_connection_by_sid( dst_host, dst_port, sid ) elsif service_name Net::TNS.logger.debug("Connecting to target by service name (""#{service_name}"")") connect_packet = ConnectPacket.make_connection_by_service_name( dst_host, dst_port, service_name ) end response = send_and_receive(connect_packet) unless response.is_a?(AcceptPacket) || response.is_a?(RedirectPacket) raise Exceptions::ProtocolException.new("Unexpected response to Connect packet: #{response.class}") end if response.is_a?(RedirectPacket) # CLR extproc on 12c will end up here return end @tns_protocol_version = response.version.to_i @tns_sdu = response.sdu_size.to_i negotiate_ano() end |
#disconnect ⇒ Object
91 92 93 94 95 96 97 98 |
# File 'lib/net/tns/connection.rb', line 91 def disconnect begin packet = DataPacket.make_disconnect_request send_tns_packet( packet ) ensure close_socket() end end |
#open_socket ⇒ Object
This is a low-level function to directly open a socket for this connection. Most callers should use #connect instead, which will open a socket and negotiate a TNS connection.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/net/tns/connection.rb', line 27 def open_socket Net::TNS.logger.debug("Connection#open_socket called") close_socket() if @host require "socket" Net::TNS.logger.info("Creating new TCPSocket for #{@host}:#{@port}") @socket = TCPSocket.new(@host, @port) elsif @new_socket_proc Net::TNS.logger.info("Calling new-socket proc for new socket") @socket = @new_socket_proc.call() else raise ArgumentError.new("Invalid socket options") end return end |
#receive_tns_packet(waiting_for_error_message = false) ⇒ Net::TNS::Packet
Attempts to receive a TNS message.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/net/tns/connection.rb', line 158 def receive_tns_packet( = false ) # This is structured as a loop in order to handle messages (e.g. Resends) # that need to be handled without returning to the caller. To keep a malicious # server from making us loop continuously, we set an arbitrary limit of # 10 loops without a "real" message before we throw an exception. receive_count = 0 while ( true ) raise Exceptions::ConnectionClosed if @socket.closed? receive_count += 1 if ( receive_count >= 3 ) raise Exceptions::TNSException.new( "Maximum receive attempts exceeded - too many Resends received." ) end # Try to receive a TNS packet Net::TNS.logger.debug("Attempting to receive packet (try ##{receive_count})") packet = Net::TNS::Packet.from_socket(@socket) case packet when Net::TNS::RefusePacket Net::TNS.logger.warn("Received RefusePacket") raise Exceptions::RefuseMessageReceived.new( packet.data ) # # We received a redirect request (typical of Oracle 9 and possibly previous versions) # when Net::TNS::RedirectPacket # raise Exceptions::RedirectMessageReceived.new( packet.data ) # We received a request to resend the last packet when Net::TNS::ResendPacket Net::TNS.logger.debug("Received ResendPacket") # Re-send the last packet and then loop again resend_last_tns_packet() # We received a normal response else Net::TNS.logger.debug("Received #{packet.class} (#{packet.num_bytes} bytes)") return packet end end end |
#send_and_receive(packet) ⇒ Object
123 124 125 126 |
# File 'lib/net/tns/connection.rb', line 123 def send_and_receive( packet ) send_tns_packet( packet ) receive_tns_packet() end |
#send_tns_packet(packet) ⇒ Object
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/net/tns/connection.rb', line 129 def send_tns_packet( packet ) if @socket.nil? || @socket.closed? Net::TNS.logger.warn( "Can't send packet to a closed or nil socket!" ) return end # Store this in case we get a Resend @tns_last_sent_packet = packet Net::TNS.logger.debug( "Sending packet #{packet.class} (#{packet.num_bytes} bytes)" ) @socket.write( packet.to_binary_s ) end |