1919 */
2020@ Component
2121public class UpnpListener {
22- private Logger log = Logger .getLogger (UpnpListener .class );
23- private static final int UPNP_DISCOVERY_PORT = 1900 ;
24- private static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250" ;
22+ private Logger log = Logger .getLogger (UpnpListener .class );
23+ private static final int UPNP_DISCOVERY_PORT = 1900 ;
24+ private static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250" ;
2525
26- @ Value ("${upnp.response.port}" )
27- private int upnpResponsePort ;
26+ @ Value ("${upnp.response.port}" )
27+ private int upnpResponsePort ;
2828
29- @ Value ("${server.port}" )
30- private int httpServerPort ;
29+ @ Value ("${server.port}" )
30+ private int httpServerPort ;
3131
32- @ Value ("${upnp.config.address}" )
33- private String responseAddress ;
32+ @ Value ("${upnp.config.address}" )
33+ private String responseAddress ;
3434
35- @ Autowired
36- private ApplicationContext applicationContext ;
35+ @ Autowired
36+ private ApplicationContext applicationContext ;
3737
38- @ Scheduled (fixedDelay = Integer .MAX_VALUE )
38+ @ Scheduled (fixedDelay = Integer .MAX_VALUE )
3939 public void startListening (){
4040 log .info ("Starting UPNP Discovery Listener" );
41-
41+
4242 try (DatagramSocket responseSocket = new DatagramSocket (upnpResponsePort );
4343 MulticastSocket upnpMulticastSocket = new MulticastSocket (UPNP_DISCOVERY_PORT );) {
4444 InetSocketAddress socketAddress = new InetSocketAddress (UPNP_MULTICAST_ADDRESS , UPNP_DISCOVERY_PORT );
@@ -49,7 +49,7 @@ public void startListening(){
4949 Enumeration <InetAddress > addrs = xface .getInetAddresses ();
5050 String name = xface .getName ();
5151 int IPsPerNic = 0 ;
52-
52+
5353 while (addrs .hasMoreElements ()) {
5454 InetAddress addr = addrs .nextElement ();
5555 log .debug (name + " ... has addr " + addr );
@@ -63,7 +63,7 @@ public void startListening(){
6363 log .debug ("Adding " + name + " to our interface set" );
6464 }
6565 }
66-
66+
6767 while (true ){ //trigger shutdown here
6868 byte [] buf = new byte [1024 ];
6969 DatagramPacket packet = new DatagramPacket (buf , buf .length );
@@ -74,44 +74,44 @@ public void startListening(){
7474 sendUpnpResponse (responseSocket , packet .getAddress (), packet .getPort ());
7575 }
7676 }
77-
77+
7878 } catch (IOException e ) {
7979 log .error ("UpnpListener encountered an error. Shutting down" , e );
8080 ConfigurableApplicationContext context = (ConfigurableApplicationContext ) UpnpListener .this .applicationContext ;
8181 context .close ();
82-
82+
8383 }
8484 log .info ("UPNP Discovery Listener Stopped" );
85-
85+
8686 }
8787
88- /**
89- * very naive ssdp discovery packet detection
90- * @param body
91- * @return
92- */
93- protected boolean isSSDPDiscovery (String body ){
94- if (body != null && body .startsWith ("M-SEARCH * HTTP/1.1" ) && body .contains ("MAN: \" ssdp:discover\" " )){
95- return true ;
96- }
97- return false ;
98- }
99-
100- String discoveryTemplate = "HTTP/1.1 200 OK\r \n " +
101- "CACHE-CONTROL: max-age=86400\r \n " +
102- "EXT:\r \n " +
103- "LOCATION: http://%s:%s/upnp/amazon-ha-bridge/setup.xml\r \n " +
104- "OPT: \" http://schemas.upnp.org/upnp/1/0/\" ; ns=01\r \n " +
105- "01-NLS: %s\r \n " +
106- "ST: urn:Belkin:device:**\r \n " +
107- "USN: uuid:Socket-1_0-221438K0100073::urn:Belkin:device:**\r \n \r \n " ;
108- protected void sendUpnpResponse (DatagramSocket socket , InetAddress requester , int sourcePort ) throws IOException {
109- String discoveryResponse = String .format (discoveryTemplate , responseAddress , httpServerPort , getRandomUUIDString ());
110- DatagramPacket response = new DatagramPacket (discoveryResponse .getBytes (), discoveryResponse .length (), requester , sourcePort );
111- socket .send (response );
112- }
113-
114- protected String getRandomUUIDString (){
115- return "88f6698f-2c83-4393-bd03-cd54a9f8595" ; // https://xkcd.com/221/
116- }
88+ /**
89+ * very naive ssdp discovery packet detection
90+ * @param body
91+ * @return
92+ */
93+ protected boolean isSSDPDiscovery (String body ){
94+ if (body != null && body .startsWith ("M-SEARCH * HTTP/1.1" ) && body .contains ("MAN: \" ssdp:discover\" " )){
95+ return true ;
96+ }
97+ return false ;
98+ }
99+
100+ String discoveryTemplate = "HTTP/1.1 200 OK\r \n " +
101+ "CACHE-CONTROL: max-age=86400\r \n " +
102+ "EXT:\r \n " +
103+ "LOCATION: http://%s:%s/upnp/amazon-ha-bridge/setup.xml\r \n " +
104+ "OPT: \" http://schemas.upnp.org/upnp/1/0/\" ; ns=01\r \n " +
105+ "01-NLS: %s\r \n " +
106+ "ST: urn:Belkin:device:**\r \n " +
107+ "USN: uuid:Socket-1_0-221438K0100073::urn:Belkin:device:**\r \n \r \n " ;
108+ protected void sendUpnpResponse (DatagramSocket socket , InetAddress requester , int sourcePort ) throws IOException {
109+ String discoveryResponse = String .format (discoveryTemplate , responseAddress , httpServerPort , getRandomUUIDString ());
110+ DatagramPacket response = new DatagramPacket (discoveryResponse .getBytes (), discoveryResponse .length (), requester , sourcePort );
111+ socket .send (response );
112+ }
113+
114+ protected String getRandomUUIDString (){
115+ return "88f6698f-2c83-4393-bd03-cd54a9f8595" ; // https://xkcd.com/221/
116+ }
117117}
0 commit comments