rubydns 0.6.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/.yardopts +1 -0
- data/README.md +98 -92
- data/lib/rubydns.rb +5 -47
- data/lib/rubydns/{extensions/string-1.9.3.rb → binary_string.rb} +2 -0
- data/lib/rubydns/extensions/logger.rb +1 -1
- data/lib/rubydns/extensions/resolv.rb +1 -5
- data/lib/rubydns/extensions/string.rb +1 -0
- data/lib/rubydns/handler.rb +7 -2
- data/lib/rubydns/message.rb +17 -4
- data/lib/rubydns/resolver.rb +3 -0
- data/lib/rubydns/server.rb +182 -93
- data/lib/rubydns/transaction.rb +110 -149
- data/lib/rubydns/version.rb +1 -1
- data/rubydns.gemspec +1 -1
- data/test/examples/dropping-dns.rb +2 -2
- data/test/examples/fortune-dns.rb +2 -2
- data/test/examples/soa-dns.rb +1 -1
- data/test/examples/wikipedia-dns.rb +2 -2
- data/test/test_daemon.rb +3 -3
- data/test/test_message.rb +41 -0
- data/test/test_passthrough.rb +5 -1
- data/test/test_rules.rb +3 -3
- data/test/test_slow_server.rb +8 -6
- data/test/test_truncation.rb +3 -3
- metadata +10 -9
- data/lib/rubydns/extensions/hexdump.rb +0 -38
- data/lib/rubydns/extensions/string-1.8.rb +0 -35
- data/lib/rubydns/extensions/string-1.9.2.rb +0 -29
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 190faf76114f4bfe4bcbff8896f6d54ff4d75667
         | 
| 4 | 
            +
              data.tar.gz: 76d443584858fdfb9d8223215c47b3935d22f53c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2d850649e8bb3f66638a30519898ece93a710c08925e83a8ca6ef15fce6474f80795133d71dfac0f67756f8945596771ddc6c0e98d6fd554a40e081b6ba41e61
         | 
| 7 | 
            +
              data.tar.gz: e797f439ff7aaa0de6b2cbe15621ebf514a24a39441b200ccc09a15cc8baabc6fbfdf5ab95e69c40f31ef2925addce7f436bf5ea8598861bbbb7e072e922f2a5
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/.yardopts
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            --markup=markdown
         | 
    
        data/README.md
    CHANGED
    
    | @@ -29,122 +29,128 @@ Or install it yourself as: | |
| 29 29 |  | 
| 30 30 | 
             
            This is copied from `test/examples/test-dns-2.rb`. It has been simplified slightly.
         | 
| 31 31 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
            	 | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
            run
         | 
| 60 | 
            -
            ```
         | 
| 32 | 
            +
            	#!/usr/bin/env ruby
         | 
| 33 | 
            +
            	require 'rubydns'
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            	INTERFACES = [
         | 
| 36 | 
            +
            		[:udp, "0.0.0.0", 53],
         | 
| 37 | 
            +
            		[:tcp, "0.0.0.0", 53]
         | 
| 38 | 
            +
            	]
         | 
| 39 | 
            +
            	Name = Resolv::DNS::Name
         | 
| 40 | 
            +
            	IN = Resolv::DNS::Resource::IN
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            	# Use upstream DNS for name resolution.
         | 
| 43 | 
            +
            	UPSTREAM = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            	def self.run
         | 
| 46 | 
            +
            	    # Start the RubyDNS server
         | 
| 47 | 
            +
            	    RubyDNS::run_server(:listen => INTERFACES) do
         | 
| 48 | 
            +
            	        match(/test.mydomain.org/, IN::A) do |transaction|
         | 
| 49 | 
            +
            	            transaction.respond!("10.0.0.80")
         | 
| 50 | 
            +
            	        end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            	        # Default DNS handler
         | 
| 53 | 
            +
            	        otherwise do |transaction|
         | 
| 54 | 
            +
            	            transaction.passthrough!(UPSTREAM)
         | 
| 55 | 
            +
            	        end
         | 
| 56 | 
            +
            	    end
         | 
| 57 | 
            +
            	end
         | 
| 58 | 
            +
            	run
         | 
| 61 59 |  | 
| 62 60 | 
             
            Start the server using `rvmsudo ./test.rb`. You can then test it using dig:
         | 
| 63 61 |  | 
| 64 | 
            -
             | 
| 65 | 
            -
            $ dig @localhost  | 
| 66 | 
            -
            $ dig @localhost  | 
| 67 | 
            -
            $ dig @localhost google.com
         | 
| 68 | 
            -
            ```
         | 
