使用eXsip和ORTP通话(一)

来源:互联网 发布:阿里云java开发手册 编辑:程序博客网 时间:2024/05/18 01:36
#include "stdafx.h"   
#include "YouToo.h"   
#include "YouTooDlg.h"   
   
#define WAIT_TIMER 200          //事件检测时间间隔ms   
#define REG_TIMER  30*1000      //注册时间间隔ms   
   
bool build_media(int local_port, const char *remote_ip,    
                 int remote_port, int payload, const char *fmtp, int jitter, bool ec, int bitrate);   
   
CYouTooDlg *dlg_wnd = NULL;   
   
AudioStream *audio = NULL;   
RtpProfile *profile = NULL;   
RtpSession *session = NULL;   
OrtpEvQueue *q = NULL;   

#ifdef _DEBUG   
#define new DEBUG_NEW   
#undef THIS_FILE   
static char THIS_FILE[] = __FILE__;   
#endif   

#define DEBUG_INFO debug_info->AddString   

UINT sip_ua_monitor(void *pArg)   
  
    bool ret = false;   
    char *payload_str;                     
    char localip[128];   
    char tmp[4096];     

    CString dtmf_str;   
    char dtmf[50] = {0};    

    int reg_remain = REG_TIMER;    

    CYouTooDlg *pMainWnd = (CYouTooDlg *)pArg;   
    CListBox *debug_info = ((CListBox *)pMainWnd->GetDlgItem(IDC_INFO));    

    DEBUG_INFO("Event monitor for ua[c|s] start!");    

    eXosip_event_t *uac_e;                 
    osip_message_t *ack = NULL;            
    osip_message_t *answer = NULL;          

       
    sdp_message_t * msg_rsp = NULL;   
    sdp_connection_t * con_rsp = NULL;   
    sdp_media_t * md_rsp = NULL;   
   
       
    sdp_message_t * msg_req = NULL;   
    sdp_connection_t * con_req = NULL;   
    sdp_media_t * md_req = NULL;    

    char out_str[100] = {0};    

    eXosip_lock ();   
    eXosip_automatic_action();   
    eXosip_unlock ();    

    while(pMainWnd->doing)   
    {   
        eXosip_lock ();   
        uac_e = eXosip_event_wait (0, WAIT_TIMER);   
        eXosip_unlock ();    

        reg_remain = reg_remain - WAIT_TIMER;   
        if(reg_remain < 0)   
        {   
            //超时,重新注册   
            eXosip_lock ();   
            eXosip_automatic_refresh();   
            eXosip_unlock ();   
            reg_remain = REG_TIMER;   
            DEBUG_INFO("register timeout,retry!");   
        }   
   
        if(pMainWnd->dtmfing)   
        {          
            ((CEdit *)pMainWnd->GetDlgItem(IDC_DTMF_STR))->GetWindowText(dtmf_str);   
            strcpy(dtmf, dtmf_str.GetBuffer(dtmf_str.GetLength()));    
   
            for(int index=0; index<50; index++)   
            {   
                //依次读取字符   
                if(dtmf[index] == '\0') break;   
                   
                   
                eXosip_lock();   
                audio_stream_send_dtmf(audio, dtmf[index]);   
                eXosip_unlock();   
   
                sprintf(out_str, "DTMF send <%c> OK!", dtmf[index]);   
                DEBUG_INFO(out_str);   
                Sleep(500);   
            }    

            pMainWnd->dtmfing = false;   
        }    

        if (uac_e == NULL)   
        {   
            //DEBUG_INFO("nothing");   
            continue;   
        }    

        eXosip_lock ();   
        eXosip_default_action(uac_e);      
        eXosip_unlock ();   
   
        if(NULL != uac_e->response)   
        {   
            //UAC 消息处理前检查   
            sprintf(out_str, "%d %s", uac_e->response->status_code, uac_e->response->reason_phrase);   
            DEBUG_INFO(out_str);    
            if(487 == uac_e->response->status_code)   
            {   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(取消呼叫成功)");   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(true);                  
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(false);   
                continue;   
            }    

            if(480 == uac_e->response->status_code)   
            {   
                //480 无应答   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(true);      
                pMainWnd->GetDlgItem(IDC_ACCEPT)->EnableWindow(true);    
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(false);                 
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(无应答)");   
                   
                //隐藏接通按钮显示呼叫按钮   
                ((CButton *)pMainWnd->GetDlgItem(IDC_ACCEPT))->ShowWindow(SW_HIDE);   
                ((CButton *)pMainWnd->GetDlgItem(IDC_DIAL))->ShowWindow(SW_SHOWNORMAL);   
                   
                pMainWnd->picked = false;   
                pMainWnd->calling = false;   
                pMainWnd->call_id = 0;   
                pMainWnd->dialog_id = 0;                
                continue;   
            }   
        }    

        if(NULL != uac_e->request)   
        {   
        }   
   
        if(NULL != uac_e->ack)   
        {   
        }   
           
        switch (uac_e->type)   
        {   
            case EXOSIP_CALL_SERVERFAILURE:   
            case EXOSIP_CALL_RELEASED:   
                   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(true);      
                pMainWnd->GetDlgItem(IDC_ACCEPT)->EnableWindow(true);    
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(false);                 
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(对方或服务器正忙!)");   
                   
                //隐藏接通按钮显示呼叫按钮   
                ((CButton *)pMainWnd->GetDlgItem(IDC_ACCEPT))->ShowWindow(SW_HIDE);   
                ((CButton *)pMainWnd->GetDlgItem(IDC_DIAL))->ShowWindow(SW_SHOWNORMAL);   
                   
                pMainWnd->call_id = 0;   
                pMainWnd->dialog_id = 0;   
                pMainWnd->picked = false;   
                pMainWnd->calling = false;   
                   
                DEBUG_INFO("Dest or Server Busy!");   
                break;   
   
               
            case EXOSIP_CALL_INVITE:   
                sprintf(out_str, "收到来自 %s 的呼叫!",uac_e->request->from->url->string);   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText(out_str);   
   
                eXosip_lock ();   
                eXosip_call_send_answer(uac_e->tid, 180, NULL);   
                if(0 != eXosip_call_build_answer(uac_e->tid, 200, &answer))   
                {   
                    eXosip_call_send_answer(uac_e->tid, 603, NULL);   
                    AfxMessageBox("error build answer!");   
                    continue;   
                }   
                eXosip_unlock ();   
                   
                pMainWnd->call_id = uac_e->cid;                  //供挂断电话上下文操作   
                pMainWnd->dialog_id = uac_e->did;   
   
                   
                eXosip_guess_localip(AF_INET, localip, 128);   
                snprintf (tmp, 4096,   
                    "v=0\r\n"   
                    "o=youtoo 1 1 IN IP4 %s\r\n"   
                    "s=##youtoo demo\r\n"   
                    "c=IN IP4 %s\r\n"   
                    "t=0 0\r\n"   
                    "m=audio %d RTP/AVP 0 8 101\r\n"   
                    "a=rtpmap:0 PCMU/8000\r\n"   
                    "a=rtpmap:8 PCMA/8000\r\n"   
                    "a=rtpmap:101 telephone-event/8000\r\n"   
                    "a=fmtp:101 0-15\r\n", localip, localip, pMainWnd->rtp_port);   
                   
                //设置回复的SDP消息体,下一步计划分析消息体   
                eXosip_lock ();   
                osip_message_set_body(answer, tmp, strlen(tmp));   
                osip_message_set_content_type(answer, "application/sdp");   
                   
                   
                msg_req = eXosip_get_remote_sdp(uac_e->did);   
                con_req = eXosip_get_audio_connection(msg_req);   
                md_req = eXosip_get_audio_media(msg_req);   
                eXosip_unlock ();   
                   
                   
                   
                //隐藏呼叫按钮显示接听按钮   
                ((CButton *)pMainWnd->GetDlgItem(IDC_ACCEPT))->ShowWindow(SW_SHOWNORMAL);   
                ((CButton *)pMainWnd->GetDlgItem(IDC_DIAL))->ShowWindow(SW_HIDE);   
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(true);   
   
                pMainWnd->calling = true;   
   
                while(!pMainWnd->picked)   
                {   
                    //未接通进入循环检测   
                    Sleep(200);   
                }   
   
                eXosip_unlock ();   
                eXosip_call_send_answer(uac_e->tid, 200, answer);   
                eXosip_unlock ();   
   
                DEBUG_INFO("200 ok 发送");   
                break;   
   
            case EXOSIP_CALL_CANCELLED:   
                   
                //隐藏接通按钮显示呼叫按钮   
                ((CButton *)pMainWnd->GetDlgItem(IDC_ACCEPT))->ShowWindow(SW_HIDE);   
                ((CButton *)pMainWnd->GetDlgItem(IDC_DIAL))->ShowWindow(SW_SHOWNORMAL);   
                   
                pMainWnd->call_id = 0;   
                pMainWnd->dialog_id = 0;                
                pMainWnd->picked = false;   
                pMainWnd->calling = false;   
                pMainWnd->GetDlgItem(IDC_REG_STATUS)->SetWindowText("(已拒绝)");   
                break;   
   
            case EXOSIP_CALL_ACK:   
                   
                if(pMainWnd->calling)   
                {   
                       
                    ret = build_media(pMainWnd->rtp_port, con_req->c_addr, atoi(md_req->m_port), 0, NULL, 0, 0, 0);   
                    if(!ret)   
                    {   
                        AfxMessageBox("媒体建立失败,无法创建通话,请挂断!");   
                        //pMainWnd->OnHang();   
                    }                  
                }   
                break;   
   
               
            case EXOSIP_REGISTRATION_SUCCESS:   
                if(0 < uac_e->response->contacts.nb_elt)      
                {   
                    pMainWnd->GetDlgItem(IDC_REG_STATUS)->SetWindowText("(已登录)");   
                    pMainWnd->GetDlgItem(IDC_REG)->EnableWindow(false);   
                    pMainWnd->GetDlgItem(IDC_UNREG)->EnableWindow(true);   
   
                    if(0 == pMainWnd->call_id)   
                    {   
                        //第一次手动注册成功时   
                        pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(true);   
                    }   
                }   
                else   
                {   
                    pMainWnd->GetDlgItem(IDC_REG_STATUS)->SetWindowText("(已注销)");   
                    pMainWnd->GetDlgItem(IDC_REG)->EnableWindow(true);   
                    pMainWnd->GetDlgItem(IDC_UNREG)->EnableWindow(false);   
                    pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(false);   
                    pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(false);   
                }   
                break;   
   
            case EXOSIP_CALL_CLOSED:   
                if(audio)    
                {   
                    //被动关闭媒体连接(远端触发)   
                    eXosip_lock ();   
                    audio_stream_stop(audio);   
                       
                    ortp_ev_queue_destroy(q);   
                    rtp_profile_destroy(profile);   
                    eXosip_unlock ();   
   
                    audio = NULL;   
                    q = NULL;   
                    profile = NULL;   
                    DEBUG_INFO("audio stream stoped!");   
                }   
   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(对方已挂断)");   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(true);      
                pMainWnd->GetDlgItem(IDC_ACCEPT)->EnableWindow(true);    
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(false);                 
   
                //隐藏接通按钮显示呼叫按钮   
                ((CButton *)pMainWnd->GetDlgItem(IDC_ACCEPT))->ShowWindow(SW_HIDE);   
                ((CButton *)pMainWnd->GetDlgItem(IDC_DIAL))->ShowWindow(SW_SHOWNORMAL);   
                   
                pMainWnd->call_id = 0;   
                pMainWnd->dialog_id = 0;                
                pMainWnd->picked = false;   
                pMainWnd->calling = false;   
                break;   
                   
            case EXOSIP_CALL_PROCEEDING:   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(查找连接中..)");   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(false);                 
                break;   
   
            case EXOSIP_CALL_RINGING:   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(对方振铃)");   
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(true);              
                pMainWnd->call_id = uac_e->cid;   
                pMainWnd->dialog_id = uac_e->did;   
   
                   
                break;   
                   
            case EXOSIP_CALL_ANSWERED:   
                //ring_stop(ring_p);                   
                pMainWnd->GetDlgItem(IDC_CALL_STATUS)->SetWindowText("(对方已接听)");   
                pMainWnd->GetDlgItem(IDC_DIAL)->EnableWindow(false);                 
                pMainWnd->GetDlgItem(IDC_HANG)->EnableWindow(true);          
                   
                pMainWnd->call_id = uac_e->cid;   
                pMainWnd->dialog_id = uac_e->did;   
                   
                eXosip_lock ();   
                eXosip_call_build_ack (uac_e->did, &ack);   
                eXosip_call_send_ack (uac_e->did, ack);   
   
                   
                msg_rsp = eXosip_get_sdp_info(uac_e->response);   
                con_rsp = eXosip_get_audio_connection(msg_rsp);   
                md_rsp = eXosip_get_audio_media(msg_rsp);   
   
                   
                payload_str = (char *)osip_list_get(&md_rsp->m_payloads, 0);   
                eXosip_unlock ();   
   
                   
                ret = build_media(pMainWnd->rtp_port, con_rsp->c_addr, atoi(md_rsp->m_port), atoi(payload_str), NULL, 0, 0, 0);   
                if(!ret)   
                {   
                    AfxMessageBox("媒体建立失败,无法创建通话,请挂断!");   
                    //pMainWnd->OnHang();   
                }   
                break;   
   
            default:   
                break;   
        }   
           
        eXosip_event_free (uac_e);   
   
           
        debug_info->SetCurSel(debug_info->GetCount()-1);   
    }   
       
    return 0;   
0 0
原创粉丝点击