基于eXosip的SIP客户端

来源:互联网 发布:网页代码编写软件 编辑:程序博客网 时间:2024/05/20 00:36

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 "SipContact.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; //呼叫idstatic int m_nDlg_id = -1;  //绘话idstatic 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 <jack@atosc.org> * * 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 32unsigned 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 CALLBACKSpeakerCallback (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 CALLBACKWaveInCallback (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;}intos_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;}voidos_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 - <jack@atosc.org>*/#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! */}#endifint 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;}
0 0
原创粉丝点击