/**
 * After calling  setSMSListeningPort(), a WMA Application will continue to listen for
 * incoming messages whose destination port number matches the registered port number.
 * this callback function will be called by platform once an incoming message is ready.
 * If the incoming message contains more than one protocol (PDU) segments, target device
 * native layer should concatenate all segments into a completed message and forward to MIDP WMA.
 * Platform should allocate the msgBuffer and put whole incoming message contents into this buffer.
 *
 * @param msgType       The encoding type of the incoming message
 *                      (GSM 7-bit alphabet, Unicode or 8-bit Binary)
 * @param sourceAddress The senders address. NULL terminated string.
 * @param msgBuffer     The incoming message body.
 * @param msgLen        The length of the incoming message body.
 * @param sourcePortNum source port number of the incoming message
 * @param destPortNum   The destination port number of the incoming message.[unsigned short]
 * @param timeStamp     When the message is received (SCT: message Service Center Time)[long].
 */
void jsr120_notify_incoming_sms(jchar msgType, char *sourceAddress,
                                unsigned char *msgBuffer, jint msgLen,
                                jchar sourcePortNum, jchar destPortNum,
                                jlong timeStamp) {

    if (WMA_OK == jsr120_sms_is_message_expected(destPortNum, sourceAddress)) {

        SmsMessage* sms = jsr120_sms_new_msg(
            msgType, (unsigned char*)sourceAddress, sourcePortNum, destPortNum, timeStamp, msgLen, msgBuffer);

        jsr120_sms_pool_add_msg(sms);

        /* Notify all listeners of the new message. */
        jsr120_sms_message_arrival_notifier(sms);
    } 
}
Beispiel #2
0
jboolean checkReadSignal(int socket) {

    WMA_STATUS status;
    unsigned char ipBytes[MAX_ADDR_LENGTH];
    jint ipPort;
    jint datagramLength;
    jint length;
    char* msg = NULL;
    char* recipientPhone = NULL;
    char *filter = NULL;
    jint i;
    WMA_PROTOCOLS sockProtocol;
    char* p;
    jint index;

    /* Message structures for the protocols SMS and CBS. */
    SmsMessage* sms = NULL;
    CbsMessage* cbs = NULL;

#if ENABLE_JSR_205
    /* Message structures for MMS. */
    MmsMessage* mms = NULL;
#endif

    if (wmaGetProtocolByFD(socket, &sockProtocol) != WMA_OK)
        return KNI_FALSE;

    /* Read the datagram. */
    p = (char *)pcsl_mem_malloc(MAX_DATAGRAM_LENGTH);
    if (p != NULL) {
        memset(p, 0, MAX_DATAGRAM_LENGTH);

        status = jsr120_datagram_read(sockProtocol, ipBytes, &ipPort, p, MAX_DATAGRAM_LENGTH,
                                      &datagramLength);

        if (status == WMA_NET_SUCCESS) {
            index = 0;

            switch (sockProtocol) {

            case WMA_SMS_PROTOCOL:
                sms = (SmsMessage *)pcsl_mem_malloc(sizeof(SmsMessage));
                if (sms != NULL) {
                    memset(sms, 0, sizeof(SmsMessage));

                    sms->encodingType = getInt(p, &index);
                    sms->sourcePortNum = ipPort;
                    sms->destPortNum = (unsigned short)getInt(p, &index);
                    sms->timeStamp = getLongLong(p, &index);
                    /* The next field is the recipient's phone number */
                    recipientPhone = getString(p, &index);
                    /* The next field is the sender's phone number */
                    sms->msgAddr = getString(p, &index);

                    length = getInt(p, &index);
                    sms->msgLen = length;
                    if (length > 0) {
                        msg = (char*)pcsl_mem_malloc(length + 1);
                        for (i = 0; i < length; i++) {
                            msg[i] = p[index++];
                        }
                        msg[i] = '\0';
                        sms->msgBuffer = msg;
                    }

                    /*
                     * Check for a push entry for this connection.
                     */
                    filter = pushgetfilter("sms://:", sms->destPortNum);

                    /*
                     * File this message, if there is no push entry for it
                     * i.e. filter is NULL or if there is a push entry for it
                     * and it passes the check filter test. The sender's phone
                     * number is checked against the filter.
                     */
                    if (filter == NULL || checkfilter(filter, sms->msgAddr)) {

                        /*
                         * Notify Push that a message has arrived and
                         * is being cached.
                         */
                        pushsetcachedflag("sms://:", sms->destPortNum);

                        /* add message to pool */
                        jsr120_sms_pool_add_msg(sms);
                    }

                    if (filter != NULL) {
                        pcsl_mem_free(filter);
                    }
                }

                break;

            case WMA_CBS_PROTOCOL:
                cbs = (CbsMessage*)pcsl_mem_malloc(sizeof(CbsMessage));
                if (cbs != NULL) {
                    memset(cbs, 0, sizeof(CbsMessage));

                    cbs->encodingType = (ENCODING_TYPE)getInt(p, &index);
                    cbs->msgID = getInt(p, &index);

                    /* Pick up the message length and the message data. */
                    length = getInt(p, &index);
                    cbs->msgLen = length;
                    if (length > 0) {
                        msg = (char*)pcsl_mem_malloc(length);
                        for (i = 0; i < length; i++) {
                            msg[i] = p[index++];
                        }
                        cbs->msgBuffer = (unsigned char*)msg;
                    }

                    /*
                     * Notify Push that a message has arrived and
                     * is being cached.
                     */
                    pushsetcachedflag("cbs://:", cbs->msgID);

                    /* Add message to pool. */
                    jsr120_cbs_pool_add_msg(cbs);
                }
                break;

#if ENABLE_JSR_205

            case WMA_MMS_PROTOCOL:

                if (assemble_frags(p) == KNI_TRUE) {

                    /*
                     * Note:
                     *
                     * The message is currently received in whole. That is, the
                     * message header and body are contained in the single
                     * MmsMessage. Normally, the header would be received on its
                     * own via (in this case, for example), some sort of state
                     * machine that processes the header,
                     */
                    MmsHeader* mmsHeader;

                    /* Create a new MMS message */
                    mms = createMmsMessageFromBuffer(mmsBuffer);
                    pcsl_mem_free(mmsBuffer);
                    mmsBuffer = NULL;

                    /* Notify the platform that a message has arrived. */
                    mmsHeader = createMmsHeader(mms);
                    MMSNotification(mmsHeader);
                    destroyMMSHeader(mmsHeader);

                    /*
                     * Check for a push entry for this connection.
                     */
                    filter = pushgetfiltermms("mms://:", mms->appID);

                    /*
                     * File this message, if there is no push entry for it
                     * i.e. filter is NULL or if there is a push entry for it
                     * and it passes the check filter test
                     */
                    if (filter == NULL || checkfilter(filter, mms->replyToAppID)) {

                        /*
                         * Notify Push that a message has arrived and
                         * is being cached.
                         */
                        pushsetcachedflagmms("mms://:", mms->appID);

                        /* When a fetch is confirmed, add message to pool. */
                        if (jsr205_fetch_mms() == WMA_OK) {
                            jsr205_mms_pool_add_msg(mms);
                        }
                    }

                    pcsl_mem_free(filter);
                }

                break;
#endif

            default:
                /* RFC: Silently fail for unknown protocols. */
                break;

            }  /* switch*/
        }
        pcsl_mem_free(p);
    }

    return KNI_TRUE;
}
Beispiel #3
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;
}
/**
 * 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) {
  
    /** The buffer that will contain all data to be written. */
    char *buffer = NULL;

    /** The writing index. */
    jint index = 0;

    /** The return status. */
    int status = 0;

    /** Internal sms phone number property */
    const char *phNum = NULL;

    /** Physical port to be used to send SMS */
    jint sendPort = smsOutPortNumber; 

    /** Time related structs, variable */
    struct timeval tv;
    jlong timestamp = 0;
    jint tstat = -1;

    (void)sourcePort;
    (void)pContext;

    /* Allocate and initialize datagram buffer */
    buffer = (char*)pcsl_mem_malloc(MAX_DATAGRAM_LENGTH);
    if (buffer == NULL) {
        return WMA_NET_IOERROR;
    }
    memset(buffer, 0, MAX_DATAGRAM_LENGTH);

    /* 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(buffer);
        /* Cannot determine device's phone number. Fatal error. */
        return WMA_NET_IOERROR;
    }

    /* 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;
    }

    /* Compute time of sending */
    tstat = gettimeofday(&tv, NULL);
    if (!tstat) { /* Success on getting time of day */
        /* We adjust to 1000 ticks per second */
        timestamp = (jlong)tv.tv_sec * 1000 + tv.tv_usec/1000;
    }

    /* Populate the datagram buffer */
    wma_put_int(buffer, &index, (int)msgType);
    wma_put_int(buffer, &index, (int)destPort);
    wma_put_long_long(buffer, &index, timestamp);
    wma_put_string(buffer, &index, (char *)address);
    wma_put_string(buffer, &index, (char *)phNum);
    wma_put_int(buffer, &index, (int)msgLen);
    if (msgLen > 0) {
        wma_put_bytes(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));
        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 = msgLen;
        } else {
           return WMA_NET_IOERROR;
        }

    }
#else
    {
        unsigned char ipAddr[256];
        jint plen = 0;
        struct sockaddr_in addr;

        memset(ipAddr, 0, 256);

        /* Send the datagram into the ether. */
        if (network_gethostbyname(targetHost, ipAddr, 256, &plen) != WMA_NET_SUCCESS) {
            return WMA_NET_IOERROR;
        }

        addr.sin_family = AF_INET;
        addr.sin_port   = htons((unsigned short)sendPort);
        memcpy(&addr.sin_addr.s_addr, ipAddr, sizeof(addr.sin_addr.s_addr));

        status = sendto(wmaGetRawSocketFD(smsHandle), buffer, MAX_DATAGRAM_LENGTH, 0, 
                        (struct sockaddr*)&addr, sizeof(addr));
    }
#endif

    /* Message was sent, so free the buffer. */
    pcsl_mem_free(buffer);

    if (status == SOCKET_ERROR) {
        if ((errno == EWOULDBLOCK) || (errno == EINPROGRESS)) {
            return WMA_NET_WOULDBLOCK;
        } else if (errno == EINTR) {
            return WMA_NET_INTERRUPTED;
        } else {
            return WMA_NET_IOERROR;
        }
    }

    *bytesWritten = status;
    return WMA_NET_SUCCESS;
}