基于eXosip的SIP客户端

SipContact.h:

#ifndef _SIP_CONTACT_H_
#define _SIP_CONTACT_H_

#include "SoftPhoneDataDef.h"
#include <eXosip2/eXosip.h>

class CSipContact
{
public:
    CSipContact(void);
    ~CSipContact(void);

public:
    void Start();
private:
    //注册操作
    eXosip_event_type_t Registeration(int nLisPort,int expires);
public:
    //取消注册操作
    eXosip_event_type_t UnRegisteration();
    //发起呼叫
    int Invite(const char* destUserid);
    //接听
    void Answer();
    //挂断
    void Hold();
    //退出
    void Exit();
private:
    struct UserMrg m_sUser;//登录用户
    int m_nAdTrPort; //音频传输端口
    //int nCall_id; //呼叫id
    //int nDlg_id; //回话id
};

#endif

SipContact.cpp:

#include "SipCon tact.h"
#include <winsock2.h>
#include <osip2/osip_mt.h>
#include <osip2/osip.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
#include <osipparser2/osip_md5.h>
#include <eXosip2/eX_call.h>
#include "jcalls.h"

static int m_nCall_id = -1; //呼叫id
static int m_nDlg_id = -1;  //绘话id
static int m_nt_id = -1;    

void invite_answer()
{
    sdp_message_t *remote_sdp = NULL; 
    osip_message_t *answer = NULL; 
    char tmp[4096]; 
    char localip[128]; 
    int pos = 0;     //初始化sip 

    if (-1 == m_nt_id)
    {
        return;
    }

    remote_sdp = eXosip_get_remote_sdp (m_nt_id);  
    eXosip_lock ();        
    //eXosip_call_send_answer (m_nt_id, 180, NULL); 
    int i = eXosip_call_build_answer (m_nt_id, 200, &answer);       
    if (i != 0)         
    {            
        printf ("This request msg is invalid!Cann't response!\n");           
        eXosip_call_send_answer (m_nt_id, 400, NULL);         
    }      
    else         
    {           
        eXosip_guess_localip (AF_INET, localip, 128); // 获取本地IP
        //SDP格式
        snprintf (tmp, 4096,
            "v=0\r\n"
            "o=josua 0 0 IN IP4 %s\r\n"// 用户名、ID、版本、网络类型、地址类型、IP地址 
            "s=conversation\r\n" 
            "t=0 0\r\n"
            "a=username:%s\r\n"
            "a=password:%s\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-11\r\n",
            localip,remote_sdp->o_username,remote_sdp->o_addr,2056);           
        osip_message_set_body (answer, tmp, strlen(tmp));            
        osip_message_set_content_type (answer, "application/sdp"); 
        eXosip_call_send_answer (m_nt_id, 200, answer);           
        printf ("send 200 over!\n");         
    }        
    eXosip_unlock ();               
    //显示出在sdp消息体中的 attribute 的内容,里面计划存放我们的信息 

    printf ("the INFO is :\n");        
    while (!osip_list_eol (&remote_sdp->a_attributes, pos))         
    {            
        sdp_attribute_t *at;                       
        at = (sdp_attribute_t *) osip_list_get (&remote_sdp->a_attributes, pos);            
        printf ("%s : %s\n", at->a_att_field, at->a_att_value);
        //这里解释了为什么在SDP消息体中属性a里面存放必须是两列 
        pos ++;         
    } 
}

int josua_event_get()
{
    int counter = 0;
    /* use events to print some info */
    eXosip_event_t *je;
    osip_message_t *ack = NULL;
    osip_message_t *answer = NULL; 

    for (;;)
    {
        je = eXosip_event_wait (0, 50);
        eXosip_lock ();

        eXosip_default_action (je);
        eXosip_automatic_refresh ();

        eXosip_unlock ();
        if (je == NULL)
            break;
        counter++;

        switch(je->type)
        {
        case EXOSIP_MESSAGE_NEW://新的消息到来 
            printf ("EXOSIP_MESSAGE_NEW!\n");  
            eXosip_lock ();
            if (MSG_IS_MESSAGE (je->request))//如果接受到的消息类型是MESSAGE 
            { 
                osip_body_t *body;          
                osip_message_get_body (je->request, 0, &body);          
                printf ("I get the msg is: %s\n", body->body);          
                //printf ("the cid is %s, did is %s\n", je->did, je->cid); 
            }        //按照规则,需要回复200 OK信息 
            eXosip_message_build_answer (je->tid, 200,&answer);       
            eXosip_message_send_answer (je->tid, 200,answer);   
            eXosip_unlock ();
            break;  

        case EXOSIP_REGISTRATION_SUCCESS:// 注册成功
            printf("EXOSIP_REGISTRATION_SUCCESS\n");
            printf("je->rid=%d\n", je->rid);
            break;

        case EXOSIP_REGISTRATION_FAILURE:// 注册失败
            printf("EXOSIP_REGISTRATION_FAILURE\n");
            printf("je->rid=%d\n", je->rid);

            call_serverfailure(je);
            break;

        case EXOSIP_CALL_INVITE:
            //printf ("a new invite reveived!\n");
            printf ("Received a INVITE msg from %s:%s, UserName is %s, password is %s\n",
                je->request->req_uri->host,           
                je->request->req_uri->port, 
                je->request->req_uri->username, 
                je->request->req_uri->password);        //得到消息体,认为该消息就是SDP格式. 
            m_nt_id = je->tid;               
            m_nCall_id = je->cid;
            m_nDlg_id = je->did;              
            printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did);  
            /*eXosip_lock (); eXosip_call_send_answer (m_nt_id, 180, NULL); eXosip_unlock (); */

            call_new (je);//
            //invite_answer();
            break;

        case EXOSIP_CALL_PROCEEDING:
            printf ("proceeding!\n");

            call_proceeding (je);//
            break;

        case EXOSIP_CALL_RINGING:
            printf ("ringing!\n");
            printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did);

            call_ringing(je);//
            break;

        case EXOSIP_CALL_ANSWERED:
            printf ("ok! connected!\n");
            m_nCall_id = je->cid;
            m_nDlg_id = je->did;
            printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did);

            call_answered(je);//
            //eXosip_call_build_ack (je->did, &ack);
            //eXosip_call_send_ack (je->did, ack);
            break;

        case EXOSIP_CALL_NOANSWER:
            printf ("no answer!\n");
            break;

        case EXOSIP_CALL_CLOSED:
            printf ("the other sid closed!\n");
            /*{ int i = eXosip_call_build_answer (je->tid, 200, &answer); if (i != 0) { printf ("This request msg is invalid!Cann't response!\n"); eXosip_call_send_answer (je->tid, 400, NULL); } else { eXosip_call_send_answer (je->tid, 200, answer); printf ("bye send 200 over!\n"); } }*/
            call_closed (je);//
            break;

        case EXOSIP_CALL_ACK:
            printf ("ACK received!\n");

            call_ack(je);//
            break;

        case EXOSIP_CALL_REQUESTFAILURE:
            printf ("%s\n",je->textinfo);

            call_requestfailure (je);
            break;

        case EXOSIP_CALL_RELEASED:
            printf ("%s\n",je->textinfo);

            call_closed (je);//
            break;

        default:
            printf ("other response!\n");
            break;
        }

        eXosip_event_free (je);
    }

    if (counter > 0)
        return 0;

    return -1;
}

//事件监听线程
DWORD WINAPI EventThread(LPVOID pParam)
{
    while(true)
    {
        josua_event_get();
    }
}

CSipContact::CSipContact(void)
{
    strcpy_s(m_sUser.chServerIP,"172.23.50.184");
    strcpy_s(m_sUser.chUserName,"wangconglin");
    strcpy_s(m_sUser.chUserId,"6666");
    strcpy_s(m_sUser.chUserPwd,"123456");
    m_sUser.unServerPort = 5060;
    m_nAdTrPort = 2056; 
    //nCall_id = -1;
    //nDlg_id = -1;
}

CSipContact::~CSipContact(void)
{
    //Exit();
}

//注册操作
eXosip_event_type_t CSipContact::Registeration(int nLisPort,int expires)
{
    //初始化环境
    if (eXosip_init ()) {
        printf("eXosip_init failed\n");

        return EXOSIP_REGISTRATION_TERMINATED;
    }

    int i = eXosip_listen_addr (IPPROTO_UDP, NULL, nLisPort, AF_INET, 0);
    if (i!=0) {
        eXosip_quit();
        printf("could not initialize transport layer\n");

        return EXOSIP_REGISTRATION_TERMINATED;
    }

    //鉴权
    eXosip_clear_authentication_info();
    if (eXosip_add_authentication_info
        (m_sUser.chUserName, m_sUser.chUserId, m_sUser.chUserPwd, NULL, NULL))
    {
        return EXOSIP_REGISTRATION_TERMINATED;
    }

    //接收线程
    HANDLE pEventThread;
    DWORD  nEventThreadID;

    pEventThread = ::CreateThread(NULL,0,
        EventThread, NULL, 0, &nEventThreadID); 

    int ret=0;
    osip_message_t *reg = NULL;
    char *from;
    char *proxy;
    proxy = (char*)malloc(100);
    from = (char*)malloc(100);
    sprintf(from, "sip:%s@%s", m_sUser.chUserId, m_sUser.chServerIP);
    sprintf(proxy, "sip:%s:%d", m_sUser.chServerIP, m_sUser.unServerPort);

    eXosip_lock ();
    int reg_id = eXosip_register_build_initial_register(from, proxy, NULL,expires,&reg);
    if (reg_id< 0)
    {
        eXosip_unlock();
        eXosip_quit();
        printf("could not initialize register\n");

        return EXOSIP_REGISTRATION_TERMINATED;
    }

    ret = eXosip_register_send_register (reg_id, reg);
    eXosip_unlock ();
    if ( ret != 0)
    {
        printf("eXosip_register_send_register error!\n");
        free(from);
        free(proxy);

        return EXOSIP_REGISTRATION_TERMINATED;
    }
    else printf("eXosip_register_send_register success!\n");

    free(proxy);
    free(from);
    return EXOSIP_REGISTRATION_SUCCESS;
}

