Не слишком знакомый с витой, я не знаю, является ли это лучшим способом. Я подозреваю, что то, что я предлагаю ниже, заключается не в том, что работа непосредственно на сокетах не кажется правильной, но здесь она идет.
Подкласс server.DNSServerFactory
и переопределить метод handleQuery()
, например:
import socket
from twisted.internet.address import IPv4Address
class MyDNSServerFactory(server.DNSServerFactory):
def handleQuery(self, message, protocol, address):
if protocol.transport.socket.type == socket.SOCK_STREAM:
self.peer_address = protocol.transport.getPeer()
elif protocol.transport.socket.type == socket.SOCK_DGRAM:
self.peer_address = IPv4Address('UDP', *address)
else:
print "Unexpected socket type %r" % protocol.transport.socket.type
print "Got message from : %r" % self.peer_address
return server.DNSServerFactory.handleQuery(self, message, protocol, address)
.
.
.
factory = MyDNSServerFactory(
clients=[DynamicResolver(), client.Resolver(resolv='/etc/resolv.conf')]
)
вещи беспокоиться о:
- IPV6 адреса
- Прямое использование
socket
кажется коварный.
- Соединяет ли socket.SOCK_STREAM соединение TCP?
Есть и другие способы сделать это, например. подкласс dns.DNSDatagramProtocol
и переопределить datagramReceived(self, data, addr)
, чтобы получить UDP-адрес клиента. Адреса клиентов TCP будут получены путем подклассификации и переопределения server.DNSServerFactory.connectionMade(self, protocol)
и получения адреса peer с protocol.transport.getPeer()
.
Обновленный ответ сделать равный адрес доступен в DynamicResolver
Изменить MyDNSServerFactory.handleQuery()
установить peer_address
для резольверов, которые имеют peer_address
атрибут:
class MyDNSServerFactory(server.DNSServerFactory):
def handleQuery(self, message, protocol, address):
if protocol.transport.socket.type == socket.SOCK_STREAM:
self.peer_address = protocol.transport.getPeer()
elif protocol.transport.socket.type == socket.SOCK_DGRAM:
self.peer_address = IPv4Address('UDP', *address)
else:
print "Unexpected socket type %r" % protocol.transport.socket.type
print "Got message from : %r" % self.peer_address
# Make peer_address available to resolvers that support that attribute
for resolver in self.resolver.resolvers:
if hasattr(resolver, 'peer_address'):
resolver.peer_address = self.peer_address
return server.DNSServerFactory.handleQuery(self, message, protocol, address)
Добавить следующую peer_address
недвижимость класса DynamicResolver
:
def __init__(self):
self._peer_address = None
@property
def peer_address(self):
return self._peer_address
@peer_address.setter
def peer_address(self, value):
self._peer_address = value
Теперь вы можете получить доступ к peer_address
в DynamicResolver.query()
, например.
def query(self, query, timeout=None):
print "In DynamicResolver.query(): self.peer_address = %r" % self.peer_address
if self._dynamicResponseRequired(query):
return defer.succeed(self._doDynamicResponse(query))
else:
return defer.fail(error.DomainError())
Большое спасибо, что выполнил эту работу. Легенда! – pjf
Еще один быстрый вопрос, если я могу; Как я могу получить содержимое self.peer_address в моем классе DynamicResolver()? – pjf
Yea ... Прикосновение к 'socket' делает все супер грустно. –