KNIEXPORT KNI_RETURNTYPE_INT Java_com_sun_cldc_io_j2me_socket_Protocol_open0() { static int inited = 0; if (!inited) { pcsl_network_init(); inited = 1; } int fd = -1; // (1) Get the hostname, and convert it to IP address KNI_StartHandles(1); { KNI_DeclareHandle(hostname_object); KNI_GetParameterAsObject(1, hostname_object); // hostname is always NUL terminated. See socket/Protocol.java for detail. char *hostname = (char*) SNI_GetRawArrayPointer(hostname_object); int port = KNI_GetParameterAsInt(2); unsigned char addr[4]; int len; int status; void *context; void *handle; status = pcsl_network_gethostbyname_start( hostname, addr, sizeof(addr), &len, &handle, &context); if (status == PCSL_NET_WOULDBLOCK) { do { status = pcsl_network_gethostbyname_finish(addr, sizeof(addr), &len, &handle, &context); } while (status == PCSL_NET_WOULDBLOCK); } if (status != PCSL_NET_SUCCESS) { goto done; } // (2) Make the connection status = pcsl_socket_open_start( addr, port, &handle, &context); if (status == PCSL_NET_WOULDBLOCK) { do { status = pcsl_socket_open_finish(handle, context); } while (status == PCSL_NET_WOULDBLOCK); } if (status != PCSL_NET_SUCCESS) { goto done; } fd = (int)handle; } done: KNI_EndHandles(); KNI_ReturnInt(fd); }
/** * Gets a raw IPv4 address for the given hostname. * <p> * Java declaration: * <pre> * static getIpNumber([B)I * </pre> * * @param szHost the hostname to lookup as a 'C' string * @return raw IPv4 address or <tt>-1</tt> if there was an error */ KNIEXPORT KNI_RETURNTYPE_INT Java_com_sun_midp_io_j2me_datagram_Protocol_getIpNumber(void) { int len; int status; int ipn = -1; unsigned char ipBytes[MAX_ADDR_LENGTH]; void* context = NULL; void* handle; MidpReentryData* info; KNI_StartHandles(1); KNI_DeclareHandle(hostObject); KNI_GetParameterAsObject(1, hostObject); info = (MidpReentryData*)SNI_GetReentryData(NULL); if (info == NULL) { /* First invocation */ SNI_BEGIN_RAW_POINTERS; status = pcsl_network_gethostbyname_start( (char*)JavaByteArray(hostObject), ipBytes, MAX_ADDR_LENGTH, &len, &handle, &context); SNI_END_RAW_POINTERS; } else { /* Reinvocation after unblocking the thread */ handle = (void*)info->descriptor; /* IMPL NOTE: Please see 6440539 for details. */ /* All but windows implementations of pcsl_network_gethostbyname_finish */ /* ignore context parameter. Windows one expects status code there. */ context = (void*)info->status; status = pcsl_network_gethostbyname_finish(ipBytes, MAX_ADDR_LENGTH, &len, handle, context); } KNI_EndHandles(); if (status == PCSL_NET_SUCCESS) { /* * Convert the unsigned char ip bytes array into an integer * that represents a raw IP address. */ //ipn = pcsl_network_getRawIpNumber(ipBytes); memcpy(&ipn, ipBytes, MAX_ADDR_LENGTH); } else if (status == PCSL_NET_WOULDBLOCK) { midp_thread_wait(HOST_NAME_LOOKUP_SIGNAL, (int)handle, context); } else { /* status is either PCSL_NET_IOERROR or PCSL_NET_INVALID */ ipn = -1; REPORT_INFO1(LC_PROTOCOL, "datagram::getIpNumber returns PCSL error code %d", status); /* * IOException is thrown at the Java layer when return value * is -1 */ //KNI_ThrowNew(midpIOException, "Host name could not be resolved"); } KNI_ReturnInt((jint)ipn); }
/** * Gets a raw IPv4 address for the given hostname. * <p> * Java declaration: * <pre> * getIpNumber([B)I * </pre> * * @param szHost the hostname to lookup as a 'C' string * @param ipBytes Output parameter that represents an unsigned char * array for an IP address * @return len Length of ipBytes * */ KNIEXPORT KNI_RETURNTYPE_INT Java_com_sun_midp_io_j2me_socket_Protocol_getIpNumber0(void) { int len = -1; int status = PCSL_NET_INVALID; unsigned char ipBytes[MAX_ADDR_LENGTH]; void* context = NULL; void* pcslHandle; MidpReentryData* info; KNI_StartHandles(2); KNI_DeclareHandle(hostObject); KNI_DeclareHandle(ipAddressObject); KNI_GetParameterAsObject(1, hostObject); KNI_GetParameterAsObject(2, ipAddressObject); info = (MidpReentryData*)SNI_GetReentryData(NULL); if (info == NULL) { /* First invocation */ SNI_BEGIN_RAW_POINTERS; status = pcsl_network_gethostbyname_start( (char*)JavaByteArray(hostObject), ipBytes, MAX_ADDR_LENGTH, &len, &pcslHandle, &context); SNI_END_RAW_POINTERS; } else { /* Reinvocation after unblocking the thread */ pcslHandle = (void*)info->descriptor; /* IMPL NOTE: Please see 6440539 for details. */ /* All but windows implementations of pcsl_network_gethostbyname_finish */ /* ignore context parameter. Windows one expects status code there. */ context = (void*)info->status; status = pcsl_network_gethostbyname_finish(ipBytes, MAX_ADDR_LENGTH, &len, pcslHandle, context); } if (status == PCSL_NET_SUCCESS) { KNI_SetRawArrayRegion(ipAddressObject, 0, len, (jbyte *)ipBytes); } else if (status == PCSL_NET_WOULDBLOCK) { midp_thread_wait(HOST_NAME_LOOKUP_SIGNAL, (int)pcslHandle, context); } else { /* must be PCSL_NET_IOERROR or PCSL_NET_INVALID */ len = -1; } KNI_EndHandles(); KNI_ReturnInt((jint)len); }
/** * Write an SMS datagram. */ WMA_STATUS jsr120_sms_write(jchar msgType, unsigned char address[], unsigned char msgBuffer[], jchar msgLen, jchar sourcePort, jchar destPort, jint *bytesWritten, void **pContext) { /* Contains context of current operation including * the buffer that will contain all data to be written. */ jsr120_udp_emulator_context *context = NULL; /** The writing index. */ jint index = 0; /** Return status */ WMA_STATUS status = WMA_NET_SUCCESS; /** Internal sms phone number property. */ const char *phNum = NULL; /** Physical port to be used to send SMS */ jint sendPort = smsOutPortNumber; /** Time related structs, variable */ /* Need revisit: add time code to fetch time */ jlong timestamp = 0; (void)sourcePort; if (*pContext == NULL) { /* Allocate and initialize datagram buffer */ context = (jsr120_udp_emulator_context*)pcsl_mem_malloc(sizeof(*context)); if (context == NULL) { return WMA_NET_IOERROR; } memset(context, 0, sizeof(*context)); /* Get phone number */ load_var_char_env_prop((char**)&phNum, "JSR_120_PHONE_NUMBER", "com.sun.midp.io.j2me.sms.PhoneNumber"); if (phNum == NULL) { /* Free resources and quit */ pcsl_mem_free(context); /* Cannot determine device's phone number. Fatal error. */ return WMA_NET_IOERROR; } *pContext = context; /* Check if SMS is being sent to yourself */ if (strcmp(phNum, (char *)address) == 0) { /* * Sending SMS to yourself, swicth port to the one you're * listening on. */ sendPort = smsInPortNumber; } /* Populate the datagram buffer */ wma_put_int(context->buffer, &index, (int)msgType); wma_put_int(context->buffer, &index, (int)destPort); wma_put_long_long(context->buffer, &index, timestamp); wma_put_string(context->buffer, &index, (char *)address); wma_put_string(context->buffer, &index, (char *)phNum); wma_put_int(context->buffer, &index, (int)msgLen); if (msgLen > 0) { wma_put_bytes(context->buffer, &index, (char *)msgBuffer, msgLen); } #if ENABLE_WMA_LOOPBACK { /* * This code is enabled mainly for unit tests * that want to test send/receive without the * network, i.e. message to be sent is put back * into the message pool and received by the sender. */ SmsMessage *sms = (SmsMessage *)pcsl_mem_malloc(sizeof(SmsMessage)); (void)bytesWritten; if (sms != NULL) { memset(sms, 0, sizeof(SmsMessage)); sms->encodingType = msgType; sms->destPortNum = (unsigned short)destPort; sms->timeStamp = timestamp; sms->msgAddr = pcsl_mem_strdup((char *)phNum); sms->msgLen = msgLen; if (msgLen > 0) { jint i; char *msg = (char*)pcsl_mem_malloc(msgLen + 1); for (i = 0; i < msgLen; i++) { msg[i] = msgBuffer[i]; } msg[i] = '\0'; sms->msgBuffer = msg; } /* add message to pool */ jsr120_sms_pool_add_msg(sms); /* Notify all listeners of the new message. */ jsr120_sms_message_arrival_notifier(sms); status = WMA_NET_SUCCESS; } else { status = WMA_NET_IOERROR; } } #else { /** The status of networking operation. */ int pcsl_status = PCSL_NET_SUCCESS; /** The length of the IP address to be retrieved. */ int plen; pcsl_status = pcsl_network_gethostbyname_start( targetHost, context->ipAddr, sizeof(context->ipAddr), &plen, &context->pcsl_handle, &context->pcsl_context); switch (pcsl_status) { case PCSL_NET_SUCCESS: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_DONE; status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_INPROGRESS; /* temporarily create entry in emulator-managed sockets list */ context->emulatorSocket = wmaCreateSocketHandle(WMA_SMS_PROTOCOL, (int)context->pcsl_handle); status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } } #endif } #if ENABLE_WMA_LOOPBACK == 0 { /** The status of networking operation. */ int pcsl_status = PCSL_NET_SUCCESS; /** The length of the IP address to be retrieved. */ int plen; if (status == WMA_NET_SUCCESS && *pContext != NULL) { /* handle reinvocation or continuation. RFC: is it needed for loopback mode? */ context = (jsr120_udp_emulator_context*)*pContext; switch (context->state) { case JSR120_UDP_EMULATOR_CONTEXT_STATE_INIT: /* Cannot have these states. */ break; case JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_INPROGRESS: /* finish gethostbyname operation */ pcsl_status = pcsl_network_gethostbyname_finish( context->ipAddr, sizeof(context->ipAddr), &plen, context->pcsl_handle, context->pcsl_context); if (pcsl_status != PCSL_NET_WOULDBLOCK) wmaDestroySocketHandle(context->emulatorSocket); switch (pcsl_status) { case PCSL_NET_SUCCESS: status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: /* still cannot get host name. */ status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } if (status != WMA_NET_SUCCESS) break; /* Intentional fallthrough to continue with sendto. */ case JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_DONE: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_INPROGRESS; pcsl_status = pcsl_datagram_write_start( (void*)wmaGetRawSocketFD(smsHandle), context->ipAddr, sendPort, context->buffer, sizeof(context->buffer), bytesWritten, &context->pcsl_context); switch (pcsl_status) { case PCSL_NET_SUCCESS: /* finish */ status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } break; case JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_INPROGRESS: pcsl_status = pcsl_datagram_write_finish( (void*)wmaGetRawSocketFD(smsHandle), context->ipAddr, sendPort, context->buffer, sizeof(context->buffer), bytesWritten, &context->pcsl_context); switch (pcsl_status) { case PCSL_NET_SUCCESS: /* finish */ status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: /* still cannot send */ status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } break; default: status = WMA_NET_IOERROR; } } } #endif if (status != WMA_NET_WOULDBLOCK) { /* Message was sent, so free the buffer. */ pcsl_mem_free(context); *pContext = NULL; } return status; }
static WMA_STATUS jsr205_datagram_write(WMA_PROTOCOLS protocol, jint outPort, void* handle, char *toAddr, char* fromAddr, jint length, char* buf, jint *bytesWritten, jsr120_udp_emulator_context *context) { /** The maximum amount of data allowed within a network packet. */ jint PACKET_MAX_SIZE = MAX_DATAGRAM_LENGTH - 10; /* 3 shorts + 1 int */ /** The socket descriptor that corresponds to the handle. */ jint socket_fd; /** The total number of datagram packets to be sent. */ jshort totalPackets; /** The pointer to buffer for all datagram data. */ char *dgramBuffer = NULL; /** Number of bytes written for given packet. */ int packetBytesWritten = 0; /** Return status. */ WMA_STATUS status = WMA_NET_IOERROR; /** Status of low level operation. */ int pcsl_status; /** The length of the IP address to be retrieved. */ int plen = 0; /** The writing index into the datagram buffer. */ jint index = 0; /* * The "to" and "from" addresses are not used in this implementation. In a * more sophisticated implementation that may involve more than one * recipient, the packets that get broadcast would need to be directed to * specific phones. The "to" address would then come into play and would * need to be for each specific phone in a phone list. */ (void)toAddr; (void)fromAddr; /* Pick up the socket descriptor that corresponds to the handle. */ socket_fd = wmaGetRawSocketFD(handle); switch (context->state) { case JSR120_UDP_EMULATOR_CONTEXT_STATE_INIT: /* First invocation. */ *bytesWritten = 0; context->p = buf; context->remaining_length = length; /* Resolve host name as a first step. */ pcsl_status = pcsl_network_gethostbyname_start( targetHost, context->ipAddr, sizeof(context->ipAddr), &plen, &context->pcsl_handle, &context->pcsl_context); switch (pcsl_status) { case PCSL_NET_SUCCESS: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_DONE; status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_INPROGRESS; /* temporarily create entry in emulator-managed sockets list */ context->emulatorSocket = wmaCreateSocketHandle(protocol, (int)context->pcsl_handle); status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } break; case JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_INPROGRESS: /* Reinvocation after gethostbyname WOULDBLOCK. */ pcsl_status = pcsl_network_gethostbyname_finish( context->ipAddr, sizeof(context->ipAddr), &plen, context->pcsl_handle, context->pcsl_context); if (pcsl_status != PCSL_NET_WOULDBLOCK) wmaDestroySocketHandle(context->emulatorSocket); switch (pcsl_status) { case PCSL_NET_SUCCESS: context->state = JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_DONE; status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: /* still cannot get host name. */ status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } break; default: /* Continue with sendto operation. */ status = WMA_NET_SUCCESS; break; } if (status == WMA_NET_SUCCESS) { /* * We must be in JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO state if we * managed to get here. So start/continue sending data */ /* Compute the total number of datagrams required to send the message. */ totalPackets = (short)((length + PACKET_MAX_SIZE - 1) / PACKET_MAX_SIZE); dgramBuffer = context->buffer; if (context->state == JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_INPROGRESS) { /* * There were sendto operation resulted in WOULDBLOCK, need to finish it * Appropriate data is saved in context */ pcsl_status = pcsl_datagram_write_finish( (void*)socket_fd, context->ipAddr, outPort, dgramBuffer, sizeof(dgramBuffer), &packetBytesWritten, &context->pcsl_context); } else { pcsl_status = PCSL_NET_SUCCESS; } /* * Perform next and possibly all the rest of writing operations * till WOULDBLOCK or error is returned from network layer */ while (pcsl_status == PCSL_NET_SUCCESS) { if (++context->packetNumber > totalPackets) break; if (context->state == JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_INPROGRESS || context->state == JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_DONE || context->state == JSR120_UDP_EMULATOR_CONTEXT_STATE_GETHOSTBYNAME_DONE) { *bytesWritten += packetBytesWritten; /* Move the pointer past the bytes just sent */ context->p += context->count; context->remaining_length -= context->count; } /* Prepare next packet and start writing it */ /** Reset the writing index into the datagram buffer. */ index = 0; /* Initialize the datagram buffer. */ memset(dgramBuffer, 0, MAX_DATAGRAM_LENGTH); /* Compute the number of bytes that can be stuffed into * this packet. */ context->count = context->remaining_length; if (context->count > PACKET_MAX_SIZE) { context->count = PACKET_MAX_SIZE; } /* Build the buffer to be written */ wma_put_short(dgramBuffer, &index, context->packetNumber); wma_put_short(dgramBuffer, &index, totalPackets); /* Needed for: count < PACKET_MAX_SIZE */ wma_put_short(dgramBuffer, &index, context->count); /* Total length of message. */ wma_put_int(dgramBuffer, &index, context->remaining_length); /* Writes count bytes, starting at p. */ wma_put_bytes(dgramBuffer, &index, context->p, context->count); pcsl_status = pcsl_datagram_write_start( (void*)socket_fd, context->ipAddr, outPort, dgramBuffer, MAX_DATAGRAM_LENGTH, &packetBytesWritten, &context->pcsl_context); context->state = pcsl_status != PCSL_NET_WOULDBLOCK ? JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_DONE : JSR120_UDP_EMULATOR_CONTEXT_STATE_SENDTO_INPROGRESS; } switch (pcsl_status) { case PCSL_NET_SUCCESS: /* We are done */ status = WMA_NET_SUCCESS; break; case PCSL_NET_WOULDBLOCK: /* cannot send right now */ status = WMA_NET_WOULDBLOCK; break; case PCSL_NET_INTERRUPTED: status = WMA_NET_INTERRUPTED; break; default: status = WMA_NET_IOERROR; } } return status; }