//发起呼叫
int CSipContact::Invite(const char* destUserid)
{
    osip_message_t *invite = NULL;
    char localip[128];
    char tmp[4096];
    char *source_call;
    char *dest_call;

    source_call = (char*)malloc(100);
    dest_call = (char*)malloc(100);
    sprintf(source_call, "sip:%s@%s", m_sUser.chUserId, m_sUser.chServerIP);
    sprintf(dest_call, "sip:%s@%s", destUserid, m_sUser.chServerIP);

    int i = eXosip_call_build_initial_invite (&invite, dest_call, source_call, NULL, "This si a call for a conversation");
    if (i != 0)
    {
        printf ("Intial INVITE failed!\n");

        return -1;
    }
    osip_message_set_supported (invite, "100rel");  
    eXosip_guess_localip (AF_INET, localip, 128); // 获取本地IP
    //SDP格式
    snprintf (tmp, 4096,
        "v=0\r\n"
        "o=josua 0 0 IN IP4 %s\r\n"// 用户名、ID、版本、网络类型、地址类型、IP地址 
        "s=conversation\r\n" 
        "t=0 0\r\n"
        "a=username:%s\r\n"
        "a=password:%s\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-11\r\n",
        localip,m_sUser.chUserName,m_sUser.chUserPwd,m_nAdTrPort);    

    osip_message_set_body (invite, tmp, strlen(tmp));
    osip_message_set_content_type (invite, "application/sdp");

    eXosip_lock ();
    i = eXosip_call_send_initial_invite (invite);
    eXosip_unlock ();

    return 0;
}

void CSipContact::Start()
{
    if (EXOSIP_REGISTRATION_TERMINATED == Registeration(5060,1800))
    {
        printf("eXosip register terminated!\n");
    }
}

//挂断
void CSipContact::Hold()
{
    printf ("Holded !\n");
    eXosip_lock ();
    eXosip_call_terminate (m_nCall_id, m_nDlg_id);
    eXosip_unlock ();
}

//退出
void CSipContact::Exit()
{
    eXosip_quit ();
    printf ("Exit the setup!\n");
}

//接听
void CSipContact::Answer()
{
    invite_answer();
}

//取消注册操作
eXosip_event_type_t CSipContact::UnRegisteration()
{
    int ret=0;
    osip_message_t *reg = NULL;
    char *from;
    char *proxy;
    proxy = (char*)malloc(100);
    from = (char*)malloc(100);
    sprintf(from, "sip:%s@%s", m_sUser.chUserId, m_sUser.chServerIP);
    sprintf(proxy, "sip:%s:%d", m_sUser.chServerIP, m_sUser.unServerPort);

    eXosip_lock ();
    int reg_id = eXosip_register_build_initial_register(from, proxy, NULL,0,&reg);
    if (reg_id< 0)
    {
        eXosip_unlock();
        eXosip_quit();
        printf("could not initialize register\n");

        return EXOSIP_REGISTRATION_TERMINATED;
    }

    ret = eXosip_register_send_register (reg_id, reg);
    eXosip_unlock ();
    if ( ret != 0)
    {
        printf("eXosip_register_send_register error!\n");
        free(from);
        free(proxy);

        return EXOSIP_REGISTRATION_TERMINATED;
    }
    else printf("eXosip_register_send_register success!\n");

    free(proxy);
    free(from);
    return EXOSIP_REGISTRATION_SUCCESS;
}

wave音频采集与播放及G729a的编解码:

/* * josua - Jack's open sip User Agent * * Copyright (C) 2002,2003 Aymeric Moizard <[email protected]> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with dpkg; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

#include "jcalls.h"
#include "sdptools.h"
#include <osip2/osip_mt.h>

#ifdef WIN32

#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>

#pragma comment(lib, "Winmm.lib") 

WAVEFORMATEX wfx;

#define MAX_IN_BUFFERS 32
#define USED_IN_BUFFERS 6
#define MAX_OUT_BUFFERS 32
#define USED_OUT_BUFFERS 32


unsigned int waveoutDeviceID = WAVE_MAPPER;
WAVEHDR waveHdrOut[MAX_OUT_BUFFERS];
HWAVEOUT hWaveOut;
char dataBufferOut[MAX_OUT_BUFFERS][3200];

unsigned int waveinDeviceID = WAVE_MAPPER;
HWAVEIN hWaveIn;
WAVEHDR waveHdrIn[MAX_IN_BUFFERS];
char dataBufferIn[MAX_IN_BUFFERS][3200];

call_t *current_call = NULL;



extern "C" void va_g729a_init_encoder();
extern "C" void va_g729a_encoder(short *speech, unsigned char *bitstream);
extern "C" void va_g729a_init_decoder();
extern "C" void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);


static void CALLBACK
SpeakerCallback (HWAVEOUT _hWaveOut, UINT uMsg, DWORD dwInstance,
                 DWORD dwParam1, DWORD dwParam2)
{
    WAVEHDR *wHdr;

    switch (uMsg)
    {
    case WOM_OPEN:
        fprintf (stderr, "SpeakerCallback : WOM_OPEN\n");
        break;
    case WOM_CLOSE:
        fprintf (stderr, "SpeakerCallback : WOM_CLOSE\n");
        break;
    case WOM_DONE:
        fprintf (stderr, "SpeakerCallback : WOM_DONE\n");
        wHdr = (WAVEHDR *) dwParam1;
        break;
    default:
        break;
    }
}


static void CALLBACK
WaveInCallback (HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1,
                DWORD dwParam2)
{
    WAVEHDR *wHdr;
    MMRESULT mr = NOERROR;
    char szSendBuffer[1024];
    int nLen = sizeof(szSendBuffer);
    switch (uMsg)
    {
    case WIM_OPEN:
        break;
    case WIM_CLOSE:
        break;
    case WIM_DATA:
        wHdr = (WAVEHDR *) dwParam1;
        if (current_call == NULL)
            return;
        mr = waveInAddBuffer (hWaveIn, &(waveHdrIn[wHdr->dwUser]),
            sizeof (waveHdrIn[wHdr->dwUser]));
        if (mr == MMSYSERR_NOERROR)
        {
            static int timestamp = 0;

            if (current_call)
            {
                EncodeAudioData(wHdr->lpData, wHdr->dwBytesRecorded,
                                szSendBuffer,&nLen);
                rtp_session_send_with_ts (current_call->rtp_session,
                    (BYTE*)szSendBuffer, nLen,
                    timestamp);
                timestamp += nLen;
            }
        }
        break;
    default:
        break;
    }
}

bool EncodeAudioData(char *pin,int len,char* pout,int* lenr)
{
    bool bRet = false;

    va_g729a_encoder((short*)pin,(BYTE*)pout);
    va_g729a_encoder((short*)(pin+320),(BYTE*)pout+20);
    va_g729a_encoder((short*)(pin+640),(BYTE*)pout+40);
    va_g729a_encoder((short*)(pin+800),(BYTE*)pout+50);

    *lenr = 60;

    bRet = true;
RET:
    return bRet;
}

bool DecodeAudioData(char *pin,int len,char* pout,int* lenr)
{
    bool bRet = false;

    va_g729a_decoder((BYTE*)pin,(short*)(pout),0);
    va_g729a_decoder((BYTE*)pin+20,(short*)(pout+320),0);
    va_g729a_decoder((BYTE*)pin+40,(short*)(pout+640),0);
    va_g729a_decoder((BYTE*)pin+50,(short*)(pout+800),0);

    *lenr=960;

    bRet=true;
RET:
    return bRet;
}

int os_sound_init ()
{
    ortp_init ();
    ortp_scheduler_init ();

    va_g729a_init_encoder();
    va_g729a_init_decoder();

    return 0;
}


int open_sndcard (int format)
{
    MMRESULT mr = NOERROR;

    WAVEFORMATEX wfx;
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = 1;
    wfx.nSamplesPerSec = 8000;
    wfx.nAvgBytesPerSec = 1 * 8000 * 16 / 8;
    wfx.nBlockAlign = 16 * 1 / 8;
    wfx.wBitsPerSample = 16;
    wfx.cbSize = 0;

    mr = waveOutOpen (&hWaveOut, waveoutDeviceID, &wfx,(DWORD)0,0,CALLBACK_NULL);
    if (mr == NOERROR)
    {
        int i;

        for (i = 0; i < USED_OUT_BUFFERS; i++)
        {
            memset (&(waveHdrOut[i]), 0, sizeof (waveHdrOut[i]));
            waveHdrOut[i].lpData = dataBufferOut[i];
            waveHdrOut[i].dwBufferLength = 960; /* frameSize */

            waveHdrOut[i].dwFlags = 0;
            waveHdrOut[i].dwUser = i;

            mr = waveOutPrepareHeader (hWaveOut, &(waveHdrOut[i]),sizeof (waveHdrOut[i]));
        }
    }


    mr = waveInOpen (&hWaveIn, waveinDeviceID, &wfx, (DWORD) WaveInCallback, 0,
        CALLBACK_FUNCTION);

    if (mr == MMSYSERR_NOERROR)
    {
        int i;

        for (i = 0; i < MAX_IN_BUFFERS; i++)
        {
            waveHdrIn[i].lpData = dataBufferIn[i];
            waveHdrIn[i].dwBufferLength = 960;    /* frameSize */
            waveHdrIn[i].dwFlags = 0;
            waveHdrIn[i].dwUser = i;
            mr = waveInPrepareHeader (hWaveIn, &(waveHdrIn[i]), sizeof (waveHdrIn[i]));
            if (mr == MMSYSERR_NOERROR)
            {
                mr = waveInAddBuffer (hWaveIn, &(waveHdrIn[i]), sizeof (waveHdrIn[i]));
            }
        }
        mr = waveInStart (hWaveIn);
        if (mr != MMSYSERR_NOERROR)
        {
            exit (-1);
            return -1;
        }
    }
    return 0;
}

