📄 protocol.java
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */package com.sun.midp.io.j2me.socket;import java.io.IOException;import java.io.InterruptedIOException;import javax.microedition.io.Connection;import javax.microedition.io.Connector;import javax.microedition.io.SocketConnection;import javax.microedition.io.ConnectionNotFoundException;import com.sun.j2me.security.AccessController;import com.sun.j2me.security.InterruptedSecurityException;import com.sun.midp.io.NetworkConnectionBase;import com.sun.midp.io.HttpUrl;import com.sun.midp.io.Util;import com.sun.midp.main.Configuration;import com.sun.midp.security.Permissions;import com.sun.midp.security.SecurityToken;import com.sun.midp.security.ImplicitlyTrustedClass;import com.sun.midp.security.SecurityInitializer;import com.sun.midp.suspend.NetworkSubsystem;import com.sun.midp.suspend.Subsystem;import com.sun.midp.suspend.StateTransitionException;/** Connection to the J2ME socket API. */public class Protocol extends NetworkConnectionBase implements SocketConnection, Subsystem { /** TCP client permission name. */ private static final String CLIENT_PERMISSION_NAME = "javax.microedition.io.Connector.socket"; /** Class registered in SecurityInitializer. */ private static class SecurityTrusted implements ImplicitlyTrustedClass {} /**Security token for provileged access to internal API's. */ private static SecurityToken classSecurityToken = SecurityInitializer.requestToken(new SecurityTrusted()); /** Size of the read ahead buffer, default is no buffering. */ private static int bufferSize; /** * Handle to native socket object. This is set and get only by * native code. */ private int handle = -1; /** Lock object for reading from the socket */ private final Object readerLock = new Object(); /** Lock object for writing to the socket */ private final Object writerLock = new Object(); /** * Class initializer */ static { /* See if a read ahead / write behind buffer size has been specified */ bufferSize = Configuration.getNonNegativeIntProperty( "com.sun.midp.io.j2me.socket.buffersize", bufferSize); } /** Hostname */ private String host; /** TCP port */ private int port; /** Shutdown output flag, true if output has been shutdown. */ private boolean outputShutdown; /** True if the owner of this connection is trusted. */ private boolean ownerTrusted; /** Byte array that represents the IP address */ byte[] ipBytes = new byte[4]; /** Creates a buffered TCP client connection. */ public Protocol() { // use the default buffer size super(bufferSize); } /** * Open a client or server socket connection. * <p> * The name string for this protocol should be: * "socket://<name or IP number>:<port number> * <p> * We allow "socket://:nnnn" to mean an inbound server socket connection. * * @param name the target for the connection * @param mode I/O access mode * @param timeouts a flag to indicate that the caller wants * timeout exceptions * * @return client or server TCP socket connection * * @exception IOException if an I/O error occurs. * @exception ConnectionNotFoundException if the host cannot be connected * to * @exception IllegalArgumentException if the name is malformed */ public Connection openPrim(String name, int mode, boolean timeouts) throws IOException { return open(null, name, mode); } /** * Make sure the calling call has the com.sun.midp permission set to * "allowed" and open a connection to a target. * Used by internal classes only so they can do work on behalf of suites * that do not have the directly use this protocol. * * @param token security token of the calling class * @param name URL for the connection, without the * without the protocol part * * @return this Connection object * * @exception IllegalArgumentException If a parameter is invalid. * @exception ConnectionNotFoundException If the connection cannot * be found. * @exception IOException If some other kind of I/O error occurs. */ public Connection openPrim(SecurityToken token, String name) throws IOException { return open(token, name, Connector.READ_WRITE); } /** * Open a client or server socket connection. * <p> * The name string for this protocol should be: * "socket://<name or IP number>:<port number> * <p> * We allow "socket://:nnnn" to mean an inbound server socket connection. * * @param token security token of the calling class * @param name the target for the connection * @param mode I/O access mode * * @return client or server TCP socket connection * * @exception IOException if an I/O error occurs. * @exception ConnectionNotFoundException if the host cannot be connected * to * @exception IllegalArgumentException if the name is malformed */ private Connection open(SecurityToken token, String name, int mode) throws IOException { HttpUrl url; ServerSocket serverSocket; if (name.charAt(0) != '/' || name.charAt(1) != '/') { throw new IllegalArgumentException( "Protocol must start with \"//\""); } url = new HttpUrl("socket", name); // parse name into host and port /* * Since we reused the HttpUrl parser, we must make sure that * there was nothing past the authority in the URL. */ if (url.path != null || url.query != null || url.fragment != null) { throw new IllegalArgumentException("Malformed address"); } NetworkSubsystem.getInstance(classSecurityToken).ensureActive(); host = url.host; port = url.port; /* * If 'host' == null then we are a server endpoint at * port 'port'. */ if (host != null) { checkForPermission(name, token); initStreamConnection(mode); // this will call the connect method which uses the host and port connect(); return this; } // We allow "socket://:nnnn" to mean an inbound TCP server socket. try { serverSocket = (ServerSocket)Class.forName( "com.sun.midp.io.j2me.serversocket.Socket").newInstance(); } catch (Exception e) { throw new ConnectionNotFoundException("Connection not supported"); } serverSocket.open(port, token); return (Connection)serverSocket; } /** * Connect to a server. * @exception IOException if an I/O error occurs. * @exception ConnectionNotFoundException if the host cannot be connected * to * @exception IllegalStateException if there is no hostname * @exception IllegalArgumentException if the name is malformed */ private void connect() throws IOException { byte[] szHost; byte[] szIpBytes = null; int result; // Max length of IPv4 address is 4 // IMPL NOTE: IPv6 needs to have an address of length =16 if (handle != -1) { // This method should only be called once. // IMPL NOTE: should use something other than handle for this check throw new RuntimeException("Illegal state for operation"); } /* * The host and port were set by overriding the openPrim method of * our super class. */ if (port < 0) { throw new IllegalArgumentException("Missing port number"); } result = getIpNumber0(host, ipBytes); if (result == -1) { throw new ConnectionNotFoundException("Could not resolve hostname"); } /* * JTWI security check, untrusted MIDlets cannot open port 80 or * 8080 or 443. This is so they cannot perform HTTP and HTTPS * requests on server without using the system code. The * system HTTP code will add a "UNTRUSTED/1.0" to the user agent * field for untrusted MIDlets. */ if (!ownerTrusted && (port == 80 || port == 8080 || port == 443)) { throw new SecurityException( "Target port denied to untrusted applications"); } open0(ipBytes, port); NetworkSubsystem.getInstance(classSecurityToken). registerSubsystem(this); } /** * Create a Java connection object from an open TCP socket. * This method is only used by com.sun.midp.io.j2me.serversocket.Socket; * * @param token either <code>null</code> for normal processing or * a security token with special privileges * * @exception IOException if an I/O error occurs */ public void open(SecurityToken token) throws IOException { try { // The connection needs to be open to call getAddress. connectionOpen = true; checkForPermission(getAddress(), token); } catch (Exception e) { connectionOpen = false; try { close0(); } catch (IOException ioe) { // ignore } if (e instanceof IOException) { throw (IOException)e; } throw (RuntimeException)e; } } /** * Check for the required permission. * * @param name name of resource to insert into the permission question * @param token either security token with special privileges if pecified * by caller or <code>null</code> * * @exception InterruptedIOException if another thread interrupts the * calling thread while this method is waiting to preempt the * display. */ private void checkForPermission(String name, SecurityToken token) throws InterruptedIOException { if (token != null) { token.checkIfPermissionAllowed(CLIENT_PERMISSION_NAME); /* Any caller with the com.sun.midp permission is trusted. */ ownerTrusted = true; return; } name = "TCP" + ":" + name; try { AccessController.checkPermission(CLIENT_PERMISSION_NAME, name); } catch (InterruptedSecurityException ise) { throw new InterruptedIOException( "Interrupted while trying to ask the user permission"); } try { AccessController. checkPermission(AccessController.TRUSTED_APP_PERMISSION_NAME); ownerTrusted = true; } catch (SecurityException se) { ownerTrusted = false; } } /** * Notify blocked Java threads waiting for an input data * that all InputStream instances of the connection are closed */ protected void notifyClosedInput() { if (iStreams == 0) { notifyClosedInput0(); } }; /** * Notify blocked Java threads trying to output data * that all OutputStream instances of the connection are closed */ protected void notifyClosedOutput() { if (iStreams == 0) { notifyClosedOutput0(); } } /** * Wake up Java threads waiting for input data on the connection * to let them know all the input streams have been closed */ private native void notifyClosedInput0(); /** * Wake up Java threads waiting to output data over the connection * to let them know all the output streams have been closed */ private native void notifyClosedOutput0(); /** * Disconnect from the server. * * @exception IOException if an I/O error occurs. */ public void disconnect() throws IOException { /* * Only shutdown or close of the sending side of a connection is * defined in the TCP spec. * * The receiver can only abort (reset) the entire connection to stop * the a sender from sending. InputStream close already causes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -