SipContact.h:
#ifndef _SIP_CONTACT_H_
#define _SIP_CONTACT_H_
#include "SoftPhoneDataDef.h"
#include <eXosip2/eXosip.h>
class CSipContact
{
public:
CSipContact(void);
~CSipContact(void);
public:
void Start();
private:
//注册操作
eXosip_event_type_t Registeration(int nLisPort,int expires);
public:
//取消注册操作
eXosip_event_type_t UnRegisteration();
//发起呼叫
int Invite(const char* destUserid);
//接听
void Answer();
//挂断
void Hold();
//退出
void Exit();
private:
struct UserMrg m_sUser;//登录用户
int m_nAdTrPort; //音频传输端口
//int nCall_id; //呼叫id
//int nDlg_id; //回话id
};
#endif
SipContact.cpp:
#include "SipContact.h"
#include <winsock2.h>
#include <osip2/osip_mt.h>
#include <osip2/osip.h>
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
#include <osipparser2/osip_md5.h>
#include <eXosip2/eX_call.h>
#include "jcalls.h"
static int m_nCall_id = -1; //呼叫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,®);
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 <jack@atosc.org>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with dpkg; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "jcalls.h"
#include "sdptools.h"
#include <osip2/osip_mt.h>
#ifdef WIN32
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
#pragma comment(lib, "Winmm.lib")
WAVEFORMATEX wfx;
#define MAX_IN_BUFFERS 32
#define USED_IN_BUFFERS 6
#define MAX_OUT_BUFFERS 32
#define USED_OUT_BUFFERS 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