datagramprotocol.c

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

C
814
字号
/* * * * 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 <anc_indicators.h>#include <midpError.h>#include <push_server_resource_mgmt.h>#include <midp_logging.h>#include <midpResourceLimit.h>#include <midpMalloc.h>#include <string.h>#include <pcsl_network.h>#include <midp_thread.h>#include <midp_libc_ext.h>#include <kni_globals.h>#include <pcsl_memory.h>#include <suitestore_common.h>#include <midpUtilKni.h>/** * @file * * The default implementation of the native functions that are needed * for supporting the "datagram:" Generic Connection protocol. *//* Macro to retrieve C structure representation of an Object */typedef struct Java_com_sun_midp_io_j2me_datagram_Protocol _datagramProtocol;#define getMidpDatagramProtocolPtr(handle) (unhand(_datagramProtocol,(handle)))/** * Opens a datagram connection on the given port. * <p> * Java declaration: * <pre> *     open0(I[B)V * </pre> * * @param port port to listen on, or 0 to have one selected * @param suiteId the ID of the current MIDlet suite */KNIEXPORT KNI_RETURNTYPE_VOIDJava_com_sun_midp_io_j2me_datagram_Protocol_open0(void) {    int port;    SuiteIdType suiteId;    jboolean tryOpen = KNI_TRUE;    KNI_StartHandles(1);    KNI_DeclareHandle(thisObject);    KNI_GetThisPointer(thisObject);    port = (int)KNI_GetParameterAsInt(1);    suiteId = KNI_GetParameterAsInt(2);    if (getMidpDatagramProtocolPtr(thisObject)->nativeHandle            != (jint)INVALID_HANDLE) {        KNI_ThrowNew(midpIOException, "already open");        tryOpen = KNI_FALSE;    }    if (tryOpen) {        int pushReturn;        pushReturn = pushcheckout("datagram", 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) {            /* leave tryOpen == KNI_TRUE and try again below */        } else if (pushReturn == -2) {            KNI_ThrowNew(midpIOException, "already in use");            tryOpen = KNI_FALSE;        } else {            /* IMPL NOTE: need to do resource accounting for this case */            getMidpDatagramProtocolPtr(thisObject)->nativeHandle                = (jint)pushReturn;            tryOpen = KNI_FALSE;        }    }    if (tryOpen) {        if (midpCheckResourceLimit(RSC_TYPE_UDP, 1) == 0) {            KNI_ThrowNew(midpIOException, "resource limit exceeded");        } else {            MidpReentryData* info;            int status;            void *socketHandle;            void *context;            info = (MidpReentryData*)SNI_GetReentryData(NULL);            if (info == NULL) {                /* initial invocation */                ANC_INC_NETWORK_INDICATOR;                status = pcsl_datagram_open_start(port, &socketHandle,                    &context);            } else {                /* reinvocation */                socketHandle = (void *)info->descriptor;                context = info->pResult;                status = pcsl_datagram_open_finish(socketHandle, context);            }            if (status == PCSL_NET_SUCCESS) {                if (midpIncResourceCount(RSC_TYPE_UDP, 1) == 0) {                    REPORT_INFO(LC_PROTOCOL,                        "Datagrams: resource limit update error");                }                getMidpDatagramProtocolPtr(thisObject)->nativeHandle                    = (jint)socketHandle;                ANC_DEC_NETWORK_INDICATOR;            } else if (status == PCSL_NET_WOULDBLOCK) {                midp_thread_wait(NETWORK_WRITE_SIGNAL, (int)socketHandle,                    context);            } else {                /* status == PCSL_NET_IOERROR */                midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE,                    "error code %d", pcsl_network_error(socketHandle));                REPORT_INFO1(LC_PROTOCOL, "datagram::open0 %s", gKNIBuffer);                KNI_ThrowNew(midpIOException, gKNIBuffer);                ANC_DEC_NETWORK_INDICATOR;            }        }    }    KNI_EndHandles();    KNI_ReturnVoid();}/** * Sends a datagram. * <p> * Java declaration: * <pre> *     send0(II[BII)I * </pre> * * @param ipNumber raw IPv4 address of the remote host * @param port UDP port of the remote host * @param buf the data buffer to send * @param off the offset into the data buffer * @param len the length of the data in the buffer * @return number of bytes sent */KNIEXPORT KNI_RETURNTYPE_INTJava_com_sun_midp_io_j2me_datagram_Protocol_send0(void) {    int ipAddress;    int port;    int offset;    int length;    int bytesSent = 0;    void *socketHandle;    MidpReentryData* info;    unsigned char ipBytes[MAX_ADDR_LENGTH];    KNI_StartHandles(2);    KNI_DeclareHandle(bufferObject);    KNI_DeclareHandle(thisObject);    KNI_GetThisPointer(thisObject);    ipAddress = (int)KNI_GetParameterAsInt(1);    port      = (int)KNI_GetParameterAsInt(2);    KNI_GetParameterAsObject(3, bufferObject);    offset    = (int)KNI_GetParameterAsInt(4);    length    = (int)KNI_GetParameterAsInt(5);    socketHandle =        (void *)getMidpDatagramProtocolPtr(thisObject)->nativeHandle;    REPORT_INFO5(LC_PROTOCOL,        "datagram::send0 off=%d len=%d port=%d ip=0x%x handle=0x%x",        offset, length, port, ipAddress, (int)socketHandle);    /* Convert ipAddress(integer) to ipBytes */    memcpy(ipBytes, &ipAddress, sizeof(ipBytes));    info = (MidpReentryData*)SNI_GetReentryData(NULL);    if (socketHandle != INVALID_HANDLE) {        int status;        void *context;        if (info == NULL) {            /* initial invocation */            ANC_INC_NETWORK_INDICATOR;            SNI_BEGIN_RAW_POINTERS;            status = pcsl_datagram_write_start(                socketHandle, ipBytes, port,                (char*)&(JavaByteArray(bufferObject)[offset]),                length, &bytesSent, &context);            SNI_END_RAW_POINTERS;        } else {            /* reinvocation */            if ((void *)info->descriptor != socketHandle) {                REPORT_CRIT2(LC_PROTOCOL,                    "datagram::send0 handle mismatch 0x%x != 0x%x\n",                        socketHandle, info->descriptor);            }	    context = info->pResult;            SNI_BEGIN_RAW_POINTERS;	    status = pcsl_datagram_write_finish(                socketHandle, ipBytes, port,                (char*)&(JavaByteArray(bufferObject)[offset]),                length, &bytesSent, context);            SNI_END_RAW_POINTERS;        }        if (status == PCSL_NET_SUCCESS) {            ANC_DEC_NETWORK_INDICATOR;        } else if (status == PCSL_NET_WOULDBLOCK) {            midp_thread_wait(NETWORK_WRITE_SIGNAL, (int)socketHandle, context);        } else if (status == PCSL_NET_INTERRUPTED) {            KNI_ThrowNew(midpInterruptedIOException, NULL);            ANC_DEC_NETWORK_INDICATOR;        } else {            /* status == PCSL_NET_IOERROR */            midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE,                "error code %d", pcsl_network_error(socketHandle));            KNI_ThrowNew(midpIOException, gKNIBuffer);            ANC_DEC_NETWORK_INDICATOR;        }    } else {        if (info == NULL) {            /* initial invocation */            KNI_ThrowNew(midpIOException, "socket closed");        } else {            /* reinvocation */            KNI_ThrowNew(midpInterruptedIOException, NULL);            ANC_DEC_NETWORK_INDICATOR;        }    }    KNI_EndHandles();    KNI_ReturnInt((jint)bytesSent);}/** * Packs an IP address, port number, and the number of bytes received into a * jlong value suitable for returning from the receive0 native method. */static jlongpack_recv_retval(int ipAddress, int port, int bytesReceived) {    return        (((jlong)ipAddress) << 32) +        (unsigned)((port & 0xFFFF) << 16) +        (bytesReceived & 0xFFFF);}/** * Receives a datagram. * <p> * Java declaration: * <pre> *     receive0([BII)J * </pre> * * @param buf the data buffer * @param off the offset into the data buffer * @param len the length of the data in the buffer * @return The upper 32 bits contain the raw IPv4 address of the *         host the datagram was received from. The next 16 bits *         contain the port. The last 16 bits contain the number *         of bytes received. */KNIEXPORT KNI_RETURNTYPE_LONGJava_com_sun_midp_io_j2me_datagram_Protocol_receive0(void) {    int offset;    int length;    void *socketHandle;    jlong lres = 0;    MidpReentryData* info;    KNI_StartHandles(2);    KNI_DeclareHandle(bufferObject);    KNI_DeclareHandle(thisObject);    KNI_GetThisPointer(thisObject);    KNI_GetParameterAsObject(1, bufferObject);    offset = (int)KNI_GetParameterAsInt(2);    length = (int)KNI_GetParameterAsInt(3);    socketHandle =        (void *)getMidpDatagramProtocolPtr(thisObject)->nativeHandle;    info = (MidpReentryData*)SNI_GetReentryData(NULL);    REPORT_INFO3(LC_PROTOCOL,        "datagram::receive0 off=%d len=%d handle=0x%x",	offset, length, (int)socketHandle);    if (socketHandle != INVALID_HANDLE) {        int ipAddress;        int port;        int bytesReceived;        /*         * Check the push cache for a waiting datagram.         *         * If pushgetcachedpacket() returns -1 [IMPL NOTE: the code checks for         * less than zero; which is correct?], we need to read a datagram         * ourselves. Otherwise, pushgetcachedpacket() has returned a waiting         * datagram and has set ipAddress and port to valid values.         */        SNI_BEGIN_RAW_POINTERS;        bytesReceived = pushgetcachedpacket((int)socketHandle, &ipAddress,            &port, (char*)&(JavaByteArray(bufferObject)[offset]), length);        SNI_END_RAW_POINTERS;        if (bytesReceived < 0) {            int status;            unsigned char ipBytes[MAX_ADDR_LENGTH];            void *context;            if (info == NULL) {                /* initial invocation */                ANC_INC_NETWORK_INDICATOR;                SNI_BEGIN_RAW_POINTERS;                status = pcsl_datagram_read_start(                           socketHandle, ipBytes, &port,                           (char*)&(JavaByteArray(bufferObject)[offset]),                           length, &bytesReceived, &context);                SNI_END_RAW_POINTERS;            } else {                /* reinvocation */                if ((void *)info->descriptor != socketHandle) {                    REPORT_CRIT2(LC_PROTOCOL,                        "datagram::send0 handle mismatch 0x%x != 0x%x\n",                            socketHandle, info->descriptor);                }                context = info->pResult;                SNI_BEGIN_RAW_POINTERS;                status = pcsl_datagram_read_finish(                           socketHandle, ipBytes, &port,                           (char*)&(JavaByteArray(bufferObject)[offset]),                           length, &bytesReceived, context);                SNI_END_RAW_POINTERS;            }            if (status == PCSL_NET_SUCCESS) {                memcpy(&ipAddress, ipBytes, MAX_ADDR_LENGTH);                lres = pack_recv_retval(ipAddress, port, bytesReceived);                ANC_DEC_NETWORK_INDICATOR;            } else if (status == PCSL_NET_WOULDBLOCK) {                midp_thread_wait(NETWORK_READ_SIGNAL, (int)socketHandle, context);            } else if (status == PCSL_NET_INTERRUPTED) {                KNI_ThrowNew(midpInterruptedIOException, NULL);                ANC_DEC_NETWORK_INDICATOR;            } else {                /* status == PCSL_NET_IOERROR */                midp_snprintf(gKNIBuffer, KNI_BUFFER_SIZE,                    "error code %d", pcsl_network_error(socketHandle));                KNI_ThrowNew(midpIOException, gKNIBuffer);                ANC_DEC_NETWORK_INDICATOR;            }        } else {            /* push gave us a datagram */            lres = pack_recv_retval(ipAddress, port, bytesReceived);        }    } else {        if (info == NULL) {            /* initial invocation */            KNI_ThrowNew(midpIOException, "socket closed");        } else {            /* reinvocation */            KNI_ThrowNew(midpInterruptedIOException, NULL);            ANC_DEC_NETWORK_INDICATOR;        }    }    KNI_EndHandles();    KNI_ReturnLong(lres);}

⌨️ 快捷键说明

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