程式架構與寫法介紹:b92043/homework/檔案...網際網路電話系統作業一程式說明文件...

14
網際網路電話系統作業一程式說明文件 資工四 B92902043 徐瑞澤 程式架構與寫法介紹: 助教您好,這次的作業我按照投影片上的說明在 SimpRTPDlg.cpp 中的 CSimRTPDlg 程序加入 cclRTPStartup(2)以初始化 RTP 的物件並設定最大 channel 數為 2,接著由於我有做使用者可以指定 port 的功能,所以 RTPOpenPort()這邊 先不做,等到設定 peeraddress 的時候會再執行。 接著在 OnOK 程序中利用以下程式碼: m_WaveIOObj->wavInClose(); m_WaveIOObj->wavOutClose(); WavIO 關閉,然後我加入以下的程式碼處理使用者自訂的 portfor (i=0; i<10; i++) { assign_port[i] = '\0'; } i = 0; while(IP[i] != ':' && i < 100) { i += 1; } if (i == 100) { flag = 1; newport = 9000; } if (flag == 0) { m = i; j = 0; i += 1; while(IP[i] != '\0') { assign_port[j] = IP[i]; i += 1; j += 1; } newport = atoi(assign_port); for(i=m; i<100; i++) { IP[i] = '\0'; } }

Upload: others

