eXosip2提供靈活的API,以幫助用戶控制呼叫。
1.2.1 初始化呼叫
要啓動一個呼出,用戶通常需要一些eXosip2用到的頭部,以建立默認的INVITE請求。以下的代碼用於啓動一個呼叫:
osip_message_t *invite;
int i;
i = eXosip_call_build_initial_invite (&invite,
"<sip:[email protected]>",
"<sip:[email protected]>",
NULL, // optional route header
"This is a call for a conversation");
if (i != 0)
{
return -1;
}
osip_message_set_supported (invite, "100rel");
{
char tmp[4096];
char localip[128];
eXosip_guess_localip (AF_INET, localip, 128); // 獲取本地IP
// 格式化SDP信息體
snprintf (tmp, 4096,
"v=0\r\n" // SDP版本
"o=josua 0 0 IN IP4 %s\r\n" // 用戶名、ID、版本、網絡類型、地址類型、IP地址
"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, port);
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); // 發送INVITE請求
if (i > 0)
{
eXosip_call_set_reference (i, reference);
}
eXosip_unlock ();
return i;
上面代碼使用eXosip_call_build_initial_invite函數爲新的呼叫建立一個默認的SIP INVITE請求。用戶需要插入SDP信息體,以指示RTP流的音頻參數。
同時上述代碼演示了eXosip2 API的靈活性,它允許您插入額外的頭部,比如:"Supported: 100rel"(宣佈支持SIP擴展)。因此,您可以完全的控制SIP請求的創建。
eXosip_call_send_initial_invite函數的返回值爲呼叫標識(call identifier),該標識可以用於發送CANCEL請求。之後的事件中(除了100 Trying),用戶可以獲得會話標識(dialog identifier),該標識用於控制已建立的呼叫。
eXosip_call_set_reference函數將用戶自己的環境(context)與呼叫聯繫起來,這樣用戶可以從eXosip_event取回指針。
1.2.2 應答呼叫
下面的代碼教您如何應答一個到來的呼叫。當接收到SIP INVITE請求後,用戶通常需要發送一個 "180 Ringing" SIP應答。
eXosip_lock ();
eXosip_call_send_answer (ca->tid, 180, NULL);
eXosip_unlock ();
上述代碼表明,協議棧有時只需要一個API函數就可以建立和發送默認的SIP消息。
然後,當用戶想要回復呼叫時,需要發送“200 OK”,同時在回覆中插入SDP信息體:
osip_message_t *answer = NULL;
eXosip_lock ();
i = eXosip_call_build_answer (ca->tid, 200, &answer);// 建立200 OK應答
if (i != 0)
{
eXosip_call_send_answer (ca->tid, 400, NULL);
}
else
{
i = sdp_complete_200ok (ca->did, answer); // 僞代碼,需要用戶自己實現
if (i != 0)
{
osip_message_free (answer);
eXosip_call_send_answer (ca->tid, 415, NULL);
}
else
eXosip_call_send_answer (ca->tid, 200, answer); // 發送200 OK應答
}
eXosip_unlock ();
注1:上述代碼中,注意到給請求發送應答時用到了傳送標識(transaction identifier)(不是呼叫標識,也不是會話標識)。
注2:爲了發送“200 OK”,通常需要在回覆中插入SDP信息體,而且是在回覆前插入,目的是爲了協商支持的參數和編碼。在test tool目錄下,eXosip2提供的josua應用程序中,可以找到一個非常基本的SDP協商操作。
1.2.3 發送其他請求
呼叫控制API允許發送和接收REFER、UPDATE、INFO、OPTIONS、NOTIFY、INVITE。當回覆其他請求時,仍然存在一些限制,但可以發送任何類型的請求。
以下的代碼是發送INFO請求,用於在不同信號層發送不同信道的dtmf。
osip_message_t *info;
char dtmf_body[1000];
int i;
eXosip_lock ();
i = eXosip_call_build_info (ca->did, &info);
if (i == 0)
{
snprintf (dtmf_body, 999, "Signal=%c\r\nDuration=250\r\n", c);
osip_message_set_content_type (info, "application/dtmf-relay");
osip_message_set_body (info, dtmf_body, strlen (dtmf_body));
i = eXosip_call_send_request (ca->did, info);
}
eXosip_unlock ();