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

📄 relayserver.java

📁 jxme的一些相关程序,主要是手机上程序开发以及手机和计算机通信的一些程序资料,程序编译需要Ant支持
💻 JAVA
字号:
/************************************************************************
 *
 * $Id: RelayServer.java,v 1.2 2002/03/04 21:43:00 echtcherbina Exp $
 *
 * Copyright (c) 2001 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *       Sun Microsystems, Inc. for Project JXTA."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
 *    must not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact Project JXTA at http://www.jxta.org.
 *
 * 5. Products derived from this software may not be called "JXTA",
 *    nor may "JXTA" appear in their name, without prior written
 *    permission of Sun.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL SUN MICROSYSTEMS OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of Project JXTA.  For more
 * information on Project JXTA, please see
 * <http://www.jxta.org/>.
 *
 * This license is based on the BSD license adopted by the Apache Foundation.
 */

package net.jxta.impl.relay;

import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FilterInputStream;
import java.io.OutputStream;
//PDA requirements 19.02.2002
//java.util.HashMap -> java.util.Hashtable
//import java.util.HashMap;
import java.util.Hashtable;
//class java.util.Iterator is never used
//import java.util.Iterator;
//PDA requirements 19.02.2002
import java.util.Timer;
import java.util.TimerTask;
import java.util.Properties;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;

//PDA requirement 28.02.02
//javax.servlet is not required for the first version for PDA
//import javax.servlet.http.*;
//import javax.servlet.*;

import net.jxta.id.ID;
import net.jxta.endpoint.EndpointService;
import net.jxta.impl.util.BoundedQueue;
import net.jxta.impl.util.Base64;

import org.apache.log4j.Category; import org.apache.log4j.Priority;

/**
 * Relay server that maintains outgoing message queues, leases, etc.
 */
public class RelayServer  {

    private static final Category LOG =
	Category.getInstance(RelayServer.class.getName());

    /** global timer used for lease expiration tasks **/
    private static Timer timer = new Timer();

    private static final String LEASE_LEN_KEY = "RelayServer.LeaseLength";

    /** Default lease length. **/
    private int leaseLength = 30 * 60 * 1000;

    /** random number generator **/
    private SecureRandom random = null;

    /** the endpoint that we're relaying for **/
    private EndpointService endpoint = null;

    /** map of (leaseId, RelayLease) **/
    //PDA requirements 19.02.2002
    //java.util.HashMap -> java.util.Hashtable
    //private HashMap leaseMap = new HashMap();
    private Hashtable leaseMap = new Hashtable();
    //PDA requirements 19.02.2002

    /** map of (leaseId,BoundedQueue) **/
    //PDA requirements 19.02.2002
    //java.util.HashMap -> java.util.Hashtable
    //private HashMap queueMap = new HashMap();
    private Hashtable queueMap = new Hashtable();
    //PDA requirements 19.02.2002

    /** map of (leaseId,LeaseExpirationTask) **/
    //PDA requirements 19.02.2002
    //java.util.HashMap -> java.util.Hashtable
    //private HashMap expirationTaskMap = new HashMap();
    private Hashtable expirationTaskMap = new Hashtable();
    //PDA requirements 19.02.2002

    /** map of (client peerId, leaseId) **/
    //PDA requirements 19.02.2002
    //java.util.HashMap -> java.util.Hashtable
    //private HashMap peerIdToLeaseIdMap = new HashMap();
    private Hashtable peerIdToLeaseIdMap = new Hashtable();
    //PDA requirements 19.02.2002

    /** Returns the peer ID that this relay server is running on **/
    public ID getPeerID() {
        return endpoint.getGroup().getPeerID();
    }

    /**
     * Constructs the relay server given the endpoint that it is serving
     */
    public RelayServer(EndpointService endpoint, Properties prop) {
	this.endpoint = endpoint;
	//PDA requirements 19.02.2002
        //java.security.SecureRandom.getInstance(String algorithm)-> new SecureRandom()
        //try {
	    //random = SecureRandom.getInstance("SHA1PRNG");
	//} catch(NoSuchAlgorithmException e) {
	    //if (LOG.isEnabledFor(Priority.ERROR)) LOG.error("RelayServer does not have SHA1PRNG crypto algorithm");
	    //throw new RuntimeException("RelayServer does not have SHA1PRNG crypto algorithm");
	//}
        random = new SecureRandom();
	//PDA requirements 19.02.2002


	// read the lease length from the properties file
	//
	if (prop != null) {
	    String leaseLenStr = prop.getProperty (LEASE_LEN_KEY);
	    if (leaseLenStr != null) {
		try {
		    leaseLength = Integer.parseInt (leaseLenStr);
		} catch (NumberFormatException e) {
		    if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("Illegal value specified for " + LEASE_LEN_KEY);
		}
	    } else {
		if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("Using default value for lease length");
	    }
	}
	if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("lease length = " + leaseLength);

	// this will seed the secure random algorithm. Otherwise, the first
	// client connect will take a long time.
	if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("Generating initial lease key");
	generateLeaseId();
    }

    /**
     * Issues a new lease to the peer. If the peer has any outstanding leases,
     * we will remove the lease.  Also, if there are any queued messages
     * on the old lease, they will be removed. When a new lease is issueed,
     * we schedule a task for the expiration of it.
     *
     * Now does remove the old lease.
     */
    public synchronized RelayLease issueNewLease(String clientPeerId) {

	RelayLease lease = null;

        String leaseId = (String) peerIdToLeaseIdMap.get(clientPeerId);
        if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug ("issuing new lease for " + clientPeerId);

        if (leaseId != null) {
            // Temporarily set at warn level to monitor progress on the issue.
            if (LOG.isEnabledFor(Priority.INFO)) LOG.info("Peer " + clientPeerId + " already has a lease");
        }

        return newLease(clientPeerId, leaseId);
    }