void * os_sound_start_thread (void *_ca)
{
    int pos_whdr = 0;
    call_t *ca = (call_t *) _ca;
    char data_in[3000];
    char szBuffer[2048];
    int nLen = 2048;
    int have_more;
    int timestamp = 0;
    int i;

    current_call = ca;

    while (ca->enable_audio != -1)
    {
        int length;
        static int sound_played = 0;
        static int cpt = 0;

        memset (data_in, 0, 3000);
        if (ca->payload == 3)
            length = 260;           /* 280 ?? */
        else
            length = 160;

        i = rtp_session_recv_with_ts (ca->rtp_session, (unsigned char*)data_in, length, timestamp,
            &have_more);
        if (i > 0)
        {
            MMRESULT mr = NOERROR;

            DecodeAudioData(data_in,i,szBuffer,&nLen);

            memset (waveHdrOut[pos_whdr].lpData, 0, length);
            memcpy (waveHdrOut[pos_whdr].lpData, szBuffer, nLen);
            waveHdrOut[pos_whdr].dwBufferLength = nLen;
            mr = waveOutWrite (hWaveOut, &waveHdrOut[pos_whdr],
                sizeof (waveHdrOut[pos_whdr]));

            pos_whdr++;
            if (pos_whdr == USED_OUT_BUFFERS)
            {
                pos_whdr = 0;     /* loop over the prepared blocks */
            }
            if (mr != MMSYSERR_NOERROR)
                switch (mr)
            {
                case MMSYSERR_INVALHANDLE:
                    fprintf (stderr,
                        "__call_free: waveOutWrite: 0x%i MMSYSERR_INVALHANDLE\n",
                        mr);
                    break;
                case MMSYSERR_NODRIVER:
                    fprintf (stderr,
                        "__call_free: waveOutWrite: 0x%i MMSYSERR_NODRIVER\n",
                        mr);
                    break;
                case MMSYSERR_NOMEM:
                    fprintf (stderr,
                        "__call_free: waveOutWrite: 0x%i MMSYSERR_NOMEM\n", mr);
                    break;
                case WAVERR_UNPREPARED:
                    fprintf (stderr,
                        "__call_free: waveOutWrite: 0x%i WAVERR_UNPREPARED\n",
                        mr);
                    break;
                case WAVERR_STILLPLAYING:
                    fprintf (stderr,
                        "__call_free: waveOutWrite: 0x%i WAVERR_STILLPLAYING\n",
                        mr);
                default:
                    fprintf (stderr, "__call_free: waveOutWrite: 0x%i\n", mr);
            } else
                ++sound_played;
            fprintf (stderr, "sound played = %i\n", sound_played);
            fprintf (stderr, "cpt = %i\n", ++cpt);
        }
        timestamp += length;
    }
    current_call = NULL;
    return NULL;
}

int
os_sound_start (call_t * ca, int port)
{
    int format = WAVE_FORMAT_MULAW;
    char localip[128];

    eXosip_guess_localip (AF_INET, localip, 128);


    if (open_sndcard (format) != 0)
        return -1;

    ca->rtp_session = rtp_session_new (RTP_SESSION_SENDRECV);
    rtp_session_set_scheduling_mode (ca->rtp_session, 1); /* yes */
    rtp_session_set_blocking_mode (ca->rtp_session, 1);

    rtp_session_set_profile (ca->rtp_session, &av_profile);
    rtp_session_set_jitter_compensation (ca->rtp_session, 60);
    rtp_session_set_local_addr (ca->rtp_session, localip, port);
    rtp_session_set_remote_addr (ca->rtp_session,
        ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port);
    rtp_session_set_payload_type (ca->rtp_session, ca->payload);
    rtp_session_signal_connect (ca->rtp_session, "telephone-event",
        (RtpCallback) rcv_telephone_event, /*ca*/0);

    ca->audio_thread = osip_thread_create (20000, os_sound_start_thread, ca);
    return 0;
}

void
os_sound_close (call_t * ca)
{
    osip_thread_join (ca->audio_thread);
    osip_free (ca->audio_thread);
    rtp_session_signal_disconnect_by_callback (ca->rtp_session,
        "telephone-event",
        (RtpCallback) rcv_telephone_event);
    rtp_session_destroy (ca->rtp_session);

/* waveInReset (hWaveIn); waveInClose (hWaveIn); waveOutReset (hWaveOut); waveOutClose (hWaveOut);*/
}

#endif

ortp操作:

/* This source has been formatted by an unregistered SourceFormatX */
/* If you want to remove this info, please register this shareware */
/* Please visit http://www.textrush.com to get more information    */

/*
The antisipc program is a modular SIP softphone (SIP -rfc3261-)
Copyright (C) 2005  Aymeric MOIZARD - <[email protected]>
*/

#include <winsock2.h>
#include <osip2/osip_mt.h>
#include <osip2/osip.h>
//#include <osip2/osip_negotiation.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
#include <osipparser2/osip_md5.h>
#include <eXosip2/eXosip.h>
#include <eXosip2/eX_call.h>
#include <ortp/ortp.h>
#include "jcalls.h"
#include "sdptools.h"


call_t calls[MAX_NUMBER_OF_CALLS];
static int ___call_init = 0;

static int __call_init()
{
    int k;

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        memset(&(calls[k]), 0, sizeof(call_t));
        calls[k].state = NOT_USED;
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
    }

#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
    return os_sound_init();
#else
    return 0;
#endif
}

#if defined(ORTP_SUPPORT)
void rcv_telephone_event(RtpSession *rtp_session, call_t *ca)
{
    /* telephone-event received! */
}
#endif

int call_get_number_of_pending_calls(void)
{
    int pos = 0;
    int k;

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED)
        {
            pos++;
        }
    }
    return pos;
}


call_t *call_get_call(int pos)
{
    return  &calls[pos];
}


int call_get_callpos(call_t *ca)
{
    return ca - calls;
}

call_t *call_locate_call_by_cid(int cid)
{
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == cid)
            return  &calls[k];
    }

    return 0;
}


