Kiến trúc thư viện PJSIP:

Một phần của tài liệu NGHIÊN CỨU THIẾT KẾ TỔNG ĐÀI IP PBX VÀ PHẦN MỀM THOẠI MÁY TRẠM (Trang 42)

Lược ựồ chỉ ra các thông ựiệp (SIP) tương tác với các thành phần như thế nào trong hệ thống:

Hình 3.2: Lược ựồ tương tác của các khối trong thư viện PJSIP

3.1.2.1 Giới thiệu về Endpoint:

Tại trung tâm của khối SIP là Endpoint, Endpoint có những thuộc tắnh và ựáp ứng như sau:

Ớ Nó có pool factory, và chứa các pool cho tất cả các thành phần SIP.

Ớ Nó có timer heap instance, và các schedule timer cho tất cả các thành phần SIP.

Ớ Nó có transport manager instance. Transport manager có các SIP transport và ựiều khiển message parsing và print.

Ớ Nó tùy thuộc một ựối tượng ựơn của PJLIBỖs ioqueue.

Ớ Nó cung cấp một thread yêu cầu chọn hàm, ựể các thread của ứng dụng có thể yêu cầu lấy các timer và các sự kiện socket (PJSIP không tự tạo ra bất kỳ thread nào).

Ớ Nó quản lý các module PJSIP. Module PJSIP là primary ý nghĩa cho việc mở rộng stack các message parsing và transport ở xa.

Ớ Nó nhận các thông ựiệp SIP từ transport manager và phân bố các thông ựiệp này ựến các module.

3.1.2.2 Các Module:

Module framework có ý nghĩa quan trọng cho các thông ựiệp SIP phân bố trong các thành phần phần mềm trong ứng dụng PJSIP. Tất cả các thành phần phần mềm trong PJSIP, bao gồm các lớp transaction và lớp dialog, ựược thực thi như module. Không có các module, core stack sẽ không biết ựiều khiển các thông ựiệp SIP như thế nào.

đối với các thông ựiệp ngõ vào, endpoint phân bố các thông ựiệp ựến tất cả module, bắt ựầu từ module có ưu tiên cao nhất, cho ựến khi có một trong số các module thông báo lại là nó ựã xử lý hoàn tất một thông ựiệp. đối với các thông ựiệp ngõ ra, endpoint phân bố các thông ựiệp ngõ ra trước khi chúng ựược phát ra mạng, cho phép các module ựặt sự hiệu chỉnh cuối cùng lên thông ựiệp nếu chúng mong muốn.

Tất cả các pointer của hàm là tùy ý, nếu chúng không ựược chỉ ựịnh, chúng sẽ tự ựiều chỉnh phù hợp nếu chúng ựược trả lại giá trị thành công.

Có bốn pointer là load, start, stop, và unload ựược gọi bởi endpoint ựể ựiều khiển trạng thái endpoint. Lược ựồ sau chỉ ra trạng thái của module

Hình 3.4: Lược ựồ trạng thái module

Các pointer hàm on_rx_request() và on_rx_response() là ưu tiên cho module nhận các thông ựiệp SIP từ endpoint (pjsip_endpt) hoặc từ các module khác. Giá trị trả lại của các callback này là quan trọng.

Các pointer hàm on_tx_request() và on_tx_response() ựược gọi bởi transport manager trước khi một thông ựiệp SIP ựược phát. điều này nó tạo cơ hội cho một vài module thay ựổi ựể hiệu chỉnh cuối cùng lên thông ựiệp. Tất cả các module phải trả lại giá trị PJ_SUCCESS, hoặc ngược lại sự truyền sẽ bị hủy.

Pointer on_tsx_state() ựược sử dụng ựể nhận ghi chú mỗi lần trạng thái giao dịch thay ựổi, cái mà có thể do nguyên nhân bởi việc nhận thông ựiệp, các sự kiện timer, hoặc sự kiện lỗi do transport.

Lược ựồ sau chỉ ra cách thức các module gọi các module khác như thế nào.

3.1.2.3 Sự quản lý Module:

Các module ựược quản lý bởi endpoint của PJSIP (pjsip_endpoint). Ứng dụng phải ựăng ký mỗi module ựến endpoint vì vậy nó có thể ựược nhận bởi stack.

a) Module management API:

Module management API ựược khai báo trong <pjsip/sip_endpt.h> như sau:

PJ_DECL(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, pjsip_module *module );

đăng ký một module ựến endpoint. Endpoint sau khi gọi sự khởi ựộng và bắt ựầu hàm trong module ựể khởi tạo module, và gán một module ID cho module.

PJ_DECL(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,pjsip_module *module );

Không ựăng ký một module từ endpoint. Endpoint sau ựó gọi sự dừng và không khởi ựộng hàm trong module ựể tắt module.

b) Khả năng của module:

Module có thể khai báo thuộc tắnh mới ựến endpoint. Thông thường thì endpoint quản lý tất cả thuộc tắnh của module: (adsbygoogle = window.adsbygoogle || []).push({});

_ Cho phép các phương thức SIP (cho phép header field). _ Hỗ trợ các nhánh SIP (hỗ trợ header field).

_ Hỗ trợ loại nội dung (chấp nhận header field).

Các vùng header này sẽ ựược tự ựộng thêm vào các request hoặc các response, vào nơi phù hợp.

Một module khai báo thuộc tắnh mới bằng gọi hàm pjsip_endpt_add_capability().

PJ_DECL(pj_status_t) pjsip_endpt_add_capability( pjsip_endpoint *endpt, pjsip_module *mod,

int htype,

const pj_str_t *hname, unsigned count,

const pj_str_t tags[]);

đăng ký các thuộc tắnh mới ựến endpoint. Thông số htype chỉ ựịnh header ựể thêm vào thuộc tắnh, như là: PJSIP_H_ACCEPT, PJSIP_H_ALLOW, PJSIP_H_SUPPORTED. Thông số hname là tùy ý, nó chỉ ựược dùng ựể chỉ ựịnh thuộc tắnh trong vùng header mà nó không ựược nhận ra bởi core stack. Các thông số tags và count chỉ ựịnh mảng các chuỗi tag ựược thêm vào vùng header .

PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_capability( pjsip_endpoint *endpt,int htype,const pj_str_t *hname);

Lấy một thuộc tắnh trong vùng, nó chứa tất cả thuộc tắnh mà nó ựược ựăng ký ựến endpoint cho vùng header chỉ ựịnh.

3.2 Th5 vi n PJSUA ( PJSUA-LIB) 3.2.1 Giới thiệu PJSUA:

Thư viện PJSUA là tập hợp các hàm API ựược viết bằng C/C++, dùng ựể lập trình các ứng dụng thoại ựa phương tiện và giao thức SIP. Nó bao bọc các chức năng báo hiệu SIP và xử lý âm thanh cùng với nhau , giúp lập trình viên thuận tiện trong việc gọi các hàm API, cung cấp chức năng quản lý tài khoản SIP, buddy, chat, và các chức năng thoại khác như : hội thảo , thu âm thoại Ầ Nó phụ thuộc vào các thư viện khác như : pjsip-ua, pjsip-simple, pjsip-core, pjmedia, pjmedia-codec, pjlib-util, và pjlib.

Sau ựây là phần hướng dẫn sử dụng một số hàm trong thư viện PJSUA . Phần này ựược viết dựa trên PJSUA Manual ( http://pjsip.org/pjsip/docs/html/group__PJSUA__ LIB.htm ) và chương trình mẫu pjsua_app.c .

3.2.2 Tạo và khởi ựộng PJSUA

Trước khi gọi bất kỳ hàm nào của PJSUA, ta cần gọi hàm pjsua_create() ựể tạo PJSUA. Hàm này sẽ giúp khởi ựộng PJLIB, tạo nền tảng cho mọi hàm khác, và tạo một ựầu cuối SIP (SIP endpoint) .

Tiếp theo ta cần gọi tiếp hàm pjsua_pool_create() ựể tạo ra vùng bộ nhớ dùng cho chương trình .

Ta thực hiện việc gán các biến ban ựầu của chương trình , gồm : thông số các port , cấu hình media , cấu hình transport (RTP, UDP) , thiết bị thu phát giọng nói , tài khoản SIP , các buddy Ầ.

static void default_config(struct app_config *cfg) {

char tmp[80]; unsigned i;

pjsua_config_default(&cfg->cfg);

pj_ansi_sprintf(tmp, "PJSUA v%s/%s", pj_get_version(), PJ_OS_NAME);

pj_strdup2_with_null(app_config.pool, &cfg->cfg.user_agent, tmp); pjsua_logging_config_default(&cfg->log_cfg); pjsua_media_config_default(&cfg->media_cfg); pjsua_transport_config_default(&cfg->udp_cfg); cfg->udp_cfg.port = 5060; pjsua_transport_config_default(&cfg->rtp_cfg); cfg->rtp_cfg.port = 4000; cfg->duration = NO_LIMIT; cfg->wav_id = PJSUA_INVALID_ID; cfg->rec_id = PJSUA_INVALID_ID; cfg->wav_port = PJSUA_INVALID_ID; cfg->rec_port = PJSUA_INVALID_ID; cfg->mic_level = cfg->speaker_level = 1.0;

cfg->playback_dev = PJSUA_INVALID_ID;

for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i) pjsua_acc_config_default(&cfg->acc_cfg[i]); for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i)

pjsua_buddy_config_default(&cfg->buddy_cfg[i]); }

Sau ựó ta khai báo các hàm callback, các hàm này sẽ làm việc khi chương trình nhận ựáp ứng từ server gởi ựến như: báo cuộc gọi ựến, báo trạng thái tài khoản SIP, báo có tin nhắn (chat), báo trạng thái buddy, báo chuyển cuộc gọi Ầ.

app_config.cfg.cb.on_call_state = &on_call_state; app_config.cfg.cb.on_call_media_state = &on_call_media_state; app_config.cfg.cb.on_incoming_call = &on_incoming_call; app_config.cfg.cb.on_call_tsx_state = &on_call_tsx_state; app_config.cfg.cb.on_dtmf_digit = &call_on_dtmf_callback; app_config.cfg.cb.on_reg_state = &on_reg_state; app_config.cfg.cb.on_buddy_state = &on_buddy_state; app_config.cfg.cb.on_pager = &on_pager; app_config.cfg.cb.on_typing = &on_typing; app_config.cfg.cb.on_call_transfer_status = &on_call_transfer_status; app_config.cfg.cb.on_call_replaced = &on_call_replaced; app_config.cfg.cb.on_nat_detect = &on_nat_detect;

Sau khi gán các thông số khởi ựộng chương trình xong , ta gọi hàm pjsua_init() ựể khởi ựộng PJSUA , nếu ta không thiết lập các thông số ở bước trên , thì hàm pjsua_init() sẽ tự ựộng gán các giá trị mặc ựịnh của chương trình .

3.2.3 đăng ký và hủy tài khoản SIP trong PJSUA (adsbygoogle = window.adsbygoogle || []).push({});

Các thông số của tài khoản SIP ựược chứa trong biến struct pjsua_acc_config. Sau ựây là các thông số chắnh của biến struct pjsua_acc_config.

typedef struct pjsua_acc_config {

int priority; độ ưu tiên của tài khoản.

pj_str_t id; địa chỉ SIP URL của tài khoản , thường có dạng "sip:account@domain".

pj_str_t reg_uri; địa chỉ URL dùng trong yêu cầu ựăng ký tài khoản , thường có dạng

Ộsip:domainỢ

pj_bool_t publish_enabled; Nếu true thì thông tin trạng thái của tài khoản sẽ ựược gởi

ựến server.

pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES]; đây là biến quan trọng nhất

của struct pjsua_acc_config vì nó chứa các thông tin ựăng nhập của tài khoản vắ dụ như username , password Ầ của tài khoản SIP .

}

struct pjsip_cred_info {

pj_str_t scheme; thường có giá trị là "digest"

pj_str_t username; Tên tài khoản SIP

int data_type; Loại mật khẩu ( 0 : mật khẩu trơn , không mã hóa ).

pj_str_t data; Mật khẩu

}

để ựăng ký tài khoản SIP với SIP Proxy , ta cần khai báo ựầy ựủ các thông số của tài khoản SIP và sau ựó dùng hàm pjsua_acc_add ựể ựăng ký và hàm pjsua_acc_set_online_status

ựể ựặt trạng thái online cho tài khoản SIP.

để xóa tài khoản SIP ựăng ký ở server , ta dùng hàm pjsua_acc_del .

Toàn bộ phần ựăng ký tài khoản SIP ựược viết trong ựoạn code sau :

