ca.viaware.dlna.ssdp.SSDPService.java Source code

Java tutorial

Introduction

Here is the source code for ca.viaware.dlna.ssdp.SSDPService.java

Source

/*
 * Copyright 2015 Seth Traverse
 *
 * This file is part of ViaWare DLNA Server.
 *
 * ViaWare DLNA Server is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ViaWare DLNA Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ViaWare DLNA Server. If not, see <http://www.gnu.org/licenses/>.
 */

package ca.viaware.dlna.ssdp;

import ca.viaware.api.logging.Log;
import ca.viaware.dlna.Globals;
import ca.viaware.dlna.settings.SettingsManager;
import ca.viaware.dlna.upnp.device.Device;
import ca.viaware.dlna.upnp.device.DeviceManager;
import ca.viaware.dlna.upnp.service.Service;
import ca.viaware.dlna.util.DateUtils;
import ca.viaware.dlna.util.HttpParser;
import org.json.JSONObject;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;

public class SSDPService extends Thread {

    private String baseAnnounce;
    private MulticastSocket outSock;
    private MulticastListener listener;
    private JSONObject ssdpConfig;
    private JSONObject httpConfig;

    public SSDPService() {
        ssdpConfig = SettingsManager.getServerConfig().getJSONObject("ssdp");
        httpConfig = SettingsManager.getServerConfig().getJSONObject("http");

        try {
            outSock = new MulticastSocket(ssdpConfig.getInt("port"));
            outSock.setNetworkInterface(
                    NetworkInterface.getByInetAddress(InetAddress.getByName(ssdpConfig.getString("host"))));
            Log.info("SSDP: Outbound UDP bound to " + this.outSock.getLocalAddress());
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.baseAnnounce = "";
        this.baseAnnounce += "HOST: 239.255.255.250:1900\r\n";
        this.baseAnnounce += "CACHE-CONTROL: max-age=1800\r\n";
        this.baseAnnounce += "NTS: ssdp:alive\r\n";
        this.baseAnnounce += "SERVER:" + Globals.SERVER + "\r\n";
    }

    public void run() {
        try {
            this.listener = new MulticastListener(this);
            this.listener.start();

            Searcher searcher = new Searcher(this.outSock);
            searcher.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Thread advertiser = new Thread(new Runnable() {
            public void send(String data) {
                try {
                    byte[] bytes = data.getBytes("UTF-8");
                    DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length,
                            InetAddress.getByName("239.255.255.250"), 1900);
                    outSock.send(packet);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            public void sendNotify(String usn, String nt, String uid) {
                String http = "NOTIFY * HTTP/1.1\n";
                http += baseAnnounce;
                http += "NT: " + nt + "\r\n";
                http += "USN: " + usn + "\r\n";
                http += "LOCATION: http://" + httpConfig.getString("host") + ":" + httpConfig.getInt("port") + "/"
                        + uid + "/\r\n";
                http += "\r\n";
                send(http);
            }

            @Override
            public void run() {
                while (true) {
                    Log.info("SSDP: Advertising...");
                    for (int i = 0; i < 3; i++) {
                        for (Device d : DeviceManager.getDevices()) {
                            sendNotify("uuid: " + d.getUid() + "::upnp:rootdevice", "upnp:rootdevice", d.getUid());
                            sendNotify("uuid:" + d.getUid(), "uuid:" + d.getUid(), d.getUid());
                            sendNotify(
                                    "uuid:" + d.getUid() + "::urn:schemas-upnp-org:device:" + d.getType() + ":"
                                            + d.getVersion(),
                                    "urn:schemas-upnp-org:device:" + d.getType() + ":" + d.getVersion(),
                                    d.getUid());
                            for (Service s : d.getServices()) {
                                sendNotify(
                                        "uuid:" + d.getUid() + "::urn:schemas-upnp-org:service:" + s.getType() + ":"
                                                + s.getVersion(),
                                        "urn:schemas-upnp-org:service:" + s.getType() + ":" + s.getVersion(),
                                        d.getUid());
                            }
                        }
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        Thread.sleep(30 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        advertiser.start();

        Log.info("Started SSDP Service");
    }

    public void reply(String st, String usn, String uid, SocketAddress source) {
        String http = "HTTP/1.1 200 OK\r\n";
        http += "CACHE-CONTROL: max-age=1800\r\n";
        http += "EXT: \r\n";
        http += "ST: " + st + "\r\n";
        http += "USN: " + usn + "\r\n";
        http += "SERVER: " + Globals.SERVER + "\r\n";
        http += "LOCATION: http://" + httpConfig.getString("host") + ":" + httpConfig.getInt("port") + "/" + uid
                + "/\r\n";

        http += "DATE: " + DateUtils.getDate() + "\r\n";

        http += "\r\n";

        try {
            byte[] bytes = http.getBytes("UTF-8");
            DatagramPacket p = new DatagramPacket(bytes, 0, bytes.length, source);
            outSock.send(p);
            Log.info("SSDP: M-SEARCH Reply sent to '" + source + "' successfully : ST: " + st + " : USN: " + usn);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void handleCommand(String data, DatagramPacket packet) {
        HttpParser parser = new HttpParser();
        parser.parseRequest(data);

        if (parser.getMethod().equals("M-SEARCH")) {
            String st = parser.getHeader("st");

            if (st.equals("ssdp:all")) {
                for (Device d : DeviceManager.getDevices()) {
                    reply("upnp:rootdevice", "uuid:" + d.getUid() + "::upnp:rootdevice", d.getUid(),
                            packet.getSocketAddress());
                    reply("uuid:" + d.getUid(), "uuid:" + d.getUid(), d.getUid(), packet.getSocketAddress());
                    reply("urn:schemas-upnp-org:device:" + d.getType() + ":" + d.getVersion(), "uuid:" + d.getUid()
                            + "::urn:schemas-upnp-org:device:" + d.getType() + ":" + d.getVersion(), d.getUid(),
                            packet.getSocketAddress());
                    for (Service s : d.getServices()) {
                        reply("urn:schemas-upnp-org:service:" + s.getType() + ":" + s.getVersion(),
                                "uuid:" + d.getUid() + "::urn:schemas-upnp-org:service:" + s.getType() + ":"
                                        + s.getVersion(),
                                d.getUid(), packet.getSocketAddress());
                    }
                }
            } else if (st.equals("upnp:rootdevice")) {

                for (Device d : DeviceManager.getDevices()) {
                    reply(st, "uuid:" + d.getUid() + "::upnp:rootdevice", d.getUid(), packet.getSocketAddress());
                }

            } else if (st.startsWith("uuid")) {

                for (Device d : DeviceManager.getDevices()) {
                    if (parser.getHeader("st").contains(d.getUid())) {
                        String usn = "uuid:" + d.getUid();
                        reply(st, usn, d.getUid(), packet.getSocketAddress());
                        break;
                    }
                }

            } else {
                for (Device d : DeviceManager.getDevices()) {
                    if (st.equals("urn:schemas-upnp-org:device:" + d.getUid() + ":" + d.getVersion())) {
                        String usn = "uuid:" + d.getUid() + "::" + st;
                        reply(st, usn, d.getUid(), packet.getSocketAddress());
                        break;
                    } else {
                        for (Service s : d.getServices()) {
                            if (st.equals("urn:schemas-upnp-org:service:" + s.getUid() + ":" + s.getVersion())) {
                                String usn = "uuid:" + d.getUid() + "::" + st;
                                reply(st, usn, d.getUid(), packet.getSocketAddress());
                                break;
                            }
                        }
                    }
                }
            }
        }

    }

}