| 62 | 
            +
            	$ dig @localhost test1.mydomain.org
         | 
| 63 | 
            +
            	$ dig @localhost dev.mydomain.org
         | 
| 64 | 
            +
            	$ dig @localhost google.com
         | 
| 69 65 |  | 
| 70 66 | 
             
            ## Compatibility
         | 
| 71 67 |  | 
| 72 | 
            -
            ### Migrating from RubyDNS 0. | 
| 68 | 
            +
            ### Migrating from RubyDNS 0.6.x to 0.7.x
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            The asynchronous deferred processing became the default and only method for processing requests in `0.7.0`. This simplifies the API but there were a few changes, notably the removal of `defer!` and the addition of `defer`. The reason for this was due to issues relating to deferred processing and the flow of control, which were confusing and introduced bugs in specific situations. Now, you can assume flow control through the entire block even with non-blocking functions.
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            	RubyDNS::run_server(:listen => SERVER_PORTS) do
         | 
| 73 | 
            +
            		match(/\.*.com/, IN::A) do |transaction|
         | 
| 74 | 
            +
            			# Won't block and won't continue until handle.resume is called.
         | 
| 75 | 
            +
            			defer do |fiber|
         | 
| 76 | 
            +
            				# No domain exists, after 5 seconds:
         | 
| 77 | 
            +
            				EventMachine::Timer.new(5) do
         | 
| 78 | 
            +
            					transaction.fail!(:NXDomain)
         | 
| 79 | 
            +
            					
         | 
| 80 | 
            +
            					fiber.resume
         | 
| 81 | 
            +
            				end
         | 
| 82 | 
            +
            			end
         | 
| 83 | 
            +
            		end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            		otherwise do
         | 
| 86 | 
            +
            			transaction.fail!(:NXDomain)
         | 
| 87 | 
            +
            		end
         | 
| 88 | 
            +
            	end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            You can see a complete example in `test/test_slow_server.rb`.
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            #### Server structure changes
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            When integrating RubyDNS into another project, the rule based DSL is often a hurdle rather than a feature. Thus, the rule-based DSL component of `RubyDNS::Server` class has been separated into a derived `RubyDNS::RuleBasedServer` class. `RubyDNS::Server` can be derived and the `RubyDNS::Server#process` method can be overridden to provide a single entry point for DNS processing.
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            In addition, `RubyDNS::Server#run` can now start the server, provided you are within an `EventMachine#run` context. The existing entry point, `RubyDNS::run_server` provides the same rule-based DSL as previous versions.
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            #### Method name changes
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            Some method names have changed to improve consistency.
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            - `failure!` became `fail!`
         | 
| 103 | 
            +
            - `append` became `add`
         | 
| 104 | 
            +
            - `append_query!` became `append!`
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            ### Migrating from RubyDNS 0.5.x to 0.6.x
         | 
| 73 107 |  | 
| 74 108 | 
             
            The order of arguments to pattern based rules has changed. For regular expression based rules, the arguments are now ordered `|transaction, match_data|`. The main reason for this change was that in many cases match_data is not important and can thus be ignored, e.g. `|transaction|`.
         | 
| 75 109 |  | 
| 76 110 | 
             
            Going forward, Ruby 1.8.x is no longer supported.
         | 
| 77 111 |  | 
| 78 | 
            -
            ### Migrating from RubyDNS 0. | 
| 79 | 
            -
             | 
| 80 | 
            -
            Due to changes in `resolv.rb`, superficial parts of RubyDNS have changed. Rather than using `:A` to specify A-records, one must now use the class name.
         | 
| 81 | 
            -
            ```ruby
         | 
| 82 | 
            -
            match(..., :A)
         | 
| 83 | 
            -
            ```
         | 
| 84 | 
            -
            becomes
         | 
| 85 | 
            -
            ```ruby
         | 
| 86 | 
            -
            IN = Resolv::DNS::Resource::IN
         | 
| 87 | 
            -
            match(..., IN::A)
         | 
| 88 | 
            -
            ```
         | 
| 89 | 
            -
            ### Migrating from RubyDNS 0.4.x to 0.5.x ###
         | 
