/** * Create a new message and populate it with the given data. Memory * will be allocated for the new message. * * @param fromAddress The strinf of the address from which this message * originated. * @param appID The application ID string for the recipient. * @param replyToAppID The application ID string of the sender. * @param msgBuffer A pointer to the message data. * * @return The new MMS message. */ MmsMessage* jsr205_mms_new_msg(char* fromAddress, char* appID, char* replyToAppID, int msgLen, unsigned char* msgBuffer) { MmsMessage* message = (MmsMessage*)pcsl_mem_malloc(sizeof(MmsMessage)); memset(message, 0, sizeof(MmsMessage)); /* Duplicate the address information. */ message->fromAddress = (char*)pcsl_mem_strdup(fromAddress); message->appID = (char*)pcsl_mem_strdup(appID); message->replyToAppID = (char*)pcsl_mem_strdup(replyToAppID); /* Make a copy of the buffer length and of the message buffer. */ message->msgLen = msgLen; message->msgBuffer = (char*)pcsl_mem_malloc(msgLen); memcpy(message->msgBuffer, msgBuffer, msgLen); return message; }
/** * Create a new list element with a string identifier. * * @param head A pointer to the first element in the list. * @param name The name which identifies this element. The name is duplicated. * @param msid The MIDlet suite identifier. * @param userData Anything the user needs to attach to this element. * @param userDataCallBack A user-defined callback. * * @return A pointer to the element that was created. */ ListElement* jsr120_list_new_by_name(ListElement** head, unsigned char* name, AppIdType msid, void* userData, void* userDataCallback) { ListElement* q = (ListElement*) pcsl_mem_malloc(sizeof(ListElement)); q->next = NULL; q->id = -1; /* Duplicate the name. */ if (name != NULL) { q->strid = (unsigned char*)pcsl_mem_strdup((char*)name); } else { q->strid = NULL; } q->msid = msid; q->userData = userData; q->userDataCallback = userDataCallback; q->isRegistered = 1; q->isNewMessage = 1; jsr120_list_add_first(head, q); return q; }
/* * test pcsl_mem_strdup function works properly and allocated memory for copied string */ void testStrdup() { int spcBefore, spcAfter; char* str1 = "a 20 character string"; char* str2; spcBefore = pcsl_mem_get_free_heap(); str2 = (char*)pcsl_mem_strdup(str1); spcAfter = pcsl_mem_get_free_heap(); assertTrue("pcsl_mem_strdup failed: str1 and str2 not equal!", strncmp(str1, str2, 20) == 0); if (spcAfter != -1) { assertTrue("pcsl_mem_strdup did not allocate any new memory", (spcAfter + 20) <= spcBefore); } pcsl_mem_free(str2); }
/** * 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; }