Example #1
0
/**
 *
 * CCApp Provider main routine.
 *
 * @param   arg - CCApp msg queue
 *
 * @return  void
 *
 * @pre     None
 */
void CCApp_task(void * arg)
{
    static const char fname[] = "CCApp_task";
    phn_syshdr_t   *syshdr = NULL;
    appListener *listener = NULL;
    void * msg;

    //initialize the listener list
    sll_lite_init(&sll_list);

    CCAppInit();

    while (1) {
        msg = cprGetMessage(ccapp_msgq, TRUE, (void **) &syshdr);
        if ( msg) {
#if DEBUG
            dump_msg("CCAPPTASKDUMPMSG", (unsigned int *)msg, syshdr->Len, syshdr->Cmd);
#else
            CCAPP_DEBUG(DEB_F_PREFIX"Received Cmd[%d] for app[%d]\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
                    syshdr->Cmd, syshdr->Usr.UsrInfo);
#endif

            listener = getCcappListener(syshdr->Usr.UsrInfo);
            if (listener != NULL) {
                (* ((appListener)(listener)))(msg, syshdr->Cmd);
            } else {
                CCAPP_DEBUG(DEB_F_PREFIX"Event[%d] doesn't have a dedicated listener.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
                        syshdr->Usr.UsrInfo);
            }
            cprReleaseSysHeader(syshdr);
            cprReleaseBuffer(msg);
        }
    }
}
Example #2
0
/**
 * Removes all messages from the queue and then destroy the message queue
 *
 * @param msgQueue - message queue to destroy
 *
 * @return CPR_SUCCESS or CPR_FAILURE, errno provided
 */
cprRC_t
cprDestroyMessageQueue (cprMsgQueue_t msgQueue)
{
    static const char fname[] = "cprDestroyMessageQueue";
    cpr_msg_queue_t *msgq;
    void *msg;

    msgq = (cpr_msg_queue_t *) msgQueue;
    if (msgq == NULL) {
        /* Bad application! */
        CPR_ERROR("%s: Invalid input\n", fname);
        errno = EINVAL;
        return CPR_FAILURE;
    }

    /* Drain message queue */
    msg = cprGetMessage(msgQueue, FALSE, NULL);
    while (msg != NULL) {
        cpr_free(msg);
        msg = cprGetMessage(msgQueue, FALSE, NULL);
    }

    /* Remove message queue from list */
    pthread_mutex_lock(&msgQueueListMutex);
    if (msgq == msgQueueList) {
        msgQueueList = msgq->next;
    } else {
        cpr_msg_queue_t *msgql = msgQueueList;

        while ((msgql->next != NULL) && (msgql->next != msgq)) {
            msgql = msgql->next;
        }
        if (msgql->next == msgq) {
            msgql->next = msgq->next;
        }
    }
    pthread_mutex_unlock(&msgQueueListMutex);

    /* Remove message queue mutex */
    if (pthread_mutex_destroy(&msgq->mutex) != 0) {
        CPR_ERROR("%s: Failed to destroy msg queue (%s) mutex: %d\n",
                  fname, msgq->name, errno);
    }

    cpr_free(msgq);
    return CPR_SUCCESS;
}
Example #3
0
/**
 *
 * CCApp Provider main routine.
 *
 * @param   arg - CCApp msg queue
 *
 * @return  void
 *
 * @pre     None
 */