| 112 | 
            +
            ### Migrating from RubyDNS 0.4.x to 0.5.x
         | 
| 90 113 |  | 
| 91 114 | 
             
            The system standard resolver was synchronous, and this could stall the server when making upstream requests to other DNS servers. A new resolver `RubyDNS::Resolver` now provides an asynchronous interface and the `Transaction::passthrough` makes exclusive use of this to provide high performance asynchonous resolution.
         | 
| 92 115 |  | 
| 93 116 | 
             
            Here is a basic example of how to use the new resolver in full. It is important to provide both `:udp` and `:tcp` connection specifications, so that large requests will be handled correctly:
         | 
| 94 | 
            -
            ```ruby
         | 
| 95 | 
            -
            resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
         | 
| 96 | 
            -
             | 
| 97 | 
            -
            EventMachine::run do
         | 
| 98 | 
            -
              resolver.query('google.com', IN::A) do |response|
         | 
| 99 | 
            -
            		case response
         | 
| 100 | 
            -
            		when RubyDNS::Message
         | 
| 101 | 
            -
            			puts "Got response: #{response.answers.first}"
         | 
| 102 | 
            -
            		else
         | 
| 103 | 
            -
            			# Response is of class RubyDNS::ResolutionFailure
         | 
| 104 | 
            -
            			puts "Failed: #{response.message}"
         | 
| 105 | 
            -
            		end
         | 
| 106 117 |  | 
| 107 | 
            -
             | 
| 118 | 
            +
            	resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            	EventMachine::run do
         | 
| 121 | 
            +
            	  resolver.query('google.com', IN::A) do |response|
         | 
| 122 | 
            +
            			case response
         | 
| 123 | 
            +
            			when RubyDNS::Message
         | 
| 124 | 
            +
            				puts "Got response: #{response.answers.first}"
         | 
| 125 | 
            +
            			else
         | 
| 126 | 
            +
            				# Response is of class RubyDNS::ResolutionFailure
         | 
| 127 | 
            +
            				puts "Failed: #{response.message}"
         | 
| 128 | 
            +
            			end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            			EventMachine::stop
         | 
| 131 | 
            +
            		end
         | 
| 108 132 | 
             
            	end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
            ```
         | 
| 133 | 
            +
             | 
| 111 134 | 
             
            Existing code that uses `Resolv::DNS` as a resolver will need to be updated:
         | 
| 112 | 
            -
             | 
| 113 | 
            -
            # 1/ Add this at the top of your file; Host specific system information:
         | 
| 114 | 
            -
            require 'rubydns/system'
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            	# 1/ Add this at the top of your file; Host specific system information:
         | 
| 137 | 
            +
            	require 'rubydns/system'
         | 
| 115 138 |  | 
| 116 | 
            -
            # 2/ Change from R = Resolv::DNS.new to:
         | 
| 117 | 
            -
            R = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
         | 
| 118 | 
            -
            ```
         | 
| 119 | 
            -
            Everything else in the server can remain the same. You can see a complete example in `test/test_resolver.rb`.
         | 
| 139 | 
            +
            	# 2/ Change from R = Resolv::DNS.new to:
         | 
| 140 | 
            +
            	R = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
         | 
| 120 141 |  | 
| 121 | 
            -
             | 
| 142 | 
            +
            Everything else in the server can remain the same. You can see a complete example in `test/test_resolver.rb`.
         | 
| 122 143 |  | 
| 123 | 
            -
             | 
| 144 | 
            +
            ### Migrating from RubyDNS 0.3.x to 0.4.x
         | 
| 124 145 |  | 
| 125 | 
            -
             | 
| 126 | 
            -
            transaction.defer!
         | 
| 127 | 
            -
            ```
         | 
| 146 | 
            +
            Due to changes in `resolv.rb`, superficial parts of RubyDNS have changed. Rather than using `:A` to specify A-records, one must now use the class name.
         | 
| 128 147 |  | 
| 129 | 
            -
             | 
| 130 | 
            -
            ```ruby
         | 
| 131 | 
            -
            RubyDNS::run_server(:listen => SERVER_PORTS) do
         | 
| 132 | 
            -
            	match(/\.*.com/, IN::A) do |transaction|
         | 
| 133 | 
            -
            		transaction.defer!
         | 
| 134 | 
            -
            		
         | 
| 135 | 
            -
            		# No domain exists, after 5 seconds:
         | 
| 136 | 
            -
            		EventMachine::Timer.new(5) do
         | 
| 137 | 
            -
            			transaction.failure!(:NXDomain)
         | 
| 138 | 
            -
            		end
         | 
| 139 | 
            -
            	end
         | 
| 148 | 
            +
            	match(..., :A)
         | 
| 140 149 |  | 
| 141 | 
            -
             | 
| 142 | 
            -
            		transaction.failure!(:NXDomain)
         | 
| 143 | 
            -
            	end
         | 
| 144 | 
            -
            end
         | 
| 145 | 
            -
            ```
         | 
| 150 | 
            +
            becomes
         | 
| 146 151 |  | 
| 147 | 
            -
             | 
| 152 | 
            +
            	IN = Resolv::DNS::Resource::IN
         | 
| 153 | 
            +
            	match(..., IN::A)
         | 
| 148 154 |  | 
| 149 155 | 
             
            ## Contributing
         | 
| 150 156 |  | 
| @@ -163,7 +169,7 @@ You can see a complete example in `test/test_slow_server.rb`. | |
| 163 169 |  | 
| 164 170 | 
             
            Released under the MIT license.
         | 
| 165 171 |  | 
| 166 | 
            -
            Copyright, 2009, 2012, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
         | 
| 172 | 
            +
            Copyright, 2009, 2012, 2014, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
         | 
| 167 173 |  | 
| 168 174 | 
             
            Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| 169 175 | 
             
            of this software and associated documentation files (the "Software"), to deal
         | 
    
        data/lib/rubydns.rb
    CHANGED
    
    | @@ -20,14 +20,6 @@ | |
| 20 20 |  | 
| 21 21 | 
             
            require 'rubydns/version'
         | 
| 22 22 |  | 
| 23 | 
            -
            if RUBY_VERSION < "1.9"
         | 
| 24 | 
            -
            	require 'rubydns/extensions/string-1.8'
         | 
| 25 | 
            -
            elsif RUBY_VERSION < "1.9.3"
         | 
| 26 | 
            -
            	require 'rubydns/extensions/string-1.9.2'
         | 
| 27 | 
            -
            else
         | 
| 28 | 
            -
            	require 'rubydns/extensions/string-1.9.3'
         | 
| 29 | 
            -
            end
         | 
| 30 | 
            -
             | 
| 31 23 | 
             
            require 'rubydns/message'
         | 
| 32 24 | 
             
            require 'rubydns/server'
         | 
| 33 25 | 
             
            require 'rubydns/resolver'
         | 
| @@ -42,50 +34,16 @@ require 'rubydns/handler' | |
| 42 34 |  | 
| 43 35 | 
             
            module RubyDNS
         | 
| 44 36 |  | 
| 45 | 
            -
            	# Run a server with the given rules. | 
| 46 | 
            -
            	#
         | 
| 47 | 
            -
            	# <tt>:interfaces</tt>:: A set of sockets or addresses as defined below.
         | 
| 48 | 
            -
            	#
         | 
| 49 | 
            -
            	# One important feature of DNS is the port it runs on. The <tt>options[:listen]</tt>
         | 
| 50 | 
            -
            	# allows you to specify a set of network interfaces and ports to run the server on. This
         | 
| 51 | 
            -
            	# must be a list of <tt>[protocol, interface address, port]</tt>.
         | 
| 52 | 
            -
            	# 
         | 
| 53 | 
            -
            	#   INTERFACES = [[:udp, "0.0.0.0", 5300]]
         | 
| 54 | 
            -
            	#   RubyDNS::run_server(:listen => INTERFACES) do
         | 
| 55 | 
            -
            	#     ...
         | 
| 56 | 
            -
            	#   end
         | 
| 57 | 
            -
            	#
         | 
| 58 | 
            -
            	# You can specify already connected sockets if need be:
         | 
| 59 | 
            -
            	#
         | 
| 60 | 
            -
            	#   socket = UDPSocket.new; socket.bind("0.0.0.0", 53)
         | 
| 61 | 
            -
            	#   Process::Sys.setuid(server_uid)
         | 
| 62 | 
            -
            	#   INTERFACES = [socket]
         | 
| 63 | 
            -
            	#
         | 
| 64 | 
            -
            	# The default interface is <tt>[[:udp, "0.0.0.0", 53]]</tt>. The server typically needs
         | 
| 65 | 
            -
            	# to run as root for this to work, since port 53 is privileged.
         | 
| 66 | 
            -
            	#
         | 
| 37 | 
            +
            	# Run a server with the given rules.
         | 
| 67 38 | 
             
            	def self.run_server (options = {}, &block)
         | 
| 68 | 
            -
            		server = RubyDNS:: | 
| 69 | 
            -
            		server.logger.info "Starting RubyDNS server (v#{RubyDNS::VERSION})..."
         | 
| 70 | 
            -
            		
         | 
| 71 | 
            -
            		options[:listen] ||= [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
         | 
| 39 | 
            +
            		server = RubyDNS::RuleBasedServer.new(&block)
         | 
| 72 40 |  | 
| 73 41 | 
             
            		EventMachine.run do
         | 
| 74 | 
            -
            			server. | 
| 75 | 
            -
            			
         | 
| 76 | 
            -
            			# Setup server sockets
         | 
| 77 | 
            -
            			options[:listen].each do |spec|
         | 
| 78 | 
            -
            				server.logger.info "Listening on #{spec.join(':')}"
         | 
| 79 | 
            -
            				if spec[0] == :udp
         | 
| 80 | 
            -
            					EventMachine.open_datagram_socket(spec[1], spec[2], UDPHandler, server)
         | 
| 81 | 
            -
            				elsif spec[0] == :tcp
         | 
| 82 | 
            -
            					EventMachine.start_server(spec[1], spec[2], TCPHandler, server)
         | 
| 83 | 
            -
            				end
         | 
| 84 | 
            -
            			end
         | 
| 85 | 
            -
            			
         | 
| 86 | 
            -
            			server.fire(:start)
         | 
| 42 | 
            +
            			server.run(options)
         | 
| 87 43 | 
             
            		end
         | 
| 88 44 |  | 
| 89 45 | 
             
            		server.fire(:stop)
         | 
| 90 46 | 
             
            	end
         | 
| 47 | 
            +
            	
         | 
| 48 | 
            +
            	
         | 
| 91 49 | 
             
            end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
             | 
| 1 2 | 
             
            # Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
         | 
| 2 3 | 
             
            # 
         | 
| 3 4 | 
             
            # Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| @@ -21,6 +22,7 @@ | |
| 21 22 | 
             
            require 'stringio'
         | 
| 22 23 |  | 
| 23 24 | 
             
            module RubyDNS
         | 
| 25 | 
            +
            	# A helper class for processing incoming network data.
         | 
| 24 26 | 
             
            	class BinaryStringIO < StringIO
         | 
| 25 27 | 
             
            		def initialize
         | 
| 26 28 | 
             
            			super
         | 
| @@ -23,11 +23,7 @@ require 'resolv' | |
| 23 23 | 
             
            class Resolv
         | 
| 24 24 | 
             
            	class DNS
         | 
| 25 25 | 
             
            		class Message
         | 
| 26 | 
            -
            			# Merge the given message with this message. A number of heuristics are
         | 
| 27 | 
            -
            			# applied in order to ensure that the result makes sense. For example,
         | 
| 28 | 
            -
            			# If the current message is not recursive but is being merged with a
         | 
| 29 | 
            -
            			# message that was recursive, this bit is maintained. If either message
         | 
| 30 | 
            -
            			# is authoritive, then the result is also authoritive.
         | 
| 26 | 
            +
            			# Merge the given message with this message. A number of heuristics are applied in order to ensure that the result makes sense. For example, If the current message is not recursive but is being merged with a message that was recursive, this bit is maintained. If either message is authoritive, then the result is also authoritive.
         | 
| 31 27 | 
             
            			#
         | 
| 32 28 | 
             
            			# Modifies the current message in place.
         | 
| 33 29 | 
             
            			def merge! (other)
         | 
    
        data/lib/rubydns/handler.rb
    CHANGED
    
    | @@ -19,18 +19,21 @@ | |
| 19 19 | 
             
            # THE SOFTWARE.
         | 
| 20 20 |  | 
| 21 21 | 
             
            require 'rubydns/message'
         | 
| 22 | 
            +
            require 'rubydns/binary_string'
         | 
| 22 23 |  | 
| 23 24 | 
             
            module RubyDNS
         | 
| 24 | 
            -
            	
         | 
| 25 | 
            +
            	# @returns the [port, ip address] of the given connection.
         | 
| 25 26 | 
             
            	def self.get_peer_details(connection)
         | 
| 26 27 | 
             
            		Socket.unpack_sockaddr_in(connection.get_peername)
         | 
| 27 28 | 
             
            	end
         | 
| 28 29 |  | 
| 30 | 
            +
            	# Handling incoming UDP requests, which are single data packets, and pass them on to the given server.
         | 
| 29 31 | 
             
            	module UDPHandler
         | 
| 30 32 | 
             
            		def initialize(server)
         | 
| 31 33 | 
             
            			@server = server
         | 
| 32 34 | 
             
            		end
         | 
| 33 | 
            -
             | 
| 35 | 
            +
            		
         | 
| 36 | 
            +
            		# Process a packet of data with the given server. If an exception is thrown, a failure message will be sent back.
         | 
| 34 37 | 
             
            		def self.process(server, data, options = {}, &block)
         | 
| 35 38 | 
             
            			server.logger.debug "Receiving incoming query (#{data.bytesize} bytes)..."
         | 
| 36 39 | 
             
            			query = nil
         | 
| @@ -98,6 +101,7 @@ module RubyDNS | |
| 98 101 | 
             
            			@processed = 0
         | 
| 99 102 | 
             
            		end
         | 
| 100 103 |  | 
| 104 | 
            +
            		# Receive the data via a TCP connection, process messages when we receive the indicated amount of data.
         | 
| 101 105 | 
             
            		def receive_data(data)
         | 
| 102 106 | 
             
            			# We buffer data until we've received the entire packet:
         | 
| 103 107 | 
             
            			@buffer.write(data)
         | 
| @@ -132,6 +136,7 @@ module RubyDNS | |
| 132 136 | 
             
            			end
         | 
| 133 137 | 
             
            		end
         | 
| 134 138 |  | 
| 139 | 
            +
            		# Check that all data received was processed.
         | 
| 135 140 | 
             
            		def unbind
         | 
| 136 141 | 
             
            			if @processed != @buffer.size
         | 
| 137 142 | 
             
            				raise LengthError.new("Unprocessed data remaining (#{@buffer.size - @processed} bytes unprocessed)")
         | 
    
        data/lib/rubydns/message.rb
    CHANGED
    
    | @@ -46,18 +46,31 @@ module RubyDNS | |
| 46 46 | 
             
            			RubyDNS.log_exception(bad_messages_log, error)
         | 
| 47 47 | 
             
            		end
         | 
| 48 48 | 
             
            	end
         | 
| 49 | 
            -
             | 
| 49 | 
            +
            	
         | 
| 50 | 
            +
            	# Decodes binary data into a {Message}.
         | 
| 50 51 | 
             
            	def self.decode_message(data)
         | 
| 52 | 
            +
            		# Otherwise the decode process might fail with non-binary data.
         | 
| 51 53 | 
             
            		if data.respond_to? :force_encoding
         | 
| 52 54 | 
             
            			data.force_encoding("BINARY")
         | 
| 53 55 | 
             
            		end
         | 
| 54 56 |  | 
| 55 | 
            -
            		 | 
| 57 | 
            +
            		begin
         | 
| 58 | 
            +
            			return Message.decode(data)
         | 
| 59 | 
            +
            		rescue DecodeError
         | 
| 60 | 
            +
            			raise
         | 
| 61 | 
            +
            		rescue StandardError => error
         | 
| 62 | 
            +
            			new_error = DecodeError.new(error.message)
         | 
| 63 | 
            +
            			new_error.set_backtrace(error.backtrace)
         | 
| 64 | 
            +
            			
         | 
| 65 | 
            +
            			raise new_error
         | 
| 66 | 
            +
            		end
         | 
| 67 | 
            +
            		
         | 
| 56 68 | 
             
            	rescue => error
         | 
| 69 | 
            +
            		# Log the bad messsage if required:
         | 
| 57 70 | 
             
            		if @dump_bad_message
         | 
| 58 | 
            -
            			@dump_bad_message.call( | 
| 71 | 
            +
            			@dump_bad_message.call(error, data)
         | 
| 59 72 | 
             
            		end
         | 
| 60 73 |  | 
| 61 74 | 
             
            		raise
         | 
| 62 75 | 
             
            	end
         | 
| 63 | 
            -
            end
         | 
| 76 | 
            +
            end
         |