AsyncDNS-cr  Check-in [86ae1b8057]

Overview
Comment:Read everything in handle_packet via IO
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA3-256: 86ae1b80574b530ce64102764553c75e4dc448ed4203087022c922e276d8c7c2
User & Date: js on 2021-03-06 22:36:41
Other Links: manifest | tags
Context
2021-03-06
22:36
Read everything in handle_packet via IO Leaf check-in: 86ae1b8057 user: js tags: trunk
22:28
Fix leftover IO and missing rescue check-in: e71ccf3e48 user: js tags: trunk
Changes

Modified src/resolver.cr from [b25ecb3e05] to [a2ff58132d].

139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
          end
          handle_packet(buf[0, len], addr)
        end
      end
    end

    def handle_packet(packet : Bytes, sender : Socket::IPAddress) : Nil

      begin
        id = packet[0].to_u16 << 8 | packet[1]

        begin
          context = @queries[id]
        rescue KeyError
          return
        end

        return if sender != context.used_ns

        @queries.delete(id)


        if packet[2] & 0x80 == 0 ||                       # QR
           packet[2] & 0x78 != context.raw_data[2] & 0x78 # Opcode
          context.block.call(Error::INVALID_REPLY)
          return
        end

        if packet[2] & 0x02 != 0 # TC
          # TODO: Switch to TCP
          context.block.call(Error::TRUNCATED)
          return
        end

        case packet[3] & 0x0F # RCODE
        when 0
          error = nil
          try_next_ns = false
        when 1
          error = Error::SERVER_INVALID_FORMAT
          try_next_ns = false
        when 2







>

|











>
|
|




|





|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
          end
          handle_packet(buf[0, len], addr)
        end
      end
    end

    def handle_packet(packet : Bytes, sender : Socket::IPAddress) : Nil
      io = IO::Memory.new(packet, writeable: false)
      begin
        id = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)

        begin
          context = @queries[id]
        rescue KeyError
          return
        end

        return if sender != context.used_ns

        @queries.delete(id)

        byte = io.read_bytes(UInt8)
        if byte & 0x80 == 0 ||                       # QR
           byte & 0x78 != context.raw_data[2] & 0x78 # Opcode
          context.block.call(Error::INVALID_REPLY)
          return
        end

        if byte & 0x02 != 0 # TC
          # TODO: Switch to TCP
          context.block.call(Error::TRUNCATED)
          return
        end

        case io.read_bytes(UInt8) & 0x0F # RCODE
        when 0
          error = nil
          try_next_ns = false
        when 1
          error = Error::SERVER_INVALID_FORMAT
          try_next_ns = false
        when 2
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
        end

        if error
          context.block.call(error)
          return
        end

        io = IO::Memory.new(packet[4, packet.size - 4], writeable: false)
        qdcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        adcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        nscount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        arcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
      rescue IndexError
      rescue IO::EOFError
      end
    end

    def stop : Nil
      @v6_sock.try { |s| s.close }
      @v4_sock.try { |s| s.close }
    end
  end
end







<




<










203
204
205
206
207
208
209

210
211
212
213

214
215
216
217
218
219
220
221
222
223
        end

        if error
          context.block.call(error)
          return
        end


        qdcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        adcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        nscount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
        arcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)

      rescue IO::EOFError
      end
    end

    def stop : Nil
      @v6_sock.try { |s| s.close }
      @v4_sock.try { |s| s.close }
    end
  end
end