{ pjsua_acc_config thisAccountsCfg; pjsua_acc_config_default(&thisAccountsCfg); thisAccountsCfg.id = pj_str(uri); thisAccountsCfg.reg_timeout = 3600; thisAccountsCfg.reg_uri = pj_str(reguri);

thisAccountsCfg.publish_enabled = PJ_TRUE; // enable publish

thisAccountsCfg.cred_count = 1;

thisAccountsCfg.cred_info[0].username = pj_str(username); thisAccountsCfg.cred_info[0].realm = pj_str(domain);

thisAccountsCfg.cred_info[0].scheme = pj_str("digest");

thisAccountsCfg.cred_info[0].data_type = 0;// plaintext password

thisAccountsCfg.cred_info[0].data = pj_str(password); pjsua_acc_id pjAccId= -1;

int status = pjsua_acc_add(&thisAccountsCfg, PJ_TRUE, &pjAccId); return pjAccId;

} (adsbygoogle = window.adsbygoogle || []).push({});

3.2.4 Các hàm quản lý cuộc gọi trong PJSUA

Sau ựây là một số hàm thường dùng của thư viện PJSUA dùng ựể quản lý cuộc gọi trong PJSUA. - Tạo cuộc gọi : ta dùng hàm pjsua_call_make_call .Hàm có các dạng như sau :

PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, const pj_str_t *dest_uri, unsigned options,

void *user_data,

const pjsua_msg_data *msg_data, pjsua_call_id *p_call_id)

Các tham số của hàm này là :

+acc_id : Tài khoản SIP thực hiện cuộc gọi.

+dst_uri : URI ựắch

+options : tùy chọn , thường có giá trị là 0 .

+user_data : thông tin người dùng gắn vào cuộc gọi và có thể phục hồi lại sau ựó , giá trị này

+p_call_id : biến pointer chứa ID của cuộc gọi

+Giá trị trả lại là PJ_SUCCESS nếu thành công, hoặc mã lỗi khi gặp lỗi.

Hàm này thường ựược viết như sau pjsua_call_make_call( current_acc, &dest, 0, NULL, NULL, NULL);

- Ngắt cuộc gọi : ta dùng hàm pjsua_call_hangup. Hàm có dạng như sau : PJ_DECL(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id,

unsigned code,

const pj_str_t *reason,

const pjsua_msg_data *msg_data);

Hàm này sẽ ngắt cuộc gọi bất chấp trạng thái của cuộc gọi, hàm này khác với hàm

pjsua_call_answer . Hàm pjsua_call_answer() ngắt cuộc gọi bằng cách gởi các ựáp ứng

3xx-6xx trong giai ựoạn ựầu của quá trình thiết lập cuộc gọi. Trong khi ựó hàm

pjsua_call_hangup() có tác dụng kết thúc cuộc gọi bất chấp trạng thái chương trình.

Các thông số của hàm :

+call_id: ID của cuộc gọi, thông số này ựược tạo ra trong hàm.

+code: Mã ựáp ứng tùy chọn gởi ựi khi ta ngắt cuộc gọi , nếu giá trị là 0 thì ựáp ứng Ộ603/DeclineỢ sẽ ựược gởi ựi.

+reason: Lý do tùy chọn từ chối cuộc gọi, nếu giá trị là NULL thì chuỗi mặc ựịnh sẽ ựược gởi

ựi.

+msg_data: Các giá trị header tùy chọn.

Hàm này thường ựược dùng với một số chức năng như sau :

+ Ngắt cuộc gọi : ta dùng hàm pjsua_call_hangup( callId, 0, NULL, NULL); ựể gởi ựáp ứng 603/Decline.

+ Không làm phiền hoặc bận rộn : khi có cuộc gọi ựến nhưng người dùng không muốn nghe, ta có thể dùng hàm pjsua_call_hangup( callId, 486 , NULL, NULL ) ựể gởi ựáp ứng (adsbygoogle = window.adsbygoogle || []).push({});

486/Busy Here.

-Gởi ựáp ứng: ta dùng hàm pjsua_call_answer ựể gởi ựáp ứng khi ta nhận ựược một thông ựiệp INVITE từ server gởi ựến . Tùy thuộc vào ựáp ứng ta gởi mà chương trình sẽ báo với server thiết lập cuộc hoặc hủy cuộc gọi Ầ

Hàm có dạng như sau :

PJ_DECL(pj_status_t) pjsua_call_answer(pjsua_call_id call_id, unsigned code,

const pj_str_t *reason,

const pjsua_msg_data *msg_data);

Các thông số của hàm pjsua_call_answer() :

+call_id : ID của cuộc gọi ựến

+code : Mã ựáp ứng (100-699).

+reason : Lý do tùy chọn , thường có giá trị NULL, khi ựó chuỗi mặc ựịnh sẽ ựược dùng.

+msg_data : Header tùy chọn dùng ựể gắn vào thông ựiệp ựáp ứng gởi ựi

Hàm pjsua_call_answer thường ựược dùng như sau :

+ để gởi ựáp ứng báo reo chuông ( ựáp ứng 180 ) ta thường sử dụng hàm pjsua_call_answer

+ để thực hiện chức năng trả lời tự ựộng ( Auto answer ) ta gởi ựáp ứng 200/OK ngay khi vừa nhận ựược yêu cầu INVITE gởi từ server ựến. Ta sử dụng hàm pjsua_call_answer như sau :

pjsua_call_answer(callId, 200, NULL, NULL);

- Giữ cuộc gọi : để thực hiện chức năng giữ cuộc gọi , ta dùng hàm pjsua_call_set_hold. Hàm này sẽ thông báo cho phắa bên kia biết cuộc gọi sẽ ựược chuyển sang trạng thái chờ. Lúc này server sẽ thực hiện chức năng Music-on-Hold ựối với cuộc gọi này , cho ựến khi người dùng cho phục hồi lại cuộc gọi.

Hàm pjsua_call_set_hold có dạng như sau :

PJ_DECL(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, const pjsua_msg_data *msg_data);

Các thông số của hàm như sau :

+call_id : ID của cuộc gọi.

+msg_data : Thông ựiệp tùy chọn gởi cùng với yêu cầu .

Hàm này thường ựược viết như sau :

pjsua_call_set_hold(current_call, NULL);

- Phục hồi cuộc gọi : để phục hồi cuộc gọi trong khi giữ cuộc gọi ta dùng hàm

pjsua_call_reinvite. Hàm pjsua_call_reinvite sẽ gởi yêu cầu re-INVITE ựến server ựể

phục hồi cuộc gọi ựang bị giữ. Hàm có dạng như sau :

PJ_DECL(pj_status_t) pjsua_call_reinvite(pjsua_call_id call_id, pj_bool_t unhold,

const pjsua_msg_data *msg_data);

Các thông số của hàm pjsua_call_reinvite : (adsbygoogle = window.adsbygoogle || []).push({});

+call_id : ID của cuộc gọi.

+unhold : Nếu giá trị này là số khác không thì nói sẽ phục hồi lại cuộc gọi có số ID là call_ID.

+msg_data : Thông ựiệp tùy chọn gởi kèm với yêu cầu.

Hàm này thường ựược viết như sau :

pjsua_call_reinvite(current_call, 1 , NULL);

- Chuyển cuộc gọi : để thực hiện chức năng chuyển cuộc gọi , ta có thể dùng hàm

pjsua_call_hangup().

Ta tìm hiểu qua hàm tạo Header SIP pjsip_generic_string_hdr_init2 .

Hàm này có cấu trúc như sau :

PJ_DECL(void) pjsip_generic_string_hdr_init2(pjsip_generic_string_hdr *h, pj_str_t *hname,

pj_str_t *hvalue);

Thông số của hàm như sau : +h : Header SIP cần tạo +hname : Tên của Header +hvalue : Giá trị của header

để chuyển cuộc gọi ta sử dụng hàm pjsua_call_hangup() với mã ựáp ứng là 302/Moved Temporarily. Khi nhận mã ựáp ứng 302 , server sẽ thử lại yêu cầu ở ựịa chỉ mới ựược cho bởi trường Contact.Chắnh vì vậy ta cần dùng hàm pjsip_generic_string_hdr_init2() ựể tạo trường Contact trong thông ựiệp SIP, trong trường Contact này sẽ chứa ựịa chỉ mới có dạng <sip:number@domain> .

Sau ựây là các bước lập trình chuyển cuộc gọi :

//1.) Tạo trường contact có chứa ựịa chỉ mới

