@@ -202,6 +202,8 @@ def __init__(self, interfaces, noTransmitInterfaces, ifFilter, waitForIP, ttl,
202202
203203 self .recentChecksums = []
204204
205+ self .bindings = set ()
206+
205207 self .listenAddr = listen
206208 self .listenSock = None
207209 if remote :
@@ -313,6 +315,7 @@ def addListener(self, addr, port, service):
313315 if self .isMulticast (addr ):
314316 rx .bind ((addr , port ))
315317 self .receivers .append (rx )
318+ self .bindings .add ((addr , port ))
316319
317320 @staticmethod
318321 def unicastIpToMac (ip , procNetArp = None ):
@@ -461,6 +464,9 @@ def transmitPacket(self, sock, srcMac, destMac, ipHeaderLength, ipPacket):
461464 else :
462465 self .logger .info ('Error sending packet: %s' % str (e ))
463466
467+ def match (self , addr , port ):
468+ return ((addr , port )) in self .bindings
469+
464470 def loop (self ):
465471 # Record where the most recent SSDP searches came from, to relay unicast answers
466472 # Note: ideally we'd be more clever and record multiple, but in practice
@@ -532,26 +538,6 @@ def loop(self):
532538 (data , addr ) = s .recvfrom (10240 )
533539 addr = addr [0 ]
534540
535- if self .remoteSockets () and not (receivingInterface == 'remote' and self .noRemoteRelay ):
536- packet = self .aes .encrypt (self .MAGIC + socket .inet_aton (addr ) + data )
537- for remoteConnection in self .remoteSockets ():
538- if remoteConnection == s :
539- continue
540- try :
541- remoteConnection .sendall (struct .pack ('!H' , len (packet )) + packet )
542-
543- for remote in self .remoteAddrs :
544- if remote ['socket' ] == remoteConnection and remote ['connecting' ]:
545- self .logger .info ('REMOTE: Connection to %s established' % remote ['addr' ])
546- remote ['connecting' ] = False
547- except socket .error as e :
548- if e .errno == errno .EAGAIN :
549- pass
550- else :
551- self .logger .info ('REMOTE: Failed to connect to %s: %s' % (self .remoteAddr , str (e )))
552- self .removeConnection (remoteConnection )
553- continue
554-
555541 eighthDataByte = data [8 ]
556542 if sys .version_info > (3 , 0 ):
557543 eighthDataByte = bytes ([data [8 ]])
@@ -585,6 +571,30 @@ def loop(self):
585571 srcPort = struct .unpack ('!H' , data [ipHeaderLength + 0 :ipHeaderLength + 2 ])[0 ]
586572 dstPort = struct .unpack ('!H' , data [ipHeaderLength + 2 :ipHeaderLength + 4 ])[0 ]
587573
574+ # raw sockets cannot be bound to a specific port, so we receive all UDP packets with matching dstAddr
575+ if receivingInterface == 'local' and not self .match (dstAddr , dstPort ):
576+ continue
577+
578+ if self .remoteSockets () and not (receivingInterface == 'remote' and self .noRemoteRelay ):
579+ packet = self .aes .encrypt (self .MAGIC + socket .inet_aton (addr ) + data )
580+ for remoteConnection in self .remoteSockets ():
581+ if remoteConnection == s :
582+ continue
583+ try :
584+ remoteConnection .sendall (struct .pack ('!H' , len (packet )) + packet )
585+
586+ for remote in self .remoteAddrs :
587+ if remote ['socket' ] == remoteConnection and remote ['connecting' ]:
588+ self .logger .info ('REMOTE: Connection to %s established' % remote ['addr' ])
589+ remote ['connecting' ] = False
590+ except socket .error as e :
591+ if e .errno == errno .EAGAIN :
592+ pass
593+ else :
594+ self .logger .info ('REMOTE: Failed to connect to %s: %s' % (self .remoteAddr , str (e )))
595+ self .removeConnection (remoteConnection )
596+ continue
597+
588598 origSrcAddr = srcAddr
589599 origSrcPort = srcPort
590600 origDstAddr = dstAddr
0 commit comments