call_t *call_create_call(int cid)
{
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state == NOT_USED)
        {
            memset(&(calls[k]), 0, sizeof(call_t));
            _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
            calls[k].cid = cid;
            calls[k].did =  - 1;
            calls[k].state =  - 1;
            return  &calls[k];
        }

    }

    return 0;
}




call_t *call_locate_call(eXosip_event_t *je, int createit)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        if (!createit)
            return 0;
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return NULL;

        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");

        ca->cid = je->cid;
        ca->did = je->did;

        if (ca->did < 1 && ca->cid < 1)
        {
            exit(0);
            return NULL; /* not enough information for this event?? */
        }
    }


    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);

    ca->state = je->type;
    return ca;

}


call_t *call_find_call(int pos)
{
    int k;

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED)
        {
            if (pos == 0)
                return  &(calls[k]);
            pos--;
        }
    }
    return NULL;
}

int call_new(eXosip_event_t *je)
{
    sdp_message_t *remote_sdp = NULL;
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state == NOT_USED)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);
    memset(&(calls[k]), 0, sizeof(call_t));
    _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");

    ca->cid = je->cid;
    ca->did = je->did;
    ca->tid = je->tid;

    if (ca->did < 1 && ca->cid < 1)
    {
        return  - 1; /* not enough information for this event?? */
    }

    osip_strncpy(ca->textinfo, je->textinfo, 255);

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    if (je->request != NULL)
    {
        char *tmp = NULL;

        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
    os_sound_init();
#endif

    /* negotiate payloads */
    if (je->request != NULL)
    {
        remote_sdp = eXosip_get_sdp_info(je->request);
    }

    if (remote_sdp == NULL)
    {
        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
            "missing SDP in INVITE request\n"));
    }

    if (remote_sdp != NULL)
        /* TODO: else build an offer */
    {
        sdp_connection_t *conn;
        sdp_media_t *remote_med;
        char *tmp = NULL;

        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            eXosip_call_send_answer(ca->tid, 400, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }

        conn = eXosip_get_audio_connection(remote_sdp);
        if (conn != NULL && conn->c_addr != NULL)
        {
            _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
        }
        remote_med = eXosip_get_audio_media(remote_sdp);

        if (remote_med == NULL || remote_med->m_port == NULL)
        {
            /* no audio media proposed */
            eXosip_call_send_answer(ca->tid, 415, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }

        ca->remote_sdp_audio_port = atoi(remote_med->m_port);

        if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0')
        {
            int pos;

            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca
                ->remote_sdp_audio_port));
            pos = 0;
            while (!osip_list_eol(&(remote_med->m_payloads), pos))
            {
                tmp = (char*)osip_list_get(&remote_med->m_payloads, pos);
                if (tmp != NULL && (0 == osip_strcasecmp(tmp, "0") || 0 ==
                    osip_strcasecmp(tmp, "8")))
                {
                    break;
                }
                tmp = NULL;
                pos++;
            }
        }
        if (tmp != NULL)
        {
            ca->payload = atoi(tmp);
        }
        else
        {
            eXosip_call_send_answer(ca->tid, 415, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }

        if (tmp != NULL && (ca->payload == 0 || ca->payload == 8) && ca
            ->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0')

        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "audio connection: (payload=%i) -> %s:%i\n", ca->payload, ca
                ->remote_sdp_audio_ip, ca->remote_sdp_audio_port));
        }
    }
#ifndef TEST_PRACK_SUPPORT
    eXosip_lock();
    eXosip_call_send_answer(ca->tid, 180, NULL);
    eXosip_unlock();
