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