Example #1
0
/*
 *  Function: ccUnload
 *
 *  Description:
 *         - deinit portable runtime.
 *         - Cleanup call control modules, GSM and SIp Stack
 *
 *  Parameters: none
 *
 *  Returns: none
 *
 */
void
ccUnload (void)
{
    static const char fname[] = "ccUnload";

    DEF_DEBUG(DEB_F_PREFIX"ccUnload called..\n", DEB_F_PREFIX_ARGS(SIP_CC_INIT, fname));
    if (platform_initialized == FALSE) 
    {
        TNP_DEBUG(DEB_F_PREFIX"system is not loaded, ignore unload\n", DEB_F_PREFIX_ARGS(SIP_CC_INIT, fname));
        return;
    }
    /*
     * We are going to send an unload msg to each of the thread, which on
     * receiving the msg, will kill itself.
    */
    send_task_unload_msg(CC_SRC_SIP);
    send_task_unload_msg(CC_SRC_GSM);

    if (FALSE == gHardCodeSDPMode) {
    	send_task_unload_msg(CC_SRC_MISC_APP);
    }

    send_task_unload_msg(CC_SRC_CCAPP);

    cprSleep(200);

    gStopTickTask = TRUE;
}
Example #2
0
int
TickerTask (void *a)
{
    TNP_DEBUG(DEB_F_PREFIX"Ticker Task initialized..\n", DEB_F_PREFIX_ARGS(SIP_CC_INIT, "TickerTask"));
    while (FALSE == gStopTickTask) {
        cprSleep(20);
        MAIN0Timer();
    }
    return 0;
}
Example #3
0
cpr_status_e
cprSocketCleanup (void)
{
    if (initialized == FALSE) {
        return CPR_SUCCESS;
    }

    /* wait for all of the sockets to close before cleaning up */
    cprSleep(500);

    if (WSACleanup() == SOCKET_ERROR) {
        /* startup failed */
        return CPR_FAILURE;
    }
    initialized = FALSE;

    return CPR_SUCCESS;
}
/**
 * cpr_timer_pre_init
 *
 * @brief Initalize timer service and client IPC
 *
 * @return CPR_SUCCESS or CPR_FAILURE
 */
cprRC_t cpr_timer_pre_init (void)
{
    static const char fname[] = "cpr_timer_pre_init";
    int32_t returnCode;

    /* start the timer service first */
    returnCode = (int32_t)pthread_create(&timerThreadId, NULL, timerThread, NULL);
    if (returnCode == -1) {
        CPR_ERROR("%s: Failed to create Timer Thread : %s\n", fname, strerror(errno));
        return CPR_FAILURE;
    }

    /*
     * wait some time so that timer service thread is up
     * TBD:we should really implement wait on timerthread using condvar.
     */
    cprSleep(1000);

    return CPR_SUCCESS;
}
/**
 *  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 #6
0
/**
 * Place a message on a particular queue.  Note that caller may
 * block (see comments below)
 *
 * @param msgQueue   - msg queue on which to place the message
 * @param msg        - pointer to the msg to place on the queue
 * @param ppUserData - pointer to a pointer to user defined data
 *
 * @return CPR_SUCCESS or CPR_FAILURE, errno provided
 *
 * @note 1. Messages queues are set to be non-blocking, those cases
 *       where the system call fails with a would-block error code
 *       (EAGAIN) the function will attempt other mechanisms described
 *       below.
 * @note 2. If enabled with an extended message queue, either via a
 *       call to cprCreateMessageQueue with depth value or a call to
 *       cprSetExtendMessageQueueDepth() (when unit testing), the message
 *       will be added to the extended message queue and the call will
 *       return successfully.  When room becomes available on the
 *       system's message queue, those messages will be added.
 * @note 3. If the message queue becomes full and no space is availabe
 *       on the extended message queue, then the function will attempt
 *       to resend the message up to CPR_ATTEMPTS_TO_SEND and the
 *       calling thread will *BLOCK* CPR_SND_TIMEOUT_WAIT_INTERVAL
 *       milliseconds after each failed attempt.  If unsuccessful
 *       after all attempts then EGAIN error code is returned.
 * @note 4. This applies to all CPR threads, including the timer thread.
 *       So it is possible that the timer thread would be forced to
 *       sleep which would have the effect of delaying all active
 *       timers.  The work to fix this rare situation is not considered
 *       worth the effort to fix....so just leaving as is.
 */
