FileDocCategorySizeDatePackage
Socket.javaAPI DocJ2ME MIDP 2.06566Thu Nov 07 12:02:22 GMT 2002com.sun.midp.io.j2me.serversocket

Socket.java

/*
 * @(#)Socket.java	1.15 02/10/14 @(#)
 *
 * Copyright (c) 1999-2002 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL
 * Use is subject to license terms.
 */

package com.sun.midp.io.j2me.serversocket;

import java.io.*;

import javax.microedition.io.*;

import com.sun.cldc.io.ConnectionBaseInterface;
import com.sun.cldc.io.GeneralBase;

import com.sun.midp.io.*;

import com.sun.midp.midlet.*;

import com.sun.midp.security.*;

/*
 * Note: Since this class references the TCP socket protocol class that
 * extends the NetworkConnectionBaseClass. The native networking will be
 * initialized when this class loads if needed without extending
 * NetworkConnectionBase.
 */
/**
 * StreamConnectionNotifier to the TCP Server Socket API.
 *
 * @author  Nik Shaylor
 * @version 1.0 10/08/99
 */
public class Socket implements ServerSocketConnection {

    /** Socket object used by native code, for now must be the first field. */
    private int handle;

    /** Flag to indicate connection is currently open. */
    boolean connectionOpen = false;

    /**
     * Opens a port to listen on.
     *
     * @param port       TCP to listen on
     *
     * @exception IOException  if some other kind of I/O error occurs
     */
    public void open(int port) throws IOException {
        Scheduler scheduler = Scheduler.getScheduler();
        MIDletSuite midletSuite = scheduler.getMIDletSuite();
	String root = midletSuite.getStorageName();

        byte[] asciiStorage = Util.toCString(root);

        open0(port > 0 ? port : 0, asciiStorage);
	connectionOpen = true;

        port = getLocalPort();

        // check permission after the open so we can get the assigned port
        try {
            // When asking permission use Internet protocol name.
            midletSuite.checkForPermission(Permissions.TCP_SERVER,
                "TCP://:" + port);
        } catch (SecurityException e) {
            close();
            throw e;
        } catch (InterruptedException ie) {
            throw new InterruptedIOException(
                "Interrupted while trying to ask the user permission");
        }

        registerCleanup();
    }

    /**
     * Checks if the connection is open.
     *
     * @exception  IOException  is thrown, if the stream is not open
     */
    void ensureOpen() throws IOException {
        if (!connectionOpen) {
            throw new IOException("Connection closed");
        }
    }

    /**
     * Opens a native socket and put its handle in the handle field.
     * <p>
     * Called by socket Protocol class after it parses a given URL and finds
     * no host.
     *
     * @param port       TCP port to listen for connections on
     * @param storage    name of current suite storage
     *
     * @exception IOException  if some other kind of I/O error occurs
     *  or if reserved by another suite
     */
    public native void open0(int port, byte[] storage) throws IOException;

    /**
     * Returns a connection that represents a server side
     * socket connection.
     * <p>
     * Polling the native code is done here to allow for simple
     * asynchronous native code to be written. Not all implementations
     * work this way (they block in the native code) but the same
     * Java code works for both.
     *
     * @return     a socket to communicate with a client.
     *
     * @exception  IOException  if an I/O error occurs when creating the
     *                          input stream
     */
    synchronized public StreamConnection acceptAndOpen()
        throws IOException {

        com.sun.midp.io.j2me.socket.Protocol con;

	ensureOpen();

        while (true) {
            int handle = accept();
            if (handle >= 0) {
                con = new com.sun.midp.io.j2me.socket.Protocol();
                con.open(handle);
                break;
            }

            /* Wait a while for I/O to become ready */
            GeneralBase.iowait(); 
        }

        return con;
    }

    /**
     * Gets the local address to which the socket is bound.
     *
     * <P>The host address(IP number) that can be used to connect to this
     * end of the socket connection from an external system. 
     * Since IP addresses may be dynamically assigned, a remote application
     * will need to be robust in the face of IP number reasssignment.</P>
     * <P> The local hostname (if available) can be accessed from 
     * <code> System.getProperty("microedition.hostname")</code>
     * </P>
     *
     * @return the local address to which the socket is bound
     * @exception  IOException  if the connection was closed
     * @see ServerSocketConnection
     */
    public String getLocalAddress() throws IOException {
	ensureOpen();
	return getLocalAddress0();
    }

    /**
     * Returns the local port to which this socket is bound.
     *
     * @return the local port number to which this socket is connected
     * @exception  IOException  if the connection was closed
     * @see ServerSocketConnection
     */
    public int getLocalPort() throws IOException {
	ensureOpen();
	return getLocalPort0();
    }

    /**
     * Closes the connection, accesses the handle field.
     *
     * @exception  IOException  if an I/O error occurs when closing the
     *                          connection
     */
    public void close() throws IOException {
	if (connectionOpen) {
	    close0();
	    connectionOpen = false;
	}
    }

    /**
     * Accepts a TCP connection socket handle to a client,
     * accesses the handle field.
     *
     * @return TCP connection socket handle
     *
     * @exception IOException  If some other kind of I/O error occurs.
     */
    private native int accept() throws IOException;

    /**
     * Closes the connection, accesses the handle field.
     *
     * @exception  IOException  if an I/O error occurs when closing the
     *                          connection
     */
    public native void close0() throws IOException;

    /**
     * Registers with the native cleanup code, accesses the handle field.
     */
    private native void registerCleanup();

    /**
     * Native finalizer
     */
    private native void finalize();

    /**
     * Gets the requested printable IP number.
     *
     * @return     the IP address as a String
     */
    private native String getLocalAddress0();

    /**
     * Returns the local port to which this socket is bound.
     *
     * @return the local port number to which this socket is connected
     */
    private native int getLocalPort0();
}