pj_str_t contact_header_to_call = pj_str((char*)destUri);

//2.) Chèn trường Contact vào nội dung biến pjsua_msg_data trong hàm pjsua_call_hangup

pjsua_msg_data aStruct;

pjsua_msg_data_init(&aStruct);//Khởi tạo pjsua_msg_data

pjsip_generic_string_hdr warn;//Khai báo biến SIP header pj_str_t hname = pj_str("Contact");//Khai báo tên trường pj_str_t hvalue = contact_header_to_call;//Gán giá trị trường pjsip_generic_string_hdr_init2(&warn, &hname, &hvalue);

warn.type = PJSIP_H_CONTACT;

pj_list_push_back(&aStruct.hdr_list, &warn);//Chèn trường Contact vào pjsua_msg_data

//3.) Chuyển cuộc gọi

pjsua_call_hangup(callId, 302, NULL, &(aStruct));

- Báo hiệu DTMF : để gởi các ký tự dựa trên giao thức báo hiệu DTMF theo ựịnh dạng của RFC2833 ta dùng hàm pjsua_call_dial_dtmf .

Cấu trúc của hàm như sau :

PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(pjsua_call_id call_id, const pj_str_t *digits);

Thông số của hàm như sau :

+call_id : ID của cuộc gọi (adsbygoogle = window.adsbygoogle || []).push({});

+digits : ký tự DTMF gởi ựi

Vắ dụ ựể gởi ký tự Ộ#Ợ ta viết code như sau :

pj_str_t dg = pj_str(Ộ#Ợ);

pjsua_call_dial_dtmf(call_id, &dg);

3.3 Gii thi u Bkphone

Bkphone là chương trình thoại trên máy trạm có giao diện (GUI) ựược viết bằng ngôn ngữ C# và phần lõi chương trình (VoIP engine) dựa trên thư viện PJSIP.

Hình 3.3: Giao diện chắnh của BKphone

3.3.1 Chức năng và cấu trúc Bkphone :

- Báo hiệu SIP theo tiêu chuẩn RFC3261 - Thực hiện các cuộc gọi

- Chức năng giữ cuộc gọi (Call Hold/retrieve)

-Chức năng chuyển cuộc gọi (Call Forwarding (Unconditional)) - Chức năng báo bận (Do Not Disturb)

- Chức năng tự ựộng trả lời (Auto Answer)

- Hỗ trợ ựăng ký thông tin 5 tài khoản SIP (chỉ có 1 tài khoản là mặc ựịnh ( default ) ) . - Liệt kê các cuộc gọi ựã thực hiện

Bkphone

GUI Giao diện người

dùng Telephony.dll CallManager, CMachineState, SipCommonProxy.. Pjsipdll.dll Callback, PJSUA_dll... PJSUA-LIB

Chi tiết các phần như sau :

- Pjsipdll.dll : là một file dll viết bằng C++ , gồm các hàm gọi từ thư viện PJSUA , giao tiếp trực tiếp với thư viện PJSUA.

- Telephony.dll : là một file dll viết bằng C# , có mục ựắch tương tác với thư viện Pjsua thông qua Pjsipdll.dll và giao diện GUI , gồm các lớp quan trọng sau :

+ CallManager: là lớp nhận lệnh giữa người dùng từ giao diện GUI và thông báo ra giao diện GUI các hoạt ựộng của chương trình trong quá trình quản lý các phiên cuộc gọi .

+ CMachineState: là lớp chứa thông tin của 1 cuộc gọi , trạng thái của chương trình : IDLE , INCOMING , ALERTING, ACTIVE , RELEASED, HOLDING.

+SipCommonProxy: là lớp tương tác với Pjsipdll.dll bằng cách sử dụng System.Runtime.InteropServices ựể wrapper các hàm Pjsua_dll trong Pjsipdll.dll .

- GUI : giao diện chương trình, gồm có : bàn phắm ựể thực hiện bấm số ( DTMF Dialling ) , menu Options ựể ựiền các thông tin tài khoản SIP , danh sách các cuộc gọi ựã diễn ra ,

Một phần của tài liệu NGHIÊN CỨU THIẾT KẾ TỔNG ĐÀI IP PBX VÀ PHẦN MỀM THOẠI MÁY TRẠM (Trang 42)