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);
}
Example #2
0
/**
 * 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);
}
Example #3
0
/**
 * 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);
}
Example #4
0
/**
 * 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;
}
Example #5
0
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;
}