⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleua.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * Note that Route URI SHOULD have an ";lr" parameter!	 */	/* Get the SDP body to be put in the outgoing INVITE, by asking	 * media endpoint to create one for us. The SDP will contain all	 * codecs that have been registered to it (in this case, only	 * PCMA and PCMU), plus telephony event.	 */	status = pjmedia_endpt_create_sdp( g_med_endpt,	    /* the media endpt	*/					   dlg->pool,	    /* pool.		*/					   1,		    /* # of streams	*/					   &g_med_skinfo,   /* RTP sock info	*/					   &local_sdp);	    /* the SDP result	*/	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);	/* Create the INVITE session, and pass the SDP returned earlier	 * as the session's initial capability.	 */	status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv);	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);	/* Create initial INVITE request.	 * This INVITE request will contain a perfectly good request and 	 * an SDP body as well.	 */	status = pjsip_inv_invite(g_inv, &tdata);	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);	/* Send initial INVITE request. 	 * From now on, the invite session's state will be reported to us	 * via the invite session callbacks.	 */	status = pjsip_inv_send_msg(g_inv, tdata);	PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);    } else {	/* No URL to make call to */	PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls..."));    }    /* Loop until one call is completed */    for (;!g_complete;) {	pj_time_val timeout = {0, 10};	pjsip_endpt_handle_events(g_endpt, &timeout);    }    /* On exit, dump current memory usage: */    dump_pool_usage(THIS_FILE, &cp);    return 0;}/* * Callback when INVITE session state has changed. * This callback is registered when the invite session module is initialized. * We mostly want to know when the invite session has been disconnected, * so that we can quit the application. */static void call_on_state_changed( pjsip_inv_session *inv, 				   pjsip_event *e){    PJ_UNUSED_ARG(e);    if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {	PJ_LOG(3,(THIS_FILE, "Call DISCONNECTED [reason=%d (%s)]", 		  inv->cause,		  pjsip_get_status_text(inv->cause)->ptr));	PJ_LOG(3,(THIS_FILE, "One call completed, application quitting..."));	g_complete = 1;    } else {	PJ_LOG(3,(THIS_FILE, "Call state changed to %s", 		  pjsip_inv_state_name(inv->state)));    }}/* This callback is called when dialog has forked. */static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e){    /* To be done... */    PJ_UNUSED_ARG(inv);    PJ_UNUSED_ARG(e);}/* * Callback when incoming requests outside any transactions and any * dialogs are received. We're only interested to hande incoming INVITE * request, and we'll reject any other requests with 500 response. */static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){    pjsip_dialog *dlg;    pjmedia_sdp_session *local_sdp;    pjsip_tx_data *tdata;    unsigned options = 0;    pj_status_t status;    /*      * Respond (statelessly) any non-INVITE requests with 500      */    if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {	if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {	    pj_str_t reason = pj_str("Simple UA unable to handle "				     "this request");	    pjsip_endpt_respond_stateless( g_endpt, rdata, 					   500, &reason,					   NULL, NULL);	}	return PJ_TRUE;    }    /*     * Reject INVITE if we already have an INVITE session in progress.     */    if (g_inv) {	pj_str_t reason = pj_str("Another call is in progress");	pjsip_endpt_respond_stateless( g_endpt, rdata, 				       500, &reason,				       NULL, NULL);	return PJ_TRUE;    }    /* Verify that we can handle the request. */    status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,				      g_endpt, NULL);    if (status != PJ_SUCCESS) {	pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");	pjsip_endpt_respond_stateless( g_endpt, rdata, 				       500, &reason,				       NULL, NULL);	return PJ_TRUE;    }     /*     * Create UAS dialog.     */    status = pjsip_dlg_create_uas( pjsip_ua_instance(), 				   rdata,				   NULL, /* contact */				   &dlg);    if (status != PJ_SUCCESS) {	pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,				      NULL, NULL);	return PJ_TRUE;    }    /*      * Get media capability from media endpoint:      */    status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 1,				       &g_med_skinfo, 				       &local_sdp);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /*      * Create invite session, and pass both the UAS dialog and the SDP     * capability to the session.     */    status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /*     * Initially send 180 response.     *     * The very first response to an INVITE must be created with     * pjsip_inv_initial_answer(). Subsequent responses to the same     * transaction MUST use pjsip_inv_answer().     */    status = pjsip_inv_initial_answer(g_inv, rdata, 				      180, 				      NULL, NULL, &tdata);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /* Send the 180 response. */      status = pjsip_inv_send_msg(g_inv, tdata);     PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /*     * Now create 200 response.     */    status = pjsip_inv_answer( g_inv, 			       200, NULL,	/* st_code and st_text */			       NULL,		/* SDP already specified */			       &tdata);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /*     * Send the 200 response.     */    status = pjsip_inv_send_msg(g_inv, tdata);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);    /* Done.      * When the call is disconnected, it will be reported via the callback.     */    return PJ_TRUE;} /* * Callback when SDP negotiation has completed. * We are interested with this callback because we want to start media * as soon as SDP negotiation is completed. */static void call_on_media_update( pjsip_inv_session *inv,				  pj_status_t status){    pjmedia_session_info sess_info;    const pjmedia_sdp_session *local_sdp;    const pjmedia_sdp_session *remote_sdp;    pjmedia_port *media_port;    if (status != PJ_SUCCESS) {	app_perror(THIS_FILE, "SDP negotiation has failed", status);	/* Here we should disconnect call if we're not in the middle 	 * of initializing an UAS dialog and if this is not a re-INVITE.	 */	return;    }    /* Get local and remote SDP.     * We need both SDPs to create a media session.     */    status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);    status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);    /* Create session info based on the two SDPs.      * We only support one stream per session for now.     */    status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt, 					   1, &sess_info, 					   local_sdp, remote_sdp);    if (status != PJ_SUCCESS) {	app_perror( THIS_FILE, "Unable to create media session", status);	return;    }    /* If required, we can also change some settings in the session info,     * (such as jitter buffer settings, codec settings, etc) before we     * create the session.     */    /* Create new media session, passing the two SDPs, and also the     * media socket that we created earlier.     * The media session is active immediately.     */    status = pjmedia_session_create( g_med_endpt, &sess_info,				     &g_med_transport, NULL, &g_med_session );    if (status != PJ_SUCCESS) {	app_perror( THIS_FILE, "Unable to create media session", status);	return;    }    /* Get the media port interface of the first stream in the session.      * Media port interface is basicly a struct containing get_frame() and     * put_frame() function. With this media port interface, we can attach     * the port interface to conference bridge, or directly to a sound     * player/recorder device.     */    pjmedia_session_get_port(g_med_session, 0, &media_port);    /* Create a sound Player device and connect the media port to the     * sound device.     */    status = pjmedia_snd_port_create_player( 		    inv->pool,				/* pool		    */		    -1,					/* sound dev id	    */		    media_port->info.clock_rate,	/* clock rate	    */		    media_port->info.channel_count,	/* channel count    */		    media_port->info.samples_per_frame, /* samples per frame*/		    media_port->info.bits_per_sample,   /* bits per sample  */		    0,					/* options	    */		    &g_snd_player);    if (status != PJ_SUCCESS) {	app_perror( THIS_FILE, "Unable to create sound player", status);	PJ_LOG(3,(THIS_FILE, "%d %d %d %d",	    	    media_port->info.clock_rate,	/* clock rate	    */		    media_port->info.channel_count,	/* channel count    */		    media_port->info.samples_per_frame, /* samples per frame*/		    media_port->info.bits_per_sample    /* bits per sample  */	    ));	return;    }    status = pjmedia_snd_port_connect(g_snd_player, media_port);    /* Create a sound recorder device and connect the media port to the     * sound device.     */    status = pjmedia_snd_port_create_rec( 		    inv->pool,				/* pool		    */		    -1,					/* sound dev id	    */		    media_port->info.clock_rate,	/* clock rate	    */		    media_port->info.channel_count,	/* channel count    */		    media_port->info.samples_per_frame, /* samples per frame*/		    media_port->info.bits_per_sample,   /* bits per sample  */		    0,					/* options	    */		    &g_snd_rec);    if (status != PJ_SUCCESS) {	app_perror( THIS_FILE, "Unable to create sound recorder", status);	return;    }    status = pjmedia_snd_port_connect(g_snd_rec, media_port);    /* Done with media. */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -