zoukankan      html  css  js  c++  java
  • exosip2 的简单使用

    今天从网上搞了一个基于osip 库的 SIP 协议的简单的 UAC 代理客户端和 UAS 代理服务器端,并进行了编译连接,代码整理后如下:
    
     
        ----------- UAC 代理客户端的代码整理 ---------------
     
    /**
     * 一个使用了 osip 和 eXosip 库的 UAC 代理客户端的演示程序
     * 
     * - 只是简单的演示了使用了 osip 和 eXosip2 库的 UAC 代理客户端的如下几个功能:
     * * i 发起呼叫 INVITE 请求
     * * h 挂断会话
     * * s 执行方法 INFO 
     * * m 执行方法 MESSAGE
     * 
     * 编 译:g++ -I/usr/local/include -L/usr/local/lib ua_client.cpp -o ua_client -leXosip2 -losip2 -losipparser2 -lpthread
     * 
     */
    
    #include <osip2/osip_mt.h>
    #include <eXosip2/eXosip.h>
    
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        eXosip_event_t *je;
        osip_message_t *reg = NULL;
        osip_message_t *invite = NULL;
        osip_message_t *ack = NULL;
        osip_message_t *info = NULL;
        osip_message_t *message = NULL;
        int call_id, dialog_id;
        int i,flag;
        int flag1 = 1;
        int id;
        
        string strIdentity = "sip:136@133.37.55.136";
        string strRegisterer = "sip:133.37.55.136:5060"; // server ip
    
        string strSrcCall = "sip:136@133.37.55.136";
        string strDestCall = "sip:136@133.37.55.136:5060"; // server ip
    
        
        char command;
        char tmp[4096];
        char localip[128];
    
        string strHelp = string("
    	--> 命令字符 功能描述 <--
    
    ")
                            + "		r 向服务器注册
    "
                            + "		c 取消注册
    "
                            + "		i 发起呼叫请求
    "
                            + "		h 挂断
    "
                            + "		q 退出程序
    "
                            + "		s 执行方法 INFO
    "
                            + "		m 执行方法 MESSAGE
    "
                            + "		e 帮助
    
    ";
        cout << strHelp;
    
        string strMsg;
    
        i = eXosip_init ();
        if (i != 0)
        {
            cout << "	--> Couldn't initialize eXosip! <--
    ";
            return -1;
        }
        else
        {
            cout << "	--> eXosip_init successfully! <-- 
    
    ";
        }
    
        i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5061, AF_INET, 0);
        if (i != 0)
        {
            eXosip_quit ();
            cerr << "
    	--> Couldn't initialize transport layer! <-- 
    
    ";
            return -1;
        }
        flag = 1;
        while (flag)
        {
            cout << "请输入一个命令字符:	";
            cin >> command;
          
            switch (command)
            {
            case 'r':
                cout << "
    	--> This modal isn't commpleted! 
    " << endl;
                break;
    
            case 'i': // 初始化的 INVITE 请求
                i = eXosip_call_build_initial_invite (&invite, 
                                                      strDestCall.c_str(), 
                                                      strSrcCall.c_str(), 
                                                      NULL, 
                                                      "This is a call for a conversation");
                if (i != 0)
                {
                    cout << "
     --> Intial INVITE failed! <-- 
    ";
                    break;
                }
    
                // 符合 SDP 格式, 其中属性 a 是自定义格式,也就是说可以存放自己的信息, 
                // 但是只能是两列,比如帐户信息
                // 但是经测试,格式: v o t必不可少,原因未知,估计是协议栈在传输时需要检查的
    
                strMsg = string("v=0
    ")
                       + "o=anonymous 0 0 IN IP4 0.0.0.0
    "
                       + "t=1 10
    "
                       + "a=username:bluesea
    "
                       + "a=password:123456
    ";
    
                osip_message_set_body (invite, strMsg.c_str(), strMsg.length());
                osip_message_set_content_type (invite, "application/sdp");
          
                // 这里使用了锁机制以保证同步
                eXosip_lock ();
                i = eXosip_call_send_initial_invite (invite);
                eXosip_unlock ();
                flag1 = 1;
                while (flag1)
                {
                    je = eXosip_event_wait (0, 200);
                    if (je == NULL)
                    {
                        cout << "
    	--> No response or the time is over! <--
    " << endl;
                        break;
                    }
              
                    switch (je->type)
                    {
                    case EXOSIP_CALL_INVITE:
                        cout << "
    	--> a new invite reveived! <--
    " << endl;
                        break;
    
                    // announce processing by a remote app
                    case EXOSIP_CALL_PROCEEDING:
                        cout << "
    	--> proceeding! <--
    " << endl;
                        break;
    
                    // announce ringback
                    case EXOSIP_CALL_RINGING:
                        cout << "
    	--> ringing! <--
    " 
                             << "
    	call_id is " << je->cid 
                             << ", dialog_id is " << je->did << endl;
                        break;
    
                    // 收到请求,表示连接成功,下面发送回复确认
                    case EXOSIP_CALL_ANSWERED:
                        cout << "
    	--> ok! connected! <--
    " << endl;
                        call_id = je->cid;
                        dialog_id = je->did;
                        cout << "
    	call_id is " << je->cid 
                             << ", dialog_id is " << je->did << endl;
                        eXosip_call_build_ack (je->did, &ack);
                        eXosip_call_send_ack (je->did, ack);
                        flag1 = 0;
                        break;
    
                    case EXOSIP_CALL_CLOSED:
                        cout << "
    	--> the other sid closed! <--
    " << endl;
                        break;
    
                    case EXOSIP_CALL_ACK:
                        cout << "
    	--> ACK received! <--
    " << endl;
                        break;
    
                    default:
                        cout << "
    	--> other response!
    " <<endl;
                        break;
                    }
              
                    eXosip_event_free (je);
                }
    
                break;
    
            case 'h':
                cout << "
    	--> Holded ! 
    " << endl;
          
                eXosip_lock ();
                eXosip_call_terminate (call_id, dialog_id);
                eXosip_unlock ();
                break;
    
            case 'c':
                cout << "
    	--> This modal isn't commpleted! 
    " << endl;
                break;
    
            case 's':
                // 传输 INFO 方法
                eXosip_call_build_info (dialog_id, &info);
                
                snprintf (tmp , 4096, "hello,bluesea");
                osip_message_set_body (info, tmp, strlen(tmp));
    
                // 格式可以任意设定, text/plain 代表文本信息
                osip_message_set_content_type (info, "text/plain");
                eXosip_call_send_request (dialog_id, info);
                break;
    
            case 'm':
                // 传输 MESSAGE方法,也就是即时消息,
                // 和 INFO 方法相比,主要区别,是 MESSAGE 不用建立连接,直接传输信息,
                // 而 INFO 必须在建立 INVITE 的基础上传输。
                cout << "
    	--> the mothed :MESSAGE 
    " << endl;
                eXosip_message_build_request (&message, 
                                              "MESSAGE", 
                                              strDestCall.c_str(), 
                                              strSrcCall.c_str(), 
                                              NULL);
                strMsg = "message: hello bluesea!";
                osip_message_set_body (message, strMsg.c_str(), strMsg.length());
          
                // 假设格式是xml
                osip_message_set_content_type (message, "text/xml");
                eXosip_message_send_request (message);
                break;
    
            case 'q':
                eXosip_quit ();
                cout << "
    	--> Exit the setup! 
    " << endl;;
                flag = 0;
                break;
    
            case 'e':
                cout << strHelp << endl;
                break;
    
            default:
                cout << "
    	--> 不支持的命令 <--
    " << endl;
                break;
            }
        }
    
        return 0;
    }
        ----------- UAS 代理服务器端的代码整理 ---------------
    
    /**
     * 一个使用了 osip 和 eXosip 库的 UAS 代理服务端的演示程序
     * 
     * - 只是简单的演示了使用了 osip 和 eXosip2 库的 UAS 代理服务端的如下几个功能:
     * 
     * 编 译:g++ -I/usr/local/include -L/usr/local/lib ua_server.cpp -o ua_server -leXosip2 -losip2 -losipparser2 -lpthread
     * 
     */
    
    #include <eXosip2/eXosip.h>
    
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    
    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        eXosip_event_t *je = NULL;
        osip_message_t *ack = NULL;
        osip_message_t *invite = NULL;
        osip_message_t *answer = NULL;
        sdp_message_t *remote_sdp = NULL;
        int call_id, dialog_id;
        int i,j;
        int id;
    
        char *sour_call = "sip:136@133.37.55.136";
        char *dest_call = "sip:136@133.37.55.136:5061"; //client ip/port
    
        char command;
        char tmp[4096];
        char localip[128];
        int pos = 0;
    
        // 初始化 sip
        i = eXosip_init ();
        if (i != 0)
        {
            cerr << "
    	--> Can't initialize eXosip!
    ";
            return -1;
        }
        else
        {
            cout << "
    	--> eXosip_init successfully!
    ";
        }
        
        i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0);
        if (i != 0)
        {
            eXosip_quit ();
            cerr << "
    	--> eXosip_listen_addr error! Couldn't initialize transport layer!
    ";
        }
    
        for(;;)
        {
            // 侦听是否有消息到来
            je = eXosip_event_wait (0, 50); 
    
            // 协议栈带有此语句,具体作用未知
            eXosip_lock ();
            eXosip_default_action (je);
            eXosip_automatic_refresh ();
            eXosip_unlock ();
    
            if (je == NULL) // 没有接收到消息,继续
            {
                continue;
            }
    
            switch (je->type)
            {
            case EXOSIP_MESSAGE_NEW: // 新的消息到来
                cout << "
    	*** EXOSIP_MESSAGE_NEW!
    " << endl;
    
                if (MSG_IS_MESSAGE (je->request)) // 如果接收到的消息类型是 MESSAGE
                {
                    {
                        osip_body_t *body;
                        osip_message_get_body (je->request, 0, &body); 
                        cout << "I get the msg is: " << body->body << endl;
                    }
    
                    // 按照规则,需要回复 OK 信息
                    eXosip_message_build_answer (je->tid, 200, &answer);
                    eXosip_message_send_answer (je->tid, 200, answer);
                }
                break;
    
            case EXOSIP_CALL_INVITE: // INVITE 请求消息
                // 得到接收到消息的具体信息
                cout << "
    	Received a INVITE msg from " << je->request->req_uri->host 
                     << " : " << je->request->req_uri->port 
                     << ", username is " << je->request->req_uri->username << endl;
    
                // 得到消息体,认为该消息就是 SDP 格式.
                remote_sdp = eXosip_get_remote_sdp (je->did);
                call_id = je->cid;
                dialog_id = je->did;
            
                eXosip_lock ();
    
                eXosip_call_send_answer (je->tid, 180, NULL);
                i = eXosip_call_build_answer (je->tid, 200, &answer);
                if (i != 0)
                {
                    cout << "
    	--> This request msg is invalid! Cann't response!
    " << endl;
                    eXosip_call_send_answer (je->tid, 400, NULL);
                }
                else
                {
                    snprintf (tmp, 4096,
                        "v=0
    "
                        "o=anonymous 0 0 IN IP4 0.0.0.0
    "
                        "t=1 10
    "
                        "a=username:rainfish
    "
                        "a=password:123
    ");
                
                    // 设置回复的SDP消息体,下一步计划分析消息体
                    // 没有分析消息体,直接回复原来的消息,这一块做的不好。
                    osip_message_set_body (answer, tmp, strlen(tmp));
                    osip_message_set_content_type (answer, "application/sdp");
                
                    eXosip_call_send_answer (je->tid, 200, answer);
                    cout << "
    	--> send 200 over!" << endl;
                }
    
                eXosip_unlock ();
            
                // 显示出在 sdp 消息体中的 attribute 的内容,里面计划存放我们的信息
                cout << "
    	--> The INFO is :
    " ;
                while (!osip_list_eol ( &(remote_sdp->a_attributes), pos))
                {
                    sdp_attribute_t *at;
                
                    //这里解释了为什么在SDP消息体中属性a里面存放必须是两列
                    at = (sdp_attribute_t *) osip_list_get ( &remote_sdp->a_attributes, pos);
                    cout << "
    	" << at->a_att_field 
                         << " : " << at->a_att_value << endl;
                
                    pos ++;
                }
                break;
    
            case EXOSIP_CALL_ACK:
                cout << "
    	--> ACK recieved!
    " << endl;
                // printf ("the cid is %s, did is %s
    ", je->did, je->cid); 
                break;
    
            case EXOSIP_CALL_CLOSED:
                cout << "
    	--> the remote hold the session!
    " << endl;
                // eXosip_call_build_ack(dialog_id, &ack);
                // eXosip_call_send_ack(dialog_id, ack); 
                i = eXosip_call_build_answer (je->tid, 200, &answer);
                if (i != 0)
                {
                    printf ("This request msg is invalid!Cann't response!
    ");
                    eXosip_call_send_answer (je->tid, 400, NULL);
                }
                else
                {
                    eXosip_call_send_answer (je->tid, 200, answer);
                    cout << "
    	--> bye send 200 over!
    ";
                } 
                break;
    
            case EXOSIP_CALL_MESSAGE_NEW:
    
                cout << "
    	*** EXOSIP_CALL_MESSAGE_NEW
    " << endl;
                if (MSG_IS_INFO(je->request) ) // 如果传输的是 INFO 方法
                {
                    eXosip_lock ();
                    i = eXosip_call_build_answer (je->tid, 200, &answer);
                    if (i == 0)
                    {
                        eXosip_call_send_answer (je->tid, 200, answer);
                    }
    
                    eXosip_unlock ();
    
                    {
                        osip_body_t *body;
                        osip_message_get_body (je->request, 0, &body);
                        cout << "the body is " << body->body << endl;
                    }
                }
                break; 
    
            default:
                cout << "
    	--> Could not parse the msg!
    " << endl;
            }
        } 
    
        return 0;
    }

  • 相关阅读:
    c++基础_矩阵乘法
    c++基础_字符串对比
    c++基础_时间转换
    c++基础_特殊回文数
    c++基础_回文数
    c++基础_特殊的数字
    c++基础_杨辉三角形
    c++基础_字母图形
    c++基础_01字串
    java 常用集合类型--以及其特性
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318522.html
Copyright © 2011-2022 走看看