serversocketprotocol.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 533 行 · 第 1/2 页

C
533
字号
/* * * * 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. */#include <stdio.h>#include <kni.h>#include <sni.h>#include <commonKNIMacros.h>#include <ROMStructs.h>#include <midp_libc_ext.h>#include <kni_globals.h>#include <midpError.h>#include <pcsl_network.h>#include <pcsl_serversocket.h>#include <push_server_resource_mgmt.h>#include <midp_properties_port.h>#include <midp_logging.h>#include <midpResourceLimit.h>#include <midp_thread.h>#include <suitestore_common.h>/** * @file * * The default implementation of the native functions that are needed * for supporting the "serversocket:" Generic Connection protocol. *//* Macro to retrieve C structure representation of an Object */typedef struct Java_com_sun_midp_io_j2me_serversocket_Socket _serversocketProtocol;#define getMidpServerSocketProtocolPtr(handle) (unhand(_serversocketProtocol,(handle)))/* Macro to retrieve C structure representation of an Object */typedef struct Java_com_sun_midp_io_j2me_socket_Protocol _socketProtocol;#define getMidpSocketProtocolPtr(handle) (unhand(_socketProtocol,(handle)))/** * Opens a server socket connection on the given port.  If successful, * stores a handle directly into the nativeHandle field.  If unsuccessful, * throws an exception. * <p> * Java declaration: * <pre> *     open0(I[B)V * </pre> * * @param port       TCP port to listen for connections on * @param suiteId    ID of current midlet suite, or null if there *                   is no current suite * * @exception IOException  if some other kind of I/O error occurs * or if reserved by another suite */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_io_j2me_serversocket_Socket_open0(void) {    int port;    jboolean tryOpen;    SuiteIdType suiteId;    void *pcslHandle = INVALID_HANDLE;    int status = PCSL_NET_INVALID;    KNI_StartHandles(1);    KNI_DeclareHandle(thisObject);    KNI_GetThisPointer(thisObject);    port = (int)KNI_GetParameterAsInt(1);    suiteId = KNI_GetParameterAsInt(2);    getMidpServerSocketProtocolPtr(thisObject)->nativeHandle = (jint)INVALID_HANDLE;    /*     * Determine whether to try opening a socket ourselves, or whether push     * has made a determination for us.     */    if (suiteId == UNUSED_SUITE_ID) {        tryOpen = KNI_TRUE;    } else {        int pushReturn;        pushReturn = pushcheckout("socket", port,                                  (char*)midp_suiteid2chars(suiteId));                                          /*         * pushcheckout() returns -1 if the handle wasn't found, -2 if it's         * already in use by another suite, otherwise a valid checked-out         * handle.         */        if (pushReturn == -1) {            tryOpen = KNI_TRUE;        } else if (pushReturn == -2) {            KNI_ThrowNew(midpIOException, "socket already in use");            tryOpen = KNI_FALSE;        } else {            /* IMPL NOTE: how to do resource accounting for this case? */            getMidpServerSocketProtocolPtr(thisObject)->nativeHandle =                pushReturn;            tryOpen = KNI_FALSE;        }    }    /*     * At this point either tryOpen is true; or it's false and we have a valid     * handle or we've thrown an exception.     */    if (tryOpen) {        if (midpCheckResourceLimit(RSC_TYPE_TCP_SER, 1) == 0) {            REPORT_INFO(LC_PROTOCOL,                        "Resource limit exceeded for TCP server sockets");            KNI_ThrowNew(midpIOException,                         "Resource limit exceeded for TCP server sockets");        } else {            status = pcsl_serversocket_open(                port, &pcslHandle);            if (status == PCSL_NET_SUCCESS) {                getMidpServerSocketProtocolPtr(thisObject)->nativeHandle = (jint)pcslHandle;                REPORT_INFO2(LC_PROTOCOL,                             "serversocket::open port = %d handle = %d\n",                             port, pcslHandle);                if (midpIncResourceCount(RSC_TYPE_TCP_SER, 1) == 0) {                    REPORT_INFO(LC_PROTOCOL,                                "TCP Server: Resource limit update error");                }            } else if (status == PCSL_NET_IOERROR) {                midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE,                              "IOError in serversocket::open = %d\n",                              pcsl_network_error(pcslHandle));                REPORT_INFO1(LC_PROTOCOL, "%s\n", gKNIBuffer);                KNI_ThrowNew(midpIOException, gKNIBuffer);            } else {                REPORT_INFO(LC_PROTOCOL, "Unknown error during serversocket::open");                KNI_ThrowNew(midpIOException, NULL);            }        }    }    KNI_EndHandles();    KNI_ReturnVoid();}/** * Closes the connection. * <p> * Java declaration: * <pre> *     close0(V)V * </pre> * * @exception  IOException  if an I/O error occurs when closing the *                          connection */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_io_j2me_serversocket_Socket_close0(void) {    int serverSocketHandle;    int status = PCSL_NET_INVALID;    void* context = NULL;    MidpReentryData* info;    KNI_StartHandles(1);    KNI_DeclareHandle(thisObject);    KNI_GetThisPointer(thisObject);    info = (MidpReentryData*)SNI_GetReentryData(NULL);    if (info == NULL) {        /* initial invocation */        serverSocketHandle =            getMidpServerSocketProtocolPtr(thisObject)->nativeHandle;        /*         * If serverSocketHandle is invalid, the socket has already been closed,         * so per specification we do nothing and return.         */        if (serverSocketHandle == (int)INVALID_HANDLE) {            REPORT_INFO(LC_PROTOCOL, "serversocket::close Invalid handle\n");        } else {            /*             * The pushcheckin() function returns -1 on error.  If pushcheckin()             * was successful, socket was checked back into the push registry, and             * we needn't do anything further. Otherwise, we need to perform close             * processing ourselves.             *             * IMPL NOTE: how to do resource accounting for the push case?             */            if (pushcheckin(serverSocketHandle) == -1) {                status = pcsl_socket_close_start((void*)serverSocketHandle,                                                 &context);                /* Server socket should be monitored for read events only */                midp_thread_signal(NETWORK_READ_SIGNAL, serverSocketHandle, 0);            }            getMidpServerSocketProtocolPtr(thisObject)->nativeHandle =                (jint)INVALID_HANDLE;        }    } else {        /* reinvocation */        serverSocketHandle = info->descriptor;        context = info->pResult;        status = pcsl_socket_close_finish((void*)serverSocketHandle, context);    }    REPORT_INFO1(LC_PROTOCOL, "serversocket::close handle=%d\n", serverSocketHandle);    if (serverSocketHandle != (int)INVALID_HANDLE) {        if (status == PCSL_NET_SUCCESS) {            if (midpDecResourceCount(RSC_TYPE_TCP_SER, 1) == 0) {                REPORT_INFO(LC_PROTOCOL,                            "TCP Server: Resource limit update error");            }        } else if (status == PCSL_NET_WOULDBLOCK) {            REPORT_INFO1(LC_PROTOCOL, "serversocket::close = 0x%x blocked\n",                         serverSocketHandle);            /* IMPL NOTE: is this the right signal? */            midp_thread_wait(NETWORK_EXCEPTION_SIGNAL,                             serverSocketHandle, context);        } else {            midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE,                          "IOError in serversocket::close = %d\n",                          pcsl_network_error((void*)serverSocketHandle));            REPORT_INFO1(LC_PROTOCOL, "%s", gKNIBuffer);            KNI_ThrowNew(midpIOException, gKNIBuffer);        }    }    KNI_EndHandles();    KNI_ReturnVoid();}/** * Polls a server socket for an incoming TCP connection. If there is an * incoming connection, it is accepted and this method returns true. If * there is no incoming connection, this method returns false immediately. * This requires callers to call this method repeatedly (often in a * busy-wait loop) while awaiting an incoming connection. * <p> * The 'con' parameter must be a freshly created client socket connection * object.  If an incoming connection is accepted, the socket handle for * the newly accepted connection is stored into this object directly from * native code. This technique ensures that the acceptance of a new * connection and the storing of the native handle are performed

⌨️ 快捷键说明

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