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 + -
显示快捷键?