package zutil.network.ssdp; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.util.HashMap; import java.util.LinkedList; import zutil.MultiPrintStream; import zutil.network.http.HTTPHeaderParser; import zutil.network.http.HttpPrintStream; import zutil.network.threaded.ThreadedUDPNetwork; import zutil.network.threaded.ThreadedUDPNetworkThread; import zutil.wrapper.StringOutputStream; /** * An SSDP client class that will request * service information. * * @author Ziver */ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{ // Contains all the received services private HashMap> services_st; private HashMap services_usn; public static void main(String[] args) throws IOException{ SSDPClient ssdp = new SSDPClient(); ssdp.requestService("upnp:rootdevice"); ssdp.start(); for(int i=0; true ;++i){ while( i==ssdp.getServicesCount("upnp:rootdevice") ){ try{Thread.sleep(100);}catch(Exception e){} } MultiPrintStream.out.println( "************************" ); MultiPrintStream.out.println( ssdp.getServices("upnp:rootdevice").get(i) ); } } /** * Creates new instance of this class. An UDP * listening socket at the SSDP port. * * @throws IOException */ public SSDPClient() throws IOException{ super( null ); super.setThread( this ); services_st = new HashMap>(); services_usn = new HashMap(); } /** * Sends an request for an service * * @param st is the SearchTarget of the service * * ***** REQUEST: * M-SEARCH * HTTP/1.1 * Host: 239.255.255.250:reservedSSDPport * Man: "ssdp:discover" * ST: ge:fridge * MX: 3 * */ public void requestService(String st){ try { services_st.put( st, new LinkedList() ); // Generate an SSDP discover message StringOutputStream msg = new StringOutputStream(); HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HTTPMessageType.REQUEST ); http.setRequestType("M-SEARCH"); http.setRequestURL("*"); http.setHeader("Host", SSDPServer.SSDP_MULTICAST_ADDR+":"+SSDPServer.SSDP_PORT ); http.setHeader("ST", st ); http.setHeader("Man", "\"ssdp:discover\"" ); http.setHeader("MX", "3" ); http.close(); //MultiPrintStream.out.println("***** REQUEST: \n"+msg); byte[] data = msg.toString().getBytes(); DatagramPacket packet = new DatagramPacket( data, data.length, InetAddress.getByName( SSDPServer.SSDP_MULTICAST_ADDR ), SSDPServer.SSDP_PORT ); super.send( packet ); } catch (Exception e) { e.printStackTrace(); } } /** * Returns a list of received services by * the given search target. * * @param st is the search target * @return a list of received services */ public LinkedList getServices(String st){ return services_st.get( st ); } /** * Returns the amount of services in the search target * * @param st is the search target * @return the amount of services */ public int getServicesCount(String st){ if( services_st.containsKey( st ) ){ return services_st.get( st ).size(); } return 0; } /** * Returns a service with the given USN. * * @param usn is the unique identifier for the service * @return an service, null if there is no such service */ public SSDPServiceInfo getService(String usn){ return services_usn.get( usn ); } /** * Clears all the received information of the services */ public void clearServices(){ services_usn.clear(); services_st.clear(); } /** * Waits for responses * * ***** RESPONSE; * HTTP/1.1 200 OK * Ext: * Cache-Control: no-cache="Ext", max-age = 5000 * ST: ge:fridge * USN: uuid:abcdefgh-7dec-11d0-a765-00a0c91e6bf6 * Location: http://localhost:80 */ public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { HTTPHeaderParser header = new HTTPHeaderParser( new String( packet.getData() ) ); //MultiPrintStream.out.println("*********** Recived\n"+header); String usn = header.getHTTPAttribute("USN"); String st = header.getHTTPAttribute("ST"); SSDPServiceInfo service; // Get existing service if( services_usn.containsKey( usn )){ service = services_usn.get( usn ); } // Add new service else{ service = new SSDPServiceInfo(); services_usn.put( usn, service); if( !services_st.containsKey(st) ) services_st.put( st, new LinkedList() ); services_st.get( header.getHTTPAttribute("ST") ).add( service ); } service.setLocation( header.getHTTPAttribute("LOCATION") ); service.setST( st ); service.setUSN( usn ); service.setExpirationTime( System.currentTimeMillis() + 1000 * getCacheTime(header.getHTTPAttribute("Cache-Control")) ); //MultiPrintStream.out.println("*********** Recived\n"+service); } private long getCacheTime(String cache_control){ long ret = 0; String[] tmp = cache_control.split(","); for( String element : tmp ){ element = element.replaceAll("\\s", "").toLowerCase(); if( element.startsWith("max-age=") ){ ret = Long.parseLong( element.substring( "max-age=".length() ) ); } } return ret; } }