Post on 26-Feb-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

  • 網際網路電話系統作業一程式說明文件

    資工四 B92902043 徐瑞澤

    程式架構與寫法介紹:

    助教您好,這次的作業我按照投影片上的說明在 SimpRTPDlg.cpp 中的CSimRTPDlg 程序加入 cclRTPStartup(2)以初始化 RTP 的物件並設定最大 channel數為 2,接著由於我有做使用者可以指定 port 的功能,所以 RTPOpenPort()這邊先不做,等到設定 peeraddress 的時候會再執行。 接著在 OnOK 程序中利用以下程式碼: m_WaveIOObj->wavInClose();

    m_WaveIOObj->wavOutClose(); 把 WavIO 關閉,然後我加入以下的程式碼處理使用者自訂的 port:

    for (i=0; i

  • 其中 newport 是我在 SimRTPDlg.cpp 檔案開頭自訂的一個 Global Variable,目的

    是儲存使用者自訂的 Port,接著執行 RTPPeerConnect(IP, newport)。

    另外為了達到使用者自訂 Port 的功能,我修改了 cclRtp.c 檔案,其中 cclRTPOpen

    修改如下:

    RETCODE cclRTPOpen(int channel, int rtpPacketSiz, int port)

    {

    if( channel=MAX_RTP_CHANS )

    return -1;

    if( rtp[channel] ) {

    RTP_PACKET_SIZ[channel] = rtpPacketSiz;

    return 1;

    }

    rtp[channel] = rtp_open(port,0);

    if( !rtp[channel] )

    return -1;

    rtcp[channel] = rtcp_open(port+1,0);

    if( !rtcp[channel] )

    return -1;

    return 0;

    }

    我在這個函數的參數列尾端新增了一個 port 的變數,以記錄使用者自訂的 Port

    Number,另外在執行 rtp_open()與 rtcp_open()的地方,將第一個參數換成 port 與

    port+1,這樣 Local 端的 port 才可以設成使用者自訂的 Port。

    程式功能與操作方法:

    如上,使用者輸入對方電腦的 IP 位址,對方也輸入自己電腦的 IP 位址,就會使用

    預設的 Port9000 連線,如果輸入對方電腦的 IP 位址之後加一個冒號,後面接上欲使用

    的 Port 號碼,對方也輸入自己電腦的 IP 位址加上 Port 號碼,就可以使用指定的 Port

    傳輸資料,如下是使用 port9500 做傳輸,圖示如下:

  • SimRTPDlg.cpp Source Code:

    // SimRTPDlg.cpp : implementation file

    //

    #include "stdafx.h"

    #include "SimRTP.h"

    #include "SimRTPDlg.h"

    #include "cclRtp.c"

    //#include "WavInOut.cpp"

    #ifdef _DEBUG

    #define new DEBUG_NEW

    #undef THIS_FILE

    static char THIS_FILE[] = __FILE__;

    #endif

    char IP[100];

    int newport = 9000;

    ///////////////////////////////////////////////////////////////////////////

    //

    // CAboutDlg dialog used for App About

    class CAboutDlg : public CDialog

    {

    public:

    CAboutDlg();

    // Dialog Data

    //{{AFX_DATA(CAboutDlg)

    enum { IDD = IDD_ABOUTBOX };

  • //}}AFX_DATA

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CAboutDlg)

    protected:

    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

    //}}AFX_VIRTUAL

    // Implementation

    protected:

    //{{AFX_MSG(CAboutDlg)

    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()

    };

    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

    {

    //{{AFX_DATA_INIT(CAboutDlg)

    //}}AFX_DATA_INIT

    }

    void CAboutDlg::DoDataExchange(CDataExchange* pDX)

    {

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CAboutDlg)

    //}}AFX_DATA_MAP

    }

    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

    //{{AFX_MSG_MAP(CAboutDlg)

    // No message handlers

    //}}AFX_MSG_MAP

    END_MESSAGE_MAP()

    ///////////////////////////////////////////////////////////////////////////

    //

    // CSimRTPDlg dialog

  • static CSimRTPDlg* csimrtpdlg = NULL;

    CSimRTPDlg::CSimRTPDlg(CWnd* pParent /*=NULL*/)

    : CDialog(CSimRTPDlg::IDD, pParent)

    {

    //{{AFX_DATA_INIT(CSimRTPDlg)

    csimrtpdlg = this;

    //}}AFX_DATA_INIT

    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32

    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    //-----------------------------------

    //cclRTPStartup add here

    cclRTPStartup(2);

    //-----------------------------------

    m_RtpChan=0;

    m_BufRTP2IO=adtBufferNew(4096);

    m_BufIO2RTP=adtBufferNew(4096);

    m_WaveIOObj = WavInOut::instance();

    m_WaveIOObj->init(Wav2RTP,RTP2Wav);

    //-----------------------------------

    //RTPOpenPort add here

    //RTPOpenPort();

    //-----------------------------------

    m_bUDP=TRUE;

    m_bTCP=FALSE;

    m_bCallAuto=TRUE;

    m_flag = TRUE;

    }

    void CSimRTPDlg::DoDataExchange(CDataExchange* pDX)

    {

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CSimRTPDlg)

    DDX_Control(pDX, IDOK, m_OK);

  • DDX_Control(pDX, IDC_EDIT1, m_IP_CTL);

    //}}AFX_DATA_MAP

    }

    BEGIN_MESSAGE_MAP(CSimRTPDlg, CDialog)

    //{{AFX_MSG_MAP(CSimRTPDlg)

    ON_WM_SYSCOMMAND()

    ON_WM_PAINT()

    ON_WM_QUERYDRAGICON()

    ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)

    //}}AFX_MSG_MAP

    END_MESSAGE_MAP()

    ///////////////////////////////////////////////////////////////////////////

    //

    // CSimRTPDlg message handlers

    BOOL CSimRTPDlg::OnInitDialog()

    {

    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.

    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);

    if (pSysMenu != NULL)

    {

    CString strAboutMenu;

    strAboutMenu.LoadString(IDS_ABOUTBOX);

    if (!strAboutMenu.IsEmpty())

    {

    pSysMenu->AppendMenu(MF_SEPARATOR);

    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

    }

  • }

    // Set the icon for this dialog. The framework does this automatically

    // when the application's main window is not a dialog

    SetIcon(m_hIcon, TRUE); // Set big icon

    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here

    m_IP_CTL.SetFocus();

    return TRUE; // return TRUE unless you set the focus to a control

    }

    void CSimRTPDlg::OnSysCommand(UINT nID, LPARAM lParam)

    {

    if ((nID & 0xFFF0) == IDM_ABOUTBOX)

    {

    CAboutDlg dlgAbout;

    dlgAbout.DoModal();

    }

    else

    {

    CDialog::OnSysCommand(nID, lParam);

    }

    }

    // If you add a minimize button to your dialog, you will need the code below

    // to draw the icon. For MFC applications using the document/view model,

    // this is automatically done for you by the framework.

    void CSimRTPDlg::OnPaint()

    {

    if (IsIconic())

    {

    CPaintDC dc(this); // device context for painting

    SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

    // Center icon in client rectangle

  • int cxIcon = GetSystemMetrics(SM_CXICON);

    int cyIcon = GetSystemMetrics(SM_CYICON);

    CRect rect;

    GetClientRect(&rect);

    int x = (rect.Width() - cxIcon + 1) / 2;

    int y = (rect.Height() - cyIcon + 1) / 2;

    // Draw the icon

    dc.DrawIcon(x, y, m_hIcon);

    }

    else

    {

    CDialog::OnPaint();

    }

    }

    // The system calls this to obtain the cursor to display while the user drags

    // the minimized window.

    HCURSOR CSimRTPDlg::OnQueryDragIcon()

    {

    return (HCURSOR) m_hIcon;

    }

    void CSimRTPDlg::OnCancel()

    {

    // TODO: Add extra cleanup here

    m_WaveIOObj->stopPlaying();

    m_WaveIOObj->stopRecording();

    if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();

    if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();

    CDialog::OnCancel();

    }

    void CSimRTPDlg::OnChangeEdit1()

    {

    // TODO: If this is a RICHEDIT control, the control will not

  • // send this notification unless you override the CDialog::OnInitDialog()

    // function and call CRichEditCtrl().SetEventMask()

    // with the ENM_CHANGE flag ORed into the mask.

    // TODO: Add your control notification handler code here

    }

    void CSimRTPDlg::OnOK()

    {

    //User specified port stored here

    char assign_port[10];

    int i, j;

    int flag = 0;

    int m;

    //-----------------------------------

    // TODO: Add extra validation here

    m_WaveIOObj->wavInClose();

    m_WaveIOObj->wavOutClose();

    //-----------------------------------

    //CDialog::OnOK();

    int t;

    t = m_IP_CTL.GetWindowText(IP, 100);

    for (i=0; i

  • m = i;

    j = 0;

    i += 1;

    while(IP[i] != '\0') {

    assign_port[j] = IP[i];

    i += 1;

    j += 1;

    }

    newport = atoi(assign_port);

    for(i=m; istopPlaying();

    m_WaveIOObj->stopRecording();

    if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();

    if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();

    if( TRUE == m_flag ) {

    m_flag = FALSE;

    m_OK.SetWindowText("掛斷");

    //-----------------------------------

    //RTPPeerConnect add here, assign target ip and port here.

    RTPPeerConnect(IP, newport);

  • //-----------------------------------

    adtBufferClear(m_BufRTP2IO);

    adtBufferClear(m_BufIO2RTP);

    if(m_WaveIOObj->wavInOpen(wavetype,8,8000,1,30)!=0)

    m_IP_CTL.SetWindowText("Open WaveIO Error!");

    else if ( m_WaveIOObj->startRecording()!=0 )

    m_IP_CTL.SetWindowText("Record Error!");

    if(m_WaveIOObj->wavOutOpen(wavetype,8,8000,1,30)!=0)

    m_IP_CTL.SetWindowText("Open WaveOut Error!");

    else if ( m_WaveIOObj->startPlaying()!=0 )

    m_IP_CTL.SetWindowText("Playing Error!");

    }

    else {

    m_flag = TRUE;

    m_OK.SetWindowText("連線");

    }

    }

    int CSimRTPDlg::RTPEventHandler(int channel,const char* buffer,int buflen)

    {

    return adtBufferWrite(csimrtpdlg->m_BufRTP2IO,((char *) buffer),buflen);

    }

    int CSimRTPDlg::Wav2RTP(char* buff, int len)

    {

    char buffer[1024];

    int xlen=0;

    memcpy(buffer,buff,len);

    xlen = cclRTPWrite(csimrtpdlg->m_RtpChan,buffer,len);

    return (xlen>=len)?len:xlen;

    }

    int CSimRTPDlg::RTP2Wav(char* buff, int len)

    {

    return adtBufferRead(csimrtpdlg->m_BufRTP2IO,buff,len);

  • }

    int CSimRTPDlg::MediaConnection()

    {

    return 0;

    }

    int CSimRTPDlg::MediaPlayTone()

    {

    return 0;

    }

    int CSimRTPDlg::Media_RTP_Stop()

    {

    m_WaveIOObj->stopPlaying();

    m_WaveIOObj->stopRecording();

    adtBufferClear(m_BufRTP2IO);

    adtBufferClear(m_BufIO2RTP);

    if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();

    if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();

    cclRTPClose(m_RtpChan);

    adtBufferClear(m_BufRTP2IO);

    adtBufferClear(m_BufIO2RTP);

    return 0;

    }

    int CSimRTPDlg::RTPOpenPort()

    {

    int result=0;

    result=cclRTPOpen(m_RtpChan, 240, newport); /*240 = packet size */

    return result;

    }

  • int CSimRTPDlg::RTPPeerConnect(CString ip,int port) int CSimRTPDlg::RTPPeerConnect(CString ip,int port)

    { {

    CString buf; CString buf;

    buf.Format("[RTP] Open Peer RTP: IP(%s),Port(%d)\n",ip,port); buf.Format("[RTP] Open Peer RTP: IP(%s),Port(%d)\n",ip,port);

    RTPOpenPort(); RTPOpenPort();

    cclRTPSetPeerAddr(m_RtpChan,(LPSTR)(LPCSTR)ip,port); cclRTPSetPeerAddr(m_RtpChan,(LPSTR)(LPCSTR)ip,port);

    buf.Format("[RTP] Get had open RTP listen Port

    (%d)\n",cclRTPGetPort(m_RtpChan));

    buf.Format("[RTP] Get had open RTP listen Port

    (%d)\n",cclRTPGetPort(m_RtpChan));

    cclRTPSetEventHandler(RTPEventHandler); /*set event handler */ cclRTPSetEventHandler(RTPEventHandler); /*set event handler */

    return 0; return 0;

    } }

    RTP封包:

  • RTCP 封包:

    查看程式碼(rtcp.c)的內容與 Ethereal 實際擷取的結果,此程式似乎並無傳送

    RTCP 封包,所以只有附上 RTCP 的規格圖如下。