http://blog.sina.com.cn/s/blog_59d649610100cqme.html
sip网络电话
首先要配置环境,需要这么几个库,libosip,libeXosip2,ortp,mediastreamer2.
libosip,libeXosip2这两个库是负责信令部分的,ortp,medastreamer2是负责媒体流传输的。如果想了解更多的关于这些库方面的信息,可以去网上搜索,会有很多相关的信息,总之学习不要怕麻烦。是师傅令进门,修行在个人。学习sip要看rfc3261 3265 3550 4353 ,还有eXosip,osip,ortp,mediastreamer2的帮助手册等。资料多了才好学习嘛。
sipAPI:http://www.gnu.org/software/osip/doc/html/group__oSIP__MESSAGE.html
eXosipAPI:http://www.antisip.com/doc/exosip2/group__eXosip2__sdp.html#gdab1e84d04b387ada72e0d548444f3c0
ortpAPI:http://download.savannah.gnu.org/releases-noredirect/linphone/ortp/docs/ortp_8h.html
mediastreamerAPI:http://www.antisip.com/doc/mediastreamer2/mscommon_8h.html
以上紧紧作为参考,并不是很全,如果想细细的研究分析,建议自己去看源码。哈,虽然会很累,但是效果很好。
下面这段是注册代码:
#include <eXosip2/eXosip.h>
#include <osip2/osip_mt.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
// ip_url 为服务器ip,
int myregister(char *ip_url,char *port,char *username,char * password)
{
int i;
char identity[50];
char registerer[50];
char localip[128];
static int flag = 0;
int id;
eXosip_guess_localip (AF_INET, localip, 128);
sprintf(identity,"sip:%s@%s",username,localip);
sprintf(registerer,"sip:%s:%s",ip_url,port);
//初始化
if( flag == 0)
{
i = eXosip_init();
if (i != 0)
{
return -1;
}
printf("eXosip_init success\n");
flag ++;
i = eXosip_listen_addr(IPPROTO_UDP, NULL, 5060, AF_INET, 0);
if (i != 0)
{
eXosip_quit();
fprintf(stderr, "could not initialize transport layer\n");
return -1;
}
printf("eXosip_listen_addr success\n");
}
osip_message_t *reg = NULL;
eXosip_lock();
id = eXosip_register_build_initial_register (identity,registerer, NULL, 1800, ®);
printf("id = %d", id);
if (id < 0)
{
eXosip_unlock();
fprintf (stderr, "eXosip_register_build_initial_register failed:(bad arguments?)\n");
return 0;
}
eXosip_lock();
i = eXosip_register_send_register(id, reg);
if (i != 0)
{
fprintf (stderr, "eXosip_register_send_register failed: (bad arguments?)\n");
return 0;
}
eXosip_unlock ();
printf("eXosip_register_send_register OK\n");
eXosip_event_t *je;
for (;;)
{
je = eXosip_event_wait (0, 50);
eXosip_lock();
eXosip_automatic_action ();
eXosip_unlock();
if (je == NULL)
{
continue;
}
if (je->type == EXOSIP_REGISTRATION_SUCCESS)
{
printf("textinfo is %s\n", je->textinfo);
return 1;
break;
}
if(je->type == EXOSIP_REGISTRATION_FAILURE)
{
//注册失败之后,再次提交授权信息, 也可放在上面
eXosip_add_authentication_info(username, username,password, NULL, NULL);
}
if(je->type == EXOSIP_REGISTRATION_REFRESHED)
{
printf("refreshed");
return 0;
}
}
eXosip_quit();
}
ps:注册其实挺简单的,代码是用eXosip实现的,帮助手册上面都有,只要细细分析就能看明白,网上有pdf版本的,csdn上也有,英文的。
继续,下面这段是拨号的代码:
#include <eXosip2/eXosip.h>
#include <osip2/osip_mt.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
int call(char *telNum)
{
eXosip_event_t *je;
osip_message_t *invite = NULL;
osip_message_t *ack = NULL;
// int call_id, dialog_id;
int i,flag;
char tmp[4096];
char localip[128];
char source_call[100];
char dest_call[100];
sprintf(source_call,"sip:%s@%s:%s",s_username,s_ip,s_port);
sprintf(dest_call,"sip:%s@%s:%s",telNum,s_ip,s_port);
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;
}
eXosip_guess_localip (AF_INET, localip, 128);
snprintf (tmp, 4096,
"v=0\r\n"
"o=josua 0 0 IN IP4 %s\r\n"
"s=conversation\r\n"
"c=IN IP4 %s\r\n"
"t=0 0\r\n"
"m=audio %s 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, localip, "9900");
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 ();
flag = 1;
while (flag)
{
je = eXosip_event_wait (0, 200);
if (je == NULL)
{
printf ("No response or the time is over!\n");
break;
}
eXosip_lock ();
eXosip_default_action(je);
eXosip_unlock ();
switch (je->type)
{
case EXOSIP_CALL_INVITE:
printf ("a new invite reveived!\n");
break;
case EXOSIP_CALL_PROCEEDING:
printf ("proceeding!\n");
call_id = je->cid;
break;
case EXOSIP_CALL_RINGING:
printf ("ringing!\n");
printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did);
break;
case EXOSIP_CALL_ANSWERED:
printf ("ok! connected!\n");
call_id = je->cid;
dialog_id = je->did;
printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did);
eXosip_call_build_ack (je->did, &ack);
eXosip_call_send_ack (je->did, ack);
break;
case EXOSIP_CALL_CLOSED:
printf ("the other sid closed!\n");
return -1;//对方挂断
break;
case EXOSIP_CALL_ACK:
printf ("ACK received!\n");
break;
default:break;
}
eXosip_event_free (je);
}
return 0;
}
ps: 初学者可能不了解格式,所以程序会调不通,学的不好给大家随便说一下,别见怪阿。
sprintf(source_call,"sip:%s@%s:%s",s_username,s_ip,s_port);
sprintf(dest_call,"sip:%s@%s:%s",telNum,s_ip,s_port);
i = eXosip_call_build_initial_invite (&invite, dest_call, source_call, NULL, "This si a call for a conversation");
用户名: 77001234
密码: 987654321
要呼叫的号码:12340602252
服务器ip:192.168.8.24
端口:5060
》》 source_call为 77001234@192.168.8.24:5060
》》 dest_call 为 12340602252@192.168.8.24:5060
密码没有涉及到,因为注册的时候已经提供密码。