#else

    if (remote_sdp != NULL)
        /* TODO: else build an offer */
    {
        osip_message_t *answer;
        int i;

        eXosip_lock();
        i = eXosip_call_build_answer(ca->tid, 183, &answer);
        if (i == 0)
        {
            osip_message_set_require(answer, "100rel");
            osip_message_set_header(answer, "RSeq", "1");

            //i = sdp_complete_message(ca->did, remote_sdp, answer);
            if (i != 0)
            {
                osip_message_free(answer);
                eXosip_call_send_answer(ca->tid, 415, NULL);
            }
            else
            {
                /* start sending audio */
                if (ca->enable_audio > 0)
                {
                    ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
                    os_sound_close(ca);
#endif
                }

                if (ca->enable_audio != 1)
                    /* audio is started */
                {
                    sdp_message_t *local_sdp;

                    local_sdp = eXosip_get_sdp_info(answer);
                    if (remote_sdp != NULL && local_sdp != NULL)
                    {
                        sdp_connection_t *conn;
                        sdp_media_t *local_med;
                        sdp_media_t *remote_med;
                        char *tmp = NULL;
                        int audio_port = 0;

                        conn = eXosip_get_audio_connection(remote_sdp);
                        if (conn != NULL && conn->c_addr != NULL)
                        {
                            _snprintf(ca->remote_sdp_audio_ip, 50, conn
                                ->c_addr);
                        }
                        remote_med = eXosip_get_audio_media(remote_sdp);
                        if (remote_med != NULL && remote_med->m_port !=
                            NULL)
                        {
                            ca->remote_sdp_audio_port = atoi(remote_med
                                ->m_port);
                        }
                        local_med = eXosip_get_audio_media(local_sdp);
                        if (local_med != NULL && local_med->m_port != NULL)
                        {
                            audio_port = atoi(local_med->m_port);
                        }

                        if (ca->remote_sdp_audio_port > 0 && ca
                            ->remote_sdp_audio_ip[0] != '\0' && local_med
                            != NULL)
                        {
                            OSIP_TRACE(osip_trace(__FILE__, __LINE__,
                                OSIP_WARNING, NULL,
                                "audio connection found: %s:%i\n", ca
                                ->remote_sdp_audio_ip, ca
                                ->remote_sdp_audio_port));

                            tmp = (char*)osip_list_get(local_med
                                ->m_payloads, 0);
                        }
                        if (tmp != NULL)
                        {
                            ca->payload = atoi(tmp);
                        }
                        if (tmp != NULL && audio_port > 0 && ca
                            ->remote_sdp_audio_port > 0 && ca
                            ->remote_sdp_audio_ip[0] != '\0')

                        {
                            OSIP_TRACE(osip_trace(__FILE__, __LINE__,
                                OSIP_WARNING, NULL,
                                "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port));

                            /* search if stream is sendonly or recvonly */
                            ca->remote_sendrecv = _sdp_analyse_attribute
                                (remote_sdp, remote_med);
                            ca->local_sendrecv = _sdp_analyse_attribute
                                (local_sdp, local_med);
                            if (ca->local_sendrecv == _SENDRECV)
                            {
                                if (ca->remote_sendrecv == _SENDONLY)
                                    ca->local_sendrecv = _RECVONLY;
                                else if (ca->remote_sendrecv == _RECVONLY)
                                    ca->local_sendrecv = _SENDONLY;
                            }
#if defined(ORTP_SUPPORT) || defined
                            (UCL_SUPPORT)
                                if (0 == os_sound_start(ca, audio_port))
                                {
                                ca->enable_audio = 1; /* audio is
                                started */
                                }
#endif
                        }
                    }
                    sdp_message_free(local_sdp);
                }

                i = eXosip_call_send_answer(ca->tid, 183, answer);
            }

            if (i != 0)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING,
                    NULL, "cannot send 183 progress?\n"));
            }
            }
            eXosip_unlock();
        }
#endif
        sdp_message_free(remote_sdp);

        ca->state = je->type;
        return 0;
}

int call_ack(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);

    if (je->ack != NULL)
    {
        sdp_message_t *remote_sdp;

        remote_sdp = eXosip_get_sdp_info(je->ack);
        if (remote_sdp != NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
                "SDP detected in ACK!\n"));
        }
        else
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
                "no SDP detected in ACK!\n"));
        }
    }

    if (ca->enable_audio != 1)
        /* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;

        remote_sdp = eXosip_get_remote_sdp(ca->did);
        local_sdp = eXosip_get_local_sdp(ca->did);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
        }
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;

            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }

            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && local_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));

                tmp = (char*)osip_list_get(&local_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')

            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));

                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
                if (0 == os_sound_start(ca, audio_port))
                {
                    ca->enable_audio = 1; /* audio is started */
                }
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }

    ca->state = je->type;
    return 0;
}

int call_remove(call_t *ca)
{
    if (ca == NULL)
        return  - 1;


    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    ca->state = NOT_USED;
    return 0;
}

int call_proceeding(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;

        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");

        ca->cid = je->cid;
        ca->did = je->did;

        if (ca->did < 1 || ca->cid < 1)
        {
            return  - 1; /* not enough information for this event?? */
        }
    }

    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    if (je->request != NULL)
    {
        char *tmp = NULL;

        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }

    ca->state = je->type;
    return 0;

}

int call_ringing(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");

        ca->cid = je->cid;
        ca->did = je->did;

        if (ca->did < 1 || ca->cid < 1)
        {
            return  - 1; /* not enough information for this event?? */
        }
    }

    ca = &(calls[k]);

    ca->cid = je->cid;
    ca->did = je->did;
    ca->tid = je->tid;

    osip_strncpy(ca->textinfo, je->textinfo, 255);

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    if (je->request != NULL)
    {
        char *tmp = NULL;

        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }

    if (ca->enable_audio == 1 && je->response != NULL)
    {
        sdp_message_t *sdp = eXosip_get_sdp_info(je->response);

        if (sdp != NULL)
        {
            /* audio is started and session may just have been modified */
            sdp_message_free(sdp);
        }
    }

    {
        osip_header_t *rseq;

        osip_message_header_get_byname(je->response, "RSeq", 0, &rseq);
        if (rseq != NULL && rseq->hvalue != NULL)
        {
            /* try sending a PRACK */
            osip_message_t *prack = NULL;
            int i;

            eXosip_lock();
            i = eXosip_call_build_prack(ca->tid, &prack);
            if (i != 0)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "Failed to build PRACK request\n"));
            }
            else
            {
                eXosip_call_send_prack(ca->tid, prack);
            }

            eXosip_unlock();
        }
    }

    if (ca->enable_audio != 1)
        /* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;

        local_sdp = eXosip_get_sdp_info(je->request);
        remote_sdp = eXosip_get_sdp_info(je->response);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            /* TODO: remote_sdp = retreive from ack above */
        }
        if (local_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "SDP body was probably in the ACK (TODO)\n"));
        }

        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;

            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }

            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && remote_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));

                tmp = (char*)osip_list_get(&remote_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')

            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));

                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
                if (0 == os_sound_start(ca, audio_port))
                {
                    ca->enable_audio = 1; /* audio is started */
                }
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }

    ca->state = je->type;

    return 0;
}

int call_answered(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");

        ca->cid = je->cid;
        ca->did = je->did;

        if (ca->did < 1 && ca->cid < 1)
        {
            exit(0);
            return  - 1; /* not enough information for this event?? */
        }
    }

    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    if (je->request != NULL)
    {
        char *tmp = NULL;

        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
    eXosip_lock();
    {
        osip_message_t *ack = NULL;
        int i;

        i = eXosip_call_build_ack(ca->did, &ack);
        if (i != 0)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "Cannot build ACK for call!\n"));
        }
        else
        {
            sdp_message_t *local_sdp = NULL;
            sdp_message_t *remote_sdp = NULL;

            if (je->request != NULL && je->response != NULL)
            {
                local_sdp = eXosip_get_sdp_info(je->request);
                remote_sdp = eXosip_get_sdp_info(je->response);
            }
            if (local_sdp == NULL && remote_sdp != NULL)
            {
                /* sdp in ACK */
                i = sdp_complete_message(ca->did, remote_sdp, ack);
                if (i != 0)
                {
                    OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING,
                        NULL, "Cannot complete ACK with sdp body?!\n"));
                }
            }
            sdp_message_free(local_sdp);
            sdp_message_free(remote_sdp);

            eXosip_call_send_ack(ca->did, ack);
        }
    }
    eXosip_unlock();

    if (ca->enable_audio == 1 && je->response != NULL)
    {
        sdp_message_t *sdp = eXosip_get_sdp_info(je->response);

        if (sdp != NULL)
        {
            /* audio is started and session has just been modified */
            ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
            os_sound_close(ca);
#endif
            sdp_message_free(sdp);
        }
    }

    if (ca->enable_audio != 1)
        /* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;

        local_sdp = eXosip_get_sdp_info(je->request);
        remote_sdp = eXosip_get_sdp_info(je->response);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            /* TODO: remote_sdp = retreive from ack above */
        }
        if (local_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "SDP body was probably in the ACK (TODO)\n"));
        }

        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;

            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }

            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && remote_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));

                tmp = (char*)osip_list_get(&remote_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')

            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));

                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
                if (0 == os_sound_start(ca, audio_port))
                {
                    ca->enable_audio = 1; /* audio is started */
                }
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }

    ca->state = je->type;
    return 0;
}

int call_redirected(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);

    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    ca->state = NOT_USED;
    return 0;
}

int call_requestfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }

    if ((je->response != NULL && je->response->status_code == 407) || (je
        ->response != NULL && je->response->status_code == 401))
    {
        /* try authentication */
        return 0;
    }

    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);

    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    ca->state = NOT_USED;
    return 0;
}

int call_serverfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);


    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    ca->state = NOT_USED;
    return 0;
}

int call_globalfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);

    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    ca->state = NOT_USED;
    return 0;
}

int call_closed(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);

    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    ca->state = NOT_USED;
    return 0;
}

int call_modified(eXosip_event_t *je)
{
    call_t *ca;
    int k;

    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }

    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;

    ca = &(calls[k]);
    ca->tid = je->tid;
    osip_strncpy(ca->textinfo, je->textinfo, 255);

    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }

    if (je->request != NULL)
    {
        char *tmp = NULL;

        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
    ca->state = je->type;

    eXosip_lock();
    {
        osip_message_t *answer = NULL;
        int i;

        i = eXosip_call_build_answer(ca->tid, 200, &answer);
        if (i != 0)
        {
            eXosip_call_send_answer(ca->tid, 400, NULL);
            eXosip_unlock();
            return 0;
        }
        else
        {
            sdp_message_t *remote_sdp = NULL;

            if (je->request != NULL)
                remote_sdp = eXosip_get_sdp_info(je->request);
            if (remote_sdp == NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "No remote SDP body found for call\n"));
                /* TODO: sdp in 200 & ACK */
                eXosip_call_send_answer(ca->tid, 200, answer);
            }
            else
            {
                i = sdp_complete_message(ca->did, remote_sdp, answer);
                if (i != 0)
                {
                    sdp_message_free(remote_sdp);
                    osip_message_free(answer);
                    eXosip_call_send_answer(ca->tid, 415, NULL);
                    eXosip_unlock();
                    return 0;
                }
                else
                    eXosip_call_send_answer(ca->tid, 200, answer);
                sdp_message_free(remote_sdp);
            }
        }
    }
    eXosip_unlock();

    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
        os_sound_close(ca);
#endif
    }

    if (ca->enable_audio != 1)
        /* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;

        remote_sdp = eXosip_get_remote_sdp(ca->did);
        local_sdp = eXosip_get_local_sdp(ca->did);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
        }
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;

            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }

            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && local_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));

                tmp = (char*)osip_list_get(&local_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')

            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));

                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
                if (0 == os_sound_start(ca, audio_port))
                {
                    ca->enable_audio = 1; /* audio is started */
                }
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }

    return 0;
}

你可能感兴趣的:(SIP,RTP,Wave,eXosip,g729a)