Package com.sun.jini.discovery.internal

Source Code of com.sun.jini.discovery.internal.EndpointBasedServer$PrearrangedServerSocketFactory

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.sun.jini.discovery.internal;

import com.sun.jini.discovery.ClientSubjectChecker;
import com.sun.jini.discovery.DiscoveryProtocolException;
import com.sun.jini.discovery.UnicastDiscoveryServer;
import com.sun.jini.discovery.UnicastResponse;
import com.sun.jini.jeri.internal.connection.ServerConnManager;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import javax.net.ServerSocketFactory;
import javax.security.auth.Subject;
import net.jini.core.constraint.InvocationConstraints;
import net.jini.io.UnsupportedConstraintException;
import net.jini.io.context.ClientSubject;
import net.jini.jeri.InboundRequest;
import net.jini.jeri.RequestDispatcher;
import net.jini.jeri.ServerEndpoint;
import net.jini.jeri.ServerEndpoint.ListenContext;
import net.jini.jeri.ServerEndpoint.ListenCookie;
import net.jini.jeri.ServerEndpoint.ListenEndpoint;
import net.jini.jeri.ServerEndpoint.ListenHandle;
import net.jini.jeri.connection.InboundRequestHandle;
import net.jini.jeri.connection.ServerConnection;

/**
* Provides an abstract server endpoint-based UnicastDiscoveryServer
* implementation, which serves as a superclass for server-side providers for
* the net.jini.discovery.ssl and net.jini.discovery.kerberos unicast discovery
* formats.
*/
public abstract class EndpointBasedServer
    extends EndpointBasedProvider implements UnicastDiscoveryServer
{
    /**
     * Constructs instance with the given format name and object providing
     * access to non-public endpoint operations.
     */
    protected EndpointBasedServer(String formatName,
          EndpointInternals endpointInternals)
    {
  super(formatName, endpointInternals);
    }

    // documentation inherited from UnicastDiscoveryServer
    public void checkUnicastDiscoveryConstraints(
              InvocationConstraints constraints)
  throws UnsupportedConstraintException
    {
  if (constraints == null) {
      constraints = InvocationConstraints.EMPTY;
  }
  ServerEndpoint ep = getServerEndpoint(null);
  checkIntegrity(ep.checkConstraints(constraints));
    }

    // documentation inherited from UnicastDiscoveryServer
    public void handleUnicastDiscovery(UnicastResponse response,
               Socket socket,
               InvocationConstraints constraints,
               ClientSubjectChecker checker,
               Collection context,
               ByteBuffer received,
               ByteBuffer sent)
  throws IOException
    {
  if (response == null || socket == null ||
      received == null || sent == null)
  {
      throw new NullPointerException();
  }
  if (constraints == null) {
      constraints = InvocationConstraints.EMPTY;
  }
  ServerEndpoint ep =
      getServerEndpoint(new PrearrangedServerSocketFactory(socket));
  ServerConnManagerImpl mgr = new ServerConnManagerImpl();
  endpointInternals.setServerConnManager(ep, mgr);

  ListenContextImpl lc = new ListenContextImpl();
  ep.enumerateListenEndpoints(lc);
  ServerConnection conn = mgr.getServerConnection();
  try {
      InputStream in = new BufferedInputStream(conn.getInputStream());
      OutputStream out = new BufferedOutputStream(conn.getOutputStream());
      InboundRequestHandle handle = conn.processRequestData(in, out);
      conn.checkPermissions(handle);
      checkIntegrity(conn.checkConstraints(handle, constraints));
      if (checker != null) {
    checker.checkClientSubject(getClientSubject(conn, handle));
      }

      byte[] hash = calcHandshakeHash(received, sent);
      byte[] clientHash = new byte[hash.length];
      new DataInputStream(in).readFully(clientHash);
      if (!Arrays.equals(clientHash, hash)) {
    throw new DiscoveryProtocolException(
        "handshake hash mismatch");
      }

      Plaintext.writeUnicastResponse(out, response, context);
      out.flush();
  } finally {
      conn.close();
      lc.getListenHandle().close();
  }
    }

    /**
     * Returns a server endpoint which uses the given server socket factory, if
     * non-null.  Other parameters of the server endpoint, such as the listen
     * port, are irrelevant from the standpoint of this class and can be chosen
     * arbitrarily.
     */
    protected abstract ServerEndpoint getServerEndpoint(
            ServerSocketFactory factory)
  throws UnsupportedConstraintException;

    /**
     * Returns the subject that the client of the given connection has
     * authenticated as, or null if the client is not authenticated.
     */
    private static Subject getClientSubject(ServerConnection connection,
              InboundRequestHandle handle)
    {
  Collection ctx = new ArrayList();
  connection.populateContext(handle, ctx);
  for (Iterator i = ctx.iterator(); i.hasNext(); ) {
      Object obj = i.next();
      if (obj instanceof ClientSubject) {
    return ((ClientSubject) obj).getClientSubject();
      }
  }
  return null;
    }

    /**
     * Server connection manager that stores the connection it is given to
     * handle.
     */
    private static class ServerConnManagerImpl implements ServerConnManager {

  private ServerConnection conn = null;

  ServerConnManagerImpl() {
  }

  public synchronized void handleConnection(ServerConnection conn,
              RequestDispatcher disp)
  {
      if (conn == null || disp == null) {
    throw new NullPointerException();
      }
      this.conn = conn;
      notifyAll();
  }

  synchronized ServerConnection getServerConnection() {
      while (conn == null) {
    try { wait(); } catch (InterruptedException e) {}
      }
      return conn;
  }
    }

    /**
     * Listen context that listens on the endpoint it is given, and stores the
     * resulting handle.
     */
    private static class ListenContextImpl implements ListenContext {

  private ListenHandle handle = null;

  public ListenCookie addListenEndpoint(ListenEndpoint endpoint)
      throws IOException
  {
      handle = endpoint.listen(new RequestDispatcher() {
    public void dispatch(InboundRequest req) {
        throw new AssertionError("dispatch should not occur");
    }
      });
      return handle.getCookie();
  }

  ListenHandle getListenHandle() {
      return handle;
  }
    }

    /**
     * Server socket that returns a prearranged socket once from its accept
     * method, and then blocks on subsequent calls to accept until closed.
     */
    private static class PrearrangedServerSocket extends ServerSocket {

  private Socket socket;
  private boolean closed = false;

  PrearrangedServerSocket(Socket socket) throws IOException {
      this.socket = socket;
  }

  public synchronized Socket accept() throws IOException {
      if (!closed && socket != null) {
    Socket s = socket;
    socket = null;
    return s;
      }
      while (!closed) {
    try { wait(); } catch (InterruptedException e) {}
      }
      throw new SocketException("socket closed");
  }

  public int getLocalPort() {
      /*
       * Although this port number is bogus, it has to be plausible,
       * otherwise calling enumerateListenEndpoints on the server
       * endpoint will fail since an endpoint cannot be created.
       */
      return 1;
  }

  public synchronized void close() throws IOException {
      if (!closed) {
    closed = true;
    notifyAll();
      }
  }
    }

    /**
     * Server socket factory that returns a PrearrangedServerSocket for a
     * prearranged socket.
     */
    private static class PrearrangedServerSocketFactory
  extends ServerSocketFactory
    {
  private final ServerSocket ssocket;

  PrearrangedServerSocketFactory(Socket socket) throws IOException {
      ssocket = new PrearrangedServerSocket(socket);
  }

  public ServerSocket createServerSocket() throws IOException {
      return ssocket;
  }

  public ServerSocket createServerSocket(int port) throws IOException {
      return ssocket;
  }

  public ServerSocket createServerSocket(int port, int backlog)
      throws IOException
  {
      return ssocket;
  }

  public ServerSocket createServerSocket(int port,
                 int backlog,
                 InetAddress addr)
      throws IOException
  {
      return ssocket;
  }
    }
}
TOP

Related Classes of com.sun.jini.discovery.internal.EndpointBasedServer$PrearrangedServerSocketFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.