⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upnphosting.java

📁 国外的j2me播放器软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
package no.auc.one.portableplayer.communication.upnphosting;

import java.io.*;
import java.lang.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.rms.*;
import javax.xml.parsers.*;

import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.log4j.*;

import no.auc.one.portableplayer.utils.Utilities;
import no.auc.one.portableplayer.communication.soap.SoapFault;

public final class UPnPHosting extends Thread {
    private static Logger LOG = Logger.getLogger("Host");

    private final static String STANDARD_RESPONSE_404 = 
        "HTTP/1.1 404 Not Found\r\nDate: " + Utilities.getRfcDateString(
            Calendar.getInstance(TimeZone.getTimeZone("GMT"))) + 
        "Content-Length: 0\r\nConnection: close\r\n\r\n";
    private final static byte[] STANDARD_RESPONSE_503 = 
        ("HTTP/1.1 503 Service Unavailable\r\nDate: " + Utilities.getRfcDateString(
            Calendar.getInstance(TimeZone.getTimeZone("GMT"))) + 
        "\r\nRetry-After: 60\r\nContent-Length: 0\r\nConnection: close\r\n\r\n").getBytes();
    private final static int MAX_CONCURRENT_CURRENT_REQUESTS = 8;
        
    private Hashtable entities = new Hashtable(10);
    private ServerSocketConnection server;
    private RecordStore descriptionDocumentCache;
    private static UPnPHosting instance = null;
    private Timer notificationTimer;
    private static SAXParserFactory pfactory;
    private Hashtable httpRequestHandlers = new Hashtable(2);
    private int requestsCurrentlyHandling = 0;
    
    /**
     * Seconds between device advertisements.
     * 
     * XXX Should make the period configurable (Settings in the UI)
     *
     */
    private final int notifyPeriod = 300;
    
    private UPnPHosting() {
        try {
            registerHttpHandler(
                ServerRootHttpHandler.NAMESPACE_NAME,
                new ServerRootHttpHandler());
            registerHttpHandler(
                SsdpHttpHandler.NAMESPACE_NAME, 
                new SsdpHttpHandler());
            server = (ServerSocketConnection)Connector.open("socket://");

            descriptionDocumentCache = RecordStore.openRecordStore(
                "UPnP Hosting XML Cache",
                true);
            try {
                RecordEnumeration re = descriptionDocumentCache.enumerateRecords(
                    null, 
                    null, 
                    false);
                while(re.hasNextElement()) {
                    descriptionDocumentCache.deleteRecord(re.nextRecordId());
                }
                
                re.destroy();
            } catch (Exception e) {
                System.out.println("Exception while deleting records of desc doc cache");
                System.out.println(e);
                e.printStackTrace();
            }
            
            notificationTimer = new Timer();

            pfactory = SAXParserFactory.newInstance();
            pfactory.setNamespaceAware(true);
        } catch(IOException ioe) {
            LOG.fatal(ioe);
        } catch(RecordStoreNotFoundException rsnfe) {
            LOG.fatal(rsnfe);
        } catch(RecordStoreFullException rsfe) {
            LOG.fatal(rsfe);
        } catch(RecordStoreException rse) {
            LOG.fatal(rse);
        } catch(IllegalArgumentException iae) {
            LOG.fatal(iae);
        }
    }

    public static UPnPHosting getInstance() {
        if (null == instance) {
            instance = new UPnPHosting();
        }

        return instance;
    }

    /**
     * Retrieve the address of the server.
     */
    public String getLocalAddress() throws IOException {
        return server.getLocalAddress();
    }

    /**
     * Retrieve the port of the server.
     */
    public int getLocalPort() throws IOException {
        return server.getLocalPort();
    }
    
    /**
     * Used to start the UPnP Hosting Support Framework.
     *
     * This thread will take care of sending out NOTIFY messages for all 
     * registered devices and services, according to the UPnP architecture.
     */
    public void run() {
        // Create a new thread for listening to incoming service control 
        // requests and downloading of description documents (dev+svc)

        try {
            // XXX Need some synch stuff to stop acceptAndOpen() when 
            //     it is time to say good bye...
            do {
                SocketConnection sc = (SocketConnection)server.acceptAndOpen();
                
                if (requestsCurrentlyHandling < MAX_CONCURRENT_CURRENT_REQUESTS) {
                    ConnectionHandler ch = new ConnectionHandler(sc);
                    ch.start();
                    incrementNumRequestsHandling();
                } else {
                    OutputStream os = sc.openOutputStream();
                    os.write(STANDARD_RESPONSE_503);
                    sc.close();
                }
            } while (true);
        } catch (IOException ioe) {
            LOG.fatal("IOException while starting");
            LOG.fatal(ioe);
        } finally {
            try {
                server.close();
            } catch (IOException ioe) {
                LOG.fatal(ioe);
            } catch (Exception e) {
                LOG.fatal(e);
            }
        }
    }
    
    private synchronized int decrementNumRequestsHandling() {
        requestsCurrentlyHandling--;
        
        return requestsCurrentlyHandling;
    }
    