cprRC_t
cprSendMessage (cprMsgQueue_t msgQueue, void *msg, void **ppUserData)
{
    static const char fname[] = "cprSendMessage";
    static const char error_str[] = "%s: Msg not sent to %s queue: %s\n";
    cpr_msgq_post_result_e rc;
    cpr_msg_queue_t *msgq;
    int16_t attemptsToSend = CPR_ATTEMPTS_TO_SEND;
    uint16_t numAttempts   = 0;

    /* Bad application? */
    if (msgQueue == NULL) {
        CPR_ERROR(error_str, fname, "undefined", "invalid input");
        errno = EINVAL;
        return CPR_FAILURE;
    }

    msgq = (cpr_msg_queue_t *) msgQueue;

    /*
     * Attempt to send message
     */
    do {

        /*
         * Post the message to the Queue
         */
        rc = cprPostMessage(msgq, msg, ppUserData);

        if (rc == CPR_MSGQ_POST_SUCCESS) {
            cprPegSendMessageStats(msgq, numAttempts);
            return CPR_SUCCESS;
        } else if (rc == CPR_MSGQ_POST_FAILED) {
            CPR_ERROR("%s: Msg not sent to %s queue: %d\n",
                      fname, msgq->name, errno);
            msgq->sendErrors++;
            /*
             * If posting to calling thread's own queue,
             * then peg the self queue error.
             */
            if (pthread_self() == msgq->thread) {
                msgq->selfQErrors++;
            }

            return CPR_FAILURE;
        }


        /*
         * Did not succeed in sending the message, so continue
         * to attempt up to the CPR_ATTEMPTS_TO_SEND.
         */
        attemptsToSend--;
        if (attemptsToSend > 0) {
            /*
             * Force a context-switch of the thread attempting to
             * send the message, in order to help the case where
             * the msg queue is full and the owning thread may get
             * a a chance be scheduled so it can drain it (Note:
             * no guarantees, more of a "last-ditch effort" to
             * recover...especially when temporarily over-whelmed).
             */
            cprSleep(CPR_SND_TIMEOUT_WAIT_INTERVAL);
            msgq->reTries++;
            numAttempts++;
        }
    } while (attemptsToSend > 0);

    CPR_ERROR(error_str, fname, msgq->name, "FULL");
    msgq->sendErrors++;
    return CPR_FAILURE;
}
Example #7
0
/*
 *  Function: send_task_unload_msg
 *
 *  Description:
 *         - send shutdown and thread destroy msg to sip, gsm, ccapp, misc
 *           threads
 *  Parameters:  destination thread
 *
 *  Returns: none
 *
 */
void
send_task_unload_msg(cc_srcs_t dest_id)
{
    const char *fname = "send_task_unload_msg";
    uint16_t len = 4;
    cprBuffer_t  msg =  gsm_get_buffer(len);
    int  sdpmode = 0;

    config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));

    if (msg == NULL) {
        err_msg("%s: failed to allocate  msg cprBuffer_t\n", fname);
        return;
    }

    DEF_DEBUG(DEB_F_PREFIX"send Unload message to %s task ..\n",
        DEB_F_PREFIX_ARGS(SIP_CC_INIT, fname),
        dest_id == CC_SRC_SIP ? "SIP" :
        dest_id == CC_SRC_GSM ? "GSM" :
        dest_id == CC_SRC_MISC_APP ? "Misc App" :
        dest_id == CC_SRC_CCAPP ? "CCApp" : "Unknown");

    switch(dest_id) {
        case CC_SRC_SIP:
        {
            /* send this msg so phone can send unRegister msg */
            SIPTaskPostShutdown(SIP_EXTERNAL, CC_CAUSE_SHUTDOWN, "");
            /* allow unRegister msg to sent out and shutdown to complete */

            if (!sdpmode) {
                cprSleep(2000);
            }
            /* send a unload message to the SIP Task to kill sip thread*/
            msg =  SIPTaskGetBuffer(len);
            if (msg == NULL) {
                err_msg("%s:%d: failed to allocate sip msg buffer\n", fname);
                return;
            }

            if (SIPTaskSendMsg(THREAD_UNLOAD, (cprBuffer_t)msg, len, NULL) == CPR_FAILURE)
            {
                cpr_free(msg);
                err_msg("%s: Unable to send THREAD_UNLOAD msg to sip thread", fname);
            }
        }
        break;
        case CC_SRC_GSM:
        {
            msg =  gsm_get_buffer(len);
            if (msg == NULL) {
                err_msg("%s: failed to allocate  gsm msg cprBuffer_t\n", fname);
                return;
            }
            if (CPR_FAILURE == gsm_send_msg(THREAD_UNLOAD, msg, len)) {
                err_msg("%s: Unable to send THREAD_UNLOAD msg to gsm thread", fname);
            }
        }
        break;
        case CC_SRC_MISC_APP:
        {
            msg = cpr_malloc(len);
            if (msg == NULL) {
                err_msg("%s: failed to allocate  misc msg cprBuffer_t\n", fname);
                return;
            }
            if (CPR_FAILURE == MiscAppTaskSendMsg(THREAD_UNLOAD, msg, len)) {
                err_msg("%s: Unable to send THREAD_UNLOAD msg to Misc App thread", fname);
            }
        }
        break;
        case CC_SRC_CCAPP:
        {
            msg = cpr_malloc(len);
            if (msg == NULL) {
                err_msg("%s: failed to allocate  ccapp msg cprBuffer_t\n", fname);
                return;
            }
            if (ccappTaskPostMsg(CCAPP_THREAD_UNLOAD, msg, len, CCAPP_CCPROVIER) == CPR_FAILURE )
            {
                err_msg("%s: Unable to send THREAD_UNLOAD msg to CCapp thread", fname);
            }
            err_msg("%s:  send UNLOAD msg to CCapp thread good", fname);
        }
        break;

        default:
            err_msg("%s: Unknown destination task passed=%d.", fname, dest_id);
        break;
    }
}