Contorto: indirizzo IP di origine per le connessioni in uscita
-
06-07-2019 - |
Domanda
Sto implementando un servizio - scritto in Python con il framework Twisted, in esecuzione su Debian GNU / Linux - che controlla la disponibilità dei server SIP. Per questo utilizzo il metodo OPTIONS (una funzione del protocollo SIP), poiché questa sembra essere una pratica comune. Per costruire intestazioni corrette e conformi a RFC, devo conoscere l'indirizzo IP di origine e la porta di origine per la connessione che verrà stabilita. [Come] può essere fatto con Twisted?
Questo è quello che ho provato:
Ho eseguito la sottoclasse del protocol.DatagramProtocol ed entro < code> startProtocol (self) Ho usato self.transport.getHost (). host
e self.transport.getHost (). port
. Quest'ultimo è in effetti la porta che verrà utilizzata, mentre il primo produce solo 0.0.0.0.
Immagino che a questo punto Twisted non [ancora?] sappia quale interfaccia e come tale quale indirizzo IP sorgente verrà usato. Twisted offre una funzione che potrebbe aiutarmi in questo caso o devo interfacciarmi con il sistema operativo (routing) in modo diverso? Oppure ho usato self.transport.getHost (). Host
in modo errato?
Soluzione
Per completezza, rispondo alla mia domanda:
Assicurarsi di utilizzare connect () sul trasporto prima di provare a determinare l'indirizzo IP di origine dell'host. Il seguente estratto mostra la parte rilevante di un'implementazione del protocollo:
class FooBarProtocol(protocol.DatagramProtocol):
def startProtocol(self):
self.transport.getHost().host # => 0.0.0.0
self.transport.connect(self.dstHost, self.dstPort)
self.transport.getHost().host # => 192.168.1.102
Altri suggerimenti
Se si utilizza UDP, l'endpoint è determinato da:
- chiamando
bind ()
sul socket e assegnandogli esplicitamente un indirizzo - invio di un pacchetto
Se desideri qualche altro dettaglio, controlla questa risposta .
Il problema è che non ho molta familiarità con il twisted. Da quello che posso dire da una rapida lettura della fonte, sembra che potresti voler usare un reattore come tidSelectReactor
. Questo è ciò che tndDNSDatagramProtocol
fa sotto il cofano .
Se estrai contorto
dall'immagine, il frammento seguente mostra cosa sta succedendo:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
<socket._socketobject object at 0x10025d670>
>>> s.getsockname() # this is an unbound or unnamed socket
('0.0.0.0', 0)
>>> s.bind( ('0.0.0.0', 0) ) # 0.0.0.0 is INADDR_ANY, 0 means pick a port
>>> s.getsockname() # IP is still zero, but it has picked a port
('0.0.0.0', 56814)
Ottenere il nome host è un po 'più complicato se è necessario supportare più interfacce di rete o IPv4 e IPv6. Se puoi rendere configurabile l'interfaccia utilizzata, passala come primo membro della tupla a socket.bind ()
e sei pronto.
Ora la parte difficile sta facendo questo entro i confini delle astrazioni fornite da twisted. Sfortunatamente, non posso aiutare molto lì. Consiglierei di cercare esempi su come ottenere l'accesso al socket sottostante o trovare un modo per passare le informazioni sul socket nel framework.
Buona fortuna.
Hai visto se ciò che vuoi fare è possibile con l'implementazione SIP che fa parte di Twisted?
In ogni caso, come impostare l'indirizzo e la porta di origine per UDP in Twisted è abbastanza simile a come li si imposta senza Twisted. In Twisted, reattor.listenUDP (porta, protocollo, interfaccia)
collega un socket UDP a una porta e un'interfaccia specifiche e gestisce i datagrammi ricevuti con il protocollo. All'interno del protocollo, self.transport.write (msg, addr)
invia un datagramma a addr
utilizzando l'indirizzo a cui il protocollo è associato come indirizzo di origine.
Rileggendo la tua domanda, penso che l'unica parte che ti mancava fosse passare interfaccia
a reattor.listenUDP (...)
.