    private synchronized int incrementNumRequestsHandling() {
        requestsCurrentlyHandling++;
        
        return requestsCurrentlyHandling;
    }

    private final class ConnectionHandler extends Thread {
        private SocketConnection sc;
        
        public ConnectionHandler(SocketConnection sc) {
            this.sc = sc;
        }
        
        public void run() {
            try {
                //
                // Handle the sc request
                // 
                // XXX Should change this to something, hopefully, more robust:
                //     1) First read (as currently implemented below) all 
                //        header values (until CRLFCRLF is detected).
                //     2) Parse the header values
                //     3) Look for Content-Length and Transfer-Encoding
                //     4) These must be used to calculate how much to data to 
                //        be read.
                //     
                //     See HTTP 2616 section 4.4 Message Length for more info.
                //
                long time = 0;
                InputStream is = sc.openInputStream();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();

                System.err.println("[" + Thread.currentThread() + "][" + System.currentTimeMillis() + "] Start to receive request: ");
                int pos = 0;
                int nextPos = 0;
                do {
                    // System.err.print("; " + is.available());
                    pos = nextPos;
                    
                    byte[] inputBuffer = new byte[is.available()];
                    int rd = is.read(inputBuffer);                    
                    if (rd == -1)
                        break;
                    
                    bos.write(inputBuffer);
                    nextPos = rd;
                } while (bos.toString().indexOf("\r\n\r\n", (pos > 4 ? pos - 4 : pos)) == -1);
                System.err.println("[" + Thread.currentThread() + "][" + System.currentTimeMillis() + "] Got request");
                
                String requestHeaders = new String(bos.toByteArray());
                
                if(requestHeaders.startsWith("\r\n")) {
                    requestHeaders = requestHeaders.substring(2);
                    System.out.println("[" + Thread.currentThread()+ "] New request due to leading new-line:");
                    System.out.println("[" + Thread.currentThread()+ "] " + requestHeaders);
                }
                
                HttpRequest req = new HttpRequest();
                
                //
                // XXX Must set the HTTP version of the req object too!
                //               
                setRequestHeaders(requestHeaders, req);
                
                //
                // Get the content, if any
                //
                if (req.hasHeader("Content-Length")) {
                    int contentLength = Integer.parseInt(req.getHeader("Content-Length"));
                    
                    if (contentLength > 0) {
                        byte[] content = new byte[contentLength];
                        is.read(content);
                        
                        bos.close();
                        is.close();
                        
                        if (content == null || content.length <= 0) {
                            System.out.println("[" + Thread.currentThread()+ "] Something is wrong with the request...");
                            System.out.flush();
                            return;
                        }
                        
                        req.setBody(new String(content));
                    }
                }
                
                int firstSpace = requestHeaders.indexOf(' ') + 1;
                int nextSpace = requestHeaders.indexOf(' ', firstSpace);
                
                String reqUri = null;
                String namespace = null;
                if (nextSpace - firstSpace > 1) {
                    reqUri = requestHeaders.substring(firstSpace, nextSpace);

                    namespace = reqUri.substring(1);
                    int firstSlash = namespace.indexOf('/');
                    if (firstSlash >= 0) {
                        namespace = namespace.substring(0, firstSlash);
                    } else {
                        namespace = ServerRootHttpHandler.NAMESPACE_NAME;
                    }
                } else {
                    reqUri = new String(new char[]{requestHeaders.charAt(firstSpace)});
                    namespace = ServerRootHttpHandler.NAMESPACE_NAME;
                }
                
                req.setRequestUri(reqUri);
                req.setSocketConnection(sc);
            
                time = System.currentTimeMillis();
                System.out.println("[" + Thread.currentThread()+ "][" + time +"] Namespace: " + namespace);

                byte[] response = null;
                if (!httpRequestHandlers.containsKey(namespace)) {
                    time = System.currentTimeMillis();
                    System.out.println("[" + Thread.currentThread()+ "][" + time +"] Unknown namespace. Return error to client");
                    response = STANDARD_RESPONSE_404.getBytes();
                } else {
                    HttpRequestHandler handler = 
                        (HttpRequestHandler)httpRequestHandlers.get(namespace);
                
                    if(requestHeaders.startsWith("GET")) {
                        req.setRequestMethod(HttpRequest.REQUEST_METHOD_GET);
                        response = handler.handleGetRequest(req);
                    } else if(requestHeaders.startsWith("POST")) {
                        req.setRequestMethod(HttpRequest.REQUEST_METHOD_POST);
                        response = handler.handlePostRequest(req);
                    } else if (requestHeaders.startsWith("OPTIONS")) {
                        req.setRequestMethod(HttpRequest.REQUEST_METHOD_OPTIONS);
                        response = handler.handleOptionsRequest(req);
/*                    } else if(request.startsWith("SUBSCRIBE")) {
                        System.out.println("Request is SUBSCRIBE");
                        req.requestMethod = REQUEST_METHOD_SUBSCRIBE;
                        response = handleSubscribeRequest(req);
                    } else if(request.startsWith("UNSUBSCRIBE")) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -