基于eXosip的SIP客户端

SipContact.h:

#ifndef _SIP_CONTACT_H_
#define _SIP_CONTACT_H_

#include "SoftPhoneDataDef.h"
#include 

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 
#include 
#include 
#include 
#include 
#include 
#include 
#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,"waaaa");
	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 
 *
 * 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 
#ifdef WIN32
#include 
#include 
#include 
#include 
#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 - 
*/

#include 
#include 
#include 
//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "jcalls.h"
#include "sdptools.h"

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

static int __call_init()
{
    int k;
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        memset(&(calls[k]), 0, sizeof(call_t));
        calls[k].state = NOT_USED;
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
    }
	
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
	return os_sound_init();
#else
	return 0;
#endif
}

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

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

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

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

call_t *call_locate_call_by_cid(int cid)
{
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == cid)
            return  &calls[k];
    }
	
    return 0;
}


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

call_t *call_locate_call(eXosip_event_t *je, int createit)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        if (!createit)
            return 0;
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return NULL;
		
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
		
        ca->cid = je->cid;
        ca->did = je->did;
		
        if (ca->did < 1 && ca->cid < 1)
        {
            exit(0);
            return NULL; /* not enough information for this event?? */
        }
    }
	
	
    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    ca->state = je->type;
    return ca;
	
}


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

int call_new(eXosip_event_t *je)
{
    sdp_message_t *remote_sdp = NULL;
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state == NOT_USED)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
    memset(&(calls[k]), 0, sizeof(call_t));
    _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
	
    ca->cid = je->cid;
    ca->did = je->did;
    ca->tid = je->tid;
	
    if (ca->did < 1 && ca->cid < 1)
    {
        return  - 1; /* not enough information for this event?? */
    }
	
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    if (je->request != NULL)
    {
        char *tmp = NULL;
		
        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
	os_sound_init();
#endif
	
    /* negotiate payloads */
    if (je->request != NULL)
    {
        remote_sdp = eXosip_get_sdp_info(je->request);
    }
	
    if (remote_sdp == NULL)
    {
        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
            "missing SDP in INVITE request\n"));
    }
	
    if (remote_sdp != NULL)
		/* TODO: else build an offer */
    {
        sdp_connection_t *conn;
        sdp_media_t *remote_med;
        char *tmp = NULL;
		
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            eXosip_call_send_answer(ca->tid, 400, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }
		
        conn = eXosip_get_audio_connection(remote_sdp);
        if (conn != NULL && conn->c_addr != NULL)
        {
            _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
        }
        remote_med = eXosip_get_audio_media(remote_sdp);
		
        if (remote_med == NULL || remote_med->m_port == NULL)
        {
            /* no audio media proposed */
            eXosip_call_send_answer(ca->tid, 415, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }
		
        ca->remote_sdp_audio_port = atoi(remote_med->m_port);
		
        if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0')
        {
            int pos;
			
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca
                ->remote_sdp_audio_port));
            pos = 0;
            while (!osip_list_eol(&(remote_med->m_payloads), pos))
            {
                tmp = (char*)osip_list_get(&remote_med->m_payloads, pos);
                if (tmp != NULL && (0 == osip_strcasecmp(tmp, "0") || 0 ==
                    osip_strcasecmp(tmp, "8")))
                {
                    break;
                }
                tmp = NULL;
                pos++;
            }
        }
        if (tmp != NULL)
        {
            ca->payload = atoi(tmp);
        }
        else
        {
            eXosip_call_send_answer(ca->tid, 415, NULL);
            sdp_message_free(remote_sdp);
            return 0;
        }
		
        if (tmp != NULL && (ca->payload == 0 || ca->payload == 8) && ca
            ->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0')
			
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "audio connection: (payload=%i) -> %s:%i\n", ca->payload, ca
                ->remote_sdp_audio_ip, ca->remote_sdp_audio_port));
        }
    }
#ifndef TEST_PRACK_SUPPORT
	eXosip_lock();
	eXosip_call_send_answer(ca->tid, 180, NULL);
	eXosip_unlock();
#else
	
	if (remote_sdp != NULL)
		/* TODO: else build an offer */
	{
		osip_message_t *answer;
		int i;
		
		eXosip_lock();
		i = eXosip_call_build_answer(ca->tid, 183, &answer);
		if (i == 0)
		{
			osip_message_set_require(answer, "100rel");
			osip_message_set_header(answer, "RSeq", "1");
			
			//i = sdp_complete_message(ca->did, remote_sdp, answer);
			if (i != 0)
			{
				osip_message_free(answer);
				eXosip_call_send_answer(ca->tid, 415, NULL);
			}
			else
			{
				/* start sending audio */
				if (ca->enable_audio > 0)
				{
					ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
					os_sound_close(ca);
#endif
				}
				
				if (ca->enable_audio != 1)
					/* audio is started */
				{
					sdp_message_t *local_sdp;
					
					local_sdp = eXosip_get_sdp_info(answer);
					if (remote_sdp != NULL && local_sdp != NULL)
					{
						sdp_connection_t *conn;
						sdp_media_t *local_med;
						sdp_media_t *remote_med;
						char *tmp = NULL;
						int audio_port = 0;
						
						conn = eXosip_get_audio_connection(remote_sdp);
						if (conn != NULL && conn->c_addr != NULL)
						{
							_snprintf(ca->remote_sdp_audio_ip, 50, conn
								->c_addr);
						}
						remote_med = eXosip_get_audio_media(remote_sdp);
						if (remote_med != NULL && remote_med->m_port !=
							NULL)
						{
							ca->remote_sdp_audio_port = atoi(remote_med
								->m_port);
						}
						local_med = eXosip_get_audio_media(local_sdp);
						if (local_med != NULL && local_med->m_port != NULL)
						{
							audio_port = atoi(local_med->m_port);
						}
						
						if (ca->remote_sdp_audio_port > 0 && ca
							->remote_sdp_audio_ip[0] != '\0' && local_med
							!= NULL)
						{
							OSIP_TRACE(osip_trace(__FILE__, __LINE__,
								OSIP_WARNING, NULL,
								"audio connection found: %s:%i\n", ca
								->remote_sdp_audio_ip, ca
								->remote_sdp_audio_port));
							
							tmp = (char*)osip_list_get(local_med
								->m_payloads, 0);
						}
						if (tmp != NULL)
						{
							ca->payload = atoi(tmp);
						}
						if (tmp != NULL && audio_port > 0 && ca
							->remote_sdp_audio_port > 0 && ca
							->remote_sdp_audio_ip[0] != '\0')
							
						{
							OSIP_TRACE(osip_trace(__FILE__, __LINE__,
								OSIP_WARNING, NULL,
								"audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port));
							
							/* search if stream is sendonly or recvonly */
							ca->remote_sendrecv = _sdp_analyse_attribute
								(remote_sdp, remote_med);
							ca->local_sendrecv = _sdp_analyse_attribute
								(local_sdp, local_med);
							if (ca->local_sendrecv == _SENDRECV)
							{
								if (ca->remote_sendrecv == _SENDONLY)
									ca->local_sendrecv = _RECVONLY;
								else if (ca->remote_sendrecv == _RECVONLY)
									ca->local_sendrecv = _SENDONLY;
							}
#if defined(ORTP_SUPPORT) || defined
							(UCL_SUPPORT)
								if (0 == os_sound_start(ca, audio_port))
								{
								ca->enable_audio = 1; /* audio is
								started */
								}
#endif
						}
					}
					sdp_message_free(local_sdp);
				}
				
				i = eXosip_call_send_answer(ca->tid, 183, answer);
			}
			
			if (i != 0)
			{
				OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING,
					NULL, "cannot send 183 progress?\n"));
			}
            }
            eXosip_unlock();
        }
#endif
		sdp_message_free(remote_sdp);
		
		ca->state = je->type;
		return 0;
}

int call_ack(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
    if (je->ack != NULL)
    {
        sdp_message_t *remote_sdp;
		
        remote_sdp = eXosip_get_sdp_info(je->ack);
        if (remote_sdp != NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
                "SDP detected in ACK!\n"));
        }
        else
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
                "no SDP detected in ACK!\n"));
        }
    }
	
    if (ca->enable_audio != 1)
		/* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;
		
        remote_sdp = eXosip_get_remote_sdp(ca->did);
        local_sdp = eXosip_get_local_sdp(ca->did);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
        }
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;
			
            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }
			
            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && local_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));
				
                tmp = (char*)osip_list_get(&local_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')
				
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));
				
                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
				if (0 == os_sound_start(ca, audio_port))
				{
					ca->enable_audio = 1; /* audio is started */
				}
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }
	
    ca->state = je->type;
    return 0;
}

int call_remove(call_t *ca)
{
    if (ca == NULL)
        return  - 1;
	
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    ca->state = NOT_USED;
    return 0;
}

int call_proceeding(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;
		
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
		
        ca->cid = je->cid;
        ca->did = je->did;
		
        if (ca->did < 1 || ca->cid < 1)
        {
            return  - 1; /* not enough information for this event?? */
        }
    }
	
    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    if (je->request != NULL)
    {
        char *tmp = NULL;
		
        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
	
    ca->state = je->type;
    return 0;
	
}

int call_ringing(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
		
        ca->cid = je->cid;
        ca->did = je->did;
		
        if (ca->did < 1 || ca->cid < 1)
        {
            return  - 1; /* not enough information for this event?? */
        }
    }
	
    ca = &(calls[k]);
	
    ca->cid = je->cid;
    ca->did = je->did;
    ca->tid = je->tid;
	
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    if (je->request != NULL)
    {
        char *tmp = NULL;
		
        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
	
    if (ca->enable_audio == 1 && je->response != NULL)
    {
        sdp_message_t *sdp = eXosip_get_sdp_info(je->response);
		
        if (sdp != NULL)
        {
            /* audio is started and session may just have been modified */
            sdp_message_free(sdp);
        }
    }
	
    {
        osip_header_t *rseq;
		
        osip_message_header_get_byname(je->response, "RSeq", 0, &rseq);
        if (rseq != NULL && rseq->hvalue != NULL)
        {
            /* try sending a PRACK */
            osip_message_t *prack = NULL;
            int i;
			
            eXosip_lock();
            i = eXosip_call_build_prack(ca->tid, &prack);
            if (i != 0)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "Failed to build PRACK request\n"));
            }
            else
            {
                eXosip_call_send_prack(ca->tid, prack);
            }
			
            eXosip_unlock();
        }
    }
	
    if (ca->enable_audio != 1)
		/* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;
		
        local_sdp = eXosip_get_sdp_info(je->request);
        remote_sdp = eXosip_get_sdp_info(je->response);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            /* TODO: remote_sdp = retreive from ack above */
        }
        if (local_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "SDP body was probably in the ACK (TODO)\n"));
        }
		
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;
			
            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }
			
            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && remote_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));
				
                tmp = (char*)osip_list_get(&remote_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')
				
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));
				
                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
				if (0 == os_sound_start(ca, audio_port))
				{
					ca->enable_audio = 1; /* audio is started */
				}
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }
	
    ca->state = je->type;
    
    return 0;
}

int call_answered(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
    {
        for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
        {
            if (calls[k].state == NOT_USED)
                break;
        }
        if (k == MAX_NUMBER_OF_CALLS)
            return  - 1;
        ca = &(calls[k]);
        memset(&(calls[k]), 0, sizeof(call_t));
        _snprintf(calls[k].wav_file, 256, "%s", "ringback.wav");
		
        ca->cid = je->cid;
        ca->did = je->did;
		
        if (ca->did < 1 && ca->cid < 1)
        {
            exit(0);
            return  - 1; /* not enough information for this event?? */
        }
    }
	
    ca = &(calls[k]);
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    if (je->request != NULL)
    {
        char *tmp = NULL;
		
        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
    eXosip_lock();
    {
        osip_message_t *ack = NULL;
        int i;
		
        i = eXosip_call_build_ack(ca->did, &ack);
        if (i != 0)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "Cannot build ACK for call!\n"));
        }
        else
        {
            sdp_message_t *local_sdp = NULL;
            sdp_message_t *remote_sdp = NULL;
			
            if (je->request != NULL && je->response != NULL)
            {
                local_sdp = eXosip_get_sdp_info(je->request);
                remote_sdp = eXosip_get_sdp_info(je->response);
            }
            if (local_sdp == NULL && remote_sdp != NULL)
            {
                /* sdp in ACK */
                i = sdp_complete_message(ca->did, remote_sdp, ack);
                if (i != 0)
                {
                    OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING,
                        NULL, "Cannot complete ACK with sdp body?!\n"));
                }
            }
            sdp_message_free(local_sdp);
            sdp_message_free(remote_sdp);
			
            eXosip_call_send_ack(ca->did, ack);
        }
    }
    eXosip_unlock();
	
    if (ca->enable_audio == 1 && je->response != NULL)
    {
        sdp_message_t *sdp = eXosip_get_sdp_info(je->response);
		
        if (sdp != NULL)
        {
            /* audio is started and session has just been modified */
            ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
			os_sound_close(ca);
#endif
            sdp_message_free(sdp);
        }
    }
	
    if (ca->enable_audio != 1)
		/* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;
		
        local_sdp = eXosip_get_sdp_info(je->request);
        remote_sdp = eXosip_get_sdp_info(je->response);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
            /* TODO: remote_sdp = retreive from ack above */
        }
        if (local_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "SDP body was probably in the ACK (TODO)\n"));
        }
		
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;
			
            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }
			
            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && remote_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));
				
                tmp = (char*)osip_list_get(&remote_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')
				
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));
				
                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
				if (0 == os_sound_start(ca, audio_port))
				{
					ca->enable_audio = 1; /* audio is started */
				}
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }
	
    ca->state = je->type;
    return 0;
}

int call_redirected(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    ca->state = NOT_USED;
    return 0;
}

int call_requestfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
	
    if ((je->response != NULL && je->response->status_code == 407) || (je
        ->response != NULL && je->response->status_code == 401))
    {
        /* try authentication */
        return 0;
    }
	
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    ca->state = NOT_USED;
    return 0;
}

int call_serverfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    ca->state = NOT_USED;
    return 0;
}

int call_globalfailure(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    ca->state = NOT_USED;
    return 0;
}

int call_closed(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }	
    ca->state = NOT_USED;
    return 0;
}

int call_modified(eXosip_event_t *je)
{
    call_t *ca;
    int k;
	
    if (___call_init == 0)
    {
        ___call_init =  - 1;
        __call_init();
    }
	
    for (k = 0; k < MAX_NUMBER_OF_CALLS; k++)
    {
        if (calls[k].state != NOT_USED && calls[k].cid == je->cid &&
            calls[k].did == je->did)
            break;
    }
    if (k == MAX_NUMBER_OF_CALLS)
        return  - 1;
	
    ca = &(calls[k]);
    ca->tid = je->tid;
    osip_strncpy(ca->textinfo, je->textinfo, 255);
	
    if (je->response != NULL)
    {
        ca->status_code = je->response->status_code;
        _snprintf(ca->reason_phrase, 50, je->response->reason_phrase);
    }
	
    if (je->request != NULL)
    {
        char *tmp = NULL;
		
        osip_from_to_str(je->request->from, &tmp);
        if (tmp != NULL)
        {
            _snprintf(ca->remote_uri, 256, "%s", tmp);
            osip_free(tmp);
        }
    }
    ca->state = je->type;
	
    eXosip_lock();
    {
        osip_message_t *answer = NULL;
        int i;
		
        i = eXosip_call_build_answer(ca->tid, 200, &answer);
        if (i != 0)
        {
            eXosip_call_send_answer(ca->tid, 400, NULL);
            eXosip_unlock();
            return 0;
        }
        else
        {
            sdp_message_t *remote_sdp = NULL;
			
            if (je->request != NULL)
                remote_sdp = eXosip_get_sdp_info(je->request);
            if (remote_sdp == NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "No remote SDP body found for call\n"));
                /* TODO: sdp in 200 & ACK */
                eXosip_call_send_answer(ca->tid, 200, answer);
            }
            else
            {
                i = sdp_complete_message(ca->did, remote_sdp, answer);
                if (i != 0)
                {
                    sdp_message_free(remote_sdp);
                    osip_message_free(answer);
                    eXosip_call_send_answer(ca->tid, 415, NULL);
                    eXosip_unlock();
                    return 0;
                }
                else
                    eXosip_call_send_answer(ca->tid, 200, answer);
                sdp_message_free(remote_sdp);
            }
        }
    }
    eXosip_unlock();
	
    if (ca->enable_audio > 0)
    {
        ca->enable_audio =  - 1;
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
		os_sound_close(ca);
#endif
    }
	
    if (ca->enable_audio != 1)
		/* audio is started */
    {
        sdp_message_t *remote_sdp;
        sdp_message_t *local_sdp;
		
        remote_sdp = eXosip_get_remote_sdp(ca->did);
        local_sdp = eXosip_get_local_sdp(ca->did);
        if (remote_sdp == NULL)
        {
            OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                "No remote SDP body found for call\n"));
        }
        if (remote_sdp != NULL && local_sdp != NULL)
        {
            sdp_connection_t *conn;
            sdp_media_t *local_med;
            sdp_media_t *remote_med;
            char *tmp = NULL;
            int audio_port = 0;
			
            conn = eXosip_get_audio_connection(remote_sdp);
            if (conn != NULL && conn->c_addr != NULL)
            {
                _snprintf(ca->remote_sdp_audio_ip, 50, conn->c_addr);
            }
            remote_med = eXosip_get_audio_media(remote_sdp);
            if (remote_med != NULL && remote_med->m_port != NULL)
            {
                ca->remote_sdp_audio_port = atoi(remote_med->m_port);
            }
            local_med = eXosip_get_audio_media(local_sdp);
            if (local_med != NULL && local_med->m_port != NULL)
            {
                audio_port = atoi(local_med->m_port);
            }
			
            if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] !=
                '\0' && local_med != NULL)
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip,
                    ca->remote_sdp_audio_port));
				
                tmp = (char*)osip_list_get(&local_med->m_payloads, 0);
            }
            if (tmp != NULL)
            {
                ca->payload = atoi(tmp);
            }
            if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0
                && ca->remote_sdp_audio_ip[0] != '\0')		
            {
                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL,
                    "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload,
                    audio_port, ca->remote_sdp_audio_ip, ca
                    ->remote_sdp_audio_port));
				
                /* search if stream is sendonly or recvonly */
                ca->remote_sendrecv = _sdp_analyse_attribute(remote_sdp,
                    remote_med);
                ca->local_sendrecv = _sdp_analyse_attribute(local_sdp,
                    local_med);
                if (ca->local_sendrecv == _SENDRECV)
                {
                    if (ca->remote_sendrecv == _SENDONLY)
                        ca->local_sendrecv = _RECVONLY;
                    else if (ca->remote_sendrecv == _RECVONLY)
                        ca->local_sendrecv = _SENDONLY;
                }
#if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT)
				if (0 == os_sound_start(ca, audio_port))
				{
					ca->enable_audio = 1; /* audio is started */
				}
#endif
            }
        }
        sdp_message_free(local_sdp);
        sdp_message_free(remote_sdp);
    }
	
    return 0;
}

你可能感兴趣的:(SIP,C/C++,SIP,eXosip,rtp,wave,g729a)