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,®);
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,®);
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;
}