# File lib/dnsruby/resource/TSIG.rb, line 282
      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