sip网络电话

来源:互联网 发布:儿童教学软件 编辑:程序博客网 时间:2024/05/17 06:39

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, &reg);
    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
   密码没有涉及到,因为注册的时候已经提供密码。

原创粉丝点击