AsyncDNS-cr  Diff

Differences From Artifact [b25ecb3e05]:

To Artifact [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
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 = packet[0].to_u16 << 8 | packet[1]
        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 packet[2] & 0x80 == 0 ||                       # QR
           packet[2] & 0x78 != context.raw_data[2] & 0x78 # Opcode
        if byte & 0x80 == 0 ||                       # QR
           byte & 0x78 != context.raw_data[2] & 0x78 # Opcode
          context.block.call(Error::INVALID_REPLY)
          return
        end

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

        case packet[3] & 0x0F # RCODE
        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
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