void CCApp_task(void * arg)
{
    static const char fname[] = "CCApp_task";
    phn_syshdr_t   *syshdr = NULL;
    appListener *listener = NULL;
    void * msg;

    // If the "ready to start" condition variable has been created
    // (is non-null), we're going to wait for it to be signaled
    // before we start processing messages.
    if (ccAppReadyToStartCond) {
        PR_Lock(ccAppReadyToStartLock);
        while (!ccAppReadyToStart) {
            PR_WaitCondVar(ccAppReadyToStartCond, PR_INTERVAL_NO_TIMEOUT);
        }
        PR_Unlock(ccAppReadyToStartLock);
    }

    //initialize the listener list
    sll_lite_init(&sll_list);

    CCAppInit();

    while (1) {
        msg = cprGetMessage(ccapp_msgq, TRUE, (void **) &syshdr);
        if ( msg) {
            CCAPP_DEBUG(DEB_F_PREFIX"Received Cmd[%d] for app[%d]\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
                        syshdr->Cmd, syshdr->Usr.UsrInfo);

            listener = getCcappListener(syshdr->Usr.UsrInfo);
            if (listener != NULL) {
                (* ((appListener)(listener)))(msg, syshdr->Cmd);
            } else {
                CCAPP_DEBUG(DEB_F_PREFIX"Event[%d] doesn't have a dedicated listener.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
                            syshdr->Usr.UsrInfo);
            }
            cprReleaseSysHeader(syshdr);
            cpr_free(msg);
        }
    }
}
/**
 *  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
}
Example #5
0
void
GSMTask (void *arg)
{
    static const char fname[] = "GSMTask";
    void           *msg;
    phn_syshdr_t   *syshdr;
    boolean        release_msg = TRUE;

    /*
     * Get the GSM message queue handle
     * A hack until the tasks in irx are
     * CPRized.
     */
    gsm_msg_queue = (cprMsgQueue_t) arg;
    if (!gsm_msg_queue) {
        GSM_ERR_MSG(GSM_F_PREFIX"invalid input, exiting\n", fname);
        return;
    }

    if (platThreadInit("GSMTask") != 0) {
        return;
    }

    /*
     * Adjust relative priority of GSM thread.
     */
    (void) cprAdjustRelativeThreadPriority(GSM_THREAD_RELATIVE_PRIORITY);

    /*
     * Initialize all the GSM modules
     */
    lsm_init();
    fsm_init();
    fim_init();
    gsm_init();
    dcsm_init();

    cc_init();

    fsmutil_init_shown_calls_ci_map();
    /*
     * On Win32 platform, the random seed is stored per thread; therefore,
     * each thread needs to seed the random number.  It is recommended by
     * MS to do the following to ensure randomness across application
     * restarts.
     */
    cpr_srand((unsigned int)time(NULL));

    /*
     * Cache random numbers for SRTP keys
     */
    gsmsdp_cache_crypto_keys();

    while (1) {

        release_msg = TRUE;

        msg = cprGetMessage(gsm_msg_queue, TRUE, (void **) &syshdr);
        if (msg) {
            switch (syshdr->Cmd) {
            case TIMER_EXPIRATION:
                gsm_process_timer_expiration(msg);
                break;

            case GSM_SIP:
            case GSM_GSM:
                release_msg = gsm_process_msg(syshdr->Cmd, msg);
                break;

            case DP_MSG_INIT_DIALING:
            case DP_MSG_DIGIT_STR:
            case DP_MSG_STORE_DIGIT:
            case DP_MSG_DIGIT:
            case DP_MSG_DIAL_IMMEDIATE:
            case DP_MSG_REDIAL:
            case DP_MSG_ONHOOK:
            case DP_MSG_OFFHOOK:
            case DP_MSG_UPDATE:
            case DP_MSG_DIGIT_TIMER:
            case DP_MSG_CANCEL_OFFHOOK_TIMER:
                dp_process_msg(syshdr->Cmd, msg);
                break;

            case SUB_MSG_B2BCNF_SUBSCRIBE_RESP:
            case SUB_MSG_B2BCNF_NOTIFY:
            case SUB_MSG_B2BCNF_TERMINATE:
                sub_process_b2bcnf_msg(syshdr->Cmd, msg);
                break;

            case SUB_MSG_FEATURE_SUBSCRIBE_RESP:
            case SUB_MSG_FEATURE_NOTIFY:
            case SUB_MSG_FEATURE_TERMINATE:
                sub_process_feature_msg(syshdr->Cmd, msg);
                break;

            case SUB_MSG_KPML_SUBSCRIBE:
            case SUB_MSG_KPML_TERMINATE:
            case SUB_MSG_KPML_NOTIFY_ACK:
            case SUB_MSG_KPML_SUBSCRIBE_TIMER:
            case SUB_MSG_KPML_DIGIT_TIMER:
                kpml_process_msg(syshdr->Cmd, msg);
                break;

            case REG_MGR_STATE_CHANGE:
                gsm_reset();
                break;
            case THREAD_UNLOAD:
                destroy_gsm_thread();
                break;

            default:
                GSM_ERR_MSG(GSM_F_PREFIX"Unknown message\n", fname);
                break;
            }

            cprReleaseSysHeader(syshdr);
            if (release_msg == TRUE) {
                cprReleaseBuffer(msg);
            }
            
            /* Check if there are pending messages for dcsm 
             * if it in the right state perform its operation 
             */
            dcsm_process_jobs();
        }
    }
}