    /**
     * Renews the lease for clientPeerId
     * @throws RelayLeaseException This exception is thrown if the client
     *   does not already have a valid lease with the relay
     */
    public synchronized RelayLease renewLease(String leaseId)
	throws RelayLeaseException {

	if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug("attempting to renew lease " + leaseId);

	// check for validiting of existing lease
	RelayLease oldLease = (RelayLease) leaseMap.get (leaseId);

	if (oldLease == null || ! oldLease.isValid()) {
	    throw new RelayLeaseException ("Existing lease is not valid");
        }

        // renew the lease
        String clientPeerId = (String) oldLease.getPeerId();
        return newLease(clientPeerId, leaseId);
    }


    // MUST be called from synchronized ctxt.
    private RelayLease newLease(String clientPeerId, String leaseId) {


        if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("making lease for peer " + clientPeerId + " with lease " + (leaseId == null ? "(none)" : leaseId));

        // Remove the old lease object etc.
        // (Keep the queue, if any, we'll move it to the new lease).
        BoundedQueue queue = null;
        peerIdToLeaseIdMap.remove (clientPeerId);
        if (leaseId != null) {
            leaseMap.remove (leaseId);
            queue = (BoundedQueue) queueMap.remove (leaseId);
            TimerTask oldTask =
                (TimerTask) expirationTaskMap.get (leaseId);
            if (oldTask!=null) {
                oldTask.cancel();
            }
            expirationTaskMap.remove (leaseId);
        } else {
            queue = new BoundedQueue(32);
        }

        // Install the new lease etc.
        String newLeaseId = generateLeaseId();
        RelayLease newLease = new RelayLease (clientPeerId,
                                              newLeaseId,
                                              leaseLength);
        leaseMap.put (newLeaseId, newLease);
        peerIdToLeaseIdMap.put (clientPeerId, newLeaseId);
        queueMap.put (newLeaseId, queue);
        TimerTask task = new LeaseExpirationTask (newLeaseId, this);
        expirationTaskMap.put (newLeaseId, task);
        timer.schedule (task, leaseLength);

        if (LOG.isEnabledFor(Priority.INFO)) LOG.info ("peer " + clientPeerId + " new lease id = "+ newLeaseId);
        return newLease;
    }

    /**
     * Tells whether the client has a valid lease
     */
    public synchronized boolean hasLease (String clientPeerId) {
	String leaseId = (String) peerIdToLeaseIdMap.get (clientPeerId);

	if (leaseId!=null) {
	    RelayLease lease = null;
	    lease = (RelayLease) leaseMap.get (leaseId);
	    if (lease!=null && lease.isValid()) {
		return true;
	    }
	}

	return false;
    }

    /**
     * Returns the leaseId for the client
     */
    public synchronized String getLeaseId (String clientPeerId) {
        return (String) peerIdToLeaseIdMap.get (clientPeerId);
    }

    /**
     * Returns the outbound message queue for the specified client
     */
    public synchronized BoundedQueue getOutboundMessageQueueByPeerId (String clientPeerId) {
	String leaseId = (String) peerIdToLeaseIdMap.get (clientPeerId);

	if (leaseId!=null)
	    return (BoundedQueue) queueMap.get (leaseId);
	else
	    return null;
    }

    /**
     * Returns the outbound message queue for the specified client
     */
    public synchronized BoundedQueue getOutboundMessageQueueByLeaseId (String leaseId) {
	return (BoundedQueue) queueMap.get (leaseId);
    }


    /**
     * Generates a 128-bit base64-encoded random lease key
     */
    private String generateLeaseId() {
	byte[] buf = new byte[16];
	random.nextBytes(buf);
	return new String (Base64.encodeBase64 (buf)).trim();
    }

    /** test code
    private void dumpClientTable() {
	Iterator i = clientMap.keySet().iterator();
	if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug ("current relay clients:" );
	while (i.hasNext()) {
	    String peerId = (String) i.next();
	    if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug ( "   - " + peerId);
	    if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug ( "     - " + getClient (peerId));
	}
	} **/

    /**
     * Task that removes clients from the relay server. This task must be
     * cancelled by lease renewal.
     */
    class LeaseExpirationTask extends TimerTask {

	String leaseId = null;
	RelayServer relayServer = null;

	LeaseExpirationTask(String leaseId, RelayServer relayServer) {
	    this.leaseId = leaseId;
	    this.relayServer = relayServer;
	}

	/** Removes the client **/
	public void run() {

	    if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug ("expiring lease: " + leaseId);
	    relayServer.removeLease (leaseId);
	}
    }


    public void removeLease (String leaseId) {

        BoundedQueue queue = null;

        synchronized(this) {

            // remove the lease from the map. Hold on to the old lease
            // to get information out of it
            RelayLease oldLease = null;
            oldLease = (RelayLease) leaseMap.get (leaseId);
            leaseMap.remove (leaseId);

            // remove the old (clientPeerId, leaseId) entry
            peerIdToLeaseIdMap.remove (oldLease.getPeerId());

            // Cancel the expiration task.
            expirationTaskMap.remove (leaseId);

            // get a handle to the old queue and then remove it from the map
            queue = (BoundedQueue) queueMap.get (leaseId);
            queueMap.remove (leaseId);
        } // close synch block. We're done with our stuff an queue.clear has
          // its own synch. No need to uslessly nest critical sections.

	// clear the queue out and notify everyone that is waiting
	if (queue!=null) {
            queue.clear();
	}
    }
}

⌨️ 快捷键说明

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