/** * sip_process_int_msg - process internal IPC message from the * the message queue waiting thread. * * @param - none. * * @return none. */ static void sip_process_int_msg (void) { const char *fname = "sip_process_int_msg"; ssize_t rcv_len; uint8_t num_messages = 0; uint8_t response = 0; sip_int_msg_t *int_msg; void *msg; phn_syshdr_t *syshdr; /* read the msg count from the IPC socket */ rcv_len = cprRecvFrom(sip_ipc_serv_socket, &num_messages, sizeof(num_messages), 0, NULL, NULL); if (rcv_len < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:" " errno=%d\n", fname, cpr_errno); return; } if (num_messages == 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"message queue is empty!\n", fname); return; } if (num_messages > MAX_SIP_MESSAGES) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"number of messages on queue exceeds maximum %d\n", fname, num_messages); num_messages = MAX_SIP_MESSAGES; } /* process messages */ int_msg = &sip_int_msgq_buf[0]; while (num_messages) { msg = int_msg->msg; syshdr = int_msg->syshdr; if (msg != NULL && syshdr != NULL) { SIPTaskProcessListEvent(syshdr->Cmd, msg, syshdr->Usr.UsrPtr, syshdr->Len); cprReleaseSysHeader(syshdr); int_msg->msg = NULL; int_msg->syshdr = NULL; } num_messages--; /* one less message to work on */ int_msg++; /* advance to the next message */ } /* * Signal message queue waiting thread to get more messages. */ if (cprSendTo(sip_ipc_serv_socket, (void *)&response, sizeof(response), 0, (cpr_sockaddr_t *)&sip_clnt_sock_addr, cpr_sun_len(sip_clnt_sock_addr)) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d sending IPC\n", fname); } }
int sip_platform_udp_channel_read (cpr_socket_t s, cprBuffer_t buf, uint16_t *len, cpr_sockaddr_t *soc_addr, cpr_socklen_t *soc_addr_len) { static const char *fname = "sip_platform_udp_channel_read"; int bytes_read; // NOT USED: cpr_sockaddr_in_t *addr = (cpr_sockaddr_in_t *)soc_addr; bytes_read = cprRecvFrom(s, buf, CPR_MAX_MSG_SIZE, 0, soc_addr, soc_addr_len); switch (bytes_read) { case SOCKET_ERROR: /* * If no data is available to read (CPR_EWOULDBLOCK), * for non-blocking socket, it is not an error. */ cpr_free(buf); *len = 0; if (cpr_errno != CPR_EWOULDBLOCK) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"fd[%d]\n", fname, s); CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED), fname, "cprRecvFrom", cpr_errno); return SIP_ERROR; } /* * Will continue reading when data arrives at socket */ break; case 0: /* * Return value 0 is OK. This does NOT mean the connection * has closed by the peer, as with TCP sockets. With UDP * sockets, there is no such thing as closing a connection. */ CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"No data on fd %d\n", DEB_F_PREFIX_ARGS(SIP_SDP, fname), s); cpr_free(buf); *len = 0; break; default: /* PKT has been read */ CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Recvd on fd %d\n", DEB_F_PREFIX_ARGS(SIP_SDP, fname), s); *len = (uint16_t) bytes_read; break; } return SIP_OK; }
/** * The function is a thread loop that waits on SIP message queue * visible for the external components (sip_msgq). The thread is used * to avoid having the main task loop from having to set a small time * waiting on select() to poll inter-thread messages. The small waiting * time on select() to poll internal messages queue increases the * unnecessary of waking up when system is idle. On the platform that * power conservative is critical such as handheld phone, waking up * periodically is not good for battery life. * * This thread splits the message queue waiting function from the * main thread waiting on select(). This thread simply listens on the * internal message queue and signal to the main thread via IPC socket * or local socket trigger. Therefore the main thread can uniformly * process internal message event and the network event via select(). * The small internal poll time on select() can be * avoided. * * @param[in] arg - pointer to SIP main thread's message queue. * * @return None. * * @pre (arg != NULL) */ void sip_platform_task_msgqwait (void *arg) { const char *fname = "sip_platform_task_msgqwait"; cprMsgQueue_t *msgq = (cprMsgQueue_t *)arg; unsigned int wait_main_thread = 0; phn_syshdr_t *syshdr; void *msg; uint8_t num_messages = 0; uint8_t response = 0; boolean quit_thread = FALSE; char tempdir[sizeof(sip_serv_sock_addr.sun_path)]; if (msgq == NULL) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"task msgq is null, exiting", fname); return; } if (platThreadInit("SIP IPCQ task") != 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to attach thread to JVM", fname); return; } /* * Wait for SIP main thread ready for IPC connection. */ while (!main_thread_ready) { /* Pause for other threads to run while waiting */ cprSleep(SIP_PAUSE_WAIT_IPC_LISTEN_READY_TIME); wait_main_thread++; if (wait_main_thread > SIP_MAX_WAIT_FOR_IPC_LISTEN_READY) { /* Exceed the number of wait time */ CCSIP_DEBUG_ERROR(SIP_F_PREFIX"timeout waiting for listening IPC" " socket ready, exiting\n", fname); return; } } /* * Adjust relative priority of SIP thread. */ (void) cprAdjustRelativeThreadPriority(SIP_THREAD_RELATIVE_PRIORITY); /* * The main thread is ready. set global client socket address * so that the server can send back response. */ sip_get_sock_dir(tempdir, sizeof(tempdir), SIP_MSG_CLNT_SUFFIX); cpr_set_sockun_addr(&sip_clnt_sock_addr, tempdir, 0); sip_ipc_clnt_socket = sip_create_IPC_sock(sip_clnt_sock_addr.sun_path); if (sip_ipc_clnt_socket == INVALID_SOCKET) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_create_IPC_sock() failed," " exiting\n", fname); return; } while (quit_thread == FALSE) { msg = cprGetMessage(msgq, TRUE, (void **) &syshdr); while (msg != NULL) { /* * There is a message to be forwarded to the main SIP * thread for processing. */ sip_int_msgq_buf[num_messages].msg = msg; sip_int_msgq_buf[num_messages].syshdr = syshdr; num_messages++; switch (syshdr->Cmd) { case THREAD_UNLOAD: thread_ended(THREADMON_MSGQ); quit_thread = TRUE; break; default: break; } if (num_messages == MAX_SIP_MESSAGES) { /* * Limit the number of messages passed to the main SIP * thread to MAX_SIP_MESSAGES since SIP main thread only * process messages up to MAX_SIP_MESSAGES at a time. */ break; } /* * Check to see if there is more message on the queue * before sending IPC message trigger to the main SIP * thread. This is to minimize the overhead of the * the main SIP thread in processing select(). */ msg = cprGetMessage(msgq, 0, (void **) &syshdr); } if (num_messages) { CCSIP_DEBUG_TASK(DEB_F_PREFIX"%d msg available on msgq", DEB_F_PREFIX_ARGS(SIP_MSG_QUE, fname), num_messages); /* * There are some number of messages sent to the main thread, * trigger the main SIP thread via IPC to process the message. */ if (cprSendTo(sip_ipc_clnt_socket, (void *)&num_messages, sizeof(num_messages), 0, (cpr_sockaddr_t *)&sip_serv_sock_addr, cpr_sun_len(sip_serv_sock_addr)) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"send IPC failed errno=%d", fname, cpr_errno); } if (FALSE == quit_thread) { /* * Wait for main thread to signal us to get more message. */ if (cprRecvFrom(sip_ipc_clnt_socket, &response, sizeof(response), 0, NULL, NULL) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:" " errno=%d\n", fname, cpr_errno); } num_messages = 0; } } } cprCloseSocket(sip_ipc_clnt_socket); unlink(sip_clnt_sock_addr.sun_path); // removes tmp file }
/** * sip_process_int_msg - process internal IPC message from the * the message queue waiting thread. * * @param - none. * * @return none. */ static void sip_process_int_msg (void) { const char *fname = "sip_process_int_msg"; ssize_t rcv_len; uint8_t num_messages = 0; uint8_t response = 0; sip_int_msg_t *int_msg; void *msg; phn_syshdr_t *syshdr; /* read the msg count from the IPC socket */ rcv_len = cprRecvFrom(sip_ipc_serv_socket, &num_messages, sizeof(num_messages), 0, NULL, NULL); if (rcv_len < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:" " errno=%d\n", fname, cpr_errno); return; } if (num_messages == 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"message queue is empty!\n", fname); return; } if (num_messages > MAX_SIP_MESSAGES) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"number of messages on queue exceeds maximum %d\n", fname, num_messages); num_messages = MAX_SIP_MESSAGES; } /* process messages */ int_msg = &sip_int_msgq_buf[0]; while (num_messages) { msg = int_msg->msg; syshdr = int_msg->syshdr; if (msg != NULL && syshdr != NULL) { if (syshdr->Cmd == THREAD_UNLOAD) { /* * Cleanup here, as SIPTaskProcessListEvent wont return. * - Remove last tmp file and tmp dir. */ cprCloseSocket(sip_ipc_serv_socket); unlink(sip_serv_sock_addr.sun_path); char stmpdir[sizeof(sip_serv_sock_addr.sun_path)]; PR_snprintf(stmpdir, sizeof(stmpdir), SIP_IPC_TEMP_PATH, getpid()); if (rmdir(stmpdir) != 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to remove temp dir\n", fname); } } SIPTaskProcessListEvent(syshdr->Cmd, msg, syshdr->Usr.UsrPtr, syshdr->Len); cprReleaseSysHeader(syshdr); int_msg->msg = NULL; int_msg->syshdr = NULL; } num_messages--; /* one less message to work on */ int_msg++; /* advance to the next message */ } /* * Signal message queue waiting thread to get more messages. */ if (cprSendTo(sip_ipc_serv_socket, (void *)&response, sizeof(response), 0, (cpr_sockaddr_t *)&sip_clnt_sock_addr, cpr_sun_len(sip_clnt_sock_addr)) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d sending IPC\n", fname); } }