# File lib/Dnsruby/resource/TSIG.rb, line 279
      def verify_envelope(response, response_bytes)
        #RFC2845 Section 4.4

        #-----

        #A DNS TCP session can include multiple DNS envelopes.  This is, for

        #example, commonly used by zone transfer.  Using TSIG on such a

        #connection can protect the connection from hijacking and provide data

        #integrity.  The TSIG MUST be included on the first and last DNS

        #envelopes.  It can be optionally placed on any intermediary

        #envelopes.  It is expensive to include it on every envelopes, but it

        #MUST be placed on at least every 100'th envelope.  The first envelope

        #is processed as a standard answer, and subsequent messages have the

        #following digest components:

        #

        #*   Prior Digest (running)

        #*   DNS Messages (any unsigned messages since the last TSIG)

        #*   TSIG Timers (current message)

        #

        #This allows the client to rapidly detect when the session has been

        #altered; at which point it can close the connection and retry.  If a

        #client TSIG verification fails, the client MUST close the connection.

        #If the client does not receive TSIG records frequently enough (as

        #specified above) it SHOULD assume the connection has been hijacked

        #and it SHOULD close the connection.  The client SHOULD treat this the

        #same way as they would any other interrupted transfer (although the

        #exact behavior is not specified).

        #-----

        #

        # Each time a new envelope comes in, this method is called on the QUERY TSIG RR.

        # It will set the response tsigstate to :Verified :Intermediate or :Failed

        # as appropriate.

        
        # Keep digest going of messages as they come in (and mark them intermediate)

        # When TSIG comes in, work out what key should be and check. If OK, mark 

        # verified. Can reset digest then.

        if (!@buf)
          @num_envelopes = 0
          @last_signed = 0
        end
        @num_envelopes += 1
        if (!response.tsig)
          if ((@num_envelopes > 1) && (@num_envelopes - @last_signed < 100))
            Dnsruby.log.debug("Receiving intermediate envelope in TSIG TCP session")
            response.tsigstate = :Intermediate
            response.tsigerror = RCode.NOERROR
            @buf = @buf + response_bytes
            return
          else
            response.tsigstate = :Failed
            Dnsruby.log.error("Expecting signed packet")
            return false
          end
        end
        @last_signed = @num_envelopes
        
        # We have a TSIG - process it!

        tsig = response.tsig
        if (@num_envelopes == 1)
          Dnsruby.log.debug("First response in TSIG TCP session - verifying normally")
          # Process it as a standard answer

          ok = verify(@query, response, response_bytes)
          if (ok)
            mac_bytes = MessageEncoder.new {|m|
              m.put_pack('n', tsig.mac_size)
              m.put_bytes(tsig.mac)
            }.to_s
            @buf = mac_bytes
          end
          return ok
        end
        Dnsruby.log.debug("Processing TSIG on TSIG TCP session")

        if (!verify_common(response))
          return false
        end
        
        # Now add the current message data - remember to frig the arcount

        response_bytes = Header.decrement_arcount_encoded(response_bytes)
        @buf += response_bytes[0, response.tsigstart]
        
        # Let's add the timers

        timers_data = MessageEncoder.new { |msg|
          time_high = (tsig.time_signed >> 32)
          time_low = (tsig.time_signed & 0xFFFFFFFF)
          msg.put_pack('nN', time_high, time_low)
          msg.put_pack('n', tsig.fudge)
        }.to_s
        @buf += timers_data
        
        mac = calculate_mac(tsig.algorithm, @buf)

        if (mac != tsig.mac)
          Dnsruby.log.error("TSIG Verify error on TSIG TCP session")
          response.tsigstate = :Failed
          return false
        end
        mac_bytes = MessageEncoder.new {|m|
          m.put_pack('n', mac.length)
          m.put_bytes(mac)
        }.to_s
        @buf=mac_bytes

        response.tsigstate = :Verified
        response.tsigerror = RCode.NOERROR
        return true
      end