You are on page 1of 577

‫من استریسک را از سال ‪ ۲۰۰۲‬زمانﯽ که به دانشگاه مﯽرفتم شروع کردم )استریسک‬

‫در سال ‪ ۱۹۹۹‬متولد شد( و توانستم یک مشاوره کسب و کار را در این زمینه‪ ،‬بالﻎ بر‬
‫یک دهه ادامه دهم‪ .‬فوقالعاده است که استریسک چگونه توانسته است همچنان یک‬
‫بســتر ‪VoIP‬منبع باز قطعﯽ براي ایجاد برنامههاي کاربردي و کســب و کارهاي جدید‬
‫بماند‪ .‬در طول این ســالها‪ ،‬من همچنان از استریسک استفاده کردهام‪ ،‬چرا که احساس‬
‫نزدیکﯽ خاصﯽ به آن دارم و مشــاهده رشد و تبدیل شدن آن به یک انقالب فناورانه‬
‫در اینترنت برایم تاثیرگذار بوده است‪.‬‬
‫استریســک همچنان یک بســتر قوي براي توسعه ‪ VoIP‬اســت و هنوز هم موضوعﯽ‬
‫است که افراد زیادي عالقه دارند درباره آن بنویسند‪ .‬باعث خوشحالﯽ است که آقاي‬
‫اســفندیاري و همکارانشان کتابﯽ در زمینه استریســک با موضوعات و سرفصلهاي‬
‫جدید به فارسﯽ نوشــتهاند‪ .‬امیدوار هستم با رشد اینگونه کتابها به زبانهاي مختلف‪،‬‬
‫دانشجویان و افراد عالقهمند‪ ،‬بیشتر با استریسک آشنا شوند و بتوانند ازطریق مقاالت‪،‬‬
‫نوشتهها و توسعه آن‪ ،‬رشد فناوري ‪ VoIP‬را موجب شوند‪.‬‬
‫‪Leif Madsen‬‬
‫مرجع آموزش ویپ‬
‫باسافت‌سوئیچاستریسک‬
‫مجتبیاسفندیاری‬
‫سیدمجتبینجفی‌مقدم‬
‫‏سرشناسه ‪ :‬اسفندیاری‪ ،‬مجتبی‪،‬‏‫‪ ۱۳۶۲‬‏‬‪-‬‬
‫‏عنوان و نام پديدآور ‪ :‬مرجع آموزش ویپ با سافت سوئیچ استریسک‪ /‬مجتبی اسفندیاری‪ ،‬سیدمجتبی نجفی‌مقدم‪.‬‬
‫‏مشخصات نشر ‪ :‬مشهد‪ :‬واژگان خرد‪،‬‏‫‪.‬۱۳۹۵‬‬
‫‏مشخصات ظاهری ‪ 576 :‬ص ‬‬‪.‬‬
‫‏شابک ‪‬‭978-964-8931-95-2‬:‬‬
‫‏وضعیت فهرست نویسی ‪ :‬فیپا‬
‫‏یادداشت‪ :‬کتابنامه‪.‬‬
‫‏موضوع ‪ :‬استریسک (فایل کامپیوتر)‪ ،Asterisk (Computer file( ،‬تلفن اینترنتی‪Internet telephony ،‬‬
‫‏شناسه افزوده ‪ :‬نجفی مقدم‪ ،‬سیدمجتبی‪،‬‏‫‪ ۱۳۶۴‬‏‬‪-‬‬
‫‏شناسه افزوده ‪ :‬انتشارات واژگان خرد‬
‫ف‪‬‭/‬‏‪‭TK۵۱۰۵/۸۸۶۵‬‫‬‬‬‬‬‬ ‫‏رده بندی کنگره ‪:‬‏‫‬‮‬‬‪۴ ۱۳۹۵‬م‪۵‬‮ال ‬‬
‫‏رده بندی دیویی ‪:‬‏‬‪‭۰۰۴/۶۹۵۰۷۶‬‫‬‬‬
‫‏شماره کتابشناسی ملی ‪‬‭ ۴۵۶۷۰۲۸‬:‬‬

‫مرجع آموزش ویپ‬


‫با سافت‌سوئیچ استریسک‬
‫مؤلف‪ :‬مجتبی اسفندیاری ‪ ،‬سید مجتبی نجفی مقدم‬
‫ناشر‪ :‬واژگان خرد‬
‫چاپ‪ :‬دانشگاه فردوسی مشهد‬
‫نوبت چاپ‪ :‬اول ‪ -‬بهار ‪1396‬‬
‫‪ 1000‬نسخه‪ 576 ،‬صفحه‪ ،‬وزیری‬
‫قیمت ‪ 48000 :‬تومان‬

‫حق چاپ برای مؤلف محفوظ است‪.‬‬

‫مراکز پخش‬
‫تهران ‪ -‬شرکت کاوا ارتباطات هوشمند‪021- 41879000 ، 021 - 4956 ،‬‬
‫مشهد ‪ -‬شرکت نسیم ارتباطات هزاره سوم‪051 - 31770000 ،‬‬
‫وب‌سایت جهت خرید آنالین‪:‬‬
‫‪www.voipshop.ir www.shop.voip98.com‬‬
‫‪5‬‬ ‫فهرست‬

‫فهرست‬

‫پیشگفتار������������������������������������������������������������������������������������������������������������������������������������������������������‪26‬‬

‫فصل اول‪ :‬آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬


‫صدا چیست؟�����������������������������������������������������������������������������������������������������������������������������������������������‪30‬‬
‫تلفن چیست؟�����������������������������������������������������������������������������������������������������������������������������������������������‪30‬‬
‫شبکه های مخابراتی ‪ PSTN‬چیست؟�����������������������������������������������������������������������������������������������������������‪31‬‬
‫تاریخچه شبکه‌های مخابراتی ‪31�����������������������������������������������������������������������������������������������������������PSTN‬‬
‫‪33������������������������������������������������������������������������������������������������������������������������������������������������������� DTMF‬‬
‫سوئیچینگ مداری چیست؟�������������������������������������������������������������������������������������������������������������������������‪34‬‬
‫سوئیچینگ بسته‌ای چیست؟�������������������������������������������������������������������������������������������������������������������������‪34‬‬
‫انواع خطوط مخابراتی����������������������������������������������������������������������������������������������������������������������������������‪35‬‬
‫‪35‬‬ ‫گ‬
‫خطوط آنالو ‬
‫‪35‬‬ ‫خطوط دیجیتال (‪) ISDN‬‬
‫اجزای تشکیل‌دهنده تلفن معمولی����������������������������������������������������������������������������������������������������������������‪36‬‬
‫اجزای تشکیل دهنده شبکه تلفنی ‪37����������������������������������������������������������������������������������������������������� PSTN‬‬
‫‪37‬‬ ‫(‪Central Office (CO Switch‬‬
‫‪37‬‬ ‫ (‪S tation (Analog Phone‬‬

‫‪37‬‬ ‫‪Local Loop‬‬


‫‪37‬‬ ‫‪ runk‬‬
‫‪T‬‬

‫‪37‬‬ ‫‪Private Switch‬‬


‫مرکز تلفن چیست؟�������������������������������������������������������������������������������������������������������������������������������������‪38‬‬
‫سالن دستگاه مخابراتی چیست؟�������������������������������������������������������������������������������������������������������������������‪38‬‬
‫شبکه مخابراتی کشور����������������������������������������������������������������������������������������������������������������������������������‪39‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪6‬‬

‫‪39‬‬ ‫ی‬
‫سطح شهر ‬
‫‪40‬‬ ‫ی‬
‫سطح بین‌شهر ‬
‫‪40‬‬ ‫ل‬
‫سطح بین‌المل ‬
‫‪40‬‬ ‫ارتباط ‪ ISC‬های ایران با کریرهای بین المل ‬
‫ل‬
‫نتیجه‌گیری���������������������������������������������������������������������������������������������������������������������������������������������������‪41‬‬

‫فصل دوم‪ :‬معماری استریسک‬


‫مقدمه ����������������������������������������������������������������������������������������������������������������������������������������������������������‪44‬‬
‫ساختار ماژوالر در استریسک ���������������������������������������������������������������������������������������������������������������������‪45‬‬
‫‪46‬‬ ‫معرفی ماژول ‪Application‬‬
‫‪50‬‬ ‫معرفی ماژول ‪ ridge‬‬
‫‪B‬‬

‫‪51‬‬ ‫س‬
‫ماژول ریز‌ گزارشات تما ‬
‫‪52‬‬ ‫ک‬
‫ماژول رویدادهای استریس ‬
‫‪53‬‬ ‫ماژول ‪ Channel Drivers‬در استریس ‬
‫ک‬
‫‪54‬‬ ‫ماژول ‪ odec Translator‬‬
‫‪C‬‬

‫‪55‬‬ ‫ماژول ‪Format Interpreter‬‬


‫‪56‬‬ ‫‪ ialplan Function‬‬
‫‪D‬‬
‫‪58‬‬ ‫‪ BX Config‬‬
‫‪P‬‬

‫‪59‬‬ ‫ماژول ‪ esource‬‬


‫‪R‬‬

‫ساختار فایل سیستم در استریسک ����������������������������������������������������������������������������������������������������������������‪59‬‬


‫‪59‬‬ ‫ک‬
‫فایل‌های پیکربندی در استریس ‬
‫‪60‬‬ ‫ک‬
‫فایل‌ ماژول‌ها در استریس ‬
‫‪60‬‬ ‫ک‬
‫فایل‌های مانیتورینگ و گزارش‌ها در استریس ‬
‫برنامه‌نویسی در استریسک ���������������������������������������������������������������������������������������������������������������������������‪60‬‬
‫‪61‬‬ ‫استفاده از ‪extensions.conf‬‬
‫‪61‬‬ ‫استفاده از ‪extensions.ael‬‬
‫‪61‬‬ ‫استفاده از ‪extensions.lua‬‬
‫‪7‬‬ ‫فهرست‬

‫نتیجه‌گیری���������������������������������������������������������������������������������������������������������������������������������������������������‪62‬‬

‫فصل سوم‪ :‬نصب و راه اندازی استریسک‬


‫مقدمات نصب استریسک�����������������������������������������������������������������������������������������������������������������������������‪64‬‬
‫‪65‬‬ ‫بروز رسانی سیستم ‬
‫‪65‬‬ ‫ک‬
‫نصب نیازمندی‌های استریس ‬
‫‪66‬‬ ‫ک‬
‫نصب همه نیازمندی‌های استریس ‬
‫‪67‬‬ ‫دانلود سورس استریسک از طریق ‪git‬‬
‫‪67‬‬ ‫ک‬
‫دانلود سورس استریس ‬
‫‪67‬‬ ‫دانلود سورس ‪ DAHDI‬و ‪LibPRI‬‬
‫نصب استریسک ������������������������������������������������������������������������������������������������������������������������������������������‪68‬‬
‫‪70‬‬ ‫ک‬
‫معرفی دستورات نصب استریس ‬
‫پیکربندی اولیه استریسک����������������������������������������������������������������������������������������������������������������������������‪73‬‬
‫‪73‬‬ ‫فایل پیکربندی ‪asterisk.conf‬‬
‫‪73‬‬ ‫بخش [‪] directories‬‬
‫‪74‬‬ ‫بخش [‪] options‬‬
‫‪78‬‬ ‫فایل پیکربندی ماژول ها در استریسک ‪modules.conf‬‬
‫‪79‬‬ ‫فایل پیکربندی ‪indications.conf‬‬

‫‪79‬‬ ‫فایل پیکربندی ‪musiconhold.conf‬‬


‫نتیجه‌گیری���������������������������������������������������������������������������������������������������������������������������������������������������‪81‬‬

‫فصل چهارم‪ :‬پیکربندی تجهیزات در شبکه‌های ویپ‬


‫مقدمه�����������������������������������������������������������������������������������������������������������������������������������������������������������‪84‬‬
‫مراحل ایجاد یک تماس در استریسک ��������������������������������������������������������������������������������������������������������‪84‬‬
‫مفاهیم نام‌گذاری تلفن‌ها در شبکه‌های ویپ ������������������������������������������������������������������������������������������������‪86‬‬
‫انواع تجهیزات تلفنی در شبکه‌های ویپ������������������������������������������������������������������������������������������������������‪87‬‬
‫مقایسه انواع تجیهزات ویپ �������������������������������������������������������������������������������������������������������������������������‪90‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪8‬‬

‫تنظیمات و پیکربندی استریسک������������������������������������������������������������������������������������������������������������������‪91‬‬


‫نحوه تعریف یک کاربر جدید از نوع پروتکل ‪91������������������������������������������������������������������������������������� SIP‬‬
‫نحوه تعریف یک کاربر جدید از نوع پروتکل ‪93������������������������������������������������������������������������������������ IAX‬‬
‫قالب‌ها���������������������������������������������������������������������������������������������������������������������������������������������������������‪94‬‬
‫مراحل اعتبارسنجی در استریسک���������������������������������������������������������������������������������������������������������������‪95‬‬
‫نتیجه‌گیری��������������������������������������������������������������������������������������������������������������������������������������������������‪95‬‬

‫فصل پنجم‪ :‬برنامه‌نویسی مقدماتی در استریسک‬


‫مفهوم برنامه‌نویسی در استریسک ����������������������������������������������������������������������������������������������������������������‪98‬‬
‫اجزای اصلی ‪99������������������������������������������������������������������������������������������������������������������������������� Dialplan‬‬
‫‪99‬‬ ‫بخش کانتکست (‪)context‬‬
‫‪101‬‬ ‫بخش اکستنشن (‪)extensions‬‬
‫پرش بین دستورات������������������������������������������������������������������������������������������������������������������������������������‪106‬‬
‫آشنایی با برخی از دستور‌ها در استریسک �������������������������������������������������������������������������������������������������‪107‬‬
‫‪107‬‬ ‫دستور ‪Answer‬‬
‫‪107‬‬ ‫دستور ‪ layback‬‬
‫‪P‬‬

‫‪108‬‬ ‫دستور ‪ ackGround‬‬


‫‪B‬‬

‫‪111‬‬ ‫دستور ‪ oto‬‬


‫‪G‬‬

‫‪113‬‬ ‫دستور ‪Dial‬‬


‫‪113‬‬ ‫آرگومان اول‪destination :‬‬
‫‪115‬‬ ‫آرگومان دوم‪ ime‌out :‬‬
‫‪T‬‬

‫‪115‬‬ ‫آرگومان سوم‪Options :‬‬


‫‪118‬‬ ‫آرگومان چهارم‪ RL :‬‬
‫‪U‬‬

‫بررسی اکستنشن‌های خاص در استریسک�������������������������������������������������������������������������������������������������‪118‬‬


‫کنترل و مدیریت تماس‌های همزمان در سیستم تلفنی استریسک ���������������������������������������������������������������‪120‬‬
‫‪120‬‬ ‫کنترل و مدیریت تماس‌ها به صورت پشت سر‌ه م‬
‫‪121‬‬ ‫کنترل و مدیریت تماس‌ها به صورت همزما ن‬
‫‪9‬‬ ‫فهرست‬

‫تعریف متغیرها در استریسک���������������������������������������������������������������������������������������������������������������������‪122‬‬


‫انواع متغیرها در استریسک ������������������������������������������������������������������������������������������������������������������������‪123‬‬
‫‪123‬‬ ‫ی‬
‫متغیرهای سراسر ‬
‫‪124‬‬ ‫متغیرهای محلی ‬
‫‪124‬‬ ‫ی‬
‫متغیرهای محیط ‬
‫‪126‬‬ ‫ک‬
‫متغیرهای وراثتی استریس ‬
‫الگوریتم الگوی تطابق در استریسک���������������������������������������������������������������������������������������������������������‪127‬‬
‫‪129‬‬ ‫ق‬
‫بررسی مثال‌هایی برای الگوریتم الگوی تطاب ‬
‫‪131‬‬ ‫استفاده از متغیر‌های محلی{‪ $}EXTEN‬‬
‫‪131‬‬ ‫ک‬
‫اصالح شماره‌ها در سیستم تلفنی استریس ‬
‫‪132‬‬ ‫ق‬
‫اولویت‌گذاری در الگوریتم الگوی تطاب ‬
‫استفاده از ‪ include‬در برنامه نویسی استریسک������������������������������������������������������������������������������������������‪134‬‬
‫قوانین استفاده از ‪136�������������������������������������������������������������������������������������������������������������������������� include‬‬
‫استفاده از ‪ include‬در ساختار فایل‌سیستم استریسک���������������������������������������������������������������������������������‪139‬‬
‫نتیجه گیری�����������������������������������������������������������������������������������������������������������������������������������������������‪140‬‬

‫فصل ششم‪ :‬ارتباط استریسک با شبکه‌های مخابراتی‬


‫ارتباط استریسک با شبکه‌های مخابراتی ‪142����������������������������������������������������������������������������������������� PSTN‬‬
‫انواع خطوط مخابراتی�������������������������������������������������������������������������������������������������������������������������������‪143‬‬
‫‪143‬‬ ‫گ‬
‫خطوط آنالو ‬
‫‪143‬‬ ‫گ‬
‫انواع سیگنالینگ در خطوط مخابراتی آنالو ‬
‫‪143‬‬ ‫خطوط دیجیتال (‪) ISDN‬‬
‫‪144‬‬ ‫انواع خطوط دیجیتا ل‬
‫‪144‬‬ ‫‪B-ISDN‬‬
‫‪144‬‬ ‫‪N-ISDN‬‬
‫‪144‬‬ ‫‪ISDN-PRI‬‬
‫‪145‬‬ ‫‪ISDN-BRI‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪10‬‬

‫‪145‬‬ ‫سیگنالینگ کانال مرتبط ‬


‫‪145‬‬ ‫سیگنالینگ کانال مشترک ‬
‫تئوری نایکوئیست‪-‬شانن ���������������������������������������������������������������������������������������������������������������������������‪146‬‬
‫تبدیل صدای آنالوگ به صدای دیجیتال ���������������������������������������������������������������������������������������������������‪146‬‬
‫‪ DAHDI‬چیست؟�������������������������������������������������������������������������������������������������������������������������������������‪147‬‬
‫اجزای تشکیل دهنده ‪149������������������������������������������������������������������������������������������������������������������DAHDI‬‬
‫پیکربندی ماژول ‪149������������������������������������������������������������������������������������������������������������������������ DAHDI‬‬
‫‪149‬‬ ‫فایل ‪ odules‬‬
‫‪m‬‬

‫‪151‬‬ ‫فایل ‪system.conf‬‬


‫‪152‬‬ ‫دستورات مه م‬
‫آشنایی با پیکربندی فایل ‪155�������������������������������������������������������������������������������������������������system.conf‬‬
‫‪155‬‬ ‫پیکر بندی کارت ‪E1‬‬
‫‪156‬‬ ‫پیکر بندی کارت ‪T1‬‬
‫‪156‬‬ ‫پیکر بندی کارت ‪FXO‬‬
‫‪156‬‬ ‫پیکر بندی کارت ‪FXS‬‬
‫تنظیمات کارت‌های ‪157�������������������������������������������������������������������������������������������������������������������������� PRI‬‬
‫تنظیمات‌ کارت‌های ‪159���������������������������������������������������������������������������������������������������������������� FXO/FXS‬‬
‫تنظیمات ارتباط ماژول ‪ DAHDI‬با استریسک�������������������������������������������������������������������������������������������‪160‬‬
‫تنظیمات مربوط به کارت‌های ‪ PRI‬در استریسک��������������������������������������������������������������������������������������‪161‬‬
‫‪161‬‬ ‫پارامتر ‪context‬‬
‫‪161‬‬ ‫پارامتر ‪channel‬‬
‫‪161‬‬ ‫پارامتر ‪signaling‬‬
‫‪162‬‬ ‫پارامتر ‪switchtype‬‬
‫تنظیمات مربوط به کارت‌های ‪ FXO/FXS‬در استریسک���������������������������������������������������������������������������‪162‬‬
‫کنترل تماس‌های ورودی به کارت‌های ‪( DAHDI‬از شبکه مخابراتی ‪164�������������������������������������������)PSTN‬‬
‫کنترل تماس‌های خروجی از کارت‌های ‪( DAHDI‬به شبکه مخابراتی ‪166�����������������������������������������)PSTN‬‬
‫مقایسه کارت‌های ‪ FXO‬با ‪ FXS‬از نقطه نظر سیگنالینگ����������������������������������������������������������������������������‪168‬‬
‫‪11‬‬ ‫فهرست‬

‫تعریف داخلی‌های ‪ FXS‬در استریسک������������������������������������������������������������������������������������������������������‪169‬‬


‫مقایسه کارت‌های ‪ FXO‬با ‪ FXS‬از نقطه‌نظر فراخوانی در برنامه‌نویسی��������������������������������������������������������‪170‬‬
‫نتیجه‌گیری�����������������������������������������������������������������������������������������������������������������������������������������������‪170‬‬

‫فصل هفتم‪ :‬ارتباط استریسک با سایر شبکه‌های ‪VoIP‬‬


‫ارتباط استریسک با سایر شبکه‌های������������������������������������������������������������������������������������������������������������‪172‬‬
‫آشنایی با پروتکل ‪173�������������������������������������������������������������������������������������������������������������������������������SIP‬‬
‫بررسی مشکالت ‪ NAT‬در شبکه‌های ویپ������������������������������������������������������������������������������������������������‪177‬‬
‫‪178‬‬ ‫کالینت با ‪ NAT‬کار کن د‬
‫‪182‬‬ ‫سرور استریسک قبل از ‪ NAT‬باش د‬
‫‪183‬‬ ‫بررسی حالت ‪( double_nat‬استریسک و کالینت هر دو به ‪ NAT‬متصل‌اند)‬
‫کنترل جریان‌های ترافیکی (‪ )RTP‬در استریسک���������������������������������������������������������������������������������������‪183‬‬
‫‪183‬‬ ‫کنترل جریان‌های ترافیکی مدیا به صورت ‪B2BUA‬‬
‫‪184‬‬ ‫کنترل جریان ترافیکی به صورت ‪Point-To-Point‬‬
‫‪185‬‬ ‫‪ STN Termination‬‬
‫‪P‬‬

‫‪186‬‬ ‫‪ STN ORGINATION‬‬


‫‪P‬‬

‫‪186‬‬ ‫‪VOIP _TO_ VOIP‬‬


‫توپولوژی ذوزنقه‌ای ����������������������������������������������������������������������������������������������������������������������������������‪186‬‬
‫توپولوژی مثلثی ����������������������������������������������������������������������������������������������������������������������������������������‪187‬‬
‫‪187���������������������������������������������������������������������������������������������������������������������������������SIP_Trunk‬‬
‫‪189‬‬ ‫‪SIP_Providers‬‬
‫‪190‬‬ ‫‪IAX2_TRUNK‬‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪192‬‬

‫فصل هشتم‪ :‬برنامه نویسی پیشرفته در استریسک‬


‫برنامه‌نویسی پیشرفته در استریسک�������������������������������������������������������������������������������������������������������������‪194‬‬
‫عبارات محاسباتی و منطقی در برنامه‌نویسی استریسک ������������������������������������������������������������������������������‪194‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪12‬‬

‫‪197‬‬ ‫ک‬
‫عبارات منطقی در برنامه‌نویسی استریس ‬
‫‪198‬‬ ‫عملگرهای مقایسه‌ای (بزرگتر‪ ،‬کوچکتر‪ ،‬مساوی‪ ،‬نامساوی)‬
‫‪199‬‬ ‫عملگرهای ریاضی (‪ )mathemetical‬در استریس ‬
‫ک‬
‫استفاده از دستورات و توابع در برنامه‌نویسی استریسک������������������������������������������������������������������������������‪200‬‬
‫‪200‬‬ ‫ک‬
‫استفاده از توابع در استریس ‬
‫‪202‬‬ ‫استفاده از تابع ‪ TIMEOUT‬در استریس ‬
‫ک‬
‫‪203‬‬ ‫ک‬
‫استفاده از دستورات و توابع شرطی در استریس ‬
‫‪204‬‬ ‫دستور ‪GotoIf‬‬
‫‪206‬‬ ‫دستور ‪ GotoIfTime‬‬
‫بررسی خطاهای منطقی در برنامه‌نویسی استریسک�������������������������������������������������������������������������������������‪209‬‬
‫استفاده از ماکروها در استریسک ���������������������������������������������������������������������������������������������������������������‪211‬‬
‫‪212‬‬ ‫تعریف ماکر و‬
‫‪213‬‬ ‫انواع متغیر‌ها در ماکر و‬
‫تعریف توابع در استریسک ������������������������������������������������������������������������������������������������������������������������‪215‬‬
‫‪216‬‬ ‫استفاده از دستور ‪ Return‬در تواب ع‬
‫‪217‬‬ ‫استفاده از متغیر{‪ $}GOSUB_RETVAL‬‬
‫کانال محلی در استریسک �������������������������������������������������������������������������������������������������������������������������‪218‬‬
‫‪219‬‬ ‫ک‬
‫بهینه‌سازی کانال‌ها در استریس ‬
‫استفاده از ‪221������������������������������������������������������������������������������������������������������������������������������������� AstDB‬‬
‫‪221‬‬ ‫س‬
‫نمایش داده‌های ذخیره شده در دیتابی ‬
‫‪221‬‬ ‫ذخیره کردن داده‌ی جدید در ‪ stDB‬‬
‫‪A‬‬

‫‪222‬‬ ‫خواندن داده‌ها از ‪AstDB‬‬


‫‪222‬‬ ‫حذف داده‌ها از ‪AstDB‬‬
‫استفاده از صندوق صوتی در استریسک�����������������������������������������������������������������������������������������������������‪225‬‬
‫‪233‬‬ ‫ک‬
‫تعریف صندوق صوتی جدید در استریس ‬
‫‪236‬‬ ‫ک‬
‫استفاده از صندوق صوتی در برنامه‌نویسی استریس ‬
‫‪237‬‬ ‫دستور ‪ oiceMail‬‬
‫‪V‬‬
‫‪13‬‬ ‫فهرست‬

‫‪238‬‬ ‫دستور ‪VoiceMailMain‬‬


‫‪238‬‬ ‫ک‬
‫بررسی فایل سیستم صندوق صوتی در استریس ‬
‫آشنایی با ‪ Feature Code‬ها در استریسک�������������������������������������������������������������������������������������������������‪239‬‬
‫‪240‬‬ ‫‪Call Parking‬‬
‫‪243‬‬ ‫تماس‬
‫‌‬ ‫انواع مدل‌های انتقال‬
‫‪246‬‬ ‫استفاده از ‪ Feture Code‬های پویا در استریس ‬
‫ک‬
‫‪246‬‬ ‫پارامتره ا‬
‫استفاده از قابلیت کنفرانس در استریسک ���������������������������������������������������������������������������������������������������‪247‬‬
‫‪248‬‬ ‫استفاده از دستور ‪ MeetMe‬در استریس ‬
‫ک‬
‫‪248‬‬ ‫پارامترهای الز م‬
‫‪249‬‬ ‫استفاده از دستور ‪ MeetMeCOUNT‬در استریس ‬
‫ک‬
‫‪250‬‬ ‫استفاده از دستور ‪ onfBridge‬‬
‫‪C‬‬

‫‪254‬‬ ‫مهمترین پارامترها در دستور ‪ ConfBridge‬‬


‫‪257‬‬ ‫ک‬
‫برقراری ایجاد کنفرانس تصویری در استریس ‬
‫نتیجه‌گیری�������������������������������������������������������������������������������������������������������������������������������������������������‪257‬‬

‫فصل نهم‪ :‬آشنایی با صف‌ها در استریسک‬


‫صف (‪260��������������������������������������������������������������������������������������������������������������������������������������������)ACD‬‬
‫تعریف صف در سیستم تلفنی استریسک ���������������������������������������������������������������������������������������������������‪261‬‬
‫اضافه و حذف‌کردن اپراتور‌ها (‪ )member‬به یک صف در استریسک������������������������������������������������������‪269‬‬
‫‪269‬‬ ‫ک‬
‫اضافه و حذف کردن اپراتور به صف به‌صورت داینامی ‬
‫‪269‬‬ ‫ف‬
‫اضافه‌کردن یک اپراتور به ص ‬
‫‪270‬‬ ‫‪ pause/unpause‬کردن یک اپراتور در ص ‬
‫ف‬
‫‪271‬‬ ‫ف‬
‫حذف کردن یک اپراتور از ص ‬
‫‪271‬‬ ‫ف‬
‫اضافه و حذف کردن اپراتور به صف به‌صورت استاتیک در زمان تعریف ص ‬
‫‪272‬‬ ‫ک‬
‫اضافه و حذف کردن اپراتور به صف به‌صورت داینامی ‬
‫مشاهده وضعیت اپراتورها در صف������������������������������������������������������������������������������������������������������������‪275‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪14‬‬

‫مدیریت و کنترل اعالن‌ها در صف������������������������������������������������������������������������������������������������������������‪282‬‬


‫صف‌های وزن‌دار (با اولویت)��������������������������������������������������������������������������������������������������������������������‪285‬‬
‫‪287‬‬ ‫ف‬
‫اولویت‌گذاری در اپراتورهای عضو یک ص ‬
‫استفاده از ‪ queuerules‬در صف‌ها�������������������������������������������������������������������������������������������������������������‪290‬‬
‫مدیریت الگ‌های صف در استریسک������������������������������������������������������������������������������������������������������‪292‬‬
‫اعالم شماره اپراتور هنگام پاسخ‌گویی�������������������������������������������������������������������������������������������������������‪295‬‬
‫نتیجه‌گیری�������������������������������������������������������������������������������������������������������������������������������������������������‪296‬‬

‫فصل دهم‪ :‬بررسی وضعیت تجهیزات در شبکه‌های ویپ‬


‫مقدمه ��������������������������������������������������������������������������������������������������������������������������������������������������������‪298‬‬
‫بررسی وضعیت دیوایس‌ها در استریسک��������������������������������������������������������������������������������������������������‪299‬‬
‫‪300‬‬ ‫ک‬
‫بررسی انواع وضعیت دیوایس‌ها در استریس ‬
‫بررسی وضعیت اکستنشن‌ها در استریسک ������������������������������������������������������������������������������������������������‪300‬‬
‫بررسی قابلیت ‪ SUBSCRIBE-NOTIFY‬در شبکه‌های ویپ ��������������������������������������������������������������������‪303‬‬
‫‪305‬‬ ‫تنظیمات ‪ SUBSCRIBE-NOTIFY‬در استریس ‬
‫ک‬
‫استفاده از ‪ Custom Device State‬در استریسک���������������������������������������������������������������������������������������‪306‬‬
‫‪307‬‬ ‫تعریف ‪Custom Device State‬‬
‫بررسی وضعیت کاربران (اپراتورها) در سیستم‌های توزیع‌شده��������������������������������������������������������������������‪310‬‬
‫‪311‬‬ ‫استفاده از ‪ Corosync‬برای برقراری ارتباط میان سرورهای استریس ‬
‫ک‬
‫‪312‬‬ ‫پیکربندی ‪Corosync‬‬
‫‪314‬‬ ‫استفاده از ‪ XMPP‬برای برقراری ارتباط میان سرورهای استریسک ‬
‫سرویس ‪ CCSS‬در استریسک�������������������������������������������������������������������������������������������������������������������‪315‬‬
‫نتیجه‌گیری�������������������������������������������������������������������������������������������������������������������������������������������������‪316‬‬

‫فصل یازدهم‪ :‬ارتباط بین استریسک و پایگاه داده‌ای‬


‫مقدمه ��������������������������������������������������������������������������������������������������������������������������������������������������������‪318‬‬
‫نصب ‪ PostgreSQL‬در لینوکس����������������������������������������������������������������������������������������������������������������‪319‬‬
‫‪15‬‬ ‫فهرست‬

‫نصب ‪ MySQL‬در لینوکس����������������������������������������������������������������������������������������������������������������������‪319‬‬


‫پیکربندی ‪ PostgreSQL‬در لینوکس ���������������������������������������������������������������������������������������������������������‪320‬‬
‫پیکربندی ‪ MySQL‬در لینوکس�����������������������������������������������������������������������������������������������������������������‪322‬‬
‫نصب و پیکربندی ‪ ODBC‬در لینوکس ����������������������������������������������������������������������������������������������������‪323‬‬
‫‪325‬‬ ‫پیکربندی ‪ ODBC‬برای ارتباط با پایگاه داده‌ای ‪PostgreSQL‬‬
‫‪326‬‬ ‫پیکربندی ‪ ODBC‬برای ارتباط با پایگاه داده‌ای ‪ ySQL‬‬
‫‪M‬‬

‫‪327‬‬ ‫پیکربندی ‪ ODBC‬برای ارتباط با پایگاه داده‌ای ‪ icrosoft SQL‬‬


‫‪M‬‬

‫پیکربندی ماژول ‪ res_odbc.so‬در استریسک�������������������������������������������������������������������������������������������‪329‬‬


‫مدیریت پایگاه‌های داده‌ای������������������������������������������������������������������������������������������������������������������������‪330‬‬
‫‪331���������������������������������������������������������������������������������������������������������������������������������������� SQL Injection‬‬
‫استفاده از پایگاه‌های داده‌ای در برنامه نویسی استریسک����������������������������������������������������������������������������‪331‬‬
‫‪334‬‬ ‫تغییر پیشوند در فراخوانی توابع از فایل ‪res_odbc‬‬
‫‪334‬‬ ‫اضافه‌کردن توضیحات در خصوص توابع تعریف‌شده در فایل ‪res_odbc‬‬
‫‪335‬‬ ‫استفاده از دستورات ‪ ulti Row Query‬‬
‫‪M‬‬

‫‪336‬‬ ‫استفاده از دستورات ‪ SQL Query‬در برنامه‌نویسی استریس ‬


‫ک‬
‫(‪337�������������������������������������������������������������������������������� Asterisk Realtime Architecture (ARA‬‬
‫‪338‬‬ ‫معماری ‪ RA_Static‬‬
‫‪A‬‬

‫‪343‬‬ ‫معماری ‪ RA_Dynamic‬‬


‫‪A‬‬

‫‪348‬‬ ‫س‬
‫ساختن صف در دیتابی ‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪352‬‬

‫فصل دوازدهم‪ :‬فکس‬


‫فکس چیست ��������������������������������������������������������������������������������������������������������������������������������������������‪354‬‬
‫بررسی نقاط ضعف در خصوص ماشین‌های فکس (‪354���������������������������������������������������������)Fax Machine‬‬
‫فکس‌های اینترنتی�������������������������������������������������������������������������������������������������������������������������������������‪355‬‬
‫بررسی انواع روش‌های ارسال و دریافت فکس������������������������������������������������������������������������������������������‪355‬‬
‫پروتکل ‪356��������������������������������������������������������������������������������������������������������������������������������������������T.38‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪16‬‬

‫ارسال و دریافت فکس با استریسک�����������������������������������������������������������������������������������������������������������‪357‬‬


‫ماژول ‪357���������������������������������������������������������������������������������������������������������������������������������������SpanDSP‬‬
‫‪358‬‬ ‫نصب ماژول ‪ Spandsp‬در توزیع‌های لینوک ‬
‫س‬
‫دریافت فکس در استریسک����������������������������������������������������������������������������������������������������������������������‪360‬‬
‫‪360‬‬ ‫استفاده از دستور ‪ ReceiveFAX‬در استریس ‬
‫ک‬
‫‪361‬‬ ‫استفاده از مودم‌های مجازی(‪ )IAXmodem‬برای دریافت فک ‬
‫س‬
‫‪361‬‬ ‫س‬
‫نصب مودم‌های مجازی در لینوک ‬
‫‪362‬‬ ‫س‬
‫پیکربندی مودم‌های مجازی در لینوک ‬
‫‪365‬‬ ‫س‬
‫نصب سرویس فکس در لینوک ‬
‫‪367‬‬ ‫استفاده از دستگاه‌های ماشین فکس در شبکه ویپ (‪ )Fax Pass-Through‬‬
‫فعال کردن پروتکل ‪ T.38‬و تجهیزات وابسته در استریسک �����������������������������������������������������������������������‪368‬‬
‫بررسی عامل تاخیر در ارسال و دریافت فکس �������������������������������������������������������������������������������������������‪368‬‬
‫ارسال فکس در استریسک�������������������������������������������������������������������������������������������������������������������������‪369‬‬
‫‪369‬‬ ‫استفاده از دستور ‪S endFAX‬‬

‫‪370‬‬ ‫استفاده از مودم‌های مجازی (‪ )IAXModem‬برای ارسال فک ‬


‫س‬
‫‪372‬‬ ‫استفاده از ماشین‌های فکس در شبکه ‪ )Fax Pass-Through) VOIP‬‬
‫تشخیص اتوماتیک فکس (‪372���������������������������������������������������������������������������������������������)Fax Detection‬‬
‫نتیجه‌گیری�������������������������������������������������������������������������������������������������������������������������������������������������‪374‬‬

‫فصل سیزدهم‪ :‬ابزار مدیریتی استریسک‬


‫ابزار مدیریتی استریسک ����������������������������������������������������������������������������������������������������������������������������‪376‬‬
‫انواع رویداد‌ها در استریسک����������������������������������������������������������������������������������������������������������������������‪376‬‬
‫‪377‬‬ ‫رویدادهای مبتنی ‪ anager Event‬‬
‫‪M‬‬

‫‪377‬‬ ‫رویداد‌های مبتنی بر ‪ Manager Action‬‬


‫پیکر‌بندی ابزار مدیریتی ‪378��������������������������������������������������������������������������������������������������������������������AMI‬‬
‫‪379‬‬ ‫‪ AMI over TCP‬‬
‫‪380‬‬ ‫‪AMI over HTTP‬‬
‫‪17‬‬ ‫فهرست‬

‫‪381‬‬ ‫پیکربندی عمومی ‪ MI‬‬


‫‪A‬‬

‫‪383‬‬ ‫پیکربندی یوزر اکانت در ‪AMI‬‬


‫کنترل رویدادها در استریسک��������������������������������������������������������������������������������������������������������������������‪384‬‬
‫استفاده از ابزار مدیریتی ‪ AMI‬در برنامه کاربردی���������������������������������������������������������������������������������������‪386‬‬
‫استفاده از ‪‌Call Files‬ها در استریسک ��������������������������������������������������������������������������������������������������������‪390‬‬
‫نتیجه‌گیری�������������������������������������������������������������������������������������������������������������������������������������������������‪394‬‬

‫فصل چهاردهم‪ :‬ابزارهای برنامه‌نویسی استریسک‬


‫ابزار‌های برنامه‌نویسی استریسک ����������������������������������������������������������������������������������������������������������������‪396‬‬
‫مفهوم ‪396������������������������������������������������������������������������������������������������������������������������������������������������� AA‬‬
‫مفهوم ‪398������������������������������������������������������������������������������������������������������� Interactive Voice Response‬‬
‫یک فایل ‪ AGI‬چگونه کار می‌کند������������������������������������������������������������������������������������������������������������‪402‬‬
‫‪403‬‬ ‫جریان‌های اجرایی فایل‌های ‪ GI‬‬
‫‪A‬‬

‫دستورات ‪403������������������������������������������������������������������������������������������������������������������������������������������ AGI‬‬


‫انواع روش‌های فراخوانی فایل‌های ‪406���������������������������������������������������������������������������������������������������� AGI‬‬
‫‪406‬‬ ‫استفاده از دستور ‪ AGI‬در استریس ‬
‫ک‬
‫‪406‬‬ ‫استفاده از ‪ Dead AGI‬در استریس ‬
‫ک‬
‫‪407‬‬ ‫استفاده از ‪ FastAGI‬در استریس ‬
‫ک‬
‫‪408‬‬ ‫نمونه‌ای از برنامه‌نویسی ‪ astAGI‬‬
‫‪F‬‬

‫انواع متغیر‌های ‪ AGI‬هنگام فراخوانی یک فایل ‪409��������������������������������������������������������������������������������� AGI‬‬

‫فصل پانزدهم‪ :‬ابزارهای ‪ RESTful‬در استریسک‬


‫ابزارهای ‪ RESTful‬در استریسک���������������������������������������������������������������������������������������������������������������‪418‬‬
‫ابزار مدیریتی در استریسک�����������������������������������������������������������������������������������������������������������������������‪418‬‬
‫ابزارهای برنامه‌نویسی در استریسک ���������������������������������������������������������������������������������������������������������‪419‬‬
‫‪419‬‬ ‫تکنولوژی ‪ RESTful‬‬
‫‪420‬‬ ‫تکنولوژی ‪ ebSocket‬‬
‫‪W‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪18‬‬

‫‪420‬‬ ‫‪S tasis‬‬

‫تنظیمات و پیکربندی ‪ WebSocket‬در استریسک ��������������������������������������������������������������������������������������‪421‬‬


‫تنظیمات و پیکربندی ‪ ARI‬در استریسک���������������������������������������������������������������������������������������������������‪421‬‬
‫‪421‬‬ ‫استفاده از ‪wscat‬‬
‫‪422‬‬ ‫ت‬
‫استفاده از جاوا اسکریپ ‬
‫‪422‬‬ ‫استفاده از ‪Python‬‬
‫فراخوانی برنامه ‪ ARI‬در استریسک������������������������������������������������������������������������������������������������������������‪423‬‬
‫روش‌های مختلف فراخوانی ‪424�����������������������������������������������������������������������������������������������RESTful API‬‬
‫‪425‬‬ ‫استفاده از ‪ curl‬و ‪ RESTful‬برای ارسال داده‌ها از برنامه ‪ ARI‬به استریس ‬
‫ک‬
‫‪426‬‬ ‫استفاده از افزونه ‪ POSTMAN‬در مرورگر ‪Chrome‬‬
‫بررسی ساختار ‪ RESTful API‬در استریسک ���������������������������������������������������������������������������������������������‪427‬‬
‫‪427‬‬ ‫‪ sterisk REST Data Models‬‬
‫‪A‬‬

‫‪429‬‬ ‫بررسی انواع مدل‌های ‪ sterisk RESTful‬‬


‫‪A‬‬

‫‪431‬‬ ‫استفاده از ‪ sterisk REST API‬‬


‫‪A‬‬

‫‪432‬‬ ‫استفاده از ‪Bridge REST API‬‬


‫‪433‬‬ ‫استفاده از ‪Channel REST API‬‬
‫‪435‬‬ ‫استفاده از ‪Endpoints REST API‬‬
‫‪437‬‬ ‫استفاده از ‪Event REST API‬‬
‫‪437‬‬ ‫استفاده از ‪Recording REST API‬‬
‫‪438‬‬ ‫استفاده از ‪Sounds REST API‬‬
‫‪439‬‬ ‫استفاده از ‪Applications REST API‬‬
‫‪440‬‬ ‫استفاده از ‪Playbacks REST API‬‬
‫‪440‬‬ ‫استفاده از ‪Devicestates REST API‬‬
‫نتیجه گیری������������������������������������������������������������������������������������������������������������������������������������������������‪441‬‬

‫فصل شانزدهم‪ :‬استفاده از ماژول ‪ PJSIP‬در استریسک‬


‫مقدمه ��������������������������������������������������������������������������������������������������������������������������������������������������������‪444‬‬
‫‪19‬‬ ‫فهرست‬

‫درباره ‪444���������������������������������������������������������������������������������������������������������������������������������������������� pjsip‬‬


‫‪445‬‬ ‫نصب ماژول ‪ pjsip‬در استریس ‬
‫ک‬
‫مهاجرت از ‪ chan_sip‬به ‪ pjsip‬در استریسک��������������������������������������������������������������������������������������������‪447‬‬
‫تعریف کاربران جدید در ماژول ‪448������������������������������������������������������������������������������������������������������ pjsip‬‬
‫تعریف ترانک‌ها (‪ )SIP-Trunk‬در ماژول ‪449��������������������������������������������������������������������������������������� pjsip‬‬
‫استفاده از ماژول ‪ pjsip‬در محیط کامندالین استریسک �����������������������������������������������������������������������������‪453‬‬
‫استفاده از ماژول ‪ pjsip‬در برنامه‌نویسی استریسک�������������������������������������������������������������������������������������‪453‬‬
‫پیکربندی فایل ‪454��������������������������������������������������������������������������������������������������������������������������������� pjsip‬‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪459‬‬

‫فصل هفدهم‪ :‬مانیتورینگ و بررسی گزارش‌ها در استریسک‬


‫مقدمه��������������������������������������������������������������������������������������������������������������������������������������������������������‪462‬‬
‫چهار حوزه مدیریت متفاوت شبکه������������������������������������������������������������������������������������������������������������‪463‬‬
‫مدیریت شبکه (‪463�����������������������������������������������������������������������������������������)Network Manager System‬‬
‫‪464‬‬ ‫انواع تقسیم بندی‌های مدیریت شبک ه‬
‫اهمیت مدیریت شبکه‌های ‪464��������������������������������������������������������������������������������������������������������������� VoIP‬‬
‫فایل پیکربندی ‪ logger‬در استریسک���������������������������������������������������������������������������������������������������������‪464‬‬
‫گزارش جزئیات تماس‌ها در استریسک�����������������������������������������������������������������������������������������������������‪466‬‬
‫‪467‬‬ ‫فیلدهای موجود در ماژول ‪ DR‬‬
‫‪C‬‬

‫‪470‬‬ ‫استفاده از ‪ CDR Backend‬در استریس ‬


‫ک‬
‫‪471‬‬ ‫استفاده از فایل ‪cdr_adaptive_odbc.conf‬‬
‫‪473‬‬ ‫پیکربندی فایل ‪ cdr.conf‬در استریس ‬
‫ک‬
‫‪474‬‬ ‫پیکربندی فایل ‪ cdr_custom‬در استریس ‬
‫ک‬
‫‪475‬‬ ‫پیکربندی فایل ‪ cdr_manager‬در استریس ‬
‫ک‬
‫‪477‬‬ ‫ثبت گزارش های ‪ CDR‬در فایل ‪s yslog‬‬

‫گزارش رویدادها در استریسک ‪478��������������������������������������������������������������������������������������������������������CEL‬‬


‫‪479‬‬ ‫انواع رویداد ‪ CEL‬در استریس ‬
‫ک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪20‬‬

‫‪480‬‬ ‫انواع فیلدها در گزارش سطری رویدادهای ‪ CEL‬در استریسک ‬


‫‪481‬‬ ‫استفاده از دستور ‪ CELGenUserEvent‬در برنامه‌نویسی استریس ‬
‫ک‬
‫‪482‬‬ ‫پیکربندی فایل ‪ cel.conf‬در استریس ‬
‫ک‬
‫‪483‬‬ ‫ثبت گزارش های ماژول ‪ CEL‬در پایگاه داده (‪)CEL Backend‬‬
‫‪485‬‬ ‫پیکربندی فایل ‪ CEL_manager‬در استریس ‬
‫ک‬
‫پروتکل مدیریت شبکه (‪486�������������������������������������������������������������������������������������������������������������) SNMP‬‬
‫‪487‬‬ ‫وظایف تجهیزات در شبک ه‬
‫‪487‬‬ ‫وظایف مدیریت شبک ه‬
‫‪487‬‬ ‫‪SNMP Community‬‬
‫‪488‬‬ ‫ک‬
‫نصب ماژول ‪ SNMP‬در استریس ‬
‫مدیریت و خطایابی سیستم تلفنی استریسک با استفاده از قابلیت ‪492�������������������������������������� BACKTRACE‬‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪494‬‬

‫فصل هجدهم‪ :‬امنیت در سیستم تلفنی استریسک‬


‫مقدمه��������������������������������������������������������������������������������������������������������������������������������������������������������‪496‬‬
‫امنیت یک شبکه چیست؟ �������������������������������������������������������������������������������������������������������������������������‪496‬‬
‫انواع آسیب‌پذیری‌های حمله‌ها������������������������������������������������������������������������������������������������������������������‪497‬‬
‫نتایج انواع حمله‌ها در شبکه‌ها��������������������������������������������������������������������������������������������������������������������‪497‬‬
‫بررسی انواع حمله‌ها در شبکه‌های ویپ ����������������������������������������������������������������������������������������������������‪498‬‬
‫‪498‬‬ ‫حمله ‪ DOS‬‬
‫‪498‬‬ ‫شنود ‬
‫‪498‬‬ ‫تغییر در جریان صدا ‬
‫‪499‬‬ ‫سوء استفاده رایگان از حساب ‬
‫‪499‬‬ ‫تغییر مسیر تماس‌ها ‬
‫‪499‬‬ ‫دست‌کاری در داده‌های حساب کاربر ‬
‫‪500‬‬ ‫جعل هویت شناسه تماس ‬
‫‪500‬‬ ‫تماس‌های ناخواسته یا ‪S PIT‬‬
‫‪21‬‬ ‫فهرست‬

‫خصیصه‌های دفاعی در شبکه‌های ویپ و چالش‌های حیاتی ���������������������������������������������������������������������‪501‬‬


‫‪502‬‬ ‫ربودن ثبت‌نام در پروتکل ‪ SIP‬‬
‫‪502‬‬ ‫تغییر پیام پروتکل ‪ SIP‬‬
‫‪502‬‬ ‫حمله لغو ‪ /‬خداحافظی در ‪ SIP‬‬
‫‪503‬‬ ‫حمله بازگشت در ‪ SIP‬‬
‫‪503‬‬ ‫حمله دعوت مجدد در ‪ SIP‬‬
‫‪503‬‬ ‫حمله به‌روزرسانی در ‪ SIP‬‬
‫‪504‬‬ ‫حمله اطالعات ‬
‫‪505‬‬ ‫ایجاد ناهنجاری در دستورات ‪ SIP‬‬
‫‪505‬‬ ‫حمله تغییر مسیر در ‪ SIP‬‬
‫‪505‬‬ ‫حمله با ِر کاری ‪ RTP‬‬
‫‪505‬‬ ‫دست‌کاری ‪ RTP‬‬
‫انواع حمله‌ها در شبکه‌های ‪506��������������������������������������������������������������������������������������������������������������������IP‬‬
‫‪506‬‬ ‫حمله فیزیکی ‬
‫‪506‬‬ ‫حمله ‪ ARP‬‬
‫‪506‬‬ ‫جعل آدرس سخت‌افزاری ‬
‫‪506‬‬ ‫جعل آدرس ‪ IP‬‬
‫‪507‬‬ ‫بسته‌های نامعتبر ‬
‫‪507‬‬ ‫حمله سیل‌آسای پیام ‪ SYN‬در پروتکل ‪ TCP‬‬
‫‪507‬‬ ‫حمله بازپخش پروتکل ‪ UDP‬و ‪ TCP‬‬
‫‪507‬‬ ‫حمله ‪ TFTP‬‬
‫‪508‬‬ ‫حمله ‪DHCP‬‬
‫‪508‬‬ ‫حمله ‪ICMP‬‬
‫‪508‬‬ ‫حمله سرریز بافر ‬
‫‪508‬‬ ‫حمله به سیستم‌عامل ‬
‫‪508‬‬ ‫ویروس‌ها ‬
‫‪508‬‬ ‫حمله به پایگاه داده ‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪22‬‬

‫امنیت سیگنالیک در پروتکل ‪509��������������������������������������������������������������������������������������������������������������SIP‬‬


‫‪509‬‬ ‫استفاده از پروتکل ‪ TLS‬در سیگنالینگ شبکه‌های وی ‬
‫پ‬
‫‪510‬‬ ‫ایجاد کلیدهای رمزنگاری به‌وسیله اسکریپت ‪ast_tls_cert‬‬
‫‪511‬‬ ‫ک‬
‫برقراری ارتباط امن بین کالینت‌ها و سرور استریس ‬
‫‪513‬‬ ‫ک‬
‫برقراری ارتباط امن میان سرورهای استریس ‬
‫امنیت مدیا (‪ )RTP‬در شبکه‌های ویپ �������������������������������������������������������������������������������������������������������‪515‬‬
‫‪516‬‬ ‫استفاده از ‪res_srtp.so‬‬
‫امنیت در پروتکل ‪517������������������������������������������������������������������������������������������������������������������������������IAX‬‬
‫راهکارهای امنیتی در سیستم تلفنی استریسک��������������������������������������������������������������������������������������������‪517‬‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪520‬‬

‫فصل نوزدهم‪ :‬ازریابی عملکرد سیستم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬


‫مقدمه��������������������������������������������������������������������������������������������������������������������������������������������������������‪522‬‬
‫طرح سؤاالت کلیدی هنگام استفاده از سیستم‌های تلفنی ‪523�������������������������������������������������������������� IPPBX‬‬
‫اهداف اصلی سواالت و ارائه راه حل‌های مناسب��������������������������������������������������������������������������������������‪524‬‬
‫بررسی آزمایشگاه‌های سیستم‌های تلفنی ‪ IPPBX‬در ایران�������������������������������������������������������������������������‪524‬‬
‫مدل سازی چیست؟�����������������������������������������������������������������������������������������������������������������������������������‪525‬‬
‫انواع روش‌های ارزیابی یک سیستم تلفنی �������������������������������������������������������������������������������������������������‪525‬‬
‫بررسی وضعیت یک سیستم ����������������������������������������������������������������������������������������������������������������������‪526‬‬
‫بررسی دو دیدگاه متفاوت از مدل‌سازی����������������������������������������������������������������������������������������������������‪526‬‬
‫مراحل مدل‌سازی یک سیستم �������������������������������������������������������������������������������������������������������������������‪527‬‬
‫ابزار‌های شبیه‌سازی �����������������������������������������������������������������������������������������������������������������������������������‪527‬‬
‫انواع پیام‌ها در پروتکل ‪528����������������������������������������������������������������������������������������������������������������������� SIP‬‬
‫سناریوهای مهم شبکه‌های ویپ�����������������������������������������������������������������������������������������������������������������‪529‬‬
‫معرفی ابزار ‪536�������������������������������������������������������������������������������������������������������������������������������������� SIPP‬‬
‫بررسی انواع سناریوها در ‪537����������������������������������������������������������������������������������������������������������������� SIPP‬‬
‫‪539‬‬ ‫طراحی سناریوی ‪ PTIONS‬‬
‫‪O‬‬
‫‪23‬‬ ‫فهرست‬

‫‪540‬‬ ‫طراحی سناریوی ‪ EGISTER‬‬


‫‪R‬‬

‫‪543‬‬ ‫طراحی سناریوی ‪I NVITE‬‬

‫بررسی تأثیر عوامل مؤثر بر مصرف منابع سیستم‌های تلفنی ‪551���������������������������������������������� IPPBX‬‬
‫‪551‬‬ ‫ی‬
‫تاثیرمیزان تماس ورودی بر منابع سیستم تلفن ‬
‫‪552‬‬ ‫تأثیر مدیا (‪ )RTP‬بر منابع سیستم تلفن ‬
‫ی‬
‫بررسی کیفیت سرویس (‪ )Quality of Service‬در سیستم‌های تلفنی ‪553�������������������������������������������� IPPBX‬‬
‫‪553‬‬ ‫از بین رفتن بسته‌ه ا‬
‫‪554‬‬ ‫تاخی ر‬
‫‪554‬‬ ‫تغییرات تأخی ر‬
‫‪555‬‬ ‫پارامتر ‪ MOS‬در شبکه‌های وی ‬
‫پ‬
‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪556‬‬

‫فصل بیستم‪ :‬آشنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬


‫مقدمه��������������������������������������������������������������������������������������������������������������������������������������������������������‪558‬‬
‫دستورات ایجاد یک تماس در استریسک��������������������������������������������������������������������������������������������������‪559‬‬
‫‪559‬‬ ‫دستور ‪console‬‬
‫‪559‬‬ ‫دستور ‪originate‬‬
‫دستورات مربوط به کنترل تماس‌ها (‪560�������������������������������������������������������������������������������)Call Handling‬‬
‫‪560‬‬ ‫دستور ‪Answer‬‬
‫‪560‬‬ ‫دستور ([‪Busy([Timeout‬‬
‫‪560‬‬ ‫دستور ‪ rogress‬‬
‫‪P‬‬

‫‪561‬‬ ‫دستور (‪DISA (Direct Inward System Access‬‬


‫‪562‬‬ ‫دستور ‪FollowMe‬‬
‫دستورات مربوط به کنترل‌های شرطی و ‪ Timeout‬در استریسک��������������������������������������������������������������‪562‬‬
‫‪562‬‬ ‫دستور ‪ hile‬‬
‫‪W‬‬

‫‪563‬‬ ‫دستور ‪Exec‬‬


‫‪563‬‬ ‫دستور ‪ ryExec‬‬
‫‪T‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪24‬‬

‫‪564‬‬ ‫دستورات ‪ ExecIf‬و ‪ExecIfTime‬‬


‫دستورات مربوط به فراخوانی ماکروها در استریسک���������������������������������������������������������������������������������‪564‬‬
‫‪564‬‬ ‫دستور ‪Macro‬‬
‫‪564‬‬ ‫دستور ‪ acroExclusive‬‬
‫‪M‬‬

‫‪564‬‬ ‫دستور ‪ acroIf‬‬


‫‪M‬‬

‫دستورات مربوط به ‪ CDR‬در استریسک���������������������������������������������������������������������������������������������������‪565‬‬


‫‪565‬‬ ‫دستور ‪ orkCDR‬‬
‫‪F‬‬

‫‪565‬‬ ‫دستور ‪ResetCDR‬‬


‫‪565‬‬ ‫دستور ‪ oCDR‬‬
‫‪N‬‬

‫دستورات مربوط به اجرای فایل‌های صوتی و موزیک انتظار در استریسک�����������������������������������������������‪565‬‬


‫‪565‬‬ ‫دستور ‪S ayAlpha‬‬

‫‪565‬‬ ‫دستور ‪SayDigits‬‬


‫‪565‬‬ ‫دستور ‪S ayNumber‬‬

‫‪566‬‬ ‫دستور ‪S ayPhonetic‬‬

‫‪566‬‬ ‫دستور ‪MusicOnHold‬‬


‫دستورات مربوط به ‪ DTMF‬و خواندن اطالعات���������������������������������������������������������������������������������������‪566‬‬
‫‪566‬‬ ‫دستور ‪Read‬‬
‫‪567‬‬ ‫دستور ‪SendDTMF‬‬
‫دستورات مربوط به مانیتورینگ و ضبط کردن ������������������������������������������������������������������������������������������‪567‬‬
‫‪567‬‬ ‫دستور ‪ChanSpy‬‬
‫‪568‬‬ ‫دستور ‪ xtenSpy‬‬
‫‪E‬‬

‫‪568‬‬ ‫دستور ‪ ixMonitor‬‬


‫‪M‬‬

‫‪569‬‬ ‫دستور ‪ ecord‬‬


‫‪R‬‬

‫سایر دستورات کاربردی در استریسک������������������������������������������������������������������������������������������������������‪569‬‬


‫‪569‬‬ ‫دستور ‪Authenticate‬‬
‫‪570‬‬ ‫دستور ‪VMAuthenticate‬‬
‫‪570‬‬ ‫دستور ‪System‬‬
‫‪25‬‬ ‫فهرست‬

‫معرفی توابع مهم و پرکاربرد در استریسک������������������������������������������������������������������������������������������������‪571‬‬


‫‪571‬‬ ‫تابع ‪ RRAY‬‬
‫‪A‬‬

‫‪571‬‬ ‫تابع ‪ BASE64_ENCODE‬و ‪ ASE64_DECODE‬‬


‫‪B‬‬

‫‪571‬‬ ‫تابع ‪ ALLERID‬‬


‫‪C‬‬

‫‪571‬‬ ‫تابع ‪ DR‬‬


‫‪C‬‬

‫‪572‬‬ ‫تابع ‪CURL‬‬


‫‪572‬‬ ‫تابع ‪ UT‬‬
‫‪C‬‬

‫‪572‬‬ ‫تابع ‪ NV‬‬


‫‪E‬‬

‫‪573‬‬ ‫تابع ‪ XIST‬‬


‫‪E‬‬

‫‪573‬‬ ‫تابع ‪ GROUP‬و ‪ ROUP_COUNT‬‬


‫‪G‬‬

‫‪573‬‬ ‫تابع ‪I F‬‬

‫‪573‬‬ ‫تابع ‪I SNULL‬‬

‫‪574‬‬ ‫تابع ‪I FTIME‬‬

‫‪574‬‬ ‫تابع ‪ EN‬‬


‫‪L‬‬

‫‪574‬‬ ‫تابع ‪RAND‬‬


‫‪574‬‬ ‫تابع ‪SIP_HEADER‬‬
‫‪575‬‬ ‫تابع ‪ EGEX‬‬
‫‪R‬‬

‫نتیجه‌گیری������������������������������������������������������������������������������������������������������������������������������������������������‪575‬‬
‫پیشگفتار‬

‫امروزه فناوریهای مخابراتی و کامپیوتری بهسرعت در حال تغییر و دگرگونیاند و باعث ایجاد یک تحول‬
‫عظیم در جوامع بشری شدهاند‪ .‬از طرف دیگر تجمیع شبکهها با هم و ایجاد شبکههای نسل جدید باعث شده‬
‫رؤیای تبدیل شدن جهان به دهکدهی کوچک جهانی‪ ،‬بیش از پیش به واقعیت نزدیکتر شود‪.‬‬
‫ســافت سوئیچ استریسک یکی از محبوبترین سافت ســوئیچهای تلفنی است که بهوسیله آقای مارک‬
‫اسپنسر در سال ‪ ۱۹۹۹‬نوشته شده است‪ .‬درحالحاضر شرکت دیجیوم‪ ،‬مالکیت این سافت سوئیچ را بر عهده‬
‫دارد‪ .‬این شــرکت برای عالقهمندان این حوزه‪ ،‬دورههای آموزشــی برگزار میکند و در انتهای هر دوره با‬
‫برگــزاری آزمونهای بینالمللی مدارک معتبری به دانشــجویان اعطا میکند‪ .‬کتاب جامع ‪Asterisk_ The‬‬
‫‪ 4th Edition ,Definitive Guide‬آقــای ‪ Leif Madsen‬یکــی از محبوبترین کتابهای آموزشــی برای‬
‫عالقمندان در حوزه ویپ است‪.‬‬
‫کتابی که در پیش رو دارید اولین کتاب در زمینه ســافت ســوئیچ استریسک به زبان فارسی است‪ .‬اکثر‬
‫منابع آموزشــی در این حوزه به زبان التیناند که به گســتردگی در اینترنت یافت میشــوند‪ .‬در این کتاب‬
‫ســعی شده اســت مطالب با موافقت آقای ‪ Leif Madsen‬و بر اساس ســر فصل کتاب ایشان نگارش شود تا‬
‫پیوســتگی مطالب حفظ گردد‪ .‬البته چون از زمان تألیف و چاپ اولین نســخه کتاب ایشان‪ ،‬نزدیک به یک‬
‫دهه میگذرد‪ ،‬ما ســعی کردهایم مطالب و مفاهیم جدید حوزه ســافت سوئیچ استریسک را نیز در سرفصل‬
‫کتاب قرار دهیم‪.‬‬
‫انگیزهی اصلی نگارش این کتاب این اســت که عالقمندان به حوزه مخابرات و شبکههای ویپ بتوانند‬
‫بهراحتی با مفاهیم آن آشنا شوند و آن را بهصورت کاربردی مطالعه نمایند‪ .‬لذا عنوان کتاب »مرجع آموزش‬
‫ویپ با سافت سوئیچ استریسک« انتخاب شده است‪ .‬این کتاب در ‪ ۲۰‬فصل نگارش شده است که در ادامه‬
‫هدف هر فصل شرح داده شده است‪.‬‬
‫‪27‬‬ ‫پیشگفتار‬

‫در فصلهای نخست کتاب )چهار فصل اول( سعی شده بیشتر راجع به نصب و راهاندازی سافت سوئیچ‬
‫استریسک و پیکربندی آن صحبت شود و در هر بخش مفاهیم با جزئیات کامل شرح داده شود‪.‬‬
‫در فصلهای پنجم و هشــتم کتاب به مباحث برنامهنویســی در استریســک وارد شدهایم و در هر فصل‬
‫بخشــی از آن را توضیح میدهیم‪ .‬عالقمندانی که تمایل دارند با ســاختار برنامهنویسی استریسک آشنا شوند‬
‫میتوانند به این فصلها مراجعه نمایند‪.‬‬
‫در فصل ششــم و هفتم چالشهای ارتباط سافت ســوئیچ استریسک با سایر شبکههای مخابراتی و ویپ‬
‫مطرح شــده است‪ .‬همچنین در این فصل انواع روشهای ارتباطی شبکههای ویپ بهصورت مفصل همراه با‬
‫مثالهای متعدد توضیح داده شده است‪.‬‬
‫در فصل نهم ساختار و معماری طراحی سیستمهای کال سنتر معرفی شده است و با معماری صفها در‬
‫استریســک آشــنا میشوید‪ .‬مفاهیم با شــرح مثالها به گونهای توضیح داده میشوند که خواننده کتاب باید‬
‫بتواند بعد از مطالعه این فصل‪ ،‬یک کال سنتر با قابلیتهای محدود طراحی نماید‪.‬‬
‫در فصل دهم ادامه مبحث در خصوص وضعیت کاربران در شــبکههای ویپ مطرح میشــود که جزء‬
‫موضوعات حســاس و کلیدی اســت‪ .‬ترکیب این فصل با فصل نهم میتواند منجر به ایجاد برنامهای شود که‬
‫بتواند درستی وضعیت اپراتورها در کال سنتر را نشان دهد‪.‬‬
‫در فصل یازدهم کتاب ســاختار اتصال ســافت سوئیچ استریسک با انواع پایگاههای دادهای بررسی شده‬
‫است و با قابلیت مهم در استریسک )‪ (ARA‬نیز آشنا خواهید شد‪.‬‬
‫در فصل دوازدهم کتاب چالشهای استفاده از فکس در شبکههای ویپ را بررسی میکنیم‪ .‬سپس یک‬
‫فکس ســرور در کنار ســافت سوئیچ استریســک راه اندازی میکنیم بطوری که بتوانیم از طریق استریسک‬
‫فکس هایی را ارسال و دریافت کنیم‪.‬‬
‫در فصلهای ســیزدهم و چهاردهم دو ابزار مهم در مدیریت و برنامهنویســی سافت سوئیچ استریسک را‬
‫معرفی میکنیم‪ .‬توســط این دو ابزار برنامه نویسان میتوانند برنامههای خود را با سایر زبانهای برنامهنویسی‬
‫توسعه دهند‪ .‬در این فصل ها سعی شده است تا با ارائه مثالهای متعدد‪ ،‬مفاهیم را به صورت ساده به خواننده‬
‫منتقل کنیم‪.‬‬
‫در فصل پانزدهم یکی از تکنولوژیهای جدید در ســافت ســوئیچ استریســک را معرفی میکنیم‪ .‬ابزار‬
‫‪ RESTful‬این قابلیت را به برنامه نویســان میدهد تا بتواننــد از طریق تکنیکهای ‪ Websocket‬و ‪ REST‬با‬
‫استریسک در ارتباط باشند‪.‬‬
‫در فصل شــانزدهم کتاب در خصوص ماژول ‪ pjsip‬توضیح داده ایم‪ .‬این ماژول در نســخههای جدیدتر‬
‫استریسک قابل استفاده میباشد‪ .‬همچنین مزایای استفاده از این ماژول را در این فصل شرح خواهیم داد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪28‬‬

‫در فصل هفدهم در خصوص مانیتور کردن و بررســی الگ فایل ها در ســافت سوئیچ استریسک شرح‬
‫خواهیم داد‪.‬‬
‫در فصل هجدهم مباحث امنیتی در استریسک مطرح میشوند‪ .‬همچنین استفاده از ارتباطات رمزنگاری‬
‫شده ‪ TLS‬و ‪ SRTP‬در این فصل مطرح میشوند‪.‬‬
‫یکی از چالشهای مهم در شــبکههای ویپ‪ ،‬ارزیابی عملکرد ســوئیچهای تلفنی و تجهیزات وابسته به‬
‫آن میباشد‪ .‬شاید این سوال بسیاری از مخاطبان باشد که چگونه یک سافت سوئیچ استریسک را برای تعداد‬
‫تماس همزمان تســت و ازریابی کنیم و یا برای یک ســناریو چه منابع ســخت افزاری مورد نیاز میباشد‪ .‬در‬
‫فصــل نوزدهم به صورت مفصل و کامل این موارد را با هم بررســی خواهیم کرد و انواع روشهای تســت‬
‫کارایی و تست تطابق را انجام خواهیم داد‪.‬‬
‫در استریسک دستورات و توابع زیادی وجود دارد که در فصل آخر سعی کرده ایم مهمترین و پرکاربرد‬
‫ترین دستورات و توابع را توضیح دهیم‪.‬‬
‫در ابتــدا از آقــای ‪ Leif Madsen‬که کتــاب اینجانب را مورد لطف خود قرار دادند صمیمانه تشــکر و‬
‫سپاسگزاری می کنم‪ .‬نگارش مطالب این کتاب بدون همکاری آقایان مهندس مجتبی نجفی مقدم و مهندس‬
‫مرتضــی ایروانی میســر نمی گردیــد‪ .‬از زحمات آقای مهندس حامد رســتگار کــه در ویرایش فنی کتاب‬
‫اینجانب را همراهی کردند صمیمانه تشکر می کنم‪ .‬همچنین از آقایان جلیل یزدانی و علیرضا رستمی که در‬
‫ویرایش اولیه کتاب اینجانب را همراهی کردند‪ ،‬سپاسگزاری می کنم‪.‬‬
‫از همســر عزیز و مهربانم که در نگارش این کتاب به طور مستمر و خستگی ناپذیر اینجانب را تشویق و‬
‫ترغیب نمودند صمیمانه تقدیر و تشکر می نمایم‪.‬‬
‫این کتاب در طی ‪ ۲‬سال با دقت و حساسیت فراوان نگارش شده است‪ .‬هدف اصلی کتاب این است که‬
‫خواننده با مطالعه و انجام مثال های آن با ســافت ســوئیچ استریسک در سطح مقدماتی و پیشرفته آشنا شود‪.‬‬
‫امیدوار هســتم کتابی مفید برای عالقمندان در حوزه تکنولوژی ویپ باشــد‪ .‬به طــور حتم این کتاب خالی‬
‫از اشــکال نخواهد بود‪ ،‬لذا از کلیه اســاتید محترم‪ ،‬دانشــجویان و همکاران عزیز می خواهم چنانچه انتقاد و‬
‫پیشــنهادی نســبت به این کتاب دارند‪ ،‬حتما به ما اطالع دهند تا بتوانیم در ویرایش های بعدی کتاب آنها را‬
‫اعمال نماییم‪.‬‬
‫مجتبی اسفندیاری‬
‫زمستان ‪۱۳۹۵‬‬
‫فصل اول‬

‫آشنایی با تلفن و شبکههای‬


‫مخابراتی ‪PSTN‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪30‬‬

‫صدا چیست؟‬
‫صــدا یا صوت نوعی انرژی اســت که از تحرک ذرات ماده بهوجــود میآید؛ به این صورت که یک ذره با‬
‫حرکت و برخورد به ذرههای دیگر‪ ،‬آنها را به حرکت درمیآورد و صدا نشــر پیدا میکند‪ .‬صدا ارتعاشــی‬
‫اســت که بهوسیله حس شــنوایی انسان درک میشــود‪ .‬ما معموالً صداهایی را که در هوا حرکت میکنند‪،‬‬
‫میشــنویم‪ .‬صــدا میتواند در گازها‪ ،‬مایعات و حتــی جامدات نیز حرکت کند‪ .‬ســرعت صدا در جامدات‬
‫به دلیل تراکم زیاد مولکولها‪ ،‬بیشــتر از مایعات و در مایعات نیز بیشــتر از گازهاســت‪ .‬صدا برخالف امواج‬
‫دیگــری همچــون نور و گرما‪ ،‬فقط در محیطی نشــر مییابد که در آن ماده وجود داشــته باشــد‪ .‬این به این‬
‫معنی اســت که اگر بر ســطح کره ماه )که هوایی وجود ندارد( انفجاری روی دهد‪ ،‬هیچوقت صدای آن را‬
‫نمیشــنویم‪ .‬واحد اندازهگیری صدا دسیبل اســت که با نماد ‪ ۱ dB‬نشان میدهند‪ .‬محدودهی شنوایی انسان‬
‫بین ‪ ۲۰‬هرتز تا ‪ ۲۰‬کیلوهرتز است ولی محدودهی توانایی تولید صدا در انسان ‪ ۳۰۰‬هرتز تا ‪ 4‬کیلوهرتز است‪.‬‬

‫تلفن چیست؟‬
‫تلفن یا دورگو‪ 2‬از دســتگاه‌های ارتباط از راه دور اســت که برای انتقال صدا به‌کار می‌رود‪ .‬نخســتین تلفن‬
‫به‌وســیله الکســاندر گراهام بل اختراع شد‪ .‬بعدازظهر روز دوم ژوئن سال ‪ ۱۸۷۵‬میالدی مصادف با ‪ ۱۱‬خرداد‬
‫‪ ۱۲۵۴‬شمســی‪ ،‬الکساندر گراهام بل با همکاری دوســتش واتسن موفق به اختراع تلفن شد و در ژانویه ‪۱۸۷۶‬‬
‫میالدی دســتگاه تلفن بل به‌کار افتاد‪ ۱۰ .‬مارس ‪ ۱۸۷۶‬میالدی (‪ ۱۲۵۵‬شمســی) بل از اتاق خود به‌وســیله این‬
‫‪1- decibel‬‬
‫‪ -2‬برگرفته از واژه فرانسوی (‪)Téléphone‬‬
‫‪31‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫دستگاه به دستیارش در اتاق دیگر گفت‪« :‬آقای واتسن بیایید با شما کار دارم»‪.‬‬
‫تلفن‪ ،‬پس از اختراع کامل به‌وسیله بل به‌سرعت رشد یافت و سیم‌های آن از شهری به شهر دیگر کشیده‬
‫شد‪ .‬چهارده سال بعد از اختراع تلفن یعنی در سال ‪ ۱۸۹۰‬میالدی آلمون براون استروجر سیستم تلفن خودکار‬
‫را بنا نهاد‪ .‬دو قاره اروپا و آمریکا تحت پوشــش شبکه‌ای درآمدند که روزبه‌روز گسترش می‌یافت‪ .‬همچنین‬
‫در ســال ‪ ۱۸۹۱‬ارتباط تلفنی بین شــهرهای لیون و تهران برقرار شــد‪ .‬روزی که گراهام بل درگذشت (سال‬
‫‪ ،)۱۹۲۲‬به احترام او ارتباط تلفنی در شبکه وسیعی از هفده میلیون تلفن به مدت یک دقیقه قطع شد‪.‬‬

‫شکل ‪1-1‬‬

‫شبکه های مخابراتی ‪ PSTN‬چیست؟‬


‫شــبکه‌های مخابراتی ‪ PSTN‬یک شبکه‌ی ســوئیچینگ مداری است که وظیفه ارتباط‌دهی تماس‌های تلفنی‬
‫و انتقــال پیام‌هــای صوتی را بر‌عهده دارد‪ .‬واقعیت این اســت که ‪ PSTN‬از گذشــته‌های دور و از همان ابتدا‬
‫به‌صورت ســاده وجود داشته است و امروزه باگذشت زمان و ظهور فناوری‌های جدید‪ ،‬به شکل کنونی خود‬
‫رســیده اســت تا ما در هر منطقه‌ی مخابراتی شاهد یک شبکه ‪ PSTN‬مجهز باشــیم‪ .‬شکل (‪ )1-1‬روند رشد‬
‫شبکه‌های ‪ PSTN‬را نشان می‌دهد‪.‬‬

‫تاریخچه شبکه‌های مخابراتی ‪PSTN‬‬

‫در ابتدا هدف از ایجاد شبکههای ‪ ،PSTN‬برقراری ارتباط بین دو دستگاه تلفن بوده است‪ .‬این ارتباط مداری‬
‫از ســمت تماسگیرنده شروعشــده و تا مقصد ادامه پیدا میکند‪ .‬در حقیقت یک زوج ســیم از تلفن مبدأ‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪32‬‬

‫تا مرکز مخابرات و یک زوج ســیم از تلفن مقصد تا مرکز مخابرات وجود داشــت که توســط یک المپ‪،‬‬
‫وضعیت گوشــی مشخص میشــد‪ .‬بهعبارتیدیگر‪ ،‬همه مشترکین بر روی تابلوی سوئیچ ‪ ،PSTN‬یک المپ‬
‫ِ‬
‫المپ وضعیت مشترک‪ ،‬با او‬ ‫وضعیت‪ ۱‬داشــتند‪ .‬کارمندان شبکههای مخابراتی ‪ ،PSTN‬پس از روشن شدن‬
‫صحبت کرده و مقصد را از وی میپرسیدند‪ .‬پس از مشخص شدن مقصد‪ ،‬بهوسیله یک کابل‪ ،‬ارتباط مورد‬
‫نیاز بین دو مشترک برقرار میشد‪ .۲‬شکل ‪ ۲-۱‬یک تابلوی سوئیچ ‪ PSTN‬را نشان میدهد‪.‬‬

‫شکل ‪2-1‬‬

‫باگذشــت زمان و افزایش مشترکین‪ ،‬این نوع شــبکهها دیگر پاسخگوی نیازهای مردم نبود‪ .‬همین امر‬
‫باعث ایجاد تغییراتی در سیگنالینگ شبکههای مخابراتی ‪ PSTN‬شد‪.‬‬
‫با اعمال تغییرات در ســیگنالینگ شــبکههای ‪ ،PSTN‬تلفنها به یک شمارهگیر گردان مجهز شدند‪ .‬این‬
‫شــمارهگیرها بهصورت ‪ PULL‬و با صداهای بیپ مانند‪ ،‬شــماره مقصد را به شبکه ‪ PSTN‬اعالم میکردند‪.‬‬
‫ســپس دفتر ‪ PSTN‬بهصورت خودکار‪ ،‬ارتباط مبدأ را با مقصد درخواســتی برقــرار میکرد‪ .‬بعدها با توجه‬
‫به اینکه شــمارهگیری با این نوع تلفنها زمانبر بود و برای شــمارههایی که تعداد زیادی ‪ ۹ ،8‬و یا صفر در‬
‫خود داشــتند‪ ،‬زمان زیادی صرف میشد‪ ،‬شــمارهگیر گردان را با یک صفحهکلید عوض کردند تا در زمان‬
‫صرفهجویی شــود‪ .‬ایــن صفحهکلیدها هماکنون روی تلفنهای کنونی دیده میشــوند و صدایی با فرکانس‬
‫متفاوت برای هر شماره ایجاد میکنند‪ .‬فرکانس ایجادشده بهوسیله هر کلید‪ ،‬استاندارد است و شبکه ‪،PSTN‬‬
‫با دریافت فرکانسها و آنالیز آنها‪ ،‬مقصد را مشــخص میکند‪ .‬حاصلضرب فرکانســی ایجادشده بهوسیله‬
‫صفحهکلید را اصطالحاً ‪ DTMF‬میگویند‪.‬‬

‫‪1- Lamp State‬‬


‫‪ -2‬به این عملیات در اصطالح ‪ bridge‬شدن دو کانال می‌گویند‪.‬‬
‫‪33‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫‪1‬‬
‫‪DTMF‬‬
‫همانطور که در شــکل ‪ ۳-۱‬مشاهده میشــود‪ ،‬بهازای هر کلید‪ ،‬دو فرکانس سطر و ستون )‪ f۱‬و ‪ (f۲‬در نظر‬
‫گرفته میشود‪ .‬در این حالت با فشردن هر کلید‪ ،‬فرکانسهای ‪ f۱‬و ‪ f۲‬در هم ضرب و حاصل آن بهصورت‬
‫تقســیم زمانی ارسال میشــود؛ یعنی بهازای ارسال هر شماره‪ ،‬یک مکث کوتاه درنظر گرفته و دوباره ارسال‬
‫انجام میشود‪ .‬شکل ‪ ۳-۱‬حاصلضرب فرکانسی را در واحد زمان نشان میدهد‪.‬‬
‫همانطور که در شکل ‪ ۳-۱‬مشاهده میشود هر عدد روی صفحه کلید‪ ،‬متناظر با دو فرکانس است که با‬
‫فشــردن هر کلید‪ ،‬این اعداد در هم ضرب میشــوند و یک فرکانس جدید را ایجاد مینمایند که واژه ‪Dual‬‬
‫‪ Tone Multi Frequency‬از این روش گرفته شده است‪.‬‬

‫شکل ‪3-1‬‬

‫خروجی ضرب شکلِ ‪ ،۳-۱‬شکل ‪ 4-۱‬است که در آن هر فرکانس در یک واحد زمانی ارسال و پس از‬
‫یک فاصله زمانی فرکانس بعدی ارسال میشود‪.‬‬

‫شکل ‪4-1‬‬

‫‪1- Dual Tone Multi Frequency‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪34‬‬

‫سوئیچینگ مداری‪ 1‬چیست؟‬


‫ســوئیچینگ مداری ابتدا‪ ،‬در ارتباطات تلفنی اســتفاده میشد؛ به این صورت که با تغییر کانالهای مختلف‪،‬‬
‫مردم میتوانستند باهم ارتباط برقرار کنند‪ .‬در سوئیچینگ مداری‪ ،‬قبل از انتقال دادههای واقعی )صدا(‪ ،‬مسیر‬
‫از قبل انتخاب و پهنای باند موردنیاز بهوسیله شبکه‪ ،‬تخصیص داده میشود‪.‬‬
‫ازآنجاکه در این نوع شــبکهها‪ ،‬قبل از انتقال دادهها‪ ،‬مســیر از قبل ایجادشده است‪ ،‬تمام دادهها از مسیر‬
‫مشخصشــده منتقل میشــوند‪ .‬این مسیر رزرو شده تا پایان مکالمه برقرار خواهد ماند‪ .‬از طرف دیگر‪ ،‬چون‬
‫تخصیص منابع در ابتدای برقراری ارتباط‪ ،‬در شــبکه انجام میشــود‪ ،‬باعث میشــود منابع شــبکه بهدرستی‬
‫مصرف نشود و کارایی شبکه افت نماید‪.‬‬

‫شکل ‪5-1‬‬

‫سوئیچینگ بسته‌ای‪ 2‬چیست؟‬


‫پیام ها در شــبکههای ســوئیچینگ بستهای‪ ،‬به بســتههای کوچکتر تقســیم و بهصورت تکتک به مقصد‬
‫فرستاده میشوند‪ .‬برای هدایت بستهها از پروتکلهای مسیریابی در الیه سوم شبکه استفاده میشود‪ .‬هر بسته‬
‫مســیر خود را با توجه به آدرس مبدأ و مقصد پیدا میکند‪ .‬از آنجاکه در شــبکههای ســوئیچینگ بســتهای‪،‬‬
‫مســیری از قبل وجود ندارد و هر بســته بهصورت جداگانه مسیریابی میشــود‪ ،‬هر بسته ممکن است از میسر‬
‫مســتقلی به مقصد برســد‪ .‬به همین دلیل تمامی بســتهها باید عالمتگذاری شــوند تا در مقصد دوباره باهم‬
‫ترکیب شوند و پیام اصلی را تشکیل دهند‪.‬‬
‫ازآنجاکه پروتکل ‪ IP‬یک پروتکل حداکثرتالش‪ ۳‬است‪ ،‬در این نوع شبکهها هیچ تضمینی در خصوص‬
‫کیفیت سرویس‪ 4‬ارائهشده وجود ندارد‪ .‬بهعبارتدیگر‪ ،‬پروتکل ‪ IP‬حداکثر تالش خود را برای انتقال دادهها‬
‫انجام میدهد ولی هیچ تضمینی برای انجام آن وجود ندارد‪.‬‬

‫‪1- Circuit Switching‬‬


‫‪2- Packet Switching‬‬
‫‪3- Best Effort‬‬
‫‪4- Quality of Service‬‬
‫‪35‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫در این نوع شــبکه‪ ،‬افزونگی‪ 1‬دادهها داریم؛ چون هر بسته بطور مستقل مسیریابی میشود‪ ،‬لذا باید درون‬
‫هر بســته آدرس مبدأ و مقصد وجود داشــته باشد‪ .‬این امر باعث افزایش مصرف منابع در این شبکه میشود‪.‬‬
‫البته راههایی به منظور کاهش مصرف پهنای باند در این شبکهها وجود دارد که در حوصله این کتاب نیست‪.‬‬

‫شکل ‪6-1‬‬

‫انواع خطوط مخابراتی‬


‫خطوط مخابراتی به دو دسته کلی تقسیم میشوند‪:‬‬
‫‪2‬‬
‫‪ (۱‬خطوط آنالوگ‬
‫‪3‬‬
‫‪ (۲‬خطوط دیجیتال‬

‫خطوط آنالوگ‬
‫منظور از خط آنالوگ‪ ،‬همان خط تلفن معمولی است‪ .‬این خط بعد از برداشتن گوشی و شنیدن بوق آزاد‪،4‬‬
‫‪ ۶4‬کیلوبیت پهنای باند را از مرکز مخابراتی رزرو میکند‪ .‬ازجمله دالیل استفاده از خطوط آنالوگ میتوان‬
‫به موارد زیر اشاره کرد‪:‬‬
‫‪ -۱‬نبود خطوط دیجیتال در یک منطقه؛‬
‫‪ -۲‬هزینه اندک؛‬
‫‪ -۳‬نگهداری خطوط قبلی‪.‬‬

‫خطوط دیجیتال (‪)5 ISDN‬‬


‫ایــده طراحی خطوط دیجیتال به اواســط دهه ‪ 8۰‬میــالدی باز میگردد و هدفش جایگزینی سیســتم تلفنی‬

‫‪1- Data Redundancy‬‬


‫‪2- Analog Telephony‬‬
‫‪3- Digital Telephony‬‬
‫‪4- off hook‬‬
‫‪5- Integrated Services Digital Network‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪36‬‬

‫آنالوگ با سیســتم دیجیتال بودهاســت تا بتواند دادههای دیجیتال )صوت( را بهخوبی پشــتیبانی کند‪ .‬در این‬
‫توپولوژی‪ ،‬صدا نخســت به دادههای دیجیتال تبدیل میشــود و سپس انتقال مییابد‪ .‬ازجمله مزایای خطوط‬
‫دیجیتال میتوان به موارد زیر اشاره کرد‪:‬‬
‫‪ (۱‬بیتأثیربودن افت ولتاژ برای فاصلههای دور؛‬
‫‪ (۲‬کاهش تأثیر نویز؛‬
‫‪ (۳‬توانایی انتقال بیشتر از یک کانال روی بستر ثابت؛‬
‫‪ (4‬سرعت باالی برقراری تماس‪.‬‬

‫اجزای تشکیل‌دهنده تلفن معمولی‬


‫یک تلفن معمولی از اجزای مختلفی تشکیلشده است که هر بخش وظایف مشخصی دارد )شکل ‪.(7-۱‬‬
‫‪ : Ringer‬قبل از کلید قرار دارد و با ولتاژ متناوب ‪ ۹۰‬ولت تحریک میشود و صدای زنگ تولید میکند‪.‬‬
‫‪ : Hook Switch‬بعد از زنگ خوردن‪ ،‬درصورت برداشــتن گوشی‪ ،‬این کلید باز میشود و مسیر تغذیه بقیه‬
‫گوشی را با ولتاژ مستقیم ‪ 4۰‬ولت فراهم میکند‪.‬‬
‫‪ : DTMF‬کار تولید سیگنالینگ یا شمارهگیری را به عهده دارد‪.‬‬
‫‪ : Handset‬حاوی میکروفن و بلندگوست و کار دریافت و ارسال صدا را به عهده دارد‪.‬‬

‫شکل ‪7-1‬‬
‫‪37‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫اجزای تشکیل دهنده شبکه تلفنی ‪PSTN‬‬


‫)‪Central Office (CO Switch‬‬
‫مرکز مخابرات یا ‪ CO‬که از آن بهعنوان دفتر مخابراتی در شبکه ‪ PSTN‬یاد میشود‪ ،‬وظایف زیر را برعهده‬
‫دارد‪:‬‬
‫‪ -۱‬تهیه یک جریان الکتریکی ‪ 48‬ولتی مســتقیم برای تغذیه گوشــیها هنگام پاسخگویی و یک جریان ‪۹۰‬‬
‫ولتی متناوب برای تحریک زنگ گوشیها؛‬
‫‪ -۲‬تولید سیگنالینگ اشغالی‪ ،‬برگشت بوق‪ ،‬خطا و ‪...‬؛‬
‫‪ -۳‬بررسی وضعیت گوشی )‪(off hook, on hook‬؛‬
‫‪ -4‬ارسال اطالعات موردنیاز مانند ‪. Caller ID‬‬

‫)‪Station (Analog Phone‬‬


‫دســتگاههایی که بهواسطه آن مشتریان به ‪ CO‬متصل میشوند را ‪ Station‬گویند‪ .‬این دستگاهها وظایف زیر‬
‫را برعهده دارند‪:‬‬
‫‪ .۱‬توانایی شمارهگیری و تولید ‪DTMF‬؛‬
‫‪ .۲‬توانایی تغییر وضعیت گوشی )‪(off hook, on hook‬؛‬
‫‪ .۳‬توانایی زنگ خوردن‪.‬‬

‫‪Local Loop‬‬
‫ارتباط بین تجهیزات مشــتریان )‪ (Analog Phone‬با مرکزمخابرات )‪ (CO‬از طریق این لینک برقرار میشود‪.‬‬
‫در اینجا منظور همان زوج سیم است که از سوی مخابرات به مشتریان درب منزل تحویل داده میشود‪.‬‬

‫‪Trunk‬‬
‫ارتباط بین مراکز مخابرات )‪ (CO‬ازطریق این لینک برقرار میشــود‪ .‬در این حالت ارتباطات از میان خطوط‬
‫‪ E1‬خواهد بود‪.‬‬

‫‪Private Switch‬‬
‫ایــن قابلیت وجــود دارد که ارتباط با برخی از مراکز تجاری و صنعتی از طریق ‪ Trunk‬برقرار گردد‪ .‬در این‬
‫حالت این نوع ارتباط همانند ارتباط بین مراکز مخابرات )‪ (CO‬است‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪38‬‬

‫شکل ‪8-1‬‬

‫مرکز تلفن‪ 1‬چیست؟‬


‫مرکز تلفن یا ‪ PBX‬که در اصطالح عامیانه به آن ســانترال میگویند‪ ،‬نقشــی اساسی در ارتباطات مخابراتی‬
‫ایفا میکند‪ PBX .‬در حقیقت یک سیســتم تلفن مرکزی یا یک مرکز تلفن داخلی اســت‪ .‬این سیستم به این‬
‫صــورت عمل میکند که با ورود چند خط تلفن معمولی‪ ،‬خطوط تلفن داخلی بیشــتری را بر اســاس نیاز و‬
‫برحسب ظرفیت روی زوج سیمهای معمولی برای متقاضیان فراهم میکند‪ .‬پس با این تعریف میتوان گفت‬
‫که مهمترین نقش این سیستم تلفنی‪ ،‬فراهم آوردن خطوط تلفن داخلی به تعداد موردنیاز برای کاربران است‪.‬‬

‫سالن دستگاه مخابراتی چیست؟‬


‫سالن دستگاه مخابرات یا سوئیچ مخابرات شامل دو بخش سخت‌افزاری و نرم‌افزاری است‪.‬‬
‫‪ -1‬بخش دسترســی (‪ :)Access‬دربرگیرنده تمامی تجهیزات مربوط به اتصال مشترکین به سوئیچ (تجهیزات‬
‫سمت مشترک) و همچنین واسطه‌های الزم‪ ،‬برای اتصال سوئیچ به سیستم‌های انتقال‪ ،‬به‌منظور ارتباط با سایر‬
‫سوئیچ‌های موجود در شبکه است‪.‬‬
‫بخش ‪ Access‬در ســالن دستگاه‪ ،‬در فایل‌هایی که یونیت نامیده می‌شود‪ ،‬قرار دارد‪ .‬هر یونیت معموالٌ دارای‬
‫‪ ۱۰‬ردیف اســت‪ .‬به هر ردیف یک شلف می‌گویند‪ .‬هر شــلف شامل ‪ ۱۶‬مدار الکترونیکی یا کارت است و‬
‫هر کارت هم شــامل ‪ ۱۶‬مدار ‪ LC‬اســت که روی یک برد ساخته می‌شوند‪ .‬به این کارت‌ها‪ ،‬کارت مشترک‬
‫می‌گویند‪ .‬در هر شــلف یا ردیف‪ ،‬دو کارت تغذیه برای اعمال ولتاژ و جریان راه‌انداز وجود دارد که عموما‬
‫در انتهای هر شــلف‪ ،‬در دو طرف نصب می‌گردد‪ .‬برای هر دو شــلف‪ ،‬دو کارت مخصوص وجود دارد که‬

‫‪1- Public Switch Exchange‬‬


‫‪39‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫در یکی از شلف‌ها قرار داده می‌شود‪ .‬این کارت‌ها به‌عنوان منبع اولیه ذخیره اطالعاتند که برخی از پیغام‌های‬
‫اولیه و اخطارها را اعالم می‌کنند‪.‬‬
‫‪ -2‬بخش ســوئیچ (‪ :)Switch‬این بخش مسؤولیت مسیریابی‪ ،‬مســیردهی (سوئیچینگ) و برقراری ارتباط بین‬
‫کانال‌های مختلف تلفن را ازطریق مسیرهایی که از بخش ‪ Access‬به آن متصل می‌شود‪ ،‬امکان‌پذیر می‌سازد‪.‬‬
‫‪ -3‬بخش کنترلی (‪ :)Control‬این بخش به‌عنوان مرکز اصلی یک ســوییچ تلفنی اســت که همه بخش‌های‬
‫مرکزی را کنترل و مدیریت می‌کند‪.‬‬
‫‪ -4‬بخــش عملیات و نگهداری ‪ :)operation and maintenance) O&M‬این بخش امکان ارتباط اپراتور با‬
‫سیســتم سوئیچ را امکان‌پذیر می‌کند تا کاربر بتواند با انجام تعاریف نرم‌افزاری‪ ،‬وضعیت سوئیچ را بررسی و‬
‫اطالعات الزم را استخراج کند‪.‬‬

‫شبکه مخابراتی کشور‬


‫شــبکه مخابراتی تلفن ثابت کشور‪ ،‬از نقطه‌نظر دسترسی (دستیابی) به سه سطح شهری‪ ،‬بین‌شهری و بین‌الملل‬
‫تقسیم می‌شود‪.‬‬

‫سطح شهری‬
‫شــبکه مخابرات شهری شبکه‌ای است که امکان برقراری ارتباط بین مشترکین یک شهر با یکدیگر را فراهم‬
‫می‌کند‪ .‬این شبکه شامل تجهیزات زیر است‪:‬‬

‫‪ -1‬مراکز محلی یا ‪LX‬‬


‫‪ -2‬مراکز ترانزیت ‪TX‬‬
‫‪ -3‬مراکز محلی ‪ +‬ترانزیت ‪LTX‬‬

‫مراکز محلی‪ :‬مراکزی هســتند که از یک‌ طرف به شــبکه ‪ PSTN‬و از طرف دیگر از طریق زوج ســیم‌ها‪ ،‬به‬
‫مشترکین وصل می‌شوند‪.‬‬

‫مراکــز ترانزیــت‪ :‬مراکزی هســتند که فقــط وظیفــه ترانزیت کــردن ترافیــک در مراکز هر ناحیــه را به‬
‫ســایر نواحــی برعهــده دارنــد‪ .‬ایــن مراکــز معمــوالً در شــهرهای پرجمعیــت و پرتراکم که شــبکه‪ ،‬بار‏‬
‫سنگینی دارد‪ ،‬مناسب است‪ .‬هر مرکز ترانزیت معموالً چندین مرکز تلفن اطراف خودش را پوشش می‌دهد‪.‬‬

‫مراکز ‪ :LTX‬این مراکز ترکیبی از دو مرکز قبل‌اند؛ یعنی عالوه بر انجام ســرویس‌دهی به مشــترکین‪ ،‬وظیفه‬
‫ترانزیت را هم انجام می‌دهند‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪40‬‬

‫سطح بین‌شهری‬
‫این شــبکه در ســطح دوم ارتباطات مخابراتی قرار دارد و برای ارتباطات بین‌شهری یا بین استانی تعریف‌شده‬
‫است‪ .‬در این سطح‪ ،‬سه نوع مرکز بین‌شهری داریم‪ :‬مراکز ‪ ، SC‬مراکز ‪ PC‬و مراکز ‪. TX‬‬

‫مراکز ‪ :SC‬مراکزی هســتند کــه چندین ‪ PC‬و یا به‌عبارت‌دیگر چندین اســتان را تحت پوشــش خود قرار‬
‫می‌دهند‪ .‬ایران درحال‌حاضر دارای هشــت منطقه مخابراتی است که در هر منطقه دو مرکز ‪ SC‬وجود دارد؛‬
‫پس در سطح کشور ‪ ۱۶‬مرکز ‪ SC‬داریم‪ ،‬جدول ‪ 1-1‬انواع ‪ SC‬ها در سطح کشور را نشان میدهد‪.‬‬
‫‌‬

‫مراکز ‪ :PC‬مراکزی هســتند که ‪ LX‬های یک شــهر یا اســتان را تحت پوشش قرار می‌دهند و خود نیز تحت‬
‫پوشش مراکز ‪ SC‬اند‪ .‬درحال‌حاضر حدودا ً ‪ ۸۴‬مرکز ‪ PC‬در سطح کشور وجود دارد‪.‬‬

‫مراكز ‪ :TX‬مراکز زيرمجموعه ‪ PC‬ها که نقطه انتهايی شبکه محسوب می‌شوند‪.‬‬

‫بابل‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪1‬‬


‫تهران‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪2‬‬
‫اصفهان‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪3‬‬
‫تبریز‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪4‬‬
‫مشهد‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪5‬‬
‫خوزستان‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪6‬‬
‫شیراز‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪7‬‬
‫همدان‬ ‫‪SC1, SC2‬‬ ‫منطقه ‪8‬‬
‫جدول ‪1-1‬‬

‫سطح بین‌الملل‬
‫این مراکز هم همان‌گونه که از نامشان پیداست‪ ،‬دروازه ارتباطات بین‌الملل ایران با دنیا هستند‪ .‬درحال‌حاضر‬
‫دو مرکز ‪ ISC1‬و ‪ ISC2‬در سطح کشور فعال‌اند و ارائه خدمات می‌دهند‪ .‬جدول ‪ 2-1‬کدهای مربوط به ‪ISC‬‬
‫های دنیا را نشان می‌دهد‪.‬‬

‫ارتباط ‪ ISC‬های ایران با کریرهای بین الملل‬


‫از لحاظ تجاری‪ ،‬ایجاد تماس از داخل به خارج کشــور را ‪ Origination‬و دریافت تماس از خارج به داخل‬
‫کشور را ‪ Termination‬می‌گویند‪ .‬در فصل‌های آینده بیشتر راجع به این اصطالحات توضیح خواهیم داد‪.‬‬
‫شــرکت‌هایی که خطوط مخابراتــی واگذار می‌کنند‪ ،‬اپراتورهــای مخابراتی نامیده می‌شــوند‪ .‬به‌عنوان‬
‫‪41‬‬ ‫آشنایی با تلفن و شبکه های مخابراتی ‪PSTN‬‬

‫مثال شــرکت مخابرات ایران چون امکان واگذاری تلفن ثابت روی زوج ســیم را دارد‪ ،‬به‌عنوان تنها اپراتور‬
‫مخابراتی ایران شــناخته می‌شود‪ .‬البته امروزه شرکت‌هایی هســتند که مجوز واگذاری تلفن ثابت روی بستر‬
‫‪ IP‬را در اختیار دارند‪ .‬این شــرکت‌ها امروزه در قالب مجوز ‪ FCP‬فعالیت می‌کنند که مجوز ‪ Origination‬و‬
‫‪Termination‬دارند‪.‬‬
‫از طرف دیگر شــرکت‌هایی که با کریرهای خارجی در ارتباطند و امکان ارتباط با خارج از کشــور را‬
‫فراهم می‌آورند‪ ،‬دارندگان مجوز ‪ Origination/ Termination‬نامیده می‌شــوند‪ .‬این شرکت‌ها از یک‌سو‬
‫با کریر‌های مختلف دنیا ارتباط دارند (این نوع ارتباط از لحاظ تجاری ‪ Interconnection‬نامیده می‌شــوند) ‬
‫و از سوی دیگر با ‪ ISC‬ها مرتبطند به‌طوری‌که تماس‌های بین‌الملل از طریق این شرکت‌ها صورت می‌گیرد‪.‬‬

‫کد تخصیصی‬ ‫نام منطقه‬ ‫ردیف‬


‫کد صفر تعریف نشده‌است‬ ‫تعریف نشده‬ ‫‪0‬‬
‫کد ‪1‬‬ ‫منطقه‌آمریکای شمالی‬ ‫‪1‬‬
‫کد ‪2‬‬ ‫آفریقا‬ ‫‪2‬‬
‫کد ‪3‬‬ ‫اروپا‬ ‫‪3‬‬
‫کد ‪4‬‬ ‫اروپا‬ ‫‪4‬‬
‫کد ‪5‬‬ ‫منطقه آمریکای جنوبی‬ ‫‪5‬‬
‫کد ‪6‬‬ ‫استرالیا‬ ‫‪6‬‬
‫کد ‪7‬‬ ‫روسیه‬ ‫‪7‬‬
‫کد ‪8‬‬ ‫خاور دور‬ ‫‪8‬‬
‫کد ‪9‬‬ ‫آسیا و خاورمیانه‬ ‫‪9‬‬

‫جدول ‪2-1‬‬

‫نتیجه‌گیری‬
‫هدف از این فصل‪ ،‬یک آشــنایی مختصر در مورد شــبکههای مخابراتی ‪ PSTN‬و اجزای تشکیل دهنده آن‬
‫اســت‪ .‬نخست تاریخچه شبکه و بعد اصطالحات عمومی شــبکه مخابراتی معرفی شد و در نهایت به معرفی‬
‫اجزای تشکیل دهنده شبکه تلفنی ‪ PSTN‬پرداخته شد‪ .‬آنچه در این فصل از اهمیت ویژهای برخوردار است‪،‬‬
‫این اســت که یک آشــنایی مختصر و مفید نسبت به شبکه های مخابراتی الزم اســت تا بتوانیم از آنها برای‬
‫ارتباط با شــبکههای مخابراتی نســل جدید استفاده کنیم‪ .‬مسلما توضیح بیشــتر و عمیقتر راجع به شبکههای‬
‫مخابراتی ‪ PSTN‬خارج از حوزه کتاب است؛ لذا در این فصل‪ ،‬بیشتر مطالب و کلیات عمومی مطرح شدهاند‬
‫و مطالعه بیشتر درخصوص این نوع شبکهها به خواننده کتاب واگذار میگردد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪42‬‬
‫فصل دوم‬

‫معماریاستریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪44‬‬

‫مقدمه‬
‫ازنظر ســاختاری و معماری طراحی‪ ،‬تفاوت زیادی بین ســوئیچ مخابراتی قدیم با ســوئیچ تلفنی ویپ وجود‬
‫دارد‪ .‬در ســوئیچ‌های مخابراتی‪ ،‬فناوری‌های مختلفی در هر حوزه ارتباطی وجود دارد که مفاهیم آن‌ها باهم‬
‫متفاوت اســت‪ .‬برای مثال فنــاوری ارتباطی بین مراکز مخابرات‪ 1‬و مراکز خانگــی‪ 2‬از نوع خطوط آنالوگ‬
‫‪3‬‬

‫است‪ .‬همچنین فن ّاوری ارتباط بین مراکز مخابرات با مراکز تجاری و سایر مراکز مخابراتی دیگر کام ً‬
‫ال باهم‬
‫تفاوت دارند‪ .‬در فصل ‪ 1‬در قسمت معرفی اجزای شبکه‌های مخابراتی ‪ ،PSTN‬هر بخش شرح داده شد‪.‬‬
‫ایــن تفاوت در فن ّاوری ارتباط در شــبکه‌های مخابراتی‪ ،‬باعث می‌شــود تجهیزات ســخت‌افزاری برای‬
‫راه‌انــدازی آن‌ها نیز باهم متفاوت باشــند‪ .‬برای مثال مــا نمی‌توانیم ارتباط بین دو مرکــز مخابراتی را از نوع‬
‫خطوط مخابراتی آنالوگ برقرار کنیم‪ ،‬بلکه این ارتباط لزوما باید از نوع ‪ Trunk Link‬باشــد‪ .‬از دیگر ســو‪،‬‬
‫در شبکه‌های نسل جدید ویپ‪ ،‬چنین نگاهی را نسبت به منابع نداریم‪ .‬استفاده از هر فن ّاوری‌ای در شبکه‌های‬
‫ویپ‪ ،‬ساختار ماژولی‪ 4‬دارد و به‌صورت یک کانال ارتباطی‌ای‪ 5‬معرفی می‌شود که به‌وسیله آن می‌توانیم یک‬
‫ارتباط برقرار کنیم‪.‬‬
‫‪1- Central Office Switch‬‬
‫‪2- Analog Telephone‬‬
‫‪3- Local Loop‬‬
‫‪4- Modular‬‬
‫‪5- Channel Driver‬‬
‫‪45‬‬ ‫معماری استریسک‬

‫شکل‪1-2‬‬

‫برای روشن‌تر شدن مطلب‪ ،‬شکل ‪ 1-2‬را در نظر بگیرید‪ .‬همان‌طور که در سمت چپ مالحظه می‌کنید‪،‬‬
‫هر فن ّاوری در شــبکه‌های مخابراتی‪ ،‬مســتقل از ســایر فن ّاوری‌هاســت‪ .‬برای مثال در ستون سمت چپ بخش‬
‫‪ ،Trunks‬فن ّاوری‌های متعددی از قبیل ‪ PRI، BRI‬و ‪ ...‬وجود دارد‪ ،‬درحالی‌که در ستون سمت راست بخش‬
‫‪ ،Stations‬فن ّاوری‌های دیگری دیده می‌شود‪ .‬همچنین در این بخش شما می‌توانید با داشتن یک زوج سیم از‬
‫مرکز مخابراتی‪ ،‬سرویس‌های مختلفی دریافت کنید‪.‬‬
‫در شکل سمت راست‪ ،‬هسته اولیه یک سافت سوئیچ استریسک دیده می‌شود‪ .‬از هر فن ّاوری ارتباطی که‬
‫موردنیاز باشد‪ ،‬می‌توان به‌صورت کام ً‬
‫ال مجزا و ماژوالر استفاده کرد‪ .‬همان‌طور که در شکل مالحظه می‌شود‪،‬‬
‫هسته‌ی اولیه سافت سوئیچ استریسک‪ ،‬سبک و بدون هیچ قابلیتی است‪ .‬تمام قابلیت‌به‌صورت ماژوالر می‌تواند‬
‫به هسته اولیه استریسک‪ 1‬اضافه شود‪.‬‬

‫ساختار ماژوالر در استریسک‬


‫استریســک یک ســاختار ماژوالر‪ 2‬دارد‪ .‬این ساختار باعث می‌شــود قابلیت‌های جدید به‌راحتی به هسته اولیه‬
‫‪4‬‬
‫اضافــه یــا از آن حذف گردد‪ .‬برای اینکه استریســک بتواند از پروتکلهای مختلــف ازجمله ‪3 SIP‬یا ‪IAX‬‬
‫پشــتیبانی کند‪ ،‬لزوما ماژول‌های آن‌ها را باید به هســته اولیه اضافه کنیم‪ .‬برای مثال استریسک از پروتکل ‪SIP‬‬
‫پشــتیبانی می‌کند؛ این موضوع نشــان می‌دهد که ماژول درایور پروتکل ‪ 5 ‌SIP‬با نام ‪ chan_sip.so‬به هســته‬
‫استریسک اضافه‌شده و فعال است‪ .‬اگر همین ماژول را از هسته استریسک حذف یا غیرفعال کنیم‪ ،‬دیگر هیچ‬
‫کاربری از نوع ‪ SIP‬نمی‌تواند روی سرور استریسک رجیستر شود و سرویس دریافت کند‪.‬‬
‫در استریســک ایــن قابلیت وجود دارد که بدون هیچ ماژولی بتــوان آن را راه‌اندازی کرد‪ .‬در این حالت‬

‫‪1- Asterisk Core‬‬


‫‪2- Modular Architecture‬‬
‫‪3- Session Initiation Protocol‬‬
‫‪4- Inter-Asterisk Exchange‬‬
‫‪5- SIP Channel Driver‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪46‬‬

‫هسته اولیه استریسک قابلیت انجام هیچ کاری را ندارد‪.‬‬


‫در استریســک انواع گوناگونی از ماژول‌ها اســتفاده می‌شــود که در ادامه فصل به معرفی و کاربرد هر‬
‫یک از آن‌ها در یک سیســتم تلفنی استریسک می‌پردازیم‪ .‬ماژول‌های استریسک بر اساس نوع قابلیت آن‌ها‬
‫دســته‌بندی می‌شوند و هر یک تنظیمات و پیکربندی خاص خود را دارند‪ .‬دسته‌بندی ماژول‌ها در استریسک‬
‫به‌صورت زیر است‪:‬‬
‫‪ -‬ماژول ‪Application‬‬
‫‪ -‬ماژول ‪Bridge‬‬
‫‪ -‬ماژول ‪CDR‬‬
‫‪ -‬ماژول ‪CEL‬‬
‫‪ -‬ماژول ‪Channel Drivers‬‬
‫‪ -‬ماژول ‪Code Translator‬‬
‫‪ -‬ماژول ‪format interpreter‬‬
‫‪ -‬ماژول ‪Dialplan function‬‬
‫‪ -‬ماژول ‪PBX‬‬
‫‪ -‬ماژول ‪Resource‬‬

‫معرفی ماژول ‪Application‬‬


‫مرکز اصلی کنترل و مدیریت تماس‌ها در استریسک‪ ،‬برنامه نویسی استریسک است‪ .‬با برنامه‌نویسی می‌توان‬
‫‪1‬‬

‫کنتــرل و هدایت همه تماس‌ها را در استریســک به دســت گرفــت‪ .‬به‌طورکلی ســاختار و بدنه اصلی یک‬
‫برنامه‌نویسی به‌صورت زیر است‪:‬‬
‫‪exten => extension, periority, application‬‬

‫دستورات استریسک جزء ساختار و بدنه اصلی برنامه‌نویسی هستند‪ .‬استریسک معموالً دستورات متفاوتی‬
‫‪2‬‬

‫را در بدنه خود دارد که همه آن‌ها به‌صورت ماژوالر به هســته اضافه‌ شــده‌ و قابل‌اســتفاده‌اند‪ .‬به عنوان مثال‪،‬‬
‫برای ایجاد یک تماس جدید از دســتوری به نام ‪ Dial‬اســتفاده می‌کنیم‪ .‬این دســتورات با اضافه شدن ماژول‬
‫‪ app_dial.so‬به هسته استریسک‪ ،‬تعریف و اضافه می‌‌شود‪.‬‬
‫برای آشنایی با انواع دستورات در استریسک‪ ،‬دستور زیر را در کامند الین استریسک وارد نمایید‪:‬‬
‫_‪CLI> module show like app‬‬

‫در جدول ‪ 1-2‬فهرست انواع ماژول‌های دستورات قابل استفاده در استریسک را می‌توانید مالحظه کنید‪.‬‬

‫‪1- Dial Plan‬‬


‫‪2- Application‬‬
47 ‫معماری استریسک‬

Name Purpose Status


app_adsiprog Loads Analog Display Services Interface (ADSI) scripts into Insignificant
compatible analog phones
app_alarmreceiver Supports receipt of reports from alarm equipment Insignificant
app_amd Detects answering machines Unreliable
app_authenticate Compares dual -tone multifrequency (DTMF) input against a Useful
provided string (password)
app_cdr Writes ad hoc record to CDR Useful
app_celgenuserevent Generates user -defined events for CEL New
app_chanisavail Checks the status of a channel Unreliable
app_channelredirect Forces another channel into a different part of the dialplan Useful
app_chanspy Allows a channel to listen to audio on another channel Useful
app_conf_bridge Provides conferencing (new version) Useful as of Asterisk 10,
app_controlplayback Plays back a prompt and offers fast forward and rewind Limited in Asterisk 1.8
functions
app_dahdibarge Allows barging in on a DAHDI channel Useful
app_dahdiras Creates a RAS (Remote Access Server) over a DAHDI Deprecated—see app_
channel (no modem emulation) chanspy Insignificant
app_db Used to add/change/delete records in Asterisk's built-in SQLite Deprecated—see func_db
database
app_dial Used to connect channels together (i.e., make phone calls) Essential
app_dictate Plays back a recording and offers start/stop functions Useful
app_directed_pickup Answers a call for another extension Useful
app_directory Presents the list of names from voicemail.conf Useful
app_disa Provides dialtone and accepts DTMF input Useful
app_dumpchan Dumps channel variables to Asterisk command -line interface Useful
(CLI)
app_echo Loops received audio back to source channel Useful
app_exec Contains Exec( ), TryExec( ), and ExecIf ( ); executes a Useful
dialplan application based on conditions
app_externalivr Controls Asterisk as with an AGI, only asynchronously Useful
app_fax Provides SendFax( ) and ReceiveFax( ) Enables basic text to Useful
speech using Festival TTS engine
app_festival Performs a hook -switch flash on channels (primarily analog) Usable
app_flash Performs find me/follow me functionality based on followme. Useful
conf
app_followme Starts new CDR record on current call Useful
app_forkcdr Gets the ADSI CPE ID Usable
app_getcpeid Sends audio to an lcecast server Insignificant
app_ices Transmits an image to supported devices Usable
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 48

Name Purpose Status


app_image Sample application for developers Limited
app_ivrdemo Works with JACK Audio Connection Kit to share audio Insignificant
between compatible applications
app_jack Triggers dialplan macros Useful
app_macro Provides multiparty conferencing Deprecated
app_neetne Generates 1,004 Hz tone for testing loss on analog circuits Useful—fully featured,
but deprecated in favor of
ConfBridge( ) as of Asterisk
10 since ConfBridge() does
not require DAHDI.
app_milliwatt Provides primitive functions to allow you to build your own Useful
voicennail application in dialplan
app_minivn Records both sides of a call and mixes them together Usable
app_mixmonitor Generates Morse code Useful
app_morsecode Uses mpg123 to play an MP3 Usable
app_mp3 Streams audio from Network Broadcast Stream (NBS) Insignificant
app_nbscat Allows origination of a call Insignificant
app_originate Performs Open Settlement Protocol (OSP) lookup Useful
app_osplookup Creates multiple audio connections to specified devices for Usable
public address (paging)
app_page Enables automated announcing of parked calls Useful
app_ Plays a file to the channel (does not accept input) Usable
parkandannounce
app_playback Plays pairs of tones of specified frequencies Useful
app_playtones Requests input of caller's phone number if no CallerlD is Useful
received
app_privacy Provides Automatic Call Distribution (ACD) Insignificant
app_queue Requests input of digits from callers and assigns input to a Useful
variable
app_read Requests input of digits from callers and passes call to a Useful
designated extension and context
app_readexten Loads contents of a text file into a channel variable Usable
app_readfile Records received audio to a file Deprecated
app_record Plays back time in specified format Useful
app_sayunixtine Transmits DTMF to calling party Useful
app_senddtmf Sends a text string to compatible channels Useful
app_sendtext Sets CallerlD on a channel Insignificant
app_setcallerid Sample application for developers Deprecated
app_skel Sends SMS message in compatible countries Useful
app_sms Requests hangup of channel Limited
49 ‫معماری استریسک‬

Name Purpose Status


app_softhangup Provides utilities relating to speech recognition Useful
app_speech_utils Provides Gosub( ), GoSubIf( ), Return( ), StackPop( ), LOCAL Useful
( ) , and LOCAL_PEEKO
app_stack Executes commands in a Linux shell Essential
app_system Similar to app_background, but allows for any received audio Useful
to interrupt playback
app_talkdetect Client/server testing application Useful
app_test Performs a transfer on the current channel Usable
app_transfer Passes a URI to the called channel Useful
app_url Generates a custom event in the Asterisk Manager Interface Limited
(AMI)
app_userevent Generates a custom event in the Asterisk CLI Useful
app_verbose Provides voicemail Useful
app_voicemail Waits for a RING signaling event (not to be confused with Essential
RINGING); most likely unnecessary, as only chan_dahdi with
analog channels where ringing is received (such as an FXO
port) generates the RING signaling event
app_waitforring Includes WaitForSilence( ) and WaitForNoise( ); listens to the Insignificant
incoming channel for a specified number of milliseconds of
noise/silence
app_waitforsilence Waits until current Linux epoch matches specified epoch Useful
app_waituntil Includes While( ), EndWhile( ), ExitWhile( ), and Useful
ContinueWhile( ); provides while -loop functionality in the
dialplan
app_while Generates SIT (Special Information Tone) to discourage Useful
telemarketers
app_zapateller Usable
1-2 ‫جدول‬

‫ استفاده شده‬app_ ‫ برای مشاهده فهرست دستورات استریسک از پیشوند‬،‫همان‌طور که مالحظه می‌کنید‬
‫ اگر قصد‬.‫ نمایش داده می‌شوند‬Application ‫ در این حالت تمام ماژول‌های دسته‌بندی‌شده در حوزه‬.‫اســت‬
‫ در این‬.‫ باید اســم ماژول را به طور کامل مشخص کنیم‬،‫داشــته باشیم فعال بودن یک ماژول را بررسی کنیم‬
.‫ مشخص خواهد شد که ماژول فعال است یا نیست‬،‫صورت با توجه به نوع خروجی استریسک‬
.‫ در استریسک فعال است یا نه‬Dial ‫برای مثال فرض کنید قرار اســت بررســی کنیم که آیا ماژول دستور‬
:‫برای این منظور دستور زیر را در کامند الین استریسک اجرا می‌کنیم‬
CLI> module show like app_dial.so
Module Description Use Count
app_dial.so Dialing Application 0
1 modules loaded
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪50‬‬

‫همان‌طور که مالحظه می‌کنید‪ ،‬ماژول فوق در استریســک فعال است‪ .‬اکنون فرض کنید بخواهیم این ماژول‬
‫را در استریسک موقتاً غیرفعال کنیم‪ .‬در این صورت دستور زیر را در کامند الین استریسک اجرا می‌کنیم‪:‬‬
‫‪CLI> module unload app_dial.so‬‬
‫‪Unloaded app_dial.so‬‬
‫›‪== Unregistered application ‹Dial‬‬
‫›‪== Unregistered application ‹RetryDial‬‬

‫با غیرفعال کردن ماژول فوق در استریســک‪ ،‬دســتور ‪ Dial‬غیرفعال شده و دیگر نمی‌توانیم از آن استفاده‬
‫کنیم‪ .‬در صورت استفاده کردن از دستور فوق‪ ،‬استریسک گزارش زیر را در کامند الین نشان می دهد‪.‬‬
‫‪[Jun 30 13:06:20] WARNING[7481][C-00000031]: pbx.c:4878 pbx_extension_helper: No‬‬
‫)‪application ‹Dial› for extension (agents, op103, 5‬‬

‫ما می‌توانیم ماژول‌هایی را که در استریسک نیاز نداریم‪ ،‬غیرفعال کنیم‪ .‬غیرفعال کردن ماژول‌های اضافی‬
‫در استریســک باعث سبک‌تر شدن آن می‌شود و در پی آن کارایی استریسک افزایش پیدا می‌کند‪ .‬عالوه بر‬
‫این‪ ،‬امنیت در سیستم استریسک نیز افزایش پیدا می‌کند‪.‬‬
‫برای مثال فرض کنید قرار است یک سیستم نظرسنجی با استریسک طراحی کنید‪ .‬در این صورت‪ ،‬چون‬
‫هدف این است که مشترک با سیستم تماس بگیرد و نظر خود را به‌صورت اعداد اعالم کند‪ ،‬مسلماً در چنین‬
‫سیســتمی نیازی به فعال بودن برخی ماژول‌ها نیســت؛ چون اکثر تماس‌ها در این سیســتم به صورت ورودی‬
‫‪1‬‬

‫هستند‪ .‬بنابراین می‌توانیم برای باالبردن امنیت‪ ،‬ماژول‌های بالاستفاده را غیرفعال کنیم‪.‬‬
‫نکته مهم در غیرفعال کردن ماژول‌ها به روش فوق‪ ،‬این اســت که اگر استریســک مجددا ً راه‌اندازی شود‪،‬‬
‫ماژول دوباره فعال می‌شود‪ .‬برای غیرفعال کردن ماژول به‌صورت دائم‪ ،‬باید از فایل ‪ module.conf‬از مسیر زیر‬
‫استفاده کنیم و تغییرات الزم را انجام دهیم‪.‬‬
‫‪#vim /etc/asterisk/modules.conf‬‬
‫>‪noload => <module name‬‬

‫بعد از انجام تغییرات در این فایل به‌صورت فوق‪ ،‬ماژول برای همیشه در استریسک غیرفعال خواهد ماند‪ .‬در‬
‫فصل‌های بعدی در مورد ماژول ‪ Application‬و کاربرد آن در استریسک بیشتر توضیح خواهیم داد‪.‬‬

‫معرفی ماژول ‪Bridge‬‬


‫بحث در مورد مفهوم ‪ Bridge‬شــدن کانال‌ها در استریســک مفصل اســت و ممکن اســت در بدو امر کمی‬
‫گیج‌کننده به نظر رسد‪ .‬بهتر است با یک مثال آن را توضیح دهیم‪:‬‬
‫با درنظر گرفتن شکل ‪ ،۲-۲‬زمانی که درخواست ایجاد یک تماس به استریسک داده میشود‪ ،‬استریسک‬
‫برای آن‪ ،‬یک کانال جدید ایجاد میکند‪ ،‬بهطوریکه بتواند از طریق آن کانال صدا را انتقال دهد‪ .‬اکنون برای‬

‫‪1- Incoming‬‬
‫‪51‬‬ ‫معماری استریسک‬

‫ایجاد یک تماس دوطرفه‪ ،‬استریســک باید دو کانال ارتباطی جدید ایجاد کند و آن دو را به هم متصل کند‪،‬‬
‫بهطوریکه دادهها )صدا( از یک کانال به کانال دیگر انتقال یابد‪ .‬این عمل را ‪ Bridge‬شدن کانالها میگویند‪.‬‬

‫شکل ‪2-2‬‬

‫برای مشاهده این نوع ماژول‌ها‪ ،‬دستور زیر را در کامند الین استریسک اجرا کنید‪:‬‬
‫_‪CLI> module show like bridge‬‬

‫در جدول زیر لیست انواع ماژول‌های ‪ Bridge‬در استریسک ارائه شده است‪.‬‬

‫‪Name‬‬ ‫‪Purpose‬‬ ‫‪Status‬‬


‫‪bridge_builtin_features‬‬ ‫‪Performs bridging when utilizing built-in user features (such as‬‬ ‫‪New‬‬
‫‪those found in features.conf).‬‬
‫‪bridge_multiplexed‬‬ ‫‪Performs complex multiplexing, as would be required in a large‬‬ ‫‪Useful‬‬
‫‪conference room (multiple participants). Currently only used by‬‬
‫‪app_confbridge.‬‬
‫‪bridge_simple‬‬ ‫‪Performs simple channel-to-channel bridging.‬‬ ‫‪Useful‬‬
‫‪bridge_softmix‬‬ ‫‪Performs simple multiplexing, as would be required in a large‬‬ ‫‪Useful‬‬
‫‪conference room (multiple participants). Currently only used by‬‬
‫‪app_confbridge.‬‬
‫جدول ‪2-2‬‬

‫‪1‬‬
‫ماژول ری ‌ز گزارشات تماس‬
‫یکــی از قابلیت‌هــا و امتیــازات منحصربه‌فــرد یــک ســوئیچ‪ ،‬گــزارش دقیــق از جزئیــات تماس‌هــای‬
‫ورودی و خروجــی اســت‪ .‬در استریســک‪ ،‬مــاژول ‪ CDR‬ایــن قابلیت‌هــا را فراهــم می‌کنــد تــا بتوانیــم‬
‫گــزارش دقیقــی از کارکــرد سیســتم داشــته باشــیم‪ .‬همــه گزارش‌هــای ‪ CDR‬به‌صورت پیش‌فــرض در‬
‫مســیر ‪ /var/log/asterisk/cdr-csv/Master.csv‬در فایــل سیســتم ذخیــره می‌شــوند‪ .‬ازآنجاکــه کار‬
‫بــا ایــن نــوع گزارش‌ها در فایل سیســتم دشــوار اســت‪ ،‬ایــن قابلیــت در استریســک وجــود دارد که این‬
‫گزارش‌ها در پایگاه‌های داده‌‌ای‪ 2‬همچون ‪ MYSQL,postgresql, MSSQL‬ذخیره شوند‪.‬‬
‫برای مشاهده این نوع ماژول‌ها‪ ،‬دستور زیر را در کامند الین استریسک اجرا کنید‪:‬‬

‫)‪1- Call Detail Recording (CDR‬‬


‫‪2- Backend DB‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 52

CLI> module show like cdr_

.‫ در استریسک قابل مالحظه است‬CDR ‫ لیست انواع ماژول‌های‬3-2 ‫در جدول‬

Name Purpose Status


cdr_adaptive_odbc Allows writing of CDRs through ODBC framework Useful
with ability to add custom fields
cdr_csv Writes CDRs to disk as a comma-separated values Usable
file
cdr_custom Writes CDRs to a CSV file, but allows addition of Useful
custom fields
cdr_manager Outputs CDRs to Asterisk Manager Interface Useful
(AMI)
cdr_odbc Writes CDRs through ODBC framework Usable
cdr_pgsql Writes CDRs to PostgreSQL Useful
cdr_radius Writes CDRs to RADIUS Usable—does not
support custom fields
cdr_sqlite Writes CDRs to SQLite2 database Deprecated—use
sqlite3_custom
cdr_sqlite3_custom Writes CDRs to SQLite3 with custom fields Useful
cdr_syslog Writes CDRs to syslog Useful
cdr_tds Writes CDRs to Microsoft SQL or Sybase Usable—requires an old
version of libtds
3-2 ‫جدول‬

.‫ خواهیم پرداخت‬CDR ‫در فصل‌ هفدهم به تفصیل در مورد ماژول‬

1
‫ماژول رویدادهای استریسک‬
‫ هر فعالیتی که‬.‫ دارای یک ســاختار پیام‌گرا (رویداد‌گرا) نیز هست‬،‫استریســک در کنار ســاختار ماژوالر خود‬
var/log/asterisk/cel-/ ‫ در مســیر‬CEL ‫ به‌صــورت رویدادهایی در گزارش‌هــای‬،‫استریســک انجام می‌دهد‬
.‫ ذخیره می‌شوند‬custom/Master.csv
:‫ دستور زیر را در کامندالین استریسک اجرا کنید‬،‫برای مشاهده این نوع ماژول‌ها‬
CLI> module show like cel_

.‫ در استریسک ارائه شده است‬CEL ‫ لیست انواع ماژول‌های‬4-2 ‫در جدول‬


.‫ بحث خواهد شد‬CEL ‫در فصل هفدهم به تفصیل در مورد ماژول‬

3- Channel Event Logging Module (CEL)


53 ‫معماری استریسک‬

Name Purpose Popularity/Status


cel_custom CEL to disk/file Useful
cel_manager CEL to AMI Usable
cel_odbc CEL to ODBC Useful
cel_pgsql CEL to PostgreSQL Useful
cel_radius CEL to RADIUS Usable—does not support custom fields
cel_sqlite3_custom CEL to SQLite3 Useful
cel_tds CEL to Microsoft SQL or Sybase Usable—requires an old version of libtds
4-2 ‫جدول‬

‫ در استریسک‬Channel Drivers ‫ماژول‬


‫ می‌تواند تماس‌هایی‬،‫ استریسک به‌واسطه کانال‌های ارتباطی خود‬،‫همان‌طور که پیش از این نیز اشاره کردیم‬
.‫ در مورد این ماژول در فصل‌های آینده مفصل‌تر بحث خواهیم کرد‬.‫برقرار نماید‬
:‫ دستور زیر را در کامند الین استریسک اجرا کنید‬،‫برای مشاهده انواع ماژول‌های کانالی در استریسک‬
CLI> module show like chan_

.‫ ها را در استریسک نشان می‌دهد‬Channel Drivers ‫ مهم‌ترین‬5-2 ‫جدول‬

Name Purpose Status


chan_agent Provides agent channel for Queue() Useful
chan_alsa Provides connection to Advanced Linux Sound Useful
Architecture
chan_bridge Used internally by the ConfBridge() application; should Essential (If you are
not be used directly using the ConfBridge()
application)
chan_console Utilizes the portaudio library to provide a cross- Useful
platform
console channel driver that uses the system sound
device
chan_dahdi Provides connection to PSTN cards that use DAHDI Useful
channel drivers
chan_gtalk Provides connection to Google Talk Deprecated as of
Asterisk 11
chan_h323 Provides connection to H.323 endpoints Deprecated
chan_iax2 Provides connection to IAX2 endpoints Useful
chan_jingle Provides connection to Jingle-enabled endpoints Deprecated as of
Asterisk 11- see chan_
motif
chan_local Provides a mechanism to treat a portion of the dialplan Useful
as a channel
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 54

Name Purpose Status


chan_mgcp Media Gateway Control Protocol channel driver Usable
chan_misdn Provides connection to mISDN-supported ISDN cards Limited
chan_motif Implements the Jingle protocol, including the ability to Useful
connect to Google Talk and Google Voice; introduced
in Asterisk 11
chan_multicast_ Provides connection to multicast Realtime Transport Useful
rtp Protocol (RTP) streams
chan_nbs Network Broadcast Sound channel driver Insignificant
chan_oss Open Sound System driver Useful
chan_phone Linux telephony interface driver (very old) Insignificant
chan_sip Session Initiation Protocol (SIP) channel driver Essential
chan_skinny Cisco Skinny Client Control Protocol (SCCP) channel Usable
driver
chan_unistim Nortel Unistim protocol channel driver Usable
5-2 ‫جدول‬

Codec Translator ‫ماژول‬


‫ آنچه در اینجا اهمیت دارد‬.‫ یکی از مســائل پرحاشــیه و چالش‌برانگیز در شبکه‌های ویپ است‬،‫بحث کدک‬
‫ مسلماً واضح‬.‫ پهنای باند را مصرف می‌کنند‬،‫ زمانی که در شبکه منتقل می‌شوند‬،‫این است که معموالً داده‌ها‬
‫ کدک‌ها داده را فشــرده‬.‫ پهنای باند مصرفــی کمتر خواهد بود‬،‫اســت هرچه داده‌های کمتری منتقل شــود‬
`.‫می‌کنند تا پهنای باند کمتری مصرف شود‬

3-2 ‫شکل‬

‫ ارتباط مستقیمی با نوع کدک استفاده‌شده‬،‫ کیفیت سرویس ارائه‌شــده‬،‫با توجه به اینکه در شــبکه‌های ویپ‬
،‫ در استریسک‬.‫ بنابراین استفاده از کدک مناسب در شبکه از اهمیت ویژه‌ای برخوردار است‬،‫در شــبکه دارد‬
‫ نکته مهم این ‌است که‬.‫ می‌توان تبدیل کدک انجام داد‬،‫چنانچه دو طرف از کدک یکســانی اســتفاده نکنند‬
1

‫ را به‬CPU ‫ افت کارایی سیســتم استریســک و افزایش پردازش‬،‫تبدیل کدک در بلندمدت و حجم‌های باال‬
.‫دنبال خواهد داشت‬
1- Transcoding
55 ‫معماری استریسک‬

:‫ دستور زیر را در کامند الین استریسک اجرا کنید‬،‫برای مشاهده انواع کدک‌های فعال در استریسک‬
CLI> module show like codec_

.‫ مهم‌ترین کدک های فعال در استریسک را نشان می‌دهد‬6-2 ‫جدول‬

Name Purpose Status


codec_adpcm Adaptive Differential Pulse Coded Modulation (ADPCM) Insignificant
codec
codec_alaw A-law PCM codec used all over the world (except Essential
Canada/USA) on the PSTN
codec_g729 Does not come with Asterisk due to the fact that it is Useful
not a public domain codec, but can be purchased from
Digium; a very popular codec if compression is desired
(and CPU use is not an issue)
codec_a_mu A-law to mu-law direct converter Useful
codec_dahdi Utilizes proprietary Digium hardware transcoding card Essential (If you are
using a Digium codec
transcoder card.)
codec_g722 Wideband audio codec Useful
codec_g726 Flavor of ADPCM Insignificant
codec_gsm Global System for Mobile Communications (GSM) codec Useful
codec_ilbc Internet Low Bitrate Codec Insignificant
codec_lpc10 Linear Predictive Coding vocoder (extremely low Insignificant
bandwidth)
codec_resample Resamples between 8-bit and 16-bit signed linear Usable
codec_speex Speex codec Usable
codec_ulaw Mu-law PCM codec used in Canada/USA on PSTN Essential
6-2 ‫جدول‬

‫ برای تبدیل صدا از یک کدک به‬.‫همان‌طور که می‌دانیم در استریســک از تبدیل کدک‌ها اســتفاده می‌شود‬
.‫ مدت‌زمان برحسب میلی‌ثانیه در نظر گرفته می‌شود‬،‫یک کدک دیگر‬
:‫دستور زیر تبدیل کدک‌ها به یکدیگر را برحسب میلی‌ثانیه نشان می‌دهد‬
CLI> core show translation
Translation times between formats (in microseconds) for one second of data
Source Format (Rows) Destination Format (Columns)

Format Interpreter ‫ماژول‬


‫گاهی نیاز داریم یک تماس با استریســک برقرار کنیم تا یک فایل صوتی پخش شــود؛ اکنون ممکن اســت‬
‫ در این شرایط ماژول‬.‫فرمت فایل صوتی پخش‌شــده با نوع کدک استفاده‌شــده توســط کاربر متفاوت باشد‬
.‫ وظیفه تبدیل کدک فایل صوتی را به عهده دارد‬Format Interpreter
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 56

4-2 ‫شکل‬

‫ در تماس‬Codec Translator ‫ در این‌است‌که ماژول‬Format Interpreter ‫ و‬Codec Translator ‫تفاوت ماژول‬


‫ شــوند؛ درحالی‌که ماژول‬Bridge ‫ زمانی اتفاق می‌افتد که دو کانال باهم‬،‫دوطرفه بین دو کاربر در استریســک‬
‫ زمانی که یک کاربر به ســرور استریســک متصل شده اســت و فایل‌های صوتی پخش‬Format Interpreter
.‫ اتفاق می‌افتد‬،‫می‌شود‬

Dialplan Function
‫ از توابع قدرتمندی استفاده می‌کند که باعث تسریع در برنامه‌نویسی‬،Application ‫استریسک در کنار ماژول‌های‬
1

:‫ دستور زیر را در کامندالین استریسک وارد نمایید‬،‫ برای مشاهده انواع توابع در استریسک‬.‫ می‌شود‬Dialplan
CLI> module show like func_

.‫ مهم‌ترین توابع فعال در استریسک را نشان می‌دهد‬7-2 ‫جدول‬

Name Purpose Status


func_aes Encrypts/decrypts an AES string Useful
func_ Allows calls to be recorded after transfer Useful
audiohookinherit
func_base64 Encodes/decodes a base -64 string Usable
func_blacklist Writes/reads blacklist in astdb Useful
func_ Gets/sets call -completion configuration parameters for the channel New
callcompletion
func_callerid Gets/sets CallerlD Useful
func_cdr Gets/sets CDR variable Useful
func_channel Gets/sets channel information Useful
func_config Includes AST_CONFIG (); reads variables from config file Usable
func_connectedline Changes connected -line information on supported handsets New
func_curl Uses cURL to obtain data from a URI Useful

1- Function
57 ‫معماری استریسک‬

Name Purpose Status


func_cut Slices and dices strings Useful
func_db Provides astdb functions Useful
func_devstate Gets state of device Useful
func_dialgroup Creates a group for simultaneous dialing Useful
func_dialplan Validates that designated target exists in dialplan Useful
func_enun Performs ENUM lookup Useful
func_env Includes FILED, STAT( ), and ENV( ); performs operating system Useful
actions
func_extstate Returns status of a hinted extension Useful
func_global Gets/sets global variables Useful
func_groupcount Gets/sets channel count for members of a group Useful
func_tanguocause Gets/sets hangupcause information from the channel Useful
func_iconv Converts between character sets Usable
func jitterbuffer Includes the JITTERBUFFER( ) function, which allows you to place a Useful
jitterbuffer on a channel.
func_lock Includes LOCK ( ), UNLOCK( ), and TRYLOCK( ); sets a lock that can be Useful
used to avoid race conditions in the -dialplan
func_loO, Includes ISNULLO( ), SET( ), EXISTS( ) , IF( ), IFTIMED( ), and IMPORT Useful
( ); performs various logical functions

func_math Includes MATH( ), INC( ), and DEC( ); performs mathematical Useful


functions Converts supplied string to an MD5 hash
func_rvIS Converts supplied string to an MD5 hash Useful
func_module Checks to see if supplied module is loaded into memory Usable
func_otlbc Allows dialplan integration with ODBC resources Shifts the pitch of Useful
an audio stream
func_pitchstift Shifts the pitch of an audio stream Useful
func_presencestate Gets/sets presence state; this is primarily used by Asterisk Useful
integration with Digium phones
func_rand Returns a random number within a given range Useful
func_realtime Performs lookups within the Asterisk Realtime Architecture (ARA) Useful
func_reclirecting Provides access to information about where this call was redirected Useful
from
func_stal Converts supplied string to an SHA1 hash Useful
func_shell Performs Linux shell operations and returns results Useful
func_speex Reduces noise and performs dB gain/loss on an audio stream Useful
func_sprintf Performs string format functions similar to (function of same name Useful
func_sry Performs SRV lookups in the dialplan Useful
func_strings Includes over a dozen string manipulation functions Useful
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 58

Name Purpose Status


func_sysinfo Gets system information such as RAM, swap, load average, etc. Useful
func_tineout Gets/sets timeouts on channel Useful
func_urt Converts strings to URI-safe encoding Useful
func_version Returns Asterisk version information Usable
func_vmcount Returns count of messages in a voicemail folder for a particular Useful
user
func_volune Sets volume on a channel Useful
7-2 ‫جدول‬

.‫در فصل‌های پنجم و هشتم در مورد برنامه‌نویسی در استریسک به طور مفصل توضیح خواهیم داد‬

PBX Config
‫ استریسک از یک‬،‫ در همین راستا‬.‫ یک ساختار اولیه برای پیکربندی و راه‌اندازی دارد‬،‫اکثر سوئیچهای تلفنی‬
‫ساختار فایل سیستمی برخوردار است که می‌تواند پیکربندی اولیه و ابتدایی استریسک را تنظیم و مدیریت کند؛‬
‫ اشاره‬،‫ که مربوط به برنامه‌نویســی است‬extension.conf ‫ازجمله این موارد می‌توان به ســاختار پیکربندی فایل‬
.‫کرد‬
،1‫ که در تولید کال فایل‌ها‬pbx-spool ‫ و ماژول‬ARA ‫ است که در‬pbx-realtime ‫ ماژول‬،‫از دیگر این موارد‬
.‫ هر ماژول به تفصیل در فصل‌های یازدهم و سیزدهم توضیح داده می‌شوند‬.‫استفاده می‌شود‬
:‫ دستور زیر را در کامندالین استریسک اجرا کنید‬،‫برای مشاهده انواع ماژول‌ها‬
CLI> module show like pbx_

.‫ در استریسک را نشان می‌دهد‬PBX ‫ مهم‌ترین ماژول‌های‬8-2 ‫جدول‬

Name Purpose Popularity/


Status
pbx_ael Asterisk Extension Logic (AEL) offers a dialplan scripting language Usable
that looks like a modern programming language.
pbx_config This is the traditional, and most popular, dialplan language for Useful
Asterisk. Without this module, Asterisk cannot read extensions.conf.
pbx_dundi Performs data lookups on remote Asterisk systems. Useful
pbx_loopback Performs something similar to a dialplan include, but in a deprecated Insignificant
manner.
pbx_lua Allows creation of a dialplan using the Lua scripting language. Useful
pbx_realtime Provides functionality related to the Asterisk Realtime Architecture. Useful
pbx_spool Provides outgoing spool support relating to Asterisk call files. Useful
8-2 ‫جدول‬

2- Asterisk call files


‫‪59‬‬ ‫معماری استریسک‬

‫ماژول ‪Resource‬‬
‫در استریســک این قابلیت فراهم‌شده اســت که بتوانیم با سایر سرویس‌ها ارتباط داشــته باشیم؛ برای مثال به‬
‫منظور ذخیره کردن گزارش‌های استریسک در پایگاه‌های داده‌ای‪ ،‬از این نوع ماژول‌ها استفاده می‌کنیم‪.‬‬
‫برای مشاهده انواع ماژول‌ها‪ ،‬دستور زیر را در کامندالین استریسک اجرا کنید‪:‬‬
‫_‪CLI> module show like res‬‬

‫جدول ‪ 9-2‬مهم‌ترین ماژول‌های ‪ Resource‬در استریسک را نشان می‌دهد‪.‬‬

‫‪Name‬‬ ‫‪Purpose‬‬ ‫‪Status‬‬


‫‪res_config_curl‬‬ ‫‪Pulls configuration information using cURL‬‬ ‫‪Useful‬‬
‫‪res_config_ldap‬‬ ‫‪Pulls configuration information using LDAP‬‬ ‫‪Usable‬‬
‫‪res_config_odbc‬‬ ‫‪Pulls configuration information using ODBC‬‬ ‫‪Useful‬‬
‫‪res_config_pgsql‬‬ ‫‪Pulls configuration information using PostgreSQL‬‬ ‫‪Usable‬‬
‫‪res_config_sqlite‬‬ ‫)‪Pulls configuration information using SQLite (version 2‬‬ ‫‪Usable‬‬
‫‪res_config_sqlite3‬‬ ‫)‪Pulls configuration information using SQLite (version 3‬‬ ‫‪Usable‬‬
‫جدول ‪9-2‬‬

‫ساختار فایل سیستم در استریسک‬


‫استریســک ساختار فایل سیســتم پیچیده‌ای دارد‪ .‬در برخی مسیرها فایل‌های پیکربندی استریسک‪ ،‬در برخی‬
‫دیگر از مسیرها فایل‌های صوتی استریسک و در سایر مسیرها ماژول‌های فعال در استریسک قرار دارند‪.‬‬
‫در ادامه به معرفی ساختار فایل سیستم در استریسک می‌پردازیم‪.‬‬

‫فایل‌های پیکربندی در استریسک‬


‫فایل‌های پیکربندی و تنظیمات استریسک در مسیر ‪ /etc/asterisk/‬قرار دارد‪ .‬در فصل‌های آینده با جزئیات هر‬
‫فایل آشنایی بیشتری پیدا می‌کنید‪.‬‬
‫برای مشاهده‌ی انواع فایل‌های پیکربندی دستور زیر را در محیط لینوکس اجرا کنید‪:‬‬
‫‪# ls /etc/asterisk/‬‬

‫برای مثال مهمترین فایل‌های پیکربندی عبارتند از‪:‬‬


‫‪ : extensions.conf -‬مهم‌تریــن فایل در استریســک اســت که مدیریت کامل تماس‌ها‪ ،‬مســیریابی و اجرای‬
‫برنامه‌های مختلف در برنامه‌نویسی را بر عهده دارد‪.‬‬
‫‪ : sip.conf -‬تنظیمات مربوط به تعریف و شناسایی یوزرها و ارتباطات با پروتکل ‪ sip‬در این فایل انجام می‌شود‪.‬‬
‫‪ : module.conf -‬ایــن فایل کنترل انواع ماژول‌ها در استریســک را بر عهــده دارد‪ .‬ازطریق این فایل می‌توان‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪60‬‬

‫مشخص کرد که چه ماژول‌هایی باید فعال شوند‪ .‬همچنین می‌توان ترتیب بارگذاری ماژول‌ها در استریسک را‬
‫تعیین نمود‪.‬‬
‫‪ :queues.conf -‬مدیریت صف‌ها در این فایل انجام می‌شود‪.‬‬
‫‪ :iax.conf -‬تنظیمــات مربوط به تعریف و شناســایی کاربرها و ارتباطات با پروتــکل ‪ IAX‬در این فایل انجام‬
‫می‌شود‪.‬‬
‫‪ :asterisk.conf -‬در این فایل پیکربندی اولیه هسته استریسک انجام می‌شود‪.‬‬

‫ل ماژول‌ها در استریسک‬
‫فای ‌‬
‫مســیر فایل‌های ماژول در استریســک در مســیر ‪ /usr/lib/asterisk/modules/‬اســت‪ .‬استریســک به‌صورت‬
‫پیش‌فــرض همه ماژول‌هایی که در این مســیر قرار دارند را بارگذاری‪ 1‬می‌کند‪ ،‬مگــر آنکه ماژول موردنظر را‬
‫به‌صورت دستی در فایل ‪ modules.conf‬غیرفعال کنیم‪ .‬همچنین می‌توانیم با حذف ماژول موردنظر از این مسیر‪،‬‬
‫ماژول را به‌صورت دائم غیرفعال کنیم‪ .‬شاید بهتر باشد برای ماژول‌هایی که به آن‌ها نیازی نداریم‪ ،‬آنها را برای‬
‫همیشــه از این مسیر حذف کنیم‪ .‬برای مشاهده انواع ماژول‌های استریسک‪ ،‬دستور زیر را در محیط استریسک‬
‫اجرا کنید‪:‬‬
‫‪#ls /usr/lib/asterisk/modules‬‬

‫فایل‌های مانیتورینگ و گزارش‌ها در استریسک‬


‫استریســک به‌صورت پیش‌فرض همه گزارش‌ها و فایل‌های مانیتورینگ را در مسیر ‪ /var/log/asterisk/‬ذخیره‬
‫می‌کند‪ .‬با بررسی این فایل‌ها می‌توان اشکاالت و خطاهای احتمالی در استریسک را رفع نمود‪ .‬در فصل هفدهم‬
‫درخصوص مانیتورینگ استریسک و بررسی الگ فایل ها در استریسک توضیحات بیشتری خواهد آمد‪.‬‬

‫‪2‬‬
‫برنامه‌نویسی در استریسک‬
‫برنامه‌نویسی در استریسک‪ ،‬مرکز اصلی کنترل تماس‌های ورودی و خروجی در استریسک است‪ .‬درواقع هر‬
‫تماس جدیدی که وارد سیســتم تلفنی استریسک می‌شــود به وسیله این فایل مسیریابی می‌شود و در صورت‬
‫مطابقت با رول‌های‪ 3‬تعریف‌شــده‪ ،‬دســتورات اجرا می‌شــوند‪ .‬در استریسک‪ ،‬ســه روش برای برنامه‌نویسی‬
‫هســت که در ادامه به آنها خواهیم پرداخت‪ .‬ازآنجاکه در فصل‌های آینده راجع به برنامه‌نویسی استریسک و‬
‫قابلیتهای آن توضیح داده خواهد شد‪ ،‬در این فصل تنها به معرفی انواع روش‌های برنامه‌نویسی در استریسک‬
‫اکتفا می‌کنیم‪.‬‬
‫‪1- Load Modules‬‬
‫‪1- Dial Plan‬‬
‫‪2- roles‬‬
‫‪61‬‬ ‫معماری استریسک‬

‫استفاده از ‪extensions.conf‬‬
‫یکی از ســاده‌ترین روش‌های برنامه‌نویســی در استریسک استفاده از این فایل است‪ .‬در زیر مثالی ساده از این‬
‫نوع برنامه‌نویسی ارائه شده‌است‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[default‬‬
‫)‪exten => 100,1,playback(please-hold‬‬
‫)‪exten => 100,2,dial(IAX2/203,60‬‬
‫)‪exten => 101,1,dial(SIP/101,60‬‬

‫استفاده از ‪extensions.ael‬‬
‫یکی دیگر از روش‌های برنامه‌نویســی در استریسک‪ ،‬استفاده از برنامه‌نویسی به‌صورت ‪ ael‬است‪ .‬نمونه‌ای از‬
‫برنامه‌نویسی با این روش در زیر ارائه شده است‪.‬‬
‫‪;extensions.ael‬‬
‫{ ‪context defualt‬‬
‫{ >= ‪100‬‬
‫;)‪Playback(please-hold‬‬
‫;)‪Dial(IAX2/203,60‬‬
‫}‬
‫{ >= ‪101‬‬
‫;)‪Dial(SIP/101,60‬‬
‫}‬

‫استفاده از ‪extensions.lua‬‬
‫یکی دیگر از روش‌های برنامه‌نویســی در استریســک استفاده از برنامه‌نویسی به‌صورت ‪ lua‬است‪ .‬نمونه‌ای از‬
‫برنامه‌نویسی با این روش در زیر ارائه شده است‪.‬‬
‫‪;extension.lua‬‬
‫{ = ‪extensions‬‬
‫{= ‪default‬‬
‫)‪[“100”] = function(function,extension‬‬
‫)”‪app.playback(“please-hold‬‬
‫)‪app.dial(“IAX2/203”,60‬‬
‫)‪[“101”] = function(function,extension‬‬
‫)‪app.dial(“SIP/101”,60‬‬
‫;‪end‬‬

‫در استریســک می‌توانیم از هر ســه روش برای برنامه‌نویســی اســتفاده کنیم‪ .‬آنچه در این کتاب بیشتر توضیح‬
‫داده می‌شــود‪ ،‬برنامه‌نویســی با روش اول و استفاده از فایل ‪ extension.conf‬اســت‪ .‬استفاده از سایر روش‌های‬
‫برنامه‌نویسی در استریسک به خواننده کتاب واگذار می‌شود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪62‬‬

‫نتیجه‌گیری‬
‫استریســک از کامپوننت‌ها و ماژول‌های مختلفی تشکیل‌شــده اســت که هرکدام از آن‌هــا قابلیت‌هایی را به‬
‫استریســک اضافه می‌کنند‪ .‬استریســک می‌تواند از همه این قابلیت‌ها‪ ،‬در صورت فعال بودن در استریســک‬
‫استفاده کند‪ .‬در فصل‌های آینده هر یک از این ماژول‌ها و قابلیت‌ها را به تفصیل شرح خواهیم داد‪.‬‬
‫فصل سوم‬
‫نصب و راه اندازی استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪64‬‬

‫مقدمات نصب استریسک‬


‫در این فصل نحوه صحیح نصب استریسک شرح داده می‌شود‪ .‬شاید در ابتدا نصب استریسک کمی دشوار و‬
‫وقتگیر به‌نظر برسد ولی با مطالعه این فصل متوجه خواهید شد که نصب استریسک از روی سورس استریسک‬
‫بســیار ساده است‪ .‬البته در زمان نصب ممکن اســت با چالش‌هایی مواجه شوید که در بخش مربوطه توضیح‬
‫داده خواهد شد‪.‬‬
‫از آنجاکه توزیع‌های لینوکس ‪ RHEL‬و ‪ Ubuntu‬جزو محبوب‌ترین توزیع‌های لینوکســی‌اند‪ ،‬برای نصب‬
‫استریســک روی این توزیع‌ها تمرکز بیشــتری خواهیم داشــت‪ .‬شاید این سوال مطرح شــود که کدام توزیع‬
‫لینوکســی برای نصب و اســتفاده از استریسک بهتر است؟ بهترین پاســخ برای این سوال‪ ،‬به اینکه به کدامیک‬
‫از توزیع‌های لینوکســی مسلط‌تر باشید‪ ،‬بازمی‌گردد‪ .‬در سیستم‌های تلفنی الستیکس (که از سورس استریسک‬
‫اســتفاده می‌شود) از توزیع ‪ RHEL‬استفاده می‌شود‪ .‬در مجموع‪ ،‬دســتورات اجرایی روی استریسک‪ ،‬برای هر‬
‫دو توزیع قابل اســتفاده‌اند و ارتباطی با توزیع لینوکســی ندارند‪ .‬در این کتاب هر دو توزیع‪ ،‬مد نظر قرار دارد و‬
‫دستورات الزم برای هر یک‪ ،‬بطور مستقل شرح داده خواهد شد‪.‬‬
‫از آنجاکه استریسک دارای نسخه‌های متعددی است و مراحل نصبشان با هم تفاوتی ندارد‪ ،‬در این فصل به‬
‫نسخه استریسک ‪ 13‬خواهیم پرداخت‪ .‬برای نصب استریسک باید دسترسی ‪ root‬داشته باشیم که با عالمت (‪ )#‬‬
‫در کامندالین لینوکس نمایش داده می‌شــود‪ .‬همچنین دسترســی به اینترنت نیز باید وجود داشته باشد‪ .‬در ادامه‬
‫نصب استریسک به صورت مرحله به مرحله شرح داده می‌شود‪.‬‬
‫‪65‬‬ ‫نصب و راه‌اندازی استریسک‬

‫‪1‬‬
‫بروز رسانی سیستم‬
‫در سیســتم عامل لینوکس برای نصب بسته‌های مورد نیاز‪ ،‬باید ابتدا آنها را بروزرسانی کنیم تا از آخرین‬
‫نسخه ارتقا یافته بسته‌ها‪ ،‬استفاده کنیم‪ .‬به همین منظور در اولین گام باید سیستم عامل را آپدیت کنیم‪ .‬مراحل‬
‫زیر را با توجه به توزیع لینوکسی انجام می‌دهیم‪.‬‬
‫‪; RHEL‬‬
‫‪# yum update –y‬‬

‫‪;Ubuntu‬‬
‫‪# apt-get update‬‬

‫بعد از انجام عملیات بروزرســانی‪ ،‬باید سیســتم را مجددا ً راه‌اندازی کنید‪ .‬برای راه‌اندازی سیستم‪ ،‬دستور‬
‫زیــر را اجرا کنید‪ .‬برای راه اندازی مجدد سیســتم‪ ،‬دســتورات متعددی وجود دارد کــه می‌توان از هر کدام‬
‫استفاده کرد‪ .‬در زیر مثال‌هایی از هریک آورده شده است‪:‬‬
‫‪; RHEL‬‬
‫‪# reboot‬‬
‫‪# shutdown –r now‬‬
‫‪# init 6‬‬

‫‪;Ubuntu‬‬
‫‪# reboot‬‬
‫‪# shutdown –r now‬‬
‫‪#init 6‬‬

‫نصب نیازمندی‌های استریسک‬


‫‪2‬‬

‫اولین اقدامی که بعد از بروزرسانی سیستم لینوکس انجام می‌دهیم‪ ،‬نصب نیازمندی‌های استریسک است‪ .‬برای‬
‫اینکه بتوانیم استریسک را با موفقیت نصب کنیم باید ابتدا بسته‌های مورد نیاز استریسک را نصب کنیم‪ .‬هدف از‬
‫این فصل‪ ،‬نصب استریسک‪ 3 DAHDI ،‬و ‪ LibPRI‬است‪ .‬در فصل‌های بعدی توضیح خواهیم‌داد که برای فعال‬
‫کردن برخی قابلیت‌های استریسک باید نیازمندی‌های آن‌ها را نیز نصب کنیم‪ .‬این قابلیت‌های استریسک در هر‬
‫فصل به‌طور مستقل شرح داده خواهند‌شد‪.‬‬
‫با توجه به توزیع لینوکس‪ ،‬برای نصب نیازمندی‌های استریسک‪ ،‬دستورات زیر را در کامندالین لینوکس‬
‫اجرا کنید‪:‬‬
‫‪; RHEL‬‬
‫‪# yum install gcc gcc-c++ make wget‬‬
‫‪subversion libxml2-devel‬‬

‫‪1- Base System Update‬‬


‫‪2- dependencies‬‬
‫‪3- Digium Asterisk Hardware Devices Interface‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪66‬‬

‫‪ncurses-devel openssl-devel‬‬
‫‪sqlite-devel libuuid-devel‬‬
‫‪vim-enhanced‬‬

‫‪;Ubuntu‬‬
‫‪# apt-get install build-essential subversion‬‬
‫‪libncurses5-dev libssl-dev‬‬
‫‪libxml2-dev libsqlite3-dev‬‬
‫‪uuid-dev vim-nox‬‬

‫از آنجاکه برای نصب استریســک ‪ 13‬باید ماژول ‪ json‬از قبل نصب شــده باشد‪ ،‬می‌توانید به‌صورت زیر آن‬
‫را دانلود و نصب کنید‪.‬‬
‫‪;RHEL‬‬
‫‪#wget http://www.digip.org/jansson/releases/jansson-2.4.tar.gz‬‬
‫‪#tar -zxf jansson-2.4.tar.gz‬‬
‫‪#cd jansson-2.4/‬‬
‫‪#./configure --prefix=/usr/ && make clean && make && make install‬‬

‫‪;Ubuntu‬‬
‫‪#apt-get install libjansson-dev‬‬
‫‪#wget http://www.digip.org/jansson/releases/jansson-2.4.tar.gz‬‬
‫‪#tar -zxf jansson-2.4.tar.gz‬‬
‫‪#cd jansson-2.4/‬‬
‫‪#./configure --prefix=/usr/ && make clean && make && make install‬‬

‫نصب همه نیازمندی‌های استریسک‬


‫همان‌طورکــه پیش‌تر توضیح دادیم برای فعال‌شــدن برخی قابلیت‌ها در استریســک‪ ،‬ابتدا باید نیازمندی‌های‬
‫آنها را نصب کنیم‪ .‬در فصل‌های آینده در مورد انواع قابلیت‌های استریســک بیشــتر توضیح خواهیم‌داد‪ .‬اگر‬
‫خواسته‌باشیم کلیه قابلیت‌ها در استریسک را داشته باشیم‪ ،‬واضح است که باید ابتدا همه نیازمندی‌های آن را‬
‫نصب کنیم‪ .‬برای این منظور در مسیر سورس استریسک‪ ،‬دستورات زیر را اجرا کنید‪:‬‬
‫‪; RHEL‬‬
‫‪# cd /usr/src/asterisk-source/‬‬
‫‪# cd contrib/scripts/‬‬
‫‪# ./install_prereq install‬‬

‫‪;Ubuntu‬‬
‫‪# cd /usr/src/asterisk-source/‬‬
‫‪# cd contrib/scripts/‬‬
‫‪# ./install_prereq install‬‬

‫اســتفاده از این روش در این مقطع زمانی توصیه نمی‌شود و از خواننده کتاب درخواست می‌گردد که نصب‬
‫نیازمندی‌های استریسک را در زمان خودش و در فصل‌های مرتبط‪ ،‬مستقال انجام‌ دهد‪.‬‬
67 ‫نصب و راه‌اندازی استریسک‬

git ‫دانلود سورس استریسک از طریق‬


‫ را نصب و سپس‬git ‫ برای این منظور ابتدا بسته‬.‫ استریسک را دانلود کنیم‬،‫ سورس‬git ‫می‌توانیم مستقیما از طریق‬
:‫دستورات زیر را اجرا کنید‬

; RHEL
#yum install git
# mkdir -p /usr/src/asterisk
# cd /usr/src/asterisk
# git clone https://gerrit.asterisk.org/asterisk

; Ubuntu
#apt-get install git
# mkdir -p /usr/src/asterisk
# cd /usr/src/asterisk
# git clone https://gerrit.asterisk.org/asterisk

:‫ دستور زیر نمایش داده خواهد شد‬،‫بعد از اجرای موفق اسکریپت فوق‬
######################################
## install completed successfully
######################################

‫دانلود سورس استریسک‬


‫ استریسک‬13 ‫ در این مرحله نسخه‬.‫از شیوه‌های متعددی بر ای دانلود سورس استریسک می‌توان استفاده کرد‬
.‫ استفاده نمایید‬wget ‫ برای دانلود از دستور‬.‫را دانلود و نصب می‌کنیم‬
; RHEL
# yum install wget
# cd /usr/src/
# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz

;Ubuntu
# apt-get install wget
# cd /usr/src/
# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz

LibPRI ‫ و‬DAHDI ‫دانلود سورس‬


.‫ را نصب کنیم‬LibPRI ‫ و‬DAHDI ‫ باید بسته‌های‬،PSTN ‫به منظور ارتباط استریســک با شــبکه‌های مخابراتی‬
:‫ دستورات زیر را اجرا نمایید‬.‫برای این منظور نخست سورس آن‌ها را دانلود می‌کنیم‬
; RHEL
# cd /usr/src/
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 68

# wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-
complete-current.tar.gz
# wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-current.tar.gz

;Ubuntu
# cd /usr/src/
# wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-
complete-current.tar.gz
# wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-current.tar.gz

.‫ اکنون باید هر بسته به صورت مجزا نصب شود‬.‫ دانلود شد‬،‫تا اینجا بسته‌های مورد نیاز برای نصب استریسک‬
.‫ اولویت نصب بسته‌ها توضیح داده خواهد شد‬،‫در بخش بعدی‬

‫نصب استریسک‬
‫ گاهی به این نیاز‬.‫ تنها نصب استریسک از روی سورس آن کافی است‬،‫برای استفاده از سافت سوئیچ استریسک‬
‫ متصل کنیم و از فناوری‌های خطوط آنالوگ‬PSTN ‫داریم که سیســتم تلفنی استریســک را به شبکه مخابراتی‬
‫ و‬DAHDI ‫ در این حالت باید دو بســته‬.‫) اســتفاده کنیم‬E1/T1 ‫ (لینک‌های‬PRI ‫) و‬FXO/FXS ‫(لینک‌هــای‬
‫ برای این منظور اولویت نصب بسته‌ها را به صورت زیر درنظر‬.‫ را نیز همزمان با استریسک نصب کنیم‬LibPRI
:‫بگیرید‬
• DAHDI
• LibPRI
• Asterisk

‫ از حالت فشرده خارج و بعد دستورات زیر را اجرا‬tar ‫ نخست باید آن را به کمک دستور‬DAHDI‫برای نصب‏‬
:‫کنید‬
; RHEL
# cd /usr/src/
# tar –zxvf dahdi-linux-complete-current.tar.gz
# cd dahdi-linux-complete2.6.1+2.6.1/
# ./configure
#make all
# make install
# make config

:‫ از دستور زیر استفاده کنید‬./configure ‫ استفاده می‌کنید باید به جای دستور‬RHEL 64-bit ‫اگر از‬
# ./configure --libdir=/usr/lib64

;Ubuntu
# cd /usr/src/
# tar –zxvf dahdi-linux-complete-current.tar.gz
# cd dahdi-linux-complete2.6.1+2.6.1/
# make all
69 ‫نصب و راه‌اندازی استریسک‬

# make install
# make config

E1/ ‫ (خطوط‬ISDN ‫ با نصب این بسته می‌توانید از فناوری‬.‫ را نصب کنید‬LibPRI ‫ بسته‬،DAHDI ‫پس از نصب‬
LibPRI ‫ برای نصب‬.‫ استفاده کنید‬PSTN ‫) در ســافت سوئیچ استریسک برای ارتباط با شــبکه‌ی مخابراتی‬T1
:‫دستورات زیر را اجرا نمایید‬
; RHEL
# cd /usr/src/
# tar –zxvf libpri-current.tar.gz
# cd libpri/
# make
# make install

:‫ از دستور زیر استفاده کنید‬make install ‫ استفاده می‌کنید باید به‌جای دستور‬RHEL 64-bit ‫اگر از‬
# make install libdir=/usr/lib64
;Ubuntu
# cd /usr/src/
# tar –zxvf libpri-current.tar.gz
# cd libpri/
# make
# make install

‫ برای نصب استریسک دستورات زیر را‬.‫ نوبت به نصب استریســک می‌رسد‬،LibPRI ‫ و‬DAHDI ‫بعد از نصب‬
:‫اجرا کنید‬
; RHEL
# cd /usr/src/
# tar –zxvf asterisk-13-current.tar.gz
# cd asterisk13/
# ./configure
# make
# make install
# make samples
# make config

:‫ از دستور زیر استفاده کنید‬./configure ‫ استفاده می‌کنید باید به جای دستور‬RHEL 64-bit ‫اگر از‬
# ./configure --libdir=/usr/lib64

;Ubuntu
# cd /usr/src/
# tar –zxvf asterisk-13-current.tar.gz
# cd asterisk13/
# ./configure
# make
# make install
# make samples
# make config
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪70‬‬

‫معرفی دستورات نصب استریسک‬


‫دستور ‪ : . /configure‬بررسی می‌کند که آیا پیش‌نیاز‌ها نصب شده‌اند یا خیر؛ به‌طوری‌که اگر پیش‌نیازهای الزم‬
‫برای فعال شدن یک ماژول نصب شده باشند‪ ،‬آن ماژول در استریسک فعال می‌شود‪.‬‬

‫دســتور ‪ : make menuselect‬یک محیط ویزارد متنی است که برای مشاهده انواع ماژول‌های فعال و غیرفعال‬
‫در استریسک به کار می‌رود‪ .‬در این محیط ویزارد متنی می‌توان مشخص کرد که کدام ماژول‌ها در استریسک‬
‫فعال و کدام یک غیرفعال اســت‪ .‬دو محیط ویزاردی برای این دستور وجود دارد‪ :‬محیط ویزاردی سیاه و سفید‬
‫(‪ )Curses‬و محیط ویزاردی رنگی (‪ .)Newt‬دســتور ‪ make menuselect‬در حالت پیش‌فرض از محیط ویزادی‬
‫سیاه و سفید (شکل ‪ )1-3‬برای نمایش و مدیریت ماژول‌ها در استریسک استفاده می‌کند‪.‬‬
‫اگر مایلید دستور ‪ make menuselect‬از محیط ویزارد رنگی )‪ (Newt‬استفاده کند‪ ،‬باید ابتدا کتابخانهی‬
‫‪ libnewt‬در لینوکس را نصب کنید‪ .‬برای این منظور با توجه به توزیع لینوکس‪ ،‬دستور زیر را اجرا نمایید‪:‬‬
‫‪; RHEL‬‬
‫‪#yum install libnewt-devel‬‬

‫‪;Ubuntu‬‬
‫‪# apt-get install libnewt-dev‬‬

‫شکل‪1-3‬‬

‫پس از اجرای دســتور فوق‪ ،‬با اجرای دســتور ‪ ،make menuselect‬محیط ویزاردی رنگی (‪ )Newt‬نمایش داده‬
‫خواهد شد (شکل ‪.)2-3‬‬
‫‪71‬‬ ‫نصب و راه‌اندازی استریسک‬

‫شکل ‪2-3‬‬

‫همانطور که در شــکل ‪ 3-3‬مشــاهده می‌کنید‪ ،‬انواع ماژول‌ها در استریسک نمایش داده می‌شوند‪ .‬در فصل‬
‫قبل درباره انواع ماژول‌ها و کاربرد آن‌ها توضیح دادیم‪ .‬به عنوان مثال می‌توانیم ماژول ‪ app_dial‬را برای همیشه‬
‫در استریسک غیرفعال کنیم‪ .‬برای این منظور کافی است از قسمت ‪ Applications‬ماژول ‪ app_dial‬را انتخاب و‬
‫عالمت [*] را حذف کنیم‪ ،‬سپس استریسک را مجددا ً نصب کنیم‪ .‬بعد از نصب استریسک‪ ،‬ماژول فوق غیرقابل‬
‫استفاده می‌شود‪ .‬با این روش می‌توانیم ماژول‌هایی را که به آن‌ها نیاز نداریم‪ ،‬در استریسک غیرفعال کنیم‪ .‬شکل‬
‫‪ 3-3‬نحوه غیرفعال‌کردن ماژول ‪ app_dial‬را نشان می دهد‪.‬‬

‫شکل ‪3-3‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪72‬‬

‫دســتور ‪ : make‬وظیفه کامپایل کردن ســورس کدهای استریســک را برعهده دارد‪ .‬با اجرای این دستور همه‬
‫سورس ‌کد‌های استریسک و ماژول‌های آن کامپایل و فایل‌های اجرایی آن‌ها (‪ )simple object‬ایجاد می‌شود‪.‬‬

‫دستور ‪ : make install‬با اجرای این دســتور‪ ،‬همه فایل‌های اجرایی استریسک (‪ )simple object‬به مکان‌های‬
‫مورد نظر و از قبل تعیین شــده منتقل می‌شوند تا بتوانیم استریســک را اجرا کنیم‪ .‬به عنوان مثال مسیر فایل‌های‬
‫اجرایی (‪ )simple object‬در استریسک در مسیر زیر قرار دارد‪ .‬اجرای این دستور در تمامی توزیع‌های لینوکسی‬
‫یکسان است‪.‬‬
‫‪# ls /usr/lib/asterisk/modules/‬‬

‫با اجرای دســتور فوق همه ماژول‌های فعال در استریســک نمایش داده‌ می‌شوند‪ .‬در زمان اجرای استریسک‪،‬‬
‫تمامی ماژول‌های موجود در این مســیر در استریســک بارگذاری و فعال می‌شوند‪ .‬درصورت لزوم می‌توانیم‬
‫ماژول‌هایی را از این مسیر حذف یا اضافه کنیم و سپس استریسک را مجددا ً راه‌اندازی نماییم‪ .‬در این صورت‬
‫استریسک‪ ،‬آن‌ها را تشخیص می‌دهد و تغییرات اعمال می‌شوند‪.‬‬
‫دســتور ‪ : make config‬وظیفه این دستور این است که یک فایل اجرایی در مسیر ‪ /etc/init.d/asterisk‬ایجاد‬
‫کند تا بتوانیم استریسک را به‌صورت سرویس مدیریت کنیم‪ .‬همچنین این امکان وجود دارد که استریسک به‬
‫صورت سرویس در ‪ background‬اجرا شود‪.‬‬
‫}‪#/etc/init.d/asterisk {start|stop|restart|reload|condrestart|status‬‬

‫دستور ‪ : make samples‬در مسیر نمونه‪ ،‬مثال‌ها و راهنمایی‌هایی از پیکربندی استریسک وجود دارد‪:‬‬
‫‪#ls /usr/src/asterisk-13.2.0/configs/samples/‬‬

‫درخروجی دستور فوق‪ ،‬نمونه‌هایی از پیکربندی در هر بخش از استریسک وجود دارد‪ .‬با اجرای دستور ‪make‬‬
‫‪ ،samples‬یک نمونه از کل فایل‌های فوق در مسیر ‪ /etc/asterisk‬ساخته می‌شود‪ .‬در ادامه بحث و در فصل‌های‬
‫آینده مفصل راجع به هر فایل و پیکربندی آن توضیح خواهیم‌ داد‪.‬‬
‫نصب استریسک با موفقیت انجام شد‪ .‬اکنون سرویس‌ها را با یکی از روش‌های زیر اجرا می‌کنیم‪:‬‬
‫‪# service dahdi start‬‬
‫‪# service asterisk start‬‬
‫یا‬
‫‪# /etc/ini t.d/dahdi start‬‬
‫‪# /etc/init.d/asterisk start‬‬

‫بعد از اجرای استریسک می‌توان با دستور زیر وارد محیط کامند الین استریسک شد‪:‬‬
‫‪# asterisk -r‬‬
‫‪Asterisk 13.2.0, Copyright (C) 1999 - 2014, Digium, Inc. and others.‬‬
‫>‪Created by Mark Spencer <markster@digium.com‬‬
‫‪Asterisk comes with ABSOLUTELY NO WARRANTY; type ‹core show warranty› for details.‬‬
‫‪This is free software, with components licensed under the GNU General Public‬‬
‫‪73‬‬ ‫نصب و راه‌اندازی استریسک‬

‫‪License version 2 and other licenses; you are welcome to redistribute it under‬‬
‫‪certain conditions. Type ‹core show license› for details.‬‬
‫================================================================‬
‫)‪Connected to Asterisk 13.2.0 currently running on Asterisk (pid = 19801‬‬
‫>‪Asterisk*CLI‬‬

‫همان‌طورکه مالحظه می‌کنید نسخه نصب شده استریسک تحت الیسنس ‪ GNU‬نشان داده شده است‪ .‬آنچه که‬
‫ما تا اینجا در باره آن توضیح دادیم‪ ،‬نصب استریسک و نیازمندی‌های آن بود‪ .‬همچنین برای ارتباط استریسک‬
‫با شــبکه‌های مخابراتی ‪ ،PSTN‬بســته‌های ‪ DAHDI‬و ‪ LibPRI‬را نیز نصب کردیم‪ .‬در ادامه بحث به پیکر‌بندی‬
‫مقدماتی استریسک و آشنایی با فایل‌سیستم‌ها در استریسک می‌پردازیم‪.‬‬

‫‪1‬‬
‫پیکربندی اولیه استریسک‬
‫برای پیکربندی سیستم تلفنی استریسک‪ ،‬نخست الزم است با ساختار فایل‌سیستم در استریسک‪ 2‬آشنا شوید‪.‬‬
‫استریسک برای کنترل و پیکربندی بخش‌های مختلف خود‪ ،‬از فایل‌های پیکربندی متعددی استفاده می‌کند که‬
‫همه آنها در مسیر ‪ /etc/asterisk/‬و با پسوند ‪ conf‬قرار دارند‪ .‬دستور زیر انواع فایل‌های پیکربندی در استریسک‬
‫را نشان می‌دهد‪.‬‬
‫‪#ls –lh /etc/asterisk‬‬

‫در ادامه به معرفی اصلی‌ترین فایل‌های پیکربندی در استریسک می‌پردازیم‪.‬‬

‫فایل پیکربندی ‪asterisk.conf‬‬


‫این فایل از بخش‌های گوناگونی تشکیل شده‌است که در ادامه به مهمترین آنها خواهیم پرداخت‪.‬‬
‫ابتدا از مسیر ‪ /etc/asterisk‬فایل ‪ asterisk.conf‬را با یک ویرایشگر باز کنید‪ .‬دراین فایل بخش‌های مختلفی‬
‫را مشاهده می‌کنید که هر بخش با عالمت [ ] شروع می‌شود‪.‬‬
‫‪# vim /etc/asterisk/asterisk.conf‬‬

‫بخش [‪]directories‬‬
‫استریســک در هنگام نصب‪ ،‬فایلهای اجرایی (‪ )Simple Object‬را می‌سازد و در مسیرهایی ذخیره می‌کند‪ .‬در‬
‫زیر مسیر پیکربندی فایل سیستم استریسک‪ ،‬نشان داده شده‌است‪.‬‬
‫)!( ]‪[directories‬‬
‫‪astetcdir => /etc/asterisk‬‬
‫‪astmoddir => /usr/lib/asterisk/modules‬‬
‫‪astvarlibdir => /var/lib/asterisk‬‬
‫‪astdbdir => /var/lib/asterisk‬‬
‫‪astkeydir => /var/lib/asterisk‬‬

‫‪1- Basic Asterisk Configuration‬‬


‫‪2- Asterisk File System‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪74‬‬

‫‪astdatadir => /var/lib/asterisk‬‬


‫‪astagidir => /var/lib/asterisk/agi-bin‬‬
‫‪astspooldir => /var/spool/asterisk‬‬
‫‪astrundir => /var/run/asterisk‬‬
‫‪astlogdir => /var/log/asterisk‬‬
‫‪astsbindir => /usr/sbin‬‬

‫ذکر این نکته مهم است که می‌توان همزمان چند نسخه از استریسک را روی یک سیستم نصب کرد‪ .‬برای این‬
‫کار ابتدا مسیرهای پیش فرض قسمت [‪ ]directories‬را تغییر دهید و مسیر جدید را مشخص کنید‪.‬‬
‫بخش [‪]options‬‬
‫هنگام اجرای استریسک می‌توان از یک سری آپشن‌ها استفاده کرد که هر کدام یکی از قابلیت‌های استریسک‬
‫را در زمان اجرا شدن فعال می‌کند‪ .‬فهرست برخی از این آپشن‌ها از قرار زیر است‪:‬‬

‫‪ : asterisk -c‬در ایــن حالت استریســک به‌صورت ‪ foreground‬اجرا می‌شــود؛ یعنی تــا زمانی‌که کامند الین‬
‫استریسک فعال باشد‪ ،‬استریسک هم فعال است و در صورت خارج شدن از آن‪ ،‬استریسک متوقف می‌شود‪ .‬در‬
‫این حالت استریسک به صورت یک برنامه (نه سرویس) اجرا می‌شود‪.‬‬

‫‪ : asterisk -r‬در این حالت استریســک در ‪ background‬فعال است و به‌صورت سرویس کار می‌کند‪ .‬در این‬
‫روش به محیط کامند الین استریسک متصل می‌شویم‪.‬‬

‫‪ : asterisk -v‬عالمت ‪ v‬درجه گزارش‌دهی (‪ )verbose‬در کامند الین استریســک را مشــخص می‌کند‪ .‬هرچه‬
‫تعداد بیشتری ‪ v‬بگذاریم‪ ،‬جزئیات بیشتری در محیط کامند الین استریسک نمایش داده می‌شود‪.‬‬

‫‪ : asterisk -x‬گاهی نیاز داریم بدون وارد شــدن به محیط کامند الین استریسک‪ ،‬دستوراتی را در استریسک‬
‫اجرا کنیم‪ .‬در این حالت از این فرمان استفاده می‌کنیم‪ .‬برای مثال فرض کنید قصد داریم ورژن استریسک را‬
‫نشان دهیم‪ .‬در این صورت دستور زیر را اجرا می‌کنیم‪:‬‬
‫'‪# asterisk -x 'core show version‬‬
‫‪Asterisk 13.2.0 built by root @ ubuntu on a x86_64 running Linux on 2016-05-08 15:19:40‬‬
‫‪UTC‬‬

‫‪ :safe_asterisk‬در زمان نصب استریســک‪ ،‬اســکریپتی به‌نام ‪ safe_asterisk‬ایجاد می‌شــود‪ .‬این اســکریپت‬
‫دائماً وضعیت استریســک را بررسی می‌کند‪ .‬در صورتی که در استریسک خطایی رخ دهد که به از کار افتادن‬
‫استریسک منتهی شــود‪ ،‬بالفاصله استریســک را مجددا ً راه‌اندازی و اطالع‌رسانی می‌کند‪ .‬همچنین این قابلیت‬
‫وجود دارد که عاملی که باعث شده استریسک از کار بیفتد را در مسیر فایل ‪ /tmp/‬ذخیره کند‪.‬‬
‫آنچه در این قسمت از فایل ‪ asterisk.conf‬مهم است‪ ،‬این است که استریسک می‌تواند در سطوح مختلفی‪،‬‬
‫گزارش‌هایی را در صفحه‌ی کامند الین خودش یا در مسیر فایل‌های ‪ Log‬استریسک تولید و نمایش دهد‪ .‬برای‬
‫‪75‬‬ ‫نصب و راه‌اندازی استریسک‬

‫مثال وقتی استریسک را نصب می‌کنیم و سپس وارد محیط کامند الین استریسک می‌شویم‪ ،‬ممکن است هیچ‬
‫‪ log‬و گزارشی نشان داده‌نشود‪.‬‬
‫گزارش‌ها در استریسک در دو بخش ‪ verbose‬و ‪ debug‬تقسیم می‌شوند‪ .‬می‌توان با دستورات زیر‪ ،‬سطح‬
‫این دو بخش را تعیین نمود‪:‬‬
‫‪# asterisk -r‬‬
‫)‪Connected to Asterisk 13.2.0 currently running on simulate1 (pid = 1635‬‬
‫‪simulate1*CLI> core set verbose 3‬‬

‫در این دستور‪ ،‬سطح گزارش‌های مربوط به ‪ verbose‬را روی ‪ 3‬تنظیم می‌کنیم‪.‬‬
‫‪# asterisk –rvvv‬‬

‫همان‌طورکه مشاهده می‌کنید با اضافه‌کردن هر ‪ ، v‬سطح گزارش‌ها‪ ،‬یکی باال می‌رود‪ .‬در نتیجه گزارش‌های‬
‫بیشتری در محیط کامندالین استریسک نمایش داده می‌شود‪.‬‬
‫اگر در بخش [‪ ]option‬در فایل ‪ ، asterisk.conf‬پارامترهای ‪ verbose‬و ‪ debug‬را فعال و سپس استریسک‬
‫را ‪ reload‬کنید‪ ،‬از آن به بعد‪ ،‬ســطح گزارش‌های این دو بخش پیش فرض به ‪ ‌level‬هایی که تنظیم کرده‌اید‪،‬‬
‫تغییر می‌یابد‪ .‬برای مثال فرض کنید این پارامترها را به صورت زیر تنظیم کرده باشیم‪:‬‬
‫‪#vim /etc/asterisk/asterisk.conf‬‬
‫]‪[options‬‬
‫‪verbose = 3‬‬
‫‪debug = 3‬‬

‫از جمله پارمترهای مهم دیگر در این بخش‪ ،‬پارامتر ‪ maxcall‬و ‪ maxfile‬و ‪ maxload‬است‪ .‬این سه پارامتر در‬
‫واقع پارامتر‌های کنترلی و مدیریت تماس‌ها در استریسک‌اند‪.‬‬
‫پرسشی که ممکن است در اینجا به ذهن خطور کند این است که این پارامترها‪ ،‬چه زمانی ممکن است مورد‬
‫استفاده قرار گیرند؟ پاسخ به این سوال مستلزم آن است که خواننده بیشتر با استریسک آشنا باشد و نقاط ضعف‬
‫و قوت آن را بخوبی بشناسد‪ .‬اما اگر بخواهیم به یک پاسخ ساده‌ اکتفا کنیم‪ ،‬پاسخ این است که اگر استریسک‬
‫استرس قرار دهیم تا تمام منابع سخت‌افزاری در دسترسش مصرف شود‪ ،‬در چنین شرایطی‬‫ِ‬ ‫را در شــرایط تست‬
‫استریســک کنترل خود را در ایجاد و مدیریت تماس‌ها (‪ session‬ها) از دســت می‌دهد؛ چون منابع کافی برای‬
‫مدیریت آن‌ها ندارد‪ .‬بنابراین برای اینکه از چنین شــرایط بحرانی‌ای در استریسک جلوگیری کنیم‪ ،‬می‌توانیم با‬
‫توجه به منابع ســخت‌افزاری و انجام تســت‌های استرس‪ ، 1‬حد نرمال را برای استریسک پیدا و پارامتر‌های آن را‬
‫تنظیم نماییم‪.‬‬
‫در فصــل نوزدهم (بررســی و ارزیابی عملکرد سیســتم‌های تلفنــی ‪ IP/PBX‬و تجهیزات وابســته) با انجام‬
‫سناریوهای‌ تست استرس آشنایی بیشتری پیدا خواهید کرد‪.‬‬
‫برای مشاهده و تخصیص منابع سخت‌افزاری موجود به سرویس استریسک‪ ،‬از دستور زیر استفاده کنید‪.‬‬

‫‪1- Test Stress‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪76‬‬

‫‪#cat /proc/`pidof asterisk`/limits‬‬


‫ ‪Limit‬‬ ‫‪Soft Limit‬‬ ‫‪Hard Limit‬‬ ‫‪Units‬‬
‫ ‪Max cpu time‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪seconds‬‬
‫ ‪Max file size‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max data size‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max stack size‬‬ ‫ ‪8388608‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max core file size‬‬ ‫ ‪0‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max resident set‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max processes‬‬ ‫ ‪120131‬‬ ‫‪120131‬‬ ‫‪processes‬‬
‫ ‪Max open files‬‬ ‫ ‪1024‬‬ ‫ ‪4096‬‬ ‫‪files‬‬
‫ ‪Max locked memory‬‬ ‫ ‪65536‬‬ ‫ ‪65536‬‬ ‫‪bytes‬‬
‫ ‪Max address space‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪bytes‬‬
‫ ‪Max file locks‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪locks‬‬
‫ ‪Max pending signals‬‬ ‫ ‪120131‬‬ ‫ ‪120131‬‬ ‫‪signals‬‬
‫ ‪Max msgqueue size‬‬ ‫ ‪819200‬‬ ‫ ‪819200‬‬ ‫‪bytes‬‬
‫‪Max nice priority 0 0‬‬
‫ ‪Max realtime priority‬‬ ‫ ‪0‬‬ ‫‪0‬‬
‫ ‪Max realtime timeout‬‬ ‫‪unlimited‬‬ ‫‪unlimited‬‬ ‫‪us‬‬

‫خروجی دستور فوق نشان می‌دهد که سرویس استریسک تا چه اندازه می‌تواند از منابع سخت‌افزاری سیستم‬
‫اســتفاده کنــد و اینکه آیا محدودیتی در اســتفاده از منابع دارد یــا خیر‪ .‬برای مثال در خروجی دســتور باال‪،‬‬
‫استریسک می‌تواند ماکزیمم تا ‪ 1024‬فایل همزمان را باز‌ کند ولی بیشتر از آن با محدودیت مواجه می‌شود‪.‬‬
‫سوالی که ممکن است در اینجا پیش آید این است که منظور از ‪ max open files‬چیست؟ بگذارید سوال‬
‫را به شــکل دیگری مطرح کنیم‪ .‬ممکن است در شــرایطی ما هیچ محدودیتی در استفاده از منابع سخت‌افزاری‬
‫نداشته‌باشیم ولی باز هم نتوانیم حداکثر استفاده از منابع سخت‌افزاری را در سرور داشته باشیم‪ .‬در چنین شرایطی‬
‫اگر به ‪‌log‬های استریسک مراجعه کنیم متوجه خطاهایی به شکل زیر می‌شویم‪:‬‬
‫‪[2016-05-08 13:33:03] ERROR [10723] acl.c: Cannot create socket‬‬
‫‪[2016-05-08 13:33:03] ERROR[10723] rtp.c: Unable to allocate socket: Too many open files‬‬
‫‪[2016-05-08 13:33:03] ERROR [10723]: create_new_socket: Unable to allocate RTP socket:‬‬
‫‪Too many open files‬‬
‫‪10723 [2016-05-08 13:33:03] WARNING[657] chan_sip.c: Unable to create RTP audio and‬‬
‫‪video session: Too many open file‬‬

‫همان‌طورکه مالحظه می‌کنید استریسک نمی‌تواند فایل‌های بیشتری را باز کند‪ .‬اکنون این سوال پیش می‌آید‬
‫که استریســک در چه مواقعی این فایل‌ها را باز می‌کند‪ .‬پاســخ این ســوال روشن اســت‪ .‬استریسک برای هر‬
‫مکالمه صوتی ‪ 5‬فایل (یا پورت) در نظر می‌گیرد‪.‬‬
‫)‪maxfiles=(active calls)*(2+2+1‬‬

‫استریسک در هر مکالمه صوتی‪ 2 ،‬پورت فعال برای ‪ RTP‬و ‪ 2‬پورت فعال برای کنترل جریان ترافیکی ‪RTCP‬‬
‫و یک پورت اضافی برای ‪ overhead‬در نظر می‌گیرد‪ .‬پس برای مثال اگر بخواهیم روی ســروری ‪ 300‬تماس‬
‫‪77‬‬ ‫نصب و راه‌اندازی استریسک‬

‫همزمان داشته‌باشیم‪ ،‬باید مقدار ‪ maxfiles‬را به صورت زیر تنظیم کنیم‪:‬‬


‫‪maxfiles= 300*5=1500‬‬

‫لذا اگر مقدار پارامتر ‪( max open files=1024‬مقدار پیش فرض) باشد‪ ،‬نمی‌توانیم به حداکثر تعداد تماس مورد‬
‫نیاز در این شرایط برسیم‪ .‬ما می‌توانیم پارامتر ‪ maxcalls‬را در بخش [‪ ]options‬را به‌صورت زیر تغییر دهیم‪:‬‬
‫‪;asterisk.conf‬‬
‫]‪[options‬‬
‫‪maxcalls = 10‬‬

‫یکی دیگر از پارامترهای مهم در بخش [‪ ،]options‬پارامتر ‪ execincludes‬اســت که می‌تواند مفید باشــد‪ .‬برای‬
‫مثال فرض کنید بخواهیم تعداد زیادی کاربر در سیستم تلفنی استریسک ایجاد کنیم‪ .‬در این حالت می‌توانیم از‬
‫این قابلیت در استریســک بهره ببریم‪ .‬برای مثال فرض کنید برنامه‌ی ‪ 1 bash script‬به صورت زیر برای تعریف‬
‫‪ 1000‬کاربر داشته‌باشیم‪.‬‬
‫‪#vim create_users.sh‬‬
‫‪#!/bin/bash‬‬
‫")!(]‪echo "[user‬‬
‫"‪echo "deny = 0.0.0.0/0.0.0.0‬‬
‫"‪echo "permit = 0.0.0.0/0.0.0.0‬‬
‫"‪echo "qualify = yes‬‬
‫"‪echo "host = dynamic‬‬
‫"‪echo "nat = force_rport,comedia‬‬
‫"‪echo "port = 5060‬‬
‫"‪echo "type = friend‬‬
‫"‪echo "context = tci‬‬
‫"‪echo "disallow = all‬‬
‫"‪echo "allow = ulaw,alaw‬‬
‫"‪echo "canreinvite = no‬‬
‫"‪echo "directmedia = no‬‬
‫}‪for i in {1000..1010‬‬
‫‪do‬‬
‫")‪echo "[$i](user‬‬
‫"‪echo "secret=123123‬‬
‫‪done‬‬

‫اکنون پارامتر ‪ execincludes‬را در استریسک به‌صورت زیر تنظیم کنید‪.‬‬


‫‪;asterisk.conf‬‬
‫]‪[options‬‬
‫‪execincludes=yes‬‬

‫حال در انتهای فایل ‪ sip.conf‬باید این تغییرات را انجام دهید‪.‬‬


‫‪;sip.conf‬‬
‫‪#exec bash create_users.sh‬‬

‫از متدوال ترین و رایج ترین روش‌های برنامه نویسی در لینوکس است‪.‬‬ ‫‪bash script‬‬ ‫‪-1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪78‬‬

‫اکنون با ‪ realod‬شدن استریسک‪ ،‬فایل ‪ create_users.sh‬اجرا می‌شود و خروجی آن در انتهای فایل ‪sip.conf‬‬
‫قرار می‌گیرد‪ .‬با این روش شما می‌توانید به‌راحتی تعداد زیادی کاربر در استریسک ایجاد کنید‪ .‬این روش تنها‬
‫برای ایجاد کاربر مفید نیست بلکه می‌توانید با استفاده از این روش تمام پیکربندی استریسک را انجام دهید‪.‬‬

‫فایل پیکربندی ماژول ها در استریسک ‪modules.conf‬‬


‫استریســک به‌صورت پیش‌فرض تنها از هسته اولیه (‪ )core‬تشکیل شده‌است و کلیه قابلیت‌های آن به صورت‬
‫ماژوالر تعریف می‌شــود‪ .‬هنگام اجراشــدن استریســک‪ ،‬این ماژول‌ها اضافه (‪ )load‬و یــا حذف (‪ )unload‬‬
‫می‌شوند‪ .‬فایل کنترل‌کننده و تنظیمات ماژول‌ها در استریسک ‪ modules.conf‬نام دارد که با این فایل می‌توان‬
‫کنترل ماژول‌های مورد نیاز را در اختیار داشــت‪ .‬به عنوان مثال‪ ،‬چه ماژول‌هایی باید فعال و یا چه ماژول‌هایی‬
‫غیر فعال باشند‪ .‬به این منظور دستور زیر را اجرا کنید‪:‬‬
‫‪#vim /etc/asterisk/modules.conf‬‬

‫در این فایل کلمات کلیدی‌ای وجود دارد که هر کدام معنای خاص خودش را دارد‪ .‬در ادامه به معرفی این‬
‫کلمات کلیدی می‌پردازیم‪.‬‬
‫‪ : autoload‬همه ماژول‌هایی که در مسیر نصب ماژول‌های استریسک وجود دارند (‪ )/var/lib/asterisk/modules‬‬
‫به ترتیب بارگذاری می‌شوند‪.‬‬
‫]‪[modules‬‬
‫‪autoload=yes‬‬

‫‪ : preload‬گاهی ممکن اســت بارگذاری برخی ماژول‌ها وابســته به بارگذاری ماژول‌های دیگری باشد که نیاز‬
‫است این ماژول‌ها را قبال به سیستم معرفی کنیم‪ .‬با این دستور می‌توان این معرفی را انجام داد‪.‬‬
‫]‪[modules‬‬
‫‪preload => chan_sip.so‬‬

‫‪ : load‬دستور بارگذاری ماژول مربوطه را صادر می‌کند‪ )autoload=yes( .‬همین کار را برای همه ماژول ها انجام‬
‫می‌دهد‪.‬‬
‫]‪[modules‬‬
‫‪load => chan_sip.so‬‬

‫‪ : noload‬اجازه نمی‌دهد ماژول بارگذاری شود و در صورت بارگذاری‪ ،‬آن را غیر فعال می‌کند‪.‬‬
‫]‪[modules‬‬
‫‪noload => chan_sip.so‬‬

‫‪ : require‬در چنین شــرایطی اگر ماژولی بنا به دالیلی بارگذاری نشود‪ ،‬استریسک راه‌اندازی نخواهد شد‪ .‬برای‬
‫مثال فرض کنید بخواهیم چنانچه ماژول ‪ chan_sip.so‬در استریســک بارگذاری نشد‪ ،‬استریسک هم راه‌اندازی‬
‫نشود‪ .‬در این‌ صورت باید ماژول ‪ chan_sip.so‬را به صورت زیر فعال کنیم‪.‬‬
‫]‪[modules‬‬
‫‪require => chan_sip.so‬‬
‫‪79‬‬ ‫نصب و راه‌اندازی استریسک‬

‫فایل پیکربندی ‪indications.conf‬‬


‫معموالً هر سیستم تلفنی‪ ،‬برای تولید ‪ tonezone‬ها از الگو‌های متفاوتی استفاده می‌کند‪ .‬این الگوها معموال در‬
‫کشورهای مختلف با هم تفاوت دارند‪ .‬از جمله مهمترین این ‪ tone‬ها می‌توان به موارد زیر اشاره کرد‪:‬‬
‫‪• dial tone‬‬
‫‪• busy tone‬‬
‫‪• congestion tone‬‬
‫‪• callwaiting tone‬‬
‫‪• dialrecall tone‬‬

‫برای هر کدام از این ‌‪tone‬ها‪ ،‬می‌توان الگویی تعریف کرد و در سیســتم تلفنی استریســک به‌کار گرفت‪ .‬برای‬
‫مثال در فایل ‪ indications.conf‬الگو‌های متفاوتی برای این پارامترها بر اساس کشورهای مختلف تعریف شده‬
‫است‪ .‬با دستور زیر این فایل را باز نمایید‪:‬‬
‫‪#vim /etc/asterisk/indications.conf‬‬

‫به صورت پیش فرض در استریســک‪ ،‬این الگوها بر اســاس کشور‏‪ US‬تعریف شــده‌اند ولی می‌توانید در فایل‬
‫‪ indications.conf‬از قسمت [‪ ]general‬آن را تغییر دهید‪.‬‬
‫]‪[general‬‬
‫‪country=us‬‬

‫این تغییر روی کل سیستم اعمال می‌شود‪ .‬گاهی الزم می‌شود سوئیچی طراحی کنید که براساس کالر آی دی‪،‬‬
‫‪ tonezone‬را عوض کند‪ .‬در این حالت باید از تابع ‪ CHANNEL‬در برنامه‌نویسی استریسک استفاده‌کنید‪.‬‬
‫‪Same => n,Set(CHANNEL(tonezone)=[yourcountry]) ; i.e., uk, de, etc.‬‬

‫در فصل‌های آینده درباره برنامه‌نویسی در استریسک به تفصیل توضیح داده می‌شود‪.‬‬
‫به عنوان یک نمونه جالب فرض کنید خواسته باشیم از آهنگ خاصی برای ‪ ringtone‬در سیستم تلفنی خود‬
‫اســتفاده نماییم (در این مثال از آهنگ زیبای “‪ ”starwars‬اســتفاده می‌کنیم )‪ .‬در این صورت نخست باید یک‬
‫بخش جدید به نام [‪ ]starwars‬ایجاد و سپس آن را به‌صورت زیر تعریف کنیم‪:‬‬
‫‪[starwars](us) description = Star Wars Theme Song‬‬
‫‪ring = 262/400,392/500,0/100,349/400,330/400,294/400,524/400,392/500,0/100, 349/400,3‬‬
‫‪30/400,294/400,524/400,392/500,0/100,349/400,330/400,349/400, 294/500,0/2000‬‬

‫اکنون فرض کنید بخواهیم از این آهنگ در برنامه خود در استریســک اســتفاده کنیم‪ .‬یک نمونه از این نوع‬
‫برنامه‌نویسی در استریسک می‌تواند به‌صورت زیر باشد‪:‬‬
‫)(‪exten => 1234,1,Answer‬‬
‫)‪same => n,Set(CHANNEL(tonezone)=starwars‬‬
‫)‪same => n,Dial(SIP/Phone1‬‬

‫فایل پیکربندی ‪musiconhold.conf‬‬


‫در مواقعــی گاهی نیاز داریم که کاربران یا مشــتریان را در حالت انتظــار و به صورت ‪ Hold‬نگه داریم؛ در این‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪80‬‬

‫حالت برای آنها موزیک خاصی پخش می‌شــود‪ .‬در استریســک به‌منظور پیکربندی موزیــک انتظار‪ ،‬از فایل‬
‫‪ musiconhold.conf‬استفاده می‌کنیم‪ .‬برای باز کردن این فایل دستور زیر را اجرا کنید‪:‬‬
‫‪#vim /etc/asterisk/musiconhold.conf‬‬

‫با اجرای دستور فوق‪ ،‬محتویات پیکربندی فایل موزیک انتظار را مشاهده می‌کنید‪ .‬می‌توان از موزیک انتظارهای‬
‫متفاوتی در استریسک استفاده نمود‪ .‬به عنوان مثال در این فایل یک موزیک انتظار پیش فرض به نام [‪]default‬‬
‫تعریف شده‌است‪ .‬می‌توانید هر نوع موزیک انتظاری با نام دلخواه را در این فایل ایجاد کنید‪ .‬در مثال زیر یک‬
‫موزیک انتظار با نام [‪ ]myfavorite‬ایجاد می‌کنیم‪.‬‬
‫]‪[myfavorite‬‬
‫‪mode=files‬‬
‫‪sort=alpha‬‬
‫‪announcement=queue-thankyou‬‬
‫‪directory=/usr/src/myfavorite/‬‬

‫در زمــان تعریف یــک موزیک انتظار‪ ،‬عالوه بر نام دلخــواه باید پارامترهایی را نیــز مقداردهی کنید‪ .‬انواع‬
‫پارامترهای مورد نظر از قرار زیرند‪:‬‬

‫‪ : mode‬با این پارامتر مشخص می‌کنیم که موزیک انتظار قرار است از طریق فایل سیستم انتخاب و سپس اجرا‬
‫شــود‪ .‬در این حالت مقدار پارامتر‪ files ،‬خواهد‌ بود‪ .‬همچنین می‌توان از برنامه‌های پخش زنده (‪ )stream‬در‬
‫موزیک انتظار استفاده نمود؛ مثال برنامه‌هایی که رادیو را به‌صورت زنده پخش می‌کنند‪ .‬در این حالت باید مقدار‬
‫این پارامتر را روی ‪ custom‬قرار دهید‪.‬‬

‫‪ : directory‬در صورتی که پارامتر ‪ mode = files‬تنظیم کرده ‌باشیم‪ ،‬باید مسیر فایل‌های صوتی که قرار است‬
‫پخش شــوند را مشخص کنیم‪ .‬به‌صورت پیش فرض مسیر فایل‌های صوتی برای موزیک انتظار به صورت زیر‬
‫است‪:‬‬
‫‪# ls /var/lib/asterisk/moh/‬‬

‫می‌توانید در هر مسیری از فایل سیستم لینوکس‪ ،‬فایل‌های صوتی خود را قرار دهید و آدرس آن‌ها را در این‬
‫پارامتر درج کنید‪ .‬در مثال فوق ما از مسیر دیگری برای پخش فایل‌های صوتی استفاده نمودیم‪.‬‬

‫‪ : announcement‬می‌توان بین موزیک انتظارها یک اعالن برای مشترک پخش نمود‪ .‬این اعالن با این پارامتر‬
‫مشخص می‌شود‪ .‬در مثال فوق بین هر موزیک انتظار‪ ،‬اعالن «‪ »queue-thankyou‬پخش می‌شود‪.‬‬

‫‪ : sort‬توسط این پارامتر موزیک انتظارها به ترتیب حروف الفبا پخش می‌شوند‪.‬‬

‫‪ : application‬درصورتی‌که پارامتر ‪ mode=custom‬تنظیم شــده باشد‪ ،‬می‌توان نام برنامه‌ی پخش ‪ stream‬را‬
‫در اینجا عنوان نمود‪ .‬برای مثال فرض کنید برنامه‌ای به نام ‪ streamplayer‬وجود دارد‪ ،‬تنظیمات به‌صورت زیر‬
‫‪81‬‬ ‫نصب و راه‌اندازی استریسک‬

‫خواهد بود‪:‬‬
‫‪application=/usr/bin/streamplayer 172.16.0.100 888‬‬

‫در این حالت به‌جای پخش موزیک از فایل‪ ،‬برنامه اجرا و جریان‌های ‪ stream‬پخش می‌شوند‪.‬‬

‫‪ : format‬اگر از اســتریم‌های آنالین استفاده کنیم (‪ ،)mode=custom‬باید نوع فرمت استریم دریافتی را برای‬
‫استریسک مشخص کنیم‪.‬‬
‫‪format=ulaw,alaw‬‬

‫نتیجه‌گیری‬
‫در این فصل نصب استریسک و نیازمندی‌های آن توضیح داده شد‪ .‬همچنین برای ارتباط استریسک با شبکه‌های‬
‫مخابراتی ‪ ،PSTN‬بسته‌های ‪ DAHDI‬و ‪ LibPRI‬نیز نصب شدند‪ .‬در ادامه در خصوص پیکربندی اولیه استریسک‬
‫و آشــنایی با فایل‌های مهم در استریســک صحبت شــد‪ .‬در فصل‌های بعدی روی قابلیت‌ها و انواع ماژول‌های‬
‫استریسک تمرکز می‌کنیم و پیرامون برنامه‌نویسی در استریسک توضیح خواهیم داد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪82‬‬
‫فصل چهارم‬

‫پیکربندی تجهیزات در‬


‫شبکه‌های ویپ‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪84‬‬

‫مقدمه‬
‫در یک شــبکه‌ی ویپ‪ ،‬تجهیزاتی وجود دارد که هر یک به نحوی باید با سیســتم تلفنی استریسک در تعامل‬
‫باشــد و کار کنــد‪ .‬در این فصل بیشــتر روی نحــوه ارتباط با این نــوع از تجهیزات و ارتباط آنها با سیســتم‬
‫تلفنی استریســک تمرکز خواهیم داشــت‪« .‬ارتباط» در اینجا به این معنی اســت که چگونــه تجهیزات تلفنی‬
‫باید درخواســت خود را برای استریســک ارســال کنند و استریســک چگونه باید آن را پــردازش کند و به‬
‫درخواست‌ها پاسخ دهد‪.‬‬

‫مراحل ایجاد یک تماس در استریسک‬


‫وقتی یک تماس جدید ایجاد می‌شود‪ ،‬در واقع دو فرآیند مستقل روی می‌دهد‪.‬‬
‫‪ )1‬فرآیند ایجاد تولید تماس بوســیله تجهیزات (مثل تلفن) و ارســال آن برای سیستم تلفنی استریسک‪ .‬شکل‬
‫‪ 1-4‬این فرآیند را نشان می‌دهد‪.‬‬

‫شکل ‪1-4‬‬
‫‪ )2‬فرآیند انتقال تماس ازطریق سیستم تلفنی استریسک به تلفن مقصد‪ .‬شکل ‪ 2-4‬این فرآیند را نشان می‌دهد‪.‬‬
‫‪85‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫شکل ‪2-4‬‬

‫این فرآیندها به کمک پروتکل ســیگنالینگ‌‪ 1 SIP‬مدیریت و کنترل می‌شــود‪ .‬پروتکل ‪ SIP‬یک پروتکل در‬
‫الیه‌ی کاربردی‪ 2‬مدل ‪ OSI‬در شــبکه اســت که فرآیندهای تولید‪ ،3‬کنترل‪ ،‬مدیریــت‪ 4‬و خاتمه‌ی تماس‌ها‪ 5‬را‬
‫به‌عهده دارد‪.‬‬
‫برای مثال شکل ‪ 3-4‬فرایند ایجاد تماس در پروتکل ‪ SIP‬بین دو کالینت (‪ 6)UA‬را نشان می‌دهد‪.‬‬

‫شکل ‪3-4‬‬

‫مطابق شکل ‪ 3-4‬مراحل ایجاد یک تماس جدید به صورت زیر است‪.‬‬


‫‪ -1‬ابتدا کاربر ‪ SIPPhoneA‬با ارســال پیام ‪ ،INVITE‬درخواســت خود را برای سیستم تلفنی استریسک ارسال‬
‫می‌کند‪.‬‬
‫‪1- Session Initiation Protocol‬‬
‫‪2- Application Layer‬‬
‫‪3- Call Setup‬‬
‫‪4- Management & Control Calls‬‬
‫‪5- Teardown‬‬
‫‪6- User Agent‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪86‬‬

‫‪ -2‬سیستم تلفنی استریسک درخواست وارد شده را اعتبارسنجی می‌کند‪.‬‬


‫‪ -3‬کاربر ‪ SIPPhoneA‬در ارسال مجدد پیام ‪ ، INVITE‬اطالعات کاربری خود را نیز ارسال می‌کند‪.‬‬
‫‪ -4‬سیســتم تلفنی استریسک بعد از بررسی اطالعات و تایید آن‪ ،‬پیام ‪ 100Trying‬را برای کاربر ‪SIPPhoneA‬‬
‫ارسال می‌کند تا به کاربر اطالع دهد پیام شما با موفقیت دریافت شده است و منتظر پاسخ بماند‪.‬‬
‫‪ -5‬سیستم تلفنی استریسک پیام ‪ INVITE‬را به سمت کاربر مقصد ‪ SIPPhoneB‬ارسال می‌کند‪.‬‬
‫‪ -6‬با ارسال پیام ‪ ،180Ringing‬پیام زنگ خوردن به کاربر ‪ SIPPhoneA‬منتقل می‌شود‪.‬‬
‫‪ -7‬با برداشته‌شــدن گوشی بوسیله ‪ ، SIPPhoneB‬پیام ‪ 200OK‬به سمت ‪ SIPPhoneA‬رسیده و تماس دو طرفه‬
‫ایجاد می‌گردد‪.‬‬
‫‪ -8‬بــا برقــرای تماس دو طرفه‪ ،‬دو کاربر با اســتفاده از پروتکل ‪ ،1 RTP‬با هم ارتبــاط صوتی و تصویری برقرار‬
‫می‌کنند‪.‬‬

‫‪2‬‬
‫مفاهیم نام‌گذاری تلفن‌ها در شبکه‌های ویپ‬
‫در مخابرات امروزی‪ ،‬تلفن‌ها را معموالً با نام شماره آنها‪ 3‬معرفی می‌کنیم؛ به این معنی که هر شماره‌ای که به‬
‫یک مشترک اختصاص دارد و به عنوان یک عضو واحد و منحصر به فرد در شبکه مخابراتی معرفی می‌گردد‪.‬‬
‫اما در شــبکه‌های ویپ این مفهوم بســیار فراتر است‪ .‬برای مثال یک اکستنشن می‌تواند یک شماره اختصاص‬
‫داده شــده به یک مشترک باشــد‪ ،‬یا می‌تواند به عنوان بخشی از عملیات محاســباتی برای اجرای یک برنامه‬
‫در استریسک باشد‪ .‬همچنین می‌تواند بخشی از اجرای یک برنامه کاربردی همچون صندوق صوتی باشد‪.‬‬
‫برای روشن‌تر شدن مطلب اجازه دهید با یک مثال ساده‪ ،‬قواعد نامگذاری را شرح دهیم‪ .‬همه‌ی ما می‌دانیم‬
‫که ‪ Numbering‬در شبکه‌های مخابراتی ‪ ،PSTN‬به شماره مشتریان مخابرات اطالق می‌گردد‪ .‬به عبارت دیگر‪،‬‬
‫هر شماره ‪ 8‬رقمی که در سیستم مخابراتی تعریف شده‌باشد‪ ،‬متعلق به مشترکی است که ازطریق یک زوج سیم‬
‫به شــبکه مخابراتی کشور متصل است‪ .‬اما در شــبکه‌های مخابراتی نسل جدید‪ ،‬این موضوع فراتر از شبکه‌های‬
‫مخابراتی ‪ PSTN‬است‪ .‬ممکن است شماره‌ای را درشبکه‌های ویپ شماره‌گیری نمایید که بواسطه آن یکسری‬
‫روال محاســباتی در سیستم اجرا شود و حتی با گرفتن یک شماره‪ ،‬یک تابع فراخوانی گردد‪ .‬این شماره‌ها یا به‬
‫عبارت دیگر اکستنشــن‌ها متعلق به هیچ مشترکی در شبکه نیستند‪ ،‬بلکه با شــماره‌گیری آن‌ها (فراخوان آنها)‪،‬‬
‫فرآیندهای محاســباتی از قبل تعریف شــده‪ ،‬اجرا می‌شوند‪ .‬برای مثال سیســتم‌های پرداخت تلفنی‪ ،‬سیستم‌های‬
‫نوبت‌دهی و مانند اینها‪ ،‬همگی از جمله سرویس‌های ارزش افزوده‪ 4‬در شبکه‌های ویپ هستند‪.‬‬
‫‪1- Real Time Protocol‬‬
‫‪2- Telephony Naming Concepts‬‬
‫‪3- Extensions‬‬
‫)‪4- Value Added Services (VAS‬‬
‫‪87‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫شکل ‪ 4-4‬این سرویس‌ها را در شبکه‌های مخابراتی امروزه نشان می‌دهد‪.‬‬

‫شکل ‪4-4‬‬

‫در شــبکه‌های ویپ این قابلیت وجود دارد که بتوانیم با ‪ URL‬موجودیت‌های یکتا و منحصر به فردی ایجاد‬
‫کنیم و ســپس ازطریق این موجودیت یکتا تماس‌هایی برقرار کنیم‪ .‬این شناســه در شــبکه‌های نســل (‪ )IMS‬‬
‫جدید با عنوان ‪ IMPI1‬شــناخته می‌شود‪ .‬برای مثال کاربران در شــبکه‌های نسل جدید می‌توانند ‪ IMPI‬هایی‬
‫به‌صورت زیر داشته باشند‪.‬‬
‫‪sip:bob@domain1.com‬‬
‫‪sip:alice@domain2.com‬‬
‫‪sip:tom@domain3.com‬‬

‫توضیح بیشتر در خصوص شبکه‌های مخابراتی ‪ IMS‬از حوصله کتاب خارج است‪.‬‬

‫انواع تجهیزات تلفنی در شبکه‌های ویپ‬


‫معموالً کاربران در شبکه‌های ویپ از چهار روش به شبکه متصل می‌شوند‪.‬‬

‫‪ :Hardphones‬منظور همان ‪ IPPhone‬هایی اســت که به‌صورت مستقل و از طریق کابل شبکه به سرور ویپ‬
‫متصل می‌شوند‪ .‬شکل ‪ 5-4‬برخی از انواع گوشی‌های ‪ IPPhone‬را نشان می‌دهد‪.‬‬

‫شکل ‪5-4‬‬

‫از جمله مزایای این تجهیزات می‌توان به‌موارد زیر اشاره کرد‪:‬‬
‫‪1- IP Multimedia Private Identity‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪88‬‬

‫‪ .۱‬کلیدهای میانبر‪ :‬کلیدهای میانبر در ‪ IP Phone‬ها ‪ ،‬این امکان را بهوجود میآورند که شماری از وظایفی‬
‫کــه باید به کمک چند عدد انجام شــوند را تنها با فشــردن یــک دکمه اجرا نمود‪ .‬ازجملــه این دکمههای‬
‫میانبــر‪ ،‬میتوان به دکمههای‪ ، Transfer‬کنفرانس‪ ،‬ولوم صدا‪ Mute ، Hold ،‬و دکمههای قابل برنامهریزی‬
‫)‪ BLF (Busy Lamp Field‬اشاره کرد‪.‬‬
‫‪ .۲‬امکان نمایش و ارسال پیامهای متنی‪.‬‬
‫‪ .۳‬امکان استفاده از افزایندهها با هدف تعداد ‪ BLF‬بیشتر‪.‬‬
‫‪ Intercom‬دربعضی از ‪IP‬‬ ‫‪ .4‬امکان اســتفاده از ‪ Auto answer‬برای کاربردهای خاص‪ ،‬ازجمله ‪ paging‬و‬
‫‪ phone‬ها‪.‬‬
‫‪ .5‬این تجهیزات وابســتگی به مکان ندارند‪ .‬کافی اســت داخلی موردنظر را به مکان دیگری ببریم و از همان‬
‫داخلی در مکان جدید استفاده نماییم‪.‬‬
‫‪IP Phone .۶‬ها پایداری نسبتا باالیی دارند‪.‬‬

‫از جمله معایب این تجهیزات‪ ،‬می‌توان به موارد زیر اشاره نمود‪:‬‬
‫‪ .1‬این مدل گوشی‌ها نسبت به گوشی‌های قدیمی‌تر‪ ،‬هزینه باالتری دارند‪.‬‬
‫‪ .2‬در این مدل‪ ،‬امکان تطبیق گوشی‌های قدیمی و گوشی‌های جدید وجود ندارد‪.‬‬

‫‪ :Softphones‬منظور از ‪ Softphone‬نرم افزار‌هایی هســتند که می‌توانید آنها را در سیســتم عامل‌های مختلف از‬
‫قبیل ویندوز‪ ،‬اندروید و ‪ ...‬نصب کنید و از طریق آن‌ها به سرور شبکه ویپ متصل شوید‪ .‬تصویر ‪ 6-4‬چند نمونه‬
‫از ‪ Softphone‬ها را نشان می‌دهد‪.‬‬

‫شکل ‪6-4‬‬

‫از جمله مزایای این تجهیزات میتوان به موارد زیر اشاره کرد‪:‬‬
‫‪ .۱‬ایــن نرمافزارها معموالً خدمات اولیه را رایــگان ارائه میدهند و برای کارهای عمومی رایگاناند و برای‬
‫تمام پلتفرمها نیز موجودند‪ ،‬اما قابلیتهای خاص آنها مستلزم تأمین هزینه است‪.‬‬
‫‪89‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫‪ .۲‬امکان استفاده از ‪ Auto answer‬برای کاربردهایی از جمله ‪ paging‬و ‪.Intercom‬‬

‫‪ .۳‬در برخــی نرمافزارها میتوان میانبرهایی برای شــمارهگیری ســریع تعریف کرد کــه تعداد آنها به نوع‬
‫نرمافزار مربوطه بستگی دارد‪.‬‬

‫‪ .4‬توانایــی مکالمــه تصویری برای تعدادی از ایــن نرمافزارها به رایگان فراهم اســت و برخی هم در ازای‬
‫پرداخت وجه اندکی به این امکان مجهز میشوند‪.‬‬
‫‪ .۵‬ارسال و دریافت آسانتر پیامها در این نرمافزارها‪ ،‬به دلیل برخورداری از صفحهکلید کامپیوتری‪.‬‬
‫‪Volume‬در این نرمافزارها‪.‬‬ ‫‪ .۶‬برخورداری از کلیدهای میانبر خاص از جمله ‪ Mute ،Hold ،Transfer‬و‬
‫‪ .7‬این نرم‌افزارها به منظور ارائه خدمات پورتابل‪ ،‬می‌توانند روی موبایل یا لپ‌تاپ نصب شوند‪.‬‬

‫از جمله معایب این سیستم می‌توان به موارد زیر اشاره کرد‪:‬‬
‫‪ .1‬سطح اطمینان ناکافی در نرم‌افزار به دالیلی از جمله وابستگی به سیستم عامل‪.‬‬
‫‪ .2‬عدم پشتیبانی از گوشی‌های قدیمی با توجه به ساختار آن‌ها‪.‬‬

‫‪ :Gateway‬مبدل‌هایی هســتند که در ظرفیت‌های باال ارائه می‌شوند؛ مثل ‪. FXO-GW، FXS-GW، E1-GW‬‬
‫چند نمونه ‪ Gateway‬در شکل ‪ 7-4‬ارائه شده است‪.‬‬

‫شکل ‪7-4‬‬

‫از جمله مزایای گیتویها میتوان به موارد زیر اشاره نمود‪:‬‬


‫‪ .۱‬چون امکان استفاده از تلفنهای قدیمی را دارا هستند‪ ،‬هزینه پایینتری دارند‪.‬‬
‫‪ .۲‬با شبکههای قدیمی و ساختارهای شبکه ای از قبل طراحی شده‪ ،‬سازگاری خوبی دارند‪.‬‬
‫‪ .۳‬از پایداری نسبتا خوبی برخوردارند‪.‬‬

‫از جمله معایب آنها میتوان موارد زیر را ذکر نمود‪:‬‬


‫‪ .۱‬بهدلیل عدم دسترسی سیستم ویپ به اسپیکر گوشیهای آنالوگ‪ ،‬امکان ‪ Auto answer‬وجود ندارد‪.‬‬
‫‪ .۲‬امکان اتصال دکمههای قابل برنامهریزی ندارند‪.‬‬
‫‪ .۳‬توانایی ارسال و دریافت پیام های متنی را ندارند‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪90‬‬

‫‪ .4‬در این نوع دستگاهها‪ ،‬میتوان از کلیدهای ترکیبی برای استفاده از آپشنهای ویپ استفاده نمود‪ ،‬ازجمله‬
‫‪ Transfer‬و‪. ...‬‬ ‫‪، Wait‬‬
‫‪ .۵‬این دستگاهها بهدلیل سرویسدهی به حجم باالیی از ارتباطات در یک مکان‪ ،‬امکان جابجایی ندارند‪.‬‬

‫‪ :1 ATA‬مبدل‌هایی هستند که از طریق آن‌ها‪ ،‬تلفن‌های آنالوگ معمولی به شبکه‌های ویپ متصل می‌شوند‪ .‬چند‬
‫نمونه ‪ ATA‬در شکل ‪ 8-4‬ارائه شده است‪.‬‬

‫شکل ‪8-4‬‬

‫‪ATA‬ها از خانواده گیتویها هســتند که مزایا و معایب آن در بخش مربوط به گیتویها بیان شــد‪.‬ازجمله‬
‫مزایا و معایب این تجهیزات نسبت به گیتویها‪ ،‬میتوان به موارد زیر اشاره کرد‪:‬‬
‫‪ .۱‬هزینه نسبتاً پایین راهاندازی سیستم‪.‬‬
‫‪ .۲‬سازگاری با شبکههای قدیمی و قابلیت جابجایی‪.‬‬
‫از معایب آنها هم میتوان به کانفیگ جزیرهای اشــاره نمود‪ .‬برای مثال اگر نیاز به کانفیگ سراسری باشد‪،‬‬
‫باید دستگاهای مختلفی را تنظیم نمایید‪ ،‬درحالیکه گیتویها را با یک اینترفیس هم میتوانید تنظیم کنید‪.‬‬

‫مقایسه انواع تجیهزات ویپ‬


‫هنگام انتخاب تجهیزات در شبکه‌های ویپ احتماال با این سوال مواجه می‌شویم که کدام تجهیزات می‌توانند‬
‫مناسب باشند‪ .‬جدول ‪ 1-4‬مقایسه‌ای بین تجهیزات ویپ از جنبه‌های مختلف را به عمل آورده است‪.‬‬

‫‪Gateway‬‬ ‫‪Video Phone‬‬ ‫‪Soft Phone‬‬ ‫‪IP Phone‬‬ ‫‪ATA‬‬ ‫تجهیزات‬


‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫هزینه‬
‫امکان استفاده از‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪Auto Answer‬‬
‫امکان استفاده از‬
‫‪‬‬ ‫در برخی از مدل ها‬ ‫‪‬‬ ‫در برخی از مدل ها‬ ‫‪‬‬ ‫‪Expansion‬‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫سازگاری با شبکه‌های قدیم‬

‫‪1- Analog Telephony Adaptor‬‬


‫‪91‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫‪Gateway‬‬ ‫‪Video Phone‬‬ ‫‪Soft Phone‬‬ ‫‪IP Phone‬‬ ‫‪ATA‬‬ ‫تجهیزات‬


‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫مکالمه تصویری‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫در برخی از مدل ها‬ ‫‪‬‬ ‫)‪IM (Instant Message‬‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫کلید‌های میانبر خاص‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫قابلیت پایداری‬
‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫‪‬‬ ‫عدم وابستگی به مکان‬
‫جدول ‪1-4‬‬

‫تنظیمات و پیکربندی استریسک‬


‫در شــبکه‌های ویپ‪ ،‬کاربران باید بتوانند به کمک یکی از تجهیزاتی که در قســمت قبل توضیح داده شد‪ ،‬به‬
‫شــبکه ویپ متصل شوند‪ .‬به این منظور ما باید بتوانیم تعدادی کاربر در سیستم تلفنی استریسک تعریف کنیم‬
‫و اطالعات مورد نیاز از قبیل نام کاربری‪ ،1‬رمز عبور‪ 2‬و آی پی سرور ویپ‪ 3‬را در اختیار آنها قرار دهیم‪.‬‬
‫برای تعریف کاربر نوع پروتکل ‪ ،SIP‬از فایل ‪ sip.conf‬استفاده می‌شود و برای تعریف کاربر نوع پروتکل‬
‫‪ IAX2‬باید از فایلی با نام ‪ iax.conf‬اســتفاده کنید‪ .‬در ادامه روش تعریف کاربر در پروتکل ‪ SIP‬و ‪ IAX‬شــرح‬
‫داده می‌شود‪.‬‬

‫نحوه تعریف یک کاربر جدید از نوع پروتکل ‪SIP‬‬


‫بــرای تعریف کاربران نوع ‪ SIP‬باید در فایل ‪ sip.conf‬تغییراتی اعمال کنیم‪ .‬برای تعریف یک کاربر جدید در‬
‫فایل ‪ ،sip.conf‬ابتدا فایل را از مسیر زیر باز کنید و سپس تغییرات زیر را در انتهای فایل ایجاد نمایید‪:‬‬
‫‪#vim /etc/asterisk/sip.conf‬‬
‫]‪[Phone_1‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪context = LocalSets‬‬
‫‪host=dynamic‬‬
‫‪type=friend‬‬
‫‪nat=force_rport,comedia‬‬
‫‪qualify=yes‬‬
‫‪secret=123123‬‬
‫‪dtmfmode=rfc2833‬‬

‫تعریف یک کاربر جدید از نوع ‪ SIP‬شــامل یک فرمت اســتاندارد با پارامترهای مشخص است که در ادامه هر‬
‫یک از موارد فوق را شرح خواهیم داد‪.‬‬
‫‪1- SIP User‬‬
‫‪2- SIP Password‬‬
‫‪3- SIP Server‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪92‬‬

‫پارامتر ‪ : deny‬با این پارامتر اجازه دسترسی و رجیستر شدن از طریق ‪ IP‬مشخص شده‪ ،‬سلب می‌شود‪.‬‬
‫پارامتر ‪ : permit‬با این پارامتر‪ ،‬اجازه دسترسی و رجیستر شدن از ‪ IP‬مشخص شده‪ ،‬داده می‌شود‪.‬‬
‫پارامتر ‪ : context‬با این پارامتر‪ ،‬کانتکست داخلی تعریف می‌شود که در فصول بعد توضیح داده می‌شود‪.‬‬
‫پارامتر ‪ : host‬این گزینه معرف آدرس دسترســی به کاربران و داخلی‌ها اســت کــه در صورت تعریف‌کردن‬
‫بصورت ‪ ، dynamic‬کاربر می‌تواند از هر آدرسی به سیستم تلفنی استریسک رجیستر شود‪.‬‬
‫پارامتر ‪ : type‬با این پارامتر نوع داخلی مورد نظر مشخص می‌شود‪ .‬برای مثال شکل ‪ 9-4‬را ببینید‪.‬‬

‫شکل ‪9-4‬‬

‫‪ : user .1‬فقط برای تماس‌های ورودی به استریسک استفاده می‌‌شود‪.‬‬


‫‪ : peer .2‬فقط برای تماس‌های خروجی از استریسک استفاده می‌شود‪.‬‬
‫‪ : friend .3‬برای تماس‌های ورودی وخروجی استفاده می‌شود‪.‬‬
‫پارامتر ‪ : nat‬در خصوص این پارامتر در فصل هفتم (ارتباط استریســک با ســایر شبکه‌های ویپ) بیشتر توضیح‬
‫خواهیم داد‪.‬‬
‫پارامتر ‪ : secret‬اطالعات رمز عبور برای این داخلی را مشخص می‌کند‪.‬‬
‫پارامتر ‪ : qualify‬با این پارامتر‪ ،‬می‌توان وضعیت رجیستر بودن داخلی را مشخص‌نمود‪ .‬در خصوص این پارامتر‬
‫در فصل‌های آینده صحبت خواهد شد‪.‬‬
‫پارامتر ‪ :dtmfmode‬توســط این پارامتر اســتاندارد ارســال ‪ DTMF‬در حین انتقال داده های ‪) RTP‬صدا( را‬
‫مشخص می کنیم‪ .‬این پارامتر می تواند یکی از مقادیر زیر را داشته باشد‪:‬‬
‫‪ :inband .۱‬در این اســتاندارد‪ DTMF ،‬همانند جریانهای دادهای ‪ RTP‬ارســال خواهد شد‪ .‬دقت کنید‬
‫‪93‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫اگر از کدک فشردهسازی در انتقال جریانهای ‪ RTP‬استفاده کنید‪ DTMF ،‬تغییر کرده و قابل تشخیص‬
‫نخواهد بود‪.‬‬
‫‪ :rfc2833 .۲‬این استاندارد همانند استاندارد ‪ inband‬است ولی مستقل از کدکهای تعریف شده برای‬
‫جریانهای دادهای ‪ RTP‬است‪.‬‬
‫‪ :info .۳‬در این اســتاندارد‪ DTMF ،‬بهصورت پیامهای ســیگنالینگ )‪ (SIP info DTMF‬و مســتقل از‬
‫جریانهای دادهای ‪ RTP‬ارسال میشد‪.‬‬
‫‪ :auto .4‬استریســک بهصــورت پیشفــرض از اســتاندارد ‪ rfc2833‬اســتفاده میکنــد‪ .‬اگــر ســمت‬
‫دیگر)مخاطب(‪ ،‬این استاندارد را نپذیرد‪ ،‬آن را به ‪ inband‬تغییر میدهد‪.‬‬

‫نحوه تعریف یک کاربر جدید از نوع پروتکل ‪IAX‬‬


‫برای تعریف کاربران از نوع ‪ IAX‬باید در فایل ‪ iax.conf‬تغییراتی را اعمال کنیم‪ .‬تعریف یک کاربر جدید‬
‫از نوع ‪ IAX‬شــامل یک فرمت اســتاندارد با پارامترهای مشخصی است که در ادامه هر یک از موارد فوق را‬
‫شرح خواهیم داد‪.‬‬
‫برای تعریف یک کاربر جدید در فایل ‪ ،iax.conf‬ابتدا فایل را از مســیر زیر باز کرده و تغییرات زیر را‬
‫در انتهای فایل ایجاد نمایید‪.‬‬
‫‪# vim /etc/asterisk/iax.conf‬‬
‫]‪[IAX_Phone‬‬
‫‪deny = 0.0.0.0/0.0.0.0‬‬
‫‪secret = 123123‬‬
‫‪transfer = no‬‬
‫‪context = LocalSets‬‬
‫‪host = dynamic‬‬
‫‪type = friend‬‬
‫‪port = 4569‬‬
‫‪qualify = yes‬‬
‫‪permit = 0.0.0.0/0.0.0.0‬‬
‫‪disallow = all‬‬
‫‪allow = alaw,ulaw‬‬
‫‪dtmfmode=rfc2833‬‬

‫همانطور که مالحظه می‌کنید اکثر پارامتر‌ها شــبیه تعریف کاربر از نوع ‪ SIP‬اســت‪ .‬در ادامه سایر پارامتر‌ها را‬
‫نیز معرفی خواهیم کرد‪.‬‬
‫پارامتر ‪ :transfer‬این پارامتر شــبیه پارامترهای ‪ canreinvite‬و ‪( directmedia‬فصل هفتم) در تعریف کاربر‬
‫از نوع پروتکل ‪ SIP‬اســت‪ .‬با این پارامتر می‌توان مشــخص کرد که جریان‌های ترافیکی مدیا مستقیما بین دو‬
‫کاربر منتقل می‌شوند‪ .‬این پارامتر می‌تواند مقادیر زیر را داشته باشید‪:‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪94‬‬

‫‪ : yes .1‬در این حالت استریسک تالش می‌کند که جریان های سیگنالینگ و مدیا بین دو کاربر مستقیما‬
‫منتقل شــوند‪ .‬پرواضح است که اگر بین دو کاربر نیاز به ‪ transcoding‬وجود داشته باشد‪ ،‬این کار انجام‬
‫نخواهد شد‪.‬‬
‫‪ : no .2‬در این حالت استریسک جریان های سیگنالیگ و مدیا بین دو کاربر را از خود عبور می‌دهد‪.‬‬
‫‪ : mediaonly .3‬در ایــن حالــت استریســک فقط جریان های ســیگنالینگ را از خــود عبور می‌دهد و‬
‫جریان‌های مدیا بین دو کاربر مستقیما منتقل می‌شوند‪ .‬در این حالت استریسک می‌تواند گزارشات ‪CDR‬‬
‫را داشته باشد‪.‬‬

‫‪1‬‬
‫قالب‌ها‬
‫از آنجاکه فرمت تعریف کاربران در اکثر پارامتر‌ها مشــابه اســت‪ ،‬می‌توانیم این پارامترهای مشابه را در یک‬
‫قالب تعریف کنیم و ســپس در هنگام تعریف کاربران جدید‪ ،‬از آن‌ها اســتفاده نماییم‪ .‬برای تعریف قالب از‬
‫عالمت (!) استفاده می‌کنیم‪ .‬به عنوان مثال در ساخت داخلی می‌توانیم به این شکل عمل کنیم‪.‬‬
‫‪;sip.conf‬‬
‫)!(]‪[users‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪context = LocalSets‬‬
‫‪host=dynamic‬‬
‫‪type=friend‬‬
‫‪nat=force_rport,comedia‬‬
‫‪qualify=yes‬‬
‫‪dtmfmode=rfc2833‬‬

‫اکنون برای تعریف کردن کاربرهای جدید‪ ،‬آن را به صورت زیر تعریف می‌کنیم‪.‬‬
‫‪;sip.conf‬‬
‫)‪[Phone_1](users‬‬
‫>‪callerid = Phone_1 <1000‬‬
‫‪secret=123123‬‬

‫)‪[Phone_2](users‬‬
‫>‪callerid = Phone_2 <1000‬‬
‫‪secret=123123‬‬
‫‪context=myContext‬‬

‫در این روش‪ ،‬فقط پارامترهایی را مینویسیم که یا میخواهیم مقدار آنها تغییر کند و یا در قالب وجود ندارد‪.‬‬
‫بــرای مثال در هر دو کاربر پارامتــر ‪ secret‬را تعریف کردهایم‪ ،‬چون این پارامتــر در قالب ]‪ [users‬تعریف‬

‫‪1- Templates‬‬
‫‪95‬‬ ‫پیکربندی تجهیزات در شبکه‌های ویپ‬

‫نشدهاست‪ .‬همچنین در هنگام تعریف کاربر ‪ ، Phone_2‬پارامتر ‪ context‬را دوباره تعریف کردهایم‪ .‬در این‬
‫حالت این مقدار جدید با مقدار قبلی تعریف شده در قالب جایگزین میشود‪.‬‬
‫بعد از تعریف داخلی جدید در استریســک‪ ،‬باید حتما ماژول های مربوطه را ‪ reload‬کنیم تا استریســک‬
‫بتواند داخلیهای جدید را بشناسد‪ .‬برای این منظور میتوانید از محیط کامند الین استریسک استفاده نمایید‪.‬‬
‫‪#asterisk –r‬‬
‫‪CLI> sip reload‬‬

‫اکنون اگر دستورات زیر را اجرا کنید باید بتوانید داخلیای که قب ً‬


‫ال تعریف کردهاید را مشاهده کنید‪.‬‬
‫‪CLI> sip show peers‬‬
‫‪Name/username‬‬ ‫‪Host Dyn Forcerport Comedia ACL Port Status‬‬ ‫‪Description‬‬
‫‪Phone_1/Phone_1‬‬ ‫‪(Unspecified) D Yes‬‬ ‫‪Yes‬‬ ‫‪A 0‬‬ ‫ ‬
‫‪UNKNOWN‬‬
‫‪Phone_2/Phone_2‬‬ ‫‪(Unspecified) D Yes‬‬ ‫‪Yes‬‬ ‫‪A 0‬‬ ‫ ‬
‫‪UNKNOWN‬‬
‫>‪CLI‬‬

‫‪CLI> sip show users‬‬


‫‪Username‬‬ ‫ ‪Secret‬‬ ‫‪Accountcode Def.Context ACL Forcerport‬‬
‫ ‪Phone_1 123123‬‬ ‫‪LocalSets‬‬ ‫ ‪Yes‬‬ ‫‪Yes‬‬
‫ ‪Phone_2 123123‬‬ ‫‪myContext‬‬ ‫ ‪Yes‬‬ ‫‪Yes‬‬
‫>‪CLI‬‬

‫مراحل اعتبارسنجی‪ 1‬در استریسک‬


‫استریسک در موارد زیر‪ ،‬عملیات اعتبارسنجی را برای داخلی‌ها انجام می‌دهد‪.‬‬

‫‪ )1‬زمانی که یک داخلی بخواهد به سیســتم تلفنی استریســک رجیستر شود‪ .‬در این حالت پیام ‪ REGISTER‬از‬
‫طرف کاربر برای استریسک ارسال می‌شود و استریسک عملیات اعتبار سنجی را انجام می‌دهد‪.‬‬

‫‪ )2‬زمانی که یک داخلی تمایل به ایجاد یک تماس خروجی داشته‌باشد‪ ،‬در این حالت یک پیام ‪ INVITE‬برای‬
‫‪2‬‬

‫استریسک ارسال می‌شود و استریسک عملیات اعتبارسنجی را انجام می‌دهد‪.‬‬

‫نتیجه‌گیری‬
‫در این فصل در خصوص معرفی انواع تجهیزات مورد نیاز در شبکههای ویپ توضیح داده شد و هر یک به‬
‫اختصار بررســی گردید‪ .‬همچنین توضیح داده شد که در سیستم تلفنی استریسک چگونه میتوان کاربرهای‬
‫جدید تعریف نمود‪ .‬بعد از تعریف کاربرهای جدید‪ ،‬باید بتوان از آنها اســتفاده و داخلیها را رجیستر نمود‪.‬‬

‫‪1- SIP User Authentication‬‬


‫‪2- Outgoing‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪96‬‬

‫به این منظور ابتدا باید تغییرات انجام شده در استریسک ثبت و ماژولهای مربوطه ‪ reload‬شوند‪ .‬دست آخر‬
‫عملیات اعتبارســنجی در استریســک بررسی شد و توضیح داده شــد که استریسک در چه زمانهایی از آن‬
‫استفاده میکند‪.‬‬
‫فصل پنجم‬
‫برنامه‌نویسی مقدماتی در استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪98‬‬

‫مفهوم برنامه‌نویسی‪ 1‬در استریسک‬


‫بخش اصلی یک سیســتم تلفنی ویپ را برنامه‌نویسی تشــکیل می‌دهد‪ .‬بدون برنامه‌نویسی‪ ،‬یک سیستم تلفنی‬
‫قادر به انجام هیچ کاری نخواهد بود‪.‬‬
‫در واقع‪ ،‬این نقش‌ها‪ 2‬و قوانین تعریف‌شــده در برنامه هســتند که به سیستم تلفنی این امکان را می‌دهند تا‬
‫بتوانیــم به‌راحتی همه تماس‌ها را مدیریت و کنترل کنیم‪ .‬هدف اصلی این بخش آشــنایی اولیه و مقدماتی با‬
‫برنامه‌نویسی در استریسک و نحوه ایجاد آن است‪.‬‬
‫از آنجــا کــه این فصل یکی از فصل‌هــای اولیه و مهم در بخش مفاهیم برنامه‌نویســی در سیســتم تلفنی‬
‫استریســک اســت‪ ،‬نباید پس از مطالعه مطالب فصل‪ ،‬ابهامی برای مخاطب وجود داشته باشد؛ بنابراین تأمل و‬
‫دقت بیشتر در مطالعه این فصل به همراه تست و اجرای همه مثال‌های آن توصیه می‌شود‪.‬‬
‫پیش‌تر اشاره شد که سه روش برنامه‌نویسی ‪ Dialplan‬در استریسک وجود دارد‪:‬‬
‫‪• extensions.conf‬‬
‫‪• extensions.ael‬‬
‫‪• extensions.lua‬‬

‫در مثال زیر هر سه روش را پیاده‌سازی می‌کنیم‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[default‬‬
‫)‪exten => 100,1,playback(please-hold‬‬
‫)‪exten => 100,2,dial(IAX2/203,60‬‬
‫)‪exten => 101,1,dial(SIP/101,60‬‬
‫‪---------------------------------‬‬

‫‪1- dialplan‬‬
‫‪2- role‬‬
‫‪99‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫‪;extensions.ael‬‬
‫{ ‪context defualt‬‬
‫{ >= ‪100‬‬
‫;)‪Playback(please-hold‬‬
‫;)‪Dial(IAX2/203,60‬‬
‫}‬
‫{ >= ‪101‬‬
‫;)‪Dial(SIP/101,60‬‬
‫}‬
‫‪---------------------------------‬‬
‫‪;extensions.lua‬‬
‫{ = ‪extensions‬‬
‫{= ‪default‬‬
‫)‪[“100”] = function(function,extension‬‬
‫)”‪app.playback(“please-hold‬‬
‫)‪app.dial(“IAX2/203”,60‬‬
‫)‪[“101”] = function(function,extension‬‬
‫)‪app.dial(“SIP/101”,60‬‬
‫;‪end‬‬

‫در استریسک می‌توان از هر سه روش در برنامه‌نویسی استفاده کرد‪ .‬آنچه در این کتاب بیشتر به آن می‌پردازیم‪،‬‬
‫برنامه‌نویســی به روش اول و استفاده از فایل ‪ extensions.conf‬است‪ .‬استفاده از سایر روش‌های برنامه‌نویسی‬
‫در استریسک به خواننده کتاب واگذار می‌شود‪.‬‬
‫در سیســتم تلفنی استریسک فایل ‪ extensions.conf‬برای تنظیمات و پیکربندی برنامه‌ها و رول‌ها در نظر‬
‫گرفته‌شده است که در ادامه درباره ساختار و بدنه این فایل توضیحات بیشتری آمده است‪.‬‬

‫اجزای اصلی ‪Dialplan‬‬

‫اگر فایل ‪ extensions.conf‬را با یک ویرایشــگر لینوکس مانند ‪ vim‬یا ‪ nano‬باز کنید‪ ،‬در نگاه اول متوجه‬
‫که ساختار هر خط در این فایل از دو قسمت اصلی تشکیل شده که به صورت زیر است‪:‬‬ ‫میشوید‬
‫]‪[context‬‬
‫‪exten => extensions,priority,application‬‬

‫بخش کانتکست (‪)context‬‬


‫معموال ‪Dialplan‬ها به بخشهای کوچکتری بهنام کانتکست تقسیم میشوند‪ ،‬بهطوریکه هر بخش میتواند‬
‫کام ً‬
‫ال مســتقل از ســایر بخشها اجرا شود‪ .‬هر بخش بهطور مســتقل دارای قوانین و رولهای متعددی است‪.‬‬
‫در هر کانتکست یک یا مجموعهای از اکستنشن ها تعریف میشوند که قوانین و رولهای آن کانتکست را‬
‫تعریف میکنند‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪100‬‬

‫برای مثال شــکل ‪ ۱-۵‬را در نظر بگیرید‪ .‬در کانتکســت ]‪ [demo‬تمامی اکستنشنهای تعریف شده‪ ،‬این‬
‫قابلیت را دارند که با هم در ارتباط باشند‪ ،‬ولی اکستنشن های کانتکست ]‪ [demo‬نمیتوانند با اکستنشن های‬
‫تعریف شده در کانتکست ]‪ [default‬در ارتباط باشند‪.‬‬

‫شکل ‪1-5‬‬

‫ما نمی‌توانیم در یک کانتکســت برای یک اکستنشــن ‪ ،‬دو رول تعریف کنیم‪ .‬برای مثال برنامه زیر را در نظر‬
‫بگیرید‪:‬‬
‫]‪[demo1‬‬
‫)‪exten => 100,1,Playback(hello-world‬‬
‫)‪exten => 200,1,Playback(hello-world‬‬
‫)‪exten => 100,1,Dial(SIP/100‬‬

‫همانطورکــه مالحظه میکنیــد برای شــماره ‪ ،۱۰۰‬دو رول کام ً‬


‫ال مجزا از هم داریم‪ .‬اگــر با چنین ترکیبی‬
‫برنامهنویسی کنید‪ ،‬استریسک حالت اول آن را در نظر میگیرد؛ برای مثال‪ ،‬فرض کنید کد باال را در ساختار‬
‫‪ dialplan‬استریســک داشته باشیم و سپس با دستور زیر بخواهیم دریابیم که استریسک چطور آن را تحلیل‬
‫میکند‪ .‬در این صورت داریم‪:‬‬
‫‪CLI> dialplan show demo1‬‬
‫] ›‪[ Context ‹demo1› created by ‹pbx_config‬‬
‫]‪‹100› => 1. Playback(hello-world) [pbx_config‬‬
‫]‪‹200› => 1. Playback(hello-world) [pbx_config‬‬

‫همان‌طورکه مالحظه می‌کنید استریسک رول اول تعریف‌شده را در نظر می‌گیرد‪.‬‬


‫یک فایل ‪ extensions.conf‬می‌تواند شامل چندین کانتکست به‌صورت زیر باشد‪:‬‬
‫]‪[demo2‬‬
‫)‪exten => 1000,1,Dial(SIP/1000‬‬
‫)‪exten => 300,1,Playback(demo-thanks‬‬

‫]‪[demo3‬‬
‫)‪exten => 200,1,Dial(SIP/200‬‬
‫)‪exten => 300,1,Dial(SIP/300‬‬
‫)‪exten => 400,1,Dial(SIP/400‬‬
‫)‪exten => 500,1,Dial(SIP/500‬‬
‫همان‌طورکــه مالحظــه می‌کنید هر بخش به صــورت کام ً‬
‫ال مســتقل تعریف می‌گردد و هیــچ ارتباطی بین‬
‫‪101‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫بخش‌ها وجود ندارد‪ .‬می‌توان در بخش‌های مختلف در صورت لزوم از اکستنشن‌های هم‌نام نیز استفاده کرد‪.‬‬
‫ال متفاوت در دو کانتکست مستقل‬ ‫همان‌طورکه در مثال باال دیده می‌شود‪ ،‬برای اکستنشن ‪ ، 300‬دو رول کام ً‬
‫از هم وجود دارد‪.‬‬
‫نام‌گذاری کانتکســت‌ها کامــ ً‬
‫ا اختیاری و آزادانه‌اند‪ ،‬ولی در تعریف و نام‌گــذاری آن‌ها باید از قواعد‬
‫خاص آن‌ها تبعیت کنیم‪ .‬لذا موارد زیر باید در تعریف نام کانتکست رعایت شود‪:‬‬
‫‪ -‬اسم کانتکست باید بین عالمت [ ] قرار بگیرد‪.‬‬
‫‪ -‬اسم کانتکست می‌تواند ترکیبی از ‪ A-Z, a-z, 0-9‬باشد‪.‬‬
‫‪ -‬حداکثر طول نام کانتکست نمی‌تواند بیش از ‪ 80‬کاراکتر باشد‪.‬‬
‫‪ -‬نام کانتکســت های پیش‌فرض در استریســک [‪ ]general], [globals‬و [‪ ]default‬اســت؛ ترجیحاً از این اسامی‬
‫استفاده نشود‪.‬‬

‫بخش اکستنشن (‪)extensions‬‬


‫همان‌طورکه در بخش مفاهیم نام‌گذاری تلفن در فصل چهارم توضیح داده‌شد‪ ،‬مفهوم اکستنشن در مخابرات‬
‫بیشــتر به شــماره تلفن مخاطبان اشاره دارد‪ .‬هر شماره تلفن از مشــتریان مخابرات‪ ،‬در حقیقت یک اکستنشن‬
‫اســت که به نحوی پلی ارتباطی با مشــتریان برقرار می‌کند‪ .‬این شماره‌ها به‌عنوان یک موجودیت یکتا و ثابت‬
‫در اختیار مشــتریان خواهد بود‪ .‬اما در سیستم تلفنی استریسک این مفهوم فراتر بوده و می‌تواند شامل هر نوع‬
‫برنامه‌ای (سرویس ارزش افزوده) باشد‪.‬‬
‫بدنه هر اکستنشن از سه قسمت اصلی تشکیل شده‌است‪:‬‬
‫‪exten =>name, priority, application‬‬

‫‪ : Name‬نام یا شــماره داخلی اکستنشــن برنامه مورد نظر است که باید در هر کانتکست یکتا و منحصر به فرد‬
‫باشد‪.‬‬

‫‪ : Priority‬هر اکستنشن می‌تواند ترکیبی از برنامه‌های مختلف باشد و مرحله به مرحله و به ترتیب اجرا شود‪.‬‬
‫با این پارامتر اولویت اجرایی ترتیب دستورات مشخص می‌شود‪.‬‬

‫‪ : Application‬برنامه‌ای اســت که باید بوسیله سیســتم تلفنی استریسک اجرا شود‪ .‬استریسک از دستورات و‬
‫توابع بسیاری استفاده می‌کند که هرکدام بوسیله ماژول‌هایی به استریسک اضافه شده‌اند‪ .‬در ادامه‌ی این فصل‬
‫و فصل‌های آینده با این دستورات و توابع آشنایی بیشتری پیدا خواهید کرد‪.‬‬
‫به عنوان یک مثال ساده فرض‌کنید تصمیم داریم اولین برنامه خود را در استریسک بنویسیم‪ ،‬به گونه‌ای که‬
‫اگر کاربر عدد ‪ 123‬را شماره‌گیری کرد‪ ،‬پیام صوتی ‪ Hello-world‬برایش پخش شود‪ .‬برای این منظور نخست‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪102‬‬

‫باید یک کاربر جدید تعریف و در سیستم‪ ،‬رجیستر نماییم‪.‬‬


‫برای تعریف کردن کاربر جدید در سیســتم و رجیســتر کردن آن در سیســتم تلفنی استریسک‪ ،‬در فصل‬
‫چهارم (پیکربندی تجهیزات در شــبکه های ویپ) توضیحات الزم داده شده است؛ اینجا هدف انجام سناریو‬
‫است‪.‬‬
‫ابتدا فایل ‪ sip.conf‬را از مسیر فایل‌های پیکربندی استریسک باز کنید‪.‬‬
‫‪# vim /etc/asterisk/sip.conf‬‬

‫به انتهای فایل فوق بروید و موارد زیر را اضافه کنید‪:‬‬


‫]‪[0000FFFF0001‬‬
‫‪deny= 0.0.0.0/0.0.0.0‬‬
‫‪dtmfmode=rfc2833‬‬
‫‪canreinvite=no‬‬
‫‪directmedia=no‬‬
‫‪host=dynamic‬‬
‫‪type=friend‬‬
‫‪nat=force_rport,comedia‬‬
‫‪port=5060‬‬
‫‪qualify=yes‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪callcounter=yes‬‬
‫‪secret=123123‬‬
‫>‪callerid=user1<1000‬‬
‫‪context=LocalSet‬‬

‫بعد از اضافه کردن موارد فوق‪ ،‬به محیط استریسک بروید و ماژول ‪ chan_sip.so‬را مجددا ‪ reload‬کنید‪.‬‬
‫‪CLI> module reload chan_sip.so‬‬

‫در استریسک ایجاد کردیم؛ اکنون با دستور زیر می‌توانید از صحت‬ ‫تا اینجا ما یک کاربر به نام ‪0000FFFF0001‬‬

‫ساخت آن مطمئن شوید‪:‬‬


‫‪CLI> sip show peers‬‬
‫ ‪Name/username Host‬‬ ‫‪Dyn Forcerport ACL Port Status Description‬‬
‫‪0000FFFF0001 (Unspecified) D N‬‬ ‫‪A 0 UNKNOWN‬‬

‫اکنون کافی است بوسیله یک سافت‌فون رجیستر شویم‪ .‬برای رجیستر شدن‪ ،‬اطالعات نام کاربری‪ ،‬رمز عبور‬
‫و آی پی ســرور‪ ،‬مورد نیاز اســت‪ .‬بعد از رجیسترشدن‪ ،‬با اجرای دســتور قبلی‪ ،‬خروجی به صورت زیر نشان‬
‫داده می‌شود‪:‬‬
‫‪CLI> sip show peers‬‬
‫‪Name/username Host‬‬ ‫‪Dyn Forcerport ACL Port Status Description‬‬
‫‪0000FFFF0001‬‬ ‫‪192.168.1.111 D N‬‬ ‫)‪A 5060 OK (107 ms‬‬

‫در مرحله بعد باید برنامه موردنظرمان را در استریســک بنویســیم‪ .‬ازآنجاکه از فایل ‪ extensions.conf‬برای‬
‫‪103‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫نوشتن برنامه‌ها در استریسک استفاده می‌کنیم‪ ،‬باید نخست فایل را باز و دستورات زیر را به انتهای آن اضافه‬
‫کنید‪.‬‬
‫‪#vim /etc/asterisk/extensions.conf‬‬

‫]‪[LocalSets‬‬
‫)(‪exten => 123,1,Answer‬‬
‫)‪exten => 123,2,Playback(hello-world‬‬
‫)(‪exten => 123,3,Hangup‬‬

‫بعد از اعمال تغییرات فوق‪ ،‬به محیط کامند الین استریسک رفته و ابتدا دستور زیر را اجرا کنید‪.‬‬
‫‪CLI> dialplan reload‬‬

‫اجرای دســتور فوق باعث می‌شود که تغییرات اعمال شده در فایل ‪ extensions.conf‬و سایر فایل‌های وابسته‬
‫به آن‪ ،‬بوسیله استریسک ثبت شود‪ .‬اگر تجربه کار با سیستم تلفنی الستیکس را دارید‪ ،‬با انجام هر تغییری در‬
‫آن‪ ،‬باید گزینه “‪ ”apply changes‬را در محیط وب کلیک کنید‪ .‬در واقع با این کار شــما این دســتور را در‬
‫استریسک اجرا می‌کنید‪.‬‬
‫‪CLI> core reload‬‬

‫تا اینجا‪ ،‬هم کاربر جدید ساختیم و هم برنامه‌ای برای آن تعریف نمودیم‪ .‬سؤالی که ممکن است اینجا پرسیده‬
‫شــود این اســت که چه ارتباطی میان ساختن فایل در ‪ sip.conf‬و رول‌های تعریف شده در فایل ‪extensions.‬‬
‫‪ conf‬وجود دارد؟‬
‫اجازه بدهید این سوال را با شکل ‪ 2-5‬توضیح دهیم‪:‬‬

‫شکل ‪2-5‬‬

‫همان‌طورکــه مالحظه می‌کنید در این شــکل‪ ،‬کاربری از نــوع ‪ sip‬در فایل ‪ sip.conf‬تعریف شده‌اســت و در‬
‫تعریف کاربر مقدار ‪ Context=localSets‬تنظیم شده‌اســت‪ .‬معنای این پارامتر این اســت که حوزه فعالیت‌ها و‬
‫مجوز دسترسی برای کاربر ‪ 0000FFFF0001‬در کانتکست [‪ ]localsets‬تعریف شده است‪ .‬مالحظه می‌شود که ‬
‫در کانتکست [‪ ]localSets‬فقط یک رول تعریف شده‌است‪ ،‬آن هم مربوط به ‪123‬است‪ .‬در این صورت اگر از‬
‫طرف این کاربر عدد ‪ 123‬ارسال شود‪ ،‬فایل صوتی ‪ hello-world‬اجرا می‌شود‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪104‬‬

‫نکته مهم در اینجا نحوه ارتباط و تعریف ســطوح دسترســی و عملکرد کاربران در سیســتم تلفنی است‪.‬‬
‫می‌توانیم این ســطح امنیتی را در هنگام تعریف رول‌ها در کانتکســت مربوطــه در نظر بگیریم‪ .‬همان‌طورکه‬
‫مالحظه می‌کنید سطح دسترسی این کاربر محدود به حوزه‌ی کانتکستی است که در زمان تعریف کاربر در‬
‫پارامتر ‪ context‬مشخص شده‌است‪.‬‬
‫در ادامه مثال‌های بیشــتری در زمینه برنامه‌نویسی استریســک خواهد آمد‪ .‬برای مثال قطعه کد زیر را در‬
‫نظر بگیرید‪:‬‬
‫)(‪exten => 124,1,Answer‬‬

‫ما یک اکستنشن به نام ‪ 124‬تعریف کرده‌ایم که اولویت اول آن‪ ،‬اجرای دستور ‪ Answer‬است‪ .‬با اجرای‬
‫این برنامه‪ ،‬استریسک به تماس ورودی ‪ 124‬پاسخ می‌دهد یا به اصطالح آن را ‪ Answer‬می‌کند‪ .‬همان‌طورکه‬
‫مالحظه می‌کنید اجرای دستورات با اولویت ‪ 1‬شروع می‌شود‪ .‬اگر خواسته باشیم چندین دستور را پشت سر‬
‫هم اجرا کنیم‪ ،‬باید اولویت اجرای دستورات را یک به یک افزایش دهیم‪ .‬برای مثال فرض کنید اجرای چند‬
‫دستور را می‌خواهیم برنامه‌نویسی کنیم‪:‬‬
‫)(‪exten => 124,1,Answer‬‬
‫‪exten => 124,2, do something‬‬
‫‪exten => 124,3, do something else‬‬
‫‪exten => 124,4, do one last thing‬‬
‫)(‪exten => 124,5,Hangup‬‬

‫همان‌طورکه مالحظه می‌کنید پنج دســتور برای اکستنشن ‪ 124‬تعریف کرده‌ایم که با شماره‌گیری ‪ ،124‬این‬
‫دستورات به ترتیب اولویت از‪ 1‬تا ‪ 5‬اجرا می‌شوند‪.‬‬
‫دقت شــود که ترتیب و توالی دســتورات بسیار مهم اســت و حتما باید اولویت دستورات‪ ،‬پشت سرهم‬
‫به‌صورت «تک واحدی» افزایش یابد‪.‬‬
‫برای مثال دستورات زیر را در نظر بگیرید‪:‬‬
‫)‪exten => 124,1,NoOp(This is my first dialplan in asterisk PBX‬‬
‫)(‪exten => 124,2,Answer‬‬
‫)‪exten => 124,3,Wait(5‬‬
‫)‪exten => 124,4,Playback(demo-congrats‬‬
‫)(‪exten => 124,5,Hangup‬‬

‫همان‌طورکه مالحظه می‌کنید با شــماره‌گیری ‪ ،124‬ابتدا دســتور ‪ 1 NoOp‬اجرا می‌شــود‪ .‬همان طور که از‬
‫اســم آن پیداست این دســتور هیچ کاری انجام نمی‌دهد بلکه فقط عبارتی که جلوی آن باشد را در خروجی‬
‫استریســک در زمان اجرا‪ ،‬نمایش می‌دهد‪ .‬از این دستور و دستور ‪ Verbose‬برای خطایابی و مشاهده الگ‌ها‬
‫در محیط کنسول استریسک استفاده می‌شود‪ .‬در اولویت بعدی‪ ،‬تماس بوسیله استریسک پاسخ داده می‌شود‪،‬‬

‫‪1- No Operation‬‬
‫‪105‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫ســپس تماس جاری به مدت ‪ 5‬ثانیه متوقف می‌شــود‪ .‬بعد از ‪ 5‬ثانیه‪ ،‬فایل صوتی ‪ demo-congrats‬بوســیله‬
‫دستور ‪ Playback‬اجرا می‌شود‪ .‬در نهایت تماس توسط دستور ‪ hangup‬در استریسک قطع می‌شود‪.‬‬
‫فرض کنید بخواهیم با کاربر ‪ Bob‬تماس بگیریم‪ .‬می‌توانیم از دستورات زیر در برنامه استفاده کنیم‪:‬‬
‫)‪exten => 125,1,Dial(SIP/Bob,45‬‬
‫)‪exten => 125,2,Playback(sorry‬‬
‫)(‪exten => 125,3,Hangup‬‬

‫در این صورت اگر شــماره ‪ 125‬را شماره‌گیری کنیم‪ ،‬ابتدا کاربر ‪ bob‬به مدت ‪ 45‬ثانیه زنگ می‌خورد‪ .‬اگر‬
‫‪ bob‬در این مدت تماس را پاسخ ندهد آنگاه اولویت اجرا به خط بعدی رفته و پیام ‪ sorry‬پخش خواهد شد‪،‬‬
‫سپس تماس قطع می‌شود‪.‬‬
‫همان‌طورکه پیش‌تر نیز اشــاره شد‪ ،‬ترتیب اجرای دستورات بر اســاس اولویت مشخص می‌شود‪ .‬فرض‬
‫کنید دستورات زیر را داشته باشیم‪:‬‬
‫)(‪exten => 124,1,Answer‬‬
‫‪exten => 124,2, do something‬‬
‫‪exten => 124,3, do something else‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫‪exten => 124,100, do one last thing‬‬

‫اکنون فرض کنید دســتوری را بخواهیم در اولویت ‪ 51‬اضافه کنیم؛ واضح اســت که باید تمامی اولویتها را‬
‫تا انتها‪ ،‬یک واحد افزایش دهیم‪ .‬مســلماً این کار کمی سخت و طاقت‌فرسا به‌نظر می‌رسد و چندان خوشایند‬
‫نیست‪ .‬برای جلوگیری از این‌گونه موارد از اولویت ‪ n‬در برنامه‌نویسی استفاده می‌کنیم‪.‬‬
‫)(‪exten => 124,1,Answer‬‬
‫‪exten => 124,n, do something‬‬
‫‪exten => 124,n, do something else‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫‪exten => 124,n, do one last thing‬‬

‫همان‌طورکه مالحظه می‌کنید به جز دســتور اول‪ ،‬از اولویت ‪ n‬در برنامه‌نویسی استفاده کردیم‪ .‬در این حالت‬
‫چنانچه تغییری در بدنه ‪ Dialplan‬در هر قســمت (در هر اولویتی) ایجاد شود‪ ،‬به راحتی می‌توان آن را اضافه‬
‫یا حذف کرد و نیازی به تغییر اولویت‌ها نیســت‪ .‬در این صورت همه دســتورات به صورت خط به خط اجرا‬
‫می‌شوند‪.‬‬
‫همان‌طورکه در زیر مشاهده می‌کنید‪ ،‬دو مثال فوق با هم معادل‌اند‪:‬‬
‫)(‪exten => 555,1,Answer‬‬
‫)‪exten => 555,2,Playback(demo-thanks‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪106‬‬

‫)‪exten => 555,3,Voicemail(555‬‬


‫)(‪exten => 555,4,Hangup‬‬

‫)(‪exten => 555,1,Answer‬‬


‫)‪exten => 555,n,Playback(demo-thanks‬‬
‫)‪exten => 555,n,Voicemail(555‬‬
‫)(‪exten => 555,n,Hangup‬‬

‫همچنین می‌توانیم برای جلوگیری از تکرار نام اکستنشن‪ ،‬برنامه باال را بصورت زیر بنویسیم‪ .‬در این حالت از‬
‫عبارت ‪ same‬استفاده می‌کنیم که نشان‌دهنده اکستنشن در اولویت قبلی است‪.‬‬
‫)(‪exten => 555,1,Answer‬‬
‫)‪same => n,Playback(demo-thanks‬‬
‫)‪same => n,Voicemail(555‬‬
‫)(‪same => n,Hangup‬‬

‫پرش بین دستورات‬


‫برخی مواقع الزم اســت بر اســاس شــرط‌هایی در زمان اجرا‪ ،‬بین دســتورات (اولویت‌هــای مختلف) پرش‬
‫داشته‌باشیم؛ در این حالت از قابلیت برچسب‪ 1‬در برنامه‌نویسی استریسک استفاده می‌کنیم‪.‬‬
‫برچسب‌ها در استریسک با فرمت زیر تعریف می‌شوند‪:‬‬
‫)(‪exten => name,n(lable), application‬‬

‫مسئله مهم در این تعریف این است که بین برچسب و اولویت‪ ،‬عالمت کاما وجود ندارد و اکثرا ً به اشتباه بین‬
‫این دو از عالمت « ‪ » ,‬استفاده می‌کنند که منجر به بروز خطا در سیستم می‌گردد‪.‬‬
‫به عنوان مثال برنامه زیر را درنظر بگیرید‪:‬‬
‫)‪exten => 206,1,GotoIf($["${CALLERID(num)}" = "303"]?dial1‬‬
‫)‪same => n,GotoIf($["${CALLERID(num)}" != "304"]?moh:dial2‬‬
‫)‪same => n(dial1),Dial(${SPHONE1},15,rt‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(dial2),Dial(${PHONE2},15,rt‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(moh),MusicOnHold(default‬‬

‫در این مثال پس از وارد کردن شــماره ‪ ، 206‬ابتدا شــرط کالر‌آیدی‪ 2‬چک می‌شــود‪ .‬اگر کالر‌آیدی شــخص‬
‫تماس‌گیرنده‪ 303 3‬باشد‪ ،‬اجرای برنامه به برچسب ‪ dial1‬منتقل می‌شود و در غیر اینصورت به گام بعدی می‌رود‬
‫و در آنجا اگر کالرآیدی ‪ 304‬باشد به بر چسب ‪ dial2‬و در غیر اینصورت به برچسب ‪ moh‬منتقل می‌گردد‪.‬‬
‫نکته مهم این اســت که بعد از انتقال به برچســب مشخص شده‪ ،‬دســتورات آن قسمت به ترتیب اولویت‬
‫اجرا خواهند شد‪.‬‬
‫‪1- Label‬‬
‫‪2- CallerID‬‬
‫‪3- Caller‬‬
‫‪107‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫آشنایی با برخی از دستور‌ها در استریسک‬


‫هدف از این بخش‪ ،‬آشــنایی با برخی از دســتورهای ســاده و پرکاربرد در سیســتم تلفنی استریسک و نحوه‬
‫کاربرد آنها در ساختار برنامه‌نویسی است‪ .‬در فصل‌های بعدی به تدریج با دستورهای بیشتری آشنا خواهید‌شد‪.‬‬

‫دستور ‪Answer‬‬
‫وقتی یک تماس جدید در استریسک ایجاد می‌شود‪ ،‬وضعیت کانال تا زمانی که به آن تماس پاسخ نداده‌ایم‬
‫در حالت ‪ Ringing‬باقی می‌ماند‪ .‬اکنون اگر تماس را بوسیله خود استریسک پاسخ دهیم‪ ،‬تماس در این حالت‬
‫‪ Answer‬شــده و ازحالت ‪ Ringing‬خارج می‌شــود‪ .‬با اجرا شدن این دســتور‪ ،‬تماس ورودی بوسیله سیستم‬
‫تلفنی استریســک ‪ Answer‬می‌شود که در اصطالح به معنای برداشتن گوشی است‪ .‬کاربرد اصلی این دستور‬
‫در مواقعی اســت که می‌خواهیم توسط سیســتم تلفنی تعامالتی را انجام دهیم و باید قبل از اجرای تعامالت‪،‬‬
‫مطمئن باشــیم که تماس برقرار و ‪ Answer‬شده است‪ .‬به‌عنوان مثال برای پخش یک فایل صوتی‪ ،‬کانال باید‬
‫‪ Answer‬شود تا امکان پخش آن به‌وجود آید‪.‬‬

‫دستور ‪Playback‬‬
‫این دســتور بــه منظور پخش کردن فایــل صوتی‪ ،‬روی کانال مورد اســتفاده قرار می‌گیرد‪.‬نــام فایل صوتی‬
‫به عنوان ورودی باید در این دســتور وارد شــود‪ .‬مســیر پیش‌فرض فایل‌های صوتی در استریســک ‪var/lib/‬‬
‫‪ /asterisk/sounds/en‬اســت؛ به‌طوری‌که اگر مســیر فایل صوتی ذکر نشــود استریسک از مسیر پیش‌فرض‬
‫استفاده می‌کند تا فایل صوتی را پیدا و اجرا کند‪ .‬درصورتی‌که بخواهیم از مسیر دیگری فایل صوتی را اجرا‬
‫کنیم‪ ،‬باید آدرس کامل مسیر را وارد کنیم‪.‬‬
‫)(‪exten => 126,1,Answer‬‬
‫)‪same => n,Playback(/var/spool/storage/sounds/demo-thanks‬‬
‫)(‪same => n,Hangup‬‬

‫بهتر است پسوند فایل صوتی را در هنگام نوشتن نام فایل‪ ،‬ذکر نکنیم؛ در این صورت اگر فایل صوتی مورد‬
‫نظر با چندین فرمت متفاوت در مســیر مشخص شده وجود داشته باشــد‪ ،‬استریسک بهترین فرمت (از لحاظ‬
‫کمتریــن پردازش جهت تبدیل به کدک مورد نظر) را انتخاب و پخش می‌نماید‪ .‬در این حالت استریســک‬
‫بار هزینه ‪ CPU‬کمتری را مصرف می‌کند (در فصل ســوم‪ ،‬ســاختار استریســک راجع به ماژول ‪Format-‬‬
‫‪ Interpreter‬توضیح داده شده‌است)‪.‬‬
‫در استریســک دستورات دیگری برای پخش فایل صوتی از قبیل دستور ‪ Read‬و دستور ‪BackGround‬‬
‫وجود دارد که بعدا با آنها آشنا می‌شوید‪.‬‬
‫اینجا به بررسی یک مثال جالب از کاربرد دستور ‪ Answer‬می‌پردازیم‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪108‬‬

‫فرض کنید دو کاربر ‪ 100‬و ‪ 101‬وجود داشــته باشــند‪ ،‬به‌طوری‌که بتوانند یکدیگر را شماره‌گیری کنند‪.‬‬
‫برنامه آن‌ها به صورت زیر و البته خیلی ساده است‪:‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 100,1,Dial(SIP/100‬‬
‫)‪exten => 200,1,Dial(SIP/200‬‬

‫با دســتور ‪ Dial‬می‌توان یک تماس جدید در استریســک به مقصد مشخص ایجاد نمود (در خصوص دستور‬
‫‪ Dial‬در همین فصل توضیحات الزم خواهد آمد)‪.‬‬
‫با اجرای این ســناریو‪ ،‬هرگاه شــماره ‪ 100‬یا ‪ 101‬را بگیریم‪ ،‬داخلی کاربران زنگ خواهد خورد‪ .‬اکنون‬
‫فرض کنید سناریوی فوق را به‌صورت زیر پیاده‌سازی کنیم‪.‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 100,1,Answer‬‬
‫)‪same => n,Dial(SIP/100‬‬
‫) (‪exten => 101,1,Answer‬‬
‫)‪same => n,Dial(SIP/101‬‬
‫) (‪exten => 200,1,Answer‬‬
‫)‪same => n,Playback( hello-world‬‬

‫در این ســناریو استفاده از دســتور ‪ Answer‬قبل از دستور ‪ Dial‬مناسب و کاربردی نخواهد بود‪ .‬همان‌طورکه‬
‫مالحظه می‌کنید تماس ازطریق خود استریسک پاسخ داده می‌شود و سپس داخلی مورد نظر زنگ می‌خورد‪.‬‬
‫اکنون ممکن است داخلی مورد نظر در دسترس نباشد‪ ،‬ولی تماس پاسخ داده شده‌است‪ .‬لذا توجه داشته‌باشید‬
‫که پیاده‌ســازی ســناریو‌ها در استریســک به این صورت‪ ،‬باعث می‌شــود در گزارشــات جزئیات تماس‌ها‬
‫‪1‬‬

‫مشکالتی به‌وجود آید‪ .‬لذا بهتر است سناریوی فوق را به‌صورت زیر بازنویسی کنیم‪.‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 100,1,Dial(SIP/100‬‬
‫)‪exten => 101,1,Dial(SIP/101‬‬
‫) (‪exten => 200,1,Answer‬‬
‫)‪same => n,Playback( hello-world‬‬

‫دستور ‪BackGround‬‬
‫فرض کنید از شــما خواســته شده که یک ســناریو برای یک شرکت یا ســازمان طراحی کنید؛ بهطوریکه‬
‫هرکس با شمارهی این سازمان تماس بگیرد‪ ،‬یک پیام خوشآمدگویی برای وی پخش شود تا داخلی مورد‬
‫نظر خود را وارد نماید‪ .‬بخش اول سناریو‪ ،‬پخش پیام خوشآمدگویی ‪ welcome‬به صورت زیر است‪.‬‬

‫]‪[LocalSets‬‬
‫)(‪exten => s,1,Answer‬‬
‫)‪same => n,Playback(welcome‬‬

‫)‪1- Call Detail Report (CDR‬‬


‫‪109‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫تا اینجا موفق به اجرای بخشی از سناریو شده‌ایم‪.‬سوالی که ممکن است پرسیده شود این است که ‪ s‬چه معنایی‬
‫می‌تواند داشته باشد؟ اجازه بدهید بعدا ً مفص ً‬
‫ال راجع به آن شرح دهیم ولی اینجا می‌توانید آن را با هر شماره‌ی‬
‫دیگری (جهت تست سناریو) جایگزین کنید (دقت کنید که قب ً‬
‫ال از آن شماره استفاده نکرده باشید)‪.‬‬
‫با اجرای ســناریو‪ ،‬پیام صوتی شــروع به پخش میکند‪ .‬نکته مهم این اســت که در این نوع از سناریوها‬
‫لزومی ندارد که حتماً پیام خوشآمدگویی تا انتها شــنیده شــود؛ بلکه باید این قابلیت وجود داشــته باشد که‬
‫ِ‬
‫پخش پیام صوتی‪ ،‬بتوانیم داخلی مورد نظر را شــمارهگیری کنیم‪ .‬اســتفاده از دستور ‪ Playback‬در‬ ‫در حین‬
‫یک چنین ســناریوهایی به هیچ وجه مناســب نیســت چون مخاطب مجبور میشــود تا انتهای پیام صوتی را‬
‫بشــنود و بعد شــماره داخلی مورد نظر خود را وارد کند؛ بنابراین‪ ،‬از دستور ‪ BackGround‬استفاده میکنیم‪.‬‬
‫دســتور ‪ BackGround‬دقیقا مانند دســتور ‪ Playback‬اســت‪ .‬اجازه دهید مثال قبل را با اســتفاده از دســتور‬
‫‪ BackGround‬دوباره بازنویسی کنیم‪.‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,Answer‬‬
‫)‪same => n,BackGround(welcome‬‬

‫تــا اینجا ما پیام صوتی را برای مخاطب پخش کردهایم‪ .‬اکنــون اگر مخاطب‪ ،‬داخلی مورد نظر را وارد کند‬
‫چه اتفاقی میافتد؟‬
‫اکثر سناریوها در سیستمهای تلفنی‪ ،‬حالت تعاملی دارند‪ .‬یعنی در حین اجرای دستورات‪ ،‬منتظر ورودی‬
‫از طرف مخاطباند تا بر اساس ورودی‪ ،‬مسیر تعیین شده را دنبال نمایند‪.‬‬
‫در مثال قبل‪ ،‬همان‌طورکه مالحظه می‌کنید ابتدا تماس توســط استریســک ‪ Answer‬می‌شود و بعد یک‬
‫فایــل صوتی پخش می‌گردد‪ .‬در حین اجــرای فایل صوتی‪ ،‬منتظر یک ورودی از طرف مخاطب نیز می‌ماند‪.‬‬
‫به محض دریافت ورودی (صرفنظر از اینکه فایل صوتی در حال پخش اســت)‪ ،‬پخش فایل صوتی متوقف و‬
‫ادامه ‪ Dialplan‬اجرا می‌شود‪.‬‬
‫اکنون می‌خواهیم ادامه ســناریو را تکمیل کنیم‪ .‬این کار بســیار ساده و راحت انجام می‌شود‪ .‬به مثال زیر‬
‫دقت کنید‪:‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,Answer‬‬
‫)‪same => n,BackGround(welcome‬‬
‫)‪same => n,WaitExten(5‬‬

‫)‪exten => 1,1,Playback(digits/1‬‬


‫)‪exten => 2,1,Playback(digits/2‬‬

‫معموالً زمانی که از مخاطب خواسته می‌شود تا داخلی مورد نظر خود را وارد کند‪ ،‬اندکی به او فرصت داده‬
‫می‌شود‪ .‬دستور ‪ WaitExten‬همین کار را انجام می‌دهد‪ .‬در این سناریو عالوه بر مدت زمانی که فایل صوتی‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪110‬‬

‫در حال پخش اســت‪ 5 ،‬ثانیه هم به مخاطب فرصت داده می‌شــود تا داخلی خود را وارد نماید‪ .‬برای آشنایی‬
‫بیشتر با ‪ ،WaitExten‬دستور زیر را وارد کنید‪.‬‬
‫‪CLI> core show application WaitExten‬‬

‫در این مثال بعد از ‪ Answer‬شدن تماس‪ ،‬فایل صوتی شروع به پخش‌شدن می‌کند‪ .‬پس از اتمام فایل صوتی‪،‬‬
‫به مدت ‪ 5‬ثانیه منتظر می‌ماند تا مخاطب عددی را وارد نماید‪ .‬با وارد کردن هر عدد‪ ،‬استریسک بهترین رول‬
‫را پیدا و اجرا می‌کند‪ .‬برای مثال اگر مخاطب عدد ‪ 1‬را وارد نماید‪ ،‬استریسک این دستور را اجرا می‌کند‪:‬‬
‫)‪exten => 1,1,Playback(digits/1‬‬

‫بنابراین فایل صوتی ‪ digit/1‬پخش می‌شود‪ .‬اگر عدد ‪ 2‬را وارد نمایید‪ ،‬استریسک این دستور را اجرا می‌کند‪:‬‬
‫)‪exten => 2,1,Playback(digits/2‬‬

‫در این حالت فایل صوتی ‪ digit/2‬اجرا می‌شــود‪ .‬نکته مهم اینجاســت که چگونه این ساختارها کنار هم قرار‬
‫می‌گیرند و اجرا می‌شوند‪ .‬در ادامه در مورد این موضوع و مثال‌های مرتبط با آن صحبت خواهیم کرد‪.‬‬
‫اگر بخواهیم مخاطب‪ ،‬داخلی مورد نظر را وارد کند باید برنامه مورد نظر به شکل زیر باشد‪:‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,Answer‬‬
‫)‪exten => s,n,BackGround(welcome‬‬
‫)‪exten => 100,1,Dial(SIP/100‬‬
‫)‪exten => 101,1,Dial(SIP/101‬‬

‫در این پیاده‌ســازی ســاده‪ ،‬فرض کردیم کــه فقط دو داخلی ‪ 100‬و ‪ 101‬داریــم‪ .‬در صورتی که داخلی‌های‬
‫بیشتری داشته باشیم باید آنها را نیز اضافه کنیم‪.‬‬
‫اگر مخاطب شــماره‌ای وارد کند که وجود نداشــته باشــد‪ ،‬تماس قطع می‌شــود‪ .‬در مثال قبل اگر کاربر‬
‫شــماره ‪ 102‬را وارد کند‪ ،‬در این صورت تماسش قطع خواهد شــد‪ .‬همچنین اگر کاربر هیچ عددی را وارد‬
‫نکند یا عددی به غیر از ‪ 1‬و ‪ 2‬را وارد کند‪ ،‬تماس پایان خواهد‌ یافت‪ .‬بیایید مثالی دیگر را با هم بررسی کنیم‪:‬‬
‫]‪[TestMenu‬‬
‫)(‪exten => 1000,1,Answer‬‬
‫)‪same => n,BackGround(enter-ext-of-person‬‬
‫)‪same => n,WaitExten(5‬‬
‫)‪exten => 1,1,Playback(digits/1‬‬
‫)‪same => n,Goto(TestMenu1,start,1‬‬
‫)‪exten => 2,1,Playback(digits/2‬‬
‫)‪same => n,Goto(TestMenu2,start,1‬‬

‫در این مثال کاربرانی که اجازه کار در کانتکســت ‪ TestMenu‬را دارند با شماره‌گیری ‪ 1000‬ابتدا تماس‬
‫‪ Answer‬می‌شــود‪ ،‬بعد فایل صوتی ‪ enter-ext-of-person‬پخش می‌شــود و سپس ‪ 5‬ثانیه منتظر می‌ماند تا‬
‫مخاطب شماره‌ای را وارد نماید‪ .‬اگر عدد وارد شده ‪ 1‬باشد فایل ‪ digits/1‬پخش می‌شود‪ .‬سپس با دستور ‪ Goto‬‬
‫‪111‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫به جایی دیگر منتقل می‌شود و اجرای دستورات از آنجا ادامه می‌یابد‪ .‬اگر عدد وارد شده ‪ 2‬باشد فایل ‪digits/2‬‬
‫پخش می‌شود و سپس دستور ‪ Goto‬اجرا می‌گردد‪.‬‬

‫دستور ‪Goto‬‬
‫از دســتور ‪ Goto‬برای پرش بین دســتورات استفاده می‌شــود‪ .‬گاهی نیاز داریم بر اساس شرایطی دستوراتی‬
‫خاص اجرا شوند‪ ،‬بر این اساس باید بتوانیم بین اجرای دستورات پرش داشته‌باشیم‪.‬‬
‫برای آشنا شدن با دستور ‪ Goto‬می‌توانید دستور زیر را در کامند‌الین استریسک اجرا کنید‪:‬‬
‫‪CLI> core show application Goto‬‬
‫]‪[Syntax‬‬
‫)‪Goto([[context,]extensions,]priority‬‬

‫این دستور در سه سطح می‌تواند اجرا شود‪:‬‬


‫ • پرش اجرای برنامه به یک اولویت خاص (برچسب)‬
‫ • پرش اجرای برنامه به یک اکستنشن و اولویت خاص‬
‫ • پرش اجرای برنامه به یک کانتکست‪ ،‬اکستنشن و اولویت خاص‬
‫برای درک بهتر موضوع به مثال زیر توجه کنید‪:‬‬
‫]‪[MyContext‬‬
‫)‪exten => 100,1,Goto(monkeys‬‬
‫)‪same => n,NoOp(We skip this‬‬
‫)‪same => n(monkeys),Playback(tt-monkeys‬‬
‫)(‪same => n,Hangup‬‬
‫‪exten => 200,1,Goto(start,1) ; play tt-weasels then tt-monkeys‬‬
‫‪exten => 300,1,Goto(start,monkeys) ; only play tt-monkeys‬‬
‫‪exten => 400,1,Goto(MyContext2,start,1) ; play hello-world‬‬
‫)(‪exten => start,1,NoOp‬‬
‫)‪exten => start,n,Playback(tt-weasels‬‬
‫)‪exten => start,n(monkeys),Playback(tt-monkeys‬‬

‫]‪[MyContext2‬‬
‫)(‪exten => start,1,NoOp‬‬
‫)‪exten => start ,n,Playback(hello-world‬‬
‫)(‪exten => start, n,Hangup‬‬

‫با در نظر گرفتن ســناریوی باال‪ ،‬اگر ما شــماره ‪ 100‬را بگیریم‪ ،‬در اولین اولویت دســتور ‪ Goto‬را داریم؛ لذا‬
‫باعث می‌شــود به خطی که دارای برچســب ‪ monkeys‬اســت‪ ،‬پرش کنیم‪ .‬در این نحوه پرش حتماً باید نام‬
‫اکستنشن یکسان باشد‪ .‬دستور فوق معادل دستور زیر است‪:‬‬
‫)‪exten => 100,1,Goto(MyContext ,100,monkeys‬‬

‫اینجا چون نام کانتکست و اکستنشن یکسان بود؛ آن‌ها را حذف کردیم‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪112‬‬

‫اگر شماره ‪ 200‬را بگیریم‪ ،‬دستور (‪ Goto (start,1‬اجرا می‌شود‪ .‬با اجرای این دستور ابتدا به اکستنشن ‪start‬‬
‫رفته و آنجا از دستوری با اولویت ‪ ،1‬اجرای دستورات را شروع می‌کنیم‪.‬‬
‫با شماره‌گیری عدد ‪ 300‬فقط دستور زیر اجرا می‌شود‪:‬‬
‫)‪exten => start, n(monkeys),Playback(tt-monkeys‬‬

‫با شماره‌گیری عدد ‪ ،400‬ابتدا به کانتکست ‪ MyContext2‬رفته‪ ،‬سپس از اولویت اول اکستنشن ‪ start‬شروع‬
‫به اجرای دستورات می‌کند‪ .‬شکل ‪ 3-5‬نحوه پرش بین دستورات را در مثال باال نمایش می‌دهد‪.‬‬

‫شکل ‪3-5‬‬
‫بیایید یک مثال دیگر را بررسی کنیم‪.‬‬
‫]‪[TestMenu‬‬
‫)(‪exten => 110,1,Answer‬‬
‫)‪same => n,BackGround(enter-ext-of-person‬‬
‫)‪same => n,WaitExten(5‬‬
‫)‪exten => 1,1,Playback(digits/1‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬
‫)‪exten => 2,1,Playback(digits/2‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬
‫)‪exten => i,1,Playback(pbx-invalid‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬
‫)‪exten => t,1,Playback(vm-goodbye‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال با شــماره‌گیری ‪ 110‬ابتدا تماس ‪ Answer‬می‌شــود؛ ســپس فایل صوتی ‪enter-ext-of-person‬‬
‫پخش می‌شود و ‪ 5‬ثانیه نیز منتظر ورود اطالعات از تلفن می‌ماند‪.‬‬
‫اگر عدد وارد شده ‪ 1‬باشد فایل ‪ digits/1‬پخش می‌شود و با دستور ‪ Goto‬به کانتکست ‪ TestMenu‬و سپس‬
‫اکستنشن ‪ 110‬و اولویت ‪ 1‬می‌رود‪.‬‬
‫‪113‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫اگر عدد وارد شده ‪ 2‬باشد فایل ‪ digits/2‬پخش می‌شود و با دستور ‪ Goto‬به کانتکست ‪ TestMenu‬و سپس‬
‫اکستنشن ‪ 110‬و اولویت ‪ 1‬می‌رود‪.‬‬
‫اگر کاربر عددی اشــتباه وارد نماید (بجز اعداد ‪1‬و‪ ،)2‬اکستنشــن ‪ i‬اجــرا و فایل ‪ pbx-invalid‬پخش‬
‫‪1‬‬

‫می‌شود و با دستور ‪ Goto‬به کانتکست ‪ TestMenu‬و سپس اکستنشن ‪ 110‬و اولویت ‪ 1‬می‌رود‪.‬‬
‫اگر کاربر در مدت زمان تعیین شــده عددی وارد نکند؛ اکتستنشن ‪ 2 t‬اجرا و فایل ‪ vm-goodbye‬پخش‬
‫می‌شود و با دستور ‪ Goto‬به کانتکست ‪ TestMenu‬و سپس اکستنشن ‪ 110‬و اولویت ‪ 1‬می‌رود‪.‬‬

‫دستور ‪Dial‬‬
‫یکی از مهمترین ویژگی‌های یک سیســتم تلفنی‪ ،‬توانایی برقراری تماس با سایر کاربران و ایجاد یک ارتباط‬
‫اســت‪ .‬این قابلیت زمانی که سیستم تلفنی استریسک کاربران زیادی داشــته باشد‪ ،‬کاربردی‌تر و با اهمیت‌تر‬
‫می‌شــود‪ .‬برای مثال فرض کنید دو کاربر در سیستم تلفنی استریســک بخواهند با هم تماس برقرار کنند و یا‬
‫کاربری بخواهد با مشــترکی در شــبکه‌های مخابراتی تلفنی(‪ )PSTN‬ارتباط برقرار کند؛ در این صورت باید‬
‫از دســتور ‪ Dial‬استفاده کند‪ .‬در این حالت سیستم تلفنی استریســک موظف است کانال‌های متعددی ایجاد‬
‫و ســپس بین آن‌ها ارتباط برقرار کند‪ .‬این ارتباط برقرار‌کردن بین کانال‌ها را در اصطالح ‪Channel Bridge‬‬
‫می‌گویند‪.‬‬
‫دســتور ‪ Dial‬در سیستم تلفنی استریسک‪ ،‬وظیفه شماره‌گیری و ایجاد تماس را بر عهده دارد‪ .‬برای آشنا‬
‫شدن با ساختار این دستور‪ ،‬در محیط کامند الین استریسک‪ ،‬این دستور را اجرا کنید‪:‬‬
‫‪CLI> core show application Dial‬‬
‫]‪[Syntax‬‬
‫)]]]‪Dial(Technology/Resource[&Technology2/Resource2[&...]][,timeout[,options[,URL‬‬

‫این دستور از چهار بخش تشکیل شده است که در ادامه به آنها خواهیم پرداخت‪.‬‬

‫آرگومان اول‪destination :‬‬


‫اولین آرگومان این دســتور‪ ،‬شماره‌ی مقصدی اســت که می‌خواهیم آن را شماره‌گیری و با آن تماس برقرار‬
‫کنیم‪ .‬این پارامتر از ترکیب زیر تشکیل شده است‪.‬‬
‫‪Technology/Resource‬‬

‫منظور از ‪ Technology‬همان ماژول‌های ‪ Channel Driver‬اســت که بوسیله آن‪ ،‬کاربرانی از نوع پروتکل‌های‬
‫‪ SIP,IAX2,DAHDI‬استفاده می‌شــوند‪ .‬به بیان دیگر منظور از ‪ Technology‬نوع تکنولوژی ارتباطی با سیستم‬
‫تلفنی اســت‪ .‬منظور از ‪ Resource‬همان شــماره‌ی مقصدی اســت که می‌خواهیم با آن تماس برقرار کنیم‪ .‬به‬

‫‪1- Invalid Extension‬‬


‫‪2- Timeout Extension‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪114‬‬

‫عنوان مثال فرض کنید بخواهیم با کاربری با شماره ‪ 100‬تماس بگیریم‪ ،‬در این صورت خواهیم داشت‪:‬‬
‫]‪[LocalSets‬‬ ‫}‪{Technology‬‬

‫)‪exten => 100,1,Dial(SIP/100‬‬


‫ ‬ ‫}‪{Resource‬‬

‫همان‌طورکه مالحظه می‌کنید چون این داخلی از طریق پروتکل ارتباطی ‪ SIP‬به ســرور متصل شده‌است‪ ،‬لذا‬
‫در قسمت ‪ Technology‬دستور ‪ Dial‬از عبارت ‪ SIP‬استفاده می‌کنیم‪.‬‬
‫اکنون فرض کنید بخواهیم از طریق سیســتم تلفنی استریســک‪ ،‬با شــبکه مخابراتی ‪ PTSN‬ارتباط برقرار‬
‫کنیم‪ .‬در این صورت داریم‪:‬‬
‫]‪[LocalSets‬‬
‫)}‪exten => _091X.,1,Dial(DAHDI/g0/${EXTEN‬‬

‫در ایــن حالت ما با مشــترک‪ ،‬از طریــق پروتکل ارتباطــی ‪ DAHDI‬ارتباط برقــرار کرده‌ایم‪ .‬در خصوص‬
‫کانال‌های ‪ DAHDI‬در فصل ششــم (ارتباط استریسک با شــبکه مخابراتی) توضیح بیشتری خواهد آمد‪ .‬در‬
‫دستور باال از الگوهای تطابق‪ 1‬نیز استفاده کرده‌ایم؛ به این صورت که هر شماره‌ای که با ‪ 091‬شروع شود‪ ،‬این‬
‫دستور اجرا می‌گردد‪ .‬منظور از عبارت{‪ $}EXTEN‬همان شماره‌ای است که ما وارد کرده‌ایم‪ .‬در فصل‌های‬
‫آینده درخصوص الگوهای تطابق توضیحات بیشتری خواهد آمد‪.‬‬
‫به‌عنوان یک مثال دیگر اگر خواســته باشــیم با شماره‌گیری ‪ ،203‬داخلی ‪ 203‬از نوع پروتکل ‪ SIP‬زنگ‬
‫بخورد باید اینگونه عمل کنیم‪.‬‬
‫)‪exten => 203,1,Dial(SIP/203‬‬

‫فرض کنید بخواهیم با شماره‌گیری ‪ ،203‬داخلی ‪ 203‬از نوع پروتکل ‪ IAX2‬زنگ بخورد‪ .‬در این صورت باید‬
‫به شکل زیر عمل کنیم‪:‬‬
‫)‪exten => 203,1,Dial(IAX2/203‬‬

‫اگــر بخواهیم با پروتکل ‪ DAHDI‬کار کنیم‪ ،‬با روش‌های متعددی می‌توانیم از این قابلیت اســتفاده کنیم‪ .‬به‬
‫عنوان مثال‪:‬‬
‫)‪exten => 300,1,Dial(DAHDI/1‬‬

‫در ایــن حالــت هدف‪ ،‬برقــراری ارتباط با داخلی تعریف شــده به پورت اول کارت ‪ FXS‬اســت‪‌FXS ( .‬ها‬
‫ســخت‌افزارهایی هســتند که با اســتفاده از تکنولوژی ‪ DAHDI‬می‌توانیم روی آنهــا داخلی تعریف کنیم و‬
‫تلفن‌های آنالوگ را به آنها وصل نماییم)‪ .‬همچنین می‌توانیم از کانال‌های ‪ DAHDI‬با شبکه مخابراتی ‪PSTN‬‬
‫تماس برقرارکنیم‪.‬‬
‫برای عنوان مثال ‪:‬‬
‫)}‪exten => _X.,1,Dial(DAHDI/1/${EXTEN‬‬

‫‪1- Match Pattern‬‬


‫‪115‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫در این مثال هر عددی شــماره‌گیری شــود در متغیر{‪ $}EXTEN‬ذخیره و با دســتور ‪ Dial‬از کانال ‪ 1‬کارت‬
‫سخت‌افزاری ‪ FXO‬شماره‌گیری می‌شود‪ .‬در این حالت برای ما مهم است که خروجی تماس ما از یک پورت‬
‫خاص (پورت اول کارت ‪ )FXO‬خارج شود‪.‬‬
‫ولــی اگر پورت یا شــماره پورت خروجی مهم نباشــد می‌توانیم با قــرار دادن چندین پورت درون یک‬
‫گروه‪ ،‬از شماره گروه استفاده کنیم‪ .‬در این صورت با توجه به نوع سناریو‪ ،‬پورت خروجی مشخص می‌شود‬
‫و شماره مورد نظر را ‪ Dial‬می‌کند‪.‬‬
‫در فصل ششم (ارتباط استریسک با شبکه‌های مخابراتی) راجع به این موضوع بیشتر توضیح داده می‌شود‪.‬‬

‫آرگومان دوم‪Time‌out :‬‬


‫دومین آرگومان در دســتور ‪ Dial‬مربوط به حداکثر مدت زمان زنگ خوردن مقصد اســت‪ ،‬به‌طوری‌که اگر‬
‫در مدت زمان مشخص شده تماس برقرار نشود‪ ،‬استریسک کنترل اجرای دستورات را ادامه داده و دستورات‬
‫با اولویت بعدی اجرا می‌شوند‪.‬‬
‫برای مثال برنامه زیر را در نظر بگیرید‪:‬‬
‫)‪exten => 500,1,Dial(DAHDI/1,20‬‬
‫)‪same => n,playback(vm-nobodyavail‬‬
‫) (‪same => n,hangup‬‬

‫در این مثال اگر کاربر (داخلی کانال ‪ 1‬از کارت ‪ ) FXS‬تماس را بعد از مدت ‪ 20‬ثانیه پاســخ ندهد‪ ،‬کنترل‬
‫برنامه به خط بعدی (اولویت بعدی اجرای دستورات) منتقل می‌شود و فایل صوتی « متاسفانه کاربر مورد نظر‬
‫در دسترس نیست» پخش می‌شود‪ .‬البته می‌توان قابلیت‌هایی به برنامه اضافه کرد‪ ،‬به‌طوری‌که اگر داخلی پاسخ‬
‫تماس را نداد تماس به سمت صندوق پستی داخلی هدایت شود‪.‬‬
‫)(‪exten => 501,1,NoOp‬‬
‫)‪same => n,Dial(SIP/501,20‬‬
‫)‪same => n,VoiceMail(501@default,u‬‬

‫در این مثال اگر کاربر ‪ 501‬تماس خود را طی مدت ‪ 20‬ثانیه پاسخ ندهد‪ ،‬دستور بعدی (صندوق پستی) اجرا‬
‫می‌شود‪ .‬در فصل هشتم (برنامه‌نویسی پیشرفته در استریسک) با قابلیت‌های صندوق پستی بیشتر آشنا خواهید‬
‫شد‪.‬‬
‫آرگومان سوم‪Options :‬‬
‫دستور ‪ Dial‬تعداد زیادی آپشن و قابلیت‌های قدرتمند دارد که درصورت نیاز می‌توانید از آنها استفاده کنید‪.‬‬
‫برای آشنایی کامل دستور ‪ Dial‬در محیط کامند الین استریسک‪ ،‬دستور زیر را تایپ نمایید‪.‬‬
‫‪CLI> core show application Dial‬‬

‫جدول ‪ 1-5‬خالصه‌ای از این آپشن‌ها را معرفی می‌کند و راهنمای استفاده از آن‌ها را شرح می‌دهد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 116

Option Note
A(x) Play an announcement (x.gsm) to the called party.
C Reset the CDR (Call Detail Record) for this call. This is like using the NoCDR command
c Sets the channel driver flag that the "call is answered elsewhere" if Dial() cancels the call
D After the called party answers, send digits as a DTMF stream, then connect the call to the
originating channel (you can also use 'w' to produce .5 second pauses).
d This flag trumps the 'H' flag and intercepts any single DTMF tone while waiting for the call
to be answered and jumps to that extension if it exists. This allows you to dial a 1-digit
exit extension while waiting for the call to be answered - see also RetryDial. This uses the
current context unless ${EXITCONTEXT} is defined.
e Execute "h" as the peer when this call ends
F(context^exten^pri) When the caller hangs up, transfer the called party to the specified context and extension
and continue execution.
f forces callerid to be set based on a dialplan "hint" for the current channel. For example,
some PSTNs don't allow callerids from other extensions than the ones that are assigned to
you.
G If the call is answered, transfer both parties to the specified context and extension. The
calling party is transferred to priority x, and the called party to priority x+1. This allows the
dialplan to distinguish between the calling and called legs of the call (new in v1.2). You
cannot use any options that would affect the post-answer state if this option is used.
g When the called party hangs up, continue to execute commands in the current context at the
next priority.
H Allow the caller to hang up by dialing * ( * is defined in features.conf -> featuremap ->
disconnect )
h Allow the callee to hang up by dialing * ( * is defined in features.conf -> featuremap ->
disconnect )
i Asterisk will ignore any forwarding requests it may receive on this dial attempt. (new in 1.4)
Useful if you are ringing a group of people and one person has set their phone to forwarded
direct to voicemail on their cell or something which normally prevents any of the other
phones from ringing.
j Asterisk 1.2 and later (1.6???): Jump to priority n+101 if all of the requested channels were
busy (just like behaviour in Asterisk 1.0.x)
K Allow the calling party to enable parking of the call by sending the DTMF sequence defined
for call parking in features.conf (Asterisk v1.4.x)
k Allow the called party to enable parking of the call by sending the DTMF sequence defined
for call parking in features.conf (Asterisk v1.4.x)
L(x[:y][:z]) Limit the call to 'x' ms, warning when 'y' ms are left, repeated every 'z' ms) Only 'x' is
required, 'y' and 'z' are optional. Numbers must be integers- beware of AGI scripts that may
return long integers in scientific notation (esp PHP 5.2.5&6) The following special variables
are optional for limit calls: (pasted from app_dial.c)
M(x) Executes the macro (x) upon connect of the call (i.e. when the called party answers).
m Provide Music on Hold to the calling party until the called channel answers. This is mutually
exclusive with option 'r', obviously. Use m(class) to specify a class for the music on hold.
N Modifies the privacy manager - turns off call screening if caller ID information is present
117 ‫برنامه‌نویسی مقدماتی در استریسک‬

Option Note
n(delete) If delete is 0 or not specified, delete the privacy manager introduction if the caller hangs up
before the call is answered. If set to 1, delete the recording even if the call is answered.
O(mode) If mode is set to 1 or isn't specified, ringback immediately if the originator hangs up. If mode
is set to 2, ring back when the operator flashes the trunk. This is only valid when the caller
and called channels are DAHDI channels. It is intended for calling an operator station.
o Restore the Asterisk v1.0 CallerId behaviour (send the original caller's ID) in Asterisk v1.2
(default: send this extension's number)
P(x) This option enables screening mode. This is basically Privacy mode without memory of how
to handle the caller.
p Indicate ringing to the calling party when the called party indicates ringing, pass no audio
until answered. This is available only if you are using kapejod's Bristuff.
R Generate a ringing tone for the calling party, passing no audio from the called channel(s)
until one answers. Without this option, Asterisk will generate ring tones automatically where
it is appropriate to do so; however, "r" will force Asterisk to generate ring tones, even if it is
not appropriate.
r Hangup the call n seconds AFTER called party picks up.
S(n) Allow the calling user to transfer the call by hitting the blind xfer keys (features.conf). Does
not affect transfers initiated through other methods.
T Allow the called user to transfer the call by hitting the blind xfer keys (features.conf)
t Does not affect transfers initiated through other methods.
U(x) Executes, via gosub, routine x on the called channel. This is similar to M above, but a gosub
rather than a macro.
W Allow the calling user to start recording after pressing *1 or what defined in features.conf
(Asterisk v1.2.x); requires Set(DYNAMIC_FEATURES=automon)
w Allow the called user to start recording after pressing *1 or what defined in features.conf
(Asterisk v1.2.x); requires Set(DYNAMIC_FEATURES=automon)
X Allow the calling user to start recording using automixer after pressing *1 or what defined in
features.conf (Asterisk v1.6)
x Allow the called user to start recording using automixer after pressing *1 or what defined in
features.conf (Asterisk v1.6)
1-5 ‫جدول‬

‫ از موزیک انتظار در زمان ایجاد تماس‬RingTone ‫به عنوان مثال فرض کنید بخواهیم به جای استفاده از‬
:‫ در این صورت خواهیم داشت‬.‫جدید استفاده کنیم‬
exten => 502,1,Dial(DAHDI/1,10,m)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()

‫ ما می‌توانیم‬.‫ استفاده می‌کنیم‬Dial ‫همان‌طورکه مالحظه می‌کنید از آپشن‌ها به‌عنوان آرگومان سوم در دستور‬
:‫برنامه باال را به‌صورت زیر نیز اجرا کنیم‬
exten => 502,1,Dial(DAHDI/1,,m)
same => n,Playback(vm-nobodyavail)
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪118‬‬

‫)(‪same => n,Hangup‬‬

‫همان‌طورکه مالحظه می‌کنید چون نیازی نداشتیم از آرگومان ‪ Timeout‬استفاده کنیم‪ ،‬جای آن را در دستور‬
‫‪ Dial‬خالی گذاشــتیم‪ .‬نکته مهم این است که حتما هنگام استفاده از دستور ‪ Dial‬و آرگومان‌های آن‪ ،‬ترتیب‬
‫آرگومان‌ها رعایت شود‪.‬‬

‫آرگومان چهارم‪URL :‬‬


‫آخرین آرگومان در دســتور ‪ ،Dial‬آرگومان ‪ URL‬می باشد‪.‬این آرگومان به دلیل وابستگی آن به تجهیزات‬
‫سخت افزاری و نرم افزاری کمتر قابل استفاده می باشد‪ .‬برای مثال اگر شما از ‪ IPPhone‬استفاده می کنید که‬
‫قابلیت پشتیبانی از ‪ URL‬را داشته باشد‪ ،‬در صورت دریافت ‪ URL‬آن را در صفحه نمایش خود نشان می دهد‪.‬‬

‫‪1‬‬
‫بررسی اکستنشن‌های خاص در استریسک‬
‫در استریســک برخی از اکستنشــن‌ها معانی خاصی دارند‪ .‬باید دقت داشته‌باشیم که در برنامه‌نویسی از آنها به‬
‫جز در موارد مشخص شده استفاده نکنیم‪ .‬در ادامه برخی از آنها را بررسی می‌کنیم‪:‬‬

‫‪ : h‬این اکستنشــن در زمان ‪ Hangup‬شــدن اجرا می‌شــود‪ .‬به عبارت دیگر زمانی که تماســی قطع می‌شــود‬
‫می‌توانیم دستورات مشخصی را در این اکستنشن اجرا کنیم‪.‬‬

‫‪ : i‬زمانی که از دســتورات ‪ BackGround‬و ‪ WaitExten‬اســتفاده می‌کنیــم و از کاربر می‌خواهیم عددی را‬


‫وارد نماید‪ ،‬اگر عدد وارد شــده در کانتکست جاری وجود نداشته باشد‪ ،‬کنترل برنامه به این اکستنشن منتقل‬
‫می‌شود و دستورات آن قسمت اجرا می‌شوند‪.‬‬

‫‪ : s‬این اکستنشــن بیشتر در کنار ماکروها و توابع استفاده می‌شود‪ .‬به طور کلی زمانی که بخواهیم یکسری از‬
‫دستورات را به صورت تکرار‪ ،‬صرف نظر از نام اکستنشن اجرا کنیم‪ ،‬از آن استفاده می‌کنیم‪ .‬در برخی موارد‬
‫به جای ‪ s‬از ‪ start‬نیز استفاده می‌شود‪ .‬در مثال‌های بعدی توضیح بیشتری خواهد آمد‪.‬‬

‫‪ : 2 t‬این اکستنشن به معنای تمام شدن مدت زمان پاسخ دادن است‪ .‬در صورتی که از دستورات ‪BackGround‬‬
‫و ‪ WaitExten‬استفاده کنیم‪ ،‬باید در یک زمان مشخص‪ ،‬عددی را وارد کنیم‪ ،‬در غیر این صورت بعد از پایان‬
‫یافتن زما ِن پاسخ؛ کنترل برنامه در اختیار این اکستنشن قرار می‌گیرد‪.‬‬

‫‪ : T‬این اکستنشــن به معنای مدت زمان فعال بودن یک تماس (کانال) در سیســتم است؛ به این معنی که وقتی‬
‫یک تماس وارد سیســتم می‌شود (ایجاد می‌شود) حداکثر طول عمر این تماس چقدر است‪ .‬برای مثال فرض‬

‫‪1- Specific Extension‬‬


‫‪2- Response timeout extension‬‬
‫‪119‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫کنید هر تماســی در سیستم ایجاد شــود‪ ،‬حداکثر ‪ 5‬دقیقه می‌تواند زمان داشته‌باشــد‪ .‬برای اینکار باید از تابع‬
‫‪ Timeout‬بصورت زیر استفاده کنیم‪:‬‬
‫]‪[incoming‬‬
‫)(‪exten => 111,1,NoOp‬‬
‫)‪exten => 111,n,Set(TIMEOUT(absulote)=300‬‬
‫)‪exten => 111,n,Dial(SIP/111‬‬

‫)‪exten => T,1,NoOp(Time is over‬‬


‫)(‪exten => T,n,Hangup‬‬

‫همان‌طورکه مالحظه می‌کنید نخســت حداکثر طول عمــر یک کانال تماس را روی ‪ 300‬ثانیه تنظیم کردیم‪.‬‬
‫اگر طول مدت زمان مکالمه بیشتر از ‪ 300‬ثانیه باشد‪ ،‬اجرای برنامه به اکستنشن ‪ T‬رفته و دستورات آن را اجرا‬
‫می‌کند‪.‬‬
‫نکته مهم این اســت که ما اینجا از تابع (و نه دســتور ) ‪ TIMEOUT‬اســتفاده‌کردیم‪ .‬در فصل‌های آینده‬
‫راجع به توابع استریسک توضیح خواهیم داد‪.‬‬
‫شاید این تصور ایجاد شود که می‌توانیم از این روش طول مدت زمان یک مکالمه را محدود کنیم‪ ،‬ولی‬
‫این روش برای محدود کردن مکالمه (بعد از پاســخ دادن‪ )1‬مناســب نیســت‪ .‬از این روش عمدتا برای کنترل‬
‫طول عمر یک کانال ایجاد شده در استریسک استفاده می‌شود‪ .‬برای مثال فرض کنید شرکتی از شما بخواهد‬
‫هر مخاطبی که به مجموعه زنگ می‌زند باید در مدت زمان مشــخصی (مثال ‪ 5‬دقیقه) پاســخ خود را بگیرد و‬
‫بعد از آن سیســتم باید مکالمه را بالفاصله قطع کند‪ .‬بنابراین ما هیچ‌گاه تماس‌هایی نخواهیم داشــت که بیش‬
‫از ‪ 5‬دقیقه در سیســتم به طول بینجامد‪ .‬در حالت دیگر‪ ،‬فرض کنید مدت زمان هر مکالمه (بعد از پاسخ دادن‬
‫تماس) نباید بیشــتر از ‪ 5‬دقیقه طول بکشــد‪ ،‬در این حالت باید از دستور ‪ Dial‬و پارامتر ‪ Limit‬برای انجام این‬
‫سناریو استفاده کنیم (جدول ‪.)1-5‬‬
‫برای فهم بهتر تفاوت این دو موضوع اجازه دهید مثالی را شرح دهیم‪ .‬فرض کنید از شما خواسته می‌شود‬
‫که مدت زمان مکالمه هر اپراتور در یک کال‌ســنتر را به ‪ 5‬دقیقه محدود کنید‪ .‬این کال‌ســنتر دارای ‪ 4‬لینک‬
‫ایــوان (‪ 120‬خط مســتقیم ورودی از مخابرات) اســت‪ .‬در زمان‌های پیک ترافیک‪ ،‬اگــر ما مدت زمان فعال‬
‫بودن کانال را روی ‪ 5‬دقیقه تنظیم کنیم‪ ،‬صرف نظر از اینکه آیا تماس هنوز در صف انتظار برای پاسخ دادن‬
‫اولین اپراتور اســت یا در حال صحبت با اپراتور‪ ،‬بعد از سپری شدن ‪ 5‬دقیقه بالفاصله تماس قطع می‌شود‪ ،‬اما‬
‫اگر مدت زمان مکالمه را به ‪ 5‬دقیقه محدود کنیم‪ ،‬در این حالت پس از پاســخ اپراتور‪ ،‬محاسبه ‪ 5‬دقیقه آغاز‬
‫خواهد شــد‪ .‬تفاوت اجرای هر دو سناریو به صورت زیر اســت‪ .‬در مثال اول مدت زمان فعال بودن کانال در‬
‫نظر گرفته می‌شود و در مثال دوم اگر تماس پاسخ داده شود‪ ،‬مدت زمان مکالمه لحاظ می‌گردد‪.‬‬

‫‪1- Channel Bridge‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪120‬‬

‫]‪[incoming‬‬
‫)(‪exten => 111,1,NoOp‬‬
‫)‪exten => 111,n,Set(TIMEOUT(absulote)=300‬‬
‫)‪exten => 111,n,Dial(SIP/operators‬‬

‫]‪[incoming‬‬
‫)(‪exten => 111,1,NoOp‬‬
‫))‪exten => 111,n,Dial(SIP/operators,,L(300000,2400000,2300000‬‬

‫‪ : e‬می‌توان از این اکستنشن به جای اکستنشن‌های ‪ t ، T‬و ‪ i‬استفاده کرد‪ .‬اغلب زمانی که نخواهیم به تفکیک‬
‫هر اکستنشــن را در سیســتم تحلیل کنیم‪ ،‬از این اکستنشــن اســتفاده می‌کنیم‪ .‬به عنوان مثال می‌توان به جای‬
‫اکستنشن‌های ‪ i‬و ‪ t‬از اکستنشن ‪ e‬به صورت زیر استفاده کرد‪:‬‬
‫]‪[TestMenu‬‬
‫)(‪exten => 110,1,Answer‬‬
‫)‪same => n,BackGround(enter-ext-of-person‬‬
‫)‪same => n,WaitExten(5‬‬
‫)‪exten => 1,1,Playback(digits/1‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬
‫)‪exten => 2,1,Playback(digits/2‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬
‫)(‪exten => e,1,NoOp‬‬
‫)‪same => n,Goto(TestMenu,110,1‬‬

‫کنترل و مدیریت تماس‌های همزمان در سیستم تلفنی استریسک‬


‫برخی مواقع شــرایطی پیش می‌آید که بیش از یک تماس به سیســتم تلفنی استریســک تحمیل می‌شــود‪ .‬ما‬
‫بایــد بتوانیم به‌ درســتی آنها را مدیریت و کنترل کنیم‪ .‬فرض کنید با یک شــماره تماس گرفته‌اید‪ .‬یک پیام‬
‫خوشــامدگویی اولیه برای شــما پخش می‌شــود و از شــما می‌خواهد برای ارتباط با بخش فروش عدد ‪ 1‬و‬
‫پشتیبانی عدد ‪ 2‬را وارد نمایید‪ .‬در هر بخش چندین اپراتور وجود دارد‪ .‬اکنون سؤال اینجاست که تماس باید‬
‫به کدام اپراتور وصل شود و این ترتیب چگونه باید باشد‪ .‬در ادامه دو سناریوی ساده را بررسی می‌کنیم‪.‬‬

‫کنترل و مدیریت تماس‌ها به صورت پشت سر‌هم‬


‫در این حالت با توجه به برنامه نوشته شده در زیر‪ ،‬ابتدا داخلی ‪ 200‬برای مدت ‪ 30‬ثانیه زنگ می‌خورد‪ .‬اگر‬
‫داخلی مشغول یا تماس بی‌پاسخ باشد داخلی ‪ 201‬زنگ می‌خورد و نهایتاً داخلی ‪ 202‬شروع به زنگ خوردن‬
‫می‌کند‪.‬‬
‫در نظر داشــته باشید اگر داخلی ‪ 200‬در ابتدا تماس را پاسخ دهد‪ ،‬دیگر تماس به سمت داخلی‌های ‪201‬‬
‫و ‪ 202‬نخواهد رفت‪ .‬لذا بدیهی است ترافیک تماس روی داخلی ‪ 200‬نسبت به سایر داخلی‌های ‪ 201‬و ‪202‬‬
‫‪121‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫بیشتر خواهد شد‪.‬‬


‫) (‪exten => s,1,Answer‬‬
‫)‪same => n,BackGround(welcome‬‬
‫)‪same => n,waitExten(5‬‬
‫)‪exten => 1,1,Dial(SIP/200,30‬‬
‫)‪same => n,Dial(SIP/201,30‬‬
‫)‪same => n,Dial(SIP/202,30‬‬

‫کنترل و مدیریت تماس‌ها به صورت همزمان‬


‫روش پیشنهادی بهتری را در نظر بگیریم که ترافیک تماس‌های ورودی روی هر سه داخلی به‌صورت مساوی‬
‫تقســیم شــود‪ .‬در این حالت منظور ما این است که زمانی که تماس جدید وارد سیستم می‌شود هر سه داخلی‬
‫باهم شروع به زنگ خوردن کند و هر داخلی که تماس را پاسخ داد‪ ،‬زنگ خوردن سایر داخلی‌ها قطع شود‪.‬‬
‫لذا برنامه را به صورت زیر تغییر می‌دهیم‪:‬‬
‫) (‪exten => s,1,Answer‬‬
‫)‪exten => s,n,BackGround(welcome‬‬
‫)‪exten => s,n,waitExten(5‬‬
‫)‪exten => 1,1,Dial(SIP/200 & SIP/201 & SIP/202‬‬

‫البته در فصل نهم (آشنایی با صف‌ها‪ 1‬در استریسک) روش‌های بهتری را بررسی خواهیم کرد و مفاهیم پیاده‬
‫سازی کال سنتر را شرح خواهیم داد‪ .‬تا اینجا شما با یکی از مهمترین دستورات استریسک آشنا شدید‪ .‬برای‬
‫مرور آنچه تا اکنون توضیح داده شد‪ ،‬بیایید مثالی را با هم بررسی کنیم‪.‬‬
‫]‪[TestMenu‬‬
‫)(‪exten => start,1,Answer‬‬
‫)‪same => n,BackGround(enter-ext-of-person‬‬
‫)‪same => n,WaitExten(5‬‬
‫)‪exten => 1,1,Dial(SIP/0000FFFF0001,10‬‬
‫)‪same => n,Playback(vm-nobodyavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪exten => 2,1,Dial(SIP/0000FFFF0002,20‬‬
‫)‪same => n,Playback(vm-nobodyavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪exten => i,1,Playback(pbx-invalid‬‬
‫)‪same => n,Goto(TestMenu,start,1‬‬
‫)‪exten => t,1,Playback(vm-goodbye‬‬
‫)(‪same => n,Hangup‬‬

‫همان‌طورکه پیش‌تر توضیح دادیم وقتی برنامه با اکستنشن ‪ s‬یا ‪ start‬شروع می‌شود به این معنی است که این‬
‫‪ Dialplan‬ازجایی دیگر فراخوانی می‌شود‪ .‬برای مثال فرض کنید این فراخوانی به صورت زیر باشد‪:‬‬
‫]‪[incoming‬‬

‫)‪1- Automatic Call Distribution (ACD‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪122‬‬

‫)(‪exten => 1212,1,NoOp‬‬


‫)‪same => n,Goto(TestMenu,start,1‬‬

‫همان‌طورکــه مالحظــه می‌کنید با شــماره‌گیری ‪ 1212‬کنترل اجــرای برنامه به کانتکســت [‪ ]TestMenu‬و‬


‫اکتنسشــن ‪ start‬با اولویت اول منتقل و دستورات آن اجرا می‌شود‪ .‬اینجا چون شماره اکستنشن اهمیتی ندارد‬
‫ما از اکستنشن‌های ویژه ‪ s‬یا ‪ start‬استفاده می‌کنیم‪.‬‬
‫بعد از انتقال کنترل برنامه به کانتکست [‪ ، ]TestMenu‬در گام اول تماس (کانال) ‪ Answer‬می‌شود و سپس‬
‫فایــل صوتــی ‪ enter-ext-of-person‬پخش می‌شــود و ‪ 5‬ثانیه منتظر ورود اطالعــات از مخاطب می‌ماند‪ .‬در‬
‫صورت وارد کردن عدد ‪ ،1‬استریسک‪ ،‬شماره کاربر ‪ 0000FFFF0001‬از پروتکل ‪ SIP‬را شماره‌گیری می‌کند‬
‫و مدت ‪ 10‬ثانیه منتظر می‌ماند؛ چنانچه تماس پاسخ داده نشود فایل ‪ vm-nobodyavail‬پخش می‌شود و سپس‬
‫تماس قطع می‌گردد‪ .‬اگرکاربر شماره ‪ 2‬را وارد نماید‪ ،‬شماره کاربر ‪ 0000FFFF0002‬را شماره‌گیری می‌کند و‬
‫به مدت ‪ 20‬ثانیه منتظر می‌ماند‪ .‬اگر تماس پاسخ داده‌نشود فایل ‪ vm-nobodyavail‬پخش و تماس قطع می‌گردد‪.‬‬
‫اگر شماره‌ای (بجز اعداد ‪ 1‬و‪ ) 2‬وارد شود‪ ،‬کنترل اجرای برنامه به اکستنشن ‪ i‬رفته و پیام ‪pbx-invalid‬‬
‫پخش می‌شود و سپس بوسیله دستور ‪ Goto‬به کانتکست [‪ ]TestMenu‬و اکستنشن ‪ start‬و اولویت ‪ 1‬می‌رود‬
‫و برنامه مجددا ً اجرا می‌شــود‪ .‬درصورتی‌که در ابتدای اجرا شدن برنامه ظرف ‪ 5‬ثانیه هیچ عددی وارد نشود‪،‬‬
‫کنترل اجرای برنامه به اکستنشن ‪ t‬رفته و پیام ‪ vm-goodbye‬پخش و سپس تماس قطع می‌شود‪.‬‬
‫این یک پیاده‌سازی ساده از طراحی یک ‪ 1 AA‬در سیستم تلفنی استریسک است‪ .‬البته در فصل چهاردهم‬
‫(ابزارهای برنامه‌نویسی در استریسک) راجع به طراحی ‪ AA‬و ‪ IVR‬در استریسک و جزئیات آن بیشتر توضیح‬
‫خواهیم داد‪ .‬آنچه تاکنون در این فصل مطرح شد معرفی چند دستور ساده و پرکاربرد در استریسک بود و نحوه‬
‫اســتفاده از آنها در قالب چند مثال شرح داده شــد‪ .‬اگر در هر یک از مثال‌های فوق ابهامی وجود داشت حتماً‬
‫بــه بخش مورد نظر مراجعه نمایید تا ابهامات برطرف گردد‪ .‬در ادامه این فصل به انواع متغیرها در استریســک‬
‫می‌پردازیم‪.‬‬

‫تعریف متغیرها در استریسک‬


‫حتما شما با مفهوم متغیرها در زبان‌های برنامه‌نویسی آشنایی کامل دارید‪ .‬متغیرها در زبان برنامه‌نویسی تعریف‬
‫می‌شــوند برای اینکه بتــوان کدهای منظم‌تر‪ ،‬خواناتر و در عین حال پیشــرفته‌تر ایجاد کرد‪ .‬در استریســک‬
‫می‌توان از متغیرها در برنامه‌نویسی استفاده نمود‪.‬‬
‫متغیر یک نام اســت که می‌تواند محتوایی را شــامل شود‪ ،‬برای شفاف‌تر شدن موضوع بهتر است با مثالی‬
‫آن را شرح دهیم‪.‬‬

‫‪1- Automatic Attendant‬‬


‫‪123‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫در شکل ‪ 4-5‬یک متغیر به‌نام ‪ SALE‬تعریف کرده و مقدار آن را ‪ SIP/300‬گذاشته‌ایم‪.‬‬

‫شکل ‪4-5‬‬
‫اکنون کد برنامه خود را به‌صورت زیر می‌نویسیم‪:‬‬
‫)‪exten => 300,1,Set(SALE=SIP/300‬‬
‫)}‪same => n,Dial(${SALE‬‬

‫در ایــن مثــال از دســتور‏‪ Set‬برای تعریف یک متغیر جدید اســتفاده کردیم‪ .‬اســم متغیــر ‪ SALE‬و مقدار آن‬
‫‪ SIP/300‬اســت‪ .‬از متغیر ‪ SALE‬هر زمان که الزم باشــد استفاده می‌کنیم‪ .‬برای استفاده از محتوای ذخیره شده‬
‫در یک متغیر‪ ،‬عالمت{‪ $}Variable-Name‬را به کار می‌گیریم‪ .‬توجه داشته باشید که متغیرها نسبت به حروف‬
‫بزرگ و کوچک حســاس‌اند‪ .‬در استریســک انواع متفاوتی از متغیر‌ها وجود دارند که در ادامه به آنها خواهیم‬
‫پرداخت‪.‬‬

‫انواع متغیرها در استریسک‬


‫در استریسک سه نوع متغیر وجود دارد‪ :‬متغیرهای سراسری‪ ،1‬متغیرهای کانالی‪ ،2‬متغیرهای محیطی‪. 3‬‬

‫متغیرهای سراسری‬
‫پاره‌ای از متغیرها می‌توانند در استریســک تعریف شــوند که در کل محیط برنامه‌نویســی استریسک و همه‬
‫کانال‌های فعال در استریســک قابل استفاده ‌باشند‪ .‬از این نوع متغیرها در سایر زبان‌های برنامه‌نویسی هم دیده‬
‫می‌شود؛ به‌طوری‌که در روند اجرای برنامه‪ ،‬قابل رؤیت و استفاده‌اند‪ .‬این متغیرها در قسمت [‪ ]global‬از فایل‬
‫‪ extensions.conf‬قابل تعریف‌اند‪ .‬برای مثال‪:‬‬
‫]‪[globals‬‬
‫‪SALE = SIP/300‬‬

‫می‌تــوان در همه قســمتهای ‪ Dialplan‬در استریســک از متغیر{‪ $}SALE‬اســتفاده کــرد‪ .‬زمانیکه نیاز داریم‬
‫‪1- Global Variable‬‬
‫‪2- Channel Variable‬‬
‫‪3- Enviroment Variable‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪124‬‬

‫متغیرهای سراسری را در زمان اجرای برنامه (‪ )Runtime‬ایجاد کنیم‪ ،‬از تابع ‪ GLOBAL‬بهره می‌گیریم‪.‬‬
‫برای آشنا شدن با تابع ‪ GLOBAL‬دستور زیر را در کامند الین استریسک اجرا کنید‪:‬‬
‫‪CLI> core show function GLOBAL‬‬
‫]‪[Synopsis‬‬
‫‪Gets or sets the global variable specified.‬‬
‫]‪[Description‬‬
‫>‪Set or get the value of a global variable specified in <varname‬‬
‫]‪[Syntax‬‬
‫)‪GLOBAL(varname‬‬

‫برنامه زیر را در نظر بگیرید‪:‬‬


‫)‪exten => 400,1,Set(GLOBAL(FOO)=456‬‬

‫برای مثال با گرفتن شماره ‪ 400‬در این برنامه‪ ،‬متغیر سراسری ‪ FOO‬با مقدار ‪ 456‬بصورت ‪ GLOBAL‬تعریف‬
‫می‌شود‪ .‬برای استفاده از این متغیر‪ ،‬آن را به‌صورت زیر فراخوان کنید‪:‬‬
‫)} ‪exten => s,1,NoOp(FOO=${FOO‬‬

‫متغیرهای محلی‬
‫ایــن متغیرها به‌صورت محلی در کانال‌های جاری ایجاد می‌شــوند و مورد اســتفاده قرار می‌گیرند‪ .‬برخالف‬
‫متغیرهای سراســری‪ ،‬این متغیرها فقط در مدت زمانی که کانال فعال است قابل استفاده‌اند و بعد از قطع شدن‬
‫تماس (کانال) این متغیرها از بین می‌روند‪.‬‬
‫در استریســک متغیرهای محلی فراوانی وجود دارد و همچنین می‌توانند تعریف شوند‪ .‬به‌عنوان مثال یکی‬
‫از پرکاربرد‌ترین متغیرهای محلی ‪ ،‬متغیر{‪ $‌}EXTEN‬است که اشاره به شماره گرفته‌شده دارد‪ .‬در این کتاب‬
‫با انواع متغیر‌های محلی آشنا می‌شوید‪ .‬برای مثال دستور زیر یک متغیر محلی بنام ‪ MESPIO‬ایجاد می‌کند‪.‬‬
‫)‪exten => 401,1,Set(MESPIO=401‬‬
‫)}‪same => n,SayNumber(${MESPIO‬‬

‫متغیرهای محیطی‬
‫گاهی نیاز داریم به متغیرهایی در استریســک دسترســی داشته باشــیم که در لینوکس تعریف شده‌اند‪ .‬در این‬
‫صورت از تابع ‪ ENV‬استفاده می‌کنیم‪.‬‬
‫برای آشنا شدن با تابع ‪ ،ENV‬دستور زیر را در کامند الین استریسک اجرا کنید‪:‬‬
‫‪CLI> core show function ENV‬‬
‫]‪[Synopsis‬‬
‫‪Gets or sets the environment variable specified.‬‬
‫]‪[Description‬‬
‫‪Variables starting with ‹AST_› are reserved to the system and may not be set.‬‬
‫]‪[Syntax‬‬
‫)‪ENV(varname‬‬
‫‪125‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫هرچند ممکن اســت از این نوع دســتورات و توابع در استریسک استفاده زیادی نداشته باشید‪ ،‬در هر صورت‬
‫برای آشنایی بیشتر با آن‌ها‪ ،‬مثال زیر مفید است‪.‬‬
‫در لینوکس متغیرهایی از پیش تعریف شــده داریم‪ .‬برای مثال فرض کنید بخواهیم از متغیر ‪ HOME‬استفاده‬
‫کنیم‪ .‬اگر دستور زیر را در محیط لینوکس اجرا کنیم‪ ،‬خروجی زیر را خواهیم داشت‪:‬‬
‫‪# echo $HOME‬‬
‫‪/root‬‬

‫اکنون اگر بخواهیم از این متغیر در استریسک نیز استفاده کنیم‪ ،‬به صورت زیر عمل می‌کنیم‪:‬‬
‫)})‪exten => _X.,1,NoOp(${ENV(HOME‬‬
‫)(‪same => n,Hangup‬‬

‫با اجرای دستور فوق در استریسک مقدار متغیر ‪ HOME‬در کامند الین استریسک نمایش داده می‌شود‪.‬‬
‫‪-- Executing [incoming:1] NoOp("Console/dsp", "/root") in new stack‬‬
‫‪-- Executing [incoming:2] Hangup("Console/dsp", "") in new stack‬‬

‫همان‌طورکــه پیش‌تــر توضیح داده شــد‪ ،‬اســتفاده از متغیر‌های محلی و سراســری‪ ،‬بیشــترین کاربرد را در‬
‫برنامه‌نویســی استریســک دارند‪ .‬در ادامه برای آشــنایی بیشــتر با این نوع متغیر‌ها‪ ،‬به مثالی جامع و کاربردی‬
‫خواهیم پرداخت‪.‬‬
‫مثال زیر را در نظر بگیرید‪:‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 402,1,NoOp(Setting Golobal Variable‬‬
‫)‪same => n,Set(GLOBAL(VAR1)=value1‬‬
‫)})‪same => n,NoOp(VAR1=${GLOBAL(VAR1‬‬

‫)‪exten => 403,1,NoOp(Setting Channel Variable‬‬


‫)‪same => n,Set(VAR2=value2‬‬
‫)}‪same => n,NoOp(VAR2=${VAR2‬‬

‫همان‌طورکه مالحظه می‌کنید در مثال فوق دو متغیر از نوع سراســری و محلی تعریف کرده‌ایم‪ .‬اکنون مقدار‬
‫متغیر را چاپ می‌کنیم‪ .‬خروجی دستور فوق در زمان اجرا به صورت زیر است‪:‬‬
‫‪CLI> console dial 402@LocalSets‬‬
‫‪-- Executing [402@LocalSets:1] NoOp("Console/dsp", "Setting Golobal Variable") in new stack‬‬
‫‪-- Executing [402@LocalSets:2] Set("Console/dsp", "GLOBAL(VAR1)=value1") in new stack‬‬
‫‪== Setting global variable ‹VAR1› to ‹value1›-- Executing [402@LocalSets:3] NoOp("Console/dsp",‬‬
‫‪"VAR1=value1") in new stack‬‬

‫‪CLI> console dial 403@LocalSets‬‬


‫‪-- Executing [403@LocalSets:1] NoOp("Console/dsp", "Setting Channel Variable") in new stack‬‬
‫‪-- Executing [403@LocalSets:2] Set("Console/dsp", "VAR2=value2") in new stack‬‬
‫‪-- Executing [403@LocalSets:3] NoOp("Console/dsp", "VAR2=value2") in new stack‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪126‬‬

‫همان‌طورکه مالحظه می‌کنید هر دو مقدار متغیر در خروجی نشــان داده شــده‌اند‪ .‬اکنون فرض کنید در‬
‫جای دیگری بخواهیم از این دو متغیر تعریف‌شده در مثال قبل استفاده کنیم‪ .‬به این مثال توجه کنید‪:‬‬
‫]‪[LocalSets-2‬‬
‫)‪exten => 405,1,NoOp(Read Golobal Variable‬‬
‫)})‪same => n,NoOp(VAR1=${GLOBAL(VAR1‬‬

‫)‪exten => 406,1,NoOp(Read channel Variable‬‬


‫)}‪same => n,NoOp(VAR2=${VAR2‬‬

‫هنگام اجرای برنامه‪ ،‬خروجی زیر را داریم‪:‬‬


‫‪CLI> console dial 405@LocalSets-2‬‬
‫‪-- Executing [405@LocalSets-2:1] NoOp("Console/dsp", "Read Golobal Variable") in new stack‬‬
‫‪-- Executing [405@LocalSets-2:2] NoOp("Console/dsp", "VAR1=value1") in new stack‬‬

‫‪CLI> console dial 406@LocalSets-2‬‬


‫‪-- Executing [406@LocalSets-2:1] NoOp("Console/dsp", "Read channel Variable") in new stack‬‬
‫‪-- Executing [406@LocalSets-2:2] NoOp("Console/dsp", "VAR2=") in new stack‬‬

‫همان‌طورکه مالحظه می‌کنید‪ ،‬متغیر‌های سراسری در هر جایی از برنامه قابل دسترس و استفاده‌اند ولی متغیر‌های ‬
‫محلی فقط در حوزه محلی خود و تا زمانی که کانال فعال باشد‪ ،‬اعتبار دارند‪ .‬اینجا به متغیر محلی ‪ VAR2‬که در‬
‫جایی دیگر تعریف شده بود‪ ،‬دسترسی نداریم و مقدار آن خالی است‪.‬‬

‫متغیرهای وراثتی استریسک‬


‫در استریسک دو نوع متغیر وراثتی داریم‪:‬‬

‫متغیر‌های وراثتی تک گانه‪ :‬در این حالت یک متغیر در برنامه استریسک ایجاد می‌کنیم‪ ،‬ولی فقط یک بار در‬
‫کل استریسک می‌توانیم به آن ارجاع داشته‌باشیم و مقدار ذخیره شده در آن را بخوانیم‪.‬‬

‫متغیر وراثتی چندگانه‪ :‬در این حالت یک متغیر در برنامه استریســک ایجاد می‌کنیم‪ ،‬و هر زمان که بخواهیم‬
‫می‌توانیم در استریسک به آن ارجاع دهیم و مقدار ذخیره شده در آن را بخوانیم‪.‬‬
‫این نوع متغیر‌ها همانند متغیر‌های سراسری‌اند‪ .‬برای مثال در برنامه‌های زیر سه نوع متغیر داریم‪ .‬متغیر ‪VAR1‬‬

‫از نوع متغیر‌های محلی و تنها در کانال مربوطه فعال است‪.‬‬


‫متغیــر ‪ VAR2‬از نوع وراثتی تک گانه اســت و فقط می توانیــم یک بار در زمان نیاز به آن ارجاع نماییم‬
‫ومتغیر ‪ VAR3‬از نوع وراثتی چندگانه است و می‌توانیم هر چند بار که نیاز باشد به آن ارجاع داشته‌باشیم‪.‬‬
‫]‪[TEST‬‬
‫)‪exten => 100,1,Set(VAR1=1‬‬
‫)‪same => n,Set(_VAR2=2‬‬
‫)‪same => n,Set(__VAR3=3‬‬
‫‪127‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫)‪same => n,Dial(LOCAL/101@LocalTest‬‬

‫]‪[LocalTest‬‬
‫)}‪exten => 101,1,NoOp(${VAR1‬‬ ‫‪;not defined‬‬
‫ )}‪same => n,NoOp(${VAR2‬‬ ‫‪;VAR2=2‬‬
‫ )}‪same => n,NoOp(${VAR3‬‬ ‫‪;VAR3=3‬‬
‫)‪same => n,Dial(LOCAL/102@LocalTest‬‬

‫)}‪exten => 102,1,NoOP(${VAR1‬‬ ‫‪;not defined‬‬


‫ )}‪same => n,NoOp(${VAR2‬‬ ‫‪;not defined‬‬
‫ )}‪same => n,NoOp(${VAR3‬‬ ‫‪;VAR3=3‬‬

‫الگوریتم الگوی تطابق در استریسک‬


‫الگوی تطابق‪ 1‬در استریسک از لحاظ مکانیسم کاری بسیار شبیه مسیریابی ‪ IP‬در شبکه‌های کامپیوتری است‪.‬‬
‫در جدول مســیریابی بر اساس ‪ IP‬مبدأ و مقصد‪ ،‬خروجی مشخص و بسته‌ها مسیریابی و هدایت می‌شوند‪ .‬در‬
‫سیستم‌های تلفنی هم جدولی داریم که براساس ‪ 2 CallerID‬و ‪ ،3 DID Number‬مسیر مشخص و دستورات‬
‫الزم اجرا می‌شوند‪.‬‬
‫برای مثال وقتی فردی شــماره‌ای می‌گیرد ‪ ،‬بر اساس کانتکســت مشخص شده‪ ،‬استریسک درپی شماره‬
‫گرفته‌شده (اکستنشن) می‌گردد و اگر بتواند آن را پیدا کند‪ ،‬دستوراتش را اجرا می‌کند ‪.‬‬
‫آنچه در جســتجوی یک شماره (اکستنشــن) در یک کانتکســت اهمیت دارد این است که جستجو باید از‬
‫قواعد خاص و مشخصی پیروی کند‪ .‬این قواعد را الگوی تطابق می‌گوییم ‪.‬‬
‫به صورت پیش فرض‪ ،‬زمانی که کاربر شماره می‌گیرد‪ ،‬استریسک دقیقاً دنبال همان شماره‌ی گرفته‌شده‬
‫در کانتکســت مربوطه می‌گردد‪ .‬اگر آن شــماره وجود داشته باشد‪ ،‬دســتورات الزم اجرا می‌شوند ولی اگر‬
‫وجود نداشته باشد با استفاده از الگوی تطابق به دنبال تطبیق دادن یک الگو با شماره گرفته‌شده می‌گردد‪.‬‬
‫الگــوی تطابق با عالمت ( _ )‪ 4‬تعریف می‌شــود ‪ ،‬این عالمت به استریســک اعــام می‌کند که این یک‬
‫اکستنشن واقعی نیست بلکه در واقع یک الگوی تطابق است‪.‬‬
‫_ >= ‪exten‬‬

‫معموالً داخل الگوهای تطابق از حروف و عالمت‌هایی اســتفاده می‌شــود که هر کدام معنای خاصی دارند‪.‬‬
‫برای مثال‪:‬‬

‫‪1- Pattern Matching‬‬


‫‪2- Caller Identification (CID) or Calling Line Identification (CLID) or Calling Number Delivery (CND) or Calling‬‬
‫)‪Number Identification (CNID) or Calling Line Identification Presentation (CLIP‬‬
‫)‪3- Direct Inward Dialing (DID‬‬
‫‪1- underscore‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪128‬‬

‫‪ : X‬ایــن حــرف به معنای یک رقم بین ‪ 0‬تا ‪ 9‬اســت‪ .‬به عبارت دیگر اگر در الگــوی تطابق این حرف وجود‬
‫داشــت به جای آن می‌توان یک رقم بین ‪ 0‬تا ‪ 9‬را جایگرین کرد ‪ .‬برای مثال در برنامه‌ی زیر چنانچه عددی‬
‫بین ‪ 0‬تا ‪ 9‬گرفته شود‪ ،‬دستورات زیر اجرا می‌گردد‪.‬‬
‫)(‪exten => _X,1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫‪ : Z‬این حرف به معنای جایگزین کردن یک رقم بین ‪ 1‬تا ‪ 9‬است ‪ .‬برای مثال چنانچه در برنامه‌ی زیر عددی‬
‫بین‪ 1‬تا ‪ 9‬درنظر گرفته شود‪ ،‬دستورات زیر اجرا می‌شود‪.‬‬
‫)(‪exten => _Z,1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫‪ : N‬این حرف به معنای جایگزین‌کردن یک رقم بین ‪ 2‬تا ‪ 9‬است‪ .‬برای مثال در برنامه زیر چنانچه عددی بین‬
‫‪ 2‬تا ‪ 9‬درنظر گرفته شود‪ ،‬دستورات زیر اجرا می‌گردد‪.‬‬
‫)(‪exten => _N,1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫[‪ : ]a-b‬یعنی عددی بین ‪ a‬و ‪ b‬است‪ .‬برای مثال در برنامه‌ی زیر چنانچه عددی بین ‪ 5‬تا ‪ 8‬درنظر گرفته شود‪،‬‬
‫دستورات زیر اجرا می‌گردد‪.‬‬
‫)(‪exten => _[5-8],1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫[‪ : ]abcd‬یعنی یکی از اعداد ذکر شده داخل براکت ‪ a ،‬یا ‪ b‬یا ‪ c‬یا ‪ . d‬برای مثال در برنامه‌ی زیر چنانچه یکی‬
‫از اعداد ‪ 3‬یا ‪ 5‬یا ‪ 6‬یا ‪ 8‬درنظر گرفته شود‪ ،‬دستورات زیر اجرا می‌گردد‪.‬‬
‫)(‪exten => _[3568],1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫•‪ : 1‬نقطه به منزله تکرار حداقل یکی و حداکثر بی‌نهایت رقم و حرف اســت‪ .‬برای مثال برنامه زیر شامل همه‬
‫‪1- period‬‬
‫‪129‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫الگوهایی است که حداقل ‪ 2‬رقم باشد و رقم اول آن بین ‪ 0‬تا ‪ 9‬باشد‪:‬‬
‫)(‪exten => _X.,1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫در مثال باال دقت کنید الگو باید دســت کم شــامل یک رقم و هر چیز دیگری (حرف یا عدد) باشــد و چون‬
‫عالمت «‪ ».‬به منزله تکرار حداقل یک رقم اســت‪ ،‬می‌تواند حداکثر شــامل هر تعداد از ترکیب حرف و عدد‬
‫باشد‪.‬‬
‫!‪ : 1‬عالمت تعجب به منزله تکرار حداقل صفر و حداکثر بی‌نهایت رقم و حروف است‪ .‬برای مثال برنامه‌ی زیر‬
‫کلیه الگوهایی که حداقل یک رقم داشته‌باشند و رقم اول بین ‪ 0‬تا ‪ 9‬باشد را شامل می‌شود‪:‬‬
‫)(‪exten => _X!,1,Answer‬‬
‫‪same => n,do something‬‬
‫‪same => n,do something else‬‬
‫‪same => n,do one last thing‬‬
‫)(‪same => n,Hangup‬‬

‫دقت داشــته باشــید که الگو باید دست کم یک رقم داشته باشد و می‌تواند شامل هر تعداد رقم باشد‪ .‬عالمت‬
‫(!) در الگوی تطابق !‪ _X‬به منزله تکرار حداقل یک رقم است‪.‬‬

‫بررسی مثال‌هایی برای الگوریتم الگوی تطابق‬


‫برای روشن‌تر شدن مطلب‪ ،‬با مثال‌های بیشتر الگوریتم الگوی تطابق را توضیح می‌دهیم‪.‬‬

‫مثال ‪ )1‬الگوی تطابق زیر را در نظر بگیرید‪ .‬این الگوی تطابق چه شماره‌هایی را شامل می‌شود؟‬
‫‪exten => _ZXX,1, do something‬‬

‫این الگوی تطابق‪ ،‬هر شماره ‪ 3‬رقمی بین ‪ 100‬تا ‪ 999‬را شامل می‌شود (از قبیل ‪ 256‬یا ‪.)459‬‬

‫مثال ‪ )2‬الگوی تطابق زیر را در نظر بگیرید‪ .‬این الگوی تطابق چه شماره‌هایی را شامل می‌شود؟‬
‫‪exten => _9X.,1, do something‬‬

‫ایــن الگــوی تطابق‪ ،‬هر شــماره‌ی حداقل ‪ 3‬رقمی که رقم اول آن ‪ ،9‬رقــم دوم آن بین ‪ 0‬تا ‪ 9‬و مابقی آن هر‬
‫ترکیبی از حرف و عدد باشد‪ ،‬را شامل می شود‪( .‬از قبیل ‪ 911‬یا ‪ 90912‬یا ‪ 90939899‬یا ‪)90ab7‬‬

‫مثال ‪ )3‬الگوی تطابق زیر را در نظر بگیرید‪ .‬این الگوی تطابق چه شماره‌هایی را شامل می‌شود؟‬
‫‪exten => _ZXXXXXX,1, do something‬‬

‫‪1- bang‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪130‬‬

‫این الگوی تطابق‪ ،‬هر شماره‌ی ‪ 7‬رقمی را شامل می‌شود (از قبیل ‪ 2228045‬یا ‪.)4228045‬‬

‫مثال ‪ )4‬الگوی تطابق زیر را در نظر بگیرید‪ .‬این الگوی تطابق چه شماره‌هایی را شامل می‌شود؟‬
‫‪exten => _[2-5]6[02468].,1, do something‬‬

‫ایــن الگــوی تطابق‪ ،‬هر شــماره‌ی حداقل ‪ 4‬رقمی که رقم اول آن بین ‪ 2‬یا ‪ 3‬یــا ‪ 4‬یا ‪ ،5‬رقم دوم آن عدد ‪، 6‬‬
‫رقم سوم آن عدد ‪ 0‬یا ‪ 2‬یا ‪ 4‬یا ‪ 6‬یا ‪ 8‬و مابقی آن هر ترکیبی از حرف و عدد باشد‪ ،‬را شامل می‌شود (از قبیل‬
‫‪ 3685‬یا ‪ 262z‬یا ‪ 5660‬یا ‪.)566057ab‬‬

‫مثال‪ )5‬الگوی تطابق زیر را در نظر بگیرید‪ .‬این الگوی تطابق چه شماره‌هایی را شامل می‌شود؟‬
‫‪exten => _[0-9a-zA-Z].,1, do something‬‬

‫ایــن الگــوی تطابق‪ ،‬هر شــماره‌ی حداقــل دو‌ رقمی که رقم اول آن بیــن ( ‪ 0‬تا ‪ ) 9‬یا (‪ a‬تــا ‪ )z‬یا ( ‪ A‬تا ‪ ) Z‬‬
‫و رقــم دوم آن هــر ترکیبی از قبیل حرف یا عدد باشــد (مثل ‪ 0912117‬یــا ‪ 0098912117‬یا ‪ z0912117‬یا‬
‫‪ aZ0912117‬یا ‪ )0Az912117‬را شامل می‌شود‪.‬‬
‫منظور از حداقل رقم این است که باید ‪ 2‬رقم و یا بیشتر از ‪ 2‬رقم (تا بی‌نهایت) داشته باشیم‪.‬‬

‫مثال ‪ )6‬به عنوان یک مثال کاربردی فرض کنید بخواهیم الگوریتم الگوی تطابق را برای چهار سطح متفاوت‬
‫تعریف کنیم‪:‬‬
‫‪ -1‬داخلی‌های یک سیستم‪ :‬در این سطح فقط این قابلیت وجود دارد که بتوانیم داخلی‌های ‪3‬رقمی داخل‬
‫مجوعه را شماره‌گیری کنیم‪.‬‬
‫]‪[local‬‬
‫)}‪exten => _ZXX,1,Dial(SIP/${EXTEN‬‬

‫‪ -2‬تماس‌های درون شهری‪ :‬در این سطح فقط این قابلیت وجود دارد که بتوانیم شماره‌های دورن شهری‬
‫(هشت رقمی) را شماره‌گیری کنیم‪.‬‬
‫]‪[provinc‬‬
‫)}‪exten => _ZXXXXXXX,1,Dial(DAHDI/g0/${EXTEN‬‬

‫‪ -3‬تماس‌های برون شــهری‪-‬بین استانی‪ :‬در این سطح فقط این قابلیت وجود دارد که بتوانیم شماره‌های‬
‫برون‌شهری ‪ -‬بین استانی را شماره‌گیری کنیم‪.‬‬
‫]‪[national‬‬
‫)}‪exten => _0Z.,1,Dial(DAHDI/g0/${EXTEN‬‬

‫‪ -4‬تماس‌های برون‌کشوری‪ :‬در این سطح فقط این قابلیت وجود دارد که بتوانیم شماره‌های برون‌کشوری‬
‫را شماره‌گیری کنیم‪.‬‬
‫]‪[national‬‬
‫)}‪exten => _00Z. ,1,Dial(DAHDI/g0/${EXTEN‬‬
‫‪131‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫استفاده از متغیر‌های محلی{‪$}EXTEN‬‬


‫استفاده از الگوریتم الگوهای تطابق در برنامه‌نویسی استریسک‪ ،‬اهمیت استفاده از متغییر{‪ $‌}EXTEN‬را بیشتر‬
‫می‌کند‪ .‬شاید برای ما اهمیت داشته‌باشد که شماره‌ی واقعی گرفته‌شده چه چیزی بوده که با این الگو مطابقت‬
‫داشته و دستورات آن اجرا شده‌است‪ .‬به مثال زیر توجه کنید‪:‬‬
‫)(‪exten => _XXX,1,Answer‬‬
‫)}‪same => n,SayDigits(${EXTEN‬‬

‫پر واضح اســت که هر شــماره ســه رقمی با اعداد بین ‪ 0‬تــا ‪ 9‬را بگیریم با این الگــو مطابقت دارد‪ ،‬لذا‬
‫با اســتفاده از متغیر{‪ $‌}EXTEN‬متوجه می‌شــویم که چه شــماره‌ای گرفته شده‌اســت‪ .‬بــرای این منظور از‬
‫متغیر{‪ $‌}EXTEN‬استفاده می‌کنیم که به شماره گرفته‌شده‪ ،‬اشاره دارد‪.‬‬
‫)}‪exten => _X.,1,NoOp(${EXTEN‬‬

‫اصالح شماره‌ها در سیستم تلفنی استریسک‬


‫گاهی الزم اســت رقم‌هایی را از ابتدا و یا انتهای شماره‌ی گرفته‌شده حذف کنیم‪ .‬برای مثال فرض کنید اگر‬
‫شــماره‌ای با ‪ 9‬آغاز شود به منزله تماس خروجی در نظر گرفته می‌شود‪ .‬رقم اول آن یعنی ‪ 9‬باید حذف شود‬
‫و سایر ارقام به عنوان شماره واقعی تلقی شود‪ .‬در این حالت از تکنیک زیر استفاده می‌کنیم‪:‬‬
‫)}‪exten => _9X.,1,NoOp(${EXTEN:1‬‬

‫در ایــن حالــت اولین رقم آن (رقم ‪ )9‬از ابتدای شــماره حــذف و بقیه ارقام به عنوان شــماره در نظر گرفته‬
‫می‌شوند‪.‬‬
‫الگوی استفاده از متغیر{‪ $‌}EXTEN‬به صورت زیر است‪:‬‬
‫} ‪${EXTEN : x : y‬‬

‫‪ x‬و ‪ y‬هر یک معنای خاصی دارند که در زیر بررسی می‌شوند‪.‬‬

‫‪: 0>x‬تعداد ارقامی که باید از سمت چپ حذف شوند‪.‬‬


‫‪ : 0<x‬تعداد ارقامی که از سمت راست انتخاب شده را برمی‌گرداند ‪.‬‬
‫‪ : 0>y‬تعداد ارقامی که از سمت چپ انتخاب می‌شود را برمی‌گرداند ‪.‬‬
‫‪ : 0<Y‬تعداد ارقامی که باید از سمت راست حذف شود ‪.‬‬

‫به عنوان مثال فرض کنید شماره ‪ 98169671111‬را شماره‌گیری کرده‌ایم‪ .‬هرکدام از متغیر‌های زیر چه‬
‫زیر‌شماره‌ای از شماره اصلی را برمی‌گرداند‪:‬‬
‫)}‪exten => _X.,1,NoOp(${EXTEN‬‬

‫شماره ‪ 98169671111‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:1:3‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪132‬‬

‫شماره ‪ 816‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:4:7‬‬

‫شماره ‪ 9671111‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:-4:4‬‬

‫شماره ‪ 1111‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:2:-4‬‬

‫شماره ‪ 16967‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:-6:-4‬‬

‫شماره ‪ 67‬انتخاب می‌شود‪.‬‬


‫)}‪exten => _X.,1,NoOp(${EXTEN:1‬‬

‫شماره ‪ 8169671111‬انتخاب می‌شود‪.‬‬

‫لذا اســتفاده از الگوریتم الگوی تطابق باعث می‌شود که بتوانیم با استفاده از متغیر{‪ $‌}EXTEN‬هر ترکیبی از ‬
‫شماره مورد نظر خود را استخراج و از آن استفاده نماییم‪.‬‬

‫اولویت‌گذاری در الگوریتم الگوی تطابق‬


‫ممکن اســت این سوال مطرح شود که اگر استریســک بتواند بیش از یک الگوی تطابق برای شماره‌ای پیدا‬
‫کند‪ ،‬اولویت با کدام یک خواهد بود؟‬
‫در چنین شــرایطی استریســک از تکنیک ‪ MAX Match Pattern‬استفاده می‌کند‪ .‬با این روش‪ ،‬الگویی‬
‫انتخاب می‌شود که دارای یکی از شرایط زیر باشد‪:‬‬
‫‪ – 1‬بیشترین تطابق با ارقام را داشته‌باشد‪.‬‬
‫‪ – 2‬کمترین دامنه اعداد را داشته‌باشد‪.‬‬
‫شاید این قوانین کمی پیچیده به نظر برسند ولی می‌توان با مثالی آن‌ها را توضیح داد‪:‬‬
‫فرض کنید دو الگوی تطابق در برنامه خود داریم‪:‬‬
‫‪exten => _[4-9].,1,do something‬‬
‫‪exten => _X.,1,do something‬‬

‫برای هر الگو‪ ،‬دامنه اعداد را یادداشت می‌کنیم‪:‬‬


‫ ‪exten => _[4-9].,1,do something‬‬ ‫‪; 4,5,6,7,8,9‬‬
‫ ‪exten => _X.,1,do something‬‬ ‫‪;0,1,2,3,4,5,6,7,8,9‬‬

‫اکنون کدام یک از الگوهای زیر دارای دامنه کمتری از اعدادند؟ پر واضح اســت که الگوی تطابق اول‬
‫دامنــه‌ی کمتری دارد‪ ،‬پــس در تکنیک ‪ MAX Match Pattern‬این الگو دارای اولویت باالتری اســت‪ .‬لذا‬
‫اگر شــماره‌ای را بگیریم که در هر دو الگوی تطابق صدق کند‪ ،‬دســتور اول اجرا می‌شــود‪ .‬می‌توان در یک‬
‫‪133‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫دسته‌بندی کلی‪ ،‬اولویت‌های الگوی تطابق را به صورت زیر دسته‌بندی کرد‪:‬‬


‫ • اعداد به صورت صحیح‬
‫ • [ ] براکت‬
‫ • ‪N‬‬
‫ • ‪Z‬‬
‫ • ‪X‬‬
‫ • ‪.‬‬
‫ • !‬
‫فرض کنید برنامه‌ای به صورت زیر وجود داشته‌باشد‪:‬‬
‫]‪[example_context‬‬
‫‪exten => _6[1-9][1-9][1-9],1,do something‬‬
‫‪exten => _6ZZZ,1,do something‬‬
‫‪exten => _6X.,1,do something‬‬
‫‪exten => _6199,1,do something‬‬

‫همان‌طورکه مالحظه می‌کنید در این برنامه الگوهای تطابق متفاوتی وجود دارد‪ .‬اکنون فرض کنید بخواهیم‬
‫شماره ‪ 6199‬را شماره‌گیری کنیم‪ ،‬سوال اینجاست که کدام یک از الگوها در نظر گرفته خواهد شد؟‬
‫ایــن نکته را در نظر داشته‌باشــید کــه اولویت در تعریف الگوهای تطابق‪ ،‬مــاک انتخاب الگوی تطابق‬
‫نیســت‪ .‬سیستم تلفنی استریسک به صورت خودکار با در نظر گرفتن تکنیک ‪ MAX Match Pattern‬الگوی‬
‫تطابق مناسب را استفاده می‌کند‪.‬‬
‫شــاید ســوالی مطرح شود که استریســک کدامیک را ابتدا انتخاب می‌کند؟ در پاســخ به این سوال باید‬
‫بگوییم که اســتفاده از یک دســتور ســاده در محیط کامند الین استریسک می‌تواند پاســخ خوبی برای این‬
‫پرسش باشد‪:‬‬
‫در محیط کامند الین استریسک دستور زیر را اجرا کنید‪:‬‬
‫‪CLI> dialplan show 6199@example_context‬‬
‫] ›‪[ Context ‹example_context› created by ‹pbx_config‬‬
‫>= ›‪‹_6199‬‬ ‫‪1. do something‬‬ ‫]‪[pbx_config‬‬
‫‪‹_6[1-9][1-9][1-9]› => 1. do something‬‬ ‫]‪[pbx_config‬‬
‫>= ›‪‹_6X.‬‬ ‫‪1. do something‬‬

‫همان‌طورکه مالحظه می‌کنید دستورات بر اساس اولویت الگوهای تطابق مرتب شده‌اند‪.‬‬
‫بنابرایــن توجه داشته‌باشــید که ممکن اســت الگوهــای تطابق که تعریــف می‌کنید‪ ،‬با هم هم‌پوشــانی‬
‫داشته‌باشند‪ .‬در این حالت از تکنیک فوق برای انتخاب الگوی تطابق استفاده می‌شود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪134‬‬

‫آنچه تاکنون درباره الگوی تطابق توضیح دادیم‪ ،‬براســاس شماره گرفته شده (‪ )DID Number‬بود‪ .‬این‬
‫فرآیند الگوی تطابق می‌تواند برای شمارۀ تماس گیرنده (‪ )Caller ID‬نیز اتفاق بیافتد‪ .‬برای استفاده از الگوی‬
‫تطابق برای شماره تماس گیرنده از فرمت زیر استفاده کنیم‪:‬‬
‫)(‪exten => extension/_pattern,1, dosomething‬‬

‫بــرای مثال فــرض کنید چنانچه فردی با شــمارهای خاص )مثل موبایل( با شــما تماس بگیــرد‪ ،‬قصد دارید‬
‫پروسهای خاص برای او اجرا کنید‪:‬‬
‫)‪exten => _X. / _9891. ,1,Goto(Mobile_context,s,1‬‬

‫در این مثال اگر فردی با شماره موبایل تماس بگیرد‪ ،‬این تماس با الگوی باال تطابق داشته و تماس به سمت‬
‫کانتکست مربوطه هدایت میشود و دستورات آن اجرا میگردد ‪.‬‬
‫البته در شــبکه مخابراتی ایران‪ ،‬شــماره‌های موبایل ممکن اســت به یکی از این روش‌ها برای شما ارسال‬
‫شود‪:‬‬
‫‪91‬‬
‫‪9891‬‬
‫‪009891‬‬
‫‪00009891‬‬
‫در این حالت باید بتوانید با اســتفاده از تکنیک‌هایی که قب ً‬
‫ال توضیح دادیم‪ ،‬ارقام اصلی آن را تشخیص دهید‬
‫و آن‌ها را استخراج کنید‪.‬‬

‫استفاده از ‪ include‬در برنامه نویسی استریسک‬


‫همان‌طورکه در ابتدای فصل توضیح دادیم‪ ،‬با اســتفاده از کانتکســت‌ها می‌توان حوزه فعالیت اکستنشن‌ها را‬
‫از یکدیگر جدا نمود‬
‫‪.‬‬

‫شکل ‪5-5‬‬

‫برای مثال شــکل ‪ 5-5‬را در نظر بگیرید‪ .‬در این شــکل سه کانتکســت متفاوت تعریف شده‌است‪ .‬کانتکست‬
‫ســیاه می‌تواند به کل کانتکست‌های خاکستری و سفید دسترســی داشته‌باشد‪ .‬کانتکست خاکستری می‌تواند‬
‫‪135‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫به کانتکســت سفید دسترســی داشته‌باشــد‪ .‬ولی عکس این موضوع صادق نخواهد‌بود‪ .‬اگر بخواهیم با زبان‬
‫ریاضی این موضوع را بیان کنیم‪ ،‬به‌صورت زیر خواهد بود‪ :‬مجموعه سفید‪ ،‬زیرمجموعه خاکستری و هر دو‬
‫زیرمجموعه سیاه خواهند بود‪.‬‬
‫‪white ⊆ grey‬‬
‫‪white,grey ⊆ black‬‬
‫برنامه‌ی مربوط به عبارت فوق به‌صورت زیر است‪:‬‬
‫]‪[white‬‬
‫)(‪exten => 301,1,NoOp‬‬

‫]‪[grey‬‬
‫)(‪exten => 201,1,NoOp‬‬
‫‪include => white‬‬

‫]‪[black‬‬
‫)(‪exten => 101,1,NoOp‬‬
‫‪include => grey‬‬

‫برای روشن‌تر شدن موضوع‪ ،‬به یک مثال کاربردی از استفاده و کاربرد ‪ include‬اکتفا می‌کنیم‪.‬‬
‫فرض کنید کاربر‌هایی با نام ‪ Phone1‬و ‪ Phone2‬در سیستم تعریف شده‌باشند‪:‬‬

‫‪;sip.conf‬‬
‫]‪[phone1‬‬
‫‪context=white‬‬

‫]‪[phone2‬‬
‫‪context=black‬‬

‫کاربر ‪ phone۱‬سعی میکند شماره ‪ ۲۰۱‬را شمارهگیری نماید‪ .‬چون در این کانتکست ]‪ [white‬برای شماره‬
‫‪ ۲۰۱‬هیچ رولی در نظر گرفته نشده است‪ ،‬لذا خطایی مبنی بر اینکه چنین رولی در کانتکست ]‪ [white‬وجود‬
‫ندارد در محیط کامند الین استریسک مشاهده خواهیدکرد‪.‬‬
‫حال فرض کنید کاربر ‪ Phone2‬شماره ‪ 201‬را شماره‌گیری نماید‪ ،‬در این کانتکست [‪ ]black‬هم برای شماره‬
‫‪ 201‬هیچ رولی تعریف نشده است‪ ،‬ولی چون کانتکست [‪ ]gray‬به این کانتکست [‪ ]black‬اضافه شده‌است‪ ،1‬لذا‬
‫استریسک در آن کانتکست هم به دنبال رول مورد نظر (شماره ‪ )201‬می‌گردد‪ .‬در صورتی که آن را پیدا کند‪،‬‬
‫اجرا می‌کند‪.‬‬
‫بنابراین می‌توان با استفاده از ‪ include‬کردن رول‌ها و قوانین در یک کانتکس دیگر‪ ،‬از آن‌ها نیز استفاده‬

‫‪1- include‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪136‬‬

‫نمود‪ .‬البته استفاده از ‪ include‬ملزم به رعایت قوانین مربوط به آن است که باعث می‌شود در ایجاد و اجرای‬
‫برنامه‌های بزرگتر‪ ،‬با خطاهای منطقی روبرو نشویم‪ .‬در ادامه به بررسی آن‌ها خواهیم پرداخت‪.‬‬

‫قوانین استفاده از ‪include‬‬


‫گاهی نیاز داریم با درنظر گرفتن مالحظاتی‪،‬کانتکست‌ها را با سطوح دسترسی متفاوتی طراحی کنیم تا اجازه‬
‫دسترسی و شماره‌گیری شماره‌های خاص برای کاربرانی خاص وجود داشته‌باشد‪ .‬رعایت اصول امنیتی‪ ،‬یک‬
‫گام مهم در برقراری امنیت سافت سوئیچ ستریسک است‪ .‬در فصل هجدهم (امنیت سیستم تلفنی استریسک) ‬
‫این موضوع به تفصیل بررسی شده است‪.‬‬
‫اســتفاده از ‪ include‬در دایل پلن نویسی ممکن است باعث به‌وجود آمدن خطاهای منطقی بسیاری شود‬
‫که عملیات عیب‌یابی‪ 1‬را دشــوار کند‪ .‬برای روشــن‌تر شــدن مطلب با مثال‌های متعددی این موارد را بررسی‬
‫می‌کنیم‪.‬‬
‫برای شروع فرض کنید کاربری به صورت زیر داشته باشیم‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phone1‬‬
‫‪context=context_a‬‬

‫برای نمونه برنامه ساده زیر را در نظر بگیرید‪:‬‬


‫]‪[context_a‬‬
‫‪include => context_b‬‬
‫‪include => context_c‬‬

‫]‪[context_b‬‬
‫)‪exten => 333,1,Playback(letters/b‬‬

‫]‪[context_c‬‬
‫)‪exten => 333,1,Playback(letters/c‬‬

‫فرض کنید کاربر ‪ Phone1‬شماره ‪ 333‬را شماره‌گیری نماید به نظر شما خروجی دستور چه چیزی خواهد بود؟‬
‫البته از خواننده کتاب درخواست می‌کنیم قبل از اینکه پاسخ سوال را در ادامه مطالعه کند‪ ،‬اندکی راجع به این‬
‫موضوع تأمل نماید‪.‬‬
‫بعد از شــماره‌گیری ‪ 333‬توسط کاربر ‪ ،Phone1‬کنترل برنامه به ســمت [‪ ]context_a‬می‌آید و چون هیچ‬
‫رولی برای شــماره ‪ 333‬در این کانتکست وجود ندارد‪ ،‬کنترل برنامه به سمت کانتکست [‪ ]context-b‬می‌رود‪.‬‬
‫در کانتکست [‪ ]context_b‬برای اکستنشن ‪ 333‬یک تعریف وجود دارد‪ ،‬بنابراین دستور (‪Playback (letters/b‬‬

‫‪1- troubleshooting‬‬
‫‪137‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫اجرا می‌شود‪.‬‬
‫اکنون فرض کنید برنامه را به شکل زیر تغییر دهیم‪.‬‬
‫]‪[context_a‬‬
‫‪include => context_c‬‬
‫‪include => context_b‬‬

‫]‪[context_b‬‬
‫)‪exten => 333,1,Playback(letters/b‬‬

‫]‪[context_c‬‬
‫)‪exten => 333,1,Playback(letters/c‬‬

‫با اجرای مجدد سناریوی قبل و شمارهگیری عدد ‪ ،۳۳۳‬خروجی دستور )‪ Playback (letters/c‬خواهد بود‪.‬‬
‫برای فهم بهتر مطلب‪ ،‬مثال زیر را به دقت بررسی کنید‪ .‬فرض کنید برنامه‌ی زیر را داشته باشیم‪:‬‬
‫]‪[context_1‬‬
‫)‪exten => 1,1,Playback(letters/a‬‬
‫)‪exten => 1,n,Goto(1‬‬
‫‪include => context_2‬‬

‫]‪[context_2‬‬
‫)‪exten => 1,1,Playback(letters/b‬‬
‫)‪exten => 1,n,Goto(1‬‬

‫)‪exten => 2,1,Playback(letters/c‬‬


‫)‪exten => 1,n,Goto(1,1‬‬

‫)‪exten => 3,1,Playback(letters/d‬‬


‫)‪exten => 3,n,Goto(context_2,2,1‬‬

‫خروجــی دســتور زیر چه خواهــد بود؟ به عبارتی دیگر اگــر کاربر عدد ‪ ۱‬را بگیرید‪ ،‬چه دســتوراتی اجرا‬
‫میشوند؟‬
‫‪CLI> console dial 1@context_1‬‬

‫در این مثال دســتور )‪ Playback (letters/a‬اجرا و در ادامه دســتور (‪ Goto(1‬اجرا میشــود‪ .‬این دستور‬
‫کنترل برنامه را به اولویت اول همان کانتکســت و اکستنشــن منتقل میکند‪ .‬پس برنامه در داخل یک ‪loop‬‬
‫قرار میگیرد و هر دفعه دستور )‪ Playback (letters/a‬اجرا میشود‪.‬‬
‫به عنوان مثالی دیگر‪ ،‬این برنامه را در نظر بگیرید‪:‬‬
‫]‪[context_1‬‬
‫)‪exten => 1,1,Playback(letters/a‬‬
‫)‪exten => 1,n,Goto(1‬‬
‫‪include => context_2‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪138‬‬

‫]‪[context_2‬‬
‫)‪exten => 1,1,Playback(letters/b‬‬
‫)‪exten => 1,n,Goto(1‬‬

‫)‪exten => 2,1,Playback(letters/c‬‬


‫)‪exten => 2,n,Goto(1,1‬‬

‫)‪exten => 3,1,Playback(letters/d‬‬


‫)‪exten => 3,n,Goto(context_2,2,1‬‬

‫خروجی دستور زیر چیست؟ به عبارت دیگر اگر کاربر عدد ‪ ۲‬را شمارهگیری کند‪ ،‬خروجی دستور چه‬
‫خواهدبود و چه برنامهای اجرا میشود؟‬
‫‪CLI> console dial 2@context_1‬‬

‫از آنجاکــه اکستنشــن‪ 2‬در داخــل [‪ ]context_1‬وجــود نــدارد‪ ،‬اجــرای دســتور در [‪ ]context_2‬ادامه‬
‫می‌یابــد‪ .‬در داخــل ایــن کانتکســت برای اکستنشــن‪ 2‬یــک رول تعریف شده‌اســت ‪ ،‬لذا برنامــه‌ی مربوط‬
‫بــه آن اجــرا می‌شــود‪ .‬به ایــن ترتیــب کــه ابتــدا دســتور (‪ playback (letters/c‬اجرا می‌شــود؛ بــا اجرای‬
‫دســتور (‪ Goto(1,1‬برنامــه بــه اولویــت اول اکستنشــن ‪ 1‬در کانتکســت [‪ ]context_1‬می‌رود و دســتور‬
‫‏(‪ playback (letters/a‬اجــرا می‌شــود؛ ســپس برنامــه وارد یــک ‪ loop‬می‌شــود کــه در آن فقط دســتور‬
‫(‪ playback (letters/a‬اجرا می‌شود‪.‬‬

‫]‪[context_1‬‬
‫)‪exten => 1,1,Playback(letters/a‬‬
‫)‪exten => 1,n,Goto(1‬‬
‫‪include => context_2‬‬

‫]‪[context_2‬‬
‫)‪exten => 1,1,Playback(letters/b‬‬
‫)‪exten => 1,n,Goto(1‬‬

‫)‪exten => 2,1,Playback(letters/c‬‬


‫)‪exten => 2,n,Goto(1,1‬‬

‫)‪exten => 3,1,Playback(letters/d‬‬


‫)‪exten => 3,n,Goto(context_2,2,1‬‬

‫همان‌طورکه مالحظه می‌کنید تفاوت زیادی بین کانتکست‌ها و دستورات وجود دارد‪ ،‬به‌طوری‌که ممکن است‬
‫خطا‌هایی منطقی در سیســتم ایجاد کند‪ .‬در مثال فوق دقت داشته باشید که دستور (‪ Goto(1,1‬مشخص شده به‬
‫[‪ ]context_1‬اتصال داده می‌شود‪.‬‬
‫‪139‬‬ ‫برنامه‌نویسی مقدماتی در استریسک‬

‫به عنوان مثالی دیگر این برنامه را در نظر بگیرید‪:‬‬


‫]‪[context_1‬‬
‫)‪exten => 1,1,Playback(letters/a‬‬
‫)‪exten => 1,n,Goto(1‬‬
‫‪include => context_2‬‬

‫]‪[context_2‬‬
‫)‪exten => 1,1,Playback(letters/b‬‬
‫)‪exten => 1,n,Goto(1‬‬

‫)‪exten => 2,1,Playback(letters/c‬‬


‫)‪exten => 2,n,Goto(1,1‬‬

‫)‪exten => 3,1,Playback(letters/d‬‬


‫)‪exten => 3,n,Goto(context_2,2,1‬‬

‫خروجی دستور زیر چه خواهد بود؟‬


‫‪CLI> console dial 3@context_1‬‬

‫در این حالت ابتدا دستور )‪ Playback (letters/d‬اجرا میشود؛ سپس توسط دستور )‪ Goto(context_2,2,1‬به‬
‫کانتکست ]‪ [context_2‬انتقال داده و دستور )‪ Playback (letters/c‬پخش میشود‪ .‬دستور )‪ Goto(1,1‬در این‬
‫حالت به سمت کانتکست ]‪ [۱_context‬نخواهد رفت بلکه در همان کانتکست ]‪ [context_2‬میماند و دستور‬
‫)‪ Playback (letters/b‬اجرا میشود‪.‬‬

‫استفاده از ‪ include‬در ساختار فایل‌سیستم استریسک‬


‫تــا اینجا کاربرد ‪ include‬در دایل پلن نویســی توضیح داده شــد‪ .‬از ‪ include‬همچنیــن میتوان در تعریف‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪140‬‬

‫فایلهای تو در تو در فایل سیســتم استریسک استفاده کرد‪ .‬اســتفاده از ‪ include‬در فایل سیستم استریسک‬
‫باعث کوچکتر شــدن فایلها در استریسک شده و بررسی و خطایابی را در استریسک آسانتر میکند‪ .‬به‬
‫عنوان مثال به جای آنکه تمام برنامهها را در استریســک در فایل ‪ extensions.conf‬بنویسیم‪ ،‬بهتر است یک‬
‫فایل دیگر را به شــکل ضمیه این فایل تعریف کنیم و از آن به عنوان فایل پیوســتی استفادهکنیم و برنامههای‬
‫خود را درون آن بنویسیم‪.‬‬
‫برای مثال فرض کنید بخواهیم برنامه‌های خود را در فایل دیگری بنویسیم‪ .‬یک فایل جدید با نام دلخواه‬
‫در مسیر دلخواه به صورت زیر بسازید‪.‬‬
‫‪#vim /etc/asterisk/routes_extensions.conf‬‬

‫ســپس برنامههــا را داخل آن اضافه میکنیم‪ .‬دقت داشــته باشــید قوانین نوشــتن برنامه دقیقــاً همانند فایل‬
‫‪ extensions.conf‬است‪.‬‬
‫]‪[new_context‬‬
‫)‪exten => 111,1,NoOp(This is new file that included to estension.conf‬‬
‫)‪same => n,NoOp(This syntax is the same as extensions.conf files‬‬
‫)(‪same => n,Habgup‬‬

‫اکنون برای آنکه این فایل جدید بوســیله استریسک قابل شناساییباشد‪ ،‬باید آن را به صورت زیر در انتهای‬
‫فایل ‪ extensions.conf‬اضافه کنیم‪:‬‬
‫‪#include routes-extensions.conf‬‬

‫در ایــن حالــت میتوانیم در فایلهای جدیــد‪ ،‬همانند فایــل ‪ extensions.conf‬برنامههــای خود را درج و‬
‫اجرا کنیم‪ .‬در فصول بعد موارد پیشــرفتهتری از برنامهنویســی در استریســک خواهد آمد و بررسی عمیقتر‬
‫برنامهنویسی در استریسک پیگرفته خواهد شد‪.‬‬

‫نتیجه گیری‬
‫همان‌طورکه پیش‌تر نیز بیان شد‪ ،‬ازآنجاکه این فصل یکی از فصل‌های اولیه و مهم در برنامه‌نویسی استریسک‬
‫اســت‪ ،‬اگر ابهامی در این فصل وجود داشته باشد‪ ،‬در ســایر فصل‌ها این ابهامات تشدید خواهد شد‪ .‬بنابراین‬
‫الزم است کلیه مطالب این فصل به‌صورت دقیق و با جزئیات بررسی و مطالعه شوند و همه مثال‌های آن دست‬
‫کم یک بار به‌صورت عملی تست و اجرا شوند‪.‬‬
‫فصل ششم‬

‫ارتباط استریسک با‬


‫شبکه‌های مخابراتی‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪142‬‬

‫ارتباط استریسک با شبکه‌های مخابراتی ‪PSTN‬‬

‫در فصل پنجم در خصوص برنامهنویســی در استریســک توضیح دادیم‪ .‬در این فصل و فصل بعد در مورد‬
‫ارتباط دادن سیســتم تلفنی استریسک با سایر شبکههای ارتباطی )شــبکههای مخابراتی ‪ PSTN‬و شبکههای‬
‫مبتنی بر ‪ (VoIP‬مطالبی ارائه خواهیم نمود‪.‬‬
‫ازآنجاکه تکنولوژی برقراری ارتباط در این دو بستر مخابراتی با یکدیگر متفاوت است‪ ،‬توضیحات مقدماتی‬
‫در این خصوص ضروری است‪ .‬برای مثال وقتی بخواهیم یک سیستم تلفنی استریسک را به شبکه‌های مخابراتی‬
‫‪ PSTN‬یــا یک شــبکه ویپ دیگر (‪ )VoIP Provider‬متصل کنیم‪ ،‬روش‌هــای متفاوتی وجود دارد‪ .‬با اینکه‬
‫تکنولوژی ارتباطی در هر دو روش کام ً‬
‫ال با هم متفاوت اســت‪ ،‬استریســک هر دو روش ارتباطی را به‌صورت‬
‫یکسان درنظر می‌گیرد‪.‬‬
‫در این فصل ابتدا در خصوص شــبکههای مخابراتی ‪ PSTN‬و انواع تکنولوژیهای آن صحبت میشود‬
‫و ســپس درباره ماژول ‪ DAHDI‬و پیکر بندی آن توضیحاتی ارائه خواهد شد‪ ،‬بهنحویکه خواننده به دالیل‬
‫اســتفاده از ماژول ‪ DAHDI‬واقف شــود‪ .‬پس از آن انواع شیوههای ارتباطی بررسی میشوند‪ .‬در فصل بعد‬
‫به ارتباط سیستم تلفنی استریسک با سایر شبکههای ‪ VoIP‬میپردازیم و انواع ارتباطات را بررسی و مقایسه‬
‫میکنیم‪.‬‬
‫در فصــل اول در خصوص شــبکههای مخابراتی ‪ PSTN‬مطالبی مقدماتی عنوان شــد‪ .‬در این فصل در‬
‫مورد انواع خطوط ارتباطی در شبکههای ‪ PSTN‬و نحوه ارتباط آنها در سیستم تلفنی استریسک توضیحات‬
‫بیشتری خواهد آمد‪.‬‬
‫ازآنجاکه در شــبکههای مخابراتی ‪ PSTN‬دو نوع خطوط مخابراتی داریم‪ ،‬بررســی روشهای ارتباط با‬
‫‪143‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫سیستم تلفنی استریسک در هر دو نوع ضرورت دارد‪.‬‬

‫انواع خطوط مخابراتی‬


‫خطوط مخابراتی به دو دسته کلی تقسیم می‌شوند‪:‬‬
‫‪1‬‬
‫‪ )1‬خطوط آنالوگ‬
‫‪2‬‬
‫‪ )2‬خطوط دیجیتال‬

‫خطوط آنالوگ‬
‫منظور از این خطوط‪ ،‬همان خطوط تلفنی معمولی است‪ .‬این خط پس از برداشتن گوشی و شنیدن بوق آزاد‪،3‬‬
‫‪ 64‬کیلوبیت پهنای باند را از مرکز مخابراتی رزرو می‌کند‪ .‬ازجمله دالیل استفاده از خطوط آنالوگ می‌توان‬
‫به موارد زیر اشاره کرد‪:‬‬
‫‪ -1‬نبود خطوط دیجیتال در یک منطقه؛‬
‫‪ -2‬هزینه اندک؛‬
‫‪ -3‬نگهداری خطوط قبلی‪.‬‬

‫انواع سیگنالینگ در خطوط مخابراتی آنالوگ‬


‫‪ -‬ســیگنالینگ ‪ FXO :4 FXO‬درگاهی اســت که برق (یا ســیگنال بوق) را دریافت می‌کند‪ .‬از این درگاه برای‬
‫اتصال خطوط آنالوگ شــبکه مخابرات ‪ PSTN‬به سیســتم‌های تلفنی استفاده می‌شــود‪ .‬برای ارتباط با خطوط‬
‫شهری مخابرات به درگاه‌های ‪ FXO‬نیاز خواهیم داشت‪.‬‬

‫‪ -‬سیگنالینگ ‪ FXS :5 FXS‬درگاهی است که برق (یا سیگنال بوق) را تولید می‌کند‪ .‬از این درگاه برای اتصال‬
‫گوشی‌های معمولی به سیستم استفاده می‌شود‪.‬‬

‫خطوط دیجیتال (‪)6 ISDN‬‬


‫ایده طراحی خطوط دیجیتال به اواســط دهه ‪ ۸۰‬میالدی باز می‌گردد‪ .‬هدف از آن جایگزینی سیســتم تلفنی‬
‫آنالوگ با دیجیتال بود تا بتواند داده‌های دیجیتال (صوت) را به‌خوبی پشــتیبانی کند‪ .‬در این توپولوژی صدا‬
‫ابتدا به داده‌های دیجیتال تبدیل‌ می‌شود و سپس انتقال می‌یابد (شکل ‪.)1-6‬‬

‫‪1- Analog telephony‬‬


‫‪2- Digital telephony‬‬
‫‪3- off hook‬‬
‫‪4- Foreign Exchange Office‬‬
‫‪5- Foreign Exchange Station‬‬
‫‪6- Integrated Services Digital Network‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪144‬‬

‫شکل ‪1-6‬‬

‫شــکل ‪ 1-6‬نحوه انتقال صوت در خطوط دیجیتال را نشــان می‌دهد‪ .‬ازجمله مزایای خطوط دیجیتال می‌توان‬
‫به موارد زیر اشاره کرد‪:‬‬
‫‪ )1‬بی‌تأثیر بودن افت ولتاژ برای فاصله‌های دور؛‬
‫‪ )2‬کاهش تأثیر نویز؛‬
‫‪ )3‬توانایی انتقال بیش از یک کانال در بستر ثابت؛‬
‫‪ )4‬سرعت باالی برقراری تماس‪.‬‬

‫انواع خطوط دیجیتال‬


‫شبکه مخابراتی ‪ ISDN‬به شاخه‌های متعددی تقسیم می‌شود‪:‬‬
‫‪1‬‬
‫‪B-ISDN‬‬
‫فناوری ‪ B-ISDN‬بر پایه فن ّاوری ‪ ATM‬اســتوار اســت که در شبکههایی با پهنای باند باال برای انتقال دادهها‬
‫اســتفاده میشــود‪ .‬در اکثر ‪Backbone‬ها )ازجمله شبکه دیتای مخابرات ایران( از این نوع شبکه استفاده می‬
‫شود‪.‬‬

‫‪2‬‬
‫‪N-ISDN‬‬
‫فناوری ‪ N-ISDN‬بهدلیل ســرعت نهچندان باال‪ ،‬در انتقــال دادهها و صدا برای کاربردهای خانگی و تجاری‬
‫اســتفاده میشود‪ .‬برای مثال اکثر خطوط ‪ PRI‬خانگی از نوع ‪ N-ISDN‬اند که بهصورت لینکهای ‪E1/T1/‬‬
‫‪ J1‬ارائه میشوند‪ .‬این فناوری بهنام ‪ Normal-ISDN‬نیز نامگذاری شدهاست‪.‬‬

‫‪3‬‬
‫‪ISDN-PRI‬‬
‫‪ ISDN-PRI‬یکی از استانداردهای خطوط دیجیتال است که دارای استانداردهای اروپایی )‪ ، (E1‬آمریکایی‬
‫)‪ (T1‬و ژاپنی )‪ (J1‬اســت‪ .‬در خطوط تلفنی معمولی )آنالوگ( صرفاً یک کانال برای ارتباط داریم ولی در‬
‫این خطوط تعداد کانالها بیش از یک است‪ .‬مث ً‬
‫ال در استاندارد آمریکایی )‪ ۲4 (T1‬کانال ارتباطی داریم که‬

‫‪1- Broadband ISDN‬‬


‫‪2- Narrowband ISDN‬‬
‫‪3- ISDN-Primary rate Interface‬‬
‫‪145‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫‪ ۲۳‬کانال برای انتقال دادههای دیجیتالی )‪ (D-Channels‬و یک کانال برای دادههای کنترلی و ســیگنالینگ‬
‫)‪ (B-Channel‬استفاده میشود‪ .‬تعداد کانالها در استاندارد اروپایی )‪ (E1‬به اینگونهاست که ‪ ۳۰‬کانال برای‬
‫انتقال دادههای دیجیتالی )‪ (D-Channels‬و یک کانال برای دادههای کنترلی و ســیگنالینگ )‪(B-Channel‬‬
‫اختصاص داده میشود‪.‬‬
‫درصورتیکه فاصله مرکز مخابرات با مشترک بیش از ‪ ۱۵۰‬متر باشد‪ ،‬برای استفاده از لینکهای ‪E1/T1‬‬
‫باید از دو دستگاه مودم ‪ 1 HDSL‬با دو سر ارتباط استفاده کرد‪ .‬معموالً یک دستگاه در مخابرات منطقه و‬
‫دستگاه دیگر در مرکز مشترک نصب میشود‪.‬‬

‫‪ISDN-BRI‬‬
‫‪ ISDN-BRI‬یکی از اســتانداردهای خطوط دیجیتال اســت که از دو کانال برای انتقال دادههای دیجیتالی و‬
‫استفاده میکند‪.‬‬ ‫یک کانال برای دادههای کنترلی و سیگنالینگ‬

‫سیگنالینگ کانال مرتبط‬


‫‪2‬‬

‫این نوع ســیگنالینگ جهت ارتبــاط مراکز موجود با یکدیگر اســتفاده می‌گردد و همواره ســیگنال‌ها روی‬
‫کانال‌هایی که ترافیک تلفنی را حمل می‌نمایند‪ ،‬بین مراکز رد و بدل می‌شود‪.‬‬
‫در ایــن تکنولوژی به ازای هر ‪ 30‬کانــال ترافیک تلفنی صدا‪ ،‬یک کانال ســیگنالینگ داریم و هم‌زمان‬
‫با ارســال ســیگنالینگ برای برقراری ارتباط‪ ،‬کانال‌های ارتباطی به منظور حمل ترافیک صدا نیز باید برقرار‬
‫گردد‪ .‬این‌یکی از معایب بزرگ این نوع سیگنالینگ‌هاســت‪ .‬عالوه بر این به دلیل انعطاف‌پذیری بســیارکم‬
‫سرویس‌دهی (با توجه به افزایش روزافزون سرویس‌ها)‪ ،‬این سرویس عم ً‬
‫ال کارایی الزم را ندارد‪.‬‬

‫‪3‬‬
‫سیگنالینگ کانال مشترک‬
‫از این نوع ســیگنالینگ همانند ســیگنالینگ )‪ (CAS‬به منظور برقراری ارتباط میان مراکز موجود اســتفاده‬
‫میشود‪ .‬به دلیل افزایش سرعت ارسال سیگنالها‪ ،‬یک کانال سیگنالینگ قادر به حمل حدود ‪ 8۰۰‬تا ‪۱۰۰۰‬‬
‫کانال ترافیک تلفنی صدا و اجرای مدیریت شــبکه است‪ .‬در این نوع سیگنالینگ‪ ،‬کانال سیگنالینگ مستقل‬
‫از کانال دیتاست؛ بنابراین مسیر سیگنالینگ و مسیر دیتا میتوانند از یکدیگر بطور کامل جدا باشند‪.‬‬
‫یکی دیگر از مزایای بسیار مهم این نوع سیگنالینگ‪ ،‬تشخیص و بررسی وضعیت مشترک‪ ،‬پیش از اشغال‬
‫کانال برای انتقال دیتاست‪ .‬یعنی ابتدا وضعیت مشترک بررسی میشود و در صورت آزاد بودن آن و آمادگی‬
‫تماس‪ ،‬فرمان ایجاد کانال دیتا از مشترک ‪ A‬به مشترک ‪ B‬صادر میگردد‪ .‬این امر باعث میشود بار ترافیکی‬
‫‪1- High-Bit-Rate Digital Subscribe Line‬‬
‫)‪2- Channel associated signaling (CAS‬‬
‫)‪3- Common Channel Signaling (CCS‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪146‬‬

‫اضافی برای تماسهای ناموفق بهدلیل مشــغول بودن یا عدم امکان دسترســی به مشترک انتهایی روی مراکز‬
‫تحمیل نشود و درنتیجه از کاهش معیار مخابراتی ‪ ASR‬جلوگیری گردد‪.‬‬

‫تئوری نایکوئیست‪-‬شانن‬
‫تئوری نمونه‌برداری نایکوئیســت ثابت می‌کند که اگر قصد نمونه‌برداری از یک ســیگنال را داشــته باشیم‪،‬‬
‫بایــد دو برابر پهنای بانــد موجود‪ ،‬نمونه‌برداری کنیم تا طیف فرکانســی آن‌ها باهم تداخل نکنند‪ .‬براســاس‬
‫تئوری نمونه‌برداری نایکوئیست‪ ،‬از صدا نمونه‌برداری می‌شود‪ ،‬سپس کوانتایز شده و به‌صورت باینری ارسال‬
‫می‌شود‪.‬‬
‫مطابق تئوری نایکوئیست در تلفن‌های معمولی‪ ،‬صدا را از فیلتر فرکانسی ‪ 4‬کیلوهرتز عبور می‌دهیم‪ .‬همچنین‬
‫به‌منظور بازســازی سیگنال نمونه‌برداری شده در مقصد باید نمونه‌برداری را با ‪ 8‬کیلوهرتز انجام دهیم‪ .‬از طرف‬
‫دیگر چون ما ‪ 8‬ســطح کوانتایز در شــبکه مخابراتی ‪ PSTN‬داریم‪ ،‬حاصل‌ضرب آن‌هــا عدد ‪ 64‬کیلوهرتز را‬
‫می‌دهد که معرف پهنای باند مصرفی در شبکه‌های مخابراتی ‪ PSTN‬است‪.‬‬
‫پهنای باند در شبکه‌های مخابراتی ‪ PSTN‬به‌صورت تضمین‌شده است و در یک ارتباط تلفنی ساده‪ ،‬پهنای‬
‫باند رزرو شده از شبکه مخابراتی ‪ 64×2 ، PSTN‬کیلوهرتز است‪.‬‬
‫‪ 8khz‬نرخ نمونه برداری × ‪ 8‬سطح کوانتایز= ‪) ۶4khz‬پهنای باند مصرفی برای یک تلفن شهری(‬

‫تبدیل صدای آنالوگ به صدای دیجیتال‬


‫برای صرفهجویی در هزینهها و جلوگیری از تعویض ســیمهای قدیمی‪ ،‬پس از دریافت درخواســت ارتباط‬
‫صوتی از طرف مبدأ به شــبکه ‪ ،PSTN‬دستگاه مبدل آنالوگ به دیجیتال آدرس مقصد را شناسایی میکند‬
‫و به مبدل ‪ ۱ A/D‬مقصد متصل میشــود و ســپس با استاندارد معروفی به نام ‪ ،۲ PCM‬در هر ثانیه ‪ 8۰۰۰‬بار از‬
‫روی ســیگنال آنالوگ صدا نمونهبرداری میشــود و معادل کدهای دیجیتال آن محاسبه و ارسال میگردد‪.‬‬
‫هدف از ‪ 8۰۰۰‬بار نمونهبرداری در ثانیه‪ ،‬انتخاب بهترین نوع فرکانس‪ ،‬دامنه و فاز بین بیتهای تعریفکننده‬
‫صداست تا در طرف گیرنده‪ ،‬صدایی معادل با صدای گوینده تولید شود‪ .‬در طرف گیرنده هم عملیاتی مشابه‬
‫طرف مبدأ صورت میگیرد )شکل ‪.(۲-۶‬‬
‫همان‌طورکه در شکل ‪ 3-6‬مشاهده می‌شود‪ ،‬بعد از ایجاد سیگنال آنالوگ به‌وسیله گوشی‪ ،‬نمونه‌برداری‬
‫از آن شروع می‌شود‪.‬‬

‫‪1- Analog to Digital‬‬


‫‪2- Pulse Code Modulation‬‬
‫‪147‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫شکل ‪2-6‬‬

‫شکل ‪3-6‬‬

‫برای ارســال صدا بهصورت دیجیتال‪ ،‬ابتدا صدای اولیه باید از فیلتر ‪ 4‬کیلو هرتز که در شــکل ‪ ۳-۶‬با نام‬
‫‪ low-pass filter‬مشــخص شــده اســت‪ ،‬بگذرد تا فرکانسهای اضافی و غیرقابل انتقال حذف شوند‪ .‬سپس‬
‫بــهازای هر ثانیه‪ 8۰۰۰ ،‬بار از صدای اصلی نمونه برداری میشــود )تئوری نایکویســت( که به آن ‪sampler‬‬
‫میگویند‪ .‬در گام بعدی بهازای هر سطح دامنه صدا‪ ،‬یک معادل قرار میدهند و سطح صدا را تا نزدیکترین‬
‫ســطوح آن گــرد میکنند که بــه آن ‪ quantizer‬میگویند )خروجی هر دو عملیات در شــکل ‪ ۳-۶‬نشــان‬
‫برنولی بیان میکنند که این عملیات بهوسیله ‪encoder‬‬ ‫دادهشــده اســت(‪ .‬در انتها هر ســطح را با یک مقدار‬
‫انجام میشود‪.‬‬

‫‪ DAHDI‬چیست؟‬
‫نــام قدیمیتــر ایــن محصول ‪ Zaptel‬بود‪ ،‬ولــی به این دلیل که یک شــرکت با همین نام تجــاری در زمینه‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪148‬‬

‫کارتهای تلفنی وجود داشــت‪ ،‬شــرکت دیجیوم ناچار به تغییر دادن نام این محصول تجاری شد و آن را به‬
‫‪ DAHDI‬تغییر داد‪.‬‬
‫‪ DAHDI‬یک تکنولوژی متن باز برای کنترل کارتهای تلفنی دیجیوم و سایر برندهاست‪ .‬این سرویس‬
‫دارای درایورهایی اســت که قادر اســت ســختافزارهای کارتهای تلفنی را به استریسک و سیستم عامل‬
‫لینوکس بشناساند و آنها را کنترل و مانیتور کند‪.‬‬
‫برخی فرآیندها در استریســک نیــاز به همزمانی دارند‪ .‬برای مثال برنامه کنفرانس تلفنی در استریســک‬
‫نیازمنــد همزمانــی بین همه کانالهاســت‪ .‬در این حالت نیاز بــه ماژولی داریم که ایــن همزمانی را بهوجود‬
‫آورد‪ .‬بــرای اســتفاده از همزمانی هنگام ایجاد یک کنفرانس در استریســک‪ ،‬باید لزومــا از ماژولی که این‬
‫همزمانــی بین کانالها را ایجاد کند‪ ،‬اســتفاده گردد‪ .‬این ماژول همزمانی‪ ،‬ازســوی استریســک و همچنین‬
‫ازسوی ماژول ‪ DAHDI‬فراهم میشود‪ .‬برخی از برنامهها در استریسک )از قبیل دستور ‪ ( MeetMe‬از ماژول‬
‫‪ res_timing_dahdi.so‬برای همزمانی بین کانالها اســتفاده میکنند‪ .‬بنابراین‪ ،‬وابستگی به ماژول ‪DAHDI‬‬
‫در برخی از برنامههای استریســک وجود دارد‪ .‬اگر چه برنامههای مشــابهی مثل ‪ ConfBridge‬وجود دارند‬
‫که جایگزین مناســبی برای برنامه ‪ MeetMe‬هســتند و از ماژولهای خود استریسک برای همزمانی استفاده‬
‫میکنند‪ ،‬بهتر اســت همیشه ماژول ‪ DAHDI‬را در کنار استریســک نصب داشته باشیم؛ حتی زمانی که هیچ‬
‫ارتباطی با شبکههای مخابراتی ‪ PSTN‬نداشته باشیم‪ .‬زمانی که از ‪Gateway‬ها برای اتصال خطوط شهری به‬
‫سیســتم تلفنی استریسک اســتفاده میکنیم‪ ،‬به ماژول ‪ DAHDI‬نیاز نداریم‪ ،‬ولی بهتر است این ماژول را هم‬
‫هنگام نصب استریســک نصب کنیم‪ .‬شــکل ‪ 4-۶‬نحوه ارتباط ماژول ‪ DAHDI‬با استریسک و سیستم عامل‬
‫لینوکس را نشان می دهد‪.‬‬

‫شکل ‪4-6‬‬
‫‪149‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫اجزای تشکیل دهنده ‪DAHDI‬‬


‫‪ DAHDI‬از دو کامپونت کام ً‬
‫ال مستقل تشکیل شده است‪:‬‬

‫‪ :DAHDI-tools -۱‬در این کامپوننت ابزارها و دســتوراتی برای مدیریت ارتباط سیســتم تلفنی استریسک با‬
‫شــبکههای مخابراتی ‪ PSTN‬فراهم شدهاســت‪ .‬از جمله این دستورات میتوان به ‪dahdi_cfg, dahdi-scan,‬‬
‫‪ dahdi-hardware‬و ‪ ...‬اشــاره کرد‪ .‬هر کدام از دستورات فوق کاربرد مشخصی دارند‪ .‬در ادامه توضیحات‬
‫بیشتری درباره آنها خواهد آمد‪.‬‬

‫‪ :DAHDI-linux -۲‬این کامپوننت فراهم کننده کرنل درایورهای ســختافزاری برای کارتهای ‪DAHDI‬‬
‫است‪ .‬به عبارت دیگر درایور سختافزاری برای کارت بهوسیله این کامپوننت فراهم میشود‪.‬‬

‫در اکثر نسخههای ‪ DAHDI‬که دانلود میکنید‪ ،‬هر دو کامپوننت در قالب نام ‪dahdi-linux-complete-‬‬
‫‪ current‬قرار دارند‪ .‬برای مثال دستورات زیر را در نظر بگیرید‪.‬‬
‫‪# tar –zxvf dahdi-linux-complete-current.tar.gz‬‬
‫‪# cd dahdi-linux-complete2.6.1+2.6.1/‬‬

‫همانطورکه مالحظه میکنید‪ ،‬بعد از اینکه بسته ماژول ‪ DAHDI‬را از حالت فشرده خارج کردیم‪ ،‬نام آن به‬
‫همراه اعدادی مانند )‪ (2.6.1+2.6.1‬ذخیره شــد‪ .‬نکته مهم در اینجا این است که این اعداد‪ ،‬ورژن کامپوننت‬
‫را مشخص میکنند‪ .‬عدد اول )سمت چپ عالمت ‪ ( +‬ورژن کامپوننت ‪ DAHDI-linux‬و عدد دوم )سمت‬
‫راست عالمت ‪ ( +‬ورژن کامپوننت ‪ DAHDI-tools‬را مشخص میکنند‪ .‬نحوه نصب این بسته در فصل سوم‬
‫کام ً‬
‫ال شرح داده شد‪.‬‬

‫پیکربندی ماژول ‪DAHDI‬‬

‫بعد از نصب ماژول ‪ ، DAHDI‬مســیر فایلهای پیکربندی در ‪ /etc/dahdi/‬قرار میگیرد‪ .‬دو فایل مهم به نام‬
‫‪ modules‬و ‪ system.conf‬در این شــاخه وجود دارند‪ .‬هر کدام از این فایلها قســمتی از پیکربندی ماژول‬
‫‪ DAHDI‬را انجام میدهند‪.‬‬

‫فایل ‪modules‬‬
‫ازآنجاکه کارتهای ســختافزاری متنوعی وجود دارد و هر کدام ســاختار منحصر بــه فرد خود را دارند‪،‬‬
‫ازطریق این فایل میتوان مشــخص کرد که ماژول ‪ ،DAHDI‬کدامیک از این نوع کارتها را باید پشتیبانی‬
‫کند یا اینکه کدامها باید غیرفعال شــوند‪ .‬با غیرفعال کردن یک ماژول خاص‪ DAHDI ،‬قادر به شناســایی‬
‫آن کارت سختافزاری نخواهد بود‪ .‬برای مثال فرض کنید بخواهیم فایل ‪ modules‬را باز کنیم‪ .‬دستور زیر‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 150

:‫را اجرا کنید‬


vim /etc/dahdi/modules

‫ این اطالعات را مشاهده‬،‫ بعد از باز شدن فایل‬.‫البته می‌توانید این فایل را با هر ویرایشگر دیگری نیز باز نمایید‬
:‫می‌کنید‬
#
# NOTE: Please add/edit /etc/modprobe.d/dahdi or /etc/modprobe.conf if you
# would like to add any module parameters.
#
# Format of this file: list of modules, each in its own line.
# Anything after a ‹#› is ignore, likewise trailing and leading
# whitespaces and empty lines.

# Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1


# Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
# Digium TE220: PCI-Express dual-port T1/E1/J1
# Digium TE420: PCI-Express quad-port T1/E1/J1
wct4xxp
# Digium TE435
# Digium TE235
wcte43x
# Digium TE120P: PCI single-port T1/E1/J1
# Digium TE121: PCI-Express single-port T1/E1/J1
# Digium TE122: PCI single-port T1/E1/J1
wcte12xp
# Digium TE131: PCI-Express single-port T1/E1/J1
# Digium TE132: PCI single-port T1/E1/J1
# Digium TE133: PCI-Express single-port T1/E1/J1 with hardware echocan
# Digium TE134: PCI single-port T1/E1/J1 with hardware echocan
wcte13xp
# Digium T100P: PCI single-port T1
# Digium E100P: PCI single-port E1
wct1xxp
# Digium TE110P: PCI single-port T1/E1/J1
wcte11xp
# Digium TDM2400P/AEX2400: up to 24 analog ports
# Digium TDM800P/AEX800: up to 8 analog ports
# Digium TDM410P/AEX410: up to 4 analog ports
wctdm24xxp
# Digium A4A/A4B/A8A/A8B
wcaxx
# X100P - Single port FXO interface
# X101P - Single port FXO interface
wcfxo
‫‪151‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫‪# Digium TDM400P: up to 4 analog ports‬‬


‫‪wctdm‬‬
‫‪# Digium B410P: 4 NT/TE BRI ports‬‬
‫‪wcb4xxp‬‬
‫‪# Digium TC400B: G729 / G723 Transcoding Engine‬‬
‫‪wctc4xxp‬‬
‫‪# Xorcom Astribank Devices‬‬

‫همانطورکه مالحظه میکنید در این فایل ابتدا نوع کارتهای ســختافزاری مشخص شدهاند که بهصورت‬
‫توضیحات)با عالمت ‪ (#‬آورده شده است و بعد از آن نام ماژول موردنظر بصورت ‪ Bold‬مشخص شدهاست‪.‬‬
‫ما میتوانیم ماژولهایی را که نیاز نداریم با گذاشتن عالمت » ‪ « #‬غیرفعال کنیم‪.‬‬
‫بعد از راهاندازی مجدد ســرویس ‪ dahdi‬مشــاهده خواهید کرد که همه ماژولهای موجود در این فایل‬
‫مجددا ً راهاندازی شدهاند‪.‬‬
‫‪#/etc/init.d/dahdi restart‬‬
‫‪Unloading DAHDI hardware modules: done‬‬
‫‪Loading DAHDI hardware modules:‬‬
‫‪wct4xxp: done wcte43x: done wcte12xp: done wcte13xp: done wct1xxp: done‬‬
‫‪wcte11xp: done wctdm24xxp: done wcaxx: done wcfxo: done wctdm: done wcb4xxp:‬‬
‫‪done wctc4xxp: done xpp_usb: done‬‬
‫‪Running dahdi_cfg: done.‬‬

‫در نظر داشــته باشــید که ما گاهی از برندهای خاصی در تجهیزات ســختافزاری برای ارتباط با شبکههای‬
‫‪ PSTN‬اســتفاده میکنیم‪ .‬در این حالت ماژول سختافزاری آن تجهیزات لزوما باید بهصورت دستی به این‬
‫فایل اضافه شود‪ .‬در راهنمای نصب تجهیزات مورد نظر‪ ،‬نام ماژول آورده شده است و لزومی ندارد نسبت به‬
‫این موارد نگران باشید‪ .‬همچنین میتوانید با استفاده از دستور زیر ماژول مورد نیاز برای کارتها را مشاهده‬
‫نمایید‪.‬‬
‫‪#dahdi-hardware‬‬

‫همانطورکه مالحظه میکنید نام ماژول مورد نیاز برای فعال شــدن این کارت ســختافزاری مشخص شده‬
‫است‪.‬‬

‫فایل ‪system.conf‬‬
‫ایــن فایل مهمترین فایل در بخش پیکربندی تجهیزات کارتهای ســختافزاری اســت‪ .‬بهوســیله این فایل‬
‫تعریف دقیقی از نوع کارت ســختافزاری و کاربرد آن خواهیم داشت‪ .‬ازآنجاکه پیکربندی این فایل کمی‬
‫پیچیده و دشوار بهنظر میرسد‪ ،‬ابزاری به نام ‪ dahdi-genconf‬در کامپوننت ‪ DAHDI-tools‬وجود دارد که‬
‫با اجرا کردن آن‪ ،‬پیکربندی این فایل بهصورت خودکار صورت میگیرد‪.‬‬
‫‪#dahdi_genconf‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪152‬‬

‫چنانچــه پس از اجرای این دســتور‪ ،‬فایــل ‪ system.conf‬را بــاز کنیم‪ ،‬متوجه خواهیم شــد که تنظیمات و‬
‫پیکربندی تجهیزات در این فایل انجام شدهاســت‪ .‬ازآنجاکه پیکربنــدی تجهیزات ‪ FXO/FXS‬با تجهیزات‬
‫کارتهــای ‪ PRI‬متفاوتند‪ ،‬درخصوص پیکربندی این فایل بهصورت دســتی و معرفی بخشهای آن بیشــتر‬
‫صحبــت خواهیم کــرد؛ ولی قبل از آن برخی از دســتورات مهم در کامپوننت ‪ DAHDI-tools‬را بررســی‬
‫میکنیم‪.‬‬

‫دستورات مهم‬
‫• ‪ :lspci‬یک دســتور لینوکســی است که لیستی از تجهیزات متصل شــده از طریق اسالید ‪ PCI‬و ‪ PCI-E‬را‬
‫نشان میدهد‪ .‬این دستور از کتابخانهی ‪ libpci‬استفاده میکند‪.‬‬
‫• ‪ :lsdahdi‬این دستور لیستی از تمامی کانالهای ‪ dahdi‬به همراه نوع آنها و شماره ‪ span‬را نشان میدهد‪.‬‬
‫• ‪ :dahdi_cfg‬این دستور فایل ‪ system.conf‬را خوانده و گزارشات پیکربندی را نشان میدهد‪.‬‬
‫• ‪ :dahdi_genconf‬این دســتور فایل ‪ system.conf‬را ســاخته و آن را بر اســاس تجهیزات ســختافزاری‬
‫موجود پیکربندی میکند‪ .‬چنانچه بهصورت دســتی تغییراتی در فایل ایجاد کردهباشیم‪ ،‬با اجرای این دستور‬
‫کلیه تغییرات از بین خواهدرفت‪.‬‬
‫• ‪ :dahdi_hardware‬این دســتور نمایشــی از همه تجهیزات سختافزاری شناخته شده بهوسیله ‪ DAHDI‬به‬
‫همراه ماژولهای مورد نیاز را نشان میدهد‪.‬‬
‫• ‪ :dahdi_monitor‬با این دستور میتوانید صدای تولید شده در کانال را ضبط کنید‪.‬‬
‫• ‪ :dahdi_scan‬این دستور لیستی از تنظیمات کانالهای ‪ DAHDI‬را با برخی از مشخصهها نشان میدهد‪.‬‬
‫• ‪ :dahdi_test‬از این دستور برای بررسی دقت ‪ DSP‬روی کارتهای ‪ FXO/FXS‬استفاده میشود‪.‬‬
‫• ‪ :dahdi_tool‬این دســتور یک محیط گرافیکی اســت برای اینکه مشخص کند چه تجهیزاتی روی سیستم‬
‫وجود دارند و چه کاری انجام میدهند‪.‬‬
‫در ادامه به بررسی مثال‌هایی از دستورات باال می‌پردازیم و خروجی‌های آن‌ها را با هم مقایسه می‌کنیم‪.‬‬
‫برای مثال دستور زیر را اجرا کنید‪:‬‬
‫‪#lspci | grep Digium‬‬
‫‪05:04.0 Communication controller: Digium, Inc. Wildcard TE405P/TE407P quad-span T1/E1/‬‬
‫)‪J1 card 5.0V (rev 02‬‬

‫البته خروجیهای بیشتری هنگام اجرای دستور داریم ولی با فیلتر کردن عبارت ‪ Digium‬این خروجی مرتبط‬
‫کارت ‪ 4‬پورت ‪ PRI‬برند دیجیوم است‪ .‬همچنین خروجی دستور میتواند بهصورت زیر باشد‪:‬‬ ‫با‬
‫‪#lspci | grep Sangoma‬‬
‫‪05:04.0 Network controller: Sangoma Technologies Corp. A104d QUAD T1/E1 AFT card‬‬

‫‪ 4‬پورت ‪ PRI‬از برند سنگوما داریم‪.‬‬ ‫در این حالت ما یک کارت‬


153 ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫ خروجی زیر نشان داده‬،‫ را اجرا کنیم‬lsdahdi ‫ دستور‬،‫ است‬PRI ‫چنانچه روی سروری که دارای لینک‬
:‫خواهد شد‬
#lsdahdi
### Span 1: TE4/0/1 "T4XXP (PCI) Card 0 Span 1" (MASTER) CCS/HDB3/CRC4 ClockSource
1 PRI Clear (In use) (EC: MG2 - INACTIVE)
2 PRI Clear (In use) (EC: MG2 - INACTIVE)
3 PRI Clear (In use) (EC: MG2 - INACTIVE)
4 PRI Clear (In use) (EC: MG2 - INACTIVE)
5 PRI Clear (In use) (EC: MG2 - INACTIVE)
6 PRI Clear (In use) (EC: MG2 - INACTIVE)
7 PRI Clear (In use) (EC: MG2 - INACTIVE)
8 PRI Clear (In use) (EC: MG2 - INACTIVE)
9 PRI Clear (In use) (EC: MG2 - INACTIVE)
10 PRI Clear (In use) (EC: MG2 - INACTIVE)
11 PRI Clear (In use) (EC: MG2 - INACTIVE)
12 PRI Clear (In use) (EC: MG2 - INACTIVE)
13 PRI Clear (In use) (EC: MG2 - INACTIVE)
14 PRI Clear (In use) (EC: MG2 - INACTIVE)
15 PRI Clear (In use) (EC: MG2 - INACTIVE)
16 PRI HDLCFCS (In use)
17 PRI Clear (In use) (EC: MG2 - INACTIVE)
18 PRI Clear (In use) (EC: MG2 - INACTIVE)
19 PRI Clear (In use) (EC: MG2 - INACTIVE)
20 PRI Clear (In use) (EC: MG2 - INACTIVE)
21 PRI Clear (In use) (EC: MG2 - INACTIVE)
22 PRI Clear (In use) (EC: MG2 - INACTIVE)
23 PRI Clear (In use) (EC: MG2 - INACTIVE)
24 PRI Clear (In use) (EC: MG2 - INACTIVE)
25 PRI Clear (In use) (EC: MG2 - INACTIVE)
26 PRI Clear (In use) (EC: MG2 - INACTIVE)
27 PRI Clear (In use) (EC: MG2 - INACTIVE)
28 PRI Clear (In use) (EC: MG2 - INACTIVE)
29 PRI Clear (In use) (EC: MG2 - INACTIVE)
30 PRI Clear (In use) (EC: MG2 - INACTIVE)
31 PRI Clear (In use) (EC: MG2 - INACTIVE)

‫ به همــراه هر کانال نوع‬.‫ همه کانالها را نشــان میدهد‬،‫همانطورکــه مالحظــه میکنید خروجی دســتور‬
‫ کانال‬، E1 ‫ نکته مهم این است که در لینکهای‬.‫ و شماره کانال را نیز مشاهده میکنید‬۱‫الگوریتم حذف اکو‬
‫ برای همین است که نوع پیکربندی آن با سایر کانالها‬.‫ استفاده خواهد شد‬۲‫ برای سیگنالینگ و همزمانی‬۱۶
.‫ برای سیگنالینگ و همزمانی استفاده میشود‬۲4 ‫ کانال‬،T1 ‫ در لینکهای‬.‫متفاوت است‬

1- Echo Cancellation
2- B channel
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 154

system. ‫ این اطالعات از طریق فایل‬.‫ هم پیکربندی کانالها را به ما نشــان میدهد‬dahdi_cfg ‫دســتور‬
.‫ بهدست میآید‬conf
#dahdi_cfg –vvv
DAHDI Tools Version - 2.10.0.1
DAHDI Version: 2.10.0.1
Echo Canceller(s): MG2
Configuration
======================
SPAN 1: CCS/HDB3 Build-out: 0 db (CSU)/0-133 feet (DSX-1)
Channel map:
Channel 01: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 01)
Channel 02: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 02)
Channel 03: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 03)
Channel 04: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 04)
Channel 05: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 05)
Channel 06: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 06)
Channel 07: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 07)
Channel 08: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 08)
Channel 09: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 09)
Channel 10: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 10)
Channel 11: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 11)
Channel 12: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 12)
Channel 13: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 13)
Channel 14: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 14)
Channel 15: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 15)
Channel 16: D-channel (Default) (Echo Canceler: none) (Slaves: 16)
Channel 17: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 17)
Channel 18: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 18)
Channel 19: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 19)
Channel 20: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 20)
Channel 21: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 21)
Channel 22: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 22)
Channel 23: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 23)
Channel 24: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 24)
Channel 25: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 25)
Channel 26: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 26)
Channel 27: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 27)
Channel 28: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 28)
Channel 29: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 29)
Channel 30: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 30)
Channel 31: Clear channel (Default) (Echo Canceler: mg2) (Slaves: 31)

:‫ شناخته شدهاند را مشاهده کنیم‬DAHDI ‫همچنین میتوانیم با دستور زیر سختافزارهایی که بهوسیله‬
#dahdi_hardware
‫‪155‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫برای مثال خروجی این دستور را بررسی میکنیم‪:‬‬


‫)‪pci:0000:06:04.0 wct4xxp+ d161:0405 Wildcard TE405P (2nd Gen‬‬
‫‪pci:0000:05:04.0 wanpipe- 1923:0100 Sangoma Technologies Corp. A104d QUAD T1/E1‬‬
‫‪AFT card‬‬

‫‪ 4‬پورت ‪ PRI‬بهوسیله درایور سختافزاری ‪wct4xxp+‬‬ ‫در خروجی اول همانطورکه مالحظه میکنید کارت‬
‫و در خروجی نوع دوم هم یک کارت ‪4‬پورت ‪ PRI‬با درایور ســختافزاری ‪ wanpipe-‬شناسایی شدهاست‬
‫)به همین دلیل است که در خصوص کارتهای سختافزاری سنگوما باید لزوما درایور ‪ wanpipe‬را نصب‬
‫کنیم‪ ،‬چون این کارتها فقط با این درایور بهوسیله ‪ DAHDI‬شناخته میشوند(‪.‬‬
‫نکته مهم این اســت که کارتهای ســختافزاری با درایورهای متفاوتی شناخته میشوند‪ .‬به همین دلیل‬
‫اگر این درایور بهصورت پیشفرض هنگام نصب ‪ DAHDI‬پشتیبانی شود‪ ،‬کارت سختافزاری بدون درنگ‬
‫پس از نصب برنامه شناخته میشود‪ ،‬درغیراینصورت بستههای مورد نیاز برای نصب درایور‪ ،‬باید روی سرور‬
‫نصب شــوند‪ .‬معموالً اغلب شرکتهای تولید کننده این نوع سختافزارها‪ ،‬یک راهنمای نصب برای نصب‬
‫درایورهای مورد نیاز ارائه میکنند که پیش از نصب نرمافزار‪ ،‬بهتر است مطالعه شوند‪.‬‬
‫ازآنجاکه اســتفاده از این دســتورات در بدو امر ممکن است کمی ســخت و ابهامبرانگیز باشد‪ ،‬پیشنهاد‬
‫میشــود پیش از مطالعهی مباحث بعدی‪ ،‬مروری بر دســتورات و خروجیهای آنها داشــته باشید‪ .‬در ادامه‬
‫پیکربندی تجهیزات سختافزاری در فایل ‪ system.conf‬بهصورت دستی بررسی میشود‪.‬‬

‫آشنایی با پیکربندی فایل ‪system.conf‬‬

‫همانطورکه پیشتر آمد‪ ،‬برای تنظیمات و پیکربندی ماژول ‪ DAHDI‬و کارتهای ســختافزاری‪ ،‬از فایل‬
‫‪ system.conf‬استفاده میکنیم‪ .‬این فایل هنگام نصب ‪ DAHDI‬در مسیر زیر تشکیل میشود‪.‬‬
‫‪#vim /etc/dahdi/system.conf‬‬

‫ازآنجاکه تنظیمات و پیکربندی کارتهای ‪ FXO/FXS‬با کارتهای ‪ PRI‬متفاوت اســت‪ ،‬پس از باز کردن‬
‫فایل‪ ،‬محتویات آن ممکن است شبیه آنچه در زیر مشاهده میکنید باشد )در صورتی که از هر دو کارتهای‬
‫‪ FXO/FXS‬و ‪ PRI‬هم زمان استفاده کنید‪ ،‬محتویات این فایل‪ ،‬ترکیبی از هر دو پیکربندی را خواهد داشت(‪.‬‬

‫پیکر بندی کارت ‪E1‬‬


‫اگر کارت ‪ PRI‬با تکنولوژی ‪ E1‬داشتهباشیم‪ ،‬تنظیمات مطابق زیر است‪:‬‬
‫‪# Span 1: TE4/0/1 "T4XXP (PCI) Card 0 Span 1" CCS/HDB3/CRC4 ClockSource‬‬
‫‪span=1,1,0,ccs,hdb3,crc4‬‬
‫‪bchan=1-15,17-31‬‬
‫‪dchan=16‬‬ ‫‪# or hardhdlc = 16‬‬
‫‪echocanceller=mg2,1-15,17-31‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪156‬‬

‫پیکر بندی کارت ‪T1‬‬


‫اگر کارت ‪ PRI‬با تکنولوژی ‪ T1‬داشته باشیم‪ ،‬تنظیمات بهصورت زیر است‪:‬‬
‫‪# Span 1: TE4/0/1 "T4XXP (PCI) Card 0 Span 1" CCS/HDB3/CRC4 ClockSource‬‬
‫‪span=1,1,0,esf,b8zs‬‬
‫‪bchan=1-23‬‬
‫‪dchan=24‬‬ ‫‪# or hardhdlc = 24‬‬
‫‪echocanceller=mg2,1-23‬‬

‫پیکر بندی کارت ‪FXO‬‬


‫اگر کارت ‪ FXO‬داشته باشیم‪ ،‬تنظیمات بر اساس زیر است‪:‬‬
‫‪fxsks = 1-4‬‬
‫‪echocanceller=mg2,1-4‬‬

‫این قابلیت وجود دارد که تنظیمات برای کارتهای ‪ FXO‬برای تک تک پورتها بهصورت جداگانه انجام‬
‫شود‪ .‬مثال تنظمیات میتواند بهصورت زیر باشد‪:‬‬
‫‪fxsks = 1‬‬
‫‪echocanceller=mg2,1‬‬
‫‪fxsks = 2‬‬
‫‪echocanceller=mg2,2‬‬
‫‪fxsks = 3‬‬
‫‪echocanceller=mg2,3‬‬
‫‪fxsks = 4‬‬
‫‪echocanceller=mg2,4‬‬

‫پیکر بندی کارت ‪FXS‬‬


‫اگر کارت ‪ FXS‬داشته باشیم‪ ،‬تنظیمات مطابق زیر است‪:‬‬
‫‪fxoks = 1-4‬‬
‫‪echocanceller=mg2,1-4‬‬

‫همچنیــن این قابلیــت وجود دارد که تنظیمات بــرای کارتهای ‪ FXS‬برای تک تــک پورتها بهصورت‬
‫جداگانه انجام شده باشد‪ .‬این تنظمیات میتواند بهصورت زیر باشد‪:‬‬
‫‪fxoks = 1‬‬
‫‪echocanceller=mg2,1‬‬
‫‪fxoks = 2‬‬
‫‪echocanceller=mg2,2‬‬
‫‪fxoks = 3‬‬
‫‪echocanceller=mg2,3‬‬
‫‪fxoks = 4‬‬
‫‪echocanceller=mg2,4‬‬

‫همانطورکــه مالحظه میکنید ایــن تنظیمات بهصورت خودکار در زمانی که دســتور ‪ dahdi_genconf‬را‬
‫‪157‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫اجرا کنیم‪ ،‬ایجاد میشوند‪ .‬پیشنهاد میشود تا حدامکان از تغییرات دستی در این فایل اجتناب شود‪ ،‬ولی در‬
‫شــرایطی ممکن اســت نیاز داشته باشــیم تغییراتی در این فایل بدهیم‪ .‬در ادامه مروری بر بخشهای مختلف‬
‫این فایل خواهیم داشت‪.‬‬

‫تنظیمات کارت‌های ‪PRI‬‬


‫همانطورکه در بخش تنظیمات کارتهای ‪ PRI‬مشاهده میکنید‪ ،‬تنظیمات این بخش بهصورت زیر است‪:‬‬
‫پارامتر ‪ : span‬فرمت استفاده از این پارامتر به‌صورت زیر است‪:‬‬
‫>‪span=<SPAN NUM> , <TIMING SOURCE>, <LBO>, <FRAMING>, <CODING‬‬

‫‪ :SPAN NUM‬شــماره پورتها یا ترتیب کارتهایی که بهوسیله لینوکس شناخته شدهاند‪ ،‬به طوری که از‬
‫یک شروع شده و به تعداد پورتها‪ ،‬یکی یکی افزایش مییابد‪.‬‬
‫‪ :TIMING SOURCE‬در تکنولوژی ‪ PRI‬از یک زمان برای همزمانی ارســال و دریافت دادهها اســتفاده‬
‫میشود‪ .‬اکنون باید مشخص کنیم که این سیگنال همزمانی با چه ترتیبی باید انجام شود‪ .‬ازآنجاکه تجیهزات‬
‫مشــتریان از دیدگاه مخابراتی در حالت ‪ slave‬قرار دارند‪ ،‬در چنین شــرایطی هیچگاه تولیدکننده ســیگنال‬
‫ایجاد همزمانی نخواهیم بود‪ .‬در چنین شــرایطی برای ترتیب همزمانی با ســیگنال مرجع )مخابرات( باید از‬
‫عدد ‪ ۱‬شــروع کنیم و بهازای هر پورت‪ ،‬آن را یک واحد افزایش دهیم‪ .‬هنگام اســتفاده از لینکهای ‪PRI‬‬
‫مخابراتی‪ ،‬هیچگاه نمیتوانیم تولیدکننده ســیگنال همزمانی باشیم‪ ،‬به همین دلیل این پارامتر نمیتواند صفر‬
‫باشد‪.‬‬
‫اگر خواســته باشــیم از طریق کارت ‪ PRI‬یک سیستم تلفنی استریسک را به یک سیستم دیگر )به غیر از‬
‫لینک مخابراتی( متصل کنیم‪ ،‬بسته به اینکه کدام طرف‪ ،‬تولیدکننده سیگنال همزمانی خواهد بود‪ ،‬باید آن را‬
‫صفر در نظر بگیریم‪ .‬برای مثال ما میتوانیم دو ســرور استریســک را از طریق لینک ‪ PRI‬به هم متصل کنیم؛‬
‫در این حالت باید یکی از آنها تولید کننده سیگنال همزمانی باشد‪ ،‬پس پارامتر را در آن صفر میکنیم‪.‬‬
‫انتخاب نامناسب و اشتباه همزمانی سیگنالینگ‪ ،‬منجر به ایجاد نویز در صدا‪ ،‬قطعی تماس‪ ،‬خطا در ارسال‬
‫و دریافت فکس و کیفیت پایین صدا میشود‪.‬‬
‫‪ :LBO‬فاصله بین کارت ‪ PRI‬و منبع تولید ســیگنال اســت که معموالً صفر در نظر گرفته میشود‪ .‬از لحاظ‬
‫تکنیکی وجود فاصله بین کارت و منبع تولید سیگنال‪ ،‬محدودیت ایجاد میکند‪ .‬در زیر فاصله و عدد متناظر‬
‫با آن آمده است‪.‬‬
‫)‪0: 0 dB (CSU) / 0 - 133 feet (DSX-1‬‬
‫)‪1: 133 - 266 feet (DSX-1‬‬
‫)‪2: 266 - 399 feet (DSX-1‬‬
‫)‪3: 399 - 533 feet (DSX-1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪158‬‬

‫)‪4: 533 - 655 feet (DSX-1‬‬


‫)‪5: -7.5 dB (CSU‬‬
‫)‪6: -15 dB (CSU‬‬
‫)‪7: -22.5 dB (CSU‬‬

‫‪ :FRAMING‬نوع اتصال فیزیکی را مشخص میکند که برای تکنولوژی ‪ E1‬و ‪ T1‬متفاوت است‪.‬‬
‫• ‪ : E1‬از ‪ cas‬یا ‪ ccs‬استفاده می‌کنیم‪.‬‬
‫• ‪ :T1‬از ‪ d4‬یا ‪ esf‬استفاده می‌کنیم‪.‬‬
‫• ‪ :BRI‬از ‪ cas‬یا ‪ ccs‬استفاده می‌کنیم‪.‬‬
‫‪ :CODING‬نوع کدینگ روی خط را مشخص می‌کند‪.‬‬
‫• ‪ :E1‬از ‪ ami‬یا ‪ hdb3‬استفاده می‌کنیم‪.‬‬
‫• ‪ :T1‬از ‪ ami‬یا ‪ b8zs‬استفاده می‌کنیم‪.‬‬
‫• ‪ :BRI‬از ‪ ami‬یا ‪ hdb3‬استفاده می‌کنیم‪.‬‬

‫در خصوص تکنولوژی ‪ E1‬در صورت لزوم می‌توان از ‪ CRC4‬نیز استفاده کرد‪.‬‬
‫پارامتر ‪ :bchan‬در این پارامتر کانال‌هایی را مشخص می‌کنیم که برای انتقال داده (صوت) استفاده می‌شوند‪.‬‬
‫پارامتر ‪ :dchan‬در این پارامتر کانال‌هایی را مشخص می‌کنیم که برای سیگنالینگ استفاده می‌شوند‪.‬‬
‫پارامتر ‪ :echocanceler‬نوع اکوکنسلر نرم‌افزاری را برای کانال مشخص می‌کند‪ .‬انواع زیادی از الگوریتم‌های‬
‫اکوکنسلر نرم‌افزاری وجود دارد که می‌توان از آنها استفاده نمود‪ .‬از مهمترین الگوریتم‌های نرم افزاری اکوکنسلر‬
‫می‌توان به ‪ mg2‬و ‪ oslec‬اشاره کرد‪ .‬برخی دیگر از انواع اکوکنسلرها ذیال ارائه شده‌اند‪:‬‬
‫)‪Asterisk mark echo canceller (mec‬‬
‫)‪Asterisk mark2 echo canceller (mec2‬‬
‫)‪Asterisk mark3 echo canceller (mec3‬‬
‫)‪Asterisk steve echo canceller (sec‬‬
‫)‪Asterisk steve2 echo canceller (sec2‬‬
‫)‪Asterisk kb1 echo canceller (kb1ec‬‬
‫)‪Asterisk mg2 echo canceller (mg2ec‬‬

‫پارامتــر ‪ loadzone‬و ‪ :defaultzone‬از این تنظیمات برای مشــخص کردن نوع ‪ tone‬ایجاد شــده به‌وســیله‬
‫کارت‌های ‪ DAHDI‬استفاده می‌شود‪ .‬اینجا منظور از ‪ ، tone‬صدای تولید شده برای انواع ‪‌ring‬ها از قبیل ‪dial،‬‬
‫‪ busy، waitcall‬و غیره است‪.‬‬
‫بــرای پیکربندی تنظیمات ‪ tone‬در استریســک‪ ،‬از دو فایل متفاوت بهــره میبریم‪ .‬برای تنظیمات ‪tone‬‬
‫در کارتهای ‪ DAHDI‬از فایل ‪ system.conf‬و برای تنظیمات ‪ tone‬در سیســتم داخلی استریسک از فایل‬
‫‪ indications.conf‬اســتفاده میکنیم‪ .‬در فصل سوم در خصوص فایل ‪ indications.conf‬توضیحات بیشتری‬
‫آمده است‪.‬‬
‫‪159‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫ت کارت‌های ‪FXO/FXS‬‬
‫تنظیما ‌‬
‫تنظیمــات مربوط به این نوع کارتها بســیار ســادهتر از تنظیمات مربوط به کارتهای ‪ PRI‬اســت‪ .‬در این‬
‫کارتها باید فقط دو پارامتر را مقداردهی کنیم‪.‬‬

‫پارامتر مربوط به نوع سیگنالینگ کانال‪ :‬در این پارامتر نوع سیگنالینگ کانال را مشخص می‌کنیم‪ .‬در شبکه‌های‬
‫مخابراتی ‪ PSTN‬روش‌های گوناگونی برای تولید ســیگنالینگ وجود دارد‪ .‬شکل ‪ 5-6‬این حالت‌ها را نمایش‬
‫می‌دهد‪.‬‬

‫شکل ‪5-6‬‬

‫برای مثال فرض کنید کانال اول )پورت اول( کارت از نوع ‪ FXO‬باشد؛ تنظیمات مربوط به این پورت‬
‫بهصورت زیر خواهد بود‪ .‬اینجا از ‪ Kewl Start‬استفاده میشود‪.‬‬
‫‪fxsks = 1‬‬
‫‪echocanceller=mg2,1‬‬

‫ازآنجاکه کارتهای ‪ FXO‬باید دارای سیگنالینگ ‪ FXS‬باشند‪ ،‬نوع سیگنالینگ را ‪ FXS‬تعیین میکنیم‪.‬‬
‫اکنــون فرض کنید اگر کانال دوم )پورت دوم( کارت از نوع ‪ FXS‬باشــد‪ ،‬تنظیمــات مربوط به این پورت‬
‫بهصورت زیر است‪:‬‬
‫‪fxoks = 1‬‬
‫‪echocanceller=mg2,1‬‬

‫همانطورکه مالحظه میکنید برای کارتهای ‪ FXS‬باید نوع سیگنالینگ را ‪ FXO‬در نظر بگیریم‪.‬‬

‫پارامتر ‪ :echocanceler‬نوع اکوکنسلر نرم‌افزاری را برای کانال مشخص می‌کند‪ .‬این پارامتر شبیه پارامتر معادل‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪160‬‬

‫در تنظیمات کارت‌های ‪ PRI‬اســت‪ .‬می‌توان از انواع اکوکنســلر‌های نرم‌افزاری که پیش‌تر توضیح داده شــد‪،‬‬
‫استفاده نمود‪.‬‬
‫آنچه تاکنون شرح داده شــد‪ ،‬پیکربندی تنظیمات مربوط به کارتهای ‪ DAHDI‬در فایلهای ‪system.‬‬
‫‪ conf‬و ‪ modules‬بود‪ .‬ســؤالی که ممکن اســت مطرح شــود این اســت که بعد از پیکربندی این فایلها و‬
‫کارتهای ‪ ،DAHDI‬سیستم تلفنی استریسک چگونه با آنها ارتباط برقرار کرده و از آنها استفاده میکند؟‪.‬‬

‫تنظیمات ارتباط ماژول ‪ DAHDI‬با استریسک‬


‫بعد از اینکه تنظیمات مربوط به شناســایی تجهیزات بهوســیله ‪ DAHDI‬انجام شــد‪ ،‬باید تنظیمات مربوط به‬
‫شناســایی آن بهوســیله استریسک را انجام دهیم‪ .‬برای شناســایی کارتهای ‪ DAHDI‬بهوسیله استریسک از‬
‫فایل ‪ chan_dahdi.conf‬استفاده میکنیم‪ .‬این فایل در مسیر فایلهای پیکربندی استریسک قرار دارد‪.‬‬
‫‪#vim /etc/asterisk/chan_dahdi.conf‬‬

‫نکته مهمی که باید دقت داشــته باشــیم این اســت که فایل ‪ system.conf‬بــرای پیکربندی کارتهای‬
‫‪ DAHDI‬درنظر گرفته شده است‪ ،‬در حالی که فایل ‪ chan_dahdi.conf‬برای شناسایی کارتهای ‪DAHDI‬‬
‫بهوســیله استریسک است‪ .‬به عبارت دیگر برای استفاده از کارتهای ‪ DAHDI‬در استریسک باید ‪ ۲‬مرحله‬
‫را انجام دهیم‪:‬‬
‫مرحله اول شناســایی کارتها بهوســیله ماژول ‪ DAHDI‬و مرحله دوم ارتباط کارتهای شــناخته شده‬
‫بهوسیله ‪ DAHDI‬با استریسک است‪ .‬در مرحله اول از ابزارهایی نظیر ‪ DAHDI-tools‬برای مدیریت کارتها‬
‫نیز میتوانیم استفاده کنیم؛ اما برای شناسایی این کارتها بهوسیله استریسک باید از فایل ‪chan_dahdi.conf‬‬
‫اســتفاده کنیم‪ .‬آنچه در تعریف و شناسایی کارتها ازطریق استریسک مهم است این است که وقتی تماسی‬
‫از طریق یک کانال وارد سیستم تلفنی استریسک میشود‪ ،‬چگونه باید آن را کنترل و مدیریت کنیم‪.‬‬
‫وقتی فایل ‪ chan_dahdi.conf‬را باز میکنید‪ ،‬ممکن اســت با یک فایل طوالنی مواجه شــویم که بیشتر‬
‫نحوهی پیکربندی را توضیح میدهد‪ .‬برای آشــنایی با پارامترهای موجود در این فایل‪ ،‬از این راهنما استفاده‬
‫کنید‪.‬‬
‫هنــگام نصب و شناســایی برخی کارتها‪ ،‬تنظیمات مربوط به این فایــل هم بهصورت خودکار صورت‬
‫میگیرد؛ اما چنانچه این تنظیمات صورت نگرفت‪ ،‬باید بهصورت دســتی و به شــکل زیر تنظیمات را انجام‬
‫دهیم‪:‬‬
‫ابتــدا فایــل ‪ chan_dahdi.conf‬را باز کنید و در انتهای آن‪ ،‬بهصورت زیر یــک فایل دیگر را ‪include‬‬
‫کنید‪.‬‬
‫‪#include dahdi_channels.conf‬‬
‫‪161‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫با این کار یک فایل جدید به فایل تنظیمات و پیکربندی اضافه میشود‪ .‬اکنون تنظیمات مورد نیاز برای‬
‫کارتهای ‪ FXO/FXS‬یا ‪ PRI‬را به این فایل اضافه کنید‪.‬‬

‫تنظیمات مربوط به کارت‌های ‪ PRI‬در استریسک‬


‫این تنظیمات برای کارتهای ‪ PRI‬میتوانند شبیه تنظیمات زیر باشند‪:‬‬
‫‪; dahdi_channels.conf‬‬
‫‪; Span 1: TE4/0/1 "T4XXP (PCI) Card 0 Span 1" CCS/HDB3/CRC4 ClockSource‬‬
‫‪group=0,11‬‬
‫‪context=from-pstn‬‬
‫‪switchtype = euroisdn‬‬
‫‪signalling = pri_cpe‬‬
‫‪channel => 1-15,17-31‬‬
‫‪context = default‬‬
‫‪group = 63‬‬

‫پارامتر ‪context‬‬
‫همانطورکه مالحظه میکنید‪ ،‬در این تنظیمات کانتکســت را مشــخص کردیم؛ یعنی هر گونه تماسی که از‬
‫این طریق ایجاد و به سیســتم تلفنی استریسک وارد شود‪ ،‬وارد کانتکست ]‪ [from-pstn‬میشود‪ .‬میتوانید از‬
‫هر اسمی برای نام کانتکست استفاده کنید‪.‬‬

‫پارامتر ‪channel‬‬
‫اینجا همهی کانالهای ‪ DAHDI‬مشــخص شــدهاند‪ .‬به عبارت دیگر مشخص کردهایم که چه کانالهایی در‬
‫کارت ‪ DAHDI‬وجود دارند‪ .‬همانطورکه قب ً‬
‫ال اشــاره کردیم در تکنولوژی ‪ ،E۱‬کانالهای ‪ ۱-۱۵‬و ‪۱7-۳۱‬‬
‫برای انتقال دیتا )صوت( مشــخص شدهاند‪ ،‬بنابراین در قســمت ‪ channel‬نام کانالها را نیز به همین صورت‬
‫مشخص میکنیم )کانال ‪ ۱۶‬جهت سیگنالینگ و همزمانی استفاده میشود(‪.‬‬

‫پارامتر ‪signaling‬‬
‫یک پارامتر مهم که باید به آن دقت کنید این اســت که تولید کننده ســیگنال همزمانی در کانالهای ‪ E۱‬در‬
‫سمت مقابل )مخابرات( انجام خواهد شد‪ .‬قب ً‬
‫ال توضیح داده شد که باید تنظیماتی در فایل ‪ system.conf‬در‬
‫قســمت >‪ ،<TIMING SOURCE‬انجام شــود‪ ،‬در این فایل هم باید پارامتر ‪ signaling‬را تنظیم کنید‪ .‬این‬
‫پارامتر میتواند مقادیر زیر را داشته باشد‪:‬‬
‫• ‪ :pri_cpe‬منظــور از ‪ cpe‬تجهیزات مشــتریان اســت‪ .‬زمانی که لینــک کارت ‪ E1‬به مخابرات متصل‬
‫‪1‬‬

‫می‌شود‪ ،‬مورد استفاده قرار می‌گیرد‪.‬‬


‫‪1- Customer Premises Equipment‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪162‬‬

‫• ‪ :pri_net‬منظور از ‪ net‬یعنی لینک کارت ‪ E1‬خود تولید کننده سیگنال هم‌زمانی است‪ .‬بیشتر در زمانی‬
‫مورد استفاده قرار می‌گیرد که با یک دستگاه دیگر‪ ،‬ارتباطی از طریق ‪ PRI‬برقرار کنیم‪.‬‬

‫پارامتر ‪switchtype‬‬
‫این پارامتر فقط در کارتهای ‪ PRI‬برای معرفی کردن نوع ســیگنالینگ و بیشــتر برای هماهنگی تنظیمات‬
‫بین ســوئیچ مخابراتی و استریسک استفاده میشــود‪ .‬در کارتهای ‪ PRI‬میتوان سیگنالینگهای زیر را بین‬
‫تجهیزات ‪ pri_net‬و ‪ pri_cpe‬داشت‪:‬‬
‫‪• national‬‬
‫‪• dms100‬‬
‫‪• 4ess‬‬
‫‪• 5ess‬‬
‫‪• euroisdn‬‬
‫‪• ni1‬‬
‫‪• qsig‬‬

‫میتوان از هر ســیگنالینگ دلخواه بین دو لینک ‪ PRI‬اســتفاده نمود‪ .‬در شــبکههای مخابراتی کشور غالبا از‬
‫‪ euroisdn‬استفاده میشود‪.‬‬

‫تنظیمات مربوط به کارت‌های ‪ FXO/FXS‬در استریسک‬


‫تنظیمات فایل ‪ dahdi_channels.conf‬برای کارتهای ‪ FXO/FXS‬بهصورت زیر است‪:‬‬
‫‪; dahdi-channels.conf‬‬
‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=from-pstn‬‬
‫‪channel => 1‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=from-pstn‬‬
‫‪channel => 2‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫‪signalling=fxs_ks‬‬
‫‪163‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=from-pstn‬‬
‫‪channel => 3‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=from-pstn‬‬
‫‪channel => 4‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫همانطورکه مالحظه میکنید‪ ،‬سیگنالینگ در تمام کانالها بهصورت ‪ fxs_ks‬تعریف شدهاست‪ .‬در صورتی‬
‫که پورتها از نوع ‪ fxs‬باشند‪ ،‬سیگنالینگ بهصورت ‪ fxo_ks‬تعریف میگردد‪ .‬پارامتر ‪callerid=asreceived‬‬
‫نیز تعریف شده است‪ ،‬به معنی این که در شروع تماس‪ ،‬کالرآی دی ارسال میشود‪ .‬پارامتر کانتکست همانند‬
‫قبل روی ]‪ [from-pstn‬تنظیم شده است تا تماسهای ورودی را کنترل و مدیریت کند‪.‬‬
‫بعد از اینکه این تنظیمات در فایل ‪ chan_dahdi.conf‬انجام شد‪ ،‬باید وارد محیط کامند الین استریسک‬
‫شوید و دستورات زیر را اجرا نمایید‪.‬‬
‫‪CLI> core reload‬‬
‫‪CLI> dahdi show status‬‬

‫ازطریق دســتور فوق میتوانید وضعیت کارتهای ‪ DAHDI‬شناخته شده بهوسیله استریسک را مشاهده‬
‫کنید‪ .‬خروجی آن میتواند بهصورت زیر باشد‪:‬‬
‫)‪T2XXP (PCI) Card 0 Span 1 OK 0 0 8 CCS HDB3 CRC4 0 db (CSU)/0-133 feet (DSX-1‬‬
‫)‪T2XXP (PCI) Card 0 Span 2 RED 0 0 0 CCS HDB3 CRC4 0 db (CSU)/0-133 feet (DSX-1‬‬
‫)‪Wildcard TDM400P REV E/F Board 5 OK 0 0 0 CAS Unk 0 db (CSU)/0-133 feet (DSX-1‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬یکــی از کارتها در وضعیت ‪ RED‬قرار دارد‪ .‬وضعیت ‪ RED‬حالتی را‬
‫نشان میدهد که لینک فیزیکی کارت برقرار نشده باشد‪.‬‬
‫در خصوص کارتهای ‪ E1‬ممکن اســت وضعیت کارت‪ ،‬نرمال )در حالت ‪ (OK‬باشد ولی هیچ یک از‬
‫کانالها فعال نباشند‪ .‬برای مشخص شدن این وضعیت‪ ،‬دستور زیر را اجرا کنید‪.‬‬
‫‪CLI> pri show spans‬‬

‫خروجی دستور بهصورت زیر است‪:‬‬


‫‪PRI span 1/0: Up, Active‬‬
‫‪PRI span 2/0: In Alarm, Down, Active‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪164‬‬

‫‪PRI span 3/0: Up, Active‬‬


‫‪PRI span 4/0: Up, Active‬‬
‫‪PRI span 5/0: Up, Active‬‬
‫‪PRI span 6/0: Up, Active‬‬

‫همانطورکه مالحظه میکنید همه لینکهای ‪ E1‬به جز لینک دوم‪ ،‬فعالاند‪.‬‬


‫کلیه کانالهای شناختهشده کارتهای ‪ DAHDI‬در استریسک را میتوان بهصورت زیر مشاهدهنمود‪:‬‬
‫‪CLI> dahdi show channels‬‬

‫خروجی دستور فوق‪ ،‬مطابق زیر همه کانال‌ها را نشان می‌دهد‪:‬‬


‫‪pseudo default‬‬ ‫‪default In Service‬‬
‫ ‪1‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪2‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪3‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪4‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪5‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪6‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬
‫ ‪7‬‬ ‫‪from-pstn‬‬ ‫‪default‬‬ ‫‪In Service‬‬

‫پس از آنکه همه کانالها بهوســیله استریسک شناختهشــد‪ ،‬باید بتوان بهوسیله آنها‪ ،‬تماس ورودی و تماس‬
‫خروجی داشــته باشــیم‪ .‬در ادامه به بررســی دقیق تماسهــای ورودی و خروجــی در کارتهای ‪DAHDI‬‬
‫)شبکههای مخابراتی ‪ (PSTN‬میپردازیم‪.‬‬

‫کنترل تماس‌های ورودی به کارت‌های ‪( DAHDI‬از شبکه مخابراتی ‪)PSTN‬‬


‫کنترل همه تماسهای ورودی به سیســتم تلفنی استریســک از طریق کانتکســت ممکن میشود‪ .‬هر تماسی‬
‫که وارد سیســتم تلفنی استریســک شود‪ ،‬بســته به اینکه از چه کانالی از کارت وارد سیستم شده باشد‪ ،‬وارد‬
‫کانتکست مشخصی میشود و سپس دستورات آن بخش اجرا میگردد‪ .‬بهعنوان مثال فرض کنید برای یک‬
‫کارت ‪ FXO‬چنین تنظیماتی را داشته باشیم‪:‬‬
‫‪; dahdi-channels.conf‬‬
‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=from-pstn‬‬
‫‪channel => 1‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫در این تنظیمات‪ ،‬تماس ورودی از روی کانال ‪ ۱‬وارد کانتکســت ]‪ [from-pstn‬میشــود و دســتورات الزم‬
‫اجرا میگردد‪ .‬ازآنجاکه پارامتر ‪ callerid=asreceived‬تنظیم شــده اســت‪ ،‬کالرآی دی میتواند هر چیزی‬
‫‪165‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫)هرشمارهای( باشد‪.‬‬
‫اکثرا ً در تماسهای ورودی از الگوی تطابق یا اکستنشن ‪ s‬استفاده می کنیم‪.‬‬
‫]‪[from-pstn‬‬
‫)(‪exten => _X.,1,Answer‬‬
‫)‪same => n,BackGround(welcome‬‬
‫)‪same => n,WaitExten(5‬‬

‫‪exten=> 1,1,do something‬‬


‫‪exten=> 2,1,do something‬‬
‫‪exten=> 3,1,do something‬‬

‫)(‪exten => s,1,Answer‬‬


‫)‪same => n,BackGround(welcome‬‬
‫)‪same => n,WaitExten(5‬‬

‫‪exten=> 1,1,do something‬‬


‫‪exten=> 2,1,do something‬‬
‫‪exten=> 3,1,do something‬‬

‫نکته مهم در خصوص تماسهای ورودی از طریق کانالهای آنالوگ این اســت که تماسهای ورودی‬
‫اکثرا بهصورت اکستنشن ‪ s‬ایجاد و وارد کانتکست میشوند‪.‬‬
‫نکتــه مهم دیگر این اســت که ما میتوانیم هر کانال را مســتقال مدیریت کنیم‪ .‬بــرای مثال فرض کنید یک‬
‫کارت ‪ FXO‬دوپورت داشــته باشــیم‪ .‬هر پورت را میتوان بطور مســتقل با کانتکستهای متفاوتی تنظیم و‬
‫مدیریت نمود‪ .‬برای مثال تنظیمات زیر را در نظر بگیرید‪:‬‬
‫‪; dahdi-channels.conf‬‬
‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=incoming1‬‬
‫‪channel => 1‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=1‬‬
‫‪context= incoming2‬‬
‫‪channel => 2‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪166‬‬

‫همانطورکه مالحظه میکنید اگر تماســی از طریق کانال ‪ ۱‬ایجاد شود‪ ،‬به کانتکست ]‪ [incoming1‬و اگر‬
‫از طریق کانال ‪ ۲‬ایجاد شود‪ ،‬به کانتکست ]‪ [incoming2‬وارد میشود‪.‬‬
‫ممکن اســت این ســوال مطرح شــود که چرا عالوه بر پارامتر ‪ ، channel‬پارامتر ‪ group‬هم تغییر کرده‬
‫است؟ در بخش بعدی به کنترل تماسهاس خروجی از کارتهای ‪ DAHDI‬میپردازیم‪.‬‬
‫به این نکتهی مهم توجه شود که فقط پارامترهایی برای یک کانال مشخص شده درنظر گرفته میشوند‬
‫که قبل از پارامتر ‪ channel‬تعریف شده باشند‪ .‬کلیه این تنظیمات برای کارتهای ‪ PRI‬مشابه است‪.‬‬

‫کنترل تماس‌های خروجی از کارت‌های ‪( DAHDI‬به شبکه مخابراتی ‪)PSTN‬‬


‫برای برقراری تماس خروجی از کارتهای ‪ ،DAHDI‬مشــابه ســایر تکنولوژیهــا )‪ SIP,IAX2‬و غیره( از‬
‫دســتور ‪ Dial‬استفاده میکنیم‪ .‬در فصلهای قبل راجع به نحوه اســتفاده از این دستور توضیح دادیم‪ .‬اکنون‬
‫به شــرح چند مثال کاربردی میپردازیم‪ .‬قبل از آن فرض کنید یک کارت ‪ DAHDI‬با چهار ماژول ‪FXO‬‬
‫داریم‪.‬‬
‫‪; dahdi-channels.conf‬‬
‫‪signalling=fxs_ks‬‬
‫‪callerid=asreceived‬‬
‫‪group=0‬‬
‫‪context=incoming1‬‬
‫‪channel => 1-4‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫اکنون برای ایجاد تماس در این کانال‪ ،‬مراحل زیر را انجام دهید‪.‬‬
‫‪;extensions_custom.conf‬‬
‫)‪exten => _X.,1,NoOp(outgoing call to PSTN network‬‬
‫)}‪same => n,Dial(DAHDI/1/${EXTEN‬‬

‫در این مثال‪ ،‬تماس از کانال یک کارت ‪ FXO‬خارج میشود‪ .‬چنانچه دو نفر همزمان بخواهند یک تماس با‬
‫بیرون برقرار کنند‪ ،‬برای نفر دوم‪ ،‬کانال یک مشغول خواهد بود و امکان ایجاد تماس برای او میسر نمیشود؛‬
‫چون اعالم کردهایم که میخواهیم تماس از طریق کانال یک برقرار شــود‪ .‬چنانچه برنامه باال بهصورت زیر‬
‫تغییر کند‪:‬‬
‫‪;extensions_custom.conf‬‬
‫)‪exten => _X.,1,NoOp(outgoing call to PSTN network‬‬
‫)}‪same => n,Dial(DAHDI/1/${EXTEN‬‬
‫)}‪same => n,Dial(DAHDI/2/${EXTEN‬‬
‫)}‪same => n,Dial(DAHDI/3/${EXTEN‬‬
‫)}‪same => n,Dial(DAHDI/4/${EXTEN‬‬
‫‪167‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫در این صورت‪ ،‬نفر اول از اولین کانال استفاده میکند و تماس او برقرار میشود و نفرات بعدی از کانالهای‬
‫بعدی استفاده میکنند‪ .‬این روش برنامهنویسی برای کانالهای ‪ DAHDI‬به دالیل زیر کاربردی نیست‪:‬‬
‫‪1 .1‬چنانچه تعداد کانال‌ها افزایش‌یابد‪ ،‬باید برنامه باال را برای تک تک کانال‌ها بنویسید‪.‬‬
‫‪2 .2‬هنگامی‌که ترافیک تماس‌های خروجی زیادند‪ ،‬به‌ازای هر تماس باید همه کانال‌های اولیه بررسی‌شــوند‬
‫تا به اولین کانال آزاد مورد نظر برسیم‪.‬‬
‫‪3 .3‬همیشه صورت حساب هزینه ی کانال‌های اولیه بیشتر است‪.‬‬
‫چنانچه تعداد کانالها افزایش یابد‪ ،‬مدیریت آنها نیز دشوارترمیشــود‪ ،‬بنابراین برای سهولت بیشتر بهتر‬
‫اســت کانالها را گروهبندی کنید‪ .‬به این ترتیب که بهجای شــماره کانال‪ ،‬شــماره گروه را بیاورید‪ .‬در این‬
‫صورت هنگام ایجاد تماس جدید‪ ،‬از کانالهای آزاد طبق الگوریتم مورد نظر اســتفاده کنید تا تماس برقرار‬
‫شود‪ .‬بر این اساس برنامه باال بهصورت زیر تغییر میکند‪:‬‬
‫‪;extensions_custom.conf‬‬
‫)‪exten => _X.,1,NoOp(outgoing call to PSTN network‬‬
‫)}‪same => n,Dial(DAHDI/g0/${EXTEN‬‬

‫همانطورکه مالحظه میکنید‪ ،‬هم کد ســادهتری ایجاد کردیم و هم میتوانیم بدون مشــکل از همه کانالها‬
‫اســتفاده کنیم‪ .‬پارامتــر ‪ group‬در تنظیمات فایل ‪ dahdi_channels.conf‬بــرای گروهبندی کانالها و ایجاد‬
‫تماس خروجی استفاده میشود‪.‬‬
‫هنگام گروهبندی کانالها‪ ،‬میتوان براســاس الگوریتمهایی مشــخص کرد که از چه کانالهایی استفاده‬
‫شود تا توزیع تماسها بین کانالها یکسان بماند‪ .‬برای این منظور حالتهای زیر را درنظر بگیرید‪:‬‬
‫‪ : g‬ترتیب انتخاب پورتها از کمترین به بیشترین )‪ (۱،۲،۳،4،۵‬است‪ .‬برای مثال در اولین شماره‪ ،‬اولین پورت‬
‫استفاده میشود‪ .‬اگر اولین پورت مشغول باشد‪ ،‬دومین پورت انتخاب میشود‪ .‬این نکته مهم است که انتخاب‬
‫پورت دوم به اشــغال بودن پورت اول بســتگی دارد )در این حالت ‪ billing‬برای شــماره پورتهای پایینتر‬
‫بیشتر خواهد شد(‪.‬‬
‫)}‪exten => _X.,1,Dial(DAHDI/g0/${EXTEN‬‬

‫‪ : G‬این ترتیب دقیقاً مثل ‪ g‬اســت اما انتخاب پورت از بیشترین به کمترین )‪ (۵،4،۳،۲،۱‬است )در این حالت‬
‫‪ billing‬برای شماره پورتهای باالتر بیشتر خواهد شد(‪.‬‬
‫)}‪exten => _X.,1,Dial(DAHDI/G0/${EXTEN‬‬

‫‪ : r‬در این حالت ترتیب انتخاب از کمترین به بیشــترین و بهصورت چرخشــی )‪ (Round-robin‬است‪ .‬یعنی‬
‫تماس جدید با پورت جدید ایجاد میشود )در این حالت ‪ billing‬برای پورتها با هم برابر است(‪.‬‬
‫)}‪exten => _X.,1,Dial(DAHDI/r0/${EXTEN‬‬

‫‪ : R‬در این حالت ترتیب انتخاب از بیشــترین به کمترین و بهصورت چرخشــی )‪ (Round-robin‬است‪ .‬یعنی‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪168‬‬

‫تماس جدید با پورت جدید ایجاد میشود )در این حالت ‪ billing‬برای پورتها با هم برابر است(‪.‬‬
‫)}‪exten => _X.,1,Dial(DAHDI/R0/${EXTEN‬‬

‫بــا ایــن قوانین میتوان بهترین الگو را انتخاب و از آن اســتفاده نمود‪ .‬این قوانین بــرای کارتهای ‪ PRI‬نیز‬
‫برقرار است‪.‬‬

‫مقایسه کارت‌های ‪ FXO‬با ‪ FXS‬از نقطه نظر سیگنالینگ‬


‫تا اینجا ارتباط سیســتم تلفنی استریسک با شبکههای مخابراتی )کارتهای ‪ PRI‬و ‪ (FXO‬را شرح داده ایم‪.‬‬
‫ازآنجاکه کارتهای ‪ FXS‬بسیار مشابه با کارتهای ‪ FXO‬اند‪ ،‬در ادامه بیشتر به آن خواهیم پرداخت‪.‬‬
‫همان‌طورکه از اســم آنها پیداســت کارت‌های ‪ FXO‬برای ارتباط با شبکه‌های مخابراتی به‌کار می‌روند و‬
‫کارت‌های ‪ FXS‬برای برقراری ارتباط تلفن‌های آنالوگ با سیستم تلفنی استریسک استفاده می‌شود‪ .‬شکل‌های‬
‫‪ 6-6‬و ‪ 7-6‬این تفاوت را در کارت‌های ‪ FXO/FXS‬نشان می‌دهد‪.‬‬

‫شکل ‪6-6‬‬

‫شکل ‪7-6‬‬
‫‪169‬‬ ‫ارتباط استریسک با شبکه‌های مخابراتی‬

‫این کارت‌ها در موارد زیر با هم تفاوت دارند‪:‬‬


‫‪ .۱‬نوع تعریف سیگنالینگ در فایل ‪system.conf‬‬
‫‪;system.conf‬‬
‫ ‪fxsks=1‬‬ ‫‪;fxo module‬‬
‫ ‪fxoks=2‬‬ ‫‪;fxs module‬‬

‫‪ .۲‬نوع تعریف سیگنالینگ در فایل ‪dahdi_channels.conf‬‬


‫‪;dahdi_channels.conf‬‬
‫‪signalling=fxs_ks ;fxo module‬‬
‫‪signalling=fxo_ks ;fxs module‬‬

‫تعریف داخلی‌های ‪ FXS‬در استریسک‬


‫داخلیهایی که بهوســیله کارت ‪ FXS‬در سیســتم تعریف میشــوند‪ ،‬همانند ســایر داخلیهای استریسک با‬
‫پروتکلهای ‪ SIP، IAX2‬و غیره اســت‪.‬این داخلیها میتوانند با ســایر داخلیها در سیستم تلفنی استریسک‬
‫ارتباط برقرار کنند‪.‬‬
‫بــرای مثال چنانچه بخواهیم یک داخلی جدید روی کارت ‪ FXS‬در استریســک ایجاد کنیم‪ ،‬تنظیمات‬
‫مربوط به فایل ‪ system.conf‬در ارتباط با این داخلی بهصورت زیر است‪:‬‬
‫‪;system.conf‬‬
‫‪fxoks = 5‬‬
‫‪echocanceller=mg2,5‬‬

‫بعد از تنظیمات در فایل ‪ ،system.conf‬نوبت به تنظیم فایل ‪ dahdi_channels.conf‬میرســد که بهصورت‬


‫زیر است‪:‬‬
‫‪;dahdi_channels.conf‬‬
‫‪signalling=fxo_ks‬‬
‫>‪callerid="Channel 5" <555‬‬
‫‪group=5‬‬
‫‪context=LocalSet‬‬
‫‪channel => 5‬‬
‫=‪callerid‬‬
‫=‪group‬‬
‫‪context=default‬‬

‫پارامتر ‪ callerid‬میتواند هر گونه داخلی مورد نظر شــما باشــد‪ .‬همانطورکه در تعریف هر داخلی‪ ،‬باید‬
‫شــمارهای به آن تخصیص داده شود‪ ،‬میتوانید شــماره مورد نظر خود را به آن اختصاص دهید‪ .‬برای ایجاد‬
‫تماس با این داخلی بهصورت زیر برنامه خود را بنویسید‪:‬‬
‫]‪[LocalSet‬‬
‫)‪exten => 555,1,NoOp(calling fxs extension‬‬
‫)‪same => n,Dial(DAHDI/5‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪170‬‬

‫همه تماسهایی که ازطریق این داخلی ایجاد میشــوند‪ ،‬با ســایر داخلیهای سیســتم تلفنی استریســک‬
‫تفاوتی ندارند؛ لذا با توجه به شماره گرفته شده‪ ،‬به کانتکست تعیینشده ]‪ [LocalSet‬میرود و از آنجا برنامه‬
‫مورد نظر اجرا میگردد‪.‬‬

‫مقایسه کارت‌های ‪ FXO‬با ‪ FXS‬از نقطه‌نظر فراخوانی در برنامه‌نویسی‬


‫هنگام فراخوانی یک کارت ‪ ، FXS‬در واقع یک تماس با داخلی تعریف شده درکارت ‪ FXS‬ایجاد میشود‪،‬‬
‫ولی هنگام فراخوانی یک کارت ‪ ،FXO‬از طریق بســتر ارتباطی با شــبکهی مخابراتی‪ ،‬یک تماس به سمت‬
‫شبکه مخابراتی ایجاد میگردد‪.‬‬
‫در برنامه زیر این مقایسه نمایش داده شده است‪:‬‬
‫‪;FXS modules in Asteirks‬‬
‫)‪exten => 555.,1,NoOp(calling fxs extension in asterisk‬‬
‫)‪same => n,Dial(DAHDI/5‬‬

‫‪;FXO modules in Asteirks‬‬


‫)‪exten => _9X.,1,NoOp(outgoing calls from asterisk‬‬
‫)}‪same => n, Dial(DAHDI/g0/${EXTEN:1‬‬

‫نتیجه‌گیری‬
‫امروزه رشــد شبکههای مخابراتی نسل جدید قابلمالحظه اســت ولی نمیتوان انتظار داشت که این فناوری‬
‫بهســرعت با شبکههای مخابراتی ‪ PSTN‬جایگزین شود‪ .‬به عبارت دیگر گذر از شبکههای مخابراتی ‪PSTN‬‬
‫به شــبکههای نســل جدید یک فرایند تدریجی اســت‪ .‬ارتباط بین این دو شبکه در این فصل بررسی شد‪ .‬در‬
‫فصل بعدی‪ ،‬انواع روشهای اتصال شبکههای ویپ را بررسی میکنیم‪.‬‬
‫فصل هفتم‬

‫ارتباط استریسک با سایر‬


‫شبکه‌های‪VoIP‬‬
‫(‪)VoIP Providers‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪172‬‬

‫ارتباط استریسک با سایر شبکه‌های‪(VoIP Providers) VoIP‬‬


‫در مقایســه با شــبکههای نسل قدیم مخابراتی )‪ ، (PSTN‬شــبکههای ویپ با سرعت قابلمالحظهای در حال‬
‫رشــد و توســعهاند‪ .‬ازآنجاکه گذر از شبکههای نسل قدیم مخابراتی به نســل جدید نمیتواند درکوتاهمدت‬
‫صورت گیرد‪ ،‬باید بتوانیم بین این شبکهها ارتباط برقرار کنیم‪ ،‬بهطوریکه کاربران هردو شبکه بتوانند بدون‬
‫هیچگونه نگرانی با هم در ارتباط باشند‪ .‬دقت شود که منظور از ارتباط بین شبکههای مخابراتی‪ ،‬لزوماً ارتباط‬
‫بین شــبکههای مخابراتی ‪ PSTN‬با شــبکههای ‪ VoIP‬نیســت‪ ،‬بلکه ارتباط بین شبکههای ‪ VoIP‬هم مورد نظر‬
‫است‪ .‬در این فصل انواع ارتباطات شبکههای ویپ و چالشهای آنها بررسی میشود‪.‬‬
‫ســرویسدهندگان ویپ‪ ۱‬خدماتشان را در بستر اینترنت ارائه میکنند و چون در شبکههای کامپیوتری‪،‬‬
‫اغلب از تجهیزاتی مانند فایروالها برای تأمین امنیت بهره گرفته میشــود‪ ،‬ارائه این نوع سرویسها معموال با‬
‫مشکالتی روبهروست‪.‬‬
‫در حوزه شــبکههای ویپ‪ ،‬پروتکلهــای فراوانی وجود دارد‪ ،‬ولی پروتــکل ‪ SIP‬از زمره محبوبترین‬
‫پروتکلها در این شــبکه است‪ .‬این پروتکل در شبکههای ویپ همراه با پروتکل ‪ RTP‬بهکار میرود‪ .‬عالوه‬
‫براین اکثر کاربران شبکههای ویپ‪ ،‬با ‪ ۲ NAT‬سروکار دارند که با مشکالتی ازقبیل یکطرفه بودن صدا‪ ۳‬و‬
‫انتقال نیافتن صدا دست به گریبانند‪ .‬این نوع چالشها در شبکههای ویپ ‪ NAT-Traversal‬نامیده میشوند‪.‬‬

‫)‪1- VoIP Provider or Internet Telephony Service Provider (ITSP‬‬


‫‪2- Network Address Translation‬‬
‫‪3- One Ways Voice‬‬
‫‪173‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫آشنایی با پروتکل ‪SIP‬‬


‫این پروتکل یکی از پروتکلهای رایج در شبکههای‪ VoIP‬است و در الیهی کاربرد مدل شبکهای قرار دارد‪.‬‬
‫از این پروتکل برای ایجاد ارتباط )ایجاد نشست جدید( بین مبدأ و مقصد استفاده و مابین دو کاربر پیامهایی‬
‫ارسال میشود‪ .‬از مهمترین اهداف این پروتکل میتوان به موارد زیر اشاره کرد‪:‬‬
‫‪ (۱‬ایجاد نشست )تماس( جدید بین دو کاربر؛‬
‫‪ (۲‬مدیریت و کنترل کلیه نشستها؛‬
‫‪ (۳‬قطع نشستها و خاتمه تماسها‪.‬‬
‫پروتکل ‪ SIP‬یک پروتکل متنی خواندنی‪ ۱‬است‪ .‬بهطوریکه با مشاهدهی پیامهای آن‪ ،‬امکان تفسیر آنها‬
‫وجود دارد )شکل ‪.(۱-7‬‬

‫شکل ‪1-7‬‬

‫همانطورکه در شــکل ‪ ۱-7‬مالحظه میکنید‪ ،‬هنگام شــروع یک تماس‪ ،‬کاربر ‪ Bob‬یک درخواست جدید‬
‫برای ایجاد تماس به کاربر ‪ Tom‬ارسال میکند‪ ،‬سپس گوشی ‪ Tom‬زنگ میخورد؛ در این زمان پیام زنگ‬
‫خوردن به کاربر ‪ Bob‬ارســال میشــود‪ .‬کاربر ‪ Bob‬متوجه میشود که گوشی ‪ Tom‬در حال زنگ خوردن‬
‫اســت‪ .‬پس از اینکه کاربر ‪ Tom‬تماس را پاســخ داد‪ ،‬پیام تأیید ارســال میشود‪ .‬در پاسخ به این پیام‪ ،‬کاربر‬
‫‪ Bob‬پیام تأیید مبنی بر شــروع زمان مکالمه را ارسال میکند‪ .‬به این ترتیب مراحل پروتکل سیگنالیک ‪SIP‬‬
‫برای ایجاد نشست جدید به پایان میرسد و دو کاربر میتوانند از طریق پروتکل ‪ RTP‬با هم مکالمه نمایند‪.‬‬
‫پس از اتمام مکالمه‪ ،‬دوباره پیام قطع مکالمه بوسیله پروتکل ‪ SIP‬و به واسطه یکی از کاربرها )در اینجا کاربر‬

‫‪1- Text base‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 174

‫ را ارسال میکند و تماس قطع میشود و به‬200 OK ‫ پیام‬،‫ با تأیید آن‬Bob ‫ کاربر‬.‫( ارســال میشــود‬Tom
.‫این ترتیب نشست میان این دو کاربر در سرور به پایان میرسد‬
‫ را میتوان‬INVITE ‫ محتویات پیــام‬.‫اکنــون میتوان محتویات پیامهای این نشســت را بررســی کــرد‬
:‫مشاهده نمود‬ ‫بهصورت زیر‬
INVITE sip:Tom@192.168.154.128;transport=UDP SIP/2.0
Via: SIP/2.0/UDP 192.168.154.1:5060;branch=z9hG4bK-d8754z-ca97d503b93222cf-1---
d8754z-
Max-Forwards: 70
Contact: <sip:Bob@192.168.154.1:5060;transport=UDP>
To: <sip:Tom@192.168.154.128;transport=UDP>
From: <sip:Bob@192.168.154.128;transport=UDP>;tag=a5575819
Call-ID: YWMzYjY0YzVhMzgzZDY1ZTlmMDFiYjQ2MDE2NjcxNjU.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
Content-Type: application/sdp
Supported: replaces, norefersub, extended-refer, X-cisco-serviceuri
User-Agent: Zoiper rev.11137
Allow-Events: presence, kpml
Content-Length: 329

v=0
o=Zoiper_user 0 0 IN IP4 192.168.154.1
s=Zoiper_session
c=IN IP4 192.168.154.1
t=0 0
m=audio 8000 RTP/AVP 3 0 8 110 98 101
a=rtpmap:3 GSM/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:110 speex/8000
a=rtpmap:98 iLBC/8000
a=fmtp:98 mode=30
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=sendrecv

‫ پیام‬،‫ صادر میشود‬INVITE ‫پیامی که معموالً )در صورت آمادگی برای پاســخ از ســمت مقابل( در پاسخ‬
،‫ در پاســخ به این پیام‬.‫( اســت و اعالم میکند که طرف مقابل در حال زنگ خوردن اســت‬۱8۰ Ringing)
.‫ میخورد‬Ringing ‫گوشی ما هم بوق‬
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 192.168.154.128:5060;branch=z9hG4bK69e0e7c1;rport=5060
Contact: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>
175 ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

To: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>;tag=
9e369779
From: "device"<sip:Tom@192.168.154.128>;tag=as64e26f7e
Call-ID: 17cde2fa7c2ac31d72125de822787ecd@192.168.154.128:5060
CSeq: 102 INVITE
User-Agent: Zoiper rev.11137
Content-Length: 0

.‫ مشخص میشود که کاربر تماس را پاسخ داده است‬200 OK ‫ازطریق پیام‬


SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.154.128:5060;branch=z9hG4bK69e0e7c1;rport=5060
Contact: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>
To: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>;tag=
9e369779
From: "device"<sip:Tom@192.168.154.128>;tag=as64e26f7e
Call-ID: 17cde2fa7c2ac31d72125de822787ecd@192.168.154.128:5060
CSeq: 102 INVITE
Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
Content-Type: application/sdp
Supported: replaces, norefersub, extended-refer, X-cisco-serviceuri
User-Agent: Zoiper rev.11137
Allow-Events: presence, kpml
Content-Length: 329

v=0
o=Zoiper_user 0 2 IN IP4 192.168.154.1
s=Zoiper_session
c=IN IP4 192.168.154.1
t=0 0
m=audio 8002 RTP/AVP 0 3 8 110 98 101
a=rtpmap:0 PCMU/8000
a=rtpmap:3 GSM/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:110 speex/8000
a=rtpmap:98 iLBC/8000
a=fmtp:98 mode=30
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=sendrecv

.‫( در تأیید پاسخ تماس ارسال میشود و دو کاربر میتوانند مکالمه خود را آغاز کنند‬ACK) ‫پیام‬
ACK sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP SIP/2.0
Via: SIP/2.0/UDP 192.168.154.128:5060;branch=z9hG4bK4d0c8070;rport
Max-Forwards: 70
From: "device" <sip:Tom@192.168.154.128>;tag=as64e26f7e
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 176

To: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>;tag=
9e369779
Contact: <sip:Tom@192.168.154.128:5060>
Call-ID: 17cde2fa7c2ac31d72125de822787ecd@192.168.154.128:5060
CSeq: 102 ACK
User-Agent: FPBX-2.8.1(1.8.7.0)
Content-Length: 0

-- SIP/Bob-00000023 answered SIP/Tom-00000022


Audio is at 5060
Adding codec 0x4 (ulaw) to SDP
Adding codec 0x8 (alaw) to SDP
Adding codec 0x2 (gsm) to SDP
Adding non-codec 0x1 (telephone-event) to SDP

.‫( ارسال میشود‬BYE) ‫ پیام خاتمه تماس‬،‫پس از پایان یافتن مکالمه‬


BYE sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP SIP/2.0
Via: SIP/2.0/UDP 192.168.154.128:5060;branch=z9hG4bK1f7ea96e;rport
Max-Forwards: 70
From: "device"<sip:Tom@192.168.154.128>;tag=as5d6280b9
To: <sip:Bob@192.168.154.1:5060;rinstance=fc85cf7452e43e92;transport=UDP>;tag=2622
bd0e
Call-ID: 3ba6e2203ffb494c1ef2410b34e3aa05@192.168.154.128:5060
CSeq: 103 BYE
User-Agent: FPBX-2.8.1(1.8.7.0)
X-Asterisk-HangupCause: Normal Clearing
X-Asterisk-HangupCauseCode: 16
Content-Length: 0

‫ پیشتر هم‬.‫ همه پیامهای ارســال شــده به صورت متنی و قابل خواندنند‬،‫همانطورکه مالحظه میشــود‬
‫ بــرای درک بهتر این‬.‫ در برقراری ارتباط اســتفاده میکنیم‬RTP ‫ و‬SIP ‫اشــاره شــد که ما از دو پروتــکل‬
.‫ فرض کنید یک ارتباط تلفنی در شبکه ویپ به صورت شکل زیر باشد‬،‫موضوع‬

2-7 ‫شکل‬
‫‪177‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫در ایــن شــکل ما باید از هر دو پروتکل برای ایجاد یک تماس اســتفاده کنیــم‪ .‬از پروتکل ‪ SIP‬برای ایجاد‬
‫تمــاس‪ ،‬کنترل و مدیریــت تماس و خاتمه دادن به تماس‪ ،‬و از پروتکل ‪ RTP‬بــرای انتقال صوت و مدیا در‬
‫شبکههای ویپ استفاده میشود‪.‬‬
‫توجه داشــته باشــید که ما از دو نوع پروتکل مختلف در یک ارتباط تلفنی اســتفاده میکنیم و این خود‬
‫مشکالت ‪ NAT Traversal‬میشود‪ ،‬چون اکثر کاربران در اینترنت‪ ،‬با ‪ NAT‬کار میکنند‪.‬‬ ‫باعث بروز‬

‫بررسی مشکالت ‪ NAT‬در شبکه‌های ویپ‬


‫همانطورکه میدانید با اســتفاده از ‪ NAT‬این امکان فراهم میگردد که چندین کامپیوتر‪ ،‬لپتاپ و گوشی‬
‫موبایل از طریق یک ‪ IP‬به شبکه اینترنت متصل شوند‪.‬‬

‫شکل ‪3-7‬‬

‫بحث ‪ NAT‬در شبکههای کامپیوتری خارج از چارچوب کتاب است‪ ،‬ولی ازآنجاکه در شبکههای ویپ‪،‬‬
‫مشکالت ناشی از ‪ NAT‬بسیار شایع است‪ ،‬مختصری راجع به آن توضیح خواهیم داد‪.‬‬
‫چنانچه تجهیزاتی که در ارتباط با ‪ NAT‬هســتند درخواستهای خود را به شبکهی اینترنت ارسال کنند‪،‬‬
‫پاســخ آنها را دریافت میکنند‪ .‬بر همین اساس غالبا بهوسیله ‪ ،NAT‬استفاده از اینترنت راحت است‪ .‬اکنون‬
‫یک پرســش مهم این اســت که آیا این احتمال وجود دارد درخواستی از بیرون وارد شود ولی نتوانیم آن را‬
‫به آدرس خاصی نگاشــت دهیم؟ پاســخ مثبت است‪ .‬بیشتر درخواســتها از داخل شبکه به خارج از آناند‪،‬‬
‫بنابراین مودم میتواند آنها را بدون مشکل نگاشت کند و هر زمان که پاسخ آنها را دریافت کند‪ ،‬به آدرس‬
‫کالینت مورد نظر ارســال کند‪ .‬چنانچه درخواســتی در یک پورت جدید به مودم داده شــود و مودم نتواند‬
‫آدرسش را نگاشت و کالینت مورد نظر را پیدا کند )که این پاسخ در برابر کدام درخواست رسیده است(‪،‬‬
‫آن را نخواهد پذیرفت‪ .‬شکل ‪ 4-7‬این فرآیند را در شبکههای ویپ با پروتکل ‪ RTP‬نمایش میدهد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪178‬‬

‫شکل ‪4-7‬‬

‫همانطورکه مالحظه میشــود‪ ،‬کالینت ابتدا درخواســت برقراری تماس را از طریق پروتکل ‪ SIP‬به ســرور‬
‫ارســال و ســرور هم پاســخ آن تماس را قبول میکند‪ .‬پس از برقراری تماس‪ ،‬جریانهای ترافیکی از طریق‬
‫پروتکل ‪ RTP‬منتقل میشوند‪ .‬کالینت از طریق این پروتکل‪ ،‬دادههای صوتی را برای سرور ارسال میکند و‬
‫سرور هم در پاسخ‪ ،‬دادههای صوتی را روی پورت دیگری برای کالینت ارسال میکند‪ .‬مودم ‪ NAT‬جلوی‬
‫دریافت این دادهها را میگیرد و دادهها از بین میروند‪ .‬در چنین شــرایطی معضل یک طرفهبودن صدا پدید‬
‫میآید‪ .‬برای واضحتر شدن موضوع‪ ،‬سه سناریوی متفاوت بررسی میشوند‪:‬‬
‫‪ (۱‬زمانی که کالینتها با ‪ NAT‬کار کنند؛‬
‫‪ (۲‬زمانی که سرور استریسک متصل به ‪ NAT‬باشد؛‬
‫‪) double_ NAT (۳‬زمانی که هر دو به ‪ NAT‬متصل باشند(‪.‬‬
‫مسلماً در هر یک از شرایط باال‪ ،‬چالشهایی وجود دارد که باید به دقت مورد بحث قرار گیرد‪.‬‬

‫کالینت با ‪ NAT‬کار کند‬


‫هر دادهای که در شبکه منتقل میشود‪ ،‬برای مسیریابی‪ ،‬یک آدرس مبدأ و مقصد دارد‪ .‬این مسیریابی در الیه‬
‫شــبکه صورت میگیرد‪ .‬عالوه بر این آدرسها‪ ،‬درون بدنه پروتــکل ‪ SIP‬در الیه کاربردی‪ ،‬وقتی کالینتی‬
‫پیامی ارسال میکند‪ ،‬آدرس ‪ IP‬خودش را قرار میدهد‪ .‬برای مثال شکل ‪ ۵-7‬را ببینید‪:‬‬
‫همانطورکه مالحظه میکنید‪ ،‬در قسمت باال‪ ،‬آدرس آیپی در هر دو الیه شبکه و الیه کاربردی یکسان‬
‫اســت‪ .‬زمانی که دادهها از ‪ NAT‬عبور میکنند )قســمت وســط شــکل(‪ ،‬آدرس آیپی آنها در الیه شبکه‬
‫عوض میشــود )آدرس آیپی ‪ NAT‬شــده را میگیرند(‪ ،‬ولی آدرس آیپی داخل بدنه پروتکل ‪ SIP‬تغییر‬
‫نمیکند‪ .‬هنگامی که یک پیام سیگنالینگ به سرور برسد‪ ،‬سرور دو آدرس آی پی متفاوت را میبیند‪ :‬یکی‬
‫آدرس آیپی محلی کالینت و دیگری آدرس آیپی‪ NAT‬شده کالینت‪ .‬حال سوال اینجاست که سرور از‬
‫کدام آدرس آیپی استفاده خواهد کرد؟‬
‫برای روشنتر شدن موضوع به بررسی یک مثال میپردازیم )شکل ‪ ۶-7‬را در نظر بگیرید(‪.‬‬
‫‪179‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫شکل ‪5-7‬‬

‫شکل ‪6-7‬‬

‫در شــکل ‪ ،۶-7‬یک کامپیوتر‪ ،‬یک دســتگاه روتر برای اتصال به اینترنت و یک سرور استریسک دیده‬
‫میشــود‪ .‬همانطورکه مالحظه میکنید سرور استریســک دارای آدرس ‪ Public‬است‪ .‬کامپیوتر )که دارای‬
‫نرم افزار کالینتی ‪ SIP‬است( درخواست خود را به صورت شکل ‪ 7-7‬به سمت سرور ارسال کند‪.‬‬

‫شکل ‪7-7‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪180‬‬

‫تا پیش از رســیدن به روتر )قبل از ‪ NAT‬شدن(‪ ،‬آدرس شبکهای با آدرس ذخیره شدن در بدنه پروتکل‬
‫‪ SIP‬برابر اســت‪ .‬هنگامیکه در خواســت از روتر عبور میکند‪ ،‬آدرس شــبکهای آن نیز تغییر میکند و بعد‬
‫از مســیریابی به سرور استریسک میرسد‪ .‬آدرسی که استریســک برای ارتباط با کالینت مورد نظر استفاده‬
‫میکند‪ ،‬به صورت زیر است‪:‬‬
‫‪phone-1 | registered@192.168.1.20‬‬

‫اکنون فرض کنید استریســک تماسی را به ســمت کالینت ‪ phone-1‬ارسال کند‪ .‬ازآنجاکه این کالینت در‬
‫یک آدرس نامعتبر از نظر ســرور ذخیره شــده است‪ ،‬ســرور نمیتواند آدرس فوق را پیدا کند؛ لذا کالینت‬
‫‪ phone-1‬از نظر سرور قابل دسترس نیست‪ .‬شکل ‪ 8-7‬این موضوع را نمایش میدهد‪.‬‬

‫شکل ‪8-7‬‬

‫در یک چنین شــرایطی وقتــی کالینتها با ‪ NAT‬کار میکننــد‪ ،‬باید پارامتر زیــر را در هنگام تعریف‬
‫کاربران به این صورت تعریف کنیم‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phone-1‬‬
‫‪nat=yes‬‬

‫حال اگر پیامی از طرف یک کالینت به ســرور استریســک برســد‪ ،‬استریســک با درنظرگرفتن پارامتر‬
‫‪ nat=yes‬برای کالینت‪ ،‬از آدرس آیپی درون بدنه پیام ‪ SIP‬صرفنظر میکند و در عوض آدرس آیپی‬
‫شبکهای پیام دریافتی را درنظر میگیرد )شکل ‪.( ۹-7‬‬
‫مطابق شــکل ‪ ،۹-7‬در یک چنین حالتی )‪ ،(nat=yes‬آدرس آیپی روتر درنظرگرفته میشــود‪ .‬در این‬
‫حالت استریســک میتواند این آدرس آیپی را مســیریابی و در صورت لزوم‪ ،‬تماس را به ســمت کالینت‬
‫ارسال کند‪ .‬چنانچه تماس به سمت روتر ارسال شود‪ ،‬روتر آن را به سمت کالینت مورد نظر فوروارد میکند‪.‬‬
‫‪181‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫شکل ‪9-7‬‬

‫مشــکل ‪ NAT‬تنها در خصوص پروتکل ســیگنالینگ ‪ SIP‬اتفاق نمیافتد‪ ،‬بلکه در خصوص انتقال صدا‬
‫)‪ (RTP‬نیز صادق اســت و منجر به یکطرفهشــدن صدا یا جلوگیری از انتقال آن میشــود؛ بنابراین‪ ،‬هنگام‬
‫فعالکردن پارامتر ‪ nat‬در استریسک ‪ ،۱۳‬باید این مقادیر را تعریف کنیم‪:‬‬
‫‪nat = force_report,comedia‬‬

‫اصطــالح ‪ comedia‬مخفف ‪ connection oriented media‬اســت‪ .‬یعنی برای ارســال یک پیام ‪، RTP‬‬
‫استریســک باید به ‪ IP‬و ‪ PORT‬آدرس شــبکهای که پیام از آنجا ارسال شدهاست‪ ،‬دسترسی داشتهباشد و به‬
‫آدرس ذخیره شده درون بدنه پروتکل ‪ SIP‬کاری نداشته باشد‪.‬‬
‫ازآنجاکه هر لحظه ممکن اســت ارتباط بین کالینتها و ســرور استریســک قطع شود‪ ،‬استریسک باید‬
‫نســبت به حفظ این ارتباط با کالینتها حســاس باشــد و وضعیت آنها را دائماً بررسی کند‪ .‬این قابلیت در‬
‫استریسک هنگام تعریف داخلی‪ ،‬ازطریق پارامتر ‪ qualify‬فعال میشود‪.‬‬
‫‪;sip.conf‬‬
‫]‪[phone-1‬‬
‫‪qualify=yes‬‬

‫درصورتیکه این پارامتر را برای کاربری تعریف نکردهباشــید‪ ،‬بهصورت پیشفرض استریسک ارتباط‬
‫بین کالینت و خودش را چک نمیکند و به صورت ‪ unmonitored‬باقی میماند‪ .‬در استریســک با دســتور‬
‫زیر میتوانید از وضعیت همه کاربران مطلع شوید‪.‬‬
‫‪CLI> sip show peers‬‬

‫اکنون چنانچه ارتباط بین استریسک و کالینت قطع شود چه وقایعی ممکن است رخ دهد؟ پاسخ به این‬
‫سوال را به صورت زیر بیان میکنیم‪:‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪182‬‬

‫زمانی که برای اولین بار یک کالینت در خواست رجیستر شدن خود را به سرور ارسال میکند‪ ،‬درواقع‬
‫آدرس فیزیکی خود را به استریسک معرفی کرده است‪ .‬از این پس استریسک چنانچه بخواهد تماسی برای‬
‫آن داخلی )کالینت( ارسال کند‪ ،‬از آدرس ذخیره شده استفاده میکند‪.‬‬
‫استریســک بایــد دربازههای زمانی متفــاوت‪ ،‬وضعیت همــه کالینتهای خود را بررســی کند که آیا‬
‫قابلدسترســیاند یا نه‪ .‬اگر وضعیت کالینتی‪ ،‬غیر قابل دســترس باشــد‪ ،‬یعنی استریسک نمیتواند تماسی را‬
‫به ســمت کالینت مورد نظر ارســال کند‪ ،‬اما این کالینت میتواند درخواست خود را برای سرور استریسک‬
‫ارسال کند‪ ،‬چون در تنظیمات کالینت‪ ،‬آدرس استریسک صریحاً معرفی شدهاست‪.‬‬

‫سرور استریسک قبل از ‪ NAT‬باشد‬


‫زمانی که استریسک قبل از ‪ NAT‬است‪ ،‬برای ارائه یک عملکرد صحیح‪ ،‬باید چند فرآیند صورت گیرد‪:‬‬
‫‪ .۱‬پورتهای زیر را باید در دستگاه روتر به سمت سرور استریسک فوروارد کنید؛‬
‫• پورت سیگنالینگ ‪ SIP‬که به‌صورت پیش‌فرض روی ‪ 5060‬است‪.‬‬
‫• پورت‌های در نظر گرفته شــده برای مدیا (انتقال صدا) به‌صورت پیش‌فرض در استریســک بین‬
‫ ‪ 10000‬است‪.‬‬
‫‪-20000‬‬
‫‪ .۲‬پارامترهای زیر را در فایل ‪ sip.conf‬تنظیم کنید‪ .‬اینجا باید از آدرس آی پی ‪ Public‬استفاده کنید‪.‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫> ‪externip = < Public IP Address‬‬
‫>‪externip = < Public IP Address > : <port‬‬

‫در این حالت این قابلیت وجود دارد که بهجای آدرس آیپی‪ ،‬از نام ‪ host‬برای معرفی آدرس استفاده کنیم‬
‫که در اینصورت آدرس مربوطه باید ‪ resolved‬شود‪:‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫>‪externhost = < Domain Name > : < port‬‬
‫‪externrefresh: 300‬‬

‫در برخی سناریوها ممکن است استریسک پشت ‪ NAT‬باشد و کاربرانی هم باشند که با آدرس آیپی داخلی‬
‫بخواهند به استریســک متصل شوند )رجیستر شوند(‪ .‬در یک چنین شرایطی باید پارامتر ‪ localnet‬را در فایل‬
‫‪ sip.conf‬در سرویس استریسک فعال کنیم تا کاربران داخلی شبکه بتوانند به استریسک متصل شوند‪.‬‬
‫این تنظیمات میتوانند بصورت زیر باشند‪:‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫‪externip = 98.139.183.24‬‬
‫‪localnet = 172.16.0.0/24‬‬
‫‪localnet = 192.168.100.0/255.255.255.0‬‬
‫‪183‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫در این شــرایط‪ ،‬کاربران میتوانند از طریق شــبکه اینترنت به ســرور استریسک متصل شوند و کاربران‬
‫داخلی هم با داشتن ‪ localnet‬میتوانند به سرور استریسک متصل شوند‪.‬‬

‫بررسی حالت ‪( double_nat‬استریسک و کالینت هر دو به ‪ NAT‬متصل‌اند)‬


‫در این شــرایط‪ ،‬کالینت و سرور استریســک هر دو به‪ NAT‬متصلاند‪ .‬توجه داشته باشید که چالشهای دو‬
‫بخش قبل‪ ،‬همچنان در این بخش نیز وجود خواهند داشت‪.‬‬

‫کنترل جریان‌های ترافیکی (‪ )RTP‬در استریسک‬


‫یکــی از چالشهای اصلی و نســبتاً مهم شــبکههای ‪ ،VoIP‬کنتــرل جریانهای ترافیکی مدیــا و جریانهای‬
‫ترافیکی ســیگنالینگ اســت‪ .‬ازآنجاکه تعداد جریانهای ترافیکی مدیا )‪ (RTP‬بســیار بیشــتر از جریانهای‬
‫سیگنالینگ)‪ (SIP‬است‪ ،‬تأثیر مستقیم آن در مصرف منابع سختافزاری اجتنابناپذیر است‪.‬‬
‫معموالً در شــبکههای ‪ VoIP‬میتوان جریانهای ترافیکی مدیا و ســیگنالینگ را از هم جدا کرد و برای‬
‫هرکدام مسیرهای متفاوتی را درنظر گرفت ‪.‬‬
‫کنترل جریانهای ترافیکی مدیا در شبکههای ویپ به دو روش قابل انجام است‪:‬‬
‫‪ (۱‬به صورت )‪B۲BUA (Back to Back User Agent‬‬
‫‪ (۲‬به صورت نقطه به نقطه )‪(Point-To-Point‬‬

‫کنترل جریان‌های ترافیکی مدیا به صورت ‪B2BUA‬‬


‫در ایــن حالت ســرور ‪ VoIP‬بهعنوان یک واســط بین دو کاربر قرار میگیرد و ترافیــک را به آنها منتقل‬
‫میکند‪ .‬برای مثال شکل ‪ ۱۰-7‬را درنظر بگیرید‪:‬‬

‫شکل ‪10-7‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪184‬‬

‫همانطــور که مالحظه میکنید عالوه بر جریانهای ســیگنالینگی از طریق ســرور بین دو کاربر منتقل‬
‫میشود ‪ ،‬جریانهای ترافیکی مدیا )‪ (RTP‬هم از طریق سرور میانی بین دو کاربر انتقال مییابد‪.‬‬
‫پر واضح است که در چنین شرایطی چون ترافیک مدیا از سرور عبور میکند‪ ،‬میتوان همه مکالمات را‬
‫ضبط کرد و حتی جریانهای ترافیکی ‪ DTMF‬را نیز تشــخیص داد‪ .‬اما باید درنظر داشــت که عبور این نوع‬
‫ترافیکها از سرور‪ ،‬منابع زیادی مصرف میکند‪.‬‬
‫چنانچه دو کاربر از کدکهای مختلفی در ســمت خود اســتفاده کنند‪ ،‬هنگامی که داده به سرور برسد‪،‬‬
‫عملیات تبدیل کدک بوسیله سرور میانی صورت میگیرد و سپس به کاربر مقابل ارسال میگردد‪ .‬عملیات‬
‫تبدیل کدک در سرور نیز منابع زیادی از ‪ CPU‬را مصرف میکند‪.‬‬
‫در استریســک برای تنظیم کاربران به منظور استفاده از حالت ‪ ، B۲BUA‬باید تنظیمات زیر را برای هر‬
‫کاربر اعمال کنید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phone-1‬‬
‫‪canreinvite = no‬‬
‫‪directmedia = no‬‬

‫]‪[phone-2‬‬
‫‪canreinvite =no‬‬
‫‪directmedia = no‬‬

‫کنترل جریان ترافیکی به صورت ‪Point-To-Point‬‬


‫در این حالت پس از انجام عملیات ســیگنالینگ‪ ،‬جریانهای ترافیکی بین دو کاربر به صورت مستقیم مبادله‬
‫خواهد شد‪ .‬شکل ‪ ۱۱-7‬مسیر ترافیکی جریانهای سیگنالینگ و مدیا را نمایش میدهد‪.‬‬

‫شکل ‪11-7‬‬
‫‪185‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫در این حالت چون جریانهای ترافیکی مدیا از مســیر دیگری )به جز ســرور( عبور میکنند‪ ،‬سرور منابع‬
‫بیشــتری در اختیــار دارد و میتوانــد تماسهای همزمان بیشــتری را کنترل کند‪.‬عالوه بــر این‪ ،‬مکالمات و‬
‫‪ DTMF‬را نیز نمیتوان ضبط کرد و چون مدیا به صورت مســتقیم میان هر دو کاربر توزیع میشــود‪ ،‬اگر از‬
‫کدکهای یکسانی استفاده نکنید با مشکالتی مواجه خواهیدشد‪.‬‬
‫در استریسک برای تنظیم کاربران به منظور استفاده از حالت ‪ ، P2P‬باید تنظیمات زیر را برای هر کاربر‬
‫اعمال کنید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phone-1‬‬
‫‪canreinvite =yes‬‬
‫‪directmedia = yes‬‬

‫]‪[phone-2‬‬
‫‪canreinvite =yes‬‬
‫‪directmedia = yes‬‬

‫سوالی که اینجا مطرح میشود این است که کدامیک از حالت ها برای سرور استریسک بهتر و مناسبتر‬
‫است؟‬
‫در پاســخ چنانچه ســرور استریســک و همه کاربران‪ ،‬داخل یک شبکه محلی باشــند‪ ،‬میتوان از ‪P2P‬‬
‫استفاده نمود‪ ،‬ولی اگر برخی از کاربران به ‪ NAT‬متصل باشند‪ ،‬بهتر است از حالت ‪ B2BUA‬استفاده شود تا‬
‫با مشکالت ‪ Nat-Traversal‬در شبکههای ویپ درگیر نشویم‪.‬‬
‫در شــرایطی که برخی کاربران به ‪ NAT‬متصلند و برخی دیگر به شبکه محلی‪ ،‬این قابلیت در استریسک‬
‫وجــود دارد که تنها برای کاربران شــبکه محلــی‪ ،‬جریانهای ترافیکی مدیا به صورت ‪ P2P‬باشــند‪ .‬در این‬
‫صورت تنظیماتی در سرور استریسک در ‪ sip.conf‬باید انجام دهید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫‪directmediadeny = 0.0.0.0/0‬‬
‫‪directmediapermits = 192.168.101.0/24‬‬
‫‪directmediapermits = 192.168.1.0/24‬‬

‫شــبکههای ویپ میتوانند با توپولوژیهای مختلفی با سایر شبکههای مخابراتی‪ ،‬در ارتباط باشند که در‬
‫ادامه فصل‪ ،‬به چگونگی این ارتباطات میپردازیم‪.‬‬

‫‪PSTN Termination‬‬
‫در شــبکههای ویپ این امکان وجود دارد که تماسهای ایجاد شــده از داخل شــبکه را به شبکه مخابراتی‬
‫‪ PSTN‬منتقــل کنیم‪ .‬به عملیات ایجاد تماس از طریق شــبکههای ‪ VoIP‬و انتقال آن به شــبکههای ‪، PSTN‬‬
‫‪ Termination‬گویند‪.‬‬ ‫عملیات‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪186‬‬

‫معمــوالً ارتباط بین شــبکههای ‪ VoIP‬با شــبکههای مخابراتی ‪ PSTN‬ازطریــق ‪ PSTN-GW‬ها صورت‬
‫میگیرد‪ .‬این تجهیزات معموالً ازطریق لینکهای پرظرفیت ‪ PRI‬به شــبکههای مخابراتی متصل میشــوند و‬
‫میتوانند بهصورت کارتهای سخت افزاری ‪ DAHDI‬با استریسک در ارتباط باشند و یا از طریق گیتوی‬
‫با سرور استریسک ارتباط برقرار کنند‪.‬‬

‫‪PSTN ORGINATION‬‬
‫در شــبکههای ویپ این امکان وجود دارد که تماسهایی از ســمت شــبکه مخابراتی ‪ PSTN‬به شبکه ‪VoIP‬‬
‫داشــته باشــیم‪ .‬عملیات ایجاد تماس از طرف شبکه مخابراتی ‪ PSTN‬به شبکه ‪ VoIP‬را عملیات ‪Orgination‬‬
‫گویند‪.‬‬
‫برای ایجاد یک تماس ‪ ، Orgination‬باید یک شــماره معتبــر ‪ DID_Number‬ازطرف مرکز مخابراتی‬
‫داشــته باشیم‪ .‬این شــماره بهصورت صریح در شــبکه مخابراتی ‪ PSTN‬تعریف میشود و در اختیار مشتری‬
‫قرار میگیرد‪.‬‬

‫‪VOIP _TO_ VOIP‬‬


‫در شــبکههای ویپ این امکان وجود دارد که با ســایر شــبکههای ویپ ارتباط داشته باشیم‪ .‬پیش از بررسی‬
‫بیشتر این موضوع‪ ،‬نخست بهتر است انواع توپولوژیها در شبکههای ویپ را بررسی کنیم‪.‬‬

‫توپولوژی ذوزنقه‌ای‬
‫در این شبکهها‪ ،‬تماس بین دو کاربر که هر یک از ‪ domain‬متفاوتی هستند‪ ،‬ایجاد میشود‪ .‬در شکل ‪۱۲-7‬‬
‫کاربر ‪ agentA‬از ‪) domainA‬ســرور استریســک‪ (۱‬یک تماس با ‪ agentB‬از ‪) domainB‬سرور استریسک‬
‫‪ (۲‬برقرار میکند‪ .‬در این مدل از شبکهها باید بین سرورها یک ارتباط وجود داشته باشد‪ .‬این ارتباط از نوع‬
‫‪ SIP-Trunk‬تعریف شده است‪.‬‬

‫شکل ‪12-7‬‬
‫‪187‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫توپولوژی مثلثی‬
‫در این توپولوژی هر دو کاربر در یک ‪) Domain‬ســرور استریســک( قرار دارند و تماس میان آنها برقرار‬
‫میگردد‪.‬‬

‫شکل‪13-7‬‬

‫تا اینجاتوپولوژی مثلثی در مثالها بیشتر توضیح داده شده است‪ .‬برای ایجاد ارتباط میان سایر شبکههای‬
‫ویپ )توپولوژیهای ذوزنقهای(‪ ،‬باید میان ســرورهای ‪ VoIP‬ارتباط برقرار کنید‪ .‬میان دو ســرور استریسک‬
‫میتوان به چند روش مختلف ارتباط برقرار کرد‪:‬‬
‫‪• SIP_Trunk‬‬
‫‪• IAX2_Trunk‬‬
‫‪• PRI_Link‬‬
‫‪• H323_Trunk‬‬
‫‪• TDMOE‬‬

‫در اینجا انواع روش های ارتباطی از طریق ‪ SIP_Trunk‬و ‪ IAX2_Trunk‬را شرح می دهیم‪.‬‬

‫‪SIP_Trunk‬‬
‫ایجاد ‪ SIP_Trunk‬بین دو سرور استریسک‪ ،‬دو روش وجود دارد‪:‬‬ ‫برای‬

‫‪ : Registration (۱‬در این حالت‪ ،‬ارتباط ‪ SIP_Trunk‬با عملیات ‪ Registration‬ایجاد میشود‪ .‬سپس هر دو‬
‫ســرور از همین طریق ارتباط خواهند داشت و میتوانند تماسهایی را به سوی یکدیگر انتقال دهند )معموالً‬
‫این نوع از ترانک بیشتر توسط ‪ VoIP_Provider‬ها انجام میشود(‪.‬‬

‫‪ : Trust_IP (۲‬در این ارتباط‪ ،‬دو ســرور استریســک نســبت به ‪ IP‬یکدیگر قابل اعتمادند و اگر تماسی از‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪188‬‬

‫طرف این ‪ IP‬ها ارســال شــود‪ ،‬آن را میپذیرنــد‪ .‬در این روش هیچ گونه عملیــات ‪ Registration‬صورت‬
‫نمیگیرد‪.‬‬

‫برای مثال اگر بین دو سرور ‪ A‬و ‪ B‬یک ارتباط از نوع ‪ Trust_IP‬ایجاد کنید‪ ،‬در طرف ‪ Server A‬باید‬
‫‪ sip.conf‬قرار دهید‪:‬‬ ‫تنظیمات زیر را در‬

‫شکل ‪14-7‬‬
‫‪;sip.conf‬‬
‫]‪[server B‬‬
‫‪type = peer‬‬
‫‪host = 192.168.1.102‬‬
‫‪defaultuser = server A‬‬
‫‪secret = apples‬‬
‫‪context = incoming‬‬
‫‪disallow = all‬‬
‫‪allow = ulaw‬‬
‫‪qualify = yes‬‬

‫‪ sip.conf‬قرار دهید‪.‬‬ ‫در ‪ Server B‬باید تنظیمات زیر را در‬


‫‪;sip.conf‬‬
‫]‪[server A‬‬
‫‪type = peer‬‬
‫‪host = 192.168.1.101‬‬
‫‪defaultuser = server B‬‬
‫‪secret = apples‬‬
‫‪context = incoming‬‬
‫‪disallow = all‬‬
‫‪allow = ulaw‬‬
‫‪qualify = yes‬‬

‫پس از انجام تغییرات در هر دو ســرور ‪ ،‬وارد محیط کامندالین استریســک شوید و ماژول ‪ chan_sip.so‬را‬
‫‪ reload‬نمایید‪:‬‬
‫‪CLI> sip reload‬‬

‫برای مشاهده وضعیت ارتباط ‪ SIP_Trunk‬در هر سرور‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫‪CLI> sip show peers‬‬

‫در این حالت وضعیت ترانک باید در حالت ‪ OK‬باشد‪.‬‬


‫‪189‬‬ ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

‫پس از اینکه ترانک بین دو سرور برقرار شد‪ ،‬باید بتوانید بین دو سرور تماس برقرار کنید‪ .‬در این حالت‬
‫فرض کنید در سرور ‪ A‬بخواهیم شمارهای را که با ‪ prefix =6‬آغاز میشود‪ ،‬به سوی سرور ‪ B‬ارسال کنیم‪.‬‬
‫در این صورت باید برنامه زیر را بنویسید‪:‬‬
‫‪;ServerA‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => _6XXX.,1,Dial(SIP/${EXTEN}@serverB‬‬

‫یا در سرور ‪ B‬باید به صورت زیر برنامه خود را بنویسید‪:‬‬


‫‪;ServerB‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => _6XXX.,1,Dial(SIP/${EXTEN}@serverA‬‬

‫‪SIP_Providers‬‬
‫همانطورکه در قبال شــرح داده شــد‪ ،‬اســتفاده از ‪ Registration‬عمدتــا ازطریــق ‪ VoIP-Provider‬ها که‬
‫ســرویسهای ویپ را بهصورت اینترنتی ارائه میدهند‪ ،‬صورت میگیرد‪ .‬در یک چنین روشی از ‪Trust_IP‬‬
‫اســتفاده نمیشــود‪ .‬برای مثال فرض کنید بخواهیم از یک ‪ Provider‬برای ارسال تماس به سوی آن استفاده‬
‫قرار میدهند‪:‬‬ ‫کنیم‪ .‬اکثر ‪ Provider‬ها اطالعات زیر را در اختیار کاربران خود‬
‫• نام دامین ‪domain IP -‬‬
‫• نام کاربری ‪Username -‬‬
‫• کلمه عبور ‪Password -‬‬
‫اگر بخواهیم از سمت یک ‪ Provider‬فقط تماس ورودی دریافت کنیم‪ ،‬باید عبارت زیر را در قسمت‬
‫]‪ [general‬فایل ‪ sip.conf‬اضافه کنیم ‪:‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫‪register => username:password@domain‬‬

‫با استفاده از دستور زیر میتوان اطالع پیدا کرد که آیا عملیات رجیستر شدن با موفقیت انجام شده است یا نه‪:‬‬
‫‪CLI> sip show registery‬‬

‫اگر بخواهید تماس را به ســوی یک ‪ Provider‬ارســال کنید‪ ،‬باید عبارت زیــر را در فایل ‪ sip.conf‬اضافه‬
‫نمایید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[myprovider‬‬
‫‪type = peer‬‬
‫>‪host = <HOST-IP‬‬
‫>‪defaultuser = <USERNAME‬‬
‫>‪secret = <SECRET‬‬
‫‪insecure = invite,port‬‬ ‫‪;very‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪190‬‬

‫‪dtmfmode = rfc2833‬‬
‫‪disallow = all‬‬
‫‪allow = ulaw,alaw‬‬

‫پس از انجام تغییرات در فایل ‪ ،sip.conf‬باید وارد محیط کامندالین استریســک شوید و ماژول ‪chan_sip.‬‬
‫‪ so‬را ‪ reload‬کنید‪:‬‬
‫‪CLI> sip reload‬‬

‫برای مشاهده وضعیت ارتباط ‪ SIP_Trunk‬در هر سرور‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫‪CLI> sip show peers‬‬

‫در این حالت وضعیت ترانک باید در حالت ‪ OK‬باشد‪.‬‬


‫پس از اینکه ارتباط ما با ‪ VoIP-Provider‬از طریق اطالعات داده شــده برقرار شــد‪ ،‬برای استفاده از این‬
‫‪ SIP Trunk‬میتوان برنامه را به این صورت نوشت‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => _1NXXXXXXX,1,Dial(SIP/${EXTEN}@myprovider‬‬

‫‪IAX2_TRUNK‬‬
‫پروتــکل )‪ IAX2 (Inter-Asterisk eXchange‬یکی دیگر از پروتکلهای شــبکههای ‪ VoIP‬اســت ‪ .‬این‬
‫پروتکل بیشــتر بهعنوان پروتکل ارتباطی میان سرورهای استریسک شناخته میشود‪ ،‬ولی در سطح محبوبیت‬
‫پایینتری نسبت به پروتکل ‪ SIP‬قرار دارد‪.‬‬
‫مهمترین مزیتی که پروتکل ‪ IAX2‬نسبت به پروتکل ‪ SIP‬دارد این است که در این پروتکل‪ ،‬جریانهای‬
‫ترافیکی ســیگنالینگ و مدیا از یک پورت مشــترک )پورت ‪ (4۵۶۹‬ارســال میشــوند‪ ،‬که این به نوبه خود‬
‫مشکل ‪ NAT‬در پروتکل ‪ SIP‬را برطرف میکند‪.‬‬
‫فرض کنید طبق شکل ‪ ۱۵-7‬یک ارتباط بین دو سرور ‪ A‬و‪ B‬ایجاد کرده باشیم‪ .‬تنظیمات مربوط به این‬
‫نوع ترانک در فایل ‪ iax2.conf‬در دو سرور به صورت زیر است‪:‬‬

‫شکل ‪15-7‬‬

‫در سمت ‪ serverA‬تنظیمات به صورت زیر می باشد‪:‬‬


‫‪;serverA‬‬
‫‪;iax2.conf‬‬
191 ‫ارتباط استریسک با سایر شبکه‌های ویپ‬

[serverB]
type = peer
host = 192.168.1.37
trunk =yes
username = serverA
secret = apples
context = incoming
disallow = all
allow = ulaw,alaw
qualify = yes

:‫ تنظیمات به صورت زیر می باشد‬serverB ‫در سمت‬


‫و‬
;serverB
;iax2.conf
[serverA]
type = peers
host = 192.168.1.36
trunk =yes
username = serverB
secret = apples
context = incoming
disallow = all
allow = ulaw,alaw
qualify = yes

:‫ کنید‬reload ‫ را‬chan_iax.so ‫ باید ماژول‬،‫بعد از انجام تغییرات باال در هر دو سرور‬


CLI> iax2 reload

:‫ دستور زیر را اجرا نمایید‬IAX_Trunk ‫برای مشاهده وضعیت ترانک‬


CLI> iax2 show peers

‫ شروع شده است را به سوی سرور‬7 ‫ بخواهیم شمارههایی که با پیش شماره‬A ‫حال فرض کنید در سرور‬
:‫ مربوطه اضافه کنید‬context ‫ در‬extensions.conf ‫ در این صورت برنامه زیر را در فایل‬،‫ ارسال کنیم‬B

;serverA
;extensions.conf
[LocalSets]
exten => _7XXX,1,Dial(IAX2/${EXTEN}@serverB)

:‫ باید به صورت زیر برنامه خود را بنویسیم‬B ‫یا در سرور‬


;serverB
;extensions.conf
[LocalSets]
exten => _7XXX,1,Dial(IAX2/${EXTEN}@serverA)
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪192‬‬

‫نتیجه‌گیری‬
‫در این فصل تالش بر این بود که با مفاهیم شــبکههای ارتباطی ویپ و مشــکالت آنها آشنایی بیشتری پیدا‬
‫کنیــم و اینکــه چگونــه بتوانیم آنها را به شــبکههای ‪ IP‬متصل کنیم‪ .‬در فصلهای بعــدی مباحث مرتبط با‬
‫شبکههای ویپ را ادامه خواهیم داد‪.‬‬
‫فصل هشتم‬

‫برنامه نویسی پیشرفته در‬


‫استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪194‬‬

‫برنامه‌نویسی پیشرفته در استریسک‬


‫در فصلهای پیشــین مختصری درباره برنامهنویســی مقدماتی در استریسک صحبت شد‪ .‬در این فصل روی‬
‫این موضوع بیشتر تمرکز میکنیم ‪.‬‬
‫همچون سایر زبانهای برنامهنویسی‪ ،‬ابتدا به اصول و قواعد زبان برنامهنویسی استریسک میپردازیم و با‬
‫دستورات و توابع آن آشنا میشویم‪ .‬توجه شود که این روش‪ ،‬تنها روش برنامهنویسی برای استریسک نیست‪.‬‬
‫استریسک ابزارهایی را فراهم آورده که با استفاده از آنها بتوان برنامهنویسی را با زبانهای سطح باال )از قبیل‬
‫‪ php, c#, python. Perl‬و غیره( انجام داد‪ .‬فهم عمیق دستورات و توابع این فصل‪ ،‬میتواند شما را در نوشتن‬
‫برنامههای قدرتمندتری نســبت به سایر زبانهای برنامهنویسی یاری رساند‪ .‬بنابراین به خواننده توصیه میشود‬
‫مطالب این فصل را با دقت بیشتری مطالعه نماید‪.‬‬

‫عبارات محاسباتی و منطقی در برنامه‌نویسی استریسک‬


‫در استریسک هم مانند سایر زبانهای برنامهنویسی‪ ،‬باید بتوان از عبارات محاسباتی و منطقی زبان برنامهنویسی‬
‫اســتفاده نمود‪ .‬یک عبارت‪ ،‬متشــکل از مجموعهای از متغیرها‪ ،‬عملگرها و مقادیر اســت که با ترکیبشدن‬
‫آنها با هم‪ ،‬یک عبارت ریاضی تشــکیل میشــود‪ .‬این عبارت میتواند در محاسبات ریاضی و منطقی برنامه‬
‫استفاده شود‪.‬‬
‫در استریسک همه عبارات بهصورت زیر تعریف میشوند‪:‬‬
‫]‪$[expression‬‬
‫‪195‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫اگر بخواهیم دو عدد ‪ ۲‬و ‪ ۳‬را با هم جمع کنیم‪ ،‬در این حالت باید عبارت محاســباتی ‪ ۲+۳‬را بهصورت زیر‬
‫در برنامه خود بنویسیم‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[logic‬‬
‫)(‪exten => 320,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)]‪same => n,NoOp(SUM=$[2+3‬‬
‫)(‪same => n,Hangup‬‬

‫همانطورکه مالحظه میکنید ما از عبارت ]‪ $[۲+۳‬در برنامه استفاده کردیم‪ .‬خروجی برنامه فوق در محیط‬
‫کامندالین استریسک بهصورت زیر است‪.‬‬
‫‪Executing [320@logic:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪Executing [320@logic:2] Answer("Console/dsp", "") in new stack‬‬
‫‪Executing [320@logic:3] NoOp("Console/dsp", "SUM=5") in new stack‬‬
‫‪Executing [320@logic:4] Hangup("Console/dsp", "") in new stack‬‬

‫توجه داشــته باشید که برای آزمون برنامههای این فصل‪ ،‬داشتن یک کاربر تعریفشده در استریسک الزامی‬
‫اســت و باید در کانتکســت مشــخصی برنامه را بنویســید‪ .‬پس از آن هر بار با شــمارهگیری آن اکستنشن‪،‬‬
‫میتوانید برنامه را تست کنید‪ .‬این روش اندکی دشوار مشکل است ولی یک روش سادهتر که در این فصل‬
‫از آن زیاد استفاده خواهیم کرد‪ ،‬استفاده از دستور زیر در محیط کامند الین استریسک است‪.‬‬
‫‪CLI> console dial 320@logic‬‬
‫‪-- Executing [320@logic:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [320@logic:2] Answer("Console/dsp", "") in new stack‬‬
‫>> ‪<< Console call has been answered‬‬
‫‪-- Executing [320@logic:3] NoOp("Console/dsp", "SUM=5") in new stack‬‬
‫‪-- Executing [320@logic:4] Hangup("Console/dsp", "") in new stack‬‬
‫›‪== Spawn extension (logic, 320, 4) exited non-zero on ‹Console/dsp‬‬
‫>> ‪<< Hangup on console‬‬
‫>‪CLI‬‬

‫با اســتفاده از این دستور‪ ،‬اکستنشــن ‪ ۳۲۰‬در کانتکست ]‪ [logic‬شمارهگیری و دستوراتش اجرا میشود‪ .‬این‬
‫روش یک ابزار ســاده و راحت برای تســت برنامهها و سناریوهای استریسک است‪ .‬البته در نظر داشته باشید‬
‫که تمامی سناریوها را نمیتوان در این روش تست کرد‪.‬‬
‫در استریســک میتوان از متغیرها در عبارات محاســباتی و منطقی اســتفاده نمود‪ .‬برای مثال فرض کنید‬
‫متغیری بهنام ‪ COUNT‬داریم که بهصورت زیر تعریف شده است‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[logic‬‬
‫)(‪exten => 321,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,Set(COUNT=3‬‬
‫)]‪same => n,Set(NEWCOUNT=$[${COUNT} + 1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪196‬‬

‫)}‪same => n,NoOp(NEWCOUNT=${NEWCOUNT‬‬


‫)}‪same => n,SayNumber(${NEWCOUNT‬‬

‫برای تست این برنامه‪ ،‬دستور زیر را اجرا کنید‪.‬‬


‫‪CLI> console dial 321@logic‬‬

‫خروجی دستور مشابه زیر خواهدبود‪:‬‬


‫>‪CLI‬‬
‫‪-- Executing [321@logic:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [321@logic:2] Answer("Console/dsp", "") in new stack‬‬
‫>> ‪<< Console call has been answered‬‬
‫‪-- Executing [321@logic:3] Set("Console/dsp", "COUNT=3") in new stack‬‬
‫‪-- Executing [321@logic:4] Set("Console/dsp", "NEWCOUNT=4") in new stack‬‬
‫‪-- Executing [321@logic:5] NoOp("Console/dsp", "NEWCOUNT=4") in new stack‬‬
‫‪-- Executing [321@logic:6] SayNumber("Console/dsp", "4") in new stack‬‬
‫)›‪-- <Console/dsp> Playing ‹digits/4.gsm› (language ‹en‬‬
‫›‪-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN‬‬
‫>> ‪<< Hangup on console‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در اولویت ســوم مقدار عددی ‪ ۳‬با دستور ‪ Set‬در متغیر ‪ COUNT‬ذخیره شد‬
‫متغیر ‪ NEWCOUNT‬ذخیره نمودیم‪.‬‬ ‫و در اولویــت بعدی مقدار ‪ COUNT‬یک واحد افزایــش یافت‪ ،‬در‬
‫در انتها با اجرای دستور ‪ ،SayNumber‬مقدار عددی ذخیره شده در متغیر ‪ NEWCOUNT‬پخش میشود‪.‬‬
‫البته با استفاده از گزارشهای ایجاد شده در کامند الین استریسک میتوانید صحت برنامه را بررسی کنید‪.‬‬
‫قبل از ادامه بحث اجازه بدهید مثال قبل را کمی با دقت بررســی کنیم‪ .‬همانطورکه مالحظه میکنید در‬
‫مثال قبل ما بخشهای متفاوتی داریم که عبارت اند از‪:‬‬
‫‪ (۱‬ابتدا با دستور ‪ Set‬متغیر ‪ COUNT‬را ایجاد میکنیم و مقدار اولیه میدهیم‪.‬‬
‫‪ (۲‬مقدار ذخیره شده در متغیر بهصورت}‪ ${COUNT‬قابل بازیابی است‪.‬‬
‫‪ (۳‬به کمک عبارت محاســباتی ]‪ $[${COUNT}+۱‬مقدار متغیر ارزیابی میشــود؛ لذا عبارت محاســباتی‬
‫بهصورت زیر مرحله به مرحله انجام میشود‪:‬‬
‫)]‪same => n,Set(NEWCOUNT =$[${ COUNT }+1‬‬
‫) ]‪same => n,Set(NEWCOUNT =$[3+1‬‬
‫)‪same => n,Set(NEWCOUNT =4‬‬

‫دســتور ‪ SayNumber‬عدد داده شــده را پخش میکند‪ .‬برای آشــنایی بیشتر با این دســتور‪ ،‬در کامند الین‬
‫استریسک دستور زیر را وارد کنید‪:‬‬
‫‪CLI> core show application SayNumber‬‬

‫در استریسک میتوان از سه نوع عبارت استفاده کرد‪:‬‬


‫‪ (۱‬عبارات منطقی‪ 1‬در برنامهنویسی استریسک؛‬
‫‪1- Boolean‬‬
‫‪197‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫‪ (۲‬عبارات محاسباتی‪ -‬ریاضی‪ 1‬در برنامهنویسی استریسک ؛‬


‫‪ (۳‬عبارات منظم‪ 2‬در برنامهنویسی استریسک ‪.‬‬
‫بحث در خصوص قوانین عبارات منظم خارج از حوصله کتاب می باشــد ولی در ادامه سایر موارد فوق‬
‫را به تفصیل شرح خواهیم داد‪.‬‬

‫عبارات منطقی در برنامه‌نویسی استریسک‬


‫عبارات منطقی در محاســبات به عملیاتی گفته میشــود که نتیجه آن بهصورت منطقی )‪ ۰‬یا ‪ (۱‬ارزیابی شود‪.‬‬
‫به عبارت دیگر‪ ،‬هر عملیاتی که نتیجه آن بهصورت »‪ «True‬یا »‪ «False‬ارزیابی شود‪ ،‬جزو عبارات منطقی‬
‫ارزیابی میگردد‪ .‬عملیات زیر از جمله مهمترین عملگرهای منطقیاند‪.‬‬

‫عملگر منطقی «‪ : »OR‬این عملگر به منزله «‪ »or‬یا «‪ »pipe‬در نظر گرفته می‌شــود‪ .‬چنانچه هریک از عبارت‌ها‬
‫«‪ »True‬باشــد‪ ،‬نتیجه کلی عبــارت «‪ »True‬در نظر گرفته می‌شــود‪ ،‬درغیراین‌صورت نتیجــه عبارت منطقی‬
‫«‪ »False‬خواهد بود‪ .‬در ریاضیات‪ ،‬این عملگر ترکیب فصلی نامیده می‌شود‪.‬‬
‫‪exper1 | exper2‬‬

‫جدول )‪ (۱-8‬حالتهای ترکیب فصلی را نمایش میدهد‪.‬‬

‫‪exper1‬‬ ‫‪exper2‬‬ ‫‪exper1| exper2‬‬


‫‪T‬‬ ‫‪F‬‬ ‫‪T‬‬
‫‪T‬‬ ‫‪T‬‬ ‫‪T‬‬
‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬
‫‪F‬‬ ‫‪T‬‬ ‫‪T‬‬
‫جدول ‪1-8‬‬
‫برای مثال برنامه زیر را در نظر بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[logic‬‬
‫)(‪exten => 322,1,NoOp‬‬
‫)‪same => n,Set(exper1=1‬‬
‫)‪same => n,Set(exper2=0‬‬
‫)]}‪same => n,NoOp($[${exper1}|${exper2‬‬

‫خروجی برنامه بهصورت زیر خواهد بود‪:‬‬


‫‪CLI> console dial 322@logic‬‬
‫‪-- Executing [322@logic:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [322@logic:2] Set("Console/dsp", "exper1=1") in new stack‬‬
‫‪-- Executing [322@logic:3] Set("Console/dsp", "exper2=0") in new stack‬‬

‫‪1- Mathametical‬‬
‫‪2- Regular Expression‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 198

-- Executing [322@logic:4] NoOp("Console/dsp", "1") in new stack


-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN›

.‫« در نظر گرفته میشود‬True» ‫همانطورکه مالحظه میکنید نتیجه عبارت منطقی‬

،‫» باشند‬True« ‫ اگر هر دو عبارت‬.‫» در نظر گرفته می‌شود‬and« ‫ این عملیات به منزله‬: »AND« ‫عملیات منطقی‬
‫ این عملگر ترکیب عطفی‬،‫ در ریاضیــات‬.‫» اســت‬False« ‫ درغیراین‌صورت نتیجه‬،‫» خواهد بود‬True« ‫نتیجــه‬
.‫نامیده می‌شود‬
exper1 & exper2

.‫ حالتهای ترکیب عطفی را نمایش میدهد‬۲-8 ‫جدول‬

exper1 exper2 exper1& exper2


T F F
T T T
F F F
F T F
2-8 ‫جدول‬
:‫برای مثال برنامه زیر را در نظر بگیرید‬
;extensions.conf
[logic]
exten => 323,1,NoOp()
same => n,Set(exper1=1)
same => n,Set(exper2=0)
same => n,NoOp($[${exper1} & ${exper2}])

:‫خروجی برنامه بهصورت زیر است‬


CLI> console dial 323@logic
-- Executing [323@logic:1] NoOp("Console/dsp", "") in new stack
-- Executing [323@logic:2] Set("Console/dsp", "exper1=1") in new stack
-- Executing [323@logic:3] Set("Console/dsp", "exper2=0") in new stack
-- Executing [323@logic:4] NoOp("Console/dsp", "0") in new stack
-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN›

.‫« در نظر گرفته میشود‬False» ‫ نتیجه عبارت منطقی‬،‫همانطورکه مالحظه میکنید‬

)‫ نامساوی‬،‫ مساوی‬،‫ کوچکتر‬،‫عملگرهای مقایسه‌ای (بزرگتر‬


‫« یا‬True» ‫ مساوی و نامساوی ( بهصورت‬،‫ کوچکتر‬،‫ نتیجه مقایسه دو عبارت را )از نظر بزرگتر‬،‫این عبارت‬
.‫« در نظر میگیرد‬False»
exper1 {=, >, <, <= ,>= ,!=} exper2
199 ‫برنامه‌نویسی پیشرفته در استریسک‬

:‫برای مثال برنامه زیر را در نظر بگیرید‬


;extensions.conf
[logic]
exten => 324,1,NoOp()
same => n,Set(exper1=1)
same => n,Set(exper2=0)
same => n,NoOp($[${exper1} > ${exper2}])
same => n,NoOp($[${exper1} >= ${exper2}])
same => n,NoOp($[${exper1} < ${exper2}])
same => n,NoOp($[${exper1} <= ${exper2}])
same => n,NoOp($[${exper1} = ${exper2}])
same => n,NoOp($[${exper1} != ${exper2}])

:‫خروجی برنامه بهصورت زیر است‬


CLI> console dial 324@logic
-- Executing [324@logic:1] NoOp("Console/dsp", "") in new stack
-- Executing [324@logic:2] Set("Console/dsp", "exper1=1") in new stack
-- Executing [324@logic:3] Set("Console/dsp", "exper2=0") in new stack
-- Executing [324@logic:4] NoOp("Console/dsp", "1") in new stack
-- Executing [324@logic:5] NoOp("Console/dsp", "1") in new stack
-- Executing [324@logic:6] NoOp("Console/dsp", "0") in new stack
-- Executing [324@logic:7] NoOp("Console/dsp", "0") in new stack
-- Executing [324@logic:8] NoOp("Console/dsp", "0") in new stack
-- Executing [324@logic:9] NoOp("Console/dsp", "1") in new stack
-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN›
CLI>

.‫« خواهد بود‬False» ‫« یا‬True» ‫ نتیجه عملگرهای مقایسهای بهصورت‬،‫همانطورکه مالحظه میکنید‬

‫) در استریسک‬mathemetical( ‫عملگرهای ریاضی‬


.‫ نتیجه عملیات ریاضی محاسبه شده و بهعنوان نتیجه درنظرگرفتهمیشود‬،‫در این نوع عملگرها‬
exper1 { +, -, *, /, %} exper2

:‫برای مثال برنامه زیر را در نظر بگیرید‬


;extensions.conf
[mathemetic]
exten => 325,1,NoOp()
same => n,Set(exper1=5)
same => n,Set(exper2=3)
same => n,NoOp($[${exper1} + ${exper2}])
same => n,NoOp($[${exper1} - ${exper2}])
same => n,NoOp($[${exper1} * ${exper2}])
same => n,NoOp($[${exper1} / ${exper2}])
same => n,NoOp($[${exper1} % ${exper2}])
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪200‬‬

‫خروجی برنامه بهصورت زیر است‪:‬‬


‫‪CLI> console dial 325@mathemetic‬‬
‫‪-- Executing [325@mathemetic:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [325@mathemetic:2] Set("Console/dsp", "exper1=5") in new stack‬‬
‫‪-- Executing [325@mathemetic:3] Set("Console/dsp", "exper2=3") in new stack‬‬
‫‪-- Executing [325@mathemetic:4] NoOp("Console/dsp", "8") in new stack‬‬
‫‪-- Executing [325@mathemetic:5] NoOp("Console/dsp", "2") in new stack‬‬
‫‪-- Executing [325@mathemetic:6] NoOp("Console/dsp", "15") in new stack‬‬
‫‪-- Executing [325@mathemetic:7] NoOp("Console/dsp", "1.66666666666666667") in new‬‬
‫‪stack‬‬
‫‪-- Executing [325@mathemetic:8] NoOp("Console/dsp", "2") in new stack‬‬
‫›‪-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در هر قسمت مقدار عبارت محاسباتی ارزیابی و نتیجه در خروجی نشان داده‬
‫میشود‪.‬‬

‫استفاده از دستورات‪ 1‬و توابع‪ 2‬در برنامه‌نویسی استریسک‬


‫در استریسک‪ ،‬یک کتابخانه بسیار قدرتمند از دستورات و توابع در دسترس است‪ .‬در نگاه اول ممکن است‬
‫این پرســش مطرح شــود که چه تفاوتی بین دستورات و توابع وجود دارد؟ در پاسخ باید گفت که مهمترین‬
‫تفاوت‪ ،‬نحوه استفاده از توابع در برنامهنویسی استریسک است که در ادامه با آنها آشنا خواهید شد‪.‬‬

‫استفاده از توابع در استریسک‬


‫اســتفاده از توابع‪ ،‬بســیار شبیه اســتفاده از متغیرها در استریســک اســت‪ .‬بهعنوان مثال اگر بخواهیم به تابعی‬
‫دسترسی داشته باشیم‪ ،‬میتوانیم بهصورتهای زیر آن را فراخوانی کنیم‪.‬‬

‫• فراخوانــی یک تابع برای مقداردهی به یــک پارامتر‪ :‬گاهی نیــاز داریم یک پارامتــر را درون یک تابع‬
‫مقدار‌دهی کنیم‪ .‬در این صورت به‌شکل زیر آن را مقدار‌دهی می‌کنیم‪ .‬نام پارامتر به‌صورت آرگومان ورودی‬
‫به تابع داده می‌شود‪.‬‬
‫)>‪exten => n,Set(function_name(argument)=<VALUE‬‬

‫• فراخوانی یک تابع برای خواندن مقدار یک پارامتر‪ :‬اگر بخواهیم به پارامتر یک تابع دسترســی داشته‌باشیم‬
‫و مقدار آن را بخوانیم‪ ،‬باید تابع را به‌صورت زیر فراخوانی کنیم‪.‬‬
‫)})‪exten => n,NoOp(VALUE=${function_name(argument‬‬

‫همانطورکه مالحظه میکنید استفاده از توابع در برنامهنویسی استریسک بسیار ساده و شبیه استفاده از متغیرها‬

‫‪1- Application‬‬
‫‪2- Function‬‬
‫‪201‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫در استریسک است‪ .‬در استریسک توابع زیادی وجود دارند که همگی بهصورت ماژول به استریسک اضافه‬
‫شــدهاند‪ .‬در فصل دوم )معماری استریســک( توضیح دادیم که این نوع ماژولها در استریســک بهصورت‬
‫>‪ func_<function_name‬تعریف شــدهاند‪ .‬برای مشــاهده انواع توابع در استریســک‪ ،‬دســتور زیر را در‬
‫کامندالین استریسک اجرا کنید‪.‬‬
‫‪CLI> core show functions‬‬

‫در خروجی دســتور باال‪ ،‬فهرســت همه توابع در استریســک نشان داده می‌شــود‪ .‬عالوه بر این با دستور زیر‬
‫می‌توانید همه ماژول‌هایی که مربوط به توابع در استریسک هستند را مشاهده کنید‪.‬‬
‫_‪CLI> module show like func‬‬

‫در این دســتور همه ماژولهای مربوط به توابع در استریسک را مشاهده میکنید‪ .‬میتوانید هر ماژولی را که‬
‫نیاز ندارید‪ ،‬به سادگی غیرفعال کنید‪ .‬در فصل دوم )معماری استریسک( درباره نحوه غیرفعالکردن ماژولها‬
‫توضیحات الزم آمده است‪.‬‬
‫بهتر است با چند مثال کاربردی‪ ،‬استفاده از توابع و دستورات در استریسک را شرح دهیم‪.‬‬
‫برای نمونه برنامه زیر را در نظر بگیرید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 123,1,NoOp‬‬
‫)‪same => n,Set(TEST=MESPIO‬‬
‫)‪same => n,Playback(demo-congrats‬‬
‫)})}‪same => n,NoOp(LET=${LEN(${TEST‬‬
‫)})}‪same => n,SayNumber(${LEN(${TEST‬‬

‫در این برنامه‪ ،‬ترکیبی از دستورات و توابع در کنار هم استفاده شدهاند‪ .‬نکته مهم تفاوت در چگونگی استفاده‬
‫اســت‪ .‬در این مثال دســتورات ‪ NoOp, Set,Playback, SayNumber‬همگی از نوع ‪Application‬‬ ‫از آنها‬
‫هســتند و تابع ‪ LEN‬از نوع ‪ Function‬اســت‪ .‬در این مثال‪ ،‬این تابع طول رشــتهای متغیر}‪ ${TEST‬را که ‪۶‬‬
‫است‪ ،‬برمیگرداند و سپس آن را پخش میکند‪ .‬خروجی برنامه باال بهصورت زیر است‪.‬‬

‫‪CLI> console dial 123@LocalSets‬‬


‫‪-- Executing [123@LocalSets:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [123@LocalSets:2] Set("Console/dsp", "TEST=MESPIO") in new stack‬‬
‫‪-- Executing [123@LocalSets:3] Playback("Console/dsp", "demo-congrats") in new stack‬‬
‫)›‪-- <Console/dsp> Playing ‹demo-congrats.gsm› (language ‹en‬‬
‫‪-- Executing [123@LocalSets:4] NoOp("Console/dsp", "LET=6") in new stack‬‬
‫‪-- Executing [123@LocalSets:5] SayNumber("Console/dsp", "6") in new stack‬‬
‫)›‪-- <Console/dsp> Playing ‹digits/6.gsm› (language ‹en‬‬
‫›‪-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN‬‬
‫>‪CLI‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪202‬‬

‫استفاده از تابع ‪ TIMEOUT‬در استریسک‬


‫همانطورکه از اســم این تابع نمایان اســت‪ ،‬با اســتفاده از آن‪ ،‬میتوان زمان را برای اجرای برخی دستورات‬
‫محدود کرد؛ بنابراین در استریسک معموالً از این تابع در شروع برنامهها استفاده میشود تا شرایط مورد نیاز‬
‫برای آن تنظیم شود‪.‬‬
‫این تابع شامل سه پارامتر است‪.‬‬
‫• ‪ :absolute‬با این پارامتر‪ ،‬میتوان حداکثر زمان فعال بودن یک کانال را مشــخص کرد‪ .‬مقدار صفر برای‬
‫این پارامتر به معنی غیرفعال بودن آن اســت‪ .‬برای مثال در برنامه زیر در ابتدای تماسهای ورودی‪ ،‬حداکثر‬
‫مــدت زمان فعال بودن کانال را پنج دقیقه تنظیم کردهایم )همانطورکه پیشتر هم شــرح داده شــد‪ ،‬از این‬
‫روش برای محدودکردن حداکثر طول زمان مکالمات اســتفاده نمیشود(‪ .‬درصورت سپری شدن این زمان‪،‬‬
‫استریسک کنترل تماس را به جانب اکستنشن ‪) T‬در صورتی که تعریف شده باشد(‪ ،‬منتقل میکند‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Set(TIMEOUT(absolute)=300‬‬

‫• ‪ : digits‬بــا ایــن پارامتر‪ ،‬حداکثر زمان مورد نیاز برای وارد کردن ‪ DTMF‬بین اعداد را مشــخص می‌کنیم‪.‬‬
‫برای مثال در برنامه زیر‪ ،‬زمان وارد کردن اعداد ‪ 5‬ثانیه تنظیم شده‌است‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Set(TIMEOUT(digits)=5‬‬

‫• ‪ : response‬زمانی که دستورات یک برنامه به ترتیب اجرا می‌شوند و به آخرین دستور می‌رسند‪ ،‬بالفاصله‬
‫بعد از اجرا شــدن آخرین دستور‪ ،‬تماس قطع می‌شود‪ .‬با این پارامتر می‌توان زمان بین اجرای آخرین دستور‬
‫‪1‬‬

‫و قطع شدن تماس را کنترل نمود‪ .‬برای مثال در برنامه زیر‪ ،‬این زمان روی حداکثر ‪ 3‬ثانیه تنظیم می‌شود‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Set(TIMEOUT(response)=3‬‬

‫نکتــه مهم در خصــوص پارامترهــای )‪ TIMEOUT(response‬و )‪ TIMEOUT(digits‬این اســت که این‬


‫پارامترها همراه با دستورات زیر در استریسک استفاده میشوند‪:‬‬
‫‪• DISA‬‬
‫‪• READ‬‬
‫‪• WaitExten‬‬

‫برای مثال برنامه زیر را در نظر بگیرید‪.‬‬

‫‪1- Auto Falling Through‬‬


203 ‫برنامه‌نویسی پیشرفته در استریسک‬

;extensions.conf
[LocalSets]
exten => s,1,Answer()
same => n,Set(TIMEOUT(response)=20)
same => n,BackGround(welcome)
same => n,WaitExten()
exten => 1,1,Saynumber(digits/1)
exten => 2,1,Saynumber(digits/2)
exten => 3,1,Saynumber(digits/3)
exten => t,1,NoOp(time out occure after 20 sec)

‫مدت زمان مجاز برای وارد‬TIMEOUT(response) ‫ با تابع‬،‫همانطورکه مالحظه میکنید در ابتدای برنامه‬
‫ کنترل برنامه به اکستنشــن‬،‫ ثانیه عددی وارد نشــود‬۲۰ ‫ ثانیه تنظیم کردهایم و چنانچه بعد از‬۲۰ ‫کردن عدد را‬
.‫ خروجی برنامه باال بهصورت زیر است‬.‫ انتقال مییابد‬t
CLI> console dial s@LocalSets
-- Executing [s@LocalSets:1] Answer("Console/dsp", "") in new stack
-- Executing [s@LocalSets:2] Set("Console/dsp", "TIMEOUT(response)=20") in new stack
-- Response timeout set to 20.000
-- Executing [s@LocalSets:3] BackGround("Console/dsp", "welcome") in new stack
-- Executing [s@LocalSets:4] WaitExten("Console/dsp", "") in new stack
-- Timeout on Console/dsp, going to ‹t›
-- Executing [t@LocalSets:1] NoOp("Console/dsp", "time out occure after 20 sec") in new
stack
-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN›
<< Hangup on console >>
CLI>

‫ نکته مهم در این‬.‫در استریسک این قابلیت وجود دارد که بتوانیم توابع را بهصورت تو در تو فراخوانی کنیم‬
‫ در فصل‬،‫ ازآنجاکه تعداد توابع در استریسک زیاد است‬.‫ رعایت تعداد پرانتزها و براکتها اســت‬،‫شــرایط‬
‫بیستم )آشنایی با دستورات و توابع مهم و پرکاربرد استریسک( با مهمترین دستورات و توابع استریسک آشنا‬
.‫خواهید شد‬

‫استفاده از دستورات و توابع شرطی در استریسک‬


‫ دســتورات شرطی در‬.‫در این بخش قصد داریم دســتورات و توابع شــرطی را در استریســک معرفی کنیم‬
:‫استریسک عبارتند از‬
GotoIf ‫ • دستور‬
GotoIfTime ‫ • دستور‬
GosubIf ‫ • دستور‬
MacroIf ‫ • دستور‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪204‬‬

‫و توابع شرطی در استریسک عبارتند از ‪:‬‬


‫ • تابع ‪IF‬‬

‫دستور ‪GotoIf‬‬
‫با این دستور میتوان پس از بررسی شرطهایی‪ ،‬کنترل اجرای برنامه را به قسمتهای دیگری از برنامه انتقال‬
‫داد‪ .‬نتیجه بررسی شرطها بهصورت منطقی »‪ «True‬یا »‪ «False‬در نظر گرفته میشود‪.‬‬
‫فرمت استفاده از دستور ‪ GotoIf‬بهصورت زیر است ‪:‬‬
‫)‪GotoIf(expression?destination1:destination2‬‬

‫در این صورت اگر مقدار عبارت )‪ (experssion‬داخل دســتور‪ «True» ،‬محاسبه شود‪ ،‬کنترل برنامه به ‪des-‬‬
‫‪ tination1‬منتقل میشــود و اگر مقدار عبارت‪ «False» ،‬محاسبه شود‪ ،‬کنترل برنامه به ‪ destination۲‬منتقل‬
‫میگردد‪.‬‬
‫نکته مهم در ارزیابی ‪ expression‬این اســت که اگر »رشــته خالی« یا »‪ «۰‬باشد ‪ ،‬به منزله »‪ «False‬در‬
‫نظر گرفته میشود‪ .‬برای مثال برنامه زیر را در نظر بگیرید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 124,1,NoOp‬‬
‫)‪same => n,Set(TEST=1‬‬
‫)‪same => n,GotoIf($[${TEST} = 1]?weasels:iguanas‬‬
‫)‪same => n(weasels),Playback(announce-one‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(iguanas),Playback(announce-two‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال‪ ،‬ابتدا متغیر ‪ TEST‬را تعریف میکنیم‪ .‬سپس در خط بعدی‪ ،‬مقدار متغیر‪ TEST‬را با مقدار عددی‬
‫‪ ۱‬مقایســه میکنیم‪ .‬در این حالت چون مقدار متغیر ‪ TEST‬برابر با ‪ ۱‬اســت‪ ،‬مقدار عبارت درســت محاسبه‬
‫میشود و کنترل برنامه به ‪ weasels‬منتقل میشود و دستورات آنجا اجرا میگردد‪.‬‬
‫خروجی برنامه باال بهصورت زیر است‪:‬‬
‫‪CLI> console dial 124@LocalSets‬‬
‫‪-- Executing [124@LocalSets:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [124@LocalSets:2] Set("Console/dsp", "TEST=1") in new stack‬‬
‫‪-- Executing [124@LocalSets:3] GotoIf("Console/dsp", "1?weasels:iguanas") in new stack‬‬
‫)‪-- Goto (LocalSets,124,4‬‬
‫‪-- Executing [124@LocalSets:4] Playback("Console/dsp", "announce-one") in new stack‬‬
‫‪-- Executing [124@LocalSets:5] Hangup("Console/dsp", "") in new stack‬‬
‫›‪== Spawn extension (LocalSets, 124, 5) exited non-zero on ‹Console/dsp‬‬
‫>‪CLI‬‬

‫اینجا از برچسب »‪ «weasele‬برای انتقال کنترل اجرای برنامه به محلی دیگر استفاده کردیم‪ .‬دستور فوق‬
‫‪205‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫معادل دستور زیر می باشد‪:‬‬


‫)‪Goto (LocalSets,124,4‬‬

‫در استریسک میتوان کنترل اجرای برنامهها را به صورت های زیر انتقال داد‪:‬‬

‫‪ )1‬پرش به اجرای یک اولویت خاص از طریق برچسب اولویت‪ :‬کنترل اجرای برنامه به برچسب اولویت مورد‬
‫نظر از کانتکست و اکستنشن جاری انتقال می‌یابد و دستورات اجرا می‌شوند‪.‬‬

‫‪ )2‬پرش به یک اکستنشــن خاص با اولویت مشــخص‪ :‬کنترل برنامه به یک اکستنشن دیگر انتقال می‌یابد و از‬
‫اولویت مشخص‌شده‪ ،‬اجرای دستورات را آغاز می‌کند‪.‬‬

‫‪ )3‬پرش به یک کانتکست‪ ،‬اکستنشــن خاص با اولویت مشخص‪ :‬دراین حالت می‌توان حتی کنترل برنامه را به‬
‫یک کانتکست دیگر با اکستنشن و اولویت خاص‪ ،‬منتقل و دستورات آنجا را اجرا کنیم‪.‬‬
‫سؤال( چرا در مثال باال دو بار از دستور ‪ Hangup‬استفاده شدهاست؟ پاسخ‪ :‬چون دستورات بهصورت پشت‬
‫ســر هم اجرا میشوند‪ ،‬بعد از انتقال اجرای برنامه به برچسب ‪ weasles‬و اجرای دستورات آن قسمت‪ ،‬نباید‬
‫دســتورات قســمت دوم شرط اجرا شوند‪ .‬لذا بعد از اتمام دستورات مشــخص شده‪ ،‬باید از دستور ‪Hangup‬‬
‫استفاده کنیم‪.‬‬
‫بیایید فرض کنیم دســتور ‪ Hangup‬را از برنامه حذف کردهایم‪ .‬بر این اســاس خروجی برنامه بهصورت‬
‫زیر خواهد بود‪.‬‬
‫‪CLI> console dial 124@LocalSets‬‬
‫‪-- Executing [124@LocalSets:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [124@LocalSets:2] Set("Console/dsp", "TEST=1") in new stack‬‬
‫‪-- Executing [124@LocalSets:3] GotoIf("Console/dsp", "1?weasels:iguanas") in new stack‬‬
‫)‪-- Goto (LocalSets,124,4‬‬
‫‪-- Executing [124@LocalSets:4] Playback("Console/dsp", "announce-one") in new stack‬‬
‫‪-- Executing [124@LocalSets:5] Playback("Console/dsp", "announce-two") in new stack‬‬
‫›‪-- Auto fallthrough, channel ‹Console/dsp› status is ‹UNKNOWN‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید با حذف دســتور ‪ Hangup‬از برنامه‪ ،‬هر دو دســتور ‪ Playback‬اجرا میشوند‪.‬‬
‫ایــن امر در برنامههــا موجب بهوجود آمدن خطاهای منطقی میشــود؛ بنابراین‪ ،‬به ایــن نکات در خصوص‬
‫استفاده از توابع شرطی دقت داشته باشید‪.‬‬
‫روش برنامهنویســی با سبک مثال قبلی‪ ،‬در استریسک زیاد مرسوم نیست‪ ،‬چون ممکن است بهدلیل عدم‬
‫اســتفاده صحیح از دســتور ‪ ،Hangup‬مشکالتی در برنامه به وجود آید؛ به همین دلیل مثال باال را به شیوه ای‬
‫صحیح دوباره مینویسیم‪ .‬این روش برنامهنویسی از نظر نوع نگارشی‪ ،‬بهتر و راحتتر است‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪206‬‬

‫)(‪exten => 125,1,NoOp‬‬


‫)‪same => n,Set(TEST=1‬‬
‫)‪same => n,GotoIf($[${TEST} = 1]?weasels,1:iguanas,1‬‬

‫)‪exten => weasels,1,Playback(announce-one‬‬


‫)(‪same => n,Hangup‬‬

‫)‪exten => iguanas,1,Playback(announce-two‬‬


‫)(‪same => n,Hangup‬‬

‫همانطورکه مالحظه میکنید به جای پرش روی برچســبها و اولویتها‪ ،‬پرش به یک اکستنشــن دیگر با‬
‫اولویت مشخص صورت میگیرد‪.‬‬
‫بهتر اســت از بحث توابع شــرطی دور نشــویم و به یک مثال جالب دیگر بپردازیم‪ .‬برنامه زیر را در نظر‬
‫بگیرید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 126,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,Set(COUNT=10‬‬
‫)‪same => n(start),GotoIf($[${COUNT} > 0]?:goodbye‬‬
‫)}‪same => n,SayNumber(${COUNT‬‬
‫)]‪same => n,Set(COUNT=$[${COUNT} - 1‬‬
‫)‪same => n,Goto(start‬‬
‫)(‪same => n(goodbye),Hangup‬‬

‫آیا میتوانید حدس بزنید برنامه باال چه کاری را انجام میدهد؟‬


‫در این برنامه ابتدا متغیر ‪ COUNT‬را روی ‪ ۱۰‬تعریف میکنیم‪ .‬در هر بار اجرای برنامه‪ ،‬مقدار آن را یک‬
‫واحد کم میکنیم‪ .‬نکته مهم اینجاست که اگر دستور شرطی‪ «True» ،‬باشد‪ ،‬فیلد ‪ destination1‬خالی است‬
‫و فقط ‪ destination2‬به برچســب ‪ goodbye‬منتقل میشود‪ .‬در این صورت اگر مقدار شرط‪ «True» ،‬باشد‪،‬‬
‫چون فیلد خالی است‪ ،‬اولویت اجرا‪ ،‬خط بعدی خواهدبود و دستور ‪ SayNumber‬اجرا میشود‪.‬‬

‫دستور ‪GotoIfTime‬‬
‫گاهی نیاز داریم براساس زمان سیستم‪ ،‬دستورات متفاوتی را اجرا کنیم‪ .‬برای مثال شرکتی را در نظر بگیرید‬
‫که میخواهد درساعات اداری‪ ،‬پیام ‪ IVR‬خود را اجرا کند و در ساعتهای غیر اداری‪ ،‬پیام دیگری را پخش‬
‫کند‪ .‬در این شرایط دستور ‪ GotoIftime‬مفید است‪.‬‬
‫فرمت استفاده از دستور بهصورت زیر است‪:‬‬
‫)‪GotoIfTime(times,days_of_week,days_of_month,months?label‬‬

‫در این حالت اگر زمان و تاریخ سیســتم با آنچه که در دســتور آمده اســت‪ ،‬مطابقت داشته باشد‪ ،‬کنترل‬
‫‪207‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫اجرای برنامه به ‪ label‬تعیینشده منتقل میشود‪ .‬در ادامه به معرفی بیشتر دستور ‪ GotoIfTime‬میپردازیم‪.‬‬

‫‪ : Time‬در این پارامتر‪ ،‬بازه زمانی مورد نظر خود را براساس فرمت ‪ 24‬ساعته‪ ،‬مشخص می‌کنیم‪ .‬به‌عنوان مثال‬
‫برای مشخص کردن زمان بین ‪ 9‬صبح تا ‪ 5‬عصر به‌صورت زیر نمایش می‌دهیم‪.‬‬
‫‪09:00-17:00‬‬

‫‪ : Day_of_weak‬لیست روز‌های (ایام) هفته را مشخص می‌کند‪ .‬به‌عنوان مثال چنانچه بخواهیم ایام هفته را از‬
‫شنبه تا پنج شنبه مشخص کنیم‪ ،‬باید به‌صورت زیر نمایش دهیم‪:‬‬
‫‪sat-thu‬‬

‫در ایــن حالت همه روزهای هفته را مشــخص می‌کنیــم‪ .‬اگر بخواهیم فقط روز‌های خاصی را (مثال ‌شــنبه و‬
‫پنجشنبه) را مشخص کنیم‪ ،‬به‌صورت زیر تعریف می‌کنیم ‪:‬‬
‫‪sat&thu‬‬

‫همچنیــن می‌تــوان ایام هفته را به‌صورت ترکیبی مشــخص نمود‪ .‬مثال فرض کنید بخواهیم روزهای شــنبه تا‬
‫دوشنبه و چهارشنبه و جمعه را تعریف کنیم‪ ،‬بنابراین داریم ‪:‬‬
‫‪sat-mon&wed&fri‬‬

‫‪ : Day_of_month‬لیست روزهای ماه را بین ‪ 1‬تا ‪ 31‬مشخص می‌کند‪ .‬به‌عنوان مثال برای مشخص کردن بازه‬
‫زمانی هفتم تا دوازدهم هر ماه‪ ،‬به‌صورت زیر تعریف می‌کنیم‪:‬‬
‫‪7-12‬‬

‫به‌عنوان مثالی دیگر برای مشخص کردن روزهای پانزدهم و سی‌ام هرماه داریم‪:‬‬
‫‪15&30‬‬

‫همچنین می‌توانیم به‌صورت ترکیبی روزهای ماه را مشخص کنیم‪:‬‬


‫‪7-12&15&20-25‬‬

‫در این مثال روزهای بین هفتم تا دوازدهم و پانزدهم و بیستم تا بیست و پنجم هر ماه در نظر گرفته می‌شود‪.‬‬
‫‪ : Month‬لیست ماه‌های سال را مشخص می‌کند‪ .‬در اینجا باید اسم ماه‌های سال را به میالدی مشخص کنیم‪.‬‬
‫به‌عنوان مثال‪:‬‬
‫‪jan-apr‬‬

‫همچنین می‌توان اسم ماه‌ها را به‌صورت زیر مشخص کرد‪:‬‬


‫‪jan&mar&jun‬‬

‫و می‌توان به‌صورت ترکیبی لیست ماه را مشخص کرد‪:‬‬


‫‪jan-apr&jun&oct-dec‬‬

‫می‌توان برای هر بخش و به ازای هر پارامتر‪ ،‬از مقادیر مشخص شده (عالمت * ) استفاده کنیم‪ .‬در این صورت‬
‫تمام حالت‌های ممکن برای آن بخش را شامل خواهد شد‪.‬‬
‫‪ : Label‬پارامتر ‪ label‬بســیار شــبیه به ‪ destination‬در دســتور ‪ Goto‬یا ‪ GotoIf‬و دستورات مشابه است که‬
‫پیش‌تر توضیح داده شد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪208‬‬

‫اکنون چنانچه بخواهیم ســاعتهای کاری شــرکتی را در قالب این دســتور قرار دهیم )مثال از ساعت ‪۹‬‬
‫صبح تا ‪ ۱8‬عصر‪ ،‬از شنبه تا پنج شنبه(‪ ،‬در تمام ایام ماه و ماههای سال عبارت است از‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,GotoIfTime(09:00-17:59,sat-thu,*,*?open,s,1‬‬

‫همانطورکــه مالحظــه میکنید از عالمت » * « در دو پارامتر آخر )که به منزله همه روزهای ماه و همه‬
‫ماههای سال است( استفاده کردیم ‪ .‬اگر شرط فوق صادق نباشد‪ ،‬اجرای برنامه به خط بعدی میرود و اجرای‬
‫ادامه دستورات انجام خواهدشد‪.‬‬
‫بهعنوان مثالی دیگر فرض کنید شــرکتی شــرایط زیر را برای ســاعت کاری خود داشــته باشد و از شما‬
‫بخواهد که برنامهی آن را بنویسید‪:‬‬
‫مسئله‪ :‬ساعات کاری شرکت از ساعت ‪ 7:30‬دقیقه تا ‪ 16‬عصر است‪ .‬روز‌های پنج شنبه و جمعه شرکت تعطیل‬
‫است‪.‬‬
‫ساعت ‪ 12:30‬تا ‪ 13:30‬زمان استراحت (نماز و نهار) است‪.‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,GotoIfTime(12:30-13:30,sat-wed,*,*?break-time,s,1‬‬
‫)‪same => n, GotoIfTime(7:30-16:00,sat-wed,*,*?open,s,1‬‬
‫)‪same => n,Goto(close,s,1‬‬

‫همانطورکه مالحظه میکنید ابتدا زمانهای ‪ break‬مشخصشــد‪ ،‬بعد زمانهای باز بودن‪ .‬اگر اجرای برنامه‬
‫با هیچ یک از دســتورات منطبق نشــود‪ ،‬یعنی شرکت خارج از بازه زمانی کاری است و ادامه دستورات اجرا‬
‫میشود‪.‬‬
‫اگر در برنامه قبل‪ ،‬ابتدا زمانهای باز بودن و ســپس زمان ‪ break‬را بررســی میکردیم‪ ،‬چه اشــکاالتی‬
‫ممکن بود بهوجود آید؟ در پاسخ برنامه زیر را در نظر بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n, GotoIfTime(7:30-16:00,sat-wed,*,*?open,s,1‬‬
‫)‪same => n,GotoIfTime(12:30-13:30,sat-wed,*,*?break-time,s,1‬‬
‫)‪same => n,Goto(close,s,1‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬در این حالت برای همیشــه شــرط اول درســت اســت و هیچگاه زمان‬
‫‪ break‬اجرا نمیشــود‪ .‬بنابراین در این برنامهها دقت داشــته باشید که اولویت بر اساس آن ساعتهایی است‬
‫که محدودهی کمتری دارند‪ .‬در ادامه چند مســئله طرح میشــود و از خواننده انتظــار میرود‪ ،‬بتواند برنامه‬
‫زمانبندی آنها را بنویسد‪.‬‬
‫‪209‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫مســئله ‪ )1‬ســاعت کاری صبح از ســاعت ‪ 8‬تا ‪ 13‬و بعد ازظهرها‪ ،‬روز‌های فرد از ساعت ‪ 17‬تا ‪ 20‬و روزهای‬
‫زوج از ساعت ‪ 17‬تا ‪ 22‬است‪.‬‬

‫مسئله ‪ )2‬شرکتی در روزهای زوج هر ماه‪ ،‬از ساعت ‪ 7:30‬تا ‪ 16‬فعال است‪ .‬اگر این روزها با پنج‌شنبه برخورد‬
‫کند‪ ،‬شــرکت تا ســاعت ‪ 14‬فعال اســت‪ .‬در هر روز از ساعت ‪ 13‬الی ‪ 13:30‬برای اســتراحت در نظر گرفته‬
‫می‌شود‪.‬‬

‫مسئله ‪ )3‬شــرکتی در روزهای پایانی هفته (چهارشــنبه و پنج‌شــنبه) از تخفیف ویژه‌ای برخوردار است‪ .‬این‬
‫تخفیف در آخرین چهارشنبه و پنج‌شنبه هر فصل تا ‪ %50‬افزایش می‌یابد‪.‬‬

‫بررسی خطاهای منطقی در برنامه‌نویسی استریسک‬


‫اســتفاده از دســتورات شرطی در زمان نوشــتن برنامه‪ ،‬گاهی با خطا همراه اســت که در ادامه به این خطاها‬
‫میپردازیم‪.‬‬
‫برای مثال در هنگام فرآیند عملیات محاســباتی– منطقی‪ ،‬یکی از طرفین نمیتواند ‪ null‬باشد‪ .‬مثالهای‬
‫زیر را ببینید‪.‬‬
‫]‪$[ = 0‬‬
‫] = }‪$[${foo‬‬
‫]‪$[ > 0‬‬
‫] ‪$[1+‬‬

‫در چنین شرایطی در کامندالین استریسک با چنین خطایی مواجه شویم‪:‬‬


‫‪WARNING[1820][C-00000000]: ast_expr2.fl:470 ast_yyerror: ast_yyerror(): syntax error:‬‬
‫‪syntax error, unexpected ‹>›, expecting $end; Input:‬‬

‫همچنین مثال زیر را ببینید‪:‬‬


‫‪;extensions.conf‬‬
‫)(‪exten => 128,1,NoOp‬‬
‫)‪same => n,Set(TEST_1=foo‬‬
‫)'‪same => n,Set(TEST_2='foo‬‬
‫)]}‪same => n,NoOp($[${TEST_1} = ${TEST_2‬‬

‫به نظر شما خروجی برنامه چگونه ارزیابی میشود؟ آیا مقدار متغیر ‪ TEST_1‬با مقدار متغیر ‪ TEST_2‬برابر‬
‫است؟‬
‫قبل از پاسخ به این پرسش‪ ،‬ذکر این نکته الزم است که در استریسک نیازی نیست برای تعریف رشتهها‬
‫از عالمتهای ' یا " اســتفاده کنید‪ ،‬ولی برای همه مقایســههای شــرطی بهتر است از این عالمتها استفاده‬
‫کنیــد‪ .‬در ایــن مثال‪ ،‬مقدار عبارت مورد نظر‪ False ،‬در نظر گرفته میشــود و مقدار دو متغیر نیز با هم برابر‬
‫نخواهند بود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪210‬‬

‫بنابراین‪ ،‬مثال باال را به روشی صحیح بهصورت زیر مینویسیم‪.‬‬


‫‪;extensions.conf‬‬
‫)(‪exten => 128,1,NoOp‬‬
‫)‪same => n,Set(TEST_1=foo‬‬
‫)‪same => n,Set(TEST_2=foo‬‬
‫)']}‪same => n,NoOp($['${TEST_1}' = '${TEST_2‬‬

‫در این صورت مقدار عبارت باال‪ «True» ،‬ارزیابی میشود‪.‬‬


‫اگر در استریسک متغیری تعریف نشده باشد‪ ،‬مقدار آن تهی یا ‪ null‬درنظر گرفته میشود و باید آن را‬
‫بهصورت زیر در شرطها بکار برید‪.‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 129,1,NoOp‬‬
‫)]'' = '}‪same => n,NoOp($['${TEST‬‬

‫در این مثال‪ ،‬چون ما متغیر ‪ TEST‬را تعریف نکردیم‪ ،‬مقدار آن‪ Null ،‬در نظر گرفته میشود؛ ولی در مقایسه‬
‫نمیتوانیم از عبارت ‪ Null‬استفاده کنیم‪ ،‬بلکه از عبارت خالی استفاده میکنیم‪.‬‬
‫پیشتر توضیح دادیم که بهتر است در همه عبارتهای شرطی از عالمتهای ' یا " استفاده کرد‪ .‬اکنون‬
‫این پرسش مطرح میشود که اگر بخواهیم عملیات مقایسهای بین اعداد را در شرطی بررسی کنیم‪ ،‬چه باید‬
‫کرد؟ در پاسخ به این سؤال‪ ،‬مثال زیر را ببینید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 130,1,NoOp‬‬
‫)‪same => n,Set(TEST=1‬‬
‫)‪same => n,GotoIf($[ '${TEST}' = '1' ] ? error_handing‬‬
‫)(‪same => n(error_handing) ,NoOp‬‬

‫در این مثال‪ ،‬نوع نگارش کام ً‬


‫ال رعایت شدهاست‪ .‬اکنون مثال را بهصورت زیر تغییر میدهیم‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 130,1,NoOp‬‬
‫)‪same => n,Set(TEST=1‬‬
‫)‪same => n,GotoIf($[ 0${TEST} < 10 ] ? error_handing‬‬
‫)(‪same => n(error_handing) ,NoOp‬‬

‫در این مثال از عملیات مقایســهای اســتفاده شده است‪ .‬مســأله مهم این است که مقایسه باید برای اعداد‬
‫انجــام شــود؛ بنابراین‪ ،‬باید از عدد صفر پیش از نام متغیر اســتفاده کنید‪ .‬در ایــن حالت مقدار آن بهصورت‬
‫عددی در نظر گرفته میشود و پس از آن عملیات شرطی اجرا میشود‪.‬‬
‫آخرین مثال از این بخش را بررســی میکنیم‪ .‬فرض کنید میخواهیم بر اســاس کالرآیدی‪ ،‬شــمارهای‬
‫را بــالک کنیم‪ .‬اینجا گرفتن شــماره از طریق تابع )‪ CALLERID(num‬اهمیــت دارد‪ .‬برنامه زیر را در نظر‬
‫بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 131,1,NoOp‬‬
‫‪211‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫)‪same => n,GotoIf($[${CALLERID(num)} = 31770000]?block‬‬


‫)‪same => n,Dial(DAHDI/4‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(block),Playback(abandon-all-hope‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال‪ ،‬ابتدا کالرآیدی بررسی میشود ؛ چنانچه شرط ‪ True‬باشد به دستور با برچسب ‪ block‬رفته‬
‫و دستورات آن بخش اجرا میشوند‪.‬‬
‫پیش از ادامه بحث‪ ،‬بهتر است درمورد تابع ‪ CALLERID‬توضیح دهیم‪ .‬مهمترین آرگومانهای این تابع‬
‫بهصورت زیر است‪:‬‬
‫• ‪ : num‬شماره تماس گیرنده را برمی‌گرداند‪.‬‬
‫• ‪ : name‬اســم تماس گیرنده را بر می‌گرداند (فقط در کاربران ‪ SIP‬قابل اســتفاده اســت‪ .‬در خصوص‬
‫شبکه‌های مخابراتی ‪ PSTN‬همان ‪ num‬است‪).‬‬
‫• ‪ : all‬ترکیب ‪ num‬و ‪ name‬را برمی‌گرداند ‪.‬‬
‫برای مثال فرض کنید برای کاربری‪ ،‬فیلد کالرآیدی را بهصورت زیر در فایل ‪ sip.conf‬تعریف کرده باشیم‪:‬‬
‫‪;sip.conf‬‬
‫]‪[Phone_1‬‬
‫>‪Callerid = Phone_1<1000‬‬

‫اکنون چنانچه برنامه زیر را داشته باشیم‪.‬‬


‫‪;extensions.conf‬‬
‫ )})‪exten => 132,1,NoOp(${CALLERID(num‬‬
‫))‪same => n,NoOp(CALLERID(name‬‬
‫ ))‪same => n,NoOp(CALLERID(all‬‬

‫در این صورت خروجی برنامه باال بهصورت زیر است‪.‬‬


‫>‪CLI‬‬
‫‪-- Executing [132@LocalSets:1] NoOp("SIP/1000-000000a6", "1000") in new stack‬‬
‫‪-- Executing [132@LocalSets:2] NoOp("SIP/1000-000000a6", "Phone_1") in new stack‬‬
‫‪-- Executing [132@LocalSets:3] NoOp("SIP/1000-000000a6", "Phone_1<1000>") in new stack‬‬
‫›‪-- Auto fallthrough, channel ‹ SIP/1000-000000a6› status is ‹UNKNOWN‬‬
‫>‪CLI‬‬

‫این نکته اهمیت دارد که عملیات را باید با تلفنی که کاربر ‪ Phone_ 1‬روی آن رجیسترشــده اســت‪ ،‬تســت‬
‫کنیم‪.‬‬

‫استفاده از ماکروها‪ 1‬در استریسک‬


‫یکی از ابزارهای قدرتمند در برنامهنویسی استریسک‪ ،‬استفاده از ماکروهاست‪ .‬ماکروها باعث میشوند که ما‬
‫‪1- Macro‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪212‬‬

‫از تکرار کدها در برنامه جلوگیری و کدهای خواناتر و منظمتری ایجاد کنیم‪ .‬البته در استریسک نسخه ‪ ۱۱‬به‬
‫بعد‪ ،‬استفاده از ماکروها کمتر توصیه شده است و بهجای آن دستور ‪ GoSub‬معرفی شده است‪.‬‬
‫یکی از مشــکالت اساسی اســتفاده از ماکروها‪ ،‬بکارگیری ماکروها بهصورت تو در تو است که ممکن‬
‫اســت به خطای »‪ «stack over flow problem‬منتهی شــود؛ هرچند که میتوان تا پنج سطح از ماکروهای‬
‫تو در تو داشت‪.‬‬
‫به منظور آشنایی بیشتر با ماکروها‪ ،‬مثال زیر را ببینید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 140,1,NoOp‬‬
‫)‪same => n,Set(JOHN=SIP/Phone_1‬‬
‫)‪same => n,Dial(${JOHN},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫)‪same => n(unavail),Playback(unavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال‪ ،‬ابتدا ســعی میشــود که با ‪ JOHN‬تماس گرفتهشــود‪ .‬چنانچه پس از ‪ ۱۰‬ثانیه پاسخی دریافت‬
‫نشود‪ ،‬بسته به اینکه وضعیت »‪ «busy‬یا »‪ «unavail‬باشد‪ ،‬پیام مشخصی پخش و به دنبال آن تماس نیز قطع‬
‫میگردد‪ .‬متغیر‪ ، DIALSTATUS‬وضعیت تماس را در دستور ‪ Dial‬مشخص میکند‪.‬‬
‫البته این برنامه برای یک کاربر )داخلی( تعریف شده است‪ .‬چنانچه بخواهیم برنامه را برای هزاران کاربر‬
‫داشــته باشــیم‪ ،‬باید انبوهی از کدهای تکراری را بهازای هر کاربر داشته باشیم که مشکالت زیادی را برای‬
‫ما به بار میآورد‪ .‬اما برای جلوگیری از تکرار کدها‪ ،‬میتوان درون یک ماکرو قطعه برنامهای را نوشــت و‬
‫سپس برای هر کاربر آن را فراخوانی نمود‪ .‬بدین وسیله از تکرار کدهای اضافی در برنامه جلوگیری میشود‪.‬‬

‫تعریف ماکرو‬
‫برای تعریف یک ماکرو ‪ ،‬ابتدا باید یک نام برای آن مشخص کنیم‪:‬‬
‫]‪[macro-name‬‬

‫عبارت »‪ «macro-‬بهعنوان پیشوند‪ ۱‬در ابتدای نام هر ماکرو ضروری است‪.‬‬


‫ازآنجاکه کدهای داخل ماکرو با فراخوانی ماکرو اجرا میشــوند‪ ،‬بهتر اســت از اکستنشــن ‪ s‬در زمان‬
‫بالمانع است(‪.‬‬ ‫تعریف ماکرو استفاده کنید )هرچند استفاده از هر اکستنشن دیگری در تعریف ماکرو‬
‫اکنون مثال قبل را در قالب یک ماکرو پیادهسازی میکنیم‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[macro-dial‬‬

‫‪1- prefix‬‬
‫‪213‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫)(‪exten => s,1,NoOp‬‬


‫)‪same => n,Set(JOHN=SIP/Phone_1‬‬
‫)‪same => n,Dial(${JOHN},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫)‪same => n(unavail),Playback(unavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫البتــه این تعریف از ماکرو کامل نیســت و باید به گونه ای تغییــر پیدا کند که همه کاربران بتوانند از آن‬
‫استفاده کنند؛ ولی قبل از آن باید نکاتی را در خصوص استفاده از ماکرو توضیح دهیم‪ .‬برای فراخوانی یک‬
‫ماکرو از دستور ‪ Macro‬استفاده میکنیم‪:‬‬
‫)‪exten => 141,1,Macro(dial‬‬

‫انواع متغیر‌ها در ماکرو‬


‫در هنگام استفاده از ماکرو ‪ ،‬متغیرهایی داریم که در بدنه ماکرو بسیار کاربردی میباشند‪:‬‬
‫‪ -‬متغیر{‪ : $}MACRO_CONTEXT‬اشاره می‌کند که ماکرو از چه کانتکستی فراخوانی شده‌است‪.‬‬
‫‪ -‬متغیر{‪ : $}MACRO_EXTEN‬اشاره می‌کند توسط چه اکستنشنی‪ ،‬ماکرو فراخوانی شده‌است‪.‬‬
‫‪ -‬متغیر{‪ : $}MACRO_PRIORITY‬اشاره به این دارد که در چه اولویتی این ماکرو فراخوانی شده‌است ‪.‬‬
‫متغیــر{‪ : $}ARG n‬اگر در فراخوانی ماکرو‪ ،‬بخواهیم پارامترهایی را به ماکرو ارســال کنیم‪ ،‬میتوانیم‬
‫آنهــا را بهصورت}‪ ${ARG1‬برای پارامتر اول‪ ${ARG2} ،‬برای پارامتر دوم و}‪ ${ARG n‬برای پارامتر ‪n‬‬
‫داشته باشیم‪.‬‬ ‫ام‬
‫در برنامه زیر از متغیر‌های ماکرو استفاده شده است‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 142,1,NoOp‬‬
‫)‪same => n,Macro(lab‬‬
‫)(‪same => n,Hangup‬‬

‫]‪[macro-lab‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)}‪same => n,NoOP(${EXTEN‬‬
‫)} ‪same => n,NoOp(${MACRO_ CONTEXT‬‬
‫)}‪same => n,NoOp(${MACRO_EXTEN‬‬
‫)}‪same => n,NoOp(${MACRO_PRIORITY‬‬

‫خروجی برنامه بهصورت زیر است‪.‬‬


‫‪CLI> console dial 142@LocalSets‬‬
‫‪-- Executing [142@LocalSets:1] NoOp("Console/dsp", "") in new stack‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪214‬‬

‫‪-- Executing [142@LocalSets:2] Macro("Console/dsp", "lab") in new stack‬‬


‫‪-- Executing [s@macro-lab:1] NoOp("Console/dsp", "") in new stack‬‬
‫‪-- Executing [s@macro-lab:2] NoOp("Console/dsp", "s") in new stack‬‬
‫‪-- Executing [s@macro-lab:3] NoOp("Console/dsp", "LocalSets") in new stack‬‬
‫‪-- Executing [s@macro-lab:4] NoOp("Console/dsp", "142") in new stack‬‬
‫‪-- Executing [s@macro-lab:5] NoOp("Console/dsp", "2") in new stack‬‬
‫‪-- Executing [142@LocalSets:3] Hangup("Console/dsp", "") in new stack‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید همه متغیرهای تعریف شده در ماکرو ارزیابی شدهاند‪.‬‬
‫متغیر}‪ ${EXTEN‬همان ‪ s‬است‪.‬‬
‫متغیر}‪ ${MACRO_ CONTEXT‬همان کانتکست ]‪ [LocalSets‬است‪.‬‬
‫متغیر}‪ ${MACRO_ EXTEN‬همان اکستنشن ‪ ۱4۲‬است‪.‬‬
‫متغیر}‪ ${MACRO_ PRIORITY‬اولویت فراخوانی ماکروست که اینجا ‪ ۲‬است‪.‬‬
‫اکنــون چنانچــه بخواهیم مثال قبلی را بهگونهای تغییر دهیم که بهصورت عمومی قابل اســتفاده باشــد؛‬
‫میتوانیم اکستنشــن را هم بهصورت پارامتر برای ماکرو ارســال کنیم و هم میتوانیم از متغیر}_‪MACRO‬‬
‫‪ ${EXTEN‬استفاده کنیم‪.‬‬
‫نخســت ماکرو را بهصورتی پیادهسازی میکنیم که شماره داخلی‪ ،‬بهصورت پارامتر برای ماکرو ارسال‬
‫شود‪ .‬این ماکرو بهصورت زیر تعریف میشود‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[macro-dial‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Dial(SIP/${ARG1},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫)‪same => n(unavail),Playback(unavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫هنگام فراخوانی ماکرو‪ ،‬باید بهصورت زیر عمل کرد‪:‬‬


‫)}‪exten => _NXX,1,Macro(dial,${EXTEN‬‬

‫در این عملیات‪ ،‬ماکرو با استفاده از الگوی تطابق برای هر اکستنشنی که با این الگو مطابقت داشته باشد‪،‬‬
‫فراخوانی میشــود‪ .‬شــمارهی اکستنشن بهصورت پارامتر برای ماکرو ارسال میشــود‪ .‬راه دیگری هم برای‬
‫پیادهسازی ماکرو وجود دارد‪ .‬به مثال زیر توجه کنید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[macro-dial‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Dial(SIP/${MACRO_EXTEN},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫‪215‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫)‪same => n(unavail),Playback(unavail‬‬


‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال از متغیرهای ماکرو استفاده کردیم که بهصورت زیر فراخوانی میشود‪.‬‬
‫)‪exten => _NXX,1,Macro(dial‬‬

‫اکنون از این ماکرو میتوان برای کاربران مختلف استفاده کرد تا از تکرار نوشتن کدها جلوگیری شود‪.‬‬
‫چنانچــه بخواهیــم کد پیشــرفتهتر ومنظمتــری از تعریف ‪ macro-dial‬داشــته باشــیم‪ ،‬آن را بهصورت زیر‬
‫مینویسیم‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[macro-dial‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Dial(SIP/${ARG1},20‬‬
‫)‪same => n,Goto(s-${DIALSTATUS},1‬‬

‫)‪exten => s-NOANSWER,1,Playback(unavail‬‬


‫)‪same => n,Goto(incoming,s,1‬‬

‫)‪exten => s-BUSY,1,Playback(busy‬‬


‫)‪same => n,Goto(incoming,s,1‬‬

‫ماکرو باال به صورت زیر فراخوانی می شود‪:‬‬


‫]‪[LocalSets‬‬

‫)}‪exten => _NXX,1,Macro(dial,${EXTEN‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬بهجای نوشــتن انبوهی از کدهای تکراری‪ ،‬بــه کمک یک ماکرو کدهایی‬
‫ایجاد کردیم که سادهتر و قابل فهمتر باشند‪ .‬چنانچه تغییری در کدها الزم باشد‪ ،‬کافی است آن تغییرات را‬
‫در ماکرو نیز اعمال کنیم‪ .‬همانطورکه پیش از این نیز گفته شد در نسخههای استریسک ‪ ۱۱‬به بعد‪ ،‬استفاده‬
‫از ماکرو توصیه نمیشــود بلکه بهجای ماکرو بهتر اســت از دستور ‪ Gosub‬استفاده کنید‪ .‬بنابراین‪ ،‬به دستور‬
‫‪ Gosub‬میپردازیم‪.‬‬

‫تعریف توابع در استریسک‬


‫در استریســک می توانیم با استفاده از دستور‪ Gosub‬توابع جدیدی تعریف کنیم‪ .‬دستور ‪ Gosub‬بسیار شبیه‬
‫دستور ‪ Macro‬است و این امکان را میدهد تا بتوانیم از تکرار کدها در برنامهنویسی جلوگیری کنیم و نهایتاً‬
‫کدهای خواناتر و منظمتری داشتهباشــیم‪ .‬همانند هر زبان برنامهنویســی دیگری‪ ،‬در استریســک نیز میتوان‬
‫بهراحتــی توابعــی تعریف کرد و از آنها بهره برد‪ .‬برای دســتور ‪ ، Gosub‬چون نیــازی به فضای ‪ stack‬در‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪216‬‬

‫حافظه وجود ندارد‪ ،‬برخالف ماکروها که تا پنج ســطح فراخوانی را پشتیبانی میکنند‪ ،‬در این دستور امکان‬
‫فراخوانیهای تو در تو بهصورت نامحدود فراهم شده است‪.‬‬
‫برای تعریف یک ‪ ، Gosub‬برخالف ماکرو به هیچ پیشوندی نیاز نداریم‪ ،‬اما بهتر است برای خواناشدن‬
‫کدها در برنامهها و تفکیک بهتر کانتکست‪ ،‬از پیشوند »‪ «sub‬در ابتدای نام دستور استفاده کنیم‪.‬‬
‫در مثال زیر برنامه مربوط به ‪ SubDial‬را بهصورت تابع با دستور ‪ Gosub‬مینویسیم‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[subDial‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Set(JOHN=SIP/Phone_1‬‬
‫)‪same => n,Dial(${JOHN},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫)‪same => n(unavail),Playback (unavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫همانطورکه مالحظه میکنید‪ ،‬تفاوت اصلی به تعریف نام ‪ Gosub‬در برابر نام ‪ Macro‬مرتبط است‪ .‬یکی از‬
‫تفاوتهای مهم دیگر این است که در ‪ ،Gosub‬متغیرهایی مثل متغیرهای ماکرویی نداریم؛ بنابراین‪ ،‬هر آنچه‬
‫که در بدنه ‪ Gosub‬نیاز داریم باید بهصورت پارامتر به بدنه ‪ Gosub‬ارسال کنیم‪.‬‬
‫مثال تکمیل شده ‪ SubDial‬که بهصورت زیر نوشته شده است‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[subDial‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)‪same => n,Dial(SIP/${ARG1},10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail‬‬
‫)‪same => n(unavail),Playback(unavail‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(busy),Playback(busy‬‬
‫)(‪same => n,Hangup‬‬

‫دستور ‪ GoSub‬را بهصورت زیر فراخوانی میکنیم‪:‬‬


‫]‪[LocalSets‬‬
‫))}‪exten => _ZXX,1,GoSub(subDial,s,1(${EXTEN‬‬

‫و آنچه را که نیاز داریم بهصورت پارامترهای}‪ ${ARG1‬برای تابع ارسال میکنیم‪.‬‬

‫استفاده از دستور ‪ Return‬در توابع‬


‫یکــی دیگر از تفاوتهای مهم بین کاربرد دســتور ‪ Gosub‬و ‪ Macro‬این اســت که بعد از اجرای دســتور‬
‫‪ ،Macro‬کنتــرل اجرای برنامه دوباره به دســتورات بعــد ازفراخوانی ‪ Macro‬برمیگردد و اجرا میشــود‪،‬‬
‫درحالیکه بعد از اجرای دستورات ‪ ، Gosub‬برنامه خاتمه مییابد‪ .‬چنانچه بخواهیم بعد از اجرای دستورات‬
217 ‫برنامه‌نویسی پیشرفته در استریسک‬

‫ برای بازگشت به‬Return ‫ در این صورت باید از دستور‬،‫ تماس قطع نشــود و دستورات اجرا شــوند‬GoSub
.‫ استفاده کنیم‬Gosub ‫دستور بعد از مرحله فراخوانی‬
:‫برای مثال برنامه زیر را در نظر بگیرید‬
;extensions.conf
[LocalSet]
exten => 101,1,NoOp()
same => n,Set(JOHN=SIP/Phone_1)
same => n,GoSub(subDialer,start,1(${JOHN},30))
same => n,GoSub(subVoicemail,start,1(${EXTEN},default,u))

[subDialer]
exten => start,1,NoOp()
same => n,Dial(${ARG1},${ARG2})
same => n,Return()

[subVoicemail]
exten => start,1,NoOp()
same => n,VoiceMail(${ARG1}@${ARG2},${ARG3})
same => n,Hangup()

‫ چنانچه برای دستور‬.‫ اجرا میشود‬Gosub ‫ بهوســیله‬subDialer ‫ نخســت تابع‬،‫همانطورکه مالحظه میکنید‬
‫ به اولویت بعدی در فراخوانی‬Return ‫ ازطریق دستور‬،‫ تماس پاسخ داده نشود‬،‫ ثانیه‬۳۰ ‫ پس از گذشت‬Dial
.‫ را اجرا میکند‬subVoicemail ‫ میرود و دستور بعدی تابع‬Gosub

$}GOSUB_RETVAL{‫استفاده از متغیر‬
‫ باید‬،‫ بخواهیم مقادیری از تابع را بهعنوان خروجی برگردانیم‬، Gosub ‫چنانچه پس از فراخوانی تابع بهوسیله‬
:‫ برنامه زیر را در نظر بگیرید‬،‫ برای مثال‬.‫ استفاده کنیم‬${GOSUB_RETVAL}‫از متغیر‬
;extensions.conf
[LocalSet]
exten => 101,1,NoOp()
same => n,Set(JOHN=SIP/Phone_1)
same => n,GoSub(subDialer,start,1(${JOHN},30))
same => n,Set(VoicemailMessage=${IF($["${GOSUB_RETVAL}" = "BUSY"]?b:u)})
same => n,GoSub(subVoicemail,start,1(${EXTEN},default,${VoicemailMessage}))

[subDialer]
exten => start,1,NoOp()
same => n,Dial(${ARG1},${ARG2})
same => n,Return(${DIALSTATUS})

[subVoicemail]
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪218‬‬

‫)(‪exten => start,1,NoOp‬‬


‫)}‪same => n,VoiceMail(${ARG1}@${ARG2},${ARG3‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال‪ ،‬نخست تابع ‪ subDialer‬بهوسیله ‪ Gosub‬اجرا میشود‪ .‬در آن تابع مقدار متغیر}‪${DIALSTATUS‬‬
‫بهعنوان خروجی تابع‪ ،‬به کمک دســتور ‪ Return‬برگشــت داده میشــود و در فراخوانی دستور بعدی )تابع‬
‫‪ (subVoicemail‬از مقدار آن استفاده میشود‪.‬‬

‫کانال محلی در استریسک‬


‫‪1‬‬

‫یکی از قابلیتهای منحصر به فرد استریســک‪ ،‬کانالهای محلی هستند‪ .‬شاید توضیح دادن در خصوص این‬
‫کانالها کمی دشوار باشد‪ .‬برای فهم آسانتر با مثالهایی کاربرد آنها را شرح میدهیم‪.‬‬
‫با اســتفاده از کانالهای محلی میتوانید تماسهایی را به سمت استریسک شبیهسازی کنید‪ ،‬بهطوریکه‬
‫این توانایی میتواند قابلیتهای خوبی را در استریســک برای ما ایجاد کند‪ .‬مثال فرض کنید بخواهیم بهطور‬
‫همزمان با گروهی از افراد تماس بگیریم‪ ،‬در این حالت بهصورت زیر عمل میکنیم‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 150,1,NoOp‬‬
‫)‪same => n,Verbose(2,Dialing multiple locations simultaneously‬‬
‫)‪same => n,Dial(SIP/Phone_1&DAHDI/g0/09151176713&SIP/MyITSP/31770000,40‬‬
‫)(‪same => n,Hangup‬‬

‫در این مثال ما بهصورت همزمان با سه نفر به مدت ‪ 4۰‬ثانیه تماس میگیریم‪ .‬چنانچه یک نفر تماس را پاسخ‬
‫دهد‪ ،‬تماس با سایر گوشیها قطع میشود‪.‬‬
‫فرض کنید بخواهیم اول ‪ SIP/Phone_1‬به مدت ‪ 4۰‬ثانیه زنگ بخورد و اگر پاســخ داده نشد آنگاه با‬
‫سایر افراد تماس بگیریم‪ .‬در این صورت برنامه مورد نظر بهصورت زیر خواهد بود‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 151,1,NoOp‬‬
‫)‪same => n,Verbose(2,Dialing multiple locations simultaneously‬‬
‫)‪same => n,Dial(SIP/Phone_1,40‬‬
‫)‪same => n,Dial(DAHDI/g0/09151176713,40‬‬
‫)‪same => n,Dial(SIP/MyITSP/31770000,40‬‬
‫)(‪same => n,Hangup‬‬

‫اکنون در نظر بگیرید ســناریو این گونه تغییر کند‪ :‬ابتدا با نفر اول تماس برقرار شــود‪ ،‬چنانچه پس از ‪ ۱۰‬ثانیه‬
‫تماس برقرار نشــد‪ ،‬نفر دوم هم شــروع به زنگ خوردن کند و اگر پس از گذشت ‪ ۲۰‬ثانیه پاسخی دریافت‬
‫نشد‪ ،‬آنگاه نفر سوم شروع به زنگ خوردن کند‪ .‬سناریوی این مثال بهصورت شکل ‪ ۱-8‬خواهد بود‪.‬‬

‫‪1- Local Channels‬‬


‫‪219‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫شکل ‪1-8‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اینجا تماسهای دوم و ســوم با فاصله زمانی معینی برقرار میشــوند؛ بنابراین‪،‬‬
‫باید از تکنیک کانالهای محلی در استریسک استفاده کنیم‪ .‬برنامه زیر را در نظر بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 152,1,Verbose(2,Dialing multiple locations with time delay‬‬
‫‪same => n,Dial(Local/channel_1@TimeDelay&Local/channel_2@TimeDelay&Local/‬‬
‫)‪channel_3@TimeDelay,40‬‬
‫)(‪same => n,Hangup‬‬

‫اکنون باید کانتکســت ‪ TimeDelay‬را بنویســیم‪ .‬در این کانتکست باید اکستنشنهای ‪channel_2 ، chan-‬‬
‫‪ nel_1‬و ‪ channel_3‬را داشته باشیم‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[TimeDelay‬‬
‫)‪exten => channel_1,1,Verbose(2,Dialing the first channel‬‬
‫)‪same => n,Dial(SIP/Phone_1,40‬‬
‫)(‪same => n,Hangup‬‬

‫)‪exten => channel_2,1,Verbose(2,Dialing the second channel with a delay‬‬


‫)‪same => n,Wait(10‬‬
‫)‪same => n,Dial(DAHDI/g0/09151176713,30‬‬
‫)(‪same => n,Hangup‬‬

‫)‪exten => channel_3,1,Verbose(2,Dialing the third channel with a delay‬‬


‫)‪same => n,Wait(20‬‬
‫)‪same => n,Dial(SIP/MyITSP/31770000,20‬‬
‫)(‪same => n,Hangup‬‬

‫همانطورکه مالحظه میکنید با اجرای دستور ‪ ، Dial‬سه کانال محلی ایجاد و وارد کانتکست ‪TimeDelay‬‬
‫میشود و سپس همانجا دستورات اجرا میشوند‪ .‬این سناریو در استریسک بدون استفاده از کانالهای محلی‪،‬‬
‫به سختی پیش میرود‪.‬‬

‫بهینه‌سازی کانال‌ها در استریسک‬


‫از نکات مهم استفاده از کانالهای محلی در استریسک این است که میتوان از این کانالها بهعنوان واسطه‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪220‬‬

‫)پلهای میانی( اســتفاده نمود‪ ،‬بهطوریکــه پس از برقراری پل‪ ،‬این واســطههای میانی بدون درنگ از بین‬
‫بروند‪ .‬شــاید مطلب کمی نامفهوم بهنظر برســد ولی در برخی از ســناریوها‪ ،‬آگاهی به این موضوع میتواند‬
‫بسیار مفید باشد‪ .‬مثال زیر را ببینید‪.‬‬
‫فرض کنید ‪ TOM‬بخواهد با ‪ BOB‬تماس بگیرد و سناریوی تماس او بهصورت زیر باشد‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 155,1,Dial(LOCAL/BOB@Locals‬‬
‫)‪exten => 156,1,Dial(LOCAL/TOM@Locals‬‬
‫)‪exten => 157,1,Dial(LOCAL/BOB@Locals/n‬‬
‫)‪exten => 158,1,Dial(LOCAL/TOM@Locals/n‬‬

‫]‪[locals‬‬
‫)‪exten => BOB,1,Set(BOB=SIP/Phone_1‬‬
‫)}‪same => n,Dial(${BOB‬‬

‫)‪exten => TOM,1,Set(TOM=SIP/Phone_2‬‬


‫)}‪same => n,Dial(${TOM‬‬

‫درحالیکه از شــمارههای ‪ ۱۵۵‬و ‪ ۱۵۶‬اســتفاده میکنیم‪ ،‬کانالهای محلی تماس را به سمت کاربر ‪ BOB‬یا‬
‫‪ TOM‬ارسال میکنند؛ اما به محض اینکه ‪ BOB‬یا ‪ TOM‬تماس را پاسخ دادند‪ ،‬کانال محلی ایجاد شده میان‬
‫آنها قطع و کانالها مستقیماً به هم متصل میشوند‪ .‬این فرایند در شکل ‪ ۲-8‬نشان داده شده است‪.‬‬

‫شکل ‪2-8‬‬

‫همانطورکــه مالحظــه میکنید پس از برقــراری تماس میــان ‪ BOB‬و ‪ ، TOM‬کانالهای محلی از بین‬
‫میرونــد‪ .‬اکنون فرض کنید بنا به دالیلی بخواهیم این کانالهــای محلی تا زمانی که کانالهای اصلی فعال‬
‫هســتند‪ ،‬از بین نروند‪ .‬در این حالت باید از شــمارههای ‪ ۱۵7‬و ‪ ۱۵8‬استفاده کنیم‪ .‬اینجا باید از پارامتر ‪ /n‬در‬
‫‪221‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫کانالهای محلی استفاده شود‪ .‬شکل ‪ ۳-8‬این فرایند را نشان میدهد‪.‬‬

‫شکل ‪3-8‬‬

‫هرچنــد بحث کمی پیچیده شــد اما در فصلهای بعدی به کاربردهــای متمایز و ویژهای از کانالهای محلی‬
‫خواهیم پرداخت‪.‬‬

‫‪1‬‬
‫استفاده از ‪AstDB‬‬

‫یکی دیگر از ابزارهای قدرتمند استریســک برای کار با دیتابیسها‪ ،‬استفاده از دیتابیس داخلی استریسک با‬
‫نام ‪ Asterisk Database‬است‪ .‬از ‪ AstDB‬برای ذخیرهکردن دادهها استفاده میشود‪ .‬استریسک از ‪SQLite‬‬
‫بهعنوان دیتابیس داخلی استفاده میکند و دادهها در آن بهصورت ‪ key/value‬ذخیره میشوند‪.‬‬
‫در فصل یازدهم )ارتباط استریسک با پایگاههای دادهای( با نحوهی ارتباط استریسک با سایر دیتابیسها‬
‫از قبیــل ‪ MySQL ، PostgreSQL‬و ‪ MSSQL‬بیشــتر آشــنا خواهید شــد‪ .‬در این بخــش دیتابیس داخلی‬
‫استریسک ‪ AstDB‬و کار با آن در برنامهنویسی بیشتر مدنظر است‪.‬‬
‫در ‪ AstDB‬دادههــا بهصورت گروهی دســتهبندی میشــوند که این گروه بنــدی ‪ family‬نام دارد‪ .‬این‬
‫دادهها در دیتابیس به صورت زیر دستهبندی میشوند‪:‬‬
‫>‪<family> <key> <value‬‬

‫نمایش داده‌های ذخیره شده در دیتابیس‬


‫میتوان از دســتور ‪ database show‬در محیط کامندالین استریسک برای مشاهده همه دادههای ذخیره شده‬
‫در ‪ AstDB‬استفاده کرد‪.‬‬
‫‪CLI> database show‬‬

‫ذخیره کردن داده‌ی جدید در ‪AstDB‬‬


‫برای ذخیره کردن دادهها در دیتابیس استریسک‪ ،‬میتوان به دو روش عمل کرد‪:‬‬
‫‪ -1‬در محیط کامند‌الین استریســک‪ :‬با دســتور زیر در محیط کامندالین استریسک می‌توان داده‌های جدید‬

‫‪1- Asterisk Database‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪222‬‬

‫دیتابیس را ذخیره کرد‪ .‬فرمت دستور به‌صورت زیر است‪.‬‬


‫>‪CLI> database put <family> <key> <value‬‬

‫فرض کنید دستور زیر را داشته باشیم‪.‬‬


‫‪CLI> database put test COUNT 1‬‬

‫‪ -2‬در محیط برنامه‌نویســی استریســک‪ :‬هنگام برنامه‌نویســی در استریســک‪ ،‬می‌توان هر زمان که نیاز باشد‬
‫متغیر‌هایی را در دیتابیس ایجاد و از آنها اســتفاده نمود‪ .‬برای ذخیره‌ســازی داده‌های جدید‪ ،‬از ترکیب دستور‬
‫‪ Set‬و تابع ‪ DB‬استفاده کنید‪.‬‬
‫)>‪Set(DB(<family>/<key>) = <value‬‬

‫مثال فرض کنید بخواهیم معادل دستور باال را به این روش بنویسیم‪.‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 201,1,NoOp‬‬
‫)‪same => n,Set(DB(test/COUNT) = 1‬‬

‫خواندن داده‌ها از ‪AstDB‬‬


‫برای خواندن دادهها از دیتابیس استریسک میتوان به دو روش به این هدف رسید‪:‬‬
‫‪ .1‬در محیط کامند‌الین استریسک‪ :‬با دستور زیر در محیط کامندالین استریسک می‌توان داده‌ها را از دیتابیس‬
‫خواند‪ .‬فرمت دستور به‌صورت زیر است‪.‬‬
‫>‪CLI> database get <family> <key‬‬

‫مثــا فــرض کنید بخواهیم مقدار داده‌ی ذخیره شــده ‪ test/COUNT‬را از دیتابیس بخوانیم‪ ،‬در این صورت‬
‫داریم‪:‬‬
‫‪CLI> database get test COUNT‬‬

‫‪ .2‬در محیط برنامه‌نویســی استریسک‪ :‬هنگام برنامه‌نویسی استریسک‪ ،‬هر زمان که نیاز باشد می‌توان متغیر‌هایی‬
‫را از دیتابیس خواند و از آنها استفاده کرد‪ .‬برای خواندن داده‌ها از دیتابیس از ‪ DB‬استفاده کنید‪.‬‬
‫})>‪${DB(<family>/<key‬‬

‫بخواهیم معادل دستور باال را به این روش بخوانیم‪.‬‬ ‫مثال فرض کنید‬
‫‪;extensions.conf‬‬
‫)(‪exten => 202,1,NoOp‬‬
‫)})‪same => n,NoOp (the value was ${DB(test/COUNT‬‬

‫حذف داده‌ها از ‪AstDB‬‬


‫برای حذف دادهها از دیتابیس استریسک‪ ،‬میتوان به دو روش به این هدف رسید‪:‬‬
‫‪ -1‬در محیط کامند الین استریســک‪ :‬با دســتورات ‪ del‬و ‪ deltree‬در محیط کامندالین می‌توان داده‌ها را از‬
‫دیتابیس حذف کرد‪.‬‬
‫‪223‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫• دستور ‪ :del‬با این دستور یک داده‌ی خاص ‪ family/key‬از دیتابیس حذف می‌گردد‪ .‬فرمت استفاده از‬
‫این دستور به‌صورت زیر است‪:‬‬
‫>‪CLI> database del <family> <key‬‬

‫• دســتور ‪ :deltree‬با این دســتور یک داده‌ی خاص یا داده‌هایی که در یک گروه ‪ family‬هســتند‪ ،‬از‬
‫دیتابیس حذف می‌شــوند‪ .‬در این دســتور مقدار ‪ keytree‬اختیاری اســت‪ .‬فرمت اســتفاده از این دستور‬
‫به‌صورت زیر است‪:‬‬
‫]‪CLI> database deltree <family> [keytree‬‬
‫]‪CLI> database deltree <family> [/keytree‬‬

‫‪ -2‬در محیط برنامه‌نویسی استریسک‪ :‬می‌توان در برنامه‌نویسی استریسک‪ ،‬هر زمان که نیاز باشد متغیر‌هایی را‬
‫از دیتابیس حذف نمود‪ .‬برای حذف داده‌ها از ‪ AstDB‬از دو تابع زیر استفاده کنید‪:‬‬
‫• تابــع ‪ : DB_DELETE‬با این تابــع‪ ،‬داده‌ای که به‌صورت ‪ family/key‬در ‪ AstDB‬ذخیره شده‌اســت‪،‬‬
‫حذف می‌شــود‪ .‬این تابع معادل دســتور ‪ database del‬در کامند‌الین استریسک است‪ .‬به مثال زیر توجه‬
‫کنید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 203,1,NoOp‬‬
‫) }) ‪same => n,NoOp(the value was ${DB_DELETE(test/COUNT‬‬

‫به کمک این دســتور‪ ،‬داده ‪ test/COUNT‬از ‪ AstDB‬حذف می‌شــود و مقدار آن در خروجی‪ ،‬نمایش‬
‫داده می‌شود‪.‬‬
‫• تابع ‪ : DBdeltree‬با این تابع کلیه داده‌هایی که در یک گروه (‪ )family‬هســتند‪ ،‬حذف می‌شــوند‪ .‬این‬
‫دستور معادل دستور ‪ database deltree‬در کامند‌الین استریسک است‪ .‬به مثال زیر توجه کنید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 204,1,NoOp‬‬
‫)})‪same => n,NoOp(all data is deleted ${DBdeltree(test‬‬

‫با این دستور تمامی دادههایی که در گروه ‪ test‬قرار دارند‪ ،‬از ‪ AstDB‬حذف میشوند‪.‬‬
‫ازآنجاکه دادهها در ‪ AstDB‬در دیتابیس داخلی استریســک ذخیره میشــوند‪ ،‬با ‪ stop‬شــدن ســرویس‬
‫استریسک و حتی ‪ restart‬شدن سرور‪ ،‬این دادهها ازبین نمیروند‪.‬‬
‫برای آشنا شدن و نحوه کار با ‪ AstDB‬در استریسک‪ ،‬مثال زیر را در نظر بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 206,1,NoOp‬‬
‫)})‪same => n,Set(COUNT=${DB(test/COUNT‬‬
‫)‪same => n,GotoIf($[${ISNULL(${COUNT})}]?:continue‬‬
‫)‪same => n,Set(DB(test/COUNT)=1‬‬
‫)‪same => n,Goto(1‬‬
‫)(‪same => n(continue),NoOp‬‬
‫)‪same => n,Playback(silence/1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪224‬‬

‫)}‪same => n,SayNumber(${COUNT‬‬


‫]‪same => n,Set(COUNT=$[${COUNT} + 1‬‬
‫)}‪same => n,Set(DB(test/COUNT)=${COUNT‬‬
‫)‪same => n,Goto(1‬‬

‫در توضیحات این برنامه‪ ،‬نخســت بررسی میشود که آیا دادهی ‪ test/COUNT‬قب ً‬
‫ال در ‪ AstDB‬ذخیره‬
‫شدهاست یا نه‪ .‬اگر تعریف نشده باشد‪ ،‬آن را تعریف میکنیم و در یک حلقه ‪ ،loop‬هر بار یک واحد به آن‬
‫و دوباره در دیتابیس ذخیره میکنیم‪.‬‬ ‫اضافه‬
‫بهعنوان یک مثال کاربردی‪ ،‬فرض کنید بخواهیم بر اســاس کالرآیدی شخصی که تماس گرفته است‪،‬‬
‫شــماره آن شــخص را بالک کنیم و اجازه ندهیم تماس بگیرد‪ .‬در این حالت خیلی ســاده میتوانیم از تابع‬
‫‪ Blacklist‬در استریســک استفاده کنیم‪ .‬در این صورت اگر شمارهای در ‪ Blacklist‬وجود داشته باشد‪ ،‬این‬
‫تابع مقدار »‪ «True‬را برمیگرداند‪ ،‬در غیر این صورت »‪ «False‬را برمیگرداند ‪ .‬به مثال زیر توجه کنید‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 207,1,NoOp‬‬
‫)‪same => n,GotoIf($[${BLACKLIST()}]?blocked,1‬‬
‫)‪same => n,Goto(IVR,s,1‬‬

‫)(‪exten => blocked,1,NoOp‬‬


‫)‪same => n,Playback(silence/1‬‬
‫)‪same => n,Playback(privacy-you-are-blacklisted‬‬
‫)‪same => n,Playback(vm-goodbye‬‬
‫)(‪same => n,Hangup‬‬

‫با اســتفاده از دســتور زیر میتوان از طریق کامند الین استریسک‪ ،‬شــماره جدید به لیست ‪ Blacklist‬اضافه‬
‫کــرد‪ .‬در این حالت مقدار ‪ value‬اهمیتی ندارد‪ .‬تنها کافی اســت کالرآیدی مورد نظر در گروه ‪blacklist‬‬
‫اضافه شود‪.‬‬
‫‪CLI> database put blacklist <number> 1‬‬

‫مثال فرض کنید بخواهیم شماره ‪ ۱۰۰‬را در لیست شمارههای ‪ blacklist‬اضافه کنیم‪:‬‬
‫‪CLI> database put blacklist 100 1‬‬

‫اکنون اگر با این کالر آی دی‪ ،‬تماس وارد کانتکست شود‪ ،‬خروجی زیر را خواهد داشت‪:‬‬
‫>‪CLI‬‬
‫‪-- Executing [207@LocalSets:1] NoOp("SIP/100-00000002", "") in new stack‬‬
‫‪-- Executing [207@LocalSets:2] GotoIf("SIP/100-00000002", "1?blocked,1") in new stack‬‬
‫)‪-- Goto (LocalSets,blocked,1‬‬
‫‪-- Executing [blocked@LocalSets:1] NoOp("SIP/100-00000002", "") in new stack‬‬
‫‪-- Executing [blocked@LocalSets:2] Playback("SIP/100-00000002", "silence/1") in new stack‬‬
‫)›‪-- <SIP/100-00000002> Playing ‹silence/1.gsm› (language ‹en‬‬
‫‪-- Executing [blocked@LocalSets:3] Playback("SIP/100-00000002", "privacy-you-are-‬‬
‫‪blacklisted") in new stack‬‬
‫‪225‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫‪-- Executing [blocked@LocalSets:4] Playback("SIP/100-00000002", "vm-goodbye") in new stack‬‬


‫)›‪-- <SIP/100-00000002> Playing ‹vm-goodbye.gsm› (language ‹en‬‬
‫‪-- Executing [blocked@LocalSets:5] Hangup("SIP/100-00000002", "") in new stack‬‬
‫›‪== Spawn extension (LocalSets, blocked, 5) exited non-zero on ‹SIP/100-00000002‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید شــماره بهعنوان ‪ blacklist‬شناســایی میشــود و به اکستنشن ‪ blocked‬انتقال‬


‫مییابد‪.‬‬

‫استفاده از صندوق صوتی‪ 1‬در استریسک‬


‫استفاده از صندوق صوتی تاریخچه نسبتاً طوالنیای دارد و به سال ‪ ۱۹8۰‬میالدی بازمیگردد‪ .‬نام اولیـهی این‬
‫دستگاهها ‪ ۲ TAM‬بودو این سیستمها پاسخ مشتریان را میدادند و در صورت لزوم پیام آنها را ثبت و ذخیره‬
‫میکردند‪ .‬پس از گذشت چندین سال‪ ،‬نام آنها به ‪ ۳ VME‬تغییر پیدا کرد‪.‬‬
‫یک ‪ VME‬از سه قسمت تشکیل شده است‪:‬‬

‫‪ -1‬پیــام خوش آمدگویــی‪ : 4‬معموالً هر صندوق صوتی‪ ،‬بــا یک پیام خوش‌آمدگویی کار خود را شــروع‬
‫می‌کند‪ .‬در این حالت یک پیام اولیه (که این پیام می‌تواند بر اساس ‪ zone‬منطقه تغییر کند) پخش می‌شود و‬
‫از کاربر می‌خواهد بخش بعدی را شروع کند‪.‬‬

‫‪ -2‬ضبط پیام کاربر‪ : 5‬در این حالت‪ ،‬کاربر پس از شــنیدن صدای بوق (‪ ،)beep‬می‌تواند پیام خود را بگذارد‪.‬‬
‫سیستم پیام او را ضبط می‌کند‪.‬‬

‫‪ -3‬کنتــرل پیام‌ها در صندوق صوتی‪ : 6‬معموالً در سیســتم‌های صندوق صوتی ایــن قابلیت وجود دارد که از‬
‫طریــق منوها‪ ،‬عملیات مختلفی روی پیام‌ها از راه دور صورت گیرد‪ ،‬از جمله خواندن پیام‌های جدید‪ ،‬حذف‬
‫پیام قبلی‪ ،‬ذخیره کردن پیام‌ها در آرشیو‪ ،‬تغییر رمز عبور و غیره‪.‬‬
‫در استریســک این قابلیت وجود دارد که با طراحی یک صندوق صوتی‪ ،‬هر کاربر یک صندوق صوتی‬
‫و حائز اهمیتی است‪.‬‬ ‫مجزا و منحصر به فرد داشته باشد‪ .‬طراحی و پیکربندی یک صندوق صوتی نکته مهم‬
‫برای طراحی و پیکربندی صندوق صوتی در استریســک باید از فایل ‪ voicemail.conf‬در مسیر زیر استفاده‬
‫کنید‪.‬‬
‫‪# vim /etc/asterisk/voicemail.conf‬‬

‫‪1- Voicemail‬‬
‫‪2- Telephony Answering Machine‬‬
‫‪3- Voice Message Exchange‬‬
‫‪4- Greeting Massage‬‬
‫‪5- Recording Message‬‬
‫‪6- Remote Control Voicemail‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 226

:‫تنظیمات صندوق صوتی به چند بخش تقسیم میشود‬

‫ اغلب این تنظیمات به مشخصه‌های صندوق صوتی و تعریف آن مرتبط‬:‫) تنظیمات عمومی صندوق صوتی‬1
‫ حداکثر‬،‫ مشخصه‌هایی از قبیل فرمت پیام ضبط شده‬،‫ برای مثال‬.‫] قرار می‌گیرد‬general[ ‫اســت که در بخش‬
‫ تنظیمات جلو و عقب بردن‬،‫ ماکزیمم مدت ضبط هر پیام بر حســب ثانیــه‬،‫تعــداد پیام‌ها در صندوق صوتی‬
‫ تنظیمات مربوط به ایمیل‌کردن پیام‌های صوتی دریافت‬،‫ تنظیمات امنیتی برای ورود به صندوق صوتی‬،‫پیام‌ها‬
‫ تنظیمات برای همه صندوق‌های‬،‫ با تعریف این مشــخصه‌ها‬.‫شــده و غیره از جمله تنظیمات عمومی هســتند‬
.‫ فهرستی از این تنظیمات را ارائه نموده است‬3-8 ‫ جدول‬.‫صوتی اعمال می‌شود‬

Option Value/Example Note


format wav49|gsm|wav For each format listed, Asterisk creates a separate recording in
that format whenever a message is left. The benefit is that some
transcoding steps may be saved if the stored format is the same as
the codec used on the channel. We like WAV because it is the highest
quality, and WAV49 because it is nicely compressed and easy to
email. We don’t like GSM due to its scratchy sound, but it enjoys some
popularity.
serveremail user@domain When an email is sent from Asterisk, this is the email address that it
will appear to come from.
attach yes,no If an email address is specified for a mailbox, this determines whether
the message is attached to the email (if not, a simple message
notification is sent).
maxmsg 9999 By default, Asterisk only allows a maximum of 100 messages to be
stored per user. For users who delete messages, this is no problem.
For people who like to save their messages, this space can get eaten
up quickly. With the size of hard drives these days, you could easily
store thousands of messages for each user, so our current thinking is
to set this to the maximum and let the users manage things from there.
maxgreet 1800 You can define the maximum greeting length if you want. Again, since
storage is not a problem and setting this too low will annoy your more
verbose users, we suggest setting this to a high value and letting your
users figure out an appropriate length for themselves.
maxsecs 0 This type of setting was useful back when a large voicemail system
might have only 40 MBc of storage: it was necessary to limit the
system because it was easy to fill up the hard drive. This setting can
be annoying to callers (although it does force them to get to the point,
so some people like it). Nowadays, with terabyte drives common,
there is no technical reason to limit the length of a message. Two
considerations are: 1) if a channel gets hung in a mailbox, it’s good
to set some sort of value so it doesn’t stay there for days, but 2) if a
user wants to use her mailbox to record notes to herself, she won’t
appreciate it if you cut her off after 3 minutes. A setting somewhere
between 600 seconds (10 minutes) and 3600 seconds (1 hour) will
probably be about right.
227 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Value/Example Note


minsecs 4 Many folks will hang up instead of leaving a message when they
call somebody and get voicemail. Sometimes this hangup happens
after recording has started, so the mailbox owner gets an annoying
2-second message of somebody hanging up. This setting ensures
that Asterisk will ignore messages that are shorter than the configured
minimum length. You should take care not to set this to a value that is
too high, though, because then a message like “Hey it’s me, give me a
call” (which can be said in less than 1 second) will get lost, and you’ll
get complaints of messages disappearing. Three seconds seems to
be about right. To discourage people from leaving ultrashort messages
that might be discarded, your greeting can request callers to identify
themselves and leave some information about why they called.
skipms 3000 When listening to messages, users can skip ahead or backwards by
pressing (by default) * and #. This setting indicates the length of the
jump (in milliseconds).
maxsilence 5 This setting defines the maximum time for which the caller can remain
silent before the recording is stopped. We like to set this setting
to 1 second longer than minsecs (if you set it equal to or greater
than minsecs, you will get a warning stating “maxsilence should be
less than minsecs or you may get empty messages”). This value
is probably most useful when you have analog trunks, as far-end
disconnect can be dodgy on such circuits. With any sort of digital
circuit (PRI or VoIP), a far-end disconnect message will tend to handle
the end of the message quite neatly, and in fact you might want to
consider increasing this value to 10 seconds, to reduce the chance
that quiet folks accidentally get disconnected midmessage.
maxlogins 3 This little security feature is intended to make brute-force attacks on
your mailbox passwords more time-consuming. If a bad password is
received this many times, voicemail will hang up and you’ll have to call
back in to try again. Note that this will not lock up the mailbox. Patient
snoopers can continue to try to log into your mailbox as many times as
they like, they’ll just have to call back every third attempt. If you have a
lot of sausagefingered users, you can set this to something like 5.
silencethreshold 128 This parameter allows you to fine-tune the silence sensitivity of the
previous parameter, maxsilence. Valid values are from 0 to 32767.
The default value is 128. The value helps app_voicemail decide
what amplitude to use as a reference point as to what it will consider
“silence.”
Since this is a linear value, and amplitude needs to be properly
considered in terms of decibels (which are logarithmic), we don’t
recommend adjusting this parameter unless you have a solid
understanding of amplitude, decibels, logarithmic scales, C
programming, digital signal processing, and so forth. If you have audio
problems with your system, this is not the first place to go to attempt
to solve them.
move heard yes This setting will move listened-to messages to the Old folder. We
recommend leaving this at the default.
forward_urgent no Setting this to yes will preserve the original urgency setting of any
_auto messages the user receives and then forwards on. If you leave it at
no, users can set the urgency level themselves on messages that they
forward.
userscontext default If you use the users.conf file (we don’t), you can define here the
context where entries are registered.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 228

Option Value/Example Note


externnotify /path/to/script If you wish to run an external app whenever a message is left, you can
define it here.
smdienable no If you are using Asterisk as a voicemail server on a PBX that supports
SMDI, you can enable it here.
smdiport /dev/ttyS0 Here is where you would define the SMDI port that messages between
Asterisk and the external PBX would pass across.
externpass /path/to/script Any time the password on a mailbox is changed, the script you define
here will be notified of the context, mailbox, and new password.
The script will then be responsible for updating voicemail.conf (the
Asterisk voicemail app will not update the password if this parameter
is defined).
externpassnotify /path/to/script Any time the password on a mailbox is changed, the script you define
here will be notified of the context, mailbox, and new password.
Asterisk will handle updating the password in voicemail.conf. If you
have defined externpass, this option will be ignored.
externpasscheck /usr/local/ See the sidebar following this table for a description of this option.
bin/voice
mailpwcheck.py
directoryintro dir-intro The Directory() dialplan application uses the voicemail.conf file to
search by name from an auto attendant. There is a default prompt that
plays, called dir-intro. If you want, you can specify a different file to
play instead.
charset ISO-8859-1 If you need a character set other than ISO-8859-1 (a.k.a Latin 1) to be
supported, you can specify it here.
adsifdn 0000000F Use this option to configure the Feature Descriptor Number.
adsisec 9BDBF7AC Use this option to configure the security lock code.
adsiver 1 This specifies the ADSI voicemail application version number.
pbxskip yes If you do not want emails from your voicemail to have the string [PBX]
added to the subject, you can set this to yes.
fromstring The Asterisk You can use this setting to configure the From: name that will appear
PBX in emails from your PBX.
usedirectory yes This option allows users composing messages from their mailboxes to
take advantage of the Directory.
odbcstorage <item from If you want to store voice messages in a database, you can do that
res_odbc.conf> using the Asterisk res_odbc connector. Here, you would set the name
of the item in the res_odbc file. For details.
odbctable <table name> This setting specifies the table name in the database that the odbcstor
age setting refers to. For details.
emailsubject [PBX]: New When Asterisk sends an email, you can use this setting to define what
message $ the Subject: line of the email will look like. See the voicemail.conf.
{VM_MSGNUM} in sample file for more details.
mailbox $
{VM_MAILBOX}
mailcmd /usr/sbin/send If you want to override the default operating system application for
mail -t sending mail, you can specify it here.
imapgreetings no, yes This enables/disables remote storage of greetings in the IMAP folder.
Formore details.
229 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Value/Example Note


emailbody Dear $ When Asterisk sends an email, you can use this setting to define what
{VM_NAME}:\n\n the body of the email will look like. See the voicemail.conf.sample file
\tjust wanted for more details.
to let you
know you were
just left a $
{VM_DUR} long
message (num
ber $
{VM_MSGNUM})
\nin mailbox $
{VM_MAILBOX u
might\nwant to
check it when
you get a
chance.
Thanks!\n\n\t
\t\t\t--
Asterisk\n

pagerfromstring The Asterisk We don’t actually know anybody who uses pagers anymore (nor can
PBX we recall having seen one in many years), but if you have one of these
historical oddities and you want to customize what Asterisk sends
with its pager notification, presumably you can do that with this. A
very practical application of this feature for short-message voicemail
notifications is to send a message to an email-to-SMS gateway.
pagersubject New VM As above.
pagerbody New ${VM_DUR} The formatting for this uses the same rules as emailbody.
long msg in
box ${VM_MAIL
BOX}\nfrom $
{VM_CALLERID},
on ${VM_DATE}

emaildateformat %A, %d %B %Y This option allows you to specify the date format in emails. Uses the
at %H:%M:%S same rules as the C function STRFTIME.
pagerdateformat %A, %d %B %Y This option allows you to specify the date format in pagerbody. Uses
at %H:%M:%S the same rules as the C function STRFTIME.
pollmailboxes no, yes If the contents of mailboxes are changed by anything other than app_
voicemail (such as external applications or another Asterisk system),
setting this to yes will cause app_voicemail to poll all the mailboxes for
changes, which will trigger proper message waiting indication (MWI)
updates.
pollfreq 30 Used in concert with pollmailboxes, this option specifies the number of
seconds to wait between mailbox polls.
greetingsfolder INBOX If you’ve enabled imapgreetings, this parameter allows you to define
the folder your greetings will be stored in (defaults to INBOX).
imapparentfolder INBOX IMAP servers can handle parent folders in different ways. This field
allows you to specify the parent folder for your mailboxes. For more
details, see Chapter 7.
imapserver localhost Defines the IMAP server Asterisk should connect to.
imapport 143 Defines the port of the IMAP server to connect to.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 230

Option Value/Example Note


imapflags ssl IMAP servers typically have different flags that can be passed along
with the mailbox name. A common flag to pass is ssl, which enables
OpenSSL encryption in the communication if the IMAP libraries were
compiled with OpenSSL support.

imapfolder INBOX The folder to store voicemail messages in on the IMAP server. The
default is INBOX.
authuser user If your IMAP server has been defined with an account that can access
all mailboxes, you can define that user for Asterisk to connect to the
server with.
authpassword password This option defines the password to be used with the authuser
attribute.
imapopentimeout 60 The TCP open timeout in seconds.
imapclosetimeout 60 The TCP close timeout in seconds.
imapreadtimeout 60 The TCP read timeout in seconds.
imapwritetimeout 60 The TCP write timeout in seconds.
3-8 ‫جدول‬

،‫ عالوه بر تنظیمات عمومی که برای همه صندوق‌های صوتی اعمال می‌شــود‬:‫ تنظیمات صنــدوق صوتی‬-2
‫ بــه عبارت دیگر این‬.‫تنظیمات و مشــخصه‌های ایــن بخش برای هر صندوق صوتی می‌تواند متفاوت باشــد‬
‫ از جمله مهمترین این‬.‫تنظیمات و مشخصه‌ها را برای هر صندوق صوتی می‌توان به‌صورت مستقل تنظیم نمود‬
‫ ارسال‬،‫ اعالن طول پیام صوتی‬،‫ اعالن شماره کالرآیدی‬،‫مشخصه‌ها می‌توان به تنظیمات زبان صندوق صوتی‬
‫ فهرســتی از این‬4-8 ‫ جدول‬.‫ اعالن تاریخ و ســاعت دریافت پیام و تنظیمات دیگر اشــاره نمود‬،‫پیام به ایمیل‬
.‫تنظیمات را ارائه کرده است‬

Option Value/Example Note


tz eastern, euro Specifies the zonemessages name, as defined under
pean, etc. [zonemessages] (discussed in the next section).
locale de_DE.utf8, Used to define how Asterisk generates date/time strings in
es_US.utf8, different locales. To determine the locales that are valid on your
etc. Linux system, type locale -a at the shell.
attach yes,no If an email address is specified for a mailbox, this determines
whether the messages are attached to the email notifications
(otherwise, a simple message notification is sent).
attachfmt wav49, wav, If attach is enabled and messages are stored in different formats,
etc. this defines which format is sent with the email notifications. Often
wav49 is a good choice, as it uses a better compression algorithm
and thus will use less bandwidth.
saycid yes, no This command will state the caller ID of the person who left the
message.
231 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Value/Example Note


cidinternalcontexts <context>, <an Any dialplan contexts listed here will be searched in an attempt to
other con locate the mailbox context, so that the name associated with the
text> mailbox number can be spoken. The voicemail box number needs
to match the extension number that the call came from, and the
voicemail context needs to match the dialplan context.
sayduration yes,no This command will state the length of the message.
saydurationm 2 Use this to specify the minimum duration of a message to qualify
for its length being played back. For example, if you set this to 2,
any message less than 2 minutes in length will not have its length
stated. (The option really is saydurationm and isn’t a typo here.)
dialout <context> If allowed, users can dial out from their mailboxes. This
isconsidered a very dangerous feature in a phone system
(mainly because many voicemail users like to use 1234 as their
password), and is therefore not recommended. If you insist on
allowing this, make sure you have a second level in the dialplan
where another password is specified. Even so, this is not a safe
practice.
searchcontexts yes, no This allows voicemail applications in the dialplan to not have to
specify the voicemail context, since all contexts will be searched.
This is not recommended.
callback <context> This specifies which dialplan context to use to call back to the
sender of a message. The specified context will need to be able to
handle dialing of numbers in the format in which they are received
(for example, the country code may not be received with the caller
ID, but might be required for the outgoing call).
exitcontext <context> There are options that allow the callers to exit the voicemail
system when they are in the process of leaving a message (for
example, pressing 0 to get an operator). By default, the context
the caller came from will be used as the exit context. If desired,
this setting will define a different context for callers exiting the
voicemail system.
envelope no, yes You can have voicemail play back the details of the message
before it plays the actual message. Since this information can also
be accessed by pressing 5, we generally set this to no.
delete no, yes After an email message notification is sent (which could include
the message itself), the message will be deleted. This option
is risky, because the fact that a message was emailed is not a
guarantee that it was received (spam filters seem to love to delete
Asterisk voicemail messages). On a new system, leave this at no
until youare certain that no messages are being lost due to spam
filters.
volgain 0.0 This handy little setting will save you some time, as it takes you
directly to the next message once you’ve finished dealing with the
current message.
nextaftercmd yes, no Any time the password on a mailbox is changed, the script you
define here will be notified of the context, mailbox, and new
password. Asterisk will handle updating the password in voicemail.
conf. If you have defined externpass, this option will be ignored.
forcename yes, no This strange little setting will check whether the mailbox password
is the same as the mailbox number. If it is, it will force the user to
change his voicemail password and record his name.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 232

Option Value/Example Note


forcegreetings yes, no As above, but for greetings.
hidefromdir no, yes If you wish, you can hide specific mailboxes from the
Directory() application using this setting.
tempgreetwarn yes, no Setting this to yes will warn the mailbox owner that she has a
temporary greeting set. This can be a useful reminder when
people return from trips or vacations.
review yes, no This should almost always be set to yes (even though it defaults
to no). People get upset if your voicemail system does not allow
them to review their messages prior to delivering them.
operator yes, no Best practice dictates that you should allow your callers to “zero
out” from a mailbox, should they not wish to leave a message.
Note that an o extension (not “zero,” “oh”) is required in the
exitcon text in order to handle these calls.
sendvoicemail yes, no This allows users to compose messages to other users from
within their mailboxes.
messagewrap no, yes If this is set to yes, when the user has listened to the last
message, pressing next (6) will take him to the first message.
Also, pressing previous (4) when at the first message will take the
user to the last message.
minpassword 6 This option enforces a minimum password length. Note that this
does not prevent users from setting their passwords to something
easy to guess (such as 123456).
listen-control-restart- 2 You can use this setting to customize the replay key.
key
passwordlocation spooldir If you want, you can have mailbox passwords stored in the
spool folder for each mailbox.b One of the advantages of using
the spooldir option is that it will allow you to define file #in clude
statements in voicemail.conf (meaning you can store mailbox
references in multiple files, as you can with, for example, dialplan
code). This is not possible otherwise, because app_voice mail
normally writes password changes to the filesystem, and cannot
update a mailbox password stored outside of either voicemail.
conf or the spool. If you do not use passwordlocation, you will
not be able to define mailboxes outside of voicemail.conf, since
password updates will not happen. Storing passwords in a file in
the specific mailbox folder in the spool solves this problem.
vm-password custom_sound If you want, you can specify a custom sound here to use for the
password prompt in voicemail.
vm-newpassword custom_sound If you want, you can specify a custom sound here to use for the
“Please enter your new password followed by the pound key”
prompt in voicemail.
vm-passchanged custom_sound If you want, you can specify a custom sound here to use for the
“Your password has been changed” prompt in voicemail.
vm-reenterpassword custom_sound If you want, you can specify a custom sound here to use for the
“Please reenter your password followed by the pound key” prompt
in voicemail.
vm-mismatch custom_sound If you want, you can specify a custom sound here to use for the
“The passwords you entered and reentered did not match” prompt
in voicemail.
233 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Value/Example Note


vm-invalid-password custom_sound If you want, you can specify a custom sound here to use for
the “That is not a valid password. Please try again” prompt in
voicemail.
vm-pls-try-again custom_sound If you want, you can specify a custom sound here to use for the
“Please try again” prompt in voicemail.
vm-prepend-timeout custom_sound If you want, you can specify a custom sound here to use when a
user times out while recording a prepend message. The default
prompt is, “then press pound” and follows the vm-pls-try-again
prompt.
listen-controlforward- # You can use this setting to customize the fast-forward key.
key
listen-controlreverse- * You can use this setting to customize the rewind key.
key
listen-control-pausekey 0 You can use this setting to customize the pause/unpause key.
listen-control-stopkey 13456789 You can use this setting to customize the interrupt playback key.
backupdeleted 0 This setting will allow you to specify how many deleted messages
are automatically stored by the system. This is similar to a recycle
bin. Setting this to 0 disables this feature. Up to 9,999 messages
can be stored, after which the oldest message will be erased each
time another message is deleted.
4-8 ‫جدول‬

‫‌های مختلف برای صندوق‬zone ‫ در این بخش می‌توان زمان را بر اساس‬:zonemessage ‫ تنظیمات بخش‬-3
‫ با این قابلیت می‌توان یک‬.‫ تعریف‌شده مرتب شود‬zone ‫ بر اساس‬،‫صوتی تنظیم نمود تا تاریخ دریافت پیام‌ها‬
.‫سرویس صندوق صوتی بین المللی ایجاد کرد‬

‫تعریف صندوق صوتی جدید در استریسک‬


،‫ باید در هر بخش‬،‫ برای ایجاد یک صندوق صوتی در استریســک‬،‫همانطورکــه پیشتر توضیح داده شــد‬
.‫ برای مثال فرض کنید تنظیمات بهصورت زیر باشد‬.‫تنظیمات الزم را انجام دهید‬
;voicemail.conf
[general]
format=wav49|gsm|wav
serveremail=asterisk
attach=yes
skipms=3000
maxsilence=10
silencethreshold=128
maxlogins=3
emaildateformat=%A, %B %d, %Y at %r
pagerdateformat=%A, %B %d, %Y at %r
sendvoicemail=yes

[zonemessages]
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 234

eastern=America/New_York|›vm-received› Q ‹digits/at› IMp


central=America/Chicago|›vm-received› Q ‹digits/at› IMp
central24=America/Chicago|›vm-received› q ‹digits/at› H N ‹hours›
military=Zulu|›vm-received› q ‹digits/at› H N ‹hours› ‹phonetic/z_p›
european=Europe/Copenhagen|›vm-received› a d b ‹digits/at› HM

.‫ باید آن را در کانتکســتهای مورد نظر و دلخواه تعریف و ایجاد کنید‬،‫برای تعریف یک صندوق صوتی‬
‫ فرمت‬.‫[ ایجاد کنیم‬default] ‫بــرای مثال فرض کنیــد بخواهیم یک صندوق صوتــی جدید در کانتکســت‬
:‫تعریف این صندوق صوتی بهصورت زیر خواهد بود‬
;voicemail.conf
[default]
mailbox => password [,full name [,email address [,short email address [,options[|options]]]]]

:‫پارامترها الزم از قرار زیرند‬


.‫ شماره تخصیص داده شده به صندوق صوتی را مشخص می‌کند‬:mailbox ‫پارامتر‬ •
‫ کنترل صندوق صوتی (از راه دور) و شــنیدن پیام‌های‬،‫ رمــز عبور را برای مدیریت‬:password ‫پارامتر‬ •
.‫ضبط شده مشخص می‌کند‬
.‫ نام و نام‌خانوادگی صاحب صندوق صوتی را مشخص می‌کند‬:full name ‫پارامتر‬ •
‫ یک پیام برای این ایمیل ارســال‬،‫ استریســک در زمان دریافت یک پیام جدید‬:email address ‫پارامتر‬ •
.‫ پیام ضبط شده می‌تواند به ایمیل پیوست شود‬.‫می‌کند‬
‫ استریسک به وسیله این پارامتر یک پیام برای ایمیل مشخص شده ارسال‬:short email address ‫پارامتر‬ •
‫ این است که در این حالت پیام ضبط شده به ایمیل پیوست‬email address ‫ تفاوت آن با پارامتر‬.‫می کند‬
.‫ شدن پیام های جدید استفاده خواهد شد‬notification ‫ این پارامتر بیشتر جهت‬.‫نخواهد شد‬
‫ می‌توان تنظیماتی در خصوص نحوه‌ی عملکرد صندوق صوتی تعریف‬،‫ با این پارامتر‬:options ‫پارامتــر‬ •
.‫ مهمترین گزینه‌های مورد قبول برای این پارامتر را نمایش می‌دهد‬5-8 ‫ جدول‬.‫نمود‬

Option Description
attach Whether to attach the voicemail to the notification email versus the pager email. If set to yes,
will attach to the email defined by the email address field.
attachfmt Sets the format to attach to the email. Normally this is the first value defined by the format
option, but you can override that per mailbox by using this option. Option can only be set per
mailbox.
callback If defined, this option will allow the receiver of the email to call back the sender of the voicemail
directly from the Voicemail() application. This option defines which context the call will be sent
from. If not set, calling the sender back will not be permitted.
cidinternalcon This is a very old option from 2004, but essentially, you can define multiple contexts (separated
texts by a comma) that will tell Asterisk to check if the call came from an internal context. If so, it will
play back the person’s name recording instead of saying their extension number. It is unclear if
this option is still valid or functional. Likely best used in the [general] section of voicemail rather
than per mailbox.
235 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Description
delete After sending the voicemail via email, the voicemail is deleted from the server. This option
is useful for users who only want to receive voicemail via email. Valid options are yes or no.
Option can only be set per mailbox.
dialout If defined, option 4 from the advanced menu will allow you to dial out from the Voicemail Main()
application. The argument defines which context the dialing will be performed from. If not
defined, the option to dial out will not be prompted to the caller.
envelope Turns on or off envelope playback prior to playback of the voicemail message. Valid options
are yes or no. Default is yes.
exitcontext The context to exit to when pressing * or 0 from the Voicemail() application. Works in
conjunction with the operator option as well. Must have an extension a in the context forexiting
with *. Must have an extension o in the context for exiting with 0.

forcegreeting Forces the recording of a greeting for new mailboxes. A new mailbox is determined by the
mailbox number and password matching. Valid values are yes or no. Default is no.
forcename Forces the recording of the person’s name for new mailboxes. A new mailbox is determined by
the mailbox number and password matching. Valid values are yes or no. Default is no.
hidefromdir If set to yes, this mailbox will be hidden from the Directory() application. Default is no.
locale Allows you to set the locale for the mailbox in order to control formatting of the date/time
strings. See voicemail.sample.conf for more information.
messagewrap Allows the first and last messages to wrap around; e.g., allow last message to wrap back to
the first on the next message, or first message to wrap to the last message when going to the
previous message. Valid options are yes or no. Default is no.
minpassword Sets the minimum password length. Argument should be a whole number.
nextaftercmd Skips to the next message after pressing the 7 key (delete) or 9 key (save). Valid values are
yes or no. Default is yes.
operator Will allow the sender of a voicemail to hit 0 before, during, or after recording of a voicemail.
Will exit to the o extension in the same context, or the context defined by the exitcontext
option. Valid options are yes or no. Default is no.
passwordlocation By default, the password for voicemail is stored in the voicemail.conf file, and modified by
Asterisk whenever the password changes. This may not be desirable, especially if you
want to parse the password from an external location (or script). The alternate option for
passwordlocation is spooldir, which will place the password for the voicemail user in a file
called secret.conf in the user’s voicemail spool directory. Valid options are voicemail.conf and
spooldir. The default option if voicemail.conf.
review When enabled, will allow the user recording a voicemail message to re-record their message.
After pressing the # key to save their voicemail, they’ll be prompted whether they wish to re-
record or save the message. Valid options are yes or no. Default is no.
saycid If enabled, and a prompt exists in /var/spool/asterisk/voicemail/recordings/callerids, then
that file will be played prior to the message, playing the file instead of saying the digits of the
callerID number. Valid options are yes or no. Default is no.
sayduration Determines whether to play the duration of the message prior to message playback. Valid
options are yes or no. Default is yes.
saydurationm Allows you to set the minimum duration to play (in minutes). For example, if you set the value
to 2, you will not be informed of the message length for messages less than 2 minutes long.
Valid values are whole numbers. Default is 2.
searchcontexts For applications such as Voicemail(), VoicemailMain(), and Directory(), the
voicemail context is an optional argument. If the voicemail context is not specified, then the
default is to only search the default context. With this option enabled, all contexts will be
searched. This comes with a caveat that, if enabled, the mailbox number must be unique
across all contexts—
otherwise there will be a collision, and the system will not understand which mailbox to use.
Valid options are yes and no. Default is no.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 236

Option Description
sendvoicemail Allows the user to compose and send a voicemail message from within the VoicemailMain()
application. Available as option 5 under the advanced menu. If this option is disabled, then
option 5 in the advanced menu will not be prompted. Valid options are yes or no. Default is no.
tempgreetwarn Enables a notice to the user when their temporary greeting is enabled. Valid options are yes or
no. Default is no.
tz Sets the time zone for a voicemail user (or globally). See /usr/share/timezone for different
available time zones. Not applicable if envelope=no.
volgain The volgain option allows you to set volume gain for voicemail messages. The value is in
decibels (dB). The sox application must be installed for this to work.
5-8 ‫جدول‬

‫ این تعریف بهصورت زیر‬،‫ تعریــف کنیم‬۱۲۳4 ‫بــرای مثال چنانچه بخواهیم یک صندوق صوتی با شــماره‬
:‫است‬
;voicemail.conf
[default]
1234 => 4242,Example Mailbox,root@localhost

[voicemail]
6713 => 123123,Mojtaba Esfandiari.S, mespio@gmail.com
6033 => 123123,Mojtaba Najafi, seyedmnmf@gmail.com

:‫ وارد محیط کامندالین شوید و دستورات زیر را اجرا کنید‬،‫برای مشاهده صندوقهای صوتی‬
CLI> voicemail reload
CLI> voicemail show users

.‫خروجی دستورات بهصورت زیر خواهد بود‬

Context Mbox User Zone NewMsg


default 1234 Example Mailbox 0
voicemail 6713 Mojtaba Esfandiari.S 0
voicemail 6033 Mojtaba Najafi 0
3 voicemail users configured.
CLI>

‫ زمان ثبت فایل و کالر آی دی شخص تماس گیرنده‬،‫اگر خواســته باشــیم در زمان بررســی صندوق صوتی‬
:‫ به صورت زیر عمل کنیم‬،‫ باید در زمان تعریف صندوق صوتی‬،‫پخش شود‬
[voicemail]
6713 => 123123,Mojtaba Esfandiari.S, mespio@gmail.com,,saycid=yes|envelope=yes
6033 => 123123,Mojtaba Najafi, seyedmnmf@gmail.com,,saycid=yes|envelope=yes

‫استفاده از صندوق صوتی در برنامه‌نویسی استریسک‬


.‫دو دستور مهم برای کار با صندوق صوتی وجود دارد که در ادامه بررسی میشوند‬ ‫در استریسک‬
‫‪237‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫دستور ‪VoiceMail‬‬
‫با این دستور میتوان صندوق صوتی مورد نظر را فراخوانی کرد‪ .‬فرمت استفاده از این دستور بهصورت زیر‬
‫است‪:‬‬
‫‪CLI> core show application VoiceMail‬‬
‫]‪[Syntax‬‬
‫)]‪VoiceMail(mailbox[@context][&mailbox[@context][&...]][,options‬‬

‫مهمترین آپشنهای مورد استفاده در این دستور عبارتند از‪:‬‬


‫• ‪ :b‬در این حالت به استریسک فرمان داده میشود که پیام مشغولی خط پخش شود‪.‬‬
‫• ]‪ : d[c‬چنانچه عددی وارد شــود‪ ،‬این عدد بهعنوان یک شــماره تلقی میشود و به کانتکست تعیینشده‬
‫منتقل میشود‪.‬‬
‫• ‪ :u‬در این حالت به استریسک فرمان داده میشود که پیام در دسترس نبودن پخش شود‪.‬‬
‫• ‪ :U‬با این گزینه تعیین میکنیم که این پیام‪ ،‬یک پیام فوری است و با برچست ‪ Urgent‬مشخص میشود‪.‬‬
‫• ‪ :s‬با این گزینه پیام خوشآمدگویی و راهنمای گذاشتن پیام برای شخص تماسگیرنده پخش نخواهدشد‪.‬‬
‫برای مثال برنامه زیر را در استریسک ببینید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 6713,1,NoOp‬‬
‫)‪same => n,Dial(SIP/Phone_1,20‬‬
‫)‪same => n,VoiceMail(6713@voicemail,u‬‬

‫در این مثال اگر کاربر ‪ Phone_1‬تماس را پس از مدت ‪ ۲۰‬ثانیه پاسخ ندهد‪ ،‬تماس به سمت صندوق صوتی‬
‫تعریفشده منتقل میشود‪ .‬اکنون برنامه را کمی توسعه داده و بهصورت زیر تغییر میدهیم‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 6713,1,NoOp‬‬
‫)‪same => n,Dial(SIP/Phone_1,10‬‬
‫)‪same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy,1:unavail,1‬‬

‫)‪exten => unavail,1,VoiceMail(6713@voicemail,u‬‬


‫)(‪same => n,Hangup‬‬

‫)‪exten => busy,1,VoiceMail(6713@voicemail,b‬‬


‫)(‪same => n,Hangup‬‬

‫میتوان کد طوالنی باال را بهصورت زیر هم نوشت‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 6713,1,NoOp‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪238‬‬

‫)‪same => n,Dial(SIP/Phone_1,10‬‬


‫)})‪same => n,Voicemail(6713@voicemail,${IF($["${DIALSTATUS}" = "BUSY"]?b:u‬‬
‫)(‪same => n,Hangup‬‬

‫دستور ‪VoiceMailMain‬‬
‫در استریسک این قابلیت وجود دارد که کاربران بتوانند از راه دور‪ ،‬پیامهای صندوق صوتی خود را مدیریت‬
‫و کنترل کنند‪ .‬دســتور ‪ VoiceMailMain‬این امکان را فراهم میکند‪ .‬قابلیتهایی که این دســتور در اختیار‬
‫کاربران میگذارد به شرح ذیل است‪:‬‬
‫ • امکان شنیدن پیام‌های جدید؛‬
‫ • امکان شنیدن مجدد پیام‌های قبلی؛‬
‫ • امکان حذف پیام از صندوق صوتی؛‬
‫ • امکان ضبط پیام خوش‌آمد‌گویی جدید؛‬
‫ • امکان عوض‌کردن رمز عبور برای صندوق‌صوتی‪.‬‬
‫فرمت استفاده از این دستور به این صورت خواهد بود‪:‬‬
‫‪CLI> core show application VoiceMailMain‬‬
‫]‪[Syntax‬‬
‫)]‪VoiceMailMain([mailbox][@context][,options‬‬

‫برای مثال برنامه زیر این قابلیت را برای کاربران فراهم میکند تا بتوانند صندوق صوتی خود را بررسی کنند‪.‬‬
‫]‪[services‬‬
‫)(‪exten => *98,1,NoOp‬‬
‫)(‪same => n,VoiceMailMain‬‬

‫]‪[LocalSets‬‬
‫‪include => services‬‬

‫بررسی فایل سیستم صندوق صوتی در استریسک‬


‫بهصورت پیش فرض پیامهای ضبطشده در صندوق صوتی در مسیر زیر ذخیره میشوند‪.‬‬
‫>‪#ls /var/spool/asterisk/voicemail/<context>/<mailbox‬‬

‫در این مسیر پیامهای صوتی با فرمتهای ‪ wav‬و ‪ gsm‬ذخیره میشوند‪ .‬ساختار یک پوشه در صندوق صوتی‬
‫بهصورت زیر است‪:‬‬
‫‪/var/spool/asterisk/voicemail/default/1234‬‬
‫‪./INBOX‬‬
‫‪./Old‬‬
‫‪ ./Old/msg0000.WAV‬‬
‫‪ ./Old/msg0000.txt‬‬
‫‪ ./Old/msg0001.WAV‬‬
‫‪239‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫‪ ./Old/msg0001.txt‬‬
‫‪./Urgent‬‬
‫‪./busy.WAV‬‬
‫‪./unavail.WAV‬‬
‫‪./greet.WAV‬‬

‫صندوق صوتی در استریســک و تنظیمات آن تا اینجا بررســی شد‪ .‬گاهی باید یک سیستم تلفنی استریسک‬
‫را بــه گونــهای تنظیم و پیکربندی کنیم که بتواند فقط در قالب یک سیســتم صندوق صوتی فعالیت کند‪ .‬به‬
‫عبارت دیگر در صورت لزوم‪ ،‬برای تقسیم بار ترافیکی ورودی در یک شبکه ویپ‪ ،‬میتوان از سیستم صندوق‬
‫صوتی بهصورت جداگانه استفاده کرد‪ .‬برای روشنتر شدن موضوع‪ ،‬شکل ‪ 4-8‬را ببینید‪.‬‬

‫شکل ‪4-8‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در این شــکل کاربر)‪ (SIP Telephone‬مســتقیما با سرور ‪ Proxy Server‬در‬
‫ارتباط اســت‪ .‬ســرور صندوق صوتی اینجا بهصورت مجزا طراحی و پیکربندی شدهاســت‪ .‬در صورتی که‬
‫کاربر بخواهد از صندوق صوتی اســتفاده کند‪ ProxyServer ،‬آن را به سمت سرور صندوق صوتی هدایت‬
‫میکند‪.‬‬
‫در طراحی شــبکههای ویپ این نکته را مد نظر داشــته باشید که برای توزیع مناسب تماسها و ترافیک‪،‬‬
‫بهتر است اجزا را بهصورت مستقل طراحی و پیکربندی کنید‪.‬‬

‫آشنایی با ‪ Feature Code‬ها در استریسک‬


‫اســتفاده از ‪Feature Code‬ها در استریسک‪ ،‬از جمله قابلیتهایی است که میتواند در سناریوها مفید باشند‬
‫که در ادامه با مفهوم و کاربرد آنها آشنا میشوید‪.‬‬
‫هنگامی که یک تماس وارد سیســتم تلفنی استریسک میشود‪ ،‬استریسک آن را مسیریابی میکند تا به‬
‫مقصد مورد نظر برسد‪ .‬پس از اینکه تماس پاسخ داده شد‪ ،‬عملیات مسیریابی مجدد ازطریق استریسک برای‬
‫‪1‬‬

‫‪1- endpoint‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪240‬‬

‫تماس مقدور نخواهد بود مگر اینکه یکی از دو حالت زیر اتفاق بیافتد‪:‬‬
‫‪ -۱‬تماس انتقال‪ 1‬یابد‪ .‬در این حالت استریسک تماس را دوباره مسیریابی میکند تا به مقصد برسد‪.‬‬
‫‪ -۲‬استفاده از ‪Feature Code‬ها باعث میشود که عملیات مورد نظر برای کانال مورد نظر اجرا شود‪.‬‬
‫در ادامه به معرفی انواع ‪Features Code‬ها میپردازیم‪.‬‬

‫‪Call Parking‬‬
‫اصطــالح پارک کــردن تماس ها این امکان را میدهد که تماس را در مکانــی بهصورت موقت نگهداریم‬
‫تا بعدا بتوانیم پاســخ دهیم ‪ .‬همانطورکه در شــکل ‪ ۵-8‬مالحظه میکنید‪ Caller ،‬با سیستم تلفنی استریسک‬
‫تماس میگیرد و به کاربر ‪ UAC1‬متصل میشود‪.‬‬

‫شکل ‪5-8‬‬

‫سپس کاربر ‪ UAC1‬با استفاده از قابلیت ‪ Call Parking‬تماس را پارک میکند )شکل ‪.(۶-8‬‬

‫شکل ‪6-8‬‬

‫تماس در ‪ Parking Lot‬منتظر میماند )شکل ‪.(7-8‬‬

‫‪1- Transfer‬‬
‫‪241‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫شکل ‪7-8‬‬

‫کاربر ‪ UAC2‬میتواند ‪ Caller‬را از پارک بردارد و با او صحبت کند )شکل ‪.(8-8‬‬

‫شکل ‪8-8‬‬

‫در نهایت تماس برقرار میشود و دو نفر میتوانند با هم مکالمه داشتهباشند )شکل ‪.(۹-8‬‬

‫شکل ‪9-8‬‬

‫در استریسک برای استفاده از ‪ Call Parking‬باید به کمک فایل زیر تنظیمات و پیکربندی را انجام دهید‪:‬‬
‫‪#vim /etc/asterisk/features.conf‬‬
‫]‪[general‬‬
‫‪parkext => 700‬‬
‫‪parkpos => 701-720‬‬
‫‪context => parkedcalls‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪242‬‬

‫‪parkingtime => 45‬‬


‫‪comebacktoorigin=yes‬‬

‫پارامترهای الزم عبارتند از‪:‬‬


‫پارامتر ‪ : parkext‬با این شــماره‌ی داخلی‪ ،‬می‌توان تماس‌هایی که در ‪ Parking lot‬منتظر هستند را پاسخ داد‪.‬‬
‫مقدار آن هر چیزی می‌تواند باشد‪.‬‬
‫پارامتر ‪ : parkpos‬با این پارامتر‪ ،‬تعداد ‪‌Parking lot‬ها تعیین می‌شــوند‪ .‬اینجا ‪ 20‬عدد ‪ Parking lot‬داریم اما‬
‫می‌توان تعداد آن‌ها را افزایش داد‪.‬‬
‫پارامتر ‪ : context‬نام کانتکست مورد نظر را مشخص می‌کند‪.‬‬
‫پارامتر ‪ :parkingtime‬حداکثر زمان انتظار در ‪ parking lot‬را مشخص می‌کند‪.‬‬
‫پارمتر ‪ :comebacktoorigin‬اگر بعد از ســپری شــدن حداکثر زمان تعریف شده در ‪ ،parkingtime‬کسی‬
‫تماس را پاسخ ندهد‪ ،‬ارتباط با کاربری که تماس را پارک کرده‌است‪ ،‬برقرار می‌شود‪.‬‬
‫بعد از تعریف و پیکربندی ‪ Call Parking‬باید تغییرات زیر را در برنامه استریسک اعمال کنید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫‪include => parkedcalls‬‬

‫در این حالت اگر کسی با شما تماس بگیرد و شما آن را به شماره ‪ 7۰۰‬فوروارد کنید‪ ،‬تماس آن شخص‬
‫بــه ‪ Parking lot‬منتقل میشــود و آنجا منتظر میماند‪ .‬با دســتور زیر میتوانید وضعیــت ‪Parking lot‬ها را‬
‫بررسی کنید‪.‬‬

‫‪CLI> parking show default‬‬


‫‪Parking Lot: default‬‬
‫‪------------------------------------------------------------------------‬‬
‫‪Parking Extension : 700‬‬
‫‪Parking Context : parkedcalls‬‬
‫‪Parking Spaces : 701-720‬‬
‫‪Parking Time‬‬ ‫‪: 45 sec‬‬
‫‪Comeback to Origin : yes‬‬
‫)‪Comeback Context : parkedcallstimeout (comebacktoorigin=yes, not used‬‬
‫‪Comeback Dial Time : 30 sec‬‬
‫‪MusicOnHold Class :‬‬
‫‪Enabled‬‬ ‫‪: yes‬‬
‫‪Dynamic‬‬ ‫‪: no‬‬
‫‪Parked Calls‬‬
‫‪------------‬‬
‫‪Space‬‬ ‫‪: 701‬‬
‫‪Channel‬‬ ‫‪: SIP/101-00000013‬‬
‫‪Parker Dial String : SIP/100‬‬
‫‪243‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫ترنسفر کنید‪.‬‬ ‫همانطورکه مالحظه میکنید تماس را باید به شماره ‪7۰۰‬‬


‫یک راه دیگر برای اســتفاده از ‪ Call Parking‬اســتفاده از ‪Feature Code‬هاست‪ .‬در این حالت‪ ،‬هنگام‬
‫مکالمه میتوان با گرفتن یک کد‪ ،‬تماس را به ســمت ‪ Parking lot‬منتقل نمود‪ .‬به این منظور باید تغییرات‬
‫زیر را در فایل ‪ features.conf‬انجام دهید‪.‬‬
‫‪;features.conf‬‬
‫]‪[featuremap‬‬
‫‪parkcall => #72‬‬

‫ســپس هنگام فراخوانی دســتور ‪ Dial‬در برنامهنویســی استریسک‪ ،‬باید از آپشــنهای ‪ k‬یا ‪ K‬بهصورت زیر‬
‫استفاده کنید‪.‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 100,1,Dial(SIP/100,20,kK‬‬
‫)‪exten => 101,1,Dial(SIP/101,20,kK‬‬

‫در این حالت نیازی نیســت کانتکســت ‪ parkedcalls‬را به کانتکســت جاری اضافه کنیــد‪ .‬بنابراین‪ ،‬بعد از‬
‫‪ 7۲#‬را )بدون فشردن کلید ترنسفر(‬ ‫‪ reload‬کردن استریســک‪ ،‬چنانچه در ضمن مکالمه‪ ،‬هر کاربر شــماره‬
‫شمارهگیری کند‪ ،‬عملیات ‪ Call Parking‬میشود‪.‬‬

‫انواع مدل‌های انتقال تماس‌‬


‫‪1‬‬

‫دو روش برای انتقال تماس وجود دارد‪:‬‬


‫الف) ‪ :Blind Transfer‬برای تشریح کامل این نوع ترنسفر‪ ،‬شکل‌های زیر را ببینید‪.‬‬
‫‪ -۱‬ابتدا مشترک با کاربر اول مکالمه میکند )شکل ‪.(۱۰-8‬‬

‫شکل ‪10-8‬‬

‫‪ -۲‬سپس کاربر اول تماس را برای کاربر دوم ترنسفر میکند‪).‬شکل ‪(۱۱-8‬‬

‫‪1- Transfer‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪244‬‬

‫شکل ‪11-8‬‬

‫‪ -۳‬تماس بالفاصله به کاربر جدید منتقل میشود‪).‬شکل ‪(۱۲-8‬‬

‫شکل ‪12-8‬‬

‫ب( ‪ :Attended Transfer‬شکلهای زیراین نوع ترانسفز را بهطور کامل تشریح کردهاند‪.‬‬
‫‪ -۱‬ابتدا مشترک با کاربر اول مکالمه میکند‪).‬شکل ‪(۱۳-8‬‬

‫شکل ‪13-8‬‬

‫‪ -۲‬ســپس کاربــر اول تماس را برای کاربر دوم ترنســفر میکند‪ .‬در این حالت مشــترک به وضعیت انتظار‬
‫میرود و باید منتظر بماند )شکل ‪.(۱4-8‬‬
‫‪245‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫شکل ‪14-8‬‬

‫‪ -۳‬کاربر دوم گوشــی را برمــیدارد و با کاربر اول مکالمه میکند‪ .‬در این حالت هم مشــترک همچنان در‬
‫حالت انتظار بهسر میبرد )شکل ‪.(۱۵-8‬‬

‫شکل ‪15-8‬‬

‫‪ -4‬چنانچه کاربر اول گوشی خود را بگذارد‪ ،‬مشترک از حالت انتظار خارج و به کاربر دوم متصل میشود‪.‬‬
‫)شکل ‪.(۱۶-8‬‬

‫شکل ‪16-8‬‬

‫برای فعال کردن این روشها باید تغییرات زیر را در استریسک ایجاد کنید‪.‬‬
‫ابتدا فایل ‪ features.conf‬را باز و تغییرات زیر را اعمال کنید‪:‬‬
‫‪;features.conf‬‬
‫]‪[featuremap‬‬
‫‪blindxfer => #1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 246

atxfer => *2

.‫ بهصورت زیر استفاده کنید‬T ‫ یا‬t ‫ از آپشنهای‬،‫ در برنامهنویسی استریسک‬Dial ‫هنگام فراخوانی دستور‬
[LocalSets]
exten => 100,1,Dial(SIP/100,20,tT)
exten => 101,1,Dial(SIP/101,20,tT)

‫ فعال میشــود و اگر از کد‬Blind Transfer ‫ عملیات‬،‫ اســتفاده کنید‬۱# ‫اکنون اگر در زمان مکالمه از کد‬
‫هایی که‬Feature Code ‫ انــواع‬۶-8 ‫ جدول‬.‫ فعال میشــود‬Attended Transfer ‫ عملیات‬،‫* اســتفاده کنید‬۲
.‫بهصورت پیشفرض در استریسک تعریف شدهاند را نشان میدهد‬

Option Value/Example Notes Dial()/Queue()


Flags
blindxfer #1 Invokes a blind (unsupervised) transfer T, t
disconnect *0 Hangs up the call H, h
automon *1 Starts recording of the current call using the Moni W, w
tor() application (pressing this key sequence a second time
stops the recording)
atxfer *2 Performs an automated transfer T, t
parkcall #72 Parks a call K, k
automixmon *3 Starts recording of the current call using the MixMonitor() X, x
application (pressing this key sequence again stops the
recording)

6-8 ‫جدول‬

1
‫ های پویا در استریسک‬Feture Code ‫استفاده از‬
‫های جدیدی تعریف‬Feature Code ،‫یکی دیگر از قابلیتهای استریسک این است که میتوان بسته به نیاز‬
‫ با‬،‫ نگاشــت کرد و در زمان مورد نیاز‬،‫ در واقع میتوان اجرای برخی دســتورات را به کدهای خاصی‬.‫کرد‬
.‫ آن دستورات را اجرا کرد‬،‫شمارهگیری کد مورد نظر‬
.‫فرمت تعریف این قابلیت در استریسک بهصورت زیر است‬
[applicationmap]
<FeatureName> = <DTMF_sequence>,<ActivateOn>[/<ActivatedBy>],<Application>[,<AppAr
guments>[,MOH_Class]]

:‫پارامترها‬
.‫ برای استفاده از آن یک نام به آن بدهید‬:FeatureName ‫پارامتر‬
.‫ شماره تعریف‌شده برای اجرای این ویژگی است‬:DTMF_Sequence ‫پارامتر‬
:‫ این پارامتر دو مقدار می‌تواند به خود بگیرد‬:ActiveOn ‫پارامتر‬
1- Application Map (Custom Dynamic Features)
‫‪247‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫ ‪ :self -1‬منظور همان کانالی است که این ‪ Feature‬برای آن اجرا می‌شود‪.‬‬


‫‪ :peer -۲‬منظور کانال طرف مقابل است که این ‪ Feature‬برای آن اجرا میشود‪.‬‬
‫پارامتر ‪ :ActivateBy‬این پارامتر سه مقدار می‌تواند به خود بگیرد‪:‬‬
‫‪ :caller -۱‬یعنی ‪ Caller‬میتواند آن را فراخوانی کند‪.‬‬
‫‪ :callee -۲‬یعنی ‪ Callee‬میتواند آن را فراخوانی کند‪.‬‬
‫‪ :both -۳‬یعنی ‪ Caller‬و ‪ Callee‬هر دو میتوانند آن را فراخوانی کنند‪.‬‬
‫پارامتر ‪ :Application‬نام برنامه‌ای اســت که قرار است به‌وسیله این ‪ Feature‬جدید اجرا شود‪.‬اگر این برنامه‬
‫به آرگومان هایی نیاز داشته باشد توسط پارامتر ‪ AppArguments‬مشخص می شود‪.‬‬
‫بهعنوان مثال ‪ Feature‬جدید زیر را تعریف میکنیم‪.‬‬
‫‪;features.conf‬‬
‫]‪[applicationmap‬‬
‫‪playdemo => #9,self/callee,Playback,demo-thanks‬‬

‫در این تعریف مشــخص کردهایم که اگر کد ‪ #9‬را شــماره گیری شــود‪ ،‬فایل صوتی ‪ demo-thanks‬برای‬
‫‪ callee‬پخش می شــود‪ .‬نام آن را ‪ playdemo‬گذاشــتیم‪ .‬اکنون برای اســتفاده از آن در استریســک‪ ،‬باید‬
‫بهصورت زیر اقدام کنید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 100,1,Set(__DYNAMIC_FEATURES=playdemo‬‬
‫)‪same => n,Dial(SIP/100,20,tTkK‬‬
‫)‪exten => 101,1,Set(__DYNAMIC_FEATURES=playdemo‬‬
‫)‪same => n,Dial(SIP/101,20,tTkK‬‬
‫)‪exten => 102,1,Set(__DYNAMIC_FEATURES=playdemo‬‬
‫)‪same => n,Dial(SIP/102,20,tTkK‬‬

‫پس از انجام تغییرات فوق‪ ،‬استریســک را مجددا ‪ reload‬کنید‪ .‬بعد از ایجاد تماس‪ ،‬اگر کد ‪ #9‬گرفته شود‪،‬‬
‫پیام صوتی ‪ demo-thanks‬پخش میشــود‪ .‬میتوانید از این قابلیتها در استریسک استفاده کنید و ‪Feature‬‬
‫‪code‬های مختلفی برای سیستم تلفنی استریسک طراحی کنید‪.‬‬

‫استفاده از قابلیت کنفرانس‪ 1‬در استریسک‬


‫کنفرانسها در استریســک این قابلیت را فراهم میآورند که بیشتر از دو مشترک‪ ،‬بتوانند در یک کنفرانس‬
‫شرکت و با هم گفتگو کنند‪ .‬از جمله ویژگیهای کنفرانس میتوان به موارد زیر اشاره کرد‪:‬‬
‫ • قابلیت افزودن عضو جدید به کنفرانس و یا حذف عضو فعلی از کنفرانس؛‬

‫‪1- Confferance‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪248‬‬

‫ • قابلیت استفاده از رمز عبور برای عضو شدن در کنفرانس؛‬


‫ • مدیریت کنفرانس؛‬
‫ • فعال‌کردن یک نفر برای سخنرانی در کنفرانس و به‌طور همزمان غیرفعال‌کردن سایر اعضای کنفرانس‪.‬‬
‫درنسخههای جدیدتر استریسک‪ ،‬دو دستور برای استفاده از کنفرانس وجود دارد‪:‬‬
‫‪ (۱‬استفاده از دستور ‪MeetMe‬‬
‫‪ (۲‬استفاده از دستور ‪ConfBridge‬‬
‫در ادامه این دو دستور را بررسی میکنیم‪.‬‬

‫استفاده از دستور ‪ MeetMe‬در استریسک‬


‫برای ایجاد و پیکربندی یک کنفرانس ابتدا فایل ‪ meetme.conf‬را از مسیر زیر باز کنید‪.‬‬
‫‪# vim /etc/asterisk/meetme.conf‬‬

‫فرمت تعریف یک کنفرانس در این فایل بهصورت زیر اســت‪ .‬برای این منظور باید در کانتکست ]‪[rooms‬‬
‫آن را تعریف کنید‪.‬‬
‫]‪[rooms‬‬
‫]‪conf => confno[,pin][,adminpin‬‬

‫پارامترهای الزم‪:‬‬
‫پارامتر ‪ :confno‬با این پارامتر شماره کنفرانس را مشخص می‌کنیم‪.‬‬
‫پارامتر ‪ :pin‬می‌توان برای ورود به یک کنفرانس‪ ،‬رمز عبور تعیین کرد‪.‬‬
‫پارامتر ‪ :adminpin‬مدیر کنفرانس می‌تواند با رمز تعیین‌شده‌ای‪ ،‬وارد سیستم شود‪.‬‬
‫برای مثال فرض کنید قرار است یک کنفرانس جدید با شماره ‪ ۱۵۱۵‬در سیستم تلفنی استریسک ایجاد‬
‫کنیم‪ .‬برای این منظور باید تغییرات زیر را اعمال کنیم‪.‬‬
‫‪;meetme.conf‬‬
‫]‪[rooms‬‬
‫‪conf => 1515,123123,123321‬‬

‫برای استفاده از کنفرانس در استریسک‪ ،‬برنامه زیر را بنویسید‪.‬‬


‫‪;extensions.conf‬‬
‫]‪[ConferenceRooms‬‬
‫)‪exten => 1515,1,MeetMe(1515,i,123123‬‬

‫]‪[LocalSets‬‬
‫‪include => ConferenceRooms‬‬

‫در این حالت‪ ،‬چنانچه کاربری شــماره ‪ ۱۵۱۵‬را شــماره گیری کند‪ ،‬ابتدا رمز عبور کنفرانس از او پرســیده‬
‫‪249‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫میشــود و در صورت تایید رمز‪ ،‬کاربر وارد کنفرانس میشــود‪ .‬فرمت استفاده از این دستور بهصورت زیر‬
‫است‪:‬‬
‫‪CLI> core show application MeetMe‬‬
‫]‪[Syntax‬‬
‫)]]‪MeetMe([confno][,options[,pin‬‬

‫مهمترین آپشنها در دستور ‪ MeetMe‬در زیر توضیح داده شده است‪:‬‬


‫ • ‪ : a‬با این آپشن‪ ،‬وضعیت ‪( admin‬مدیر کنفرانس) فعال می‌شود‪.‬‬
‫ • ‪ : i‬با این آپشن‪ ،‬اعالن ورود موفقیت‌آمیز به کنفرانس برای کاربر پخش می‌شود‪.‬‬
‫ • ‪ : l‬با این آپشن‪ ،‬کاربر تنها به‌صورت شنونده در کنفرانس حضور خواهد‌داشت‪.‬‬

‫استفاده از دستور ‪ MeetMeCOUNT‬در استریسک‬


‫در استریسک این قابلیت وجود دارد که بتوان افراد داخل یک کنفرانس را شمارش کرد‪ .‬این دستور تعداد‬
‫شــرکتکنندگان در کنفرانس را شــمارش و پخش میکند‪ .‬راهنمای اســتفاده از این دستور بهصورت زیر‬
‫است‪.‬‬
‫‪CLI> core show application MeetMeCOUNT‬‬
‫]‪[Syntax‬‬
‫)]‪MeetMeCOUNT(confno[,var‬‬

‫مثال‪ (۱‬فرضکنید قرار باشــد اعضای یک کنفرانس را شمارش کنیم‪ .‬برای این منظور از دستور زیر استفاده‬
‫میکنیم‪:‬‬
‫‪;extensions.conf‬‬
‫)(‪exten => 1516,1,NoOp‬‬
‫)‪same => n,Playback(conf-thereare‬‬
‫)‪same => n,MeetMeCOUNT(1515‬‬
‫)‪same => n,Playback(conf-peopleinconf‬‬

‫مثال‪ (۲‬فرض کنید یک کنفرانس با ظرفیت ‪ ۱۰‬نفر بهصورت زیر تعریف کردهباشــیم‪ .‬با وارد شــدن هر نفر‬
‫به کنفرانس‪ ،‬یک نفر به افراد حاضر در کنفرانس اضافه میشــود‪ .‬پس از اینکه تعداد افراد حاضر به ‪ ۱۰‬نفر‬
‫رســید‪ ،‬از ورود افراد بیشــتر به کنفرانس جلوگیری میشــود‪ .‬در این برنامه از تکنیک متغیرهای سراسری و‬
‫ماکرو استفاده میشود‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[globals‬‬
‫‪CONFMAX => 10‬‬

‫]‪[ConferenceRooms‬‬
‫))‪exten => 1517,1,Macro(MyConf,1515‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪250‬‬

‫]‪[LocalSets‬‬
‫‪include => ConferenceRooms‬‬

‫]‪[macro-MyConf‬‬
‫)‪exten => s,1,MeetMeCOUNT(${MACRO_EXTEN},COUNT‬‬
‫)‪same => n,GotoIf($[${COUNT} >= ${CONFMAX}]?full‬‬
‫)}‪same => n,MeetMe(${MACRO_EXTEN‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(full),BackGround(conf-full‬‬
‫‪same => n,Hangup‬‬

‫استفاده از دستور ‪ConfBridge‬‬


‫دســتور ‪ Confbridge‬از دیگر دستورهای مهم درجهت استفاده از قابلیت کنفرانس در استریسک است‪ .‬در‬
‫واقع از استریسک نسخهی ‪ ۱۰‬به بعد‪ ،‬استفاده از این دستور به جای دستور ‪ MeetMe‬توصیه شد‪.‬‬
‫یکی از چالشها و نقاط ضعف دســتور ‪ ،MeetMe‬اســتفاده از ماژول ‪ res_timing_dahdi‬برای ایجاد‬
‫همزمانی میان کلیه کانالها در کنفرانس اســت‪ .‬از این رو‪ ،‬چنانچه در یک سیســتم تلفنی استریسک‪ ،‬نیازی‬
‫به اســتفاده از ماژول ‪ DAHDI‬نداشته باشــیم‪ ،‬به اجبار برای استفاده از کنفرانس و دستور ‪ MeetMe‬باید آن‬
‫را نصبکنیم‪ .‬پس اگر در یک سیستم تلفنی استریسک‪ ،‬از ماژول ‪ res_timing_dahdi‬استفاده نکردهباشیم‪،‬‬
‫برای برقراری کنفرانس باید دستور ‪ ConfBridge‬را بکار ببریم‪ .‬برای این منظور از فایل ‪confbridge.conf‬‬
‫در مسیر زیر استفاده میکنیم‪.‬‬
‫‪# vim /etc/asterisk/confbridge.conf‬‬

‫تنظیمات پیشفرض و سادهی آن بهصورت زیر است‪:‬‬


‫‪;confbridge.conf‬‬
‫]‪[general‬‬

‫]‪[default_user‬‬
‫‪type=user‬‬

‫]‪[default_bridge‬‬
‫‪type=bridge‬‬

‫عملکرد این تنظیمات از قرار زیر هستند‪:‬‬


‫• بخــش [‪ :]default_user‬این بخش مربوط به تعریف سیاســت‌های کاربرانی اســت که می‌خواهند از‬
‫کنفرانس اســتفاده کنند‪ .‬در این بخش می‌توان سیاســت‌هایی تعریف کرد و هنگام اضافه شــدن اعضا به‬
‫کنفرانس‪ ،‬این سیاســت‌ها را روی آنهــا اعمال نمود‪ .‬جدول ‪ 7-8‬انواع پارامترهــای قابل تعریف در این‬
‫بخش را نشان می‌دهد‪.‬‬
251 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Description
admin Determines if the user is marked as an administrator of the conference. Users marked as
administrators can be given different options only available to administrators in the user
menu. The menus are defined in confbridge.conf and selected when the ConfBridge()
application is called from the dialplan. Available options are yes or no. Default is no.
marked Sets whether user in this profile should be marked or not. Used to start a conference when
waiting on a marked user. See wait_marked and end_marked. Available options are yes or
no. Default is no
startmuted Sets users in this profile as muted when initially joining the conference. Available options
are yes or no. Default is no.
music_on_hold_when_ Determines whether MOH should be played when only one conference participant exists,
empty or when the conference is waiting on a marked user. Available options are yes or no.
Default is no.
music_on_hold_class Sets which MOH class should be used. Default value is default.
quiet If enabled, this option will limit the sounds played into the conference, such as join sounds
and user announcements. Available options are yes or no. Default is no
announce_user_count If enabled, the number of users in the conference are announced to the joining participant
prior to entering the conference. Available options are yes or no. Default is no.
announce_user_count_ Used for announcing the participant count to all members of the conference. If set to a
all number, then the announcement is only played when the number of participants is above
the set number. Available options are yes, no, or a whole number. Default is no
announce_only_user If enabled, a prompt will be played when the first participant of a conference joins, notifying
they are the only member of the conference. Available options are yes or no. Default is yes.
wait_marked If enabled, the participant of the conference must wait for a marked user to join. Available
options are yes or no. Default is no.
end_marked Determines if remaining users after the last marked user leaves the conference are
removed from the conference. Available options are yes or no. Default is no.
dsp_drop_silence When enabled, Asterisk will drop what it detects as silence from the conference, drastically
deducing the buildup of background noise in the conference. Recommended for large
conferences where background noise can become a problem. Available options are yes or
no. Default is no.
dsp_talking_ A value in milliseconds—the length of time sound has remained above the baseline value
threshold the DSP has established. The value should not be changed unless you are familiar with the
internals of how this number can affect your conference. See the conf bridge.conf.sample
file in the contribs directory of your Asterisk source for more information
dsp_silence_ Similar to dsp_talking_threshold, but looking for silence. Value in milliseconds. Not
threshold recommended to be tuned.
talk_detection_ If enabled, a notification of when a speaker begins and ends talking is sent as an event
events over AMI. Available options are yes or no. Default is no.
denoise The denoise option is useful if you’re using the speex codec, and the talker has an elevated
level of background noise. When enabled, this option will attempt to remove background
noise before the audio is mixed into the conference, while preserving the desired speech
audio. This option should not be confused with dsp_drop_silence. Additionally, this option
does come at a slight performance hit. Available options are yes or no. Default is no
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 252

Option Description
jitterbuffer If enabled, then the jitterbuffer will be enabled on the user’s audio channel prior to mixing.
This is desirable in that it can help smooth out the audio played into the conference
bridge, at the expense of a slight delay. This option utilizes the JITTER BUFFER() dialplan
function’s adaptive mode. If fine-tuned configuration of the jitterbuffer is desired, then
disable this option, and use the JITTERBUFFER() function prior to calling the ConfBridge()
application. Available options are yes or
no. Default is no.
pin If set, then the person entering the conference will be prompted for a PIN. Valid value is
any integer
announce_join_leave If enabled, the person entering the conference will be prompted to record their name prior
to joining the conference. The name will then be played, announcing the person joining and
leaving the conference. Available options are yes or no. Default is no.
dtmf_passthrough When enabled, this option will allow DTMF to be passed through the conference. This
is useful when the conference bridge may be connected to an endpoint that you want
to receive DTMF; otherwise, it is absorbed by Asterisk. Available options are yes or no.
Default is no.
announcement If set, an announcement prompt is played to users when they join the conference. Value
should be a path to an announcement file

7-8 ‫جدول‬

‫ هنگام‬.‫ این بخش مربوط به پیکربندی و تعریف سیاست‌های کنفرانس است‬:]default_bridge[ ‫• بخش‬
‫ انواع پارامترهای‬8-8 ‫جدول‬.‫ از این پیکربندی و سیاســت‌ها استفاده می‌شود‬،‫ایجاد یک کنفرانس جدید‬
.‫قابل تعریف در این بخش را نشان می‌دهد‬

Option Description
max_members Defines the maximum number of conference participants for a single conference. When the limit
is reached, the conference will be locked until a participant leaves. The only exception is that
administrators are always able to join the conference, regardless of the number of participants.
Value should be an integer. Default is unlimited participants.
record_confer When enabled, the conference will start being recorded when the first participant joins the
ence conference, and stop recording when the last participant leaves. The filename for the recording is
in the format confbridge-<name of the conference bridge>-<start time>.wav. The file by default will
be recorded in 8 kHz slinear. The recording will be saved in the monitoring directory configured in
asterisk.conf. Available options are yes or no.
record_file If record_conference is enabled, you can specify the filename for the recorded conference.
However, since multiple conferences could potentially use the same bridge profile, it is not
recommended to specify this option in the confbridge.conf file itself. Instead, use the CONF
BRIDGE() function to dynamically set the filename prior to entering the conference in the dialplan.
internal_sam This option will set the internal conference native sampling rate at which mixing will occur. By
ple_rate default, the sample rate is automatically selected; however, you can specify a value between
8,000 and 192,000. If you set a sample rate that Asterisk doesn’t support, the closest rate that
Asterisk does support will be used. Available values are auto or a value between 8000 and
192000. Default is auto.
253 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Description
mixing_interval This option sets the internal mixing interval of the conference bridge, in milliseconds. Setting a
higher mixing interval can reduce the amount of load used by large conferences at the expense
of a more loosely coupled conference (e.g., delay). Valid values are 10, 20, 40, and 80. Default
value is 20.
video_mode The video_mode option is used for controlling how video is distributed to conference participants
who can source and/or view video feeds. Participants who want to view and be the source of
video must share the same video codec, such as H.264 (in sip.conf, use allow=h264 in addition
to your audio codecs). Additionally, it is recommended that you turn off the jitterbuffer, since the
jitterbuffer only works on the audio portion of the conference, and thus can cause the audio and
video to become out of sync.
none By default, no video sources are selected. You can still enable a video source for the conference
via DTMF or the AMI.
follow_talker The source video will be that of whoever is talking in the conference (loudest) and which has a
video source. The video source will see the last selected source of video, and not their own.
last_marked The source video will be the last marked user to have joined the conference. If multiple marked
conference participants joined the conference and the last marked user leaves, then the marked
participant who joined just prior to the last will become the source (and so forth).
first_marked Similar to last_marked, the first marked participant of a conference with a video source will be the
source of video for the conference. If that participant leaves, then the next marked participant with
a video source will become the source video for the conference.
8-8 ‫جدول‬
‫ میتوانید اعالن صوتی مورد نظر را‬.‫تمام اعالنهای صوتی درون کنفرانس قابل تنظیم در این بخش هســتند‬
.(۹-8 ‫برای هر یک از پارامترها تعیین کنید )جدول‬

Option Description
sound_join Sound played when a participant joins the conference
sound_leave Sound played when a participant leaves the conference
sound_has_joined Sound played when announcing the name of a joining participant
sound_has_left Sound played when announcing the name of a leaving participant
sound_kicked Sound played to a participant when they have been removed from the conference
sound_muted Sound played to a participant when they have been muted
sound_unmuted Sound played to a participant when they have been unmuted
sound_only_person Sound played to a participant when they are the only member of the conference
sound_only_one Sound played to a joining participant when there is only one other participant in
the conference
sound_there_are Sound played when announcing how many participants are in the conference
sound_other_in_party The adjoining sound used with sound_there_are; the sound files are
concatenated like this: sound_there_are number_of_participants
sound_other_in_party
sound_place_into_ Sound played to the participant when being placed into a conference after waiting for the
conference marked user to join
sound_wait_for_leader Sound played to the participant notifying them they are waiting for a marked user to join the
conference
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 254

Option Description
sound_leader_has_left Sound played when the last marked user has left the conference
sound_get_pin Sound played to the participant when requesting a PIN for the conference
sound_invalid_pin Sound played to the participant when they have entered an invalid PIN
sound_locked Sound played to the participant when they have attempted to join a locked
conference
sound_locked_now Sound played to an administrator after they have locked the conference
sound_unlocked_now Sound played to an administrator after they have unlocked the conference
sound_error_menu Sound played when an invalid menu option has been entered

.‫ انواع اعالن‌های صوتی در کنفرانس‬9-8 ‫جدول‬

.‫ کنید‬reload ‫ وارد محیط کامندالین استریسک شوید و ماژول مربوطه را‬،‫بعد از انجام تنظیمات موردنظر‬
CLI> module reload app_confbridge.so

:‫ در برنامه خود استفاده کنیم‬ConfBridge ‫اکنون باید بتوانیم از دستور‬


CLI> core show application ConfBridge
[Syntax]
ConfBridge(conference[,bridge_profile[,user_profile[,menu]]])

: ConfBridge ‫مهمترین پارامترها در دستور‬


‫ این نــام می‌تواند ترکیبی از حرف و عدد‬.‫ نام یک کنفرانس را مشــخص می‌کنیم‬:conference ‫پارامتر‬ •
.‫باشد‬
‫ نام سیاســت تعریف‌شــده بــرای کاربران در زمان ورود به صف را مشــخص‬:bridge_profile ‫پارامتر‬ •
‫] استفاده‬default_user[ ‫ این پارامتر به‌صورت پیش‌فرض از سیاســت‌های تعریف شده در بخش‬.‫می‌کند‬
.‫می‌کند‬
‫ این‬.‫ نام سیاست تعریف‌شده در زمان ایجاد کنفرانس جدید را مشخص می‌کند‬:default_bridge ‫پارامتر‬ •
.‫] استفاده می‌کند‬default_bridge[ ‫پارامتر به‌صورت پیش‌فرض از سیاست‌های تعریف‌شده در بخش‬
‫ برای یک کنفرانس رول‌هایــی را برای کاربران تعریف می‌کنیم‬،DTMF ‫ با اســتفاده از‬:menu ‫پارامتر‬
1

‫ فرمت تعریف‬.‫ صدا را افزایش می‌دهیم‬،‫ در کنفرانس‬1 ‫ برای مثال بــا گرفتن کد‬.‫تــا آن‌ها را اجرا نمایند‬
:‫رول‌ها به‌صورت زیر است‬
;confbridge.conf
[<menu_name>]
type=menu
<dtmf_code>=<actions>

.‫ انواع رولهای قابل تعریف در بخش کنفرانس را نشان میدهد‬۱۰-8 ‫جدول‬

1- Actions
255 ‫برنامه‌نویسی پیشرفته در استریسک‬

Option Description
playback(<audio_file The playback option can be used to play audio to the participant entering the
name>[[&<audio_filename>]]) DTMF string. The audio cannot be interupted with this option. Similar in style to
the Playback() dialplan application.
playback_and_ Similar to playback except that it will listen for DTMF while the audio is being
continue(<audio_ played. This is useful in situations where you create an audio menu and wish to
filename>[[&<audio_ allow DTMF to be entered during playback. Similar in style to the Background()
filename>]]) dialplan application
toggle_mute Toggles mute between on and off states for the participant. While mute is
enabled, the participant’s audio will not play into the conference bridge, but she
will still be able to listen.
no_op The no_op option performs No Operation. Its purpose is simply for reserving
DTMF sequences in the menu
decrease_listening_volume Decrease the listening volume of the participant.
increase_listening_volume Increase the listening volume of the participant.
reset_listening_volume Reset the listening volume of the participant to the default value.
decrease_talking_volume Decrease the talking volume of the participant.
increase_talking_volume Increase the talking volume of the participant.
reset_talking_volume Reset the talking volume of the participant to the default value.
dialplan_exec(context,exten Use of the dialplan_exec option allows a participant to leave the conference,
sion,priority_label) execute a dialplan, and at the end of the dialplan be returned to the conference.
leave_conference Allows the participant to leave the conference through the use of a DTMF
sequence. Dialplan execution will continue after the ConfBridge() application.
admin_kick_last Allows an administrator to kick the last joining participant from the conference.
This option is only available to administrators so it can be safely enabled in a
common menu between users and admins.
admin_toggle_conference_ Allows an administrator to toggle the conference being locked between on and
lock off. Can only be utilized by admins even if enabled in a user menu.
set_as_single_video_src Allows a participant to set themselves as the single video source for the
conference. This enables video to be stuck to a single participant, regardless of
which mode video_mode is set to
release_as_single_video_src The denoise option is useful if you’re using the speex codec, and the talker has
an elevated level of background noise. When enabled, this option will attempt to
remove background noise before the audio is mixed into the conference, while
preserving the desired speech audio. This option should not be confused with
dsp_drop_silence. Additionally, this option does come at a slight performance hit.
Available options are yes or no. Default is no
admin_toggle_mute_ Allows an administrator to toggle between muting and unmuting all nonadmin
participants participants in the conference. Admins will still be able to speak to the
conference. When this option is toggled, all participants including administrators
will be notified that the conference has been muted.
participant_count When used, will tell the participant how many total participants are in the
conference.

۱۰-8 ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 256

:‫مثال( فرض کنید رولهای زیر را برای ایجاد یک کنفرانس بهصورت زیر داشته باشیم‬
;confbridge.conf
[sample_user_menu]
type=menu
*=playback_and_continue(conf-usermenu)
*1=toggle_mute
1=toggle_mute
*4=decrease_listening_volume
4=decrease_listening_volume
*6=increase_listening_volume
6=increase_listening_volume
*7=decrease_talking_volume
7=decrease_talking_volume
*8=leave_conference
8=leave_conference
*9=increase_talking_volume
9=increase_talking_volume

.‫ برنامه زیر را در نظر بگیرید‬،ConfBridge ‫برای استفاده از دستور‬


;extensions.conf
[ConferenceRooms]
exten => 1520,1,NoOp()
same => n,ConfBridge(${EXTEN},,, sample_user_menu)

[LocalSets]
include => ConferenceRooms

.‫ کاربر وارد کنفرانس میشــود‬،‫گرفته شــود‬۱۵۲۰ ‫ اگر شــماره‬،‫ کردن ماژول مربوطه‬reload ‫اکنون بعد از‬
،[sample_user_menu] ‫کاربر پس از ورود به کنفرانس میتواند با گرفتن کدهای تعریف شده در قسمت‬
.‫با نحوه استفاده از آنها آشنا شود‬
‫( در هنگام ورود به کنفرانس استفاده‬PIN) ‫ میتوان از رمز عبور‬MeetMe ‫در این دستور همانند دستور‬
.‫ برای این منظور تغییرات زیر را در پیکربندی کنفرانس انجام دهید‬.‫نمود‬
;confbridge.conf
[general]

[default_user]
type=user
pin=123123

[default_bridge]
type=bridge

.‫ باید بهصورت زیر تغییرات را در برنامه اعمال کنید‬،ConfBridge ‫هنگام استفاده از دستور‬
[ConferenceRooms]
‫‪257‬‬ ‫برنامه‌نویسی پیشرفته در استریسک‬

‫)(‪exten => 1020,1,NoOp‬‬


‫)‪same => n,Set(CONFBRIDGE(user,pin)=123123‬‬
‫)}‪same => n,ConfBridge(${EXTEN‬‬

‫برقراری ایجاد کنفرانس تصویری در استریسک‬


‫اســتفاده از کنفرانــس تصویــری در استریســک‪ ،‬بســیار ســاده و راحت اســت‪ .‬از آنجاکه استریســک از‬
‫‪Multiplexing‬هــا اســتفاده نمیکند‪ ،‬این نوع کنفرانس در هر لحظه تنهــا میتواند یک کاربر را در تصویر‬
‫نمایش دهد‪ .‬برای فعالکردن این قابلیت در استریســک‪ ،‬ابتــدا باید پارامتر ‪ videosupport‬را هنگام تعریف‬
‫کاربر‪ ،‬بهصورت زیر فعال کنیم‪ .‬برای مثال چنانچه بخواهیم برای کاربر ‪ ،Phone_1‬قابلیت استفاده از تماس‬
‫تصویری را فعال کنیم‪ ،‬تنظیمات مربوطه بهصورت زیر خواهند بود‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phone_1‬‬
‫‪videosupport=yes‬‬
‫‪disallow=all‬‬
‫‪allow=g722‬‬
‫‪allow=ulaw‬‬
‫‪allow=alaw‬‬
‫‪allow=h264‬‬

‫پس از آن‪ ،‬تنظیمات زیر را هنگام تعریف سیاستهای کنفرانس‪ ،‬انجام دهید‪:‬‬
‫‪;confbridge.conf‬‬
‫]‪[default_bridge‬‬
‫‪type=bridge‬‬
‫‪video_mode=follow_talker‬‬

‫در اینجا منظور از ‪ ،follow_talker‬کاربری است که در حال حاضر در کنفرانس در حال صحبت است‪.‬‬

‫نتیجه‌گیری‬
‫در این فصل با مفاهیم بیشــتری درخصوص برنامهنویســی در استریســک‪ ،‬کتابخانهی قدرتمندی از توابع و‬
‫دســتورات‪ ،‬تفاوت آنها با یکدیگر و چگونگی اســتفاده از آنها‪ ،‬آشنا شدید‪ .‬پس از بررسی فرمت استفاده‬
‫از دســتورات استریسک‪ ،‬به معرفی قابلیتهای برجســتهای از قبیل ‪Local Channels‬ها ‪Feature Code ،‬ها‬
‫و ایجاد کنفرانس در استریســک پرداختیم‪ .‬البته نمیتوان تمام دســتورات و توابع موجود در استریســک را‬
‫بهصورت مفصل شــرح داد‪ .‬بنابراین‪ ،‬در فصل بیستم )آشــنایی با دستورات و توابع پرکاربرد در استریسک(‬
‫بهطور مســتقل مهمترین دســتورات و توابع در استریســک را بررســی خواهیمکــرد‪ .‬در فصلهای آینده با‬
‫ویژگیهای بیشتری از استریسک آشنا خواهیدشد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪258‬‬
‫فصل نهم‬

‫آشنایی با صف‌ها در‬


‫استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪260‬‬

‫صف (‪)ACD‬‬

‫یکی از ویژگیهای مهم در سیستمهای تلفنی‪ ،‬قابلیت استفاده از صفهاست‪ .‬شاید استفاده از صف در معنای‬
‫عام چندان پر اهمیت نباشد ولی از چنان امتیازات برجستهای برخوردار است که به کمک آن میتوان کنترل‬
‫و مدیریت جامعی بر تماسهای ورودی یک سیســتم تلفنی داشت‪ .‬به همین دلیل در معنای کاربردی ‪ACD‬‬
‫‪ ۱‬نامیده میشوند‪.‬‬
‫امروزه استفاده از این توانمندیها در سیستمهای تلفنی رو به گسترش است؛ برای مثال وقتی با سازمانی‬
‫تماس میگیرید‪ ،‬معموال پیش از ارتباط با اپراتور‪ ،‬سیســتم تلفنی بهطور خودکار تماس را پاســخ میدهد و‬
‫ضمن تشکر‪ ،‬از شما میخواهد که منتظر بمانید تا به اپراتور متصل شوید‪.‬‬
‫ممکن اســت این ســؤال در ذهن مخاطبان بهوجود آید که با استفاده از صفها‪ ،‬چگونه کنترلی میتوان‬
‫بر تماس ورودی داشته باشیم‪ .‬میتوان با مثالی ساده آن را توضیح داد‪:‬‬
‫فرض کنید تعداد منابع شــهری )خطوط ارتباطی شــبکه ویپ با شــبکه مخابراتی ‪ (PSTN‬بیش از تعداد‬
‫کاربران )اپراتورها( یک سازمان باشد‪ .‬مسلماً در چنین وضعیتی اگر تماسهای ورودی مستقیماً به اپراتورها‬
‫متصل شــود‪ ،‬تماسهای زیادی به دلیل »کمبود اپراتور در ســازمان« و عدم امکان پاســخگویی از دســت‬
‫خواهند رفت‪ .‬در این حالت‪ ،‬صرفنظر از »عدم رضایتمندی در پاسخگویی« نمیتوان بر سیستم مدیریت‬
‫و نظارت داشت‪ .‬از طرف دیگر بدون استفاده از صف نمیتوان عملکرد اپراتورها را در کیفیت پاسخگویی‬
‫زیــر نظر داشــت‪ .‬به همین دلیل‪ ،‬با تکنیک ‪ ACD‬میتوان همه تماسهــای ورودی را کنترل کرد و افزایش‬
‫رضایتمندی مشتریان از کیفیت پاسخگویی و سطح سرویسدهی را بهدست آورد‪.‬‬

‫)‪1- Automatic Call Distribution (ACD‬‬


‫‪261‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫موضوعات مطرح شــده در این فصل از کتاب‪ ،‬برای طراحی یک کالســنتر‪ 1‬بسیار بااهمیت و ارزشمند‬
‫اســت؛ بهطوریکه بــا مطالعه این فصل میتوانید بهراحتی یک سیســتم کالســنتر طراحــی و گزارشهای‬
‫ارزشــمندی تولید کنید‪ .‬نکته مهم در طراحی یک کالســنتر خوب‪ ،‬شناخت کافی و جامع نسبت به اجزای‬
‫طراحی آن است که در این کتاب به تفصیل بررسی شده است‪ .‬در واقع هدف از این فصل‪ ،‬آموزش طراحی‬
‫یک کالسنتر و تحلیل بخشهای مختلف آن ازطریق سیستم تلفنی استریسک است‪ ،‬اما پیش از پرداختن به‬
‫بحث اصلی‪ ،‬بهتر است انواع کالسنترها را معرفی نماییم‪:‬‬
‫‪ :Inbound -1‬همان قابلیت ‪ ACD‬است که کنترل تماس‌های ورودی را برعهده دارد‪.‬‬
‫‪ :Outbound -2‬تکنیک ‪ Predictive Dialer‬است و کنترل تماس‌های خروجی را برعهده دارد‪.‬‬
‫تمرکز ما در این فصل روی کال‌سنتر با تماس‌های ورودی ‪ ۲ ACD‬خواهد بود‪.‬‬
‫ازآنجاکه مطالب این فصل بســیار ساده و کاربردی اســت‪ ،‬بر مثال‌ها و تمرین‌ها تمرکز بیشتری صورت‬
‫گرفته است‪.‬‬

‫تعریف صف در سیستم تلفنی استریسک‬


‫برای استفاده از صفها‪ ،‬نخست باید یک صف در سیستم تلفنی استریسک ایجاد کنید‪ .‬از مهمترین عناوین‬
‫مورد استفاده در این فصل‪ ،‬واژههای ‪ member‬و ‪ agent‬هستند که ممکن است با ابهام همراه باشند‪.‬‬
‫منظــور از ‪ ،member‬تلفنهــا و تجهیزاتی اســت که عضــو صفاند و تماسها به ســمت آنها هدایت‬
‫میشــوند‪ .‬مثال گوشــی تلفنی که عضو صف اســت و با ورود تماس به صف‪ ،‬شروع به زنگ زدن میکند‪،‬‬
‫پاسخ میدهد‪.‬‬ ‫بهعنوان ‪ member‬شناخته میشود‪ .‬منظور از ‪ agent‬اپراتوری است که تلفن منتظر در صف را‬
‫بهعبارت سادهتر ‪ ،member‬تجهیزاتی )تلفنیهایی( هستند که عضو صفاند و تماسهای جدید به سوی‬
‫آنها منتقل میشود‪ ،‬درحالیکه ‪ agent‬اپراتوری است که به تماس ورودی پاسخ میدهد )شکل ‪.(۱-۹‬‬

‫شکل ‪1-9‬‬

‫در نسخههای جدیدتر برنامه استریسک‪ ،‬استفاده از ‪agent‬ها کمتر توصیه شده است‪ ،‬به این دلیل که استفاده‬
‫از آنها در صف با مشکالتی همراه است و انعطافپذیری الزم را ندارند‪ .‬بنابراین در این کتاب بیشتر روی‬

‫‪1- Call Center‬‬


‫‪2- Inbound Call Center‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪262‬‬

‫‪Channel Driver‬ها که در صف بهعنوان ‪ member‬شناخته میشوند‪ ،‬تمرکز خواهیم داشت‪.‬‬


‫برای اســتفاده از یک صف‪ ،‬نخســتین گام‪ ،‬ساختن یک صف است‪ .‬روال ساخت یک صف جدید بسیار به‬
‫تعریف یک کاربر )داخلی جدید( شــبیه اســت‪ .‬برای تعریف یک صف باید از فایل ‪ queues.conf‬استفاده‬
‫کنید‪.‬‬
‫‪#vim /etc/asterisk/queues.conf‬‬

‫اگــر فایل را باز کنید‪ ،‬یک راهنمای کامل از انواع پارامترهای موجود در صف را مشــاهده میکنید‪ .‬برخی‬
‫از پارامترهای استریســک‪ ،‬مفهومی کلی و جامع دارند و غالبا برای همه صفها قابلاســتفادهاند‪ .‬همانطور‬
‫که قب ً‬
‫ال اشاره شد‪ ،‬به دلیل کاربردی بودن مطالب این فصل‪ ،‬و برای فهم بهتر کالسنتر‪ ،‬این مفاهیم را تا حد‬
‫ممکن با یک مثال همراه خواهیم کرد‪.‬‬
‫برای مثال فایل ‪ queues.conf‬را از مســیر باال باز کنید‪ ،‬همان طور که مالحظه می کنید در ابتدای فایل‪،‬‬
‫کانتکست ]‪ [general‬وجود دارد‪ .‬تنظیمات این بخش بر همه صف ها اعمال خواهد شد‪.‬در ادامه هر یک از‬
‫این پارامترها را به تفصیل شرح خواهیم داد‪.‬‬

‫پارامتر ‪ :autofill‬یکی از پارامتر‌های مهم در تعریف صف ‪ autofill‬اســت‪ .‬در نســخه‌های اولیه استریســک‪،‬‬
‫برای طراحی صف‌ها یک چالش اصلی وجود داشت؛ تا زمانی که نفر اول صف به‌وسیله اپراتور‌ها پاسخ داده‬
‫نمی‌شــد‪ ،‬نفرات بعدی بایــد در صف منتظر می‌ماندند و این در حالی بود که تمــام اپراتور‌ها در صف آزاد‬
‫‪1‬‬

‫بودند‪ .‬پر واضح است که در چنین شرایطی‪ ،‬زمان انتظار‪ 2‬برای اتصال به اپراتورها افزایش می‌یابد‪.‬‬
‫در نسخههای جدید برنامه‪ ،‬با تنظیم پارامتر ‪ autofill=yes‬در صف‪ ،‬این امکان فراهم میشود که به تعداد‬
‫اپراتورهای آزاد در صف‪ ،‬تماسهای موجود در صف به اپراتورها متصل شوند‪.‬‬
‫‪autofill=yes‬‬

‫برای مثال شکل ‪ ۲-۹‬را در نظر بگیرید‪:‬‬

‫شکل ‪2-9‬‬

‫‪1- Not In Use‬‬


‫‪2- Waiting Time‬‬
‫‪263‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫در این حالت اگر ‪ autofill=no‬باشــد‪ ،‬صرفنظر از اینکه اپراتورها آزاد باشــند یا نباشــند؛ نفر اول از صف‬
‫برداشته و به اولین اپراتور وصل میشود‪ .‬تا زمانی که این تماس به اپراتور متصل نشود‪ ،‬نفرات بعدی در صف‬
‫منتظر میمانند‪ .‬اما چنانچه ‪ autofill=yes‬باشد‪ ،‬صف بهصورت همزمان‪ ،‬به تعداد اپراتورهای آزاد‪ ،‬تماسها‬
‫را به ترتیب اولویت برداشــته و به اپراتور متصل میکند‪ .‬در چنین حالتی اگر اپراتور تماســی را پاسخ ندهد‪،‬‬
‫تماس بالفاصله به اپراتور بعدی منتقل میشود‪ .‬در این شرایط واضح است که سرعت پاسخگویی در صف‪،‬‬
‫چندین برابر میشود‪ .‬با یک مثال این وضعیت را نمایش میدهیم‪.‬‬
‫مثال( یک شرکت خدمات پس از فروش‪ ،‬سناریویی شبیه زیر دارد‪:‬‬
‫یک خط ایوان دارای ‪ ۳۰‬کانال همزمان‪.‬‬
‫تعداد ‪ ۱۰‬اپراتور پاسخگو در سیستم که همگی فعالند ) آن را با متغیر ‪ m‬نشان میدهیم‪.(m =۱۰ ،‬‬
‫در این سیستم ‪ autofill=no‬تنظیم شدهاست‪.‬‬
‫نرخ سرعت پاسخ دادن به تماسها بهوسیله اپراتورها‪ ،‬حداکثر ‪ ۲۰‬ثانیه است )‪.(AnswerTime=۲۰ s‬‬
‫متوسط سرعت پاسخگویی‪ ۱۰ ،‬ثانیه است )‪.(Average Answer Time‬‬
‫متوسط مدت پاسخگویی هر اپراتور‪ ۵ ،‬دقیقه است )‪.(Duration Time= ۵ min‬‬
‫مدت زمان انتظار در صف برای مشتریان‪:‬‬
‫زمان انتظار در صف برای نفر اول‪1 × 10s = 10s :‬‬
‫‪2 × 10s = 20s‬‬ ‫زمان انتظار در صف برای نفر دوم‪:‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫زمان انتظار در صف برای نفر ‪n‬ام‪n × 10s :‬‬
‫برای چنین سیســتمی اگر ‪ 10‬نفر هم‌زمان در صف وجود داشته‌باشــد‪ ،‬نفر آخر باید به‌طور متوســط‬
‫‪ 10×10‬ثانیه منتظر بماند تا به اپراتور متصل شود‪ .‬چنانچه تعداد افراد منتظر در صف از این هم بیشتر باشد‪،‬‬
‫متوسط مدت زمان مکالمه هر اپراتور به همان نسبت افزایش می‌یابد‪.‬‬
‫اکنــون ســناریوی باال را با پارامتــر ‪ autofill=yes‬تکــرار کنید‪ .‬در این حالت زمــان انتظار در صف‬
‫به‌صورت زیر تغییر می‌کند‪.‬‬
‫ • مدت زمان انتظار در صف برای مشتریان‪:‬‬
‫برای نفر اول ‪⌈1⁄m⌉ × 10s :‬‬
‫برای نفر دوم‪⌈2⁄m⌉ × 10s:‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫برای نفر ‪n‬ام‪⌈n⁄m⌉ × 10s :‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪264‬‬

‫حالت فرض کنید تعداد اپراتورهای منتظر در صف ‪ m=۱۰‬نفر باشــد‪ .‬واضح است که برای ‪ ۱۰‬نفر اول‬
‫مشتریان منتظر در صف‪ ،‬زمان انتظار ثابت است؛ چون به تعداد اپراتورهای آزاد‪ ،‬تماسها به اپراتورها منتقل‬
‫میشــود‪ .‬اگر تعداد افراد منتظر در صف بیش از ‪ ۱۰‬نفر باشــد‪ ،‬در این حالت متوسط زمان مکالمه هم اضافه‬
‫میشود‪.‬‬

‫پارامتــر ‪ :warpuptime‬یکی از پارامترهای مهم در صف ‪ shared_lastcall‬اســت‪ .‬کاربرد این پارامتر غالبا‬


‫در کنــار پارامتر دیگری به‌نام ‪ warpuptime‬مفهوم پیدا می‌کند‪ .‬فرض کنید مکالمه یک اپراتور تمام شــده‬
‫اســت و وضعیت آن به حالت ‪ Not In Use‬درآمده باشــد‪ .‬در این وضعیت‪ ،‬فورا تماس جدیدی برای یک‬
‫اپراتور ارســال می‌شــود‪ .‬اکنون اگر بخواهیم این تماس جدید برای اپراتور با تأخیر صورت گیرد (به این که‬
‫شاید اپراتور قصد دارد یک یادداشت از تماس قبلی ثبت کند)‪ ،‬باید از پارامتر ‪ wrapuptime‬استفاده‌کنیم‪.‬‬
‫مثــال چنانچه‪ wrapuptime=۱۰‬باشــد‪ ،‬بین دو مکالمه‪ ،‬اپراتور ‪ ۱۰‬ثانیه زمان برای یادداشــتبرداری در‬
‫اختیار خواهد داشت‪ .‬دقت کنید هرچه زمان ‪ wrapuptime‬بیشتر باشد زمان انتظار در صف نیز بیشتر میشود‪.‬‬
‫همچنین این امکان وجود دارد که یک اپراتور بهصورت همزمان عضو چندین صف مختلف باشــد؛ در این‬
‫حالت تماس از طرف هر دو صف برای اپراتور ارسال میشود‪ .‬اگر پارامتر ‪ wrapuptime‬برای هر دو صف‬
‫تعریف شده باشد‪ ،‬هیچ تضمینی وجود ندارد که بالفاصله بعد از اتمام مکالمه اپراتور‪ ،‬از صف دیگر تماس‬
‫جدید نیاید‪ .‬در این شــرایط از پارامتر ‪ shared_lastcall=yes‬استفاده میکنیم‪ .‬به این مفهوم که اگر اپراتور‬
‫از اتمام مکالمه‪ ،‬تماس جدید از هیچ صفی تا زمان تعیینشده در ‪wrapuptime‬‬ ‫عضو چندین صف باشد‪ ،‬بعد‬
‫برای او ارسال نشود‪.‬‬
‫‪wrapuptime=10‬‬

‫پارامتــر ‪ :musicOnHold‬پارامتر بعدی در تعریف صف‪ musiconhold ،‬اســت‪ .‬برای افرادی که در صف‬
‫منتظر ارتباط با اپراتور هســتند‪ ،‬می‌توان یک موزیک انتظار پخش کرد تا زمان انتظار برایشــان خســته‌کننده‬
‫و مالل‌آور نباشــد‪ .‬به کمک این پارامتــر‪ ،‬یک موزیک برای زمان انتظار مشــخص می‌کنیم‪ .‬پیش‌تر درباره‬
‫موزیک انتظار در فصل سوم توضیح داده‌ شد‪.‬‬
‫‪musiconhold=default‬‬

‫پارامتر ‪ :strategy‬شاید این مطلب قبال در ذهن مخاطب خطور کرده‌باشد که بر چه معیاری تماس‌ها از صف‬
‫به اپراتور‌ها متصل می‌شــوند؟ در استریســک رول‌های منظم و از پیش تعیین شده‌ای وجود دارد که می‌توان‬
‫از آنها اســتفاده کرد‪ .‬به‌عنوان مثال استفاده از استراتژی ‪ round robin‬باعث می‌شود انتخاب اپراتور به‌شکل‬
‫چرخشی انجام شود‪.‬‬
‫‪strategy=rrmemory‬‬

‫جدول ‪ ۱-۹‬انواع استراتژیهای موجود در صف را توضیح میدهد‪.‬‬


265 ‫آشنایی با صف‌ها در استریسک‬

Strategy Description
ringall ring all available channels until one answers (default)
leastrecent ring interface which was least recently hung up by this queue
fewestcalls ring the one with fewest completed calls from this queue
random ring random interface
rrmemory round robin with memory, remember where we left off last ring pass
rrordered same as rrmemory, except the queue member order from config file is preserved
linear rings interfaces in the order specified in this configuration file.
- If you use dynamic members, the members will be rung in the order in which they were added
wrandom rings random interface, but uses the member's penalty as a weight when calculating their metric. So a
member with penalty 0 will have a metric somewhere between 0 and 1000, and a member with penalty
1 will have a metric between 0 and 2000, and a member with penalty 2 will have a metric between 0
and 3000. Please note, if using this strategy, the member penalty is not the same as when using other
queue strategies. It is ONLY used as a weight for calculating metric.

1-9 ‫جدول‬

‫ فرض کنید تمام اپراتورها از‬.‫ اســت‬joinempty ‫ پارامتر‬،‫ پارامتر بعدی در تعریف صف‬:joinempty‫پارامتر‬
‫ واضح است که این تماس برای همیشه (یا تا‬.‫صف خارج شــده باشند؛ سپس یک مشــترک وارد صف شود‬
‫ در‬.‫ مشــخص شــده) در صف باقی می‌ماند و هیچ اپراتوری نیست که تماس او را پاسخ دهد‬timeout ‫زمان‬
‫ تماس‬،‫ را به گونه‌ای تنظیم می‌نماییم که اگر اپراتوری در صف وجود نداشت‬joinempty ‫این شرایط پارامتر‬
.‫جدیدی به داخل صف وارد‌ نشود‬
joinempty=no

‫ ممکن اســت تماس‌هایی از قبل در صف باشــند که منتظــر ارتباط با اپراتور‌ها‬:leavewhenempty ‫پارامتر‬


‫ در این شرایط طبیعتا تماس‌هایی‬.‫ اما شرایطی پیش می‌آید که تمامی اپراتور‌ها از صف خارج می‌شوند‬،‫باشند‬
‫ وظیفه پارامتر‬.‫که داخل صف بودند باید قطع شوند چون پاسخگویی وجود ندارد که به تماس آنها پاسخ دهد‬
.‫ تماس‌های درون صف را هم خارج می‌کند‬،‫فوق این است که با خروج اپراتور‌ها از صف‬
leavewhenempty=yes

‫ تماسی به این اپراتور‬،‫ اگر اپراتوری در حال مکالمه باشــد و بر اســاس چرخه استراتژی‬:ringinuse ‫پارامتر‬
‫ اگر مایل نباشیم تماس‌های جدید به اپراتور‌های در حال‬.‫ به‌عنوان پشت خطی به اپراتور اعالم می‌شود‬،‫برسد‬
.‫ این پارامتر را به صورت زیر تنظیم می‌کنیم‬،‫مکالمه ارسال شوند‬
ringinuse=no

‫ بگذارید‬myqueue ‫ اسم صف را‬.‫پیش از ادامه بحث بهتر اســت یک صف جدید در استریسک ایجاد کنیم‬
:‫و تنظیمات زیر را انجام دهید‬
.‫ یک فایل دیگر را برای ایجاد تغییرات اضافه کنید‬،‫ را باز کنید و به انتهای آن‬queues.conf ‫ابتدا فایل‬
;queues.conf
#include queues_custom.conf
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪266‬‬

‫سپس فایل فوق را ایجاد و تغییرات زیر را به آن اضافه کنید‪:‬‬


‫‪#vim /etc/asterisk/queues_custom.conf‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬

‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
‫‪joinempty=no‬‬
‫‪leavewhenempty=yes‬‬
‫‪ringinuse=no‬‬

‫با تعریف پارامترهای باال‪ ،‬یک صف با نام ‪ myqueue‬در استریســک ایجاد میشــود‪ .‬اکنون برای اعمال آن‬
‫باید ماژول صف را ‪ reload‬کنیم‪ .‬برای این منظور به محیط کامندالین استریســک بروید و دســتور زیر را‬
‫اجرا کنید‪.‬‬
‫‪CLI> module reload app_queue.so‬‬

‫یا‬
‫‪CLI> queue reload all‬‬

‫همانطورکه مالحظه میکنید با هر دو روش فوق میتوان ماژول صف را دوباره راهاندازی کرد‪ .‬توجه داشته‬
‫باشــید که صف بهعنوان یک اپلیکیشن و بهصورت ماژول به استریسک اضافه شدهاست و میتوانید )اگر به‬
‫این ماژول نیازی ندارید( آن را غیر فعال یا حذف کنید‪.1‬‬
‫برای مشاهده وضعیت صفهای موجود در استریسک‪ ،‬دستور زیر را اجرا کنید‪.‬‬
‫‪CLI>queue show‬‬

‫خروجی دستور فوق حاوی اطالعات مفید و ارزشمندی در خصوص صف خواهد بود‪.‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:0, SL:0.0% within 0s‬‬
‫‪No Members‬‬
‫‪No Callers‬‬

‫همان‌طورکه در خروجی دستورفوق مالحظه می‌کنید‪ ،‬اطالعات زیر قابل استخراج است‪:‬‬
‫‪ :W‬وزن صف را نشان میدهد‪ .‬صفهای با وزن بیشتر‪ ،‬اولویت باالتری برای برقراری ارتباط دارند‪ .‬در ادامه‬
‫درباره صفهای وزندار )با اولویت( مطالب بیشتری خواهد آمد‪.‬‬
‫‪ :C‬تعداد تماسهای وارد شده به داخل صف را نشان میدهد که پاسخ داده شده اند‪.‬‬
‫‪ :A‬تعداد تماسهای وارد شــده به داخل صف را نشــان میدهد که پاسخ داده نشده اند)قبل از اینکه اپراتور‬
‫تماس را پاسخ دهد تماس قطع شده است(‪.‬‬

‫‪ -1‬جهت حذف کردن ماژول‌ها از استریسک می‌توانید به فصل سوم (نصب و راه اندازی استریسک) مراجعه کنید‪.‬‬
267 ‫آشنایی با صف‌ها در استریسک‬

‫ در واقع این پارامتر تعداد تماسهای پاسخ دادهشده در یک زمان‬.‫ است‬service level ‫ نشــان دهندهی‬:SL
،‫ هنگام تعریف صف‬servicelevel ‫ زمان را بهوســیله پارامتر‬.‫مشــخص را برحســب درصد نشــان میدهد‬
.‫مشخص میکنیم‬
.‫ این پارامتر را لحاظ میکنیم‬myqueue ‫برای مثال در تعریف صف‬
servicelevel=60

:‫ خروجی بهصورت زیر خواهد بود‬،‫ کردن ماژول‬reload ‫بعد از‬


myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 60s
No Members
No Callers

:‫ بهصورت زیر استفاده میکنیم‬،‫اکنون از صف تعریفشده در برنامه خود‬


[Queues]
exten => 7000,1,Answer()
same => n,Verbose(2,${CALLERID(all)} entering the support queue)
same => n,Queue(myqueue)
same => n,Hangup()

[LocalSets]
include => Queues ; allow phones to call queues

:‫ این دستور را اجرا کنید‬،‫ برای تست برنامه‬.‫ استفاده کردیم‬include context ‫در این مثال از روش‬
CLI> console dial 7000@LocalSets
-- Executing [7000@LocalSets:1] Answer("Console/dsp", "") in new stack
-- Executing [7000@LocalSets:2] Verbose("Console/dsp", "2,"" <> entering the support
queue") in new stack
== "" <> entering the support queue
-- Executing [7000@LocalSets:3] Queue("Console/dsp", "myqueue") in new stack
[Aug 14 04:49:13] WARNING[4697][C-00000019]: app_queue.c:7049 queue_exec: Unable to
join queue 'myqueue'
-- Executing [7000@LocalSets:4] Hangup("Console/dsp", "") in new stack
CLI>

WARNING ‫همانطور که مالحظه میکنید ما نتوانســتیم به داخل صف واردشــویم و بهجای آن یک پیام‬


.‫دریافت کردیم‬
WARNING[4697][C-00000019]: app_queue.c:7049 queue_exec: Unable to join queue

'myqueue'

‫ حال اگر فرض کنیم‬.‫ تنظیم شده بود‬joinempty=no ‫چون هیچ اپراتوری در صف وجود نداشت و پارامتر‬
.‫ تماس وارد صفی خواهد شد که هیچ اپراتوری در آن وجود ندارد‬،‫پارامتر بهصورت زیر تنظیم شدهباشد‬
joinempty=yes
leavewhenempty=no
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 268

.‫خروجی دستور بهصورت زیر خواهد بود‬


CLI> console dial 7000@LocalSets
-- Executing [7000@LocalSets:1] Answer("Console/dsp", "") in new stack
<< Console call has been answered >>
-- Executing [7000@LocalSets:2] Verbose("Console/dsp", "2,"" <> entering the support
queue") in new stack
== "" <> entering the support queue
-- Executing [7000@LocalSets:3] Queue("Console/dsp", "myqueue") in new stack
-- Started music on hold, class 'default', on Console/dsp
CLI>

‫همانطور که مالحظه میکنید در این حالت هیچ اخطاری وجود نداشت و تماس وارد صف شد هرچند‬
.‫ وضعیت صف در این حالت بهصورت زیر است‬.‫که هیچ اپراتوری وجود نداشته باشد‬
CLI> queue show
myqueue has 1 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:6, SL:0.0% within 60s
No Members
Callers:
1. Console/dsp (wait: 0:02, prio: 0)

‫مشــاهده میکنید که یک نفر مشــترک در صف داریم ولی هیچ اپراتوری وجود ندارد که تماس را پاســخ‬
.‫ اعالم میشود‬No Members ‫ بنابراین عبارت‬.‫دهد‬
‫ را شمارهگیری‬7۰۰۰ ‫ در سیســتم تلفنی استریسک رجیستر شدهایم و شماره‬۱۰۰ ‫مثال( فرض کنید با داخلی‬
.‫ بهصورت زیر خواهدبود‬queue show ‫ در این صورت خروجی دستور‬.‫کردیم‬
CLI> queue show
myqueue has 1 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:8, SL:0.0% within 60s
No Members
Callers:
1. SIP/100-0000000f (wait: 0:09, prio: 0)

wait ‫ پارامتر‬.‫تعداد افراد منتظر در صف با عدد مشــخص میشوند که اینجا تنها یک نفر در صف قرار دارد‬
‫ ثانیه بوده‬۹ ‫ زمان انتظار‬، ‫نشان دهنده زمانیست که تماس مربوطه در صف منتظر مانده است که در این مثال‬
.‫ خروجی دستور میتواند بهصورت زیر باشد‬.‫است‬
CLI> queue show
myqueue has 9 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:8, SL:0.0% within 60s
No Members
Callers:
1. SIP/self-00037dc8 (wait: 0:30, prio: 0)
2. SIP/self-00035da8 (wait: 0:25, prio: 0)
3. SIP/self-00045db8 (wait: 0:21, prio: 0)
4. SIP/self-00034dc8 (wait: 0:20, prio: 0)
‫‪269‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫)‪5. SIP/self-00085dc8 (wait: 0:19, prio: 0‬‬


‫)‪6. SIP/self-00012dc8 (wait: 0:10, prio: 0‬‬
‫)‪7. SIP/self-00087dc8 (wait: 0:09, prio: 0‬‬
‫)‪8. SIP/self-00033dc8 (wait: 0:05, prio: 0‬‬
‫)‪9. SIP/self-00043gc8 (wait: 0:02, prio: 0‬‬

‫در این مثال ‪ ۹‬نفر در صف قرار دارند که نفرات اول زمان بیشتری منتظر بودهاند‪ .‬در این مثال تمامی تماسها‬
‫از سمت ترانکی بهنام ‪ self‬وارد سیستم استریسک شدهاند‪.‬‬
‫تا اینجا تماسهای جدیدی که اپراتوری برای پاسخگویی به آنها وجود نداشت‪ ،‬بررسی شدند‪ .‬در ادامه‬
‫انواع روشهای اضافهکردن اپراتور به صف را هم بررسی خواهیمکرد‪.‬‬

‫اضافه و حذف‌کردن اپراتور‌ها (‪ )member‬به یک صف در استریسک‬


‫پیشتر اشاره شد که صفها قابلیتهای منحصربهفردی برای ما فراهم میکنند‪ .‬برای استفاده از این قابلیتها‬
‫بایــد ابتدا اپراتورهایــی را به صف اضافه کنیم‪ .‬یک صف بدون داشــتن اپراتور‪ ،‬هیــچ قابلیتی ندارد‪ .‬برای‬
‫اضافهکردن اپراتور به صف یا خارج کردن اپراتور از آن‪ ،‬از سه روش میتوان اقدام کرد‪:‬‬
‫‪ .۱‬بهصورت داینامیک از طریق محیط کامندالین استریسک؛‬
‫‪ .۲‬بهصورت استاتیک هنگام تعریف صف با پارامتر ‪member‬؛‬
‫‪ .۳‬بهصورت داینامیک از طریق برنامهنویسی‪.‬‬
‫در ادامه هر روش به تفصیل بررسی میشوند‪.‬‬

‫اضافه و حذف کردن اپراتور به صف به‌صورت داینامیک از طریق محیط کامندالین استریسک‬
‫از طریق دســتورات مدیریتی و کنترلی در کامندالین استریســک میتوان اپراتور جدیدی به صف اضافه و‬
‫یا از آن حذف کرد‪ .‬برای این کار باید وارد محیط کامند الین استریســک بشــوید و دستورات زیر را اجرا‬
‫نمایید‪.‬‬

‫اضافه‌کردن یک اپراتور به صف‬


‫]>‪CLI> queue add member <channel> to <queue> [[[penalty <penalty>] as <membername‬‬
‫]>‪state_interface <interface‬‬

‫مثال( فرض کنید بخواهیم اپراتور )‪ (Phone_1‬را به صف ‪ myqueue‬که قب ً‬


‫ال تعریفشده‪ ،‬اضافه کنیم‪:‬‬
‫‪CLI> queue add member SIP/Phone_1 to myqueue Added interface 'SIP/Phone_1' to queue‬‬
‫'‪'myqueue‬‬

‫بعد از اجرای دستور فوق‪ ،‬دستور زیر را برای مشاهده اپراتورهای صف اجرا کنید‪.‬‬
‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪270‬‬

‫‪C:0, A:11, SL:0.0% within 60s‬‬


‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (dynamic) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫همانطورکه مالحظه میکنید این صف دارای یک اپراتور به نام ‪ Phone_1‬است که بهصورت داینامیک به‬
‫صف اضافه شده و در وضعیت ‪ Not in use‬قرار دارد‪.‬‬

‫‪ pause/unpause‬کردن یک اپراتور در صف‬


‫گاهی الزم اســت اپراتورها بهطور موقت از صف خارج شــوند و بعد از زمانی تعیینشــده‪ ،‬دوباره به صف‬
‫برگردند‪ .‬در چنین شــرایطی بهتر اســت به جای حذف و اضافه کردن اپراتورها‪ ،‬آنها را ‪pause/unpause‬‬
‫کنیم‪ .‬در این صورت اگر اپراتوری در حالت ‪ pause‬باشد‪ ،‬هیچ تماسی را دریافت نخواهدکرد‪.‬‬
‫برای ‪ pause‬یا ‪ unpause‬کردن یک اپراتور حاضر در صف‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫]]>‪CLI> queue {pause|unpause} member <member> [queue <queue> [reason <reason‬‬

‫مثــال( فرض کنید بخواهیم اپراتــور ‪ Phone_1‬حاضر در صف را در حالت ‪ pause‬قرار دهیم‪ .‬برای این کار‬
‫دستور زیر را اجرا کنید‪:‬‬
‫"‪CLI> queue pause member SIP/Phone_1 queue myqueue reason "on-break‬‬
‫'‪paused interface 'SIP/Phone_1' in queue 'myqueue' for reason 'on-break‬‬

‫همانطــور که مالحظه میکنیــد با اجرای این دســتور‪ ،‬اپراتور ‪ Phone_1‬به حالــت ‪ pause‬تغییر وضعیت‬
‫میدهد‪.‬‬
‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:11, SL:0.0% within 60s‬‬
‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (dynamic) (paused) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫میتــوان از پارامتــر ‪ reason‬برای ثبت رویدادها و علت ‪ pause‬شــدن اپراتــور در فایلها و گزارشها‬
‫استفاده کرد‪ .‬پارامتر ‪ reason‬بیشتر جنبه گزارش برای سیستم دارد‪.‬‬
‫و پذیرش تماسهای جدید‪ ،‬دستور زیر را اجرا کنید‪.‬‬ ‫برای ‪ unpause‬کردن اپراتور‬
‫"‪CLI> queue unpause member SIP/Phone_1 queue myqueue reason "off-break‬‬
‫'‪unpaused interface 'SIP/Phone_1' in queue 'myqueue' for reason 'off-break‬‬

‫پس از اجرای دستور‪ ،‬خروجی صف بهصورت زیر خواهدبود‪.‬‬


‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:11, SL:0.0% within 60s‬‬
‫‪Members:‬‬
‫‪271‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫‪SIP/Phone_1 (ringinuse disabled) (dynamic) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫حذف کردن یک اپراتور از صف‬


‫برای حذف کردن یک اپراتور از صف‪ ،‬دستور زیر را اجرا کنید‪.‬‬
‫>‪CLI> queue remove member <channel> from <queue‬‬

‫مثــال( فرضکنید بخواهیم اپراتور ‪ Phone_1‬را از صف ‪ myqueue‬خارج کنیم‪ .‬برای این کار‪ ،‬دســتور زیر‬
‫اجرا کنید‪.‬‬ ‫را‬
‫‪CLI> queue remove member SIP/Phone_1 from myqueue‬‬
‫'‪Removed interface SIP/Phone_1 from queue 'myqueue‬‬

‫با اجرای دستور فوق‪ ،‬اپراتور ‪ Phone_1‬از صف خارج میشود و خروجی دستور بهصورت زیر خواهد بود‪.‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:11, SL:0.0% within 60s‬‬
‫‪No Members‬‬
‫‪No Callers‬‬

‫نکته مهم خروجی دســتور ‪ queue show‬این است که برای اپراتور ‪ Phone_1‬همیشه عبارت »‪«dynamic‬‬
‫مشاهده میشود که معنای آن این است که اپراتور مورد نظر بهصورت داینامیک به صف اضافه شده است‪.‬‬

‫اضافه و حذف کردن اپراتور به صف به‌صورت استاتیک در زمان تعریف صف‬


‫هنــگام تعریف صف جدید‪ ،‬میتــوان اپراتورهایی را بهصورت ‪ static‬صریحاً تعریــف کنیم‪ .‬بهعنوان مثال‬
‫در صفهایی که قب ً‬
‫ال تعریف شــده اســت‪ ،‬باید تغییرات زیر را اعمال کنید‪ .‬برای این منظور فایل _‪queues‬‬
‫‪ custom.conf‬را باز و موارد زیر را به صف اضافه کنید‪:‬‬
‫‪;vim /etc/asterisk/queues_custom.conf‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬

‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
‫‪joinempty=no‬‬
‫‪leavewhenempty=yes‬‬
‫‪ringinuse=no‬‬
‫‪member => SIP/Phone_1‬‬

‫این روش یکی از سادهترین روشها برای اضافهکردن اعضای جدید به صف است‪ .‬هر تعداد عضو را برای‬
‫صف الزم داشــته باشــید میتوانید بهصورت فوق تعریف کنید و سپس باید ماژول صف را ‪ reload‬کنید تا‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪272‬‬

‫تغییرات الزم اعمال گردد‪ .‬خروجی دستور بهصورت زیر است‪:‬‬


‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:11, SL:0.0% within 60s‬‬
‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫همانطورکه مالحظه میکنید‪ ،‬چون این روش اضافهکردن اپراتورها به صف بهصورت اســتاتیک است‪ ،‬لذا‬
‫عبارت ‪ dynamic‬در اینجا وجود ندارد‪.‬‬
‫البته این روش در کنار سادگی استفاده‪ ،‬معایبی هم دارد‪ .‬در طراحی کالسنترها برای سازمانها‪ ،‬اپراتورها‬
‫باید بهراحتی بتوانند در سیستم‪ login ،‬یا ‪ logout‬شوند‪ .‬لذا استفاده از این روش چندان مناسب نیست‪ .‬روش‬
‫اول هم چندان کاربردی نیست‪ ،‬چون عموما باید بهوسیله مدیر سیستم انجام شود و برای کاربران معمولی به‬
‫دلیل عدم دسترسی به محیط کامند الین استریسک‪ ،‬امکان پذیر نیست‪ .‬بهترین حالت این است که اپراتورها‬
‫بتوانند با شــمارهگیری یک عدد خاص‪ ،‬به صف مربوطه وارد شــوند و هر زمان الزم باشــد با شــمارهگیری‬
‫مجدد‪ ،‬از صف خارج شوند‪ .‬در ادامه این روش بیشتر توضیح داده میشود‪.‬‬

‫اضافــه و حذف کــردن اپراتور به صف به‌صــورت داینامیک از طریق برنامه‌نویســی در‬


‫استریسک‬
‫شــاید این روش ایدهآلترین روش برای اضافه و حذف کردن اپراتورها در صف باشــد‪ .‬اپراتورها در بدو‬
‫ورود به سازمان‪ ،‬وارد صف پاسخگویی میشوند و پس از اتمام ساعتکاری‪ ،‬از صف خارج میشوند‪ .‬زمان‬
‫ورود به سیســتم و خروج از سیستم میتواند بهعنوان یک گزارش برای استفادههای بعدی در سیستم ذخیره‬
‫شود‪ .‬برای این منظور از دستورات کاربردی زیر استفاده میکنیم‪.‬‬
‫ •‪ :AddQueueMember‬برای اضافه‌کردن اپراتور به صف استفاده می‌کنیم‪.‬‬
‫ •‪ :RemoveQueueMember‬برای حذف اپراتور از صف استفاده می‌کنیم‪.‬‬
‫ •‪ :PauseQueueMember‬برای ‪ pause‬کردن اپراتور در صف استفاده می‌شود‪.‬‬
‫ •‪ :UnpauseQueueMember‬برای ‪ unpause‬کردن اپراتور در صف استفاده می‌شود‪.‬‬
‫برای آشنایی بیشتر با هر یک از دستورات فوق‪ ،‬می‌توانید در محیط کامند‌الین استریسک دستور زیر را اجرا‬
‫کنید‪.‬‬
‫‪CLI> core show application AddQueueMember‬‬

‫مثال( فرضکنید بخواهیم امکان ورود به صف‪ ،‬خروج از صف‪ pause ،‬و ‪ unpause‬کردن را برای اپراتورها‬
‫فراهم کنیم‪ .‬در این صورت برنامه زیر را خواهیم داشت‪.‬‬
‫]‪[Queues‬‬
273 ‫آشنایی با صف‌ها در استریسک‬

exten => *54,1,Verbose(2,Logging In Queue Member)


same => n,Set(MemberChannel=${CHANNEL(channeltype)}/${CHANNEL(peername)})
same => n,AddQueueMember(myqueue,${MemberChannel})
same => n,Verbose(1,${AQMSTATUS}) ; ADDED, MEMBERALREADY, NOSUCHQUEUE
same => n,Playback(agent-loginok)
same => n,Hangup()

exten => *56,1,Verbose(2,Logging Out Queue Member)


same => n,Set(MemberChannel=${CHANNEL(channeltype)}/${CHANNEL(peername)})
same => n,RemoveQueueMember(myqueue,${MemberChannel})
same => n,Verbose(1,${RQMSTATUS}; REMOVED, NOTINQUEUE, NOSUCHQUEUE
same => n,Playback(agent-loggedoff)
same => n,Hangup()

exten => *72,1,Verbose(2,Pause Queue Member)


same => n,Set(MemberChannel=${CHANNEL(channeltype)}/${CHANNEL(peername)})
same => n,PauseQueueMember(myqueue,${MemberChannel})
same => n,Verbose(1,${PQMSTATUS}); PAUSED, NOTFOUND
same => n,Playback(dictate/paused)
same => n,Hangup()

exten => *87,1,Verbose(2,Unpause Queue Member)


same => n,Set(MemberChannel=${CHANNEL(channeltype)}/${CHANNEL(peername)})
same => n,UnpauseQueueMember(myqueue,${MemberChannel})
same => n,Verbose(1,${UPQMSTATUS}); UNPAUSED, NOTFOUND
same => n,Playback(agent-loginok)
same => n,Hangup()

‫ وضعیت خود را در صف تغییر‬،‫همانطورکه مالحظه میکنید هر اپراتور میتواند با گرفتن یک کد مشخص‬


.‫ آنها را دست کم یکبار اجرا کنید‬،‫ کدها را به دقت بررسی کنید و برای درک بهتر‬.‫دهد‬
.‫ خروجی زیر را مشاهده خواهید کرد‬.‫* را شمارهگیری کند‬۵4 ‫ شماره‬Phone_1 ‫فرض کنید کاربر‬
== Using SIP RTP CoS mark 5
-- Executing [*54@LocalSets:1] Verbose("SIP/Phone_1-00000013", "2,Logging In Queue
Member") in new stack
== Logging In Queue Member
-- Executing [*54@LocalSets:2] Set("SIP/Phone_1-00000013", "MemberChannel=SIP/
Phone_1") in new stack
-- Executing [*54@LocalSets:3] AddQueueMember("SIP/Phone_1-00000013", "myqueue,SIP/
Phone_1") in new stack
[Aug 14 08:01:13] NOTICE[6242][C-00000028]: app_queue.c:6807 aqm_exec: Added interface
'SIP/Phone_1' to queue 'myqueue'
-- Executing [*54@LocalSets:4] Verbose("SIP/Phone_1-00000013", "1,ADDED") in new stack
ADDED
-- Executing [*54@LocalSets:5] Playback("SIP/Phone_1-00000013", "agent-loginok") in new stack
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪274‬‬

‫)'‪-- <SIP/Phone_1-00000013> Playing 'agent-loginok.gsm' (language 'en‬‬


‫‪-- Executing [*54@LocalSets:6] Hangup("SIP/Phone_1-00000013", "") in new stack‬‬
‫'‪== Spawn extension (LocalSets, *54, 6) exited non-zero on 'SIP/Phone_1-00000013‬‬
‫>‪CLI‬‬

‫همانطــور که مالحظه میکنید‪ ،‬اپراتور ‪ Phone_1‬به صف ‪ myqueue‬اضافه شــده اســت‪ .‬خروجی صف‬
‫بهصورت زیر است‪.‬‬
‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:11, SL:0.0% within 60s‬‬
‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (dynamic) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫در این روش نیز چون اپراتور بهصورت داینامیک اضافه شدهاست‪ ،‬عبارت ‪ dynamic‬دیده میشود‪.‬‬
‫شاید این سوال مطرح شود که از کجا بدانیم کدام کاربر را به صف اضافه کردهایم؟ این مقادیر بهوسیله‬
‫تابع ‪ CHANNEL‬بهصورت زیر دریافت میشود‪.‬‬
‫})‪${CHANNEL(channeltype)}/${CHANNEL(peername‬‬

‫بنابراین‪ ،‬هر نوع گوشی که کدهای فوق را اجرا کند‪ ،‬ابتدا باید })‪ ${CHANNEL(channeltype‬مشخص‬
‫شده باشد و بعد شماره اپراتوری })‪ ${CHANNEL(peername‬مشخص شود‪.‬‬
‫مثــال( فرض کنید اپراتوری با تلفن ‪ Phone_1‬یکی از کدهای باال را گرفتهباشــد‪ .‬در این صورت خروجی‬
‫توابع فوق بهصورت زیر خواهد بود‪:‬‬
‫• })‪ :${CHANNEL(channeltype‬خروجی این تابع ‪ SIP‬است‪.‬‬
‫• })‪ : ${CHANNEL(peername‬خروجی این تابع ‪ Phone_1‬است‪.‬‬
‫تا اینجا انواع روشهای ورود اپراتور به صف و یا حذف اپراتور از صف بررســی شــد‪ .‬مســلماً روش آخر‬
‫بهعنوان یک روش کاربردی در مورد کالسنترها قابل استفاده است‪ ،‬بهطوریکه اپراتورها میتوانند خودشان‬
‫به صف وارد و یا از آن خارج شوند‪ .‬پیش از ادامه بحث‪ ،‬بهتر است سناریویی را با هم بررسی کنیم‪.‬‬
‫تصمیم داریم یک کال ســنتر برای یک شرکت بسازیم‪ .‬مطابق آنچه گفته شد‪ ،‬استفاده از آخرین روش‬
‫برای ورود به صف یا خروج از آن‪ ،‬بهترین انتخاب اســت؛ ولی اینجا یک ســوال پیش میآید‪ :‬فرض کنید‬
‫این شــرکت تعداد ‪۱۵‬نفر پرســنل داشــته باشد که در سه شیفت کاری و در هر شــیفت ‪ ۵‬نفر به صورت ‪۲4‬‬
‫ســاعته خدمات ارائه میکنند‪ .‬در این شرایط ‪ ۱۵‬اپراتور داریم‪ ،‬اما پرسش این است که آیا برای هر نفر باید‬
‫‪ ۱۵‬گوشــی تلفن در نظر بگیریم یا اینکه با داشــتن ‪ ۵‬گوشــی تلفن هم میتوانیم یک کالســنتر راهاندازی‬
‫کنیم؟ مســلماً لزومی به داشــتن ‪ ۱۵‬گوشی تلفن نخواهد بود‪ ،‬اما چگونه میتوان با تنها ‪ ۵‬گوشی‪ ۱۵ ،‬اپراتور‬
‫را مدیریت و نظارت کرد؟‬
‫‪275‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫راه حل این اســت که گوشــیها بین همه اپراتورها مشترک باشند‪ .‬اینجا باید شرایطی فراهم شود که هر‬
‫اپراتور بتواند در سیســتم ‪ login/logout‬کند‪ .‬البته الگوی ‪ login/logout‬برای اپراتورها بهصورت پیشفرض‬
‫در استریســک وجود ندارد ولی اکنون بر اســاس دانشــی که به دســت آوردهاید باید بتوانیــد برنامه آن را‬
‫بنویســید‪ .‬در این برنامه میتوان با اســتفاده از ترکیب مثال های قبلی و تکنیک ‪ AstDB‬دادههای الزم را در‬
‫از ‪ AstDB‬باعث میشود بتوان برنامهای بهتر و انعطافپذیرتر داشت‪.‬‬ ‫‪ database‬ذخیره نمود‪ .‬استفاده‬

‫مشاهده وضعیت اپراتورها در صف‬


‫کنترل و مانیتورینگ اپراتورها در یک سیســتم کالســنتر‪ ،‬امری ضروری و اجتنابناپذیر است‪ .‬برای مثال‪،‬‬
‫پس از اینکه اپراتورها به صف وارد شدند‪ ،‬باید بتوانید وضعیت آنها را دائماً بررسی کنید‪ .‬هر اپراتور حاضر‬
‫در صف میتواند در یکی از این وضعیتها باشد‪:‬‬
‫• ‪ :Inuse/Busy‬در حال مکالمه است‪.‬‬
‫• ‪ :Not in use‬آزاد است‪.‬‬
‫• ‪ :Ringing‬در حال زنگ خوردن است‪.‬‬
‫• ‪ :Unavailable‬در دسترس نیست‪.‬‬
‫• ‪ :Pause‬در حال استراحت است‪.‬‬
‫اکنون این سؤال پیش میآیدکه آیا این قابلیت برای همه اپراتورها از هر نوعی )از قبیل ‪ SIP‬و ‪ DAHDI‬و‬
‫‪ IAX2‬و ‪ (...‬وجود دارد یا نه؟ سؤال بعدی این است که برنامه استریسک چگونه متوجه میشود که اپراتور‬
‫در چه وضعیتی قرار دارد؟ در پاســخ به ســوال اول باید گفت این قابلیتها فقط در پروتکل ‪ SIP‬تعریف و‬
‫بررسی میشوند و سایر ‪channel driver‬ها این قابلیت را ندارند‪ .‬اما اینکه استریسک چگونه متوجه وضعیت‬
‫اپراتورهــا میشــود باید گفت هنــگام تعریف یک داخلی از نــوع ‪ ،SIP‬باید در فایــــل ‪ ، sip.conf‬پارامتر‬
‫‪ callcounter=yes‬را برای داخلی مورد نظر تعریف کنید‪ .‬در این صورت استریســک وضعیت داخلی را در‬
‫صف متوجه میشــود‪ .‬برای مثال یک داخلی را در نظر بگیرید که ‪ callcounter‬آن روی مقدار ‪ No‬تنظیم‬
‫شــده است‪ ،‬سپس این داخلی را به عضویت یک صف درمیآید‪ .‬اگر از طریق داخلی تماسی ایجاد شود یا‬
‫داخلی در حال مکالمه باشــد‪ ،‬متاسفانه استریسک نمیتواند وضعیت درست آن را در صف تشخیص دهد و‬
‫بهصورت پیش فرض مقدار ‪ Not in use‬را در نظر میگیرد‪.‬‬
‫‪;sip.conf‬‬
‫]‪[Phone_1‬‬
‫‪callcounter=no‬‬

‫‪CLI> queue show‬‬


‫‪myqueue support has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 276

talktime), W:0, C:0, A:0, SL:0.0% within 60s


Members:
SIP/Phone_1 (dynamic) (Not in use) has taken no calls yet
No Callers

‫ استریسک وضعیت اپراتور‬،‫ تنظیم شــود و شرایط قبل دوباره تست شود‬yes ‫اکنون چنانچه این پارامتر برابر‬
.‫ نمایش میدهد‬In use ‫در صف را‬
;sip.conf
[Phone_1]
callcounter=yes

CLI> queue show


myqueue support has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s
talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/0000FFFF0001 (dynamic) (In use) has taken no calls yet
No Callers

relaod ً‫ باید لزوما‬،‫ کل استریسک یا ماژول مورد نظر‬،‫نکته مهم این است که بعد از هر گونه تغییر در هر فایل‬
.‫ چنین قابلیتی را دراختیار نداریم‬،‫ ها‬channel driver ‫ نکته مهم دیگر اینکه هنگام اســتفاده از ســایر‬.‫شــود‬
.‫ مجموعهای از داخلیهای یک دســتگاه ســانترال باشــند‬،‫بهعنوان مثال فرض کنید اپراتورهای یک صف‬
‫ چون داخلیهای‬،‫در این حالت ما هیچ کنترل و نظارتی روی داخلیهای دســتگاه ســانترال نخواهیم داشت‬
،‫ در صف است؛ بنابراین‬unavailable ‫ هستند و وضعیت اپراتورها همیشه بهصورت‬DAHDI ‫سانترال از نوع‬
Device State ‫ در یک چنین شــرایطی میتوان از قابلیت‬.‫استریســک نمیتواند وضعیت آنها را مانیتور کند‬
.‫در استریسک استفاده کرد که در فصل دهم در مورد آن توضیح داده خواهدشد‬
‫ ایجاد‬queues.conf ‫ میتــوان صفهای مورد نیاز را درون فایــل‬،‫همانطــور کــه در ابتدای فصل آمد‬
،‫ برای تعریف صف‬.‫ در ابتدای فصل با برخی از پرکاربردترین پارامترهای تعریف صف آشــنا شــدیم‬.‫کرد‬
.‫ ارائه شدهاند‬۲-۹ ‫پارامترهای زیادی وجود دارد که اغلب آنها در جدول‬

Option yes, no Note


persistentmembers yes, no Set this to yes to store dynamically added members to queues in
the Asterisk database so they will be automatically re-added upon
Asterisk restart.
autofill MixMonitor, With autofill disabled, the queue application will attempt to deliver
<unspecified> calls to agents in a serial manner. This means only one call is
attempted to be distributed to agents at a time. Additional callers
are not distributed to agents until that caller is connected to an
agent. With autofill enabled, callers are distributed to available
agents simultaneously. You always want this set to yes.
277 ‫آشنایی با صف‌ها در استریسک‬

Option yes, no Note


monitor-type yes, no If you set this as MixMonitor, you are directing Asterisk to use the
Mix Monitor( ) application for recording calls within the queue. If you
do not specify a value or comment out the option, the Monitor( )
dialplan application will be used instead to record calls.
updatecdr yes, no Set this to yes so that when a queue call is answered by an agent,
Asterisk populates the dstchannel field of the CDR with the name
of the queue member. The value is defined when the agent logs in
using the Add QueueMember() application. This option is used to
mimic the behavior of chan_agent channels within the CDR.
shared_lastcall Music class This value is important when you have members logged into more
as defined by than one queue. It ensures that reference to their last call is shared
musiconhold.conf across all queues to ensure all queues will respect the wrapup time
of other queues.

musicclass Filename of the Sets the music class to be used by a particular queue. You
announcement can also override this value on a per-call basis using the
CHANNEL(musicclass) channel variable.

announce ringall, Used for playing an announcement to the agent that answers the
leastrecent, call, typically to let him know which queue the caller is coming from.
fewestcalls, Useful when the agent is in multiple queues, especially when calls
from the queue are set to autoanswer. Bear in mind that the length
random, of time it takes to play this recording is added to the length of time
rrmemory, the caller has to wait (since they cannot hear it). Also consider
linear, wrandom that your agents will hear this recording several times per day, and
aren’t going to benefit from a long-winded message. If you use this
option, keep the recordings short; one or two words at most (and no
more than a second in length).

context Value of 0 or Allows a caller to exit the queue by pressing a single DTMF digit.
greater If a context is specified and the caller enters a number, that digit
will attempt to be matched in the context specified, and dialplan
execution will continue there. Note that by doing this, the caller also
loses their place in line.

strategy Value in seconds ringall: Rings all available members (default). This distribution
strategy doesn’t really count as ACD (automatic call distribution). In
traditional telephony terms, this would be known as a Ring Group.
leastrecent: Rings the interface that least recently received a
call. In a queue where there are many calls of roughly the same
duration, this can work. It doesn’t work as well if an agent has been
on a call for an hour, and their colleagues all got their last call 30
minutes ago, because the agent who just finished the 60-minute
call will get the next one.
fewestcalls: Rings the interface that has completed the fewest
calls in this queue. This can be unfair if calls are not always of the
same duration. An agent could handle three calls of 15 minutes
each and her colleague had four 5-second calls; the agent who
handled three calls will get the next one.
random: Rings a random interface. This actually can work very
well and end up being very fair in terms of evenly distributing calls
among agents.
Rrmemory: Rings members in a round-robin fashion, remembering
where it left off last for the next caller. This can also work out to be
very fair, but not as much as random.
linear: Rings members in the order specified, always starting at
the beginning of the list. This works if you have a team where there
are some agents who are supposed to handle most calls, and other
agents who should only get calls if the primary agents are busy.
wrandom: Rings a random member, but uses the members’
penalties as a weight. Worth considering in a larger queue with
complex weighting among the agents.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 278

Option yes, no Note


servicelevel Dialplan context This setting is not as useful as it should be. The idea is to define
the maximum acceptable time for a caller to wait before being
answered. You then note how many calls are answered within that
threshold, and they go toward your service level. So, for example, if
your service level is 60 seconds, and 4 out of 5 calls are answered
in 60 seconds or less, your service level is 80%. The reason this
metric is not so useful in Asterisk is because it’s not broken down in
any useful way (by hour or day of the week, for example).
penaltymemberslimit Value in seconds Used to disregard penalty values if the number of members in the
queue is lower than the value specified.
timeout Value in seconds Specifies the number of seconds to ring a member’s device. Also
see timeoutpriority.
retry app, conf Specifies the number of seconds to wait before attempting the
next member in the queue if the timeout value is exhausted while
attempting to ring a member of the queue.
timeoutpriority Value of 0 or Used to control the priority of the two possible timeout options
higher specified for a queue. The Queue() application has a timeout value
that can be specified to control the absolute time a caller can be in
the queue. The timeout value in queues.conf controls the amount of
time (along with retry) to ring a member for. Sometime these values
conflict, so you can control which value takes precedence. The
default is app, as this is the way it works in previous versions.
weight Value in seconds Defines the weight of a queue. A queue with a higher weight
defined will get first priority when members are associated with
multiple queues. Keep in mind that if you have a very busy queue
with a high weight, callers in a lower-weight queue might never get
answered (or have to wait for a long time).
wrapuptime yes, no The number of seconds to keep a member unavailable in a queue
after completing a call. This time allows an agent to finish any
postcall processing they may need to handle
before they are presented with the next call.
autofill yes, no, all Same as defined in the [general] section. This value can be defined
per queue.
autopause Value of 0 or Enables/disables the automatic pausing of members who fail to
higher answer a call. A value of all causes this member to be paused
in all queues she is a member of. This parameter can be tricky
in a live environment, because if the agent doesn’t know they’ve
been paused, you could end up with agents waiting for calls, not
knowing they’ve been paused. Never use this unless you have a
way to indicate to the members that they’ve been paused, or have
a supervisor who is watching the status of the queue in real time.
This is also a training issue, in that agents need to be taught that
answering a call from the queue is not optional; the queue expects
them to answer every call it presents to them.
maxlen Value in seconds Specifies the maximum number of callers allowed to be
waiting in a queue. A value of zero means an unlimited
number of callers are allowed in the queue.
announce-frequency Value in seconds Defines how often we should announce the caller’s position and/or
estimated hold time in the queue. Set this value to zero to disable.
In a small call center, it is unlikely that the system will be able to
make accurate estimates, and thus callers are more likely to find
this information frustrating.
279 ‫آشنایی با صف‌ها در استریسک‬

Option yes, no Note


min-announce- Value in seconds Specifies the minimum amount of time that must pass
frequency before we announce the caller’s position in the queue again. This is
used when the caller’s position may change frequently, to prevent
the caller hearing multiple updates in a short period of time.
periodic-announce- yes, no Indicates how often we should make periodic
frequency announcements to the caller. Bear in mind that playing a
message to callers on a regular basis will tend to upset
them, so give some thought to a) keeping this message
short, and b) not playing it too frequently. Pleasant music
will keep your callers far more happy than endlessly
repeated apologies or advertising.
random-periodic- yes, no If set to yes, will play the defined periodic announcements in a
announce random order. See periodic-announce.
relative-periodic- yes, no, once If set to yes, the periodic-announce-frequency
announce timer will start from when the end of the file being played back is
reached, instead of from the beginning. Defaults to no.
announce-holdtime yes, no, limit, Defines whether the estimated hold time should be played along
with the periodic announcements. Can be set to yes, no, or only
once.
announce-position more Defines whether the caller’s position in the queue should be
announced to her. If set to no, the position will never be announced.
If set to yes, the caller’s position will always be announced. If the
value is set to limit, the caller will hear her position in the queue only
if it is within the limit defined by announce-position-limit. If the value
is set to more, the caller will hear her position if it is beyond the
number defined by announce-position-limit. If you have any logic in
your system that can promote callers in rank (i.e., high-priority calls
get moved to the front of the queue), it is best not to use this option.
Very few things upset a caller more than hearing that they’ve been
moved toward the back of the line.
announce-position- Number of zero Used if you’ve defined announce-position as either
limit or greater limit or more.
announce-round- Value in seconds If this value is nonzero, the number of seconds is announced and
seconds rounded to the value defined.
queue-thankyou Filename of If not defined, plays the default value (“Thank you for your
prompt to play patience”). If set to an empty value, prompt will not be played at all.
queue-youarenext Filename of If not defined, plays the default value (“You are now first in line”). If
prompt to play set to an empty value, prompt will not be played at all.
queue-thereare Filename of If not defined, plays the default value (“There are”). If set to an
prompt to play empty value, prompt will not be played at all.
queue-callswaiting Filename of If not defined, plays the default value (“calls waiting”). If set to an
prompt to play empty value, prompt will not be played at all.
queue-holdtime Filename of If not defined, plays the default value (“The current estimated hold
prompt to play time is”). If set to an empty value, prompt will not be played at all.
queue-minutes Filename of If not defined, plays the default value (“minutes”). If set to an empty
prompt to play value, prompt will not be played at all.
queue-seconds Filename of If not defined, plays the default value (“seconds”). If set to an empty
prompt to play value, prompt will not be played at all.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 280

Option yes, no Note


queue-reporthold Filename of If not defined, plays the default value (“Hold time”). If set to an
prompt to play empty value, prompt will not be played at all.
periodic-announce A set of periodic Prompts are played in the order they are defined. Defaults to
announcements queue-periodic-announce (“All representatives are currently
to be played, busy assisting other callers. Please wait for the next available
separated by representative”).
commas
monitor-format gsm, wav, wav49, Specifies the file format to use when recording. If
<any valid file monitor-format is commented out, calls will not be
format> recorded.
monitor-type MixMonitor Same as monitor-type as defined in the [general]
section, but on a per-queue basis. If you want the old
monitor behavior, simply remove or remark out this option entirely.
joinempty paused, penalty, Controls whether a caller is added to the queue when no members
inuse, ringing, are available. Comma-separated options can be included to define
unavailable, how this option determines whether members are available. The
invalid, definitions for the values are:
unknown, wrapup paused: Members are considered unavailable if they are paused.
penalty: Members are considered unavailable if their penalties
are less than QUEUE_MAX_PENALTY.
inuse: Members are considered unavailable if their device status
is In Use.
ringing: Members are considered unavailable if their device
status is Ringing.
unavailable: Applies primarily to agent channels; if the agent
is not logged in but is a member of the queue, the channel is
considered unavailable.
invalid: Members are considered unavailable if their device
status is Invalid. This is typically an error condition.
unknown: Members are considered unavailable if device status is
unknown.
wrapup: Members are considered unavailable if they are currently
in the wrapup time after the completion of a call.
leavewhenempty paused, penalty, Used to control whether callers are kicked out of the queue when
inuse, ringing, members are no longer available to take calls. See joinempty for
unavailable, more information on the assignable values.
invalid,
unknown, wrapup
eventwhencalled yes, no, vars If set to yes, the following manager events will be sent to the
Asterisk Manager Interface (AMI):
• AgentCalled
• AgentDump
• AgentConnect
• AgentComplete
If set to vars, all channel variables associated with the agent
will also be sent to the AMI.
eventmemberstatus yes, no If set to yes, the QueueMemberStatus event will be
sent to AMI. Note that this may generate a lot of manager events.
reportholdtime yes, no Enables reporting of the caller’s hold time to the queue
member prior to bridging. Keep in mind that playing this
information to the agent will consume time, which to the
caller will represent even more hold time.
281 ‫آشنایی با صف‌ها در استریسک‬

Option yes, no Note


ringinuse yes, no Used to avoid sending calls to members whose status is InUse.
Recall from our discussion in the preceding section that only the
SIP channel driver is currently able to accurately report this status.
memberdelay Value in seconds Used if you want a delay prior to the caller and queue
member being connected to each other.
timeoutrestart yes, no If set to yes, resets the timeout for an agent to answer if either a
BUSY or CONGESTION status is received from the channel. This
can be useful if the agent is allowed to reject or cancel a call.
defaultrule Rule as defined Associates a queue rule as defined in queuerules.conf to this
in queuerules. queue; is used to dynamically change the minimum and maximum
conf penalties, which are then used to select an available agent.
member Device Used to define static members in a queue. To define a static
member, you supply its Technology/Device_ID (e.g., Agent/1234,
SIP/0000FFFF0001, DAHDI/
g0/14165551212).
setinterfacevar yes If set to yes, the following channel variables will be set just prior to
bridging the caller to the queue member:
MEMBERINTERFACE
The member’s interface, such as Agent/1234
MEMBERNAME
The name of the member
MEMBERCALLS
The number of calls the interface has taken
MEMBERLASTCALL
The last time the member took a call
MEMBERPENALTY
The penalty value of the member
MEMBERDYNAMIC
Indicates whether the member was
dynamically added to the queue or not
MEMBERREALTIME
Indicates whether the member is included
from real time or not
setqueueentryvar yes, no If set to yes, the following channel variables will be set just prior to
the call being bridged:
QEHOLDTIME
The amount of time the caller was held in the queue
QEORIGINALPOS
The position the caller originally entered the queue at
membermacro Name of a macro Defines a macro to be executed just prior to bridging the caller
defined in the and the queue member. You can use this macro with the previous
dialplan options (which set the additional channel variables), allowing you to
evaluate queue conditions in your system at the very moment a call
is delivered to an agent. If this interests you, make sure you look
into using the Asterisk Local channel instead (define your queue
members as Local channels). You will then be able to implement
routing decisions that take place right before a call is presented to
an agent, which can give you far more control over your queues
than app_queue can provide on its own.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 282

Option yes, no Note


setqueuevar yes, no If set to yes, the following channel variables will be set just prior to
the call being bridged:
QUEUENAME
The name of the queue
QUEUEMAX
The maximum number of calls allowed in this queue
QUEUESTRATEGY
The strategy method defined for the queue
QUEUECALLS
The number of calls currently in the queue
QUEUEHOLDTIME
The current average hold time of callers in the queue
QUEUECOMPLETED
The number of completed calls in this queue
QUEUEABANDONED
The number of abandoned calls
QUEUESRVLEVEL
The queue service level
QUEUESRVLEVELPERF
The queue’s service-level performance
2-9 ‫جدول‬

‫مدیریت و کنترل اعالن‌ها در صف‬


‫ میتوان از یک کالس برای پخش موزیک‬،‫هنگامی که افراد در صف منتظرند تا به اپراتورها متصل شوند‬
‫ میتوان اعالنهایی برای افراد‬،‫ هنگام پخش موزیک انتظار‬،‫ به عنوان یک ترفند جالب‬.‫انتظار اســتفاده کرد‬
‫ از حدود‬،‫حاضــر در صف پخش کرد تا از یکنواختی صدای موزیک انتظار خســته نشــوند و عالوه بر این‬
‫ جدول زیر انواع اعالنهای صوتی را نمایش‬.‫ آگاه شــوند‬،‫زمــان باقی مانده تا امکان ارتباط با اولین اپراتور‬
‫ جدول‬.‫ چگونگی تعریف و تنظیم زمان تکرار اعالنهای صوتی از اهمیت خاصی برخوردار اســت‬.‫میدهد‬
.‫ انواع اعالنها را در صف نشان میدهد‬۳-۹

Option yes, no Note


announce-frequency Value in seconds Defines how often we should announce the caller’s position and/or
estimated hold time in the queue. Set this value to zero to disable.
In a small call center, it is unlikely that the system will be able to
make accurate estimates, and thus callers are more likely to find this
information frustrating.
min-announce- Value in seconds Specifies the minimum amount of time that must pass
frequency before we announce the caller’s position in the queue again. This is
used when the caller’s position may change frequently, to prevent the
caller hearing multiple updates in a short period of time.
periodic-announce- yes, no Indicates how often we should make periodic
frequency announcements to the caller. Bear in mind that playing a
message to callers on a regular basis will tend to upset
them, so give some thought to a) keeping this message
short, and b) not playing it too frequently. Pleasant music
will keep your callers far more happy than endlessly
repeated apologies or advertising.
283 ‫آشنایی با صف‌ها در استریسک‬

Option yes, no Note


random-periodic- yes, no If set to yes, will play the defined periodic announcements in a
announce random order. See periodic-announce.
relative-periodic- yes, no, once If set to yes, the periodic-announce-frequency
announce timer will start from when the end of the file being played back is
reached, instead of from the beginning. Defaults to no.
announce-holdtime yes, no, limit, Defines whether the estimated hold time should be played along with
the periodic announcements. Can be set to yes, no, or only once.
announce-position more Defines whether the caller’s position in the queue should be
announced to her. If set to no, the position will never be announced.
If set to yes, the caller’s position will always be announced. If the
value is set to limit, the caller will hear her position in the queue only
if it is within the limit defined by announce-position-limit. If the value
is set to more, the caller will hear her position if it is beyond the
number defined by announce-position-limit. If you have any logic in
your system that can promote callers in rank (i.e., high-priority calls
get moved to the front of the queue), it is best not to use this option.
Very few things upset a caller more than hearing that they’ve been
moved toward the back of the line.
announce-position- Number of zero Used if you’ve defined announce-position as either
limit or greater limit or more.
announce-round- Value in seconds If this value is nonzero, the number of seconds is announced and
seconds rounded to the value defined.
3-9 ‫جدول‬

‫ نوع فایلی که باید پخش‬4-۹ ‫ در جدول‬.‫ زمان پخش اعالنهای صوتی مشــخص شــده است‬۳-۹ ‫در جدول‬
.‫ مشخص گردیده است‬،‫شود‬

Option yes, no Note


musicclass Filename of the Sets the music class to be used by a particular queue. You
announcement can also override this value on a per-call basis using the
CHANNEL(musicclass) channel variable.
queue-thankyou Filename of If not defined, plays the default value (“Thank you for your patience”).
prompt to play If set to an empty value, prompt will not be played at all.
queue-youarenext Filename of If not defined, plays the default value (“You are now first in line”). If
prompt to play set to an empty value, prompt will not be played at all.
queue-thereare Filename of If not defined, plays the default value (“There are”). If set to an empty
prompt to play value, prompt will not be played at all.
queue-callswaiting Filename of If not defined, plays the default value (“calls waiting”). If set to an
prompt to play empty value, prompt will not be played at all.
queue-holdtime Filename of If not defined, plays the default value (“The current estimated hold
prompt to play time is”). If set to an empty value, prompt will not be played at all.
queue-minutes Filename of If not defined, plays the default value (“minutes”). If set to an empty
prompt to play value, prompt will not be played at all.
queue-seconds Filename of If not defined, plays the default value (“seconds”). If set to an empty
prompt to play value, prompt will not be played at all.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 284

Option yes, no Note


queue-reporthold Filename of If not defined, plays the default value (“Hold time”). If set to an empty
prompt to play value, prompt will not be played at all.
periodic-announce A set of periodic Prompts are played in the order they are defined. Defaults to queue-
announcements periodic-announce (“All representatives are currently busy assisting
to be played, other callers. Please wait for the next available representative”).
separated by
commas
4-9 ‫جدول‬

ً ‫ را که قب‬myqueue ‫مثــال( فرض کنید بخواهیم صف‬


‫ کامل و اعالنهایی را به آن اضافه‬،‫ال تعریف کردهایم‬
.‫کنیم‬
[general]
autofill=yes
shared_lastcall=yes

[myqueue]
musicclass=default
strategy=rrmemory
joinempty=yes
leavewhenempty=no
ringinuse=no
;-------- Announcement Control --------
announce-frequency=30
min-announce-frequency=30
periodic-announce-frequency=45
random-periodic-announce=no
relative-periodic-announce=yes
announce-holdtime=once
announce-position=limit
announce-position-limit=10
announce-round-seconds=30

،‫ اعالنهایی نیز در فواصل زمانی معین برای افراد حاضر در صف‬،‫ عالوه بر آهنگ انتظار‬،‫مطابــق برنامه باال‬
‫ خروجی زیر را خواهیم‬،‫ با فراخوانی صف در برنامه‬.‫ فرض کنید صف باال را داشته باشــید‬.‫پخش میشــود‬
:‫داشت‬
== Using SIP RTP CoS mark 5
-- Executing [7000@LocalSets:1] Answer("SIP/Phone_1-00000014", "") in new stack
-- Executing [7000@LocalSets:2] Verbose("SIP/Phone_1-00000014", "2,"Phone_1"
<Phone_1> entering the support queue") in new stack
== "Phone_1" <Phone_1> entering the support queue
-- Executing [7000@LocalSets:3] Queue("SIP/Phone_1-00000014", "myqueue") in new stack
-- Started music on hold, class 'default', on SIP/Phone_1-00000014
-- Stopped music on hold on SIP/Phone_1-00000014
-- <SIP/Phone_1-00000014> Playing 'queue-youarenext.gsm' (language 'en')
‫‪285‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫)‪-- Told SIP/Phone_1-00000014 in myqueue their queue position (which was 1‬‬
‫)'‪-- <SIP/Phone_1-00000014> Playing 'queue-thankyou.gsm' (language 'en‬‬
‫‪-- Started music on hold, class 'default', on SIP/Phone_1-00000014‬‬

‫همانطور که مالحظه میکنید ابتدا اعالن »‪ «queue-youarenext.gsm‬و سپس اعالن »‪queue-thankyou.‬‬


‫‪ «gsm‬پخش میشود و پس از آن موزیک انتظار پخش میشود‪ .‬این فایلها بهصورت پیشفرض ضبط شده‬
‫هســتند‪ .‬میتوانید این فایلها را با یک نام فارســی در مســیر زیر جایگزین کنید و یا با تغییر دادن مسیر فایل‬
‫های صوتی در استریسک از فایلهای صوتی دیگری استفاده کنید‪.‬‬
‫‪#ls -lh /var/lib/asterisk/sounds/en/queue-youarenext.gsm‬‬

‫صف‌های وزن‌دار (با اولویت)‬


‫محدودیتی در تعریف تعداد صفها در استریســک وجود ندارد‪ .‬گاهی نیاز داریم از صفهای اولویتدار‬
‫اســتفاده کنیــم‪ .‬اولویت در صفها به معنای باالتر بودن اهمیت آنهاســت‪ .‬اولویــت در صفها زمانی رخ‬
‫میدهد که اپراتورها‪ ،‬عضو چندین صف متفاوت بهصورت همزمان و با اولویتهای متفاوت باشند؛ در غیر‬
‫اینصورت اولویت در صفها معنایی ندارد‪.‬‬
‫مثــال( فــرض کنید اپراتور ‪ Phone_1‬عضو صــف ‪ support‬با اولویت صفر و صــف ‪ support-priority‬با‬
‫اولویت‪ ۱۰‬است‪ .‬شکل ‪ ۹-۳‬را در نظر بگیرید‪.‬‬

‫شکل ‪3-9‬‬

‫ازآنجاکه صفها دارای اولویتهای متفاوتی هستند‪ ،‬تا زمانی که تماسی در صف ‪ support-priority‬وجود‬
‫داشتهباشــد‪ ،‬تماسهای صف ‪ support‬بهوسیله این اپراتور پاسخ داده نمیشوند‪ .‬اینجا ما دو صف داریم که‬
‫هر کدام اولویتهای متفاوتی دارند‪ .‬تعریف این دو صف در استریسک بهصورت زیر است‪:‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 286

[support_template](!)
musicclass=default
strategy=rrmemory
joinempty=yes
leavewhenempty=no
ringinuse=no
;-------- Announcement Control --------
announce-frequency=30
min-announce-frequency=30
periodic-announce-frequency=45
random-periodic-announce=no
relative-periodic-announce=yes
announce-holdtime=once
announce-position=limit
announce-position-limit=10
announce-round-seconds=30

[support](support_template)
weight=0
member=>Phone_1

[support-priority](support_template)
weight=10
member=>Phone_1

:‫ در کامندالین استریسک بهصورت زیر است‬queue show ‫خروجی دستور‬


CLI> queue show
support has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 0s
Members:
SIP/Phone_1 (ringinuse disabled) (Not in use) has taken no calls yet
No Callers

support-priority has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime),
W:10, C:0, A:0, SL:0.0% within 0s
Members:
SIP/Phone_1 (ringinuse disabled) (Not in use) has taken no calls yet
No Callers
CLI>

weight ‫ هر چه‬.‫ میتوان اولویت آن را تغییــر داد‬،‫ هنــگام تعریف یک صف‬weight ‫بــا اســتفاده از پارامتر‬
‫ نحوهی استفاده از صفهای اولویتدار دقیقاً همانند صفهای‬.‫ اولویت صف باالتر خواهد بود‬،‫بیشتر باشد‬
.‫ اولویت صفها مشخص شدهاند‬،‫ همانطورکه در خروجی دستور باال مشاهده میکنید‬.‫معمولی است‬
‫ شــرایط گرســنگی اســت؛ به این مفهوم کــه تا زمانی که‬،‫نکته مهم اســتفاده از صفهای اولویتدار‬
‫‪287‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫تماسهایی در صف با اولویت باالتر وجود داشــته باشــند‪ ،‬اپراتورها آنها را پاســخ میدهند و این به منزله‬
‫شرایط گرسنگی یا عدم سرویسدهی به صفهای با اولویت پایینتر است‪ .‬برای جلوگیری از چنین شرایطی‬
‫بهتر است اپراتورها بین صفها مشترک نباشند‪.‬‬
‫اکنون فرض کنید خروجی دستور ‪ queue show‬بهصورت زیر باشد‪:‬‬
‫‪CLI> queue show‬‬
‫‪support has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:1,‬‬
‫‪C:0, A:0, SL:0.0% within 0s‬‬
‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (Not in use) has taken no calls yet‬‬
‫‪SIP/Phone_2 (ringinuse disabled) (dynamic) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬

‫‪support-priority has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime),‬‬
‫‪W:2, C:0, A:0, SL:0.0% within 0s‬‬
‫‪Members:‬‬
‫‪SIP/Phone_1 (ringinuse disabled) (Not in use) has taken no calls yet‬‬
‫‪SIP/Phone_3 (ringinuse disabled) (dynamic) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬
‫>‪CLI‬‬

‫در این حالت اپراتور ‪ phone_1‬در هر دو صف عضو اســت و تماسهای صف ‪ support-priority‬برای این‬
‫اپراتور از اولویت باالتری برخوردار است‪ .‬سایر اپراتورها در این حالت روال معمول خود را دارند و اولویت‬
‫صف برای آنها اعمال نخواهد شد‪.‬‬

‫اولویت‌گذاری در اپراتورهای عضو یک صف‬


‫یکــی دیگــر از قابلیتهای صفها‪ ،‬ایجاد تمایز میان اپراتورهای یک صف اســت‪ .‬به عبارت دیگر اعضای‬
‫یک صف )اپراتورها( در حالت پیشفرض‪ ،‬همگی دارای یک اولویت یکسان برای پاسخگوییاند‪ .‬میتوان‬
‫بین اپراتورهای یک صف‪ ،‬اولویت پاسخگویی را تعریف نمود‪ .‬بهعنوان مثال تعریف زیر را برای یک صف‬
‫در نظر بگیرید‪:‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬

‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
‫‪joinempty=yes‬‬
‫‪leavewhenempty=no‬‬
‫‪ringinuse=no‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪288‬‬

‫‪;-------- Announcement Control --------‬‬


‫‪announce-frequency=30‬‬
‫‪min-announce-frequency=30‬‬
‫‪periodic-announce-frequency=45‬‬
‫‪random-periodic-announce=no‬‬
‫‪relative-periodic-announce=yes‬‬
‫‪announce-holdtime=once‬‬
‫‪announce-position=limit‬‬
‫‪announce-position-limit=10‬‬
‫‪announce-round-seconds=30‬‬

‫‪member => SIP/100,1‬‬


‫‪member => SIP/101,2‬‬

‫در این صف‪ ،‬دو اپراتور تعریف شدهاست‪ .‬عددی که بعد از تعریف اپراتور آمده به معنی اولویت )جریمه(‬
‫است‪ .‬هر چه این عدد بزرگتر باشد به منزله اولویت کمتر است‪.‬‬
‫در این صف‪ ،‬صرف نظر از اینکه اســتراتژی تماس به چه صورت تعریف شــده است‪ ،‬ابتدا اپراتورهایی‬
‫کــه از اولویت باالتری )عدد جریمه کمتــر( برخوردارند زنگ میخورند‪ .‬بهعنوان مثال اگر اپراتور ‪ ۱۰۰‬در‬
‫وضعیت ‪ Not in use‬باشــد‪ ،‬فقط این اپراتور زنگ میخورد؛ در غیر اینصورت ‪ ۱۰۱‬زنگ خواهد خورد و‬
‫به همین ترتیب عملیات ادامه خواهد یافت‪.‬‬
‫درصورتیکه اپراتور ‪ ۱۰۰‬تماس را پاســخ ندهد‪ ،‬تماس به ســوی ســایر اپراتورهای با اولویت پایینتر‬
‫)اپراتور ‪ (۱۰۱‬نخواهد رفت‪ .‬تنها در صورتی تماس به ســوی اپراتورهای اولویتپایین منتقل میشود که این‬
‫اپراتورها در وضعیت ‪ Busy‬یا ‪ In use‬و یا ‪ Unavailble‬باشــند‪ .‬این ســناریو میتواند برای برخی سازمانها‬
‫بسیار کاربردی باشــد‪ .‬بهعنوان مثال فرض کنید یک صف پشتیبانی ‪ support‬داشتهباشیم و تمام اپراتورهای‬
‫آن در یک اولویت قرار داشته باشند‪ .‬مدیر پشتیبانی هم میتواند در این صف‪ ،‬با اولویت کمتر عضو باشد تا‬
‫در مواردی که تمام اپراتورها مشغولند‪ ،‬بتواند تماسها را پاسخ دهد‪ .‬برای این منظور به مثال زیر توجه کنید‪:‬‬
‫]‪[support‬‬
‫‪member=>SIP/operator1,1‬‬
‫‪member=>SIP/operator2,1‬‬
‫‪member=>SIP/operator3,1‬‬
‫…‬
‫‪member=>SIP/operatorn,1‬‬
‫‪member=>SIP/manager,10‬‬

‫در این حالت اگر تمامی اپراتورها مشغول باشند‪ ،‬تماس به سمت مدیر پشتیبانی خواهد رفت‪.‬‬
‫مثال( فرض کنید ســه اپراتور با ســه صف متفاوت داشته باشــیم‪ .‬در تعریف زیر‪ ،‬هر کدام از این اپراتورها‪،‬‬
‫در هر ســه صف عضوند‪ ،‬ولی اولویت )‪ (penalty‬آنها در صف‪ ،‬با هم متفاوت اســت‪ .‬در این مثال اولویت‬
289 ‫آشنایی با صف‌ها در استریسک‬

.‫صفها با هم برابر است‬


[support](StandardQueue)
member => SIP/Phone_1,0,Phone_1; preferred
member => SIP/Phone_2,10, Phone_2 ; second preferred
member => SIP/Phone_3,20, Phone_3; least preferred

[sales](StandardQueue)
member => SIP/Phone_2,0, Phone_2
member => SIP/Phone_3,10, Phone_3
member => SIP/Phone_1,20, Phone_1

[billing](StandardQueue)
member => SIP/Phone_3,0, Phone_3
member => SIP/Phone_1,10, Phone_1
member => SIP/Phone_2,20, Phone_2

‫ در اولویت اول پاســخگویی اســت و در صف‬support ‫ در صف‬Phone_1 ‫همانطورکه مالحظه میکنید‬


‫ مطابق آنچه‬.‫ در اولویت آخر پاســخگویی قرار دارد‬sales ‫ در اولویت دوم پاســخگویی و درصف‬billing
‫ در هر سه روش میتوان اعضای‬.‫ میتوان با سه روش اعضای جدیدی به صف اضافه کرد‬،‫ال اشاره کردیم‬ ً ‫قب‬
.‫( به صف اضافه نمود‬penality) ‫جدید را با اولویت مشخصی‬
:‫در زیر هر یک از این روشها ارائه شدهاند‬
:‫ بهصورت داینامیک از طریق محیط کامندالین استریسک‬-۱
CLI> queue add member SIP/100 to myqueue penalty 1
CLI> queue add member SIP/101 to myqueue penalty 2

:member ‫ بهصورت استاتیک هنگام تعریف صف با پارامتر‬-۲


member => SIP/Phone_1,1
member => SIP/Phone_2,2

:‫ بهصورت داینامیک ازطریق برنامهنویسی استریسک‬-۳


[Queues]
exten => *54,1,Verbose(2,Logging In Queue Member)
same => n,Set(MemberChannel=${CHANNEL(channeltype)}/${CHANNEL(peername)})
same => n,AddQueueMember(myqueue,${MemberChannel},1)
same => n,Verbose(1,${AQMSTATUS}) ; ADDED, MEMBERALREADY, NOSUCHQUEUE
same => n,Playback(agent-loginok)
same => n,Hangup()

‫ به هیچ عنوان نمیتوانیم‬،‫ بعد از اضافهکردن اپراتور با اولویت مشخص به صف‬،‫همانطورکه مالحظه میکنید‬
‫ اما این هم یک‬.‫ مگر اینکه اپراتور را از صف خارج و دوباره به صف اضافه کنیم‬،‫اولویت آن را تغییر دهیم‬
.‫ بهتر است از قابلیت تعریف رولها در صف استفاده کنیم‬.‫روش مناسبی نیست‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪290‬‬

‫استفاده از ‪ queuerules‬در صف‌ها‬


‫اســتفاده از ‪ queuerules‬در صف‪ ،‬یکی از روشهای هوشــمندانه است‪ .‬با اســتفاده از این تکنیک میتوان‬
‫صفهــای قدرتمندی برای مدیریت و کنترل بهتر روی تماسهــای ورودی‪ ،‬طراحی کرد‪ .‬پیش از ورود به‬
‫جزئیات‪ ،‬بهتر است صورت مسئله را با مثالی توضیح دهیم‪.‬‬
‫فرض کنید یک سازمان دارای یک مرکز پاسخگویی است‪ .‬دراین مرکز ‪ ۵‬سطح اولویتگذاری تعریف‬
‫میشود‪ :‬سطح ‪ ،۱‬سطح ‪ ،۲‬سطح ‪ ،۳‬سطح ‪ ،4‬سطح ‪. ۵‬‬
‫بر اساس آنچه تاکنون آموختیم‪ ،‬ابتدا اعضای سطح ‪ ۱‬تماسهارا جواب میدهند و درصورتی تماسها به‬
‫سطح ‪ ۲‬منتقل میشوند که تمامی اعضای سطح ‪ ۱‬درحالت »‪ «Busy‬یا »‪ «Inuse‬و یا »‪ «Unavailahe‬باشند‪.‬‬
‫و این روال تا سطح ‪ ۵‬ممکن است پیش رود‪.‬‬
‫اکنون فرضکنید بخواهیم سطح پاسخگویی را محدود کنیم و فقط اعضای سطح ‪ ۲‬تا ‪ 4‬بتوانند تماسها‬
‫را پاسخ دهند‪ .‬در این روشتماسها هرگز به سطحهای ‪ ۱‬و ‪ 4‬و ‪ ۵‬متصل نخواهد شد‪.‬‬
‫فرض کنید صف زیر با اپراتورهای مشخصشده را داشتهباشیم‪:‬‬
‫]‪[Suppport‬‬
‫‪member=>SIP/100,1‬‬
‫‪member=>SIP/200,2‬‬
‫‪member=>SIP/300,3‬‬
‫‪member=>SIP/400,4‬‬
‫‪member=>SIP/500,5‬‬

‫اکنون هنگام فراخوانی صف‪ ،‬باید این قیود را تنظیم کنیم‪:‬‬


‫]‪[Queues‬‬
‫)‪exten => 7000,1,Verbose(2,Entering the support queue‬‬
‫‪same => n,Set(QUEUE_MIN_PENALTY=2) ; set minimum member penalty‬‬
‫‪same => n,Set(QUEUE_MAX_PENALTY=4) ; set maximum member penalty‬‬
‫‪same => n,Queue(support) ; entering the queue with min and max member penalties to be‬‬
‫‪used‬‬

‫همانطور کــه مالحظه میکنید‪ ،‬با تنظیمکــردن متغیرهــای ‪ QUEUE_MIN_PENALTY‬و _‪QUEUE‬‬


‫‪ MAX_PENALTY‬مشــخص کردیم که فقط اعضای حاضر در این ســطوح میتوانند تماسها را پاســخ‬
‫با حفظ و رعایت اولویت‪ ،‬تماسها را پاسخ میدهند‪.‬‬ ‫دهند‪ .‬دراین مثال فقط اپراتورهای ‪ ۳۰۰ ،۲۰۰‬و ‪4۰۰‬‬
‫اکنون فرضکنید بخواهیم این سیاســت را در زمان اجــرا )‪ (RunTime‬تغییر دهیم‪ .‬به این معنی که اگر‬
‫تعداد تماسها زیاد شود و زمان انتظار در صف در حال افزایش باشد‪ ،‬قادر باشیم از سایر اعضا بخواهیم که‬
‫تماسها را پاسخ دهند‪ .‬دراین حالت باید از ‪ queuerules‬استفاده کنیم‪.‬‬
‫مثال( فرضکنید چنین روالی را در فایل ‪ queuerules.conf‬تعریف کرده باشیم‪:‬‬
‫‪;queuerules.conf‬‬
‫‪291‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫]‪[more_members‬‬
‫‪penaltychange => 60,5,1‬‬

‫پارامتر اول تعیین کنندۀ حداقل مدت زمانی اســت که باید ســپری شود تا تغییرات اولویت انجام پذیرد‬
‫)این پارامتر برای هر فردی که با مرکز تماس بگیرد و وارد صف شــود بهطور مســتقل محاسبه میشود( که‬
‫اینجا ‪ ۶۰‬ثانیه محاسبه شدهاست‪.‬‬
‫پارامتــر دوم برای متغیــر ‪ QUEUE_MAX_PENALTY‬در نظر گرفته میشــود‪ .‬این پارامتر میتواند‬
‫نسبی باشد‪ .‬برای مثال‪ ،‬اینجا پس از گذشت ‪ ۶۰‬ثانیه‪ ،‬حداکثر سطح پاسخگویی به سطح ‪ ۵‬تغییر یافته است‪.‬‬
‫پارامتر ســوم برای متغیر ‪ QUEUE_MIN_PENALTY‬در نظر گرفته میشود‪ .‬این پارامتر هم میتواند‬
‫باشد‪ .‬برای مثال‪ ،‬اینجا پس از گذشت ‪ ۶۰‬ثانیه‪ ،‬حداقل سطح پاسخگویی به سطح‪ ۱‬تغییر یافته است‪.‬‬ ‫نسبی‬
‫پــس از تنظیم رولهای مشــخص در فایــل ‪ ، queuerules.conf‬باید تغییــرات الزم در برنامه را هنگام‬
‫فراخوانی دستور ‪ queue‬داشتهباشیم‪ .‬این تغییرات بهصورت زیر خواهند بود ‪:‬‬
‫]‪[Queues‬‬
‫)‪exten => 7000,1,Verbose(2,Entering the support queue‬‬
‫‪same => n,Set(QUEUE_MIN_PENALTY=2) ; set minimum queue member penalty‬‬
‫‪same => n,Set(QUEUE_MAX_PENALTY=4) ; set maximum queue member penalty‬‬
‫‪; Queue(queuename[,options[,URL[,announceoverride[,timeout[,AGI[,macro[,gosub[,rule[,po‬‬
‫)]]]]]]]]]‪sition‬‬
‫‪same => n,Queue(support,,,,,,,,more_members) ; enter queue with minimum and maximum‬‬
‫‪member penalties‬‬

‫‪ app-queue‬را ‪ relood‬کنید‪.‬‬ ‫بعد از انجام تغییرات فوق‪ ،‬باید ماژول‬


‫‪CLI> module reload app-queue.so‬‬
‫‪CLI> queue reload all‬‬

‫برای مشاهده رولهای تعریف شده در‪ ، queuerules.conf‬میتوانید دستور زیر را در کامند الین استریسک‬
‫وارد کنید‪.‬‬
‫‪CLI> queue show rules‬‬

‫مثال( فرض کنید رولهای زیر را داشته باشیم‪:‬‬


‫‪;queuerules.conf‬‬
‫]‪[more_members‬‬
‫‪penaltychange => 30,+1‬‬
‫‪penaltychange => 45,,-1‬‬
‫‪penaltychange => 60,+1‬‬
‫‪penaltychange => 120,+2‬‬

‫همانطورکه مالحظه میکنید بعد از گذشــت ‪ ۳۰‬ثانیه‪ ،‬مقــدار ‪ QUEUE_MAX_PENALTY‬یک واحد‬


‫افزایش یافته است‪ .‬بعد از گذشت ‪ 4۵‬ثانیه یک سطح کمتر )سطح ‪ (۱‬هم میتواند تماسها را پاسخ دهد‪.‬‬
‫برای مشاهده جزئیات بیشتر‪ ،‬دستور زیر را تایپ کنید‪:‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪292‬‬

‫‪CLI> queue show rules‬‬


‫‪Rule: more_members‬‬
‫‪After 30 seconds, adjust QUEUE_MAX_PENALTY by 1 and QUEUE_MIN_PENALTY by 0‬‬
‫‪After 45 seconds, adjust QUEUE_MAX_PENALTY by 0 and QUEUE_MIN_PENALTY by -1‬‬
‫‪After 60 seconds, adjust QUEUE_MAX_PENALTY by 1 and QUEUE_MIN_PENALTY by 0‬‬
‫‪After 120 seconds, adjust QUEUE_MAX_PENALTY by 2 and QUEUE_MIN_PENALTY by 0‬‬

‫در این شرایط چنانچه تماسی وارد سیستم شود‪ ،‬بعد از گذشت ‪ ۳۰‬ثانیه‪ ،‬رول اول اعمال می شود‪ .‬سپس بعد‬
‫از گذشت ‪ ۱۵‬ثانیه)‪ 4۵‬ثانیه از بدو ورود( رول دوم اعمال می شود و به همین ترتیب ادامه پیدا خواهد کرد‪.‬‬

‫مدیریت الگ‌های صف در استریسک‬


‫همه رویدادهایی که در صف اتفاق میافتد‪ ،‬بهصورت الگ در سیستم ثبت میشوند‪ .‬برای مثال فرض کنید‬
‫تماسی وارد یک صف شده و بهوسیله یک اپراتور پاسخ داده شدهاست‪ .‬این گزارشات همگی در یک فایل‬
‫ضبط میشود‪.‬‬
‫اکنون برای فعالکردن این گزارشات‪ ،‬ابتدا باید فایل زیر را در استریسک باز کنید‪:‬‬
‫‪# vim /etc/asterisk/logger.conf‬‬

‫سپس پارامترها را به این صورت تنظیم کنید‪:‬‬


‫‪; logger.conf‬‬
‫‪queue_log = yes‬‬
‫‪queue_log_to_file = no‬‬
‫‪queue_log_name = queue_log‬‬

‫بعد از انجام این تنظیمات‪ ،‬حتما ماژول مربوط را ‪ reload‬نمایید‪.‬‬


‫‪CLI>logger reload‬‬

‫با انجام این تنظیمات‪ ،‬همه رویدادهایی که در کلیه صفها رخ دادهاند‪ ،‬در فایلی در مسیر زیر ثبت میشوند‪.‬‬
‫‪#vim /var/log/asterisk/queue_log‬‬

‫برای درک بهتر‪ ،‬بیایید با مثالی آن را بررســی کنیم‪ .‬فرض کنید یک صف بهصورت زیر در سیســتم تلفنی‬
‫استریسک داریم‪:‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬

‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
‫‪joinempty=yes‬‬
‫‪leavewhenempty=no‬‬
‫‪ringinuse=no‬‬
‫‪;-------- Announcement Control --------‬‬
‫‪293‬‬ ‫آشنایی با صف‌ها در استریسک‬

‫‪announce-frequency=30‬‬
‫‪min-announce-frequency=30‬‬
‫‪periodic-announce-frequency=45‬‬
‫‪random-periodic-announce=no‬‬
‫‪relative-periodic-announce=yes‬‬
‫‪announce-holdtime=once‬‬
‫‪announce-position=limit‬‬
‫‪announce-position-limit=10‬‬
‫‪announce-round-seconds=30‬‬

‫دستور زیر را برای مشاهده الگها در فایل اجرا کنید‪.‬‬


‫‪#tail -n 10 -f /var/log/asterisk/queue_log‬‬

‫اکنون سعی کنید با گرفتن کدهایی )مثل ‪ (*۵4‬که قب ً‬


‫ال تعریف کردهاید‪ ،‬کاربرانی را بهصورت داینامیک به‬
‫صف اضافه کنید‪ .‬خروجیها در فایل بهصورت زیر است‪:‬‬
‫‪;queue_log‬‬
‫|‪1471179637|1471179637.57|myqueue|SIP/100|ADDMEMBER‬‬
‫|‪1471179697|1471179697.58|myqueue|SIP/101|ADDMEMBER‬‬

‫همانطورکه مالحظه میکنید‪ ،‬کاربرهای ‪ ۱۰۰‬و ‪ ۱۰۱‬به صف ‪ myqueue‬اضافه شدهاند‪ .‬اکنون فرض کنید‬
‫یک تماس وارد صف شده است‪ ،‬در این صورت گزارش ها بهصورت زیر خواهندبود‪:‬‬
‫‪1471179844|1471179843.59|myqueue|NONE|ENTERQUEUE|||1‬‬
‫‪1471179859|1471179843.59|myqueue|SIP/101|RINGNOANSWER|15000‬‬
‫‪1471179886|1471179843.59|myqueue|SIP/100|RINGNOANSWER|15000‬‬
‫‪1471179902|1471179843.59|myqueue|SIP/101|RINGNOANSWER|4000‬‬
‫‪1471179917|1471179843.59|myqueue|SIP/101|CONNECT|73|1471179915.64|1‬‬
‫‪1471179937|1471179843.59|myqueue|SIP/101|COMPLETEAGENT|73|20|1‬‬

‫بر اســاس این گزارش ها‪ ،‬تماس وارد صفی به نام ‪ myqueue‬شدهاســت‪ .‬ابتدا اپراتور ‪ ۱۰۱‬به مدت ‪ ۱۵‬ثانیه‬
‫زنگ خورده‪ ،‬ولی پاســخی دریافت نشــده اســت‪ .‬سپس تماس به ســمت اپراتور ‪ ۱۰۰‬رفته و ‪ ۱۵‬ثانیه زنگ‬
‫میخورد ولی باز هم تماس پاســخ داده نمیشــود‪ .‬دوباره تماس به سمت اپراتور ‪ ۱۰۱‬میرود و در اینجا بعد‬
‫از ‪ 4‬ثانیه تماس پاسخ داده می شود‪ .‬براساس گزارش های موجود‪ ،‬تماس گیرنده به مدت ‪ 7۳‬ثانیه در صف‬
‫منتظر مانده و مکالمه او ‪ ۲۰‬ثانیه به طول انجامیده است‪.‬‬
‫اکنون سعی کنید با گرفتن کدهایی )مثل کد ‪(*7۲‬که قب ً‬
‫ال تعریف کردهاید‪ ،‬کاربرانی در صف به حالت‬
‫‪ pause‬تغییر وضعیت دهند‪ .‬خروجی الگ در فایل بهصورت زیر است‪.‬‬
‫‪;queue_log‬‬
‫|‪1471188601|NONE|myqueue|SIP/101|PAUSE‬‬
‫|‪1471188605|NONE|myqueue|SIP/100|PAUSE‬‬

‫یا با گرفتن کد ‪ *87‬کاربران از حالت ‪ pause‬خارج شوند‪.‬‬


‫‪;queue_log‬‬
‫|‪1471188698|NONE|myqueue|SIP/101|UNPAUSE‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 294

1471188702|NONE|myqueue|SIP/100|UNPAUSE|

.‫* کاربران از صف خارج شوند‬۵۶ ‫و با گرفتن کد‬


;queue_log
1471188798|1471188798.6|myqueue|SIP/101|REMOVEMEMBER|
1471188800|1471188800.7|myqueue|SIP/100|REMOVEMEMBER|

‫ البته‬.‫همانطورکه مالحظه میکنید از این الگها میتوان گزارش هایی در خصوص صفها بهدست آورد‬
.‫در فصل سیزدهم روشهای دیگری برای جمعآوری گزارش از سیستم را بررسی خواهیم کرد‬
.‫ انواع رویدادهای موجود در صف را نشان میدهد‬۵-۹ ‫جدول‬

Event Information provided


ABANDON Written when a caller in a queue hangs up before his call is answered by an agent. Three
parameters are provided for ABANDON: the position of the caller at hangup, the original
position of the caller when entering the queue, and the amount of time the caller waited prior to
hanging up.
ADDMEMBER Written when a member is added to the queue. The bridged channel name will be populated
with the name of the channel added to the queue.
AGENTDUMP Indicates that the agent hung up on the caller while the queue announcement was being
played, prior to them being bridged together.
AGENTLOGIN Recorded when an agent logs in. The bridged channel field will contain something like
Agent/9994 if logging in with chan_agent, and the first parameter field will contain the channel
logging in (e.g., SIP/0000FFFF0001).
AGENTLOGOFF Logged when an agent logs off, along with a parameter indicating how long the agent was
logged in for. Note that since you will often use RemoveQueueMember() for agent log off, this
parameter may not be written. See the REMOVEMEMBER event instead.
COMPLETEAGENT Recorded when a call is bridged to an agent and the agent hangs up, along with parameters
indicating the amount of time the caller was held in the queue, the length of the call with the
agent, and the original position at which the caller entered the queue.
COMPLETECALLER Same as COMPLETEAGENT, except the caller hung up and not the agent.
CONFIGURELOAD Indicates that the queue configuration was reloaded (e.g., via module reload app_queue.so).
CONNECT Written when the caller and the agent are bridged together. Three parameters are also written:
the amount of time the caller waited in the queue, the unique ID of the queue member’s
channel to which the caller was bridged, and the amount of time the queue member’s phone
rang prior to being answered.
ENTERQUEUE Written when a caller enters the queue. Two parameters are also written: the URL (if specified)
and the caller ID of the caller.
EXITEMPTY Written when the caller is removed from the queue due to a lack of agents available to answer
the call (as specified by the leavewhenempty parameter). Three parameters are also written:
the position of the caller in the queue, the original position at which the caller entered the
queue, and the amount of time the caller was held in the queue.
EXITWITHKEY Written when the caller exits the queue by pressing a single DTMF key on his phone to exit the
queue and continue in the dialplan (as enabled by the context parameter in queues.conf). Four
parameters are recorded: the key used to exit the queue, the position of the caller in the queue
upon exit, the
original position the caller entered the queue at, and the amount of time the caller was waiting
in the queue.
295 ‫آشنایی با صف‌ها در استریسک‬

Event Information provided


EXITWITHTIMEOUT Written when the caller is removed from the queue due to timeout (as specified by the timeout
parameter to Queue( )). Three parameters are also recorded: the position the caller was in
when exiting the queue, the original position of the caller when entering the queue, and the
amount of time
the caller waited in the queue.
PAUSE Written when a queue member is paused.
PAUSEALL Written when all members of a queue are paused.
UNPAUSE Written when a queue member is unpaused.
UNPAUSEALL Written when all members of a queue are unpaused.
PENALTY Written when a member’s penalty is modified. The penalty can be changed through several
means, such as the QUEUE_MEMBER_PENALTY( ) function, the Asterisk Manager Interface,
or the Asterisk CLI commands.
REMOVEMEMBER Written when a queue member is removed from the queue. The bridge channel field will
contain the name of the member removed from the queue.
RINGNOANSWER Logged when a queue member is rung for a period of time, and the timeout value for ringing
the queue member is exceeded. A single parameter will also be written indicating the amount
of time the member’s extension rang.
TRANSFER Written when a caller is transferred to another extension. Additional parameters are also
written, which include: the extension and context the caller was transferred to, the hold time of
the caller in the queue, the amount of time the caller was speaking to a member of the queue,
and the original position of the caller when he entered the queue.a
SYSCOMPAT Recorded if an agent attempts to answer a call, but the call cannot be set up due to
incompatibilities in the media setup.

5-9 ‫جدول‬

‫ بهتر است‬،‫ اما پیش از آنکه به فصل بعدی بپردازیم‬،‫ اینجا به پایان میرسد‬ACD ‫مطالب اصلی در خصوص‬
ACD ‫ این مورد شــاید جزو نکات کلیدی بحث‬.‫یک نکته کاربردی در خصوص صفها را بررســی کنیم‬
.‫نباشند ولی از اهمیت ویژهای برخوردار است‬

‫اعالم شماره اپراتور هنگام پاسخ‌گویی‬


،‫شاید با این موضوع تا به حال مواجه شده باشید که هنگامی که اپراتوری تماس را در صف پاسخ میدهد‬
‫ این کار‬.‫قبل از آنکه بخواهد با مشترک صحبت کند ابتدا شماره اپراتوری آن برای مشترک پخش میشود‬
.‫ مراحل زیر را انجام دهید‬،‫ برای فعال کردن این قابلیت در استریسک‬.‫به سادگی روی میدهد‬
.‫ابتدا باید پارامترهای زیر را به صفهای تعریف شده در مثالهای قبل اضافه کنید‬
[myqueue]
setinterfacevar=yes
setqueuevar=yes
setqueueentryvar=yes

‫ قیل از اینکه به‬،‫ چنانچه اپراتوری تماســی را در صف پاســخ دهد‬،‫پــس از تنظیم پارامترهای فوق در صف‬
.‫ مقداردهی میشود‬MEMBERINTERFACE ‫ یک متغیر کانال در استریسک به نام‬،‫مشترک متصل شود‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪296‬‬

‫مقدار این متغیر‪ ،‬شماره ی اپراتوری است که تماس را پاسخ داده است‪ .‬ما باید بتوانیم از این متغیر در برنامه‬
‫خود استفاده کنیم‪.‬‬
‫این نکته مهم اســت که اعالن شــماره اپراتور باید بعد از پاســخ دادن اپراتور در صف باشــد‪ .‬برای این‬
‫منظور پارامتری به نام ‪ AGI‬در صف داریم که پس از پاسخدهی اپراتور‪ ،‬ابتدا این فایل اجرا میشود و سپس‬
‫مشــترک به اپراتور متصل میشــود‪ .‬پس ما باید در آن فایل ‪ ،AGI‬شــماره اپراتور را اعالن کنیم‪ .‬برای مثال‬
‫نحوهی فراخوانی فایل ‪ AGI‬در صف میتواند بهصورت زیر باشد‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[Queues‬‬
‫)(‪exten => 7001,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,Queue(myqueue,,,,,AgentNumber.php‬‬
‫)(‪same => n,Hangup‬‬

‫اینجــا ما فایل ‪ AgentNumber.php‬را برای اعالم شــماره اپراتوری بــهکار میبریم‪ .‬این فایل بهصورت زیر‬
‫میتواند نوشته شود‪.‬‬
‫‪<?php‬‬
‫;)‪set_time_limit(30‬‬
‫;)"‪require("phpagi.php‬‬
‫;)‪error_reporting(E_ALL‬‬

‫;)(‪$agi = new AGI‬‬


‫;)(‪$agi->answer‬‬
‫;)"‪$member = $agi->get_variable("MEMBERINTERFACE‬‬ ‫‪//get memberinterface variable.‬‬
‫;)]'‪$agi->SayDigits($member['data‬‬
‫>?‬

‫البته برای پخش شــماره اپرتوری بهصورت فارســی باید از روش دیگری استفاده کرد‪ ،‬ولی در این مثال‬
‫توانستهاید شمارهی اپراتوری که به تماس پاسخ داده است را دریافت و اعالم کنید‪.‬‬
‫در فصل چهاردهم )ابزارهای برنامه نویســی در استریسک( درباره برنامهنویسی ‪ AGI‬توضیحات بیشتری‬
‫خواهیم داد‪.‬‬

‫نتیجه‌گیری‬
‫ابتدا با یک مثال ســاده‪ ،‬فصل شــروع شــد و در ادامه بخشهای مختلف ایجاد یک صف توضیح داده شد‪.‬‬
‫مهمترین کاربرد صفها‪ ،‬کنترل و مدیریت تماسهای ورودی اســت؛ بنابراین‪ ،‬صفهای هوشمند میتوانند‬
‫بســیار پرکاربرد باشــند‪ .‬نظارت و کنترل بر اپراتور نقش مهمی در سرویسدهی بهتر به مشتریان ایفا میکند‬
‫که چگونگی آن نیز شــرح داده شد‪ .‬به این ترتیب انتظار میرود با اطالعاتی که در این فصل در اختیار شما‬
‫قرار داده شد‪ ،‬بتوانید صفهایی هوشمند در سیستم استریسک ایجاد کنید‪.‬‬
‫فصل دهم‬

‫بررسی وضعیت تجهیزات‬


‫در شبکه‌های ویپ‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪298‬‬

‫مقدمه‬
‫در سیستمهای تلفنی‪ ،‬معموالً مشخصشدن وضعیت کاربران از اهمیت ویژهای برخوردار است‪ .‬در شبکههای‬
‫مخابراتی این امکان وجود ندارد که متوجه شویم شخص مورد نظر ما در دسترس قرار دارد یا نه‪ ،‬آیا در حال‬
‫‪Ring Back Tone‬‬ ‫مکالمه با شــخص دیگری است یا آزاد اســت‪ .‬اما هنگام برقراری تماس میتوان از نوع‬
‫به این وضعیت پی برد‪.‬‬
‫این وضعیت قابل تعمیم به شبکههای داخلسازمانی و حتی شبکههای نسل جدید ویپ نیز هست‪ .‬اهمیت‬
‫این ویژگی زمانی روشــن میشود که قصد نظارت و کنترل روی سیســتمهای تلفنی داشتهباشیم‪ .‬برای مثال‬
‫چنانچه در یک ســازمان‪ ،‬منشــی قصد داشته باشد تماسی را به فردی مشــخص متصل نماید‪ ،‬بدون دراختیار‬
‫داشتن این سیستم‪ ،‬صرف نظر از در دسترس بودن یا نبودن فرد‪ ،‬ممکن است تماس از دست برود‪.‬‬
‫بــه کمــک وضعیت دیوایسهــا‪) ۱‬در اینجا منظــور از دیوایس ها همــان ‪ SIPPhone‬ها می باشــد( در‬
‫شــبکههای ویپ‪ ،‬میتوان وضعیت تجهیزات ســختافزاری و حتی نرمافزاری را در شبکه بررسی و مانیتور‬
‫کنیــم‪ .‬بــه عنوان یک مثال کاربردی در فصل قبــل راجع به صفها و اپراتورهای صــف توضیح دادیم که‬

‫‪1- Device States‬‬


299 ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫ چگونگی بررسی وضعیت اپراتورها در صف‬.‫چگونه وضعیت اپراتورها را در صف میتوانیم مشاهده کنیم‬
.‫از جمله مباحث این فصل است‬

‫بررسی وضعیت دیوایس‌ها در استریسک‬


‫ وضعیت‬،‫ وجود دارد که میتوان به وسیله آن‬DEVICE_STATE ‫در سیســتم تلفنی استریســک تابعی بنام‬
.‫ برای مثال برنامه زیر را در نظر بگیرید‬.‫فعلی یک دیوایس را مشخص کرد‬
;extensions.conf
[LocalSets]
exten => 7001,1,Answer()
same => n,Verbose(3,The state of SIP/Phone_1 is ${DEVICE_STATE(SIP/Phone_1)})
same => n,Hangup()

‫ این‬.‫ نمایش دادهشود‬Phone_1 ‫ در برنامه خواســته شده که وضعیت دیوایس‬،‫همانطورکه مالحظه میکنید‬
.‫برنامه به دو روش فراخوانی میشود‬
:‫در روش اول برنامه به صورت زیر فراخوانی می شود‬
CLI> console dial 7001@LocalSets
-- Executing [7001@LocalSets:1] Answer("Console/dsp", "") in new stack
<< Console call has been answered >>
-- Executing [7001@LocalSets:2] Verbose("Console/dsp", "3,The state of SIP/Phone_1 is
NOT_INUSE") in new stack
-- The state of SIP/Phone_1 is NOT_INUSE
-- Executing [7001@LocalSets:3] Hangup("Console/dsp", "") in new stack
<< Hangup on console >>
CLI>

NOT_ ‫( در حالت‬Phone_1) ‫همانطورکــه مالحظه میکنید در ایــن حالت وضعیت دیوایس مورد نظــر‬
،‫ را شمارهگیری کنید‬7۰۰۱ ‫( شماره‬Phone_1)‫ در روش دوم چنانچه از طریق این دیوایس‬.‫ اســت‬INUSE
:‫بهصورت زیر خواهد بود‬ ‫وضعیت آن‬
CLI>
== Using SIP RTP CoS mark 5
-- Executing [7001@LocalSets:1] Answer("SIP/Phone_1-00000000", "") in new stack
-- Executing [7001@LocalSets:2] Verbose("SIP/Phone_1-00000000", "3,The state of SIP/
Phone_1 is INUSE") in new stack
-- The state of SIP/Phone_1 is INUSE
-- Executing [7001@LocalSets:3] Hangup("SIP/Phone_1-00000000", "") in new stack
== Spawn extension (LocalSets, 7001, 3) exited non-zero on 'SIP/Phone_1-00000000'
CLI>

.‫ است‬INUSE ‫( در حالت‬Phone_1) ‫در این حالت وضعیت دیوایس مورد نظر‬


‫ نخســت آشــنایی با مفهوم وضعیت دیوایس ها وکاربرد آن در سیستم تلفنی‬،‫در این فصل هدف اصلی‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪300‬‬

‫استریســک اســت‪ .‬از این مفهوم باید بتوانیم برای موارد خاص استفاده کنیم و آن را توسعه دهیم‪ .‬البته شاید‬
‫توضیح اولیه در این خصوص کمی با ابهام همراه باشــد ولی در ادامه به کمک چند مثال‪ ،‬با قابلیتهای آن‬
‫در برنامهنویسی استریسک آشنا خواهید شد‪.‬‬

‫بررسی انواع وضعیت دیوایس‌ها در استریسک‬


‫پیش از ادامه بحث‪ ،‬به این موضوع توجه داشته باشید که یک دیوایس در سیستم تلفنی استریسک میتواند‬
‫در یکی از وضعیتهای زیر باشد‪:‬‬
‫•‪ :UNKNOWN‬در این وضعیت استریسک نمی‌تواند وضعیت دیوایس مورد نظر را مشخص کند‪.‬‬
‫•‪ :NOT_INUSE‬در ایــن وضعیت‪ ،‬دیوایس در سیســتم تلفنی استریســک رجیســتر شــده و در حالت‬
‫بالاستفاده (‪ )idle‬است‪.‬‬
‫•‪ :INUSE‬در این وضعیت‪ ،‬دیوایس در سیستم تلفنی استریسک رجیستر شده و در حالت استفاده (صحبت‬
‫کردن) است‪ .‬امکان پشت‌خطی برای داخلی فعال است‪.‬‬
‫•‪ :BUSY‬این وضعیت دقیقاً مانند وضعیت ‪ INUSE‬است با این تفاوت که امکان پشت‌خطی برای دیوایس‬
‫فعال نیست‪.‬‬
‫•‪ :UNAVAILABLE‬در این وضعیت‪ ،‬استریسک نمی‌تواند وضعیت دیوایس مورد نظر را مشخص کند‪.‬‬
‫•‪ :RINGING‬در این وضعیت‪ ،‬دیوایس در حال زنگ خوردن است‪.‬‬
‫•‪ :RINGINGINUSE‬در این وضعیت‪ ،‬همزمان که دیوایس در حال مکالمه است‪ ،‬پشت خطی هم دارد‪.‬‬
‫•‪ :INHOLD‬در این وضعیت دیوایس در وضعیت ‪ HOLD‬است‪.‬‬
‫چنانچه در یک سیســتم تلفنی استریسک‪ ،‬دیوایس های زیادی رجیستر شده باشند‪ ،‬درصورت نیاز به برقرای‬
‫ارتباط با آن‌ها‪ ،‬ابتدا می‌توانید وضعیت آن‌ها را بررسی کنید که می‌تواند یکی از مقادیر باال باشد‪.‬‬

‫بررسی وضعیت اکستنشن‌ها در استریسک‬


‫یکی از قابلیتهای مهم سیســتم تلفنی استریسک‪ ،‬بررسی وضعیت اکستنشنهاست‪ .‬به کمک این قابلیت در‬
‫استریســک میتوان وضعیت اکستنشنهای مورد نظر را بررسی نمود‪ .‬در استریسک این قابلیت وجود دارد‬
‫که بتوان وضعیت همه اکستنشنها )از جمله کاربران( را بررسی کرد‪.‬‬
‫تفاوت عمدهی میان ‪ Device States‬و ‪ Extensions States‬این اســت که اولی وضعیت یک دیوایس‬
‫)در اینجا منظور وضعیت یک تلفن یا اپراتور در شبکه است( را نشان میدهد درحالیکه دومی وضعیت یک‬
‫اکستنشــن را در یک شــبکه نمایش میدهد‪ .‬برای روشنترشــدن موضوع به یک مثال میپردازیم‪ .‬به شکل‬
‫‪ ۱-۱۰‬توجه کنید‪:‬‬
‫‪301‬‬ ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫شکل ‪1-10‬‬

‫فــرض کنیــد ‪ Tom‬بخواهد وضعیت ‪ Bob‬را بررســی کند کــه اگر در حال مکالمه نبــود‪ ،‬با وی تماس‬
‫بگیرد‪ .‬اینجا ‪ Bob‬دو دیوایس مختلف )دو دســتگاه تلفن( دارد که از هر دو اســتفاده میکند‪ .‬اما اینکه ‪Tom‬‬
‫بخواهد هر دو دیوایس را بررسی کند‪ ،‬چندان جالب نخواهد بود‪ .‬بنابراین‪ ،‬هر دو دیوایس را به یک شماره‬
‫)اکستنشــن( مشــخص نگاشــت میدهیم‪ .‬اکنون هر زمان که ‪ Tom‬بخواهد وضعیت ‪ Bob‬را بررســی کند‪،‬‬
‫میتواند از آن اکستنشن استفاده نماید و وضعیت ‪ Bob‬را بررسی نماید‪.‬‬
‫برای نگاشت دیوایسها در یک اکستنشن‪ ،‬بهصورت زیر عمل کنید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[Custom_hints‬‬
‫‪exten = 7002,hint,SIP/Bob-mobile&SIP/Bob-desk‬‬

‫همانطورکه در شــکل ‪ ۲-۱۰‬مالحظه میشود‪ ،‬میتوان چندین ‪ Device States‬را به یک ‪Extensions‬‬


‫‪ States‬نگاشت داد‪.‬‬
‫در این حالت ‪ Tom‬با استفاده از اکستنشن ‪ 7۰۰۲‬میتواند وضعیت ‪ Bob‬را بررسی کند‪ .‬برای انجام این‬
‫کار‪ ،‬تنظیمات زیر را انجام دهید‪.‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫‪callcounter=yes‬‬

‫]‪[Tom‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪302‬‬

‫شکل ‪2-10‬‬
‫‪type=friend‬‬
‫‪subscribecontext=Custom_hints‬‬
‫‪allowsubscribe=yes‬‬

‫]‪[Bob-mobile‬‬
‫‪type=friend‬‬
‫‪busylevel=1‬‬

‫]‪[Bob-desk‬‬
‫‪type=friend‬‬
‫‪busylevel=1‬‬

‫با انجام این تنظیمات در استریســک‪ ،‬کاربر ‪ Tom‬میتواند وضعیت کاربر ‪ Bob‬را هر زمان که الزم باشــد‪،‬‬
‫بررســی کند‪ .‬در محیط کامندالین استریسک با دســتور زیر میتوان وضعیت تمام ‪Extension States‬ها را‬
‫مشاهده نمود‪.‬‬
‫‪CLI> core show hints‬‬

‫خروجی دستور بهصورت زیر است‪:‬‬


‫‪CLI> core show hints‬‬
‫‪-= Registered Asterisk Dial Plan Hints =-‬‬
‫‪7002@Custom_hints‬‬ ‫‪: SIP/Bob-mobile&Bob-desk State:Idle‬‬ ‫‪Watchers‬‬
‫‪0‬‬
‫‪- 1 hints registered‬‬
‫>‪CLI‬‬

‫تا اینجا شــرایطی فراهم شــد که هر زمان کاربر ‪ Tom‬تصمیم گرفت‪ ،‬بتواند وضعیت کاربر ‪ Bob‬را بررسی‬
‫کند‪.‬‬
‫برای بررســی وضعیت یک اکستنشــن در برنامهنویســی استریســک‪ ،‬از تابع ‪EXTENSION_STATE‬‬
‫‪303‬‬ ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫اســتفاده کنید‪ .‬این تابع بسیار شبیه به تابع ‪ DEVICE_STATE‬است‪ ،‬با این تفاوت که در پارامتر ورودی‪ ،‬از‬
‫اکستنشن بهجای دیوایس استفاده میشود‪.‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 7003,1,Answer‬‬
‫_‪same => n,Verbose(3,The state of 7002@default is ${EXTENSION_STATE(7002@Custom‬‬
‫)})‪hints‬‬
‫)(‪same => n,Hangup‬‬

‫خروجی برنامه بهصورت زیر خواهدبود‪:‬‬


‫‪CLI> console dial 7003@LocalSets‬‬
‫‪-- Executing [7003@LocalSets:1] Answer("Console/dsp", "") in new stack‬‬
‫>> ‪<< Console call has been answered‬‬
‫_‪-- Executing [7003@LocalSets:2] Verbose("Console/dsp", "3,The state of 7002@Custom‬‬
‫‪hints is NOT_INUSE") in new stack‬‬
‫‪-- The state of 7002@Custom_hints is NOT_INUSE‬‬
‫‪-- Executing [7003@LocalSets:3] Hangup("Console/dsp", "") in new stack‬‬
‫>> ‪<< Hangup on console‬‬
‫>‪CLI‬‬

‫خروجی تابع ‪ EXTENSION_STATE‬همانند تابع ‪ DEVICE_STATE‬است‪.‬‬

‫بررسی قابلیت ‪ SUBSCRIBE-NOTIFY‬در شبکه‌های ویپ‬


‫یکی از قابلیتهای مهم شــبکههای ویپ‪ ،‬اســتفاده از قابلیت ‪ SUBSCRIBE-NOTIFY‬اســت‪ .‬بهتر است‬
‫مطلب‪ ،‬با توجه به شکل ‪ ۱-۱۰‬توضیح داده شود‪.‬‬
‫فرض کنید ‪ Tom‬قصد داشــته باشــد وضعیت همه داخلیها )یا برخی از آنها( را برای همیشــه بررسی‬
‫کند‪ .‬در این حالت ‪ Tom‬با ارســال پیام ‪ Subscribe‬به استریســک‪ ،‬اعالم میکند که وضعیت اکستنشنها را‬
‫نیاز دارد‪ .‬در این صورت هر تغییری که در وضعیت اکستنشــنها رخ دهد‪ ،‬استریســک از طریق پیام ‪Notify‬‬
‫به کاربر ‪ Tom‬گزارش میدهد‪.‬‬
‫نکته مهمی که اینجا باید در نظر داشت این است که کاربر ‪ Tom‬باید از تلفنی )‪IPPhone, SoftPhone‬‬
‫و غیره( اســتفاده کند که از قابلیت ‪ SUBSCRIBE-NOTIFY‬پشتیبانی کند‪ ،‬درغیراینصورت نمیتوانید از‬
‫‪ BLF‬مشخص میشود‪.‬‬ ‫این قابلیت در استریسک استفاده کنید‪ .‬این قابلیت در گوشیهای تلفن با عنوان‬
‫چنانچه دستور "‪ "sip set debug on‬را در محیط کامند الین استریسک اجرا کنید‪ ،‬پیامهای مبادله شده‬
‫در استریسک برای اعالم وضعیت ‪ Bob‬به ‪ ، Tom‬قابل مشاهده خواهند بود‪.‬‬

‫>‪<--- SIP read from UDP:10.24.17.254:37509 ---‬‬


‫‪SUBSCRIBE sip:7002@10.24.18.124;transport=UDP SIP/2.0‬‬
‫‪Via: SIP/2.0/UDP 10.24.17.254:37509;branch=z9hG4bK-d8754z-c6908de6f0126edf-1---‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 304

d8754z-
Max-Forwards: 70
Contact: <sip:Tom@10.24.17.254:37509;transport=UDP>
To: <sip:7002@10.24.18.124;transport=UDP>
From: <sip:Tom@10.24.18.124;transport=UDP>;tag=f51e9632
Call-ID: ZjE2ZDAwYThiOTA2MzYxOWEwNTEwMjc1ZGIxNTk3NDU.
CSeq: 2 SUBSCRIBE
Expires: 1800
Accept: application/pidf+xml
Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
Supported: replaces, norefersub, extended-refer, timer, X-cisco-serviceuri
User-Agent: Z 3.2.21357 r21103
Authorization:Digest username="Tom",realm="asterisk",nonce="522456f4",uri="sip:7002
@10.24.18.124;transport=UDP",response="6d66dcad8c176aa3ef7baec7680d2445",algorit
hm=MD5
Event: presence
Allow-Events: presence, kpml
Content-Length: 0

SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.24.17.254:37509;branch=z9hG4bK-d8754z-c6908de6f0126edf-1---
d8754z-;received=10.24.17.254
From: <sip:Tom@10.24.18.124;transport=UDP>;tag=f51e9632
To: <sip:7002@10.24.18.124;transport=UDP>;tag=as46a6e039
Call-ID: ZjE2ZDAwYThiOTA2MzYxOWEwNTEwMjc1ZGIxNTk3NDU.
CSeq: 2 SUBSCRIBE
Server: Asterisk PBX SVN-branch-12-r413487
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
Expires: 1800
Contact: <sip:7002@10.24.18.124:5060>;expires=1800
Content-Length: 0

NOTIFY sip:Tom@10.24.17.254:37509;transport=UDP SIP/2.0


Via: SIP/2.0/UDP 10.24.18.124:5060;branch=z9hG4bK14aacddc
Max-Forwards: 70
From: <sip:7002@10.24.18.124;transport=UDP>;tag=as46a6e039
To: <sip:Tom@10.24.18.124;transport=UDP>;tag=f51e9632
Contact: <sip:7002@10.24.18.124:5060>
Call-ID: ZjE2ZDAwYThiOTA2MzYxOWEwNTEwMjc1ZGIxNTk3NDU.
CSeq: 102 NOTIFY
User-Agent: Asterisk PBX SVN-branch-12-r413487
Subscription-State: active
Event: presence
305 ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

Content-Type: application/pidf+xml
Content-Length: 530

<?xml version="1.0" encoding="ISO-8859-1"?>


<presence xmlns="urn:ietf:params:xml:ns:pidf"
xmlns:pp="urn:ietf:params:xml:ns:pidf:person"
xmlns:es="urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status"
xmlns:ep="urn:ietf:params:xml:ns:pidf:rpid:rpid-person"
entity="sip:Tom@10.24.18.124">
<pp:person><status>
<ep:activities><ep:away/></ep:activities>
</status></pp:person>
<note>Unavailable</note>
<tuple id="7002">
<contact priority="1">sip:7002@10.24.18.124</contact>
<status><basic>closed</basic></status>
</tuple>
</presence>
---
<--- SIP read from UDP:10.24.17.254:37509 --->
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.24.18.124:5060;branch=z9hG4bK14aacddc
Contact: <sip:Tom@10.24.17.254:37509;transport=UDP>
To: <sip:Tom@10.24.18.124;transport=UDP>;tag=f51e9632
From: <sip:7002@10.24.18.124;transport=UDP>;tag=as46a6e039
Call-ID: ZjE2ZDAwYThiOTA2MzYxOWEwNTEwMjc1ZGIxNTk3NDU.
CSeq: 102 NOTIFY
User-Agent: Z 3.2.21357 r21103
Content-Length: 0
<------------->
--- (9 headers 0 lines) ---

‫ میتوانید توسط دستور زیر‬،‫هنگامی که درخواســت اعالن وضعیت در سیستم تلفنی استریسک صادر شود‬
:‫آن را مشاهده کنید‬
CLI> sip show subscriptions
Peer User CallID Extension Last state Type Mailbox Expiry
10.24.17.254 Tom ZjE2ZDAwYThiOTA 7002@Custom_hints Unavailable pidf+xml <none>
001800
1 active SIP subscription

‫ در استریسک‬SUBSCRIBE-NOTIFY ‫تنظیمات‬
‫ پارامترهایی را‬sip.conf ‫ باید در فایــل‬،‫ در استریســک‬SUBSCRIBE-NOTIFY ‫برای اســتفاده از قابلیت‬
.‫ این پارامترها به شرح زیرند‬.‫تنظیم کنید‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪306‬‬

‫•‪ : callcounter‬از این پارامتر برای مشاهده وضعیت اپراتور‌ها در صف استفاده می‌شود‪ .‬در فصل قبل در‬
‫مورد آن صحبت شد‪.‬‬
‫•‪ :busylevel‬مشخص می‌کند که چه زمانی استریسک باید وضعیت ‪ busy‬را برای یک اپراتور نشان دهد‪.‬‬
‫درحالت پیش‌فرض‪ ،‬استریســک وضعیت اپراتور در صف را ‪ INUSE‬نشان می‌دهد‪ .‬اگر ‪busylevel =1‬‬
‫باشد‪ ،‬استریسک وضعیت را به حالت ‪ busy‬برمی‌گرداند‪.‬‬
‫•‪ :call-limit‬با این پارامتر تعداد تماس‌های هم‌زمانی که یک کاربر می‌تواند داشته‌باشد‪ ،‬کنترل می‌گردد‪.‬‬
‫•‪ : allowsubscribe‬با این پارامتر قابلیت ‪ SUBSCRIBE‬را برای یک اپراتور‪ ،‬فعال یا غیر‌فعال می‌کنیم‪.‬‬
‫•‪ : subscribecontext‬با این پارامتر مشــخص می‌کنیم که در کدام کانتکست تعاریف مربوط به نگاشت‬
‫‪ DeviceState‬به ‪ Extension_State‬انجام شده‌است یا به عبارت دیگر در کدام کانتکست تعاریف ‪hint‬‬
‫انجام شده‌اســت‪ .‬اگر ایــن پارامتر را مقدار ندهیم‪ ،‬به‌طور پیش‌فرض همان مقدار پارامتر کانتکتســت در‬
‫تعریف کاربر در نظر گرفته خواهد‌شد‪.‬‬
‫•‪ : notifyringing‬با این پارامتر مشخص می‌کنیم که پیام ‪ ringing‬برای اپراتورها اعالم شود‪.‬‬
‫•‪ : notifyhold‬با این پارامتر مشخص می‌کنیم که اگر اپراتور در وضعیت ‪ hold‬باشد‪ ،‬پیام آن اعالم شود‪.‬‬

‫استفاده از ‪ Custom Device State‬در استریسک‬


‫استریســک این قابلیت را فراهم آوردهاســت که بتوان ‪Device State‬های جدیــدی ایجاد نمود‪ .‬برای مثال‬
‫چنانچــه بخواهیم وضعیت کاربرانی از نوع ‪ FXS‬را در استریســک بررســی کنیــم و ازآنجاکه وضعیت این‬
‫کاربران بهصورت پیشفرض در استریســک بررسی نمیشود‪ ،‬میتوانیم با نگاشت آنها به ‪Custom Device‬‬
‫‪ State‬به هدف خود برسیم‪ .‬برای مثال صف زیر را درنظر بگیرید‪:‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬
‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
‫‪joinempty=yes‬‬
‫‪leavewhenempty=no‬‬
‫‪ringinuse=no‬‬
‫‪;-------- Announcement Control --------‬‬
‫‪announce-frequency=30‬‬
‫‪min-announce-frequency=30‬‬
‫‪periodic-announce-frequency=45‬‬
‫‪random-periodic-announce=no‬‬
‫‪relative-periodic-announce=yes‬‬
307 ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

announce-holdtime=once
announce-position=limit
announce-position-limit=10
announce-round-seconds=30
member=>DAHDI/1
member=>DAHDI/2

‫ اکنون دستور‬.‫ در صف استفاده کردهایم‬DAHDI ‫همانطورکه مالحظه میکنید اینجا ما از کاربرانی از نوع‬
.‫زیر را در محیط کامندالین استریسک اجرا میکنیم‬
CLI> queue show
myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 0s
Members:
DAHDI/2 (ringinuse disabled) (Unknown) has taken no calls yet
DAHDI/1 (ringinuse disabled) (Unknown) has taken no calls yet
No Callers
CLI>

‫ قصد ما است که برای آنها یک‬.‫مالحظه میشود که وضعیت این اپراتورها برای استریسک مشخص نیست‬
‫ ایجاد کنیم و این اپراتورها را به این پارامتر نگاشت دهیم تا امکان بررسی وضعیت‬Custom Device State
.‫آنها فراهم شود‬

Custom Device State ‫تعریف‬


.‫ استفاده میکنیم‬DEVICE_STATE ‫ از تابع‬Custom Device State ‫برای تعریف یک‬
[LocalSets]
exten => mytest,Set(DEVICE_STATE(Custom:mystate)=NOT IN USE)

‫ تعریف‬Custom:mystate ‫ جدید بهنــام‬Device state ‫همانطورکه مالحظــه میکنید در این تعریف یک‬
‫ اکنون آن را به یک‬.‫ تنظیم شــده است‬NOT IN USE ‫شــده اســت و وضعیت فعلی )پیشفرض( آن روی‬
.‫( نگاشت میدهیم‬mytest ‫اکستنشن خاص )در اینجا‬
[Custom_hints]
exten => mystate,hint,Custom:mystate

.‫ جدید در استریسک تعریف شود‬Device state ‫ دستور زیر را اجرا کنید تا این‬،‫پس از تعریف فوق‬
CLI> console dial mystate@LocalSets

.‫ دستور زیر را اجرا کنید‬،‫ جدید و وضعیت آن‬Device state ‫برای مشاهده این‬
CLI> core show hints

-= Registered Asterisk Dial Plan Hints =-


mystate@custom_hints : Custom:mystate State:Idle Presence:not_set
Watchers 0
7002@Custom_hints : SIP/Bob-mobile&Bob-desk State:Unavailable Presence:not_set
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪308‬‬

‫‪Watchers 0‬‬
‫‪----------------‬‬
‫‪- 2 hints registered‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬وضعیت ‪ Device state‬جدید در حالت ‪ NOT IN USE‬یا ‪ idle‬است‪ .‬از این‬
‫‪ Device state‬اســتفاده میکنیم و آن را به یکی از اپراتورهای صف نگاشــت میدهیم‪ .‬برای رسیدن به این‬
‫هدف تغییرات زیر را در صف اعمال کنید‪.‬‬
‫‪member=>DAHDI/1,,,Custom:mystate‬‬

‫بعد از اعمال تغییرات و ‪ reload‬کردن استریسک‪ ،‬دستور زیر را در کامند الین استریسک اجرا کنید‪.‬‬
‫‪CLI> queue show‬‬
‫‪myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,‬‬
‫‪C:0, A:0, SL:0.0% within 0s‬‬
‫‪Members:‬‬
‫‪DAHDI/2 (ringinuse disabled) (Unknown) has taken no calls yet‬‬
‫‪DAHDI/1 (ringinuse disabled) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اینجا با اســتفاده از ‪ Custom Device State‬و نگاشــت آن به یک دیوایس‪،‬‬
‫میتوانیم وضعیت آن را در صف مشــخص کنیم و از آن در بررسی وضعیت کاربران )در کل سیستم تلفنی‬
‫استریسک( استفاده کنیم‪.‬‬
‫قبل از ادامه بحث بهتر اســت به یک مثال بپردازیم‪ .‬در این مثال هدف ما‪ ،‬اســتفاده از اپراتورهایی است‬
‫که استریســک نمیتواند وضعیت آنها را در صف نشان دهد )استریسک فقط میتواند وضعیت اپراتورهایی‬
‫از نوع پروتکل ‪ SIP‬را نشان دهد(؛ بنابراین‪ ،‬باید بتوانیم با استفاده از ‪ Custom Device State‬وضعیت آنها‬
‫را شبیهســازی کنیم‪ .‬این مثال در این بخش تنها جنبه آموزشــی دارد و برای اســتفاده در محصوالت توصیه‬
‫نمیشود‪.‬‬
‫مثال( فرض کنید صفی داریم که دارای اپراتورهایی از نوع پروتکل ‪ DAHDI‬اســت‪ .‬ازآنجاکه استریســک‬
‫نمیتواند وضعیت این نوع اپراتورها را داشــته باشــد‪ ،‬باید از ‪ Custom Device State‬استفادهکنیم‪ .‬تعریف‬
‫صف بهصورت زیر خواهد بود‪:‬‬
‫‪;queues.conf‬‬
‫]‪[general‬‬
‫‪autofill=yes‬‬
‫‪shared_lastcall=yes‬‬

‫]‪[myqueue‬‬
‫‪musicclass=default‬‬
‫‪strategy=rrmemory‬‬
309 ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

joinempty=yes
leavewhenempty=no
ringinuse=no
;-------- Announcement Control --------
announce-frequency=30
min-announce-frequency=30
periodic-announce-frequency=45
random-periodic-announce=no
relative-periodic-announce=yes
announce-holdtime=once
announce-position=limit
announce-position-limit=10
announce-round-seconds=30
member=>Local/1@agents/n,,,Custom:op1
member=>Local/2@agents/n,,,Custom:op2

:‫ بهصورت زیر داده شود‬Custom:op2 ‫ و‬Custom:op1 ‫اکنون باید مقادیر پیشفرض به‬
[Custom_hints]
exten => op1,hint,Custom:op1
exten => op1,1,Set(DEVICE_STATE(Custom:op1)=NOT_INUSE)

exten => op2,hint,Custom:op2


exten => op2,1,Set(DEVICE_STATE(Custom:op2)=NOT_INUSE)

‫ ولی باید دســتکم‬،‫ دادهایم‬Custom:op2 ‫ و‬Custom:op1 ‫ را به‬NOT_INUSE ‫ مقدار اولیه‬،‫با این برنامه‬
.‫ وضعیت صف را بررسی میکنیم‬،‫ پیش از اجرای برنامه‬.‫اجرا کنیم‬ ‫یک بار برنامه باال را‬
CLI> queue show
myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 0s
Members:
Local/1@agents (ringinuse disabled) (Unknown) has taken no calls yet
Local/2@agents (ringinuse disabled) (Unknown) has taken no calls yet
No Callers
CLI>

:‫ بهصورت زیر اجرا کنیم‬،‫اکنون برنامه باال را ازطریق محیط استریسک‬


CLI>console dial op1@Custom_hints
CLI>console dial op1@Custom_hints

.‫ تعریف میشــوند و مقدار اولیــه به خود میگیرند‬Custom Device State ‫ دو‬،‫بــا اجرای دســتورات فوق‬
.‫مجددا وضعیت صف را بررسی میکنیم‬
CLI> queue show
myqueue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 0s
Members:
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪310‬‬

‫‪Local/1@agents (ringinuse disabled) (Not in use) has taken no calls yet‬‬


‫‪Local/2@agents (ringinuse disabled) (Not in use) has taken no calls yet‬‬
‫‪No Callers‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اینجا وضعیت آنها تغییر کرده اســت و باید بتوانیم در صورت نیاز‪ ،‬وضعیت‬
‫آنها را کنترل کنیم‪ .‬به عبارت دیگر‪ ،‬وقتی تماسی به سمت آنها ارسال میکنیم‪ ،‬وضعیت آنها را بهصورت‬
‫دستی به ‪ Ringing‬تغییر میدهیم و یا زمانی که تماس جواب داده میشود‪ ،‬وضعیت آنها را ‪ INUSE‬میکنیم‪.‬‬
‫اکنون باید برنامه خود را تکمیل کنیم‪ .‬نخست باید کانتکست ]‪ [agents‬را بنویسیم‪ .‬برنامه آن بهصورت‬
‫زیر است‪:‬‬
‫]‪[agents‬‬
‫)‪exten => _X,1,NoOp(Agent calling‬‬
‫)}‪same => n,Set(DESK=Custom:op${EXTEN‬‬
‫)})}‪same => n,NoOp(${DEVICE_STATE(${DESK‬‬
‫)‪same => n,Set(DEVICE_STATE(${DESK})=RINGING‬‬
‫))}‪same => n,Dial(SIP/${EXTEN},20,U(subChangeState,${DESK‬‬
‫)(‪same => n(hang),Hangup‬‬

‫)(‪exten => h,1,NoOp‬‬


‫)‪same => n,Set(DEVICE_STATE(${DESK})=NOT_INUSE‬‬
‫)‪same => n(hang),NoOp(Hangup‬‬

‫]‪[subChangeState‬‬
‫)‪exten => s,1,Set(DEVICE_STATE(${ARG1})=INUSE‬‬

‫وقتی تماس به اپراتورهای صف متصل میشود‪ ،‬به کانتکست ]‪ [agents‬وارد میشود‪ .‬در این کانتکست اول‬
‫وضعیت اپراتور مورد نظر را ‪ Ringing‬و بعد تماس را به سمت اپراتور ارسال میکنیم‪ .‬اگر اپراتور تماس را‬
‫پاسخ دهد‪ ،‬با آپشن ‪ U‬در دستور ‪ ،Dial‬وضعیت اپراتور به حالت ‪ INUSE‬تغییر میکند و سپس تماس برقرار‬
‫میگردد‪ .‬چنانچه تماس قطع شــود‪ ،‬اکستنشن ‪ h‬اجرا میشــود و دوباره وضعیت به حالت ‪NOT_INUSE‬‬
‫تغییر میکند‪.‬‬
‫برای فهم بهتر برنامه‪ ،‬بهتر است آن را خط به خط تحلیل و اجرا کنید‪ .‬چنانچه ابهامی در این مورد وجود‬
‫داشته باشد‪ ،‬مفاهیم اولیه این فصل را مجددا ً مطالعه نمایید‪.‬‬
‫در ادامه به بررسی وضعیت کاربران در سیستمهای توزیع شده میپردازیم‪.‬‬

‫بررسی وضعیت کاربران (اپراتورها) در سیستم‌های توزیع‌شده‬


‫سیســتم تلفنی استریسک‪ ،‬به گونهای طراحی شده که در یک سیستم‪ ،‬نصبشده و قابل استفاده باشد‪ .‬گاهی‬
‫شــرایطی پیش میآید که باید از چندین ســرور استریســک بهصورت توزیع شده اســتفاده کنیم‪ .‬هر سرور‬
‫‪311‬‬ ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫استریسک کاربران مخصوص به خودش را دارد و ما باید بتوانیم در چنین توپولوژیهایی‪ ،‬وضعیت کاربران‬
‫یک ســرور را میان سایر ســرورها به اشتراک بگذاریم‪ .‬برای این منظور‪ ،‬سرورهای استریسک باید با هم در‬
‫ارتباط باشند‪ .‬برای برقراری ارتباط میان سرورهای استریسک‪ ،‬میتوان از روشهای زیر استفادهکرد‪:‬‬
‫‪ -۱‬اگر سرورهای استریسک در یک شبکه ‪ LAN‬باشند‪ ،‬میتوان از ‪ Corosync‬استفاده کرد‪.‬‬
‫‪ -۲‬اگر سرورهای استریسک در موقعیتهای جغرافیایی توزیع شده باشند‪ ،‬میتوان از ‪ XMPP‬استفاده نمود‪.‬‬
‫‪ -۳‬از ابزارهای مدیریتی استریسک استفاده کرد‪.‬‬
‫در این فصل به روش اول )استفاده از ‪ (Corosync‬خواهیم پرداخت‪.‬‬

‫استفاده از ‪ Corosync‬برای برقراری ارتباط میان سرورهای استریسک‬


‫استریســک از ‪API‬های موجود در دســتور ‪ Corosync‬برای توزیع رویدادهای خود )وضعیت کاربران( در‬
‫ســطح شبکه و به اشتراک گذاشتن آنها با سایر سرورهای استریسک استفاده میکند‪ .‬برای این منظور ابتدا‬
‫باید ‪ Corosync‬نصب شود‪ .‬دقت داشته باشید که این تنظیمات باید روی کلیه سرورهای استریسک صورت‬
‫گیرند‪.‬‬
‫برای استفاده از ‪ Corosync‬در توزیعهای مختلف لینوکسی‪ ،‬دستورات زیر را اجرا کنید‪:‬‬
‫‪; RHEL‬‬
‫‪# sudo yum install corosync corosynclib corosynclib-devel‬‬

‫‪;Ubuntu‬‬
‫‪# sudo apt-get install corosync corosync-dev‬‬

‫پس از نصب ‪ ،Corosync‬به مســیر نصب استریسک بروید و استریسک را مجددا ً نصب نمایید تا ماژول‬
‫‪ res_corosync‬بهوسیله استریسک شناسایی شود‪.‬‬

‫شکل ‪3-10‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 312

:‫برای این منظور به مسیر نصب استریسک بروید و دستورات زیر را اجرا کنید‬
# cd path/to/asterisk13/
#./configure
#make menuselect

res_corosync ‫ باید ماژول‬،‫ مراجعه کنید‬Resource Module ‫ چنانچه به قسمت‬،‫پس از اجرای این دستورات‬
.‫ سپس ادامه دستورات را اجرا کنید‬.‫را فعالشده ببینید‬
#make & make install

Corosync ‫پیکربندی‬
.‫ نخست فایل زیر را باز کنید‬Corosync ‫برای پیکربندی‬
#vim /etc/corosync/corosync.conf

.‫سپس تغییرات زیر را در فایل اعمال کنید‬


totem {
version: 2
secauth: off
interface {
member {
memberaddr: 192.168.122.250
}
member {
memberaddr: 192.168.122.94
}
ringnumber: 0
bindnetaddr: 192.168.122.0
mcastport: 5405
ttl: 1
}
transport: udpu
}
logging {
fileline: off
to_logfile: yes
to_syslog: yes
debug: on
logfile: /var/log/corosync/corosync.log
debug: off
timestamp: on
logger_subsys {
subsys: AMF
debug: off
}
}
‫‪313‬‬ ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫همانطورکــه مالحظه میکنید‪ ،‬اینجا آدرس ســرورهای استریســک را آوردهایم‪ .‬برای آشــنایی بیشــتر با‬
‫‪ Corosync‬دستور زیر را اجرا کنید‪:‬‬
‫‪# man corosync.conf‬‬

‫سپس مشخص کنید که کدام گروهها )منظور استریسک است( میتوانند به ‪ Corosync‬متصل شوند و به آن‬
‫دسترسی داشته باشند‪ .‬برای مثال فایل زیر را باز کنید و تغییرات زیر را انجام دهید‪.‬‬
‫‪#vim /etc/corosync/uidgid.d/asterisk‬‬
‫{ ‪uidgid‬‬
‫‪uid: asteriskpbx ; or uid: root‬‬
‫‪gid: asteriskpbx ; or gid: root‬‬
‫}‬

‫سپس برای اجرای ‪ corosync‬دستور زیر را اجرا کنید‪:‬‬


‫‪#service corosync start‬‬

‫دست آخر باید تنظیمات استریسک را انجام دهید‪.‬‬


‫‪#vim /etc/asterisk/corosync.conf‬‬
‫]‪[general‬‬
‫‪publish_event = device_state‬‬
‫‪subscribe_event = device_state‬‬

‫پس از انجام تغییرات الزم‪ ،‬وارد کامندالین استریســک شــوید و دســتورات زیر را اجرا کنید‪ .‬با اجرای این‬
‫دستورات میتوان مطمئن شد که تنظیمات بهدرستی انجام شده است‪.‬‬
‫‪CLI> corosync show config‬‬

‫به کمک دستور زیر میتوان اعضای موجود در ‪ corosync cluster‬را مشاهدهکرد‪:‬‬
‫‪CLI> corosync show members‬‬
‫======== ‪=== Cluster members‬‬
‫‪Node 1‬‬
‫‪--> Group: asterisk‬‬
‫‪--> Address 1: 192.168.122.94‬‬
‫‪Node 2‬‬
‫‪--> Group: asterisk‬‬
‫‪--> Address 1: 192.168.122.250‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در این حالت دو ســرور استریســک داریم که آیپی هرکدام نمایش داده‬
‫شدهاست‪.‬‬
‫این دو ســرور در این شــرایط‪ ،‬وضعیت کاربران خودرا برای یکدیگر ارســال میکنند‪ .‬اکنون چنانچه‬
‫در یکی از ســرورها تغییــری در وضعیت یکی از کاربران یا دیوایسها رخ دهد‪ ،‬این تغییر در ســرور دیگر‬
‫قابلمشاهده است‪ .‬این تغییرات را میتوانید با دستور ‪ core show hints‬در سرور دیگر مالحظه کنید‪.‬‬
‫با فعال کردن مود دیباگ در استریسک‪ ،‬پیامهای این تغییر وضعیت را در کامند الین استریسک مشاهده‬
‫خواهید کرد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 314

CLI> core set debug 1


CLI> dialplan set global DEVICE_STATE(Custom:mystate) NOT_INUSE
-- Global variable 'DEVICE_STATE(Custom: mystate)' set to 'NOT_INUSE'
[Nov 16 13:27:12] DEBUG[14801]: devicestate.c:652
handle_devstate_change: Processing device state change for 'Custom:abc'
[Nov 16 13:27:12] DEBUG[14801]: devicestate.c:602
process_collection: Adding per-server state of 'Not in use' for 'Custom:abc'
[Nov 16 13:27:12] DEBUG[14801]: devicestate.c:602
process_collection: Adding per-server state of 'Not in use' for 'Custom:abc'
[Nov 16 13:27:12] DEBUG[14801]: devicestate.c:609
process_collection: Aggregate devstate result is 'Not in use' for 'Custom:abc'
[Nov 16 13:27:12] DEBUG[14801]: devicestate.c:631
process_collection: Aggregate state for device 'Custom: mystate ' has changed to'Not in use
ubuntu*CLI> dialplan set global DEVICE_STATE(Custom: mystate) INUSE
-- Global variable 'DEVICE_STATE(Custom: mystate)' set to 'INUSE'
[Nov 16 13:29:30] DEBUG[14801]: devicestate.c:652 handle_devstate_change:
Processing device state change for 'Custom: mystate '
[Nov 16 13:29:30] DEBUG[14801]: devicestate.c:602 process_collection:
Adding per-server state of 'Not in use' for 'Custom: mystate '
[Nov 16 13:29:30] DEBUG[14801]: devicestate.c:602 process_collection:
Adding per-server state of 'In use' for 'Custom: mystate '
[Nov 16 13:29:30] DEBUG[14801]: devicestate.c:609 process_collection:
Aggregate devstate result is 'In use' for 'Custom: mystate '
[Nov 16 13:29:30] DEBUG[14801]: devicestate.c:631 process_collection:
Aggregate state for device 'Custom:abc' has changed to 'In use'

‫ برای برقراری ارتباط میان سرورهای استریسک‬XMPP ‫استفاده از‬


‫ این پروتکل مخفف‬.‫ یک پروتکل پیامرســان ارتباطی روی بســتر شــبکه است‬Jabber ‫ یا‬XMPP ‫پروتکل‬
‫ بهمعنــی “پروتــکل پیامرســانی و وضعیــت حضــور‬Extensible Messaging and Presence Protocol
.‫ استفاده میشود‬Message-Oriented Middleware ‫قابلتوسعه” است و برای پیادهسازی‬
‫ اســتفاده میکند و اســتانداردی برای عملیاتهای‬xml ‫ بــرای انتقال پیامها از فرمت‬XMPP ‫پروتــکل‬
‫ این اســتانداردها بهوســیله مؤسسه مستقل و غیرانتفاعی‬.‫ گفته میشــود‬xep ‫مختلف ایجاد میکند که به آن‬
،‫ شــناخته میشــد‬Jabber Software Foundation ‫ال با نام‬ ً ‫ که قب‬XMPP Standards Foundation ‫ یا‬XSF
.‫تعیین میشوند‬
.‫ خارج از حوصله کتاب می باشد‬XMPP ‫بحث در خصوص پروتکل‬
‫‪315‬‬ ‫بررسی وضعیت تجهیزات در شبکه‌های ویپ‬

‫سرویس ‪ 1 CCSS‬در استریسک‬


‫حتماً برای شــما پیش آمده که با شــخصی در سیســتم تلفنی استریســک تماس بگیرید‪ ،‬ولی بنا به دالیلی‬
‫مخاطب مورد نظر در دســترس نبوده یا مشغول باشــد‪ .‬در یک چنین شرایطی معموالً پس از مدتی دوباره با‬
‫مخاطب تماس برقرار میکنیم‪ .‬اما این کار ممکن است طاقتفرسا و وقتگیر باشد‪ .‬استریسک با ارائه قابلیت‬
‫ســرویس ‪ CCSS‬این امکان را فراهم آورده که هر زمان مخاطب در دســترس بود‪ ،‬با او تماس بگیرد و به ما‬
‫اطالع دهد‪ .‬مثالی زیر را ببینید‪.‬‬
‫مثال( فرض کنید کاربر ‪ ۱۰۰‬بخواهد با کاربر ‪ ۱۰۱‬تماس برقرار کند ولی کاربر ‪ ۱۰۱‬تماس را پاسخ نمیدهد‪.‬‬
‫کاربر ‪ ۱۰۰‬بالفاصله با شــماره گیری ‪ *۳۰‬ســرویس ‪ CCSS‬را فعال میکند‪ .‬به محض فعالشدن کاربر ‪،۱۰۱‬‬
‫استریسک با او تماس گرفته به کاربر ‪ ۱۰۰‬متصل می کند‪ .‬تنظیمات این سرویس بهصورت زیر است‪.‬‬
‫ابتدا باید پارامترهای زیر را برای هر کاربر در سیستم تلفنی استریسک اضافه کنید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[100‬‬
‫…‬
‫‪cc_agent_policy = generic‬‬
‫‪cc_monitor_policy = generic‬‬

‫]‪[101‬‬
‫…‬
‫‪cc_agent_policy = generic‬‬
‫‪cc_monitor_policy = generic‬‬

‫سپس برنامه زیر را اضافه کنید‪:‬‬


‫]‪[LocalSets‬‬

‫)‪exten => 100,1,Dial(SIP/100,20‬‬


‫)(‪same => n,Hangup‬‬

‫)‪exten => 101,1,Dial(SIP/101,20‬‬


‫)(‪same => n,Hangup‬‬
‫)(‪exten => *30,1,CallCompletionRequest‬‬
‫)(‪same => n,Hangup‬‬

‫)(‪exten => *31,1,CallCompletionCancel‬‬


‫)(‪same => n,Hangup‬‬

‫اکنون چنانچه کاربری ‪ *30‬را شــمارهگیری نماید‪ ،‬با اجرای دستور ‪ ، CallCompletionRequest‬سرویس‬
‫‪ CCSS‬برای تماس گیرنده فعال میشود‪ .‬عالوه بر این‪ ،‬با گرفتن شماره ‪ *31‬دستور ‪CallCompletionCancel‬‬

‫‪1- Call Completion Supplementary Services‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪316‬‬

‫اجرا و سرویس ‪ CCSS‬برای تماس گیرنده غیر فعال میشود‪.‬‬


‫با اجرای دســتور زیر در کامندالین استریســک‪ ،‬می‌توانید خروجی ســرویس ‪ CCSS‬را مشاهده کنید‪.‬‬
‫خروجی دستور به این صورت خواهد بود‪:‬‬
‫‪CLI> cc report status‬‬
‫‪1 Call completion transactions‬‬
‫‪Core ID‬‬ ‫‪Caller‬‬ ‫‪Status‬‬
‫‪-----------------------------------------------------------------------‬‬
‫‪6‬‬ ‫‪SIP/100‬‬ ‫ ‬ ‫‪CC accepted by callee‬‬
‫‪|-->101@LocalSets‬‬
‫)‪|-->SIP/101(CCNR‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید وضعیت ‪ accepted by callee‬نشــان میدهد که سرویس ‪ CCSS‬برای کاربر‬
‫‪ ۱۰۰‬فعال شــده اســت و به محض در درســترس بودن کاربر ‪ ، ۱۰۱‬استریســک با او تماس میگیرد‪ .‬پس از‬
‫اجرای سرویس ‪ ، CCSS‬وضعیت آن بهصورت ‪ CC offered to caller‬تغییر میکند‪.‬‬

‫نتیجه‌گیری‬
‫در این فصل در خصوص بررســی وضعیت کاربران در یک سیســتم تلفنی‪ ،‬صحبت شد و اینکه چگونه این‬
‫اطالعات میتوانند ســودمند باشند‪ .‬همچنین معلوم شــد که این قابلیت بهصورت پیش فرض در کاربرانی از‬
‫نوع ‪ SIP‬فعال اســت‪ .‬برای توسعه این قابلیت به ســایر کاربران‪ ،‬مفهوم ‪ Custom Device state‬و چگونگی‬
‫نگاشــت آن به کاربران مورد نظر بررســی شد‪ .‬سپس در سیستمهای توزیع شــده شرح داده شد که چگونه‬
‫سرورهای متعدد به اشتراک گذاشت‪.‬‬ ‫میتوان وضعیت اپراتورها را میان‬
‫فصل یازدهم‬

‫ارتباط بین استریسک‬


‫و پایگاه داده‌ای‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪318‬‬

‫مقدمه‬
‫در این فصل قصد داریم ارتباط میان استریسک و پایگاه دادهای در لینوکس و ویندوز را بررسی کنیم‪.‬‬
‫در سیســتم عامل لینوکس‪ ،‬پایگاههای دادهای زیادی وجود دارند ولی در این فصل روی پایگاه دادهای‬
‫‪ PostgreSQL‬و ‪ MySQL‬تمرکز بیشــتری خواهیم داشــت و به نحوه ارتباط استریســک بــا پایگاه دادهای‬
‫‪ MicrosoftSQL‬نیز خواهیم پرداخت‪.‬‬
‫اهمیت این فصل در این است که برای ارتباط با پایگاههای دادهای )صرف نظر از نوع پایگاه داده( باید‬
‫از ‪ ODBC Connection‬ها در لینوکس اســتفاده کنیم‪ .‬اســتفاده از پایگاه دادهای و ارتباط آن با یک سافت‬
‫سوئیچ)مثل استریسک‪ ،‬فری سوئیچ یا ‪ (Yate‬میتواند یک سسیستمهای تلفنی بزرگ توزیع شده ایجاد کند‪.‬‬
‫همچنین میتوان از پایگاه دادهای برای ذخیره کردن دادههایی مانند موارد زیر استفاده کرد‪:‬‬
‫ • گزارش جزئیات تماس‌ها ‪CDR‬‬
‫ • گزارش رویدادها ‪CEL‬‬
‫ • گزارش صف‌ها ‪Queue‬‬
‫ • استفاده از ‪ARA‬‬
‫مســلماً برای هر سیستم تلفنی ضرورتی وجود ندارد که به پایگاه دادهای متصل شود‪ .‬آشنا شدن با این بخش‬
‫و نحوه اتصال سیستم تلفنی استریسک با پایگاههای دادهای‪ ،‬به ما کمک میکند که بتوانیم محصوالت بهتر‬
‫و کاربردیتــری ایجاد کنیم‪ .‬در ادامه نحوه چگونگی این ارتباط در توزیعهای مختلف لینوکســی از جمله‬
‫‪ RHEL‬و ‪ Ubunto‬بررسی میشوند‪.‬‬
‫‪319‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫نخست باید پایگاه دادهای مورد نیاز خود را نصب کنیم که در ادامه‪ ،‬نصب پایگاه دادهای ‪PostgreSQL‬‬
‫و ‪ MySQL‬بررسی میشوند‪.‬‬

‫نصب ‪ PostgreSQL‬در لینوکس‬


‫برای نصب ‪ PostgreSQL‬در توزیع ‪ RHEL‬بهصورت زیر عمل کنید‪:‬‬
‫‪;RHEL‬‬
‫‪#sudo yum install postgre-server‬‬

‫بعد از نصب ‪ PostgreSQL‬باید دستور زیر را برای ‪ initialize‬کردن‪ ،‬اجرا کنید‪:‬‬


‫‪;RHEL‬‬
‫‪#sudo service postgresql initdb‬‬

‫برای راهاندازی سرویس پایگاه دادهای ‪ ،PostgreSQL‬از دستور زیر استفاده کنید‪:‬‬
‫‪;RHEL‬‬
‫‪#sudo service postgresql start‬‬

‫برای نصب ‪ PostgreSQL‬در توزیع ‪ Ubuntu‬به شکل زیر عمل کنید‪:‬‬


‫‪;ubuntu‬‬
‫‪#sudo apt-get install postgresql‬‬

‫ممکن است در ابتدای کار‪ ،‬وضعیت نصب نیازمندیها پرسش شود‪ .‬در این مرحله با تأیید لیست نیازمندی‪،‬‬
‫اجازه دهید تا مراحل نصب با موفقیت اجرا شود‪ .‬پس از نصب ‪ PostgreSQL‬در توزیع ‪ ،Ubuntu‬این پایگاه‬
‫دادهای بهصورت خودکار ‪ initialize‬میشود‪.‬‬
‫برای راهاندازی سرویس پایگاه دادهای ‪ PostgreSQL‬از دستور زیر استفاده کنید‪:‬‬
‫‪;Ubuntu‬‬
‫‪#sudo service postgresql start‬‬

‫نصب ‪ MySQL‬در لینوکس‬


‫نســخههای زیادی از پایگاه دادهای ‪ MySQL‬وجود دارد‪ .‬توصیه میشود از نسخههای ‪ ۵,۵ MySQL‬یا ‪۵,۶‬‬
‫که برتریهای فراوانی نســبت به نســخههای قدیمیتر مانند ‪ ۵,۱ MySQL‬دارند‪ ،‬اســتفاده شــود‪ .‬نسخههای‬
‫جدید ‪ MySQL‬در مقایســه با نسخههای قدیمی‪ ،‬پیشــرفتهای قابلتوجهی در عملکردشان دارند‪ ،‬از جمله‬
‫این توانایی ها می توان به انجام عملیات با سرعت باال اشاره کرد‪.‬‬
‫برای نصب ‪ MySQL‬در توزیع ‪ RHEL‬بهصورت زیر عمل کنید‪.‬‬
‫‪;Ubuntu‬‬
‫‪#sudo yum install mysql-server-5.6‬‬

‫هنگام نصب‪ ،‬پســورد ‪ root‬از شما پرسیده میشود)شــکل ‪ .(۱-۱۱‬با انتخاب صحیح پسورد‪ ،‬اجازه دهید‬
‫مراحل نصب کامل شود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪320‬‬

‫شکل ‪1-11‬‬

‫برای راهاندازی سرویس پایگاه دادهای ‪ MySQL‬در توزیع لینوکس ‪ RHEL‬از دستور زیر استفاده کنید‪:‬‬
‫‪;RHEL‬‬
‫‪#sudo service mysql start‬‬

‫برای نصب ‪ MySQL‬در توزیع ‪ Ubuntu‬به شکل زیر عمل کنید‪:‬‬


‫‪;ubuntu‬‬
‫‪#sudo apt-get install mysql-server‬‬

‫ممکن اســت لیســت نیازمندیها از شما پرسیده شود‪ .‬در این صورت همانند قبل با تأیید لیست نیازمندیها‪،‬‬
‫اجازه دهید تا مراحل نصب با موفقیت کامل شود‪.‬‬
‫‪;ubuntu‬‬
‫]‪Do you want to continue? [Y/n‬‬

‫هنگام نصب‪ ،‬پسورد ‪ root‬از شما پرسیده میشود‪ .‬با انتخاب صحیح پسورد‪ ،‬اجازه دهید مراحل نصب کامل‬
‫شــود‪ .‬برای راهاندازی ســرویس پایگاه دادهای ‪ MySQL‬در توزیع لینوکس ‪ Ubuntu‬از دستور زیر استفاده‬
‫کنید‪:‬‬
‫‪;Ubuntu‬‬
‫‪#sudo service mysql start‬‬

‫تــا اینجا مراحل نصب و راهاندازی پایگاههای داداهای ‪ PostgreSQL‬و ‪ MySQL‬بررســی شــدند‪ .‬در ادامه‬
‫مراحل پیکربندی هر یک از آنها توضیح داده میشود‪.‬‬

‫پیکربندی ‪ PostgreSQL‬در لینوکس‬


‫برای ارتباط با دیتابیس و مدیریت آن‪ ،‬نخست باید یک کاربر جدید بهنام ‪ asterisk‬با سطح دسترسی مناسب‬
‫داشته باشید‪ .‬برای این منظور دستور زیر را اجرا کنید )اینجا از نسخه ‪ PostgreSQL 9.3‬استفاده میکنیم(‪.‬‬
‫‪#sudo su - postgres‬‬
‫‪postgres@ubuntu14:~$‬‬

‫سپس برای ساختن کاربر ‪ ،asterisk‬این دستور را اجرا و تنظیمات مشخص شده را انجام دهید‪.‬‬
‫‪postgres@ubuntu14:~$createuser –P asterisk‬‬
‫‪Enter password for new user:‬‬
‫‪Enter it again:‬‬
321 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

postgres@ubuntu14:~$

‫ تغییرات زیر را اعمال‬pg_hba.conf ‫ باید در فایل‬،‫ متصل شود‬PostgreSQL ‫برای آنکه این کاربر بتواند به‬
:‫کنید‬
#vim /etc/postgresql/9.3/main/pg_hba.conf

# TYPE DATABASE USER ADDRESS METHOD


host all asterisk 127.0.0.1/32 md5
local all asterisk trust

‫ باید خــط زیر را هم به فایل باال اضافه‬،‫ انجام دهید‬۶ ‫چنانچــه بخواهید ایــن تنظیمات را برای آی پی ورژن‬
.‫کنید‬
host all asterisk ::1/128 md5

‫ یک‬PostgreSQL ‫ باید بتوانید در پایگاه دادهای‬،‫پس از ایجاد کاربر جدید و اعطای ســطح دسترسی به آن‬
:‫ برای ایجاد این دیتابیس دستور زیر را اجرا کنید‬.‫ ایجاد کنید‬asterisk ‫دیتابیس جدید بهنام‬

postgres@ubuntu14:~$ createdb --owner=asterisk asterisk


CREATE DATABASE

:‫ دستور زیر را اجرا کنید‬،asterisk ‫برای تخصیص کلمه عبور به کاربر‬


postgres@ubuntu14:~$ psql -d template1
template1=# "ALTER USER asterisk WITH PASSWORD '123123'"
template1=# \q

.‫ را مجددا ً راهاندازی کنید‬PostgreSQL ‫ خارج شوید و سرویس‬PostgreSQL ‫سپس از محیط‬


postgres@ubuntu14:~$ exit
logout

;RHEL
#sudo service postgresql restart

;ubuntu
# /etc/init.d/postgresql restart
* Restarting PostgreSQL 9.3 database server [ OK ]

:‫ تست را انجام داد‬TCP/IP ‫ با‬PostgreSQL ‫ میتوان با اتصال به‬،‫برای بررسی درستی تنظیمات و پیکربندی‬
# psql -h 127.0.0.1 -U asterisk
Password for user asterisk:
psql (9.3.14)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

asterisk=>
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪322‬‬

‫پیکربندی ‪ MySQL‬در لینوکس‬


‫پــس از آنکــه ‪ MySQL‬را نصب کردید‪ ،‬باید با انجام تنظیماتی در آن‪ ،‬موارد امنیتی را به آن بیفزایید‪ .‬با کد‬
‫زیر‪ ،‬میتوانید برای ‪ MySQL‬رمز عبور تعیین کنید‪ .‬برای مثال دستور زیر را اجرا کنید‪:‬‬

‫‪# sudo /usr/bin/mysql_secure_installation‬‬

‫اکنون وارد محیط کامندالین ‪ MySQL‬شوید و یک کاربر جدید بهنام ‪ asterisk‬ایجاد کنید‪.‬‬
‫‪# mysql -u root –p‬‬
‫>‪mysql‬‬

‫پس از ورود پسورد‪ ،‬به کنسول ‪ MySQL‬وارد شوید‪ .‬با اجرای دستور ‪ ،CREATE USER‬یک کاربر بهنام‬
‫‪ asterisk‬بســازید‪ .‬کاراکتر ‪ %‬مشــخص میکند کــه کاربر ‪ asterisk‬میتواند از هر سیســتمی به دیتابیس‬
‫دسترسی داشته باشد‪.‬‬
‫;'‪mysql> CREATE USER 'asterisk'@'%' IDENTIFIED BY '123123‬‬

‫به دالیل امنیتی توصیه میشــود چنانچه استریســک و دیتابس روی یک سرور قرار دارند‪ ،‬بهجای استفاده از‬
‫کاراکتر »‪ «%‬از عبارت ‪ localhost‬استفاده کنید‪ .‬اما اگر مایلید دسترسی از راه دور‪ ۱‬به دیتابیس داشتهباشید‬
‫‪ my.conf‬انجام دهید‪.‬‬ ‫باید تنظیمات زیر را در فایل‬
‫‪#vim /etc/mysql/my.cnf‬‬
‫‪bind-address = 0.0.0.0‬‬

‫سپس سرویس ‪ MySQL‬را ریست کنید‪.‬‬


‫‪;RHEL‬‬
‫‪#Service mysqld restart‬‬

‫‪;ubuntu‬‬
‫‪#/etc/init.d/mysqld restart‬‬

‫اکنون یک دیتابیس بهنام ‪ asterisk‬ایجاد کنید‪.‬‬


‫‪mysql> CREATE DATABASE asterisk‬‬

‫پس از ساخت یوزر ‪ asterisk‬و دیتابیس‪ ،‬سطح دسترسیهای الزم به دیتابیس ‪ asterisk‬را برای کاربر ایجاد‬
‫کنید‪.‬‬
‫;'‪mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'%‬‬
‫)‪Query OK, 0 rows affected (0.00 sec‬‬

‫در نهایت با دستور زیر تغییرات را اعمال کنید‪:‬‬


‫;‪mysql> FLUSH PRIVILEGES‬‬
‫)‪Query OK, 0 rows affected (0.00 sec‬‬

‫برای تست کاربر جدید‪ ،‬از محیط کامند الین ‪ MySQL‬خارج و دوباره با کاربر جدید وارد شوید‪.‬‬

‫‪1- Remote Access‬‬


‫‪323‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫‪mysql> exit‬‬
‫‪Bye‬‬
‫‪# mysql -u asterisk -p 123123‬‬
‫‪Enter password:‬‬
‫>‪mysql‬‬

‫نصب و پیکربندی ‪ ODBC‬در لینوکس‬


‫تا اینجا با مراحل نصب و پیکربندی پایگاه دادهای ‪ MySQL‬و ‪ PostgreSQL‬در لینوکس آشنا شدید‪ .‬برای‬
‫کار با این پایگاه دادهای در سیســتم تلفنی استریســک‪ ،‬نخست باید یک ‪ ODBC Connector‬ایجاد کنید و‬
‫به پایگاههای دادهای متصل نمایید‪.‬‬
‫‪ ODBC Connector‬نوعی ‪ API‬برای دیتابیس اســت که بهوســیله آن‪ ،‬برنامه بدون آگاهی از ســاختار‬
‫دیتابیسها‪ ،‬میتواند به دیتابیس دسترسی پیدا کند‪ ODBC .‬درخواستهای مربوط به دیتابیس را دریافت و‬
‫به درخواستهای قابلاستفاده برای دیتابیس تبدیل میکند‪.‬‬
‫استریســک بهوسیله ماژول ‪ res_odbc.so‬میتواند با یک ‪ ODBC Connector‬ارتباط برقرار کند‪ .‬برای‬
‫درک این موضوع شکل ‪ ۲-۱۱‬را ببینید‪.‬‬

‫شکل ‪2-11‬‬

‫همانطورکه مالحظه میکنید استریســک از طریق ماژول “‪ ”res_odbc.so‬و بهواسطه ‪،ODBC driver‬‬
‫به پایگاه دادهای متصل میشود‪.‬‬
‫در شکل ‪ ۳-۱۱‬نمایی از ‪ ODBC Config Stack‬ارائه شده است‪.‬‬
‫‪ODBC‬‬ ‫همانطورکــه مالحظه میکنید‪ ،‬برای برقراری یک ارتباط صحیح با پایگاه دادهای‪ ،‬باید مطابق‬
‫‪ Config Stack‬تنظیمات را انجام دهید‪ .‬در ادامه هر بخش بیشتر توضیح داده میشود‪.‬‬
‫ابتدا باید ‪ ODBC Driver‬را نصب کنید‪ .‬اینجا از ‪ unixODBC‬استفاده میکنیم‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 324

3-11 ‫شکل‬

‫ را پیادهسازی میکند و قابلیت استفاده در محیط‬ODBC API ‫ برنامهای متن باز اســت که‬unixODBC
‫ یکی از‬. IBM OS/2 ‫ و‬Unix، Linux، Mac OS X ‫ از جمله سیستم عامل‬،‫بسیاری از سیستمعاملها را دارد‬
‫ برای نصب آن دستورات‬.‫ در سیستمهای غیرویندوزی است‬ODBC ‫ استفاده از‬unixODBC ‫اهداف اصلی‬
:‫زیر را اجرا کنید‬
;RHEL
# sudo yum install unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel
;Ubuntu
# sudo apt-get install unixODBC unixODBC-dev

‫ مورد نیاز‬ODBC Connector ،‫اکنون باید با توجه به نوع پایگاه دادهای و توزیع لینوکســی مورد اســتفاده‬
.‫خود را نصب کنید‬
;To install the MySQL ODBC connector on RHEL
# sudo yum install mysql-connector-odbc

;To install the PostgreSQL ODBC connector on RHEL


# sudo yum install postgresql-odbc

;To install the PostgreSQL ODBC connector on Ubuntu


# sudo apt-get install odbc-postgresql

;Or to install the MySQL ODBC connector on Ubuntu


# sudo apt-get install libmyodbc

‫ با پایگاه‬ODBC ‫ باید تنظیمات مربوط به ایجاد ارتباط‬ODBC Connection ‫ و‬unixODBC ‫بعــد از نصــب‬
.‫ با موفقیت به پایگاه دادهای متصل شود‬ODBC ‫ بهطوریکه‬،‫دادهای را انجام دهید‬
325 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

PostgreSQL ‫ برای ارتباط با پایگاه داده‌ای‬ODBC ‫پیکربندی‬


.‫ را باز کنید و تنظیمات زیر را انجام دهید‬odbcinist.ini ‫فایل‬ ‫برای انجام این تنظیمات‬
# vim /etc/odbcinst.ini
;RHEL
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib/psqlodbc.so
Setup = /usr/lib/libodbcpsqlS.so
Driver64 = /usr/lib64/psqlodbc.so
Setup64 = /usr/lib64/libodbcpsqlS.so
FileUsage = 1

;Ubuntu
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib/odbc/psqlodbca.so
Setup = /usr/lib/odbc/libodbcpsqlS.so
FileUsage = 1

‫ درصورتیکه ارتباط بهدرستی‬.‫ از دستور زیر استفاده کنید‬،‫برای اطمینان از درستی تنظیمات صورت گرفته‬
.‫ نشان داده میشود‬PostgreSQL ‫ عبارت‬،‫برقرار شده باشد‬
#odbcinst -q –d
[PostgreSQL]

‫ این فایل یک شناســه میســازد که استریســک‬.‫ را باید انجام دهید‬odbc.ini ‫ تنظیمات فایل‬،‫در مرحله بعد‬
‫ تنها کافیست مقادیر این‬،‫ درصورت تمایل به تعویض دیتابیس‬.‫بهواسطه آن به پایگاه دادهای متصل میشود‬
.‫فایل را تغییر دهید‬
#vim /etc/odbc.ini
[asterisk-connector]
Description = PostgreSQL connection to ‘asterisk’ database
Driver = PostgreSQL
Database = asterisk
Servername = localhost
Port = 5432
Protocol = 8.1
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
ConnSettings =
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 326

MySQL ‫ برای ارتباط با پایگاه داده‌ای‬ODBC ‫پیکربندی‬


:‫ را باز کنید و تنظیمات زیر را انجام دهید‬odbcinist.ini ‫ فایل‬،‫برای تنظیم این پیکربندی‬
# vim /etc/odbcinst.ini
;RHEL
[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib/libmyodbc5.so
Setup = /usr/lib/libodbcmyS.so
Driver64 = /usr/lib64/libmyodbc5.so
Setup64 = /usr/lib64/libodbcmyS.so
FileUsage =1

;Ubuntu
[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so
FileUsage =1

‫ در صورتی که ارتباط بهدرستی برقرار‬.‫ دستور زیر را اجرا کنید‬،‫برای اطمینان از صحت تنظیمات انجامشده‬
:‫ نمایش داده میشود‬MySQL ‫ عبارت‬،‫شده باشد‬
#odbcinst -q –d
[MySQL]

‫ این فایل یک شناســه میســازد که استریســک‬.‫ را انجام دهید‬odbc.ini ‫ باید تنظیمات فایل‬،‫در مرحله بعد‬
‫ تنها کافیست مقادیر این‬،‫ درصورت تمایل به تعویض دیتابیس‬.‫بهواسطه آن به پایگاه دادهای متصل میشود‬
.‫فایل را تغییر دهید‬
#vim /etc/odbc.ini
;RHEL
[asterisk-connector]
Description = MySQL connection to ‘asterisk’ database
Driver = MySQL
Database = asterisk
Server = localhost
Port = 3306
Socket = /var/lib/mysql/mysql.sock

.‫ بهصورت زیر است‬Socket ‫ استفاده میکنید؛ مسیر‬Ubuntu ‫اگر از توزیع‬


Socket = /var/run/mysqld/mysqld.sock
‫‪327‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫پیکربندی ‪ ODBC‬برای ارتباط با پایگاه داده‌ای ‪Microsoft SQL‬‬


‫برای برقراری اتصال ‪ Microsoft SQL‬باید ابتدا درایور ‪ FreeTDS‬را در لینوکس نصب کنید‪.‬‬
‫‪;RHEL‬‬
‫‪$ sudo yum install freetds‬‬
‫‪;Ubuntu‬‬
‫‪$ sudo apt-get install tdsodbc‬‬

‫پس از نصب درایور فوق‪ ،‬فایل ‪ odbcinist.ini‬را باز کنید و تنظیمات آن را مطابق زیر انجام دهید‪.‬‬
‫‪# vim /etc/odbcinst.ini‬‬
‫]‪[FreeTDS‬‬
‫‪Description‬‬ ‫‪= ODBC for Microsoft SQL‬‬
‫‪Driver‬‬ ‫‪= /usr/lib/i386-linux-gnu/odbc/libtdsodbc.so‬‬
‫‪UsageCount‬‬ ‫‪=1‬‬
‫‪Threading‬‬ ‫‪=2‬‬

‫بــرای اطمینان از صحت تنظیمات صورتگرفته‪ ،‬دســتور زیر را اجرا کنید‪ .‬درصورتیکه ارتباط بهدرســتی‬
‫برقرار شدهباشد‪ ،‬عبارت ‪ FreeTDS‬باز گردانده میشود‪.‬‬
‫‪#odbcinst -q –d‬‬
‫]‪[FreeTDS‬‬

‫در مرحله بعد‪ ،‬باید تنظیمات فایل ‪ odbc.ini‬را انجام دهید‪ .‬این فایل یک شناســه میســازد که استریســک‬
‫بهواســطه آن به پایگاه دادهای متصل میگردد‪ .‬درصورت تمایل به تعویض دیتابیس‪ ،‬تنها کافیســت مقادیر‬
‫این فایل را تغییر دهید‪.‬‬
‫‪#vim /etc/odbc.ini‬‬
‫]‪[asterisk-connector‬‬
‫‪Description‬‬ ‫‪= MS SQL connection to ‘asterisk’ database‬‬
‫‪Driver‬‬ ‫‪= FreeTDS‬‬
‫‪Database‬‬ ‫‪= asterisk‬‬
‫‪Server‬‬ ‫‪= 192.168.100.1‬‬
‫‪Trace‬‬ ‫‪= No‬‬
‫‪TDS_Version‬‬ ‫‪= 7.0‬‬
‫‪Port‬‬ ‫‪= 1433‬‬

‫تا اینجا ارتباط پایگاه دادهای با ‪ ODBC Connector‬برقرار شد‪ .‬برای تست این ارتباط از دستور زیر استفاده‬
‫کنید‪:‬‬
‫‪# isql -vvv asterisk-connector asterisk 123123‬‬
‫‪# echo "select 1" | isql -vvv asterisk-connector asterisk 123123‬‬
‫‪+---------------------------------------+‬‬
‫!‪| Connected‬‬ ‫|‬
‫|‬ ‫|‬
‫‪| sql-statement‬‬ ‫|‬
‫]‪| help [tablename‬‬ ‫|‬
‫‪| quit‬‬ ‫|‬
‫‪+---------------------------------------+‬‬
‫>‪SQL‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪328‬‬

‫چنانچه همه تنظیمات بهدرســتی انجام شــده باشــند‪ ،‬خروجی باال را مشــاهده خواهید کــرد‪ .‬هم اکنون هر‬
‫دستوری را اجرا کنید‪ ،‬در پایگاه دادهای شما نیز اعمال میشود‪.‬‬
‫چنانچه خطایی در برقراری این ارتباط وجود داشته باشد‪ ،‬این پیام را مشاهده خواهید کرد‪:‬‬

‫‪# isql -vvv asterisk-connector asterisk 123123‬‬


‫'‪[S1000][unixODBC][MySQL][ODBC 5.1 Driver]Access denied for user 'asterisk'@'localhost‬‬
‫)‪(using password: YES‬‬
‫‪[ISQL]ERROR: Could not SQLConnect‬‬

‫بعد از نصب و پیکربندی ‪ ODBC Connection‬و ارتباط آن با پایگاههای دادهای‪ ،‬باید به مســیر نصب‬
‫استریسک وارد شوید و ماژول مورد نیاز )‪ (res_odbc.so‬را فعال و سپس دوباره استریسک را کامپایل کنید‪.‬‬
‫ازآنجاکه ‪ ODBC Deriver‬قب ً‬
‫ال در سیستم نصب نشده است‪ ،‬واضح است که استریسک آن را تشخیص‬
‫میدهد‪ .‬پیشفرض تمامی ماژولهای مربوطه غیرفعال است‪.‬‬
‫با اجرای دســتور ‪ ، . /configure‬استریسک مجددا ً تمامی ‪ Driver‬ها و ماژولهای نصب شده در سیستم‬
‫لینوکس را بررسی میکند و چنانچه ‪ Driver‬ها و ماژولهای جدیدی نصب شده باشند‪ ،‬ماژولهای خود را‬
‫در استریسک فعال میکند‪.‬‬
‫‪#./configure‬‬

‫بعد از اجرای دستور فوق‪ ،‬استریسک ماژولهای زیر را فعال میکند‪:‬‬


‫‪• cdr_odbc.so‬‬
‫‪• cdr_adaptive.so‬‬
‫‪• func_odbc.so‬‬
‫‪• func_realtime.so‬‬
‫‪• pbx_realtime.so‬‬
‫‪• res_config_odbc.so‬‬
‫‪• res_odbc.so‬‬

‫برای مشاهده همه ماژولها‪ ،‬دستور زیر را تایپ کنید‪:‬‬


‫‪#make menuselect‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬در این بخــش میتوان ماژولهای مورد نیاز را با فشــردن کلید “‪ ”space‬و‬
‫نمایــش عالمت]*[ فعال کرد و درصورت عدمنیاز به ماژولها‪ ،‬با فشــردن مجــدد کلید "‪ "space‬و نمایش‬
‫عالمت ] [ ‪ ،‬ماژول را غیرفعال کرد‪ .‬در این بخش اطمینان پیدا کنید که ماژولهای ‪res_odbc , func_odbc‬‬
‫حتماً فعال )عالمت ]*[( باشند‪.‬‬
‫چنانچه جلوی برخی ماژولها عالمت ]‪ [XXX‬دیده شــد‪ ،‬به منزله این است که ماژولها و ‪ Driver‬های‬
‫الزم برای اســتفاده از این ماژول‪ ،‬درسیستم لینوکس نصب نشدهاند‪ .‬در این صورت ابتدا باید آنها را نصب‬
‫کنید و بعد استریسک را مجددا ً کامپایل کنید‪.‬‬
‫‪329‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫پیکربندی ماژول ‪ res_odbc.so‬در استریسک‬


‫بعد از نصب مجدد استریسک‪ ،‬باید بتوانیم ماژول ‪ res_odbc.so‬در استریسک را به ‪ODBC Connection‬های‬
‫تعریفشده متصل کنیم‪ .‬برای این منظور از فایل ‪ res_odbc.conf‬در مسیر زیر استفاده میکنیم‪.‬‬

‫‪# vim /etc/asterisk/res_odbc.conf‬‬

‫در این فایل تنظیمات برای ارتباط با ‪ ODBC Connector‬بهصورت زیر خواهد بود‪:‬‬
‫]‪[asterisk‬‬
‫‪enabled => yes‬‬
‫‪dsn => asterisk-connector‬‬
‫‪username => asterisk‬‬
‫‪password => 123123‬‬
‫‪pooling => no‬‬
‫‪limit => 1‬‬
‫‪pre-connect => yes‬‬

‫پارامتر ‪ :dsn‬نام شناسه تعریف شده در فایل ‪ /etc/odbc.ini‬است‪.‬‬


‫پارامتر ‪ :username‬برای ارتباط با پایگاه داده‌ای‪ ،‬به یک نام کاربری نیاز خواهیم داشــت که به‌وســیله این‬
‫پارمتر تعیین می‌شود‪.‬‬
‫پارامتــر ‪ :password‬برای ارتباط با پایگاه داده‌ای نیازمند رمز عبور هســتیم که به‌وســیله این پارامترتعیین‬
‫می‌شود‪.‬‬
‫پارامتــر ‪ :pre-connected‬برای کاهش ســربار اضافــی هنگام اتصال بــه پایــگاه داده‌ای‪ ،‬پارامتر ‪pre-‬‬
‫‪ connected=yes‬تنظیم می‌شــود‪ .‬هنگام لود شــدن ماژول "‪ ،"res_odbc.so‬ارتباط بــا پایگاه داده‌ای برقرار‬
‫می‌ماند‪.‬‬
‫پس از اینکه تنظیمات الزم را انجام دادید میتوانید بهوسیله دستور زیر‪ ،‬در محیط کامندالین استریسک‪،‬‬
‫‪ ODBC Connector‬را مشاهده کنید‪.‬‬ ‫وضعیت ارتباطی استریسک با‬
‫‪CLI> odbc show all‬‬
‫‪ODBC DSN Settings‬‬
‫‪-----------------‬‬
‫‪Name: asterisk‬‬
‫‪DSN: asterisk-connector‬‬
‫‪Last connection attempt: 1970-01-01 03:30:00‬‬
‫)‪Number of active connections: 1 (out of 1‬‬

‫پرسشی که اینجا مطرح میشود این است که چه ارتباطی میان پیکربندی فایلهای ‪odbc.int, odbcints.‬‬
‫‪ int‬و ماژول ‪ res_odbc‬وجود دارد؟ برای روشن شدن این مطلب‪ ،‬به شکل ‪ 4-۱۱‬دقت کنید‪:‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪330‬‬

‫شکل ‪4-11‬‬

‫همانطورکه در شــکل مالحظــه میکنید‪ ،‬بهوســیله ‪ odbcints.ini‬ابتدا یک نمونه‪ ۱‬از یــک پایگاه دادهای‬
‫ایجاد کردیم‪ .‬ســپس بهوسیله فایل ‪ odbc.ini‬یک ‪ ODBC Connection‬میسازیم و در فایلهای پیکربندی‬
‫استریسک از این ‪ ODBC Connection‬برای ارتباط با پایگاه دادهای استفاده میکنیم‪.‬‬

‫مدیریت پایگاه‌های داده‌ای‬


‫بررســی موضوعات مرتبط بــا مدیریت پایگاه دادهای‪ ،‬خارج از موضوع و هدف این کتاب اســت و تنها به‬
‫نرمافزار اکتفا میکنیم‪ .‬با این نرمافزارها میتوانید یک پایگاه دادهای را آسانتر مدیریت کنید‪.‬‬ ‫معرفی چند‬
‫برخــی از این نرمافزارها بهصورت یــک برنامه کاربردی و برخی دیگر بهصــورت نرمافزارهای تحت وب‬
‫هستند‪.‬‬
‫به کمک این ابزارها میتوانید به دیتابیس متصل شوید و آن را مدیریت کنید‪.‬‬
‫‪• phpMyAdmin‬‬
‫‪• MySQL dbforge‬‬
‫)‪• pgAdmin (PostgreSQL‬‬

‫وقتی با ‪ ODBC Connector‬و استریسک کار میکنید‪ ،‬ممکن است خطاهایی در سیستم رخ دهد که مربوط‬
‫به ارتباط با پایگاههای دادهای باشــد‪ .‬بنابراین‪ ،‬اطالعاتی که از طرف استریسک به طرف دیتابیس میرود را‬
‫با هدف یافتن خطاهای احتمالی باید بررسی کنید‪.‬‬

‫‪1- instance‬‬
‫‪331‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫برای مثال فرض کنید تصمیم داریم اطالعاتی را در یک جدول ذخیره کنیم که ساختارش با آن چیزی‬
‫که در استریســک انتظار میرود‪ ،‬متفاوت اســت‪ .‬در نتیجه استریســک هنگام افزودن اطالعات‪ ،‬اعالم خطا‬
‫میکند‪ .‬نیاز به سیستم الگگیری در این شرایط الزامی است‪.‬‬

‫‪SQL Injection‬‬
‫برای برنامههای تحت شبکه‪ ،‬امنیت همیشه حرف اول را میزند و چنانچه این نرمافزارها با دیتابیس در ارتباط‬
‫باشند‪ ،‬حفظ امنیت دیتابیس نیز باید تأمین گردد‪.‬‬
‫برای برنامههایی که با دیتابیس در ارتباطاند‪ ،‬کنترل ‪ SQL Injection‬بسیار حیاتی است‪SQL Injection .‬‬
‫عبارت است از انتقال اطالعات مخرب به طرف دیتابیس‪ ،‬به این صورت که نفوذگر با یک سری دستورهای‬
‫‪ SQL‬یک عملیات تهاجمی )متفاوت با عملیات عادی موردنظر طراح نرمافزار( در دیتابیس صورت میدهد‪.‬‬
‫اینگونه حمالت میتواند موجب پاکشدن کلیه اطالعات و به سرقت رفتن آنها شود‪.‬‬

‫استفاده از پایگاه‌های داده‌ای در برنامه نویسی استریسک‬


‫اســتفاده از ‪ func_odbc‬در استریسک یکی از قابلیتهای ارزشــمند در برنامهنویسی است‪ .‬با استفاده از این‬
‫قابلیت میتوان هنگام اجرای برنامهها در استریسک‪ ،‬دستورات ‪ SQL‬را اجرا نمود‪.‬‬
‫مثال( فرض کنید قصد داریم درخصوص هر تماس جدیدی که وارد سیستم میشود‪ ،‬ابتدا شماره کالرآیدی‬
‫آن را مشــخص کنیم‪ .‬ســپس براساس شماره کالرآیدی‪ ،‬سابقه تماس آن را در دیتابیس جستجو کنیم و در‬
‫مورد ‪ Block‬کردن آن تصمیم بگیریم‪.‬‬
‫اینجا باید دســتورات در دو بخش متفاوت قرار گیرند‪ .‬بخش اول‪ ،‬برنامهنویســی استریسک است که در‬
‫فایــل ‪ extensions.conf‬قــرار دارد و بخش دوم به اجرا شــدن کدهای ‪ SQL‬مربوط اســت و باید در فایل‬
‫‪ func_odbc.conf‬انجام شود‪.‬‬
‫مثال( ابتدا در فایل ‪ func_odbc.conf‬یک تابع ایجاد کنید و دستورات ‪ SQL‬را در آنجا قرار دهید‪:‬‬
‫]‪[ANIBLOCK‬‬
‫‪dsn=asterisk‬‬
‫'}‪readsql=SELECT IF(COUNT(1)>0, 1, 0) FROM Aniblock WHERE NUMBER='${ARG1‬‬

‫پارامتر ‪ ، dsn‬نام ‪ ODBC Conector‬است که قب ً‬


‫ال در فایل ‪ res_odbc.conf‬تعریف شده است‪ .‬اکنون قرار‬
‫است در استریسک این تابع را فراخوانی کنیم‪ .‬فرمت فراخوانی تابع نوشته شده بهصورت زیر است‪:‬‬

‫]]‪ODBC_functionname(<arg1>[...[,<argN>]])[=[val1‬‬

‫اکنون برای استفاده از تابع تعریف شده در برنامه‪ ،‬تابع زیر را اجرا کنید‪:‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 332

[LocalSets]
exten => _5XXX,1,NoOp()
same => n,Set(CDR(accountcode)=pricall)
; Does this callerID appear in the database?
same => n,GotoIf($[${ODBC_ANIBLOCK(${CALLERID(number)})}]?busy)
same => n(dial),Dial(DAHDI/g1/${EXTEN})
same => n(busy),Busy(10) ; Yes, you are on the blacklist.
same => n,Hangup

‫ استفاده‬ODBC ‫ از پیشوند‬،‫ ضرورتا باید پیش از نام تابع‬،‫ در فرمت اصلی تابع‬،‫همانطورکه مالحظه میکنید‬
.‫ مثال کاربردی زیر را انجام دهید‬،‫ برای درک بهتر این موضوع‬.‫کنید‬
‫ یک دیتابیس جدید ایجاد کنید و‬، PostgreSQL ‫ یا‬MySQL ،‫مثال( ابتدا در پایگاه دادهای مورد نظر خود‬
.‫ استفاده میکنیم‬MySQL ‫ در این مثال از پایگاه دادهای‬.‫ بگذارید‬AsteriskDB ‫نام آن را‬
mysql > CREATE DATABASE asteriskdb;
Query OK, 1 row affected (0.00 sec)

.‫ ایجاد کنید که دارای فیلدهای زیر باشد‬user ‫سپس یک جدول جدید بهنام‬

filed Type null key deafult extra


userid Int(11) no PRI null AUTO_INCREMENT
password Int(11) yes null
callerid Int(11) yes null

1-11 ‫جدول‬

.‫برای ساختن این جدول دستور زیر را اجرا کنید‬


mysql> use asteriskdb;
Database changed
mysql> CREATE TABLE user (
-> userid int(11) NOT NULL AUTO_INCREMENT,
-> password int(11) DEFAULT NULL,
-> callerid int(11) DEFAULT NULL,
-> PRIMARY KEY (userid)
-> );
Query OK, 0 rows affected (0.02 sec)

:‫ دستور زیر را اجرا کنید‬،‫برای مشاهده جدولهای موجود در این دیتابیس‬


mysql> show tables;
+----------------------+
| Tables_in_asteriskdb |
+----------------------+
| user |
+----------------------+
1 row in set (0.00 sec)
‫‪333‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫و برای دیدن ساختار جدولهای موجود در دیتابیس‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫;‪mysql> describe user‬‬
‫‪+----------+---------+------+-----+---------+----------------+‬‬
‫‪| Field | Type | Null | Key | Default | Extra‬‬ ‫|‬
‫‪+----------+---------+------+-----+---------+----------------+‬‬
‫| ‪| userid | int(11) | NO | PRI | NULL | auto_increment‬‬
‫‪| password | int(11) | YES | | NULL‬‬ ‫|‬ ‫|‬
‫‪| callerid | int(11) | YES | | NULL‬‬ ‫|‬ ‫|‬
‫‪+----------+---------+------+-----+---------+----------------+‬‬
‫)‪3 rows in set (0.01 sec‬‬

‫اکنون باید یک تابع در فایل ‪ func_odbc.conf‬بهنام ]‪ [GET-PSWD‬بســازید‪ .‬هدف این اســت که در این‬
‫تابع‪ ،‬پسورد براساس کالرآیدی استخراج شود‪ Query .‬دستورات ‪ SQL‬بهصورت زیر است‪:‬‬
‫‪#vim /etc/asterisk/func_odbc.conf‬‬
‫]‪[GET_PSWD‬‬
‫‪dsn=asterisk‬‬
‫"}‪readsql=SELECT password FROM user WHERE callerid = "${ARG1‬‬

‫‪res_odbc.conf‬‬ ‫اینجا ]‪ [GET-PSWD‬نام تابع اســت‪ dsn .‬نام ‪ ODBC Connector‬اســت که قب ً‬


‫ال در فایل‬
‫تعریف شدهاست‪.‬‬
‫‪ :readsql‬چون این ‪ query‬از نوع ‪ read-only‬اســت و خروجی آن‪ ،‬خواندن دادههایی از دیتابیس است‪ ،‬لذا‬
‫نوع کالس تابع را بهصورت ‪ readsql‬نشان میدهیم‪.‬‬
‫اگر دســتوراتی کــه در ‪ SQL‬اســتفاده میکنید ‪ ،‬باعث ایجاد تغییــر در دیتابیس شــود ) مثل ‪ Insert‬یا‬
‫‪ ،(Update‬باید از کالس تابع "‪ "writesql‬استفاده کنید‪.‬‬
‫اکنون باید از تابع ]‪ [GET-PSWD‬در برنامهنویسی استریسک استفاده کنید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[localSets‬‬
‫)})})‪exten => s,n,NoOp(${ODBC_GET_PSWD(${CALLERID(num‬‬

‫در این مثال )‪ CALLERID(num‬را بهعنوان آرگومان ورودی به تابع‪ ،‬ارســال میکنیم‪ .‬هنگام تعریف‬
‫تابع‪ ،‬مقدار پارامتر ارسالی را بهصورت }‪ ${ARG 1‬میخوانیم‪.‬‬
‫مثال) فرض کنید از کاربر بخواهیم یک پســورد وارد کند و ســپس آن را‪ ،‬با پسورد ذخیره شده در دیتابیس‬
‫مقایسه نماید‪ .‬در صورت یکسان نبودن دو پسورد‪ ،‬تماس را‌ ‪ Hangup‬کنید‪ .‬به مثال زیر توجه کنید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[localSets‬‬
‫)‪exten => s,1,Read(UserInput,pls-enter-password‬‬
‫)‪same => n,GotoIf($[${ODBC_GET_PSWD(${CALLERID(num)})} = ${UserInput}]?:hangup‬‬
‫)‪same => n,VoiceMail(${EXTEN},s‬‬
‫)(‪same => n(hangup),Hangup‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪334‬‬

‫بهوســیله دستور ‪ Read‬یک فایل صوتی پخش میشــود و از کاربر خواسته میشود که پسورد خود را وارد‬
‫نماید‪ .‬پســورد وارد شده بهوسیله کاربر‪ ،‬در متغیر ‪ UserInput‬ذخیره میشود‪ .‬سپس با پسورد ذخیره شده در‬
‫جدول مقایسه میشود‪.‬‬
‫مثال( فرض کنید بخواهیم دستوراتی را اجرا کنیم که مقداری را در دیتابیس ذخیره کند‪ .‬بهعنوان مثال برنامه‬
‫زیر را در نظر بگیرید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[localSets‬‬
‫)‪exten => s,1,Read(User_Pass,pls-enter-password‬‬
‫)}‪same => n,Set(OBDC_SET_PSWD(${CALLERID(num)})=${User_Pass‬‬

‫در این مثال )‪ CALLERID(num‬بهعنوان }‪ ${ARG1‬درنظر گرفتهشده و مقدار متغیر ‪ User_Pass‬بهعنوان‬


‫}‪ ${VAL1‬درنظر گرفته شــده اســت‪ .‬ازآنجاکه تصمیم داریم مقداری را در دیتابیس "‪ "Update‬کنیم‪ ،‬تابع‬
‫جدیدی در فایل ‪ func_odbc.conf‬باید ایجاد کنیم که از نوع کالس "‪ "writesql‬باشد‪.‬‬
‫‪;func_odbc.conf‬‬
‫]‪[SET_PSWD‬‬
‫‪dsn=asterisk‬‬
‫"}‪writesql=UPDATE user SET password = "${VAL1}" WHERE callerid = "${ARG1‬‬

‫تغییر پیشوند در فراخوانی توابع از فایل ‪res_odbc‬‬


‫همانطورکه پیشتر توضیح داده شــد‪ ،‬برای فراخوانی نام تابع‪ ،‬از پیشــوند "_‪ "ODBC‬استفاده میکنیم‪ .‬این‬
‫پیشوند را درصورت نیاز میتوانیم تغییر دهیم‪ .‬برای مثال برنامههای زیر را ببینید‪.‬‬
‫‪;func_odbc.conf‬‬
‫]‪[PSWD1‬‬
‫‪dsn=asterisk‬‬
‫"}‪readsql=SELECT password FROM user WHERE callerid = "${ARG1‬‬

‫]‪[PSWD2‬‬
‫‪prefix=GET‬‬
‫‪dsn=asterisk‬‬
‫"}‪readsql=SELECT password FROM user WHERE callerid = "${ARG1‬‬

‫نحوه فراخوانی کردن توابع تعریف شــده در باال به صورت زیر می باشــد‪ ،‬به پیشــوند استفاده شده در زمان‬
‫فراخوانی کردن توابع دقت کنید‪.‬‬
‫‪;extensions.conf‬‬
‫)})})‪same => n,NoOp(${ODBC_PSWD1(${CALLERID(num‬‬
‫)})})‪same => n,NoOp(${GET_PSWD2(${CALLERID(num‬‬

‫اضافه‌کردن توضیحات در خصوص توابع تعریف‌شده در فایل ‪res_odbc‬‬


‫گاهی نیاز است توضیحاتی در مورد هر تابع داشته باشیم‪ .‬به این منظور بهصورت زیر عمل کنید‪:‬‬
335 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

;func_odbc.conf
[PSWD2]
synopsis=This function reads a password out of the database based on the CallerID number
prefix=GET
dsn=asterisk
readsql=SELECT password FROM user WHERE callerid = "${ARG1}"

‫ توضیحاتی در خصوص تابع فوق در محیط کامندالین استریسک‬،‫دراینصورت میتوان بهوسیله دستور زیر‬
.‫مشاهدهکرد‬
CLI> core show function GET_PSWD2
[Synopsis]
This function reads a password out of the database based on the CallerID number
SQL:
SELECT password FROM user WHERE callerid = '${ARG1}'

[Syntax]
GET_PSWD2(<arg1>[...[,<argN>]])

Multi Row Query ‫استفاده از دستورات‬


‫ برای مثال‬.‫گاهی الزم اســت از دســتوراتی در دیتابیس استفاده کنیم که بیش از یک ســطر خروجی دارند‬
.‫دستور زیر را اجرا کنید‬
mysql>SELECT blknumber FROM blacklist-table;

‫ در چنین شرایطی باید هنگام تعریف تابع در‬.‫در این حالت ممکن اســت بیش از یک خروجی داشــته باشید‬
.‫ برای مثال به تعریف تابع زیر توجه کنید‬.‫ را فعال کنید‬mode = multirow ‫ پارامتر‬، func_odbc.conf ‫فایل‬

;func_odbc.conf
[BLK_NUMBER]
mode=multirow
dsn=asterisk
readsql=SELECT blknumber FROM blacklist_table
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 336

mode = ‫ پارامتر‬،‫ بنابراین‬،‫ ممکن اســت چند ســطر خروجی داشته باشیم‬،‫همانطورکه مالحظه میکنید‬
:‫ نحوه استفاده از این تابع بهصورت زیر است‬.‫ تعریف میکنیم‬multirow
;extensions.conf
[multirow]
exten => _NXXX,1,NoOp()
same => n,Set(ID=${ODBC_BLK_NUMBER()})
same => n(loop_start),Set(ROW_VALUE=${ODBC_FETCH(${ID})})
same => n,GotoIF($[ "${ODBC_FETCH_STATUS}" = "FAILURE"]?End)
same => n,GotoIf($[ "${ROW_VALUE}" = "${EXTEN}"]?Number-Found)
same => n,Goto(loop_start)
same => n(End),ODBCFinish(${ODBC_ID})
same => n,Goto(outgoing,${EXTEN},1)
same => n,Hangup()
same => n(Number-Found),ODBCFinish(${ODBC_ID})
same => n,Playback(extension&privacy-backlisted)
same => n,Hangup()

‫ را‬Query ‫ میتوان هر ســطر از اجرای‬ODBC_FETCH ‫ بهوســیله تابع‬،‫همانطورکه مالحظه میکنید‬


:‫ فرمت استفاده از این تابع بهصورت زیر است‬.‫گرفت‬
CLI> core show function ODBC_FETCH
[Synopsis]
Fetch a row from a multirow query.
[Syntax]
ODBC_FETCH(result-id)

‫ این متغییر میتواند مقادیر زیر‬.‫ ذخیره میشــود‬ODBC_FETCH_STATUS ‫ در متغیر‬،‫نتیجه خروجی تابع‬
:‫را داشته باشد‬
.‫ موفقیتآمیز باشد‬ODBC_FETCH ‫ اگر نتیجه تابع‬:SUCCESS •
.‫ موفقیتآمیز نباشد‬ODBC_FETCH ‫ اگر نتیجه تابع‬:FAILURE •
،‫ را پاک کرد‬Query ‫ میتوان نتایج حاصل از اجــرای‬ODBCFinish ‫ بهوســیله دســتور‬،‫عــالوه بر این‬
ODBCFinish ‫ فرمت اســتفاده از دســتور‬.‫ حافظه خالی باشــد‬،‫بهطوری که برای اجرای بعدی دســتورات‬
:‫بهصورت زیر است‬
CLI> core show application ODBCFinish
[Synopsis]
Clear the resultset of a sucessful multirow query.
[Syntax]
ODBCFinish(result-id)

‫ در برنامه‌نویسی استریسک‬SQL Query ‫استفاده از دستورات‬


.‫ بود‬func_odbc.conf ‫ در توابع تعریف شده از فایل‬SQL ‫ استفاده از دستورات‬،‫آنچه تا اینجا صحبت شــد‬
‫‪337‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫اکنون میتوانیم بهطور مستقیم در برنامهنویسی استریسک از دستورات ‪ SQL‬استفاده و ‪Query‬های مختلفی‬
‫را اجرا کنیم‪.‬‬
‫مثال( فرض کنید ما در فایل ‪ func_odbc.conf‬چنین مقادیری داشته باشیم‪:‬‬
‫]‪[SQL‬‬
‫‪prefix=GENERIC‬‬
‫‪dsn=asterisk‬‬
‫})}‪readsql=${SQL_ESC(${ARG1‬‬
‫})}‪writesql=${SQL_ESC(${VAL1‬‬

‫در ایــن حالت هیچ دســتوری از نــوع ‪ SQL‬نداریم‪ ،‬بلکه دســتورات ‪ SQL‬را بهصــورت پارامتر برای تابع‬
‫‪ SQL_ESC‬ارسال میکنیم تا بهوسیله آن اجرا شوند‪.‬‬
‫به مثالهای زیر توجه کنید‪:‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 8811,1,Goto(odbcreadtest,1‬‬
‫)‪exten => 8822,1,Goto(odbcwritetest,1‬‬

‫)(‪exten => odbcreadtest,1,NoOp‬‬


‫‪same => n,Set(result=${GENERIC_SQL(SELECT first_name FROM ast_hotdesk WHERE‬‬
‫)})‪id=4‬‬
‫)}‪same => n,Verbose(1,${result‬‬
‫)(‪same => n,Hangup‬‬

‫)(‪exten => odbcwritetest,1,NoOp‬‬


‫‪same => n,Set(GENERIC_SQL()=UPDATE ast_hotdesk SET first_name =\'${EXTEN}\' WHERE‬‬
‫)‪id=4‬‬
‫)}‪same => n,Verbose(1,ODBC_RESULT is ${OBDBC_RESULT‬‬
‫)(‪same => n,Hangup‬‬

‫همان طور که مالحظه می کنید ما از دســتورات ‪ SQL‬در داخل برنامه استریسک استفاده کرده ایم‪.‬در ادامه‬
‫‪ Asterisk Realtime Architecture‬میپردازیم‪.‬‬ ‫به یکی از قابلیتهای منحصر به فرد استریسک بهنام‬

‫(‪Asterisk Realtime Architecture (ARA‬‬


‫‪ Asterisk Realtime Architecture‬که به اختصار آن به آن ‪ ARA‬گفته میشــود‪ ،‬یکی از ویژگیهای مهم‬
‫و بر جســته استریســک اســت‪ .‬معماری ‪ ARA‬به ما این امکان را میدهد که بهجای پیکربندی استریسک‬
‫ازطریق فایلها‪ ،‬از پایگاههای دادهای برای ذخیرهکردن پیکربندی استریسک‪ ،‬استفاده کنیم‪.‬‬
‫شــاید پیکربندی استریسک بهوســیله فایلها بسیار ساده به نظر برسد‪ ،‬اما اگر سناریوها بزرگ باشند و به‬
‫چند ســرور استریسک بهصورت توزیع شده نیاز داشته باشــند‪ ،‬در این وضعیت بهتر است از معماری ‪ARA‬‬
‫بهره گرفته شود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪338‬‬

‫معماری ‪ ARA‬در استریسک به دو روش قابل پیاده‌سازی است‪:‬‬


‫• معماری ‪ARA_Static‬‬
‫• معماری ‪ARA_Dynamic‬‬
‫در روش معماری ‪ ،ARA_Static‬پیکربندی استریســک به پیکربندی در فایل‪ ،‬بســیار شبیه است‪ ،‬با این‬
‫تفاوت که تنها بهجای اســتفاده از فایل از دیتابیس اســتفاده میشود‪ .‬پس از اعمال هر تغییری در استریسک‪،‬‬
‫باید ماژول مربوطه را مجددا ً راه اندازی کنید‪.‬‬
‫در روش معمــاری ‪ ،ARA_Dynamic‬بهراحتی هر تغییــری را از طریق دیتابیس میتوان انجام داد و در‬
‫نهایت این تغییرات بهصورت خودکار‪ ،‬در استریسک آپدیت میشوند و نیازی به ‪ reload‬کردن ماژولهای‬
‫مربوطه وجود ندارد‪.‬‬
‫برای بهره گرفتن از معماری ‪ ، ARA‬الزم اســت تنظیماتی در فایل ‪ extconfig.conf‬در مســیر فایلهای‬
‫پیکربندی استریســک انجام دهید‪ .‬در این فایل تعیین میشــود که استریســک برای پیکربندی خود‪ ،‬از چه‬
‫دیتابیس و جداولی باید اســتفاده کند‪ .‬برای مثال میتوان اینگونه تعیین کرد که استریسک بهجای استفاده از‬
‫فایل ‪ ، sip.conf‬از دیتابیس و جدول مشــخصی اســتفاده کند‪ .‬بنابراین‪ ،‬چنانچه قصد داشته باشید یک کاربر‬
‫جدید از نوع پروتکل ‪ SIP‬ایجاد کنید‪ ،‬باید بهجای تعریف آن در فایل ‪ ،sip.conf‬آن را در دیتابیس تعریف‬
‫کنید‪.‬‬
‫در ادامه درخصوص این معماری توضیحات بیشتری خواهد آمد‪.‬‬

‫معماری ‪ARA_Static‬‬
‫همانطورکه پیشتر توضیح داده شــد‪ ،‬این روش به روش استفاده از تنظیمات پیکربندی استرسیک بهوسیله‬
‫فایلها شــباهت زیادی اســت؛ با این تفاوت که بهجای کار با یک فایل مشــخص‪ ،‬از یک دیتابیس استفاده‬
‫میکنیم‪.‬‬
‫هنگام اســتفاده از معماری ‪ ARA_Static‬باید مشخص کنید که با چه نوع دیتابیسی کار میکنید‪ .‬فرمت‬
‫استفاده از این نوع تعریف در فایل ‪ extconfig.conf‬بهصورت زیر است‪.‬‬
‫‪#vim /etc/asterisk/extconfig.conf‬‬
‫]‪[settings‬‬
‫]‪filename.conf => driver,database[,table‬‬
‫ِ‬
‫تنظیمات کدام فایلها‪ ،‬باید از دیتابیس استفاده کند‪.‬‬ ‫در این فرمت مشخص میشود که استریسک برای‬
‫مثال( فرض کنید استریســک‪ ،‬برای پیکربندی موزیک انتظار قرار اســت از دیتابیس استفاده کند‪ .‬برای این‬
‫منظور باید در فایل ‪ extconfig.conf‬تنظیمات زیر ار انجام دهید‪.‬‬
‫‪;extconfig.conf‬‬
‫‪339‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫]‪[settings‬‬
‫‪musiconhold.conf=>odbc,asterisk,ast_config‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬به کمک این تنظیمات‪ ،‬از طریق ‪ ،ODBC Connection‬به پایگاه دادهای و‬
‫دیتابیس ‪ asterisk‬و جدول ‪ ast_config‬متصل میشوید و تنظیمات پیکربندی را از آنجا میخوانید‪.‬‬
‫در تنظیمات باال میتوان از ذکر نام جدول خودداری کرد‪ .‬در این صورت‪ ،‬استریســک نام جدول و نام‬
‫فایل را یکسان در نظر میگیرد‪ .‬برای مثال تنظیمات زیر یکساناند‪:‬‬
‫‪;extconfig.conf‬‬
‫]‪[settings‬‬
‫‪musiconhold.conf=>odbc,asterisk‬‬
‫‪; musiconhold.conf=>odbc,asterisk,musiconhold‬‬

‫اکنون الزم اســت که یک جدول در دیتابیس داشته باشــید تا بتوانید تنظیمات فایل مربوطه را در آن ذخیره‬
‫کنید‪.‬‬
‫پرسشــی که ممکن است اینجا مطرح شود این است که جدول دیتابیس چه فیلدهایی باید داشته باشد و‬
‫چگونه باید تنظیمات فایل را درون یک جدول نگاشت داد؟‬
‫برای پاسخ به این پرسش‪ ،‬نخست بهتر است فایل ‪ musiconhold.conf‬را بررسی کنیم‪ .‬اگر این فایل را‬
‫باز کنید‪ ،‬خواهید دید که یک کالس ]‪ [default‬برای ‪ musiconhold‬بهصورت پیشفرض تعریف شدهاست‪.‬‬
‫‪;musiconhold.conf‬‬
‫]‪[default‬‬
‫‪mode=files‬‬
‫‪directory=moh‬‬

‫اکنون همین تنظیمات باال را به یک جدول در دیتابیس نگاشت میدهیم تا در نهایت جدول زیر را داشتهباشیم‪:‬‬

‫‪filename‬‬ ‫‪category‬‬ ‫‪Var_name‬‬ ‫‪Var_val‬‬


‫‪msiconhold.conf‬‬ ‫‪default‬‬ ‫‪mode‬‬ ‫‪files‬‬
‫‪msiconhold.conf‬‬ ‫‪default‬‬ ‫‪directory‬‬ ‫‪/var/lib/asterisk/moh‬‬
‫جدول ‪2-11‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬به ازای هر کالس جدید‪ ،‬یک “‪ ”category‬جدید خواهیم داشــت‪ .‬به ازای‬
‫هر پارامتر یک "‪ "var_name‬و به ازای هر مقدار در هر پارامتر نیز یک “‪ ”var_val‬خواهیم داشــت‪ .‬شــکل‬
‫‪ ۵-۱۱‬مراحل نگاشت را نمایش میدهد‪.‬‬
‫بنابراین‪ ،‬نگاشت موردنظر برای یک تعریف جدید از موزیک انتظار‪ ،‬میتواند بهصورت زیر باشد‪:‬‬
‫‪;musiconhold.conf‬‬
‫]‪[mymoh‬‬
‫‪mode=files‬‬
‫‪directory=mymoh‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪340‬‬

‫شکل ‪5-11‬‬

‫‪filename‬‬ ‫‪category‬‬ ‫‪Var_name‬‬ ‫‪Var_val‬‬


‫‪msiconhold.conf‬‬ ‫‪mymoh‬‬ ‫‪mode‬‬ ‫‪files‬‬
‫‪msiconhold.conf‬‬ ‫‪mymoh‬‬ ‫‪directory‬‬ ‫‪/var/lib/asterisk/mymoh‬‬
‫جدول ‪3-11‬‬
‫چنانچه مایل باشــیم از پارامترهای جدیدی برای تعریف موزیک انتظار اســتفاده کنیم‪ ،‬به سهولت میتوانیم‬
‫آنها را به جدول باال نگاشت دهیم‪.‬‬
‫گاهی هنگام تعریف پارامترها‪ ،‬اولویت ترتیب در تعریف مهم است)مثل پارامتر ‪ deny/permit‬در زمان‬
‫تعریف کاربر جدید(‪ .‬در چنین شــرایطی از فیلدهــای ‪ var_matric‬و ‪ cat_metric‬موجود در جدول‪ ،‬برای‬
‫اولویت دادن به تعریف پارامترها اســتفاده میکنیم )هر چه عدد کوچکتر باشــد‪ ،‬به این معناســت که پارامتر‬
‫زودتر تعریف شدهاست(‪.‬‬
‫برای مثال فرض کنید این تنظیمات را داشته‌باشیم‪:‬‬
‫‪;musiconhold.conf‬‬
‫]‪[default‬‬
‫‪mode=files‬‬
‫‪directory=moh‬‬

‫]‪[mymoh‬‬
‫‪mode=files‬‬
‫‪directory=mymoh‬‬

‫نگاشت آن به جدول‪ ،‬بهصورت زیر خواهد بود‪.‬‬

‫‪id‬‬ ‫‪cat_metric‬‬ ‫‪var_metric‬‬ ‫‪filename‬‬ ‫‪category‬‬ ‫‪var_name‬‬ ‫‪var_val‬‬ ‫‪Commentd‬‬


‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪musiconhold.conf‬‬ ‫‪default‬‬ ‫‪mode‬‬ ‫‪files‬‬
‫‪2‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪musiconhold.conf‬‬ ‫‪default‬‬ ‫‪directory‬‬ ‫‪/var/lib/‬‬
‫‪asterisk/moh‬‬
‫‪3‬‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪musiconhold.conf‬‬ ‫‪mymoh‬‬ ‫‪mode‬‬ ‫‪files‬‬
‫‪4‬‬ ‫‪2‬‬ ‫‪2‬‬ ‫‪musiconhold.conf‬‬ ‫‪mymoh‬‬ ‫‪directory‬‬ ‫‪/var/lib/‬‬
‫‪asterisk/‬‬
‫‪mymoh‬‬
‫جدول ‪4-11‬‬
‫‪341‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫همانطورکه مالحظه میکنید‪ ،‬پارامترهای الزم برای پیکربندی را میتوانید به صورت جدول ‪ 4-۱۱‬نگاشت‬
‫دهید‪ .‬به این منظور باید جدولی با فیلدهای مشــابه جدول ‪ 4-۱۱‬داشــته باشــید‪ .‬این جدول بهصورت زیر در‬
‫پایگاه دادهای ایجاد میشود‪:‬‬
‫( ‪mysql> CREATE TABLE ast_config‬‬
‫‪id int(8) primary key auto_increment,‬‬
‫‪cat_metric int(8),‬‬
‫‪var_metric int(8),‬‬
‫‪filename varchar(128),‬‬
‫‪category varchar(128),‬‬
‫‪var_name varchar(128),‬‬
‫‪var_val varchar(128),‬‬
‫‪commented int default 0‬‬
‫;)‬
‫)‪Query OK, 0 rows affected (0.02 sec‬‬
‫>‪mysql‬‬

‫واضح اســت که میتوان هر فایلی از مســیر ‪ /etc/asterisk‬را با این روش نگاشــت داد و تنظیمات آن را در‬
‫جدول ذخیره نمود‪ .‬برای نمونه یک کاربر جدید با روش مذکور در استریســک ایجاد میکنیم‪ .‬این کاربر‬
‫در فایل ‪ sip.conf‬بهصورت زیر تعریف میشود‪:‬‬
‫‪;sip.conf‬‬
‫]‪[Phone_1‬‬
‫‪qualify=yes‬‬
‫‪host=dynamic‬‬
‫‪nat=force_rport,comedia‬‬
‫‪port=5060‬‬
‫‪type=friend‬‬
‫‪disallow=all‬‬
‫‪allow=ulaw,alaw‬‬
‫‪canreinvite=no‬‬
‫‪directmedia=no‬‬
‫‪callcounter=yes‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪secret=123123‬‬
‫‪context=LocalSets‬‬

‫ایــن تعریــف را باید به یک جدول نگاشــت دهیم‪ .‬این نگاشــت بهصــورت زیر خواهد بــود )ترتیب برای‬
‫پارامترهای ‪ Bold‬شده مهم است(‪:‬‬
‫ابتدا فایل ‪ sip.conf‬را باز کرده و در انتهای آن خط زیر را اضافه کنید‪.‬‬
‫‪;sip.conf‬‬
‫‪#include sip_custom.conf‬‬

‫حال جدول نگاشت را بهصورت زیر طراحی کنید‪.‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 342

id cat_metric var_metric filename category var_name var_val


1 1 1 sip_custom.conf Phone_1 qualify yes
2 1 2 sip_custom.conf Phone_1 host dynamic
3 1 3 sip_custom.conf Phone_1 nat force_
port,comedia
4 1 4 sip_custom.conf Phone_1 port 5060
5 1 5 sip_custom.conf Phone_1 type friend
6 1 6 sip_custom.conf Phone_1 disallow all
7 1 7 sip_custom.conf Phone_1 allow ulaw,alaw
8 1 8 sip_custom.conf Phone_1 canreinvite no
9 1 9 sip_custom.conf Phone_1 directmedia no
10 1 10 sip_custom.conf Phone_1 callcounter yes
11 1 11 sip_custom.conf Phone_1 deny 0.0.0.0/0.0.0.0
12 1 12 sip_custom.conf Phone_1 permite 0.0.0.0/0.0.0.0
13 1 13 sip_custom.conf Phone_1 secret 123123
14 1 14 sip_custom.conf Phone_1 context LocalSets
5-11 ‫جدول‬

:‫ کنید‬reload ‫ استریسک را‬،‫بعد از اجرای مراحل فوق‬


CLI>core reload

‫ پیشتر در فصل سوم )نصب استریسک و پیکربندی‬.‫ممکن است هنگام لود شدن مجدد با خطا مواجه شوید‬
.‫اولیه( توضیح داده شد که گاهی الزم است ترتیبی برای لود شدن ماژو لها در استریسک وجود داشته باشد‬
‫ برای‬.‫ پیش از سایر ماژول ها لود شوند‬res_config_odbc.so ‫ و‬res_odbc.so ‫اینجا الزم اســت ماژولهای‬
:‫ تغییرات زیر را اعمال کنید‬modules.conf ‫ در فایل‬،‫این منظور‬

; modules.conf
[modules]
autoload=yes
preload => res_odbc.so
preload => res_config_odbc.so

‫ در استریسک ایجاد‬Phone_2 ‫ چنانچه تصمیم داشــته باشــیم یک کاربر جدید با نام‬،‫بهعنوان نمونهای دیگر‬
.‫ طراحی کنید‬۱۱-۶ ‫ ابتدا باید تغییرات زیر را در هر فایل انجام دهید و بعد جدول را مطابق جدول‬،‫کنیم‬

;extconfig.conf
sip_mytest.conf => odbc,asterisk,ast_config
;sip.conf
#include sip_mytest.conf
343 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

id cat_metric var_metric filename category var_name var_val


1 1 1 sip_mytest.conf Phone_2 qualify yes
2 1 2 sip_mytest.conf Phone_2 host dynamic
3 1 3 sip_mytest.conf Phone_2 nat force_
port,comedia
4 1 4 sip_mytest.conf Phone_2 port 5060
5 1 5 sip_mytest.conf Phone_2 type friend
6 1 6 sip_mytest.conf Phone_2 disallow all
7 1 7 sip_mytest.conf Phone_2 allow ulaw,alaw
8 1 8 sip_mytest.conf Phone_2 canreinvite no
9 1 9 sip_mytest.conf Phone_2 directmedia no
10 1 10 sip_mytest.conf Phone_2 callcounter yes
11 1 11 sip_mytest.conf Phone_2 deny 0.0.0.0/0.0.0.0
12 1 12 sip_mytest.conf Phone_2 permite 0.0.0.0/0.0.0.0
13 1 13 sip_mytest.conf Phone_2 secret 123123
14 1 14 sip_mytest.conf Phone_2 context LocalSets
6-11 ‫جدول‬

:‫ به محیط کامندالین استریسک رفته و دستور زیر را اجرا کنید‬۱۱-۶ ‫پس از تعریف جدول‬
CLI> sip reload
CLI> sip show peers

.‫ را مشاهده کنید‬Phone_2 ‫در این حالت باید کاربر‬


ARA_ ‫ در ادامه بررســی معماری‬.‫ بهطور کامل بررســی شــد‬ARA_Static ‫تــا اینجا روش معمــاری‬
.‫ را پی خواهیم گرفت‬Dynamic

ARA_Dynamic ‫معماری‬
‫ از دیتابیس‬،‫ روش دیگری اســت برای اجازه دادن به استریسک تا بهجای فایلها‬ARA_Dynamic ‫معماری‬
‫ با این تفاوت که‬،‫ شباهت زیادی دارد‬ARA_Static ‫ این روش به روش‬.‫برای پیکربندی خود اســتفاده کند‬
‫ کردن ســرویس استریسک و یا ماژول مربوطه نیازی نیست؛‬reload ‫ به‬،‫پس از انجام هر تغییری در دیتابیس‬
.‫ آسانتر است‬،‫ این روش نسبت به روش مشابه‬،‫بنابراین‬
.‫ غالبا برای ماژولهایی در استریســک مناســب است که دائما در حال تغییرند‬ARA_Dynamic ‫روش‬
:‫مهمترین ماژولهای این سری عبارتند از‬
• SIP Module
• IAX2 Module
• Queue Module
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 344

:‫ باید بهصورت زیر عمل کنید‬ARA_Dynamic ‫در استریسک برای استفاده از‬
; extconfig.conf
[settings]
sippeers => driver,database[,table]

‫ نام جدول اختیاری است و استریسک درصورت لزوم میتواند از نامهای از قبل‬،ARA_Static ‫مانند روش‬
.‫( استفاده کند‬SIP ‫ برای ماژول‬sippers ‫تعریف شده )از قبیل‬
:‫ از تنظیمات پیشفرض زیر میتواند استفاده کند‬ARA_Dynamic ‫ استریسک برای‬،‫برای مثال‬
; extconfig.conf
[setting]
iaxusers => odbc,asterisk
iaxpeers => odbc,asterisk
sippeers => odbc,asterisk
sipregs => odbc,asterisk
ps_endpoints => odbc,asterisk
ps_auths => odbc,asterisk
ps_aors => odbc,asterisk
ps_domain_aliases => odbc,asterisk
ps_endpoint_id_ips => odbc,asterisk
voicemail => odbc,asterisk
extensions => odbc,asterisk
meetme => mysql,general
queues => odbc,asterisk
queue_members => odbc,asterisk
queue_rules => odbc,asterisk
acls => odbc,asterisk
musiconhold => mysql,general
queue_log => mysql,general

‫ در این صورت تنظیمات‬.‫ از دیتابیس استفاده کند‬SIP ‫مثال( تصمیم داریم استریسک برای پیکربندی ماژول‬
:‫ را باید بهصورت زیر انجام دهیم‬ARA_Dynamic ‫برای‬
; extconfig.conf
[settings]
sippeers => odbc,asterisk,ast_sippeers

‫ شــباهت‬ARA_Static ‫ به تنظیمات روش‬ARA_Dynamic ‫ تنظیمات روش‬،‫همانطورکه مالحظه میکنید‬


:‫ اما دو تفاوت اصلی با هم دارند‬،‫زیادی دارند‬
‫ در حالی که برای هر ماژول در‬،‫ برای همه فایلها یکســان است‬ARA-Static ‫ ســاختار جدول در روش‬-۱
.‫ باید جدول مربوط به آن طراحی شود‬ARA-Dynamic ‫روش‬
reload ‫ باید ســرویس استریســک یا ماژول مربوطه را‬، ARA_Static ‫ پس از اعمال هر تغییر در روش‬-۲
‫ کردن نیست و این تغییرات بهصورت خودکار اعمال‬reload ‫ نیازی به‬ARA_Dynamic ‫کنید ولی در روش‬
345 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

.‫میشوند‬
ARA_Dynamic ‫استریســک بهصورت پیشفرض از نامهــای زیر برای نامگذاری جــداول در روش‬
‫ استریســک از‬،‫” مقدار ندهیم‬table“ ‫ به پارامتر‬،‫ در این صورت اگر هنگام تعریف جدول‬.‫اســتفاده میکند‬
:‫نامهای زیر استفاده خواهدکرد‬
• iaxusers—IAX users
• iaxpeers—IAX peers
• sippeers—SIP peers and users
• sipregs—SIP registrations
• voicemail—voicemail boxes
• extensions—dialplan
• meetme—MeetMe conferences
• queues—queues
• queues_members—members of queues
• acls—access control lists
• musiconhold—music on hold
• queue_log—queue logging

‫ دســتور زیر را‬،‫ اگر در محیط کامندالین استریســک‬،extconfig.conf ‫پس از انجام تغییرات فوق در فایل‬
:‫” هایی )هشدارهایی( مواجه خواهید شد‬WARNING“ ‫ با‬،‫اجرا کنید‬
CLI> module unload chan_sip.so
CLI> module load chan_sip.so
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'name', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'ipaddr', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'port', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'regseconds', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'defaultuser', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'fullcontact', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'regserver', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'useragent', but that column does not exist!
res_config_odbc.c:1177 require_odbc: Realtime table ast_sippeers@asterisk requires
column 'lastms', but that column does not exist!

‫” به ما اعالم میکنــد که فیلد خاصی در جدول‬WARNING“ ‫ هر ســطر از‬،‫همانطورکــه مالحظه میکنید‬


.‫” ساخته نشده است‬ast_sippeers“ ‫ به این دلیل که هنوز جدول‬،‫” وجود ندارد‬ast_sippeers“
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 346

‫ عالوه بر این‬.‫”ها مشاهده میشود‬WARNING“ ‫ در هر سطر از‬،‫فیلدهای مورد نیاز برای ساختن جدول‬
.‫ فیلدهای دیگری نیز موردنیاز است‬،‫فیلدها‬
:‫ ایجاد نمایید‬MySQL ‫بهوسیله دستور زیر میتوانید این جدول را در‬
mysql>CREATE TABLE `ast_sippeers` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(80) NOT NULL default '',
`host` varchar(31) NOT NULL default '',
`nat` varchar(5) NOT NULL default 'no',
`type` enum('user','peer','friend') NOT NULL default 'friend',
`accountcode` varchar(20) default NULL,
`amaflags` varchar(13) default NULL,
`call-limit` smallint(5) unsigned default NULL,
`callgroup` varchar(10) default NULL,
`callerid` varchar(80) default NULL,
`cancallforward` char(3) default 'yes',
`canreinvite` char(3) default 'yes',
`context` varchar(80) default NULL,
`defaultip` varchar(15) default NULL,
`dtmfmode` varchar(7) default NULL,
`fromuser` varchar(80) default NULL,
`fromdomain` varchar(80) default NULL,
`insecure` varchar(4) default NULL,
`language` char(2) default NULL,
`mailbox` varchar(50) default NULL,
`md5secret` varchar(80) default NULL,
`deny` varchar(95) default NULL,
`permit` varchar(95) default NULL,
`mask` varchar(95) default NULL,
`musiconhold` varchar(100) default NULL,
`pickupgroup` varchar(10) default NULL,
`qualify` char(3) default NULL,
`regexten` varchar(80) default NULL,
`restrictcid` char(3) default NULL,
`rtptimeout` char(3) default NULL,
`rtpholdtimeout` char(3) default NULL,
`secret` varchar(80) default NULL,
`setvar` varchar(100) default NULL,
`disallow` varchar(100) default 'all',
`allow` varchar(100) default 'g729;ilbc;gsm;ulaw;alaw',
`fullcontact` varchar(80) NOT NULL default '',
`ipaddr` varchar(100) NOT NULL default '',
`port` int(11) unsigned NOT NULL default '0',
`regserver` varchar(100) default NULL,
`regseconds` int(11) NOT NULL default '0',
‫‪347‬‬ ‫ارتباط بین استریسک و پایگاه داده‌ای‬

‫‪`lastms` int(11) NOT NULL default '0',‬‬


‫‪`username` varchar(80) NOT NULL default '',‬‬
‫‪`defaultuser` varchar(80) NOT NULL default '',‬‬
‫‪`subscribecontext` varchar(80) default NULL,‬‬
‫‪`useragent` varchar(20) default NULL,‬‬
‫‪PRIMARY KEY (`id`),‬‬
‫)`‪UNIQUE KEY `name` (`name‬‬
‫;)‬

‫پس از ســاختن جدول‪ ،‬چنانچه قصد داشته باشــید یک کاربر جدید تعریف کنید‪ ،‬کافی است فیلدهای آن‬
‫را در یک ســطر از جدول پر کنید و بعد بهوســیله یک “‪ ”IP Phone‬یا “‪ ”Soft Phone‬در سرور استریسک‬
‫رجیستر شوید‪.‬‬
‫نکته مهم آنکه پس از تعریف کاربر جدید‪ ،‬نیازی به ‪ reload‬کردن ماژول ‪ chan_sip.so‬وجود ندارد‪.‬‬
‫بــرای نمونه فرض کنید بخواهیم یک کاربر جدیــد در جدول ‪ ast_sippeers‬ایجاد کنیم‪ .‬برای این کار‬
‫کافی است فیلدهای زیر را مقداردهی کنیم‪.‬‬

‫‪Column name‬‬ ‫‪value‬‬


‫‪name‬‬ ‫‪Phone_3‬‬
‫‪defaultuser‬‬ ‫‪Phone_3‬‬
‫‪host‬‬ ‫‪dynamic‬‬
‫‪type‬‬ ‫‪friend‬‬
‫‪context‬‬ ‫‪LocalSets‬‬
‫‪Permite‬‬ ‫‪0.0.0.0/0.0.0.0‬‬
‫‪deny‬‬ ‫‪0.0.0.0/0.0.0.0‬‬
‫‪direct media‬‬ ‫‪no‬‬
‫‪nat‬‬ ‫‪force_rport,comedia‬‬
‫‪qualify‬‬ ‫‪yes‬‬
‫جدول ‪7-11‬‬

‫اکنون ســعی کنید با اســتفاده از اطالعات فوق و به کمک یک “‪ ”IP Phone‬یا “‪ ”Soft Phone‬در ســرور‬
‫استریسک رجیستر شوید‪ .‬پس از آن‪ ،‬به محیط ‪ CLI‬استریسک وارد شوید و دستور زیر را اجرا کنید‪:‬‬
‫‪CLI>sip show peers‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اینجا هیچ نشــانی از یوزر تعریف شده در دیتابیس دیده نمیشود‪ .‬ازآنجاکه‬
‫این یوزرها بهصورت “‪ ”realtime‬به استریســک معرفی شــدهاند‪ ،‬نخســت باید در فایل ‪ ،sip.conf‬تنظیمات‬
‫مربوط به ‪ Real Time Caching‬را فعال کنید‪ .‬این تنظیمات بهصورت زیرند‪.‬‬
‫]‪[general‬‬
‫‪rtcachefriends=yes‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪348‬‬

‫پس از انجام تغییرات باال و ‪ reload‬کردن ماژول ‪ ،chan_sip.so‬اکنون میتوانید مجددا عملیات رجیستر در‬
‫استریســک را از ســر بگیرید‪ .‬پس از آن‪ ،‬به محیط کامندالین استریسک وارد شوید و دستور زیر را مجددا ً‬
‫اجرا کنید‪.‬‬
‫‪CLI>sip show peers‬‬
‫‪Name/username Host Dyn Forcerport Comedia ACL Port Status Description Realtime‬‬
‫‪Phone_3/Phone_3 192.168.141.1 D No No 60319 OK (115 ms) Cached RT‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اطالعات کاربر دیده میشــود‪ .‬در ســتون مربوط به ‪ ،Realtime‬کاربرانی از‬
‫نوع ‪ Cached RT‬دیده میشــوند‪ .‬با مشاهده جدول تعریفشده در دیتابیس‪ ،‬خواهید دید که سایر فیلدهای‬
‫جدول در زمان عملیات رجیسترشدن‪ ،‬مقداردهی شدهاند‪.‬‬
‫به کمک این روش‪ ،‬میتوان برای ســایر کاربران نیز از روش ‪ ARA_Dynamic‬اســتفاده کرد‪ .‬در ادامه‬
‫ســایر ماژولهایی را بررســی خواهیم کرد که قرار اســت با این روش به دیتابیس متصل شــوند‪ .‬برای مثال‬
‫میتوان از ‪ ARA_Dynamic‬برای ایجاد صف در استریسک‪ ،‬استفاده کرد‪.‬‬

‫ساختن صف در دیتابیس‬
‫ذخیره کردن صف در دیتابیس میتواند ازطریق هر دو روش ‪ ARA_Static‬و ‪ ARA_Dynamic‬انجام شود‪.‬‬
‫روش ‪ ARA_Static‬بسیار ساده است‪ .‬با داشتن ساختار جدولی بهصورت زیر‪ ،‬بهراحتی میتوان تنظیمات‬
‫را در دیتابیس ذخیره نمود‪ .‬برای مثال در فایل ‪ extconfig.conf‬داریم‪:‬‬
‫‪;extconfig.conf‬‬
‫]‪[settings‬‬
‫‪queues_ara.conf => odbc,asterisk,ast_config‬‬

‫اکنون اگر تصمیم بگیرید یک صف جدید بهنام ‪ ara_queue‬در جدول تعریف کنید‪ ،‬ابتدا باید تنظیمات‬
‫زیر را در انتهای فایل ‪ queues.conf‬اضافه کنید‪.‬‬
‫‪#include queues_ara.conf‬‬

‫جدول تعریف صف بهصورت زیر است )جدول ‪.(8-۱۱‬‬

‫‪id‬‬ ‫‪cat_metric‬‬ ‫‪var_metric‬‬ ‫‪filename‬‬ ‫‪category‬‬ ‫‪var_name‬‬ ‫‪var_val‬‬


‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪queues_ara.conf‬‬ ‫‪ara_queue‬‬ ‫‪musicclass‬‬ ‫‪default‬‬
‫‪2‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪queues_araconf‬‬ ‫‪ara_queue‬‬ ‫‪strategy‬‬ ‫‪rrmemory‬‬
‫‪3‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪queues_ara.conf‬‬ ‫‪ara_queue‬‬ ‫‪joinempty‬‬ ‫‪yes‬‬
‫‪4‬‬ ‫‪1‬‬ ‫‪4‬‬ ‫‪queues_ara.conf‬‬ ‫‪ara_queue‬‬ ‫‪leave‬‬ ‫‪no‬‬
‫‪whereempty‬‬
‫‪5‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪queues_ara.conf‬‬ ‫‪ara_queue‬‬ ‫‪ringinuse‬‬ ‫‪no‬‬
‫‪6‬‬ ‫‪1‬‬ ‫‪6‬‬ ‫‪queues_ara.conf‬‬ ‫‪ara_queue‬‬ ‫‪announce-‬‬ ‫‪30‬‬
‫‪frequency‬‬
349 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

id cat_metric var_metric filename category var_name var_val


7 1 7 queues_ara.conf ara_queue min-announce- 30
frequency
8 1 8 queues_ara.conf ara_queue periodic- 45
announce-
frequency
9 1 9 queues_ara.conf ara_queue random- no
periodic-
announce
10 1 10 queues_ara.conf ara_queue relative- yes
periodic-
announce
11 1 11 queues_ara.conf ara_queue announce- once
holdtime
12 1 12 queues_ara.conf ara_queue announce- limit
position
13 1 13 queues_ara.conf ara_queue announce- 10
position-limit
14 1 14 queues_ara.conf ara_queue announce- 30
round-seconds
8-11 ‫جدول‬

ara_queue ‫ صف جدید‬،‫اکنون چنانچه وارد محیط کامند الین استریسک شوید و دستور زیر را اجرا کنید‬
.‫را مشاهده میکنید‬
CLI> core reload
CLI> queue show
ara_queue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0,
C:0, A:0, SL:0.0% within 0s
No Members
No Callers

.‫ میتوان یک صف در دیتابیس ذخیره کرد‬،‫ به کمک ساختار جدولی زیر‬ARA_Dynamic ‫در روش‬
mysql>CREATE TABLE Queues (
`QueueID` mediumint(8) unsigned NOT NULL auto_increment,
`name` varchar(128) NOT NULL COMMENT 'Asterisk name for the queue',
`description` varchar(128) default NULL,
`maxlen` tinyint(4) default NULL,
`reportholdtime` varchar(3) default 'no',
`periodic_announce_frequency` varchar(4) default NULL,
`periodic_announce` varchar(128) default NULL,
`strategy` varchar(20) NOT NULL default 'rrmemory',
`joinempty` varchar(35) default 'no',
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 350

`leavewhenempty` varchar(35) default 'no',


`autopause` varchar(3) default 'no',
`announce_round_seconds` varchar(4) default NULL,
`retry` varchar(4) default NULL,
`wrapuptime` varchar(4) default NULL,
`announce_holdtime` varchar(3) default 'no',
`announce_frequency` varchar(4) default '0',
`timeout` varchar(4) default '60',
`context` varchar(128) NOT NULL,
`musicclass` varchar(128) default 'default',
`autofill` varchar(3) default 'yes',
`ringinuse` varchar(45) default 'no',
`musiconhold` varchar(128) default 'yes',
`monitor_type` varchar(128) default 'MixMonitor',
`monitor_format` varchar(128) default 'wav',
`servicelevel` varchar(4) default '60',
`queue_thankyou` varchar(128) default '',
`queue_youarenext` varchar(128) default '',
`queue_thereare` varchar(128) default '',
`queue_callswaiting` varchar(128) default '',
`queue_holdtime` varchar(128) default '',
`queue_minutes` varchar(128) default '',
`queue_seconds` varchar(128) default '',
`queue_lessthan` varchar(128) default '',
`queue_reporthold` varchar(128) default '',
`relative_periodic_announce` varchar(4) default 'yes',
PRIMARY KEY (`QueueID`),
UNIQUE KEY `name_UNIQUE` (`name`),
UNIQUE KEY `UniqueID_UNIQUE` (`QueueID`)
);

.‫ انجام دهید‬extconfig.conf ‫فایل‬ ‫سپس باید تنظیمات زیر را‬


#vim /etc/asterisk/extconfig.conf
[settings]
queues => odbc,asterisk,Queues

.‫ کنید‬reaload ‫ را مجدا‬app_queue.so ‫در این مرحله ماژول‬


CLI> module reload app_queue.so

.‫ در دیتابیس مراجعه میکند‬Queues ‫ به جدول‬،‫ استریسک برای پیکربندی تنظیمات صف‬،‫با این کار‬
‫ برای این کار فیلدهای‬.‫ در استریسک ایجاد کنیم‬ara2_queue ‫اکنون قصد داریم یک صف جدید بهنام‬
‫ وارد‬،‫ کنید‬reload ‫ ســپس بدون اینکه استریســک را‬.‫موردنیــاز جدول را مطابق با جدول قبلی مقدار دهید‬
.‫کامندالین استریسک شوید و دستور زیر را اجرا نمایید‬
CLI> queue show
351 ‫ارتباط بین استریسک و پایگاه داده‌ای‬

ara2_queue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime),
W:0, C:0, A:0, SL:0.0% within 60s
No Members
No Callers

.‫ نمایش داده میشود‬Queues ‫ صف جدید در جدول‬،‫همانطورکه مالحظه میکنید‬


‫ چون این صف بهصورت‬،‫ برای ایــن منظور‬.‫ اپراتورهایی را به صف اضافه کنید‬،‫بعــد از تعریــف صف‬
‫ ساختار این‬.‫ ایجاد کنید‬queue_member ‫ باید جدول دیگری بهنام‬،‫ تعریف شدهاســت‬ARA_Dynamic
:‫جدول بهصورت زیر است‬
mysql> CREATE TABLE queue_member (
uniqueid INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT,
membername varchar(40),
queue_name varchar(128),
interface varchar(128),
penalty INT(11),
paused INT(11),
UNIQUE KEY queue_interface (queue_name, interface)
);

.‫ نیز انجام دهید‬extconfig.conf ‫سپس تغییرات زیر را در فایل‬


#vim /etc/asterisk/extconfig.conf
[settings]
queues => odbc,asterisk,Queues
queue_members => odbc,asterisk,queue_member

.‫ کنید‬reload ً ‫اکنون باید ماژول صف را مجددا‬


CLI> module reload app_queue.so

:‫ اپراتورهایی را به صف اضافه کنید‬queue_member ‫ میتوانید با پرکردن جدول‬،‫با انجام این تغییرات‬


CLI> queue show
ara2_queue has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime),
W:0, C:0, A:0, SL:0.0% within 60s
Members:
Phone_3 (SIP/Phone_3 from SIP/Phone_3) (ringinuse disabled) (realtime) (Not in use) has
taken no calls yet
No Callers

‫ برای‬.‫ میخواهیم گزارشات مربوط به صفها را در دیتابیس ذخیره کنیم‬،‫بهعنوان آخرین مثال از این بخش‬
:‫این منظور ابتدا باید یک جدول بهصورت زیر ایجاد کنید‬
mysql> CREATE TABLE queue_log (
id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
time char(26) default NULL,
callid varchar(32) NOT NULL default '',
queuename varchar(32) NOT NULL default '',
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪352‬‬

‫‪agent varchar(32) NOT NULL default '',‬‬


‫‪event varchar(32) NOT NULL default '',‬‬
‫‪data1 varchar(100) NOT NULL default '',‬‬
‫‪data2 varchar(100) NOT NULL default '',‬‬
‫‪data3 varchar(100) NOT NULL default '',‬‬
‫‪data4 varchar(100) NOT NULL default '',‬‬
‫‪data5 varchar(100) NOT NULL default '',‬‬
‫)`‪PRIMARY KEY (`id‬‬
‫;)‬

‫سپس باید تغییرات زیر را در فایل ‪ extconfig.conf‬وارد کنید‪:‬‬


‫‪#vim /etc/asterisk/extconfig.conf‬‬
‫]‪[settings‬‬
‫‪queues => odbc,asterisk,Queues‬‬
‫‪queue_members => odbc,asterisk,queue_member‬‬
‫‪queue_log => odbc,asterisk,queue_log‬‬

‫پس از آن‪ ،‬برنامه زیر را در استریسک بنویسید‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[queues‬‬
‫)(‪exten => 7000,1,Answer‬‬
‫)‪same => n,Verbose(2,${CALLERID(all)} entering the support queue‬‬
‫)‪same => n,Queue(ara2_queue‬‬
‫)(‪same => n,Hangup‬‬

‫‪ queue_log‬ثبت خواهد شد‪.‬‬ ‫اکنون چنانچه تماس جدیدی ایجاد شود‪ ،‬گزارشات مربوطه در جدول‬

‫نتیجه‌گیری‬
‫در ایــن بخــش‪ ،‬چندین حــوزه مختلف و کاربردی در استریســک مطرح شــد‪ .‬ابتدا به معرفــی پایگاههای‬
‫دادهای و چگونگی اتصال به آنها پرداختیم‪ .‬ســپس اجرای دســتورات ‪ SQL‬در برنامهنویسی استریسک را‬
‫بررســی نمودیم‪ .‬در نهایت درباره ‪ Asterisk Realtime Articheture‬و روشهای ‪ ARA_Static‬و _‪ARA‬‬
‫‪ Dynamic‬توضیحاتــی دادیم و برای هر کــدام از مفاهیم فوق‪ ،‬مثالهایی ارائه نمودیم‪ .‬مطمئنا اطالعات این‬
‫فصل میتواند بسیار کاربردی باشد و شما را در تولید محصوالت مرتبط با این زمینه تخصصی‪ ،‬یاری رساند‪.‬‬
‫فصل دوازدهم‬

‫فکس‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪354‬‬

‫فکس چیست‬
‫فکس دســتگاهی اســت که میتواند از یک صفحه کاغذ‪ ،‬یک تصویر بســازد و به کمک خط تلفن ارسال‬
‫نماید‪ .‬دســتگاه فکس در مبدأ‪ ،‬تصویر را به یک ســری کدهای قابل انتقال روی خط تلفن‪ ،‬تبدیل میکند و‬
‫این کدها در مقصد بهوسیله دستگاه فکس مخاطب‪ ،‬مجددا به تصویر تبدیل و روی کاغذ چاپ میشود‪.‬‬
‫فکس در ســال ‪۱۲۲۲‬هجری شمسی معادل ســال ‪ ۱84۳‬میالدی بهوســیله یک مخترع اسکاتلندي بهنام‬
‫الکساندربین ســـاخته شـــد‪ .‬دستگاههای ابتدایی تصویر را به خطوط عرضی کوچک تقسیم میکردند و هر‬
‫نقطه را با رنگهای سیاه و سفید نشان میدادند‪ ،‬سپس این نقاط بهوسیله تلگراف بهصورت خط و نقطه )کد‬
‫مورس( منتقل میشــد‪ .‬تا ســال ‪ ۱۳۳۹‬هجری شمسی برابر با ‪ ۱۹۶۰‬میالدی‪ ،‬هر شرکت به روش خاص خود‬
‫ارســال و دریافت فکس را انجام میداد تا اینکه در همین ســال قانون یکسانسازی به روش آمریکایی آغاز‬
‫و تجاری گردید‪.‬‬

‫بررسی نقاط ضعف در خصوص ماشین‌های فکس (‪)Fax Machine‬‬


‫از جمله چالشها و مشــکالت فکسهای ســنتی‪ ،‬وابســتگی آنها به کاغذ‪ ،‬جوهر و ریبون است‪ .‬در این نوع‬
‫سیستمها‪ ،‬عالوه بر باال بودن هزینههای خرید دستگاههای فکس به تعداد کارمندان‪ ،‬هزینههای جاری فکس‬
‫شــامل کاغــذ‪ ،‬جوهر‪ ،‬برق‪ ،‬هزینههای تعمیر و نگهداری و مهمتر از همــه آلودگی صوتی را به همراه دارد‪.‬‬
‫‪355‬‬ ‫فاکس‬

‫همچنین ارتباط با یک نیروی انسانی برای دریافت و یا ارسال فکس ضروری است‪.‬‬
‫یکی دیگر از چالشها و مشکالت فکسهای سنتی‪ ،‬وابستگی آنها به موقعیت مکانی برای ارسال فکس‬
‫و مشاهده فکس است‪ .‬به عبارت دیگر برای ارسال فکس باید در اداره یا سازمان خود باشید تا بتوانید فکس‬
‫را ارسال یا دریافت کنید‪.‬‬

‫‪1‬‬
‫فکس‌های اینترنتی‬
‫فکسهــای اینترنتی که از آنها با اســمهایی چون ‪ MyFax، eFax‬و ‪ onlineFax‬نام برده میشــود‪ ،‬امروزه‬
‫رشــد چشمگیری داشتهاند‪ .‬این نوع فکسها اغلب با عناوینی چون ‪ Web-Fax، Email-Fax‬و یا ‪VoIP-Fax‬‬
‫معرفی میشــوند‪ ،‬بهطوریکه هر یک از این عناوین‪ ،‬ســهولت اســتفاده از فکس را در شبکههای اینترنتی و‬
‫نســل جدید مخابراتی ارائه میدهند‪ .‬برای مثال »‪ «Fax-To-Mail‬یک عنوان جالب برای استفاده از این نوع‬
‫سرویسهاست تا قادر باشید فکسهای دریافتی خود را بهراحتی از طریق ایمیل ارسال و دریافت نمایید‪.‬‬
‫از جمله مزایای استفاده از فکسهای اینترنتی میتوان به موارد زیر اشاره نمود‪:‬‬
‫‪ -1‬به نرم‌افزارها و سخت‌افزارهای جدید نیاز ندارند؛‬
‫‪ -2‬به خطوط تلفنی برای ارسال فکس نیاز ندارند؛‬
‫‪ -3‬از قابلیت اتصال به سایر سرویس‌ها برخوردارند؛‬
‫‪ -4‬توانایی ارسال دریافت هم‌زمان چندین فکس (به‌صورت انبوه) را دارند؛‬
‫‪ -5‬هزینه‌های ارسالی فکس در تعداد باال زیاد نیست؛‬
‫‪ -6‬ارسال و دریافت فکس از طریق گوشی‌های هوشمند امکان‌پذیر است‪.‬‬

‫بررسی انواع روش‌های ارسال و دریافت فکس‬


‫امروزه برای ارسال و دریافت فکس روشهای زیادی وجود دارد‪ .‬این روشها عبارتند از‪:‬‬
‫‪ )1‬اســتفاده از روش فکس به فکس‪ :‬در این روش از دستگاه‌های ماشین فکس استفاده می‌کنیم‪ .‬شکل ‪1-12‬‬
‫این روش را نشان می‌دهد‪.‬‬

‫شکل ‪1-12‬‬

‫‪ ‌)2‬استفاده از روش کامپیوتر به فکس‪ :‬در این روش‪ ،‬یک طرف ارتباط یک دستگاه کامپیوتر است که مجهز به‬

‫‪1- Internet Fax‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪356‬‬

‫کارت تلفن با پورت ‪ RJ11‬و یک نرم افزار ارسال و دریافت فکس است و در طرف دیگر یک دستگاه ماشین‬
‫فکس داریم‪ .‬شکل‌ ‪ 2-12‬و ‪ 3-12‬ارسال فکس به این روش را نمایش می‌دهد‪.‬‬

‫شکل ‪2-12‬‬
‫یا‬

‫شکل ‪3-12‬‬

‫‪ )3‬اســتفاده از فکس گیت‌وی‪ :‬در این روش یک ‪ Fax-Gateway‬فکس‌های دریافتی را برای یک ســرویس‬
‫معین (مثال ســرویس ایمیل) ارســال می‌نماید‪ .‬در این روش می‌توان از ســرویس‌های دیگر (از جمله ایمیل) ‬
‫اطالعات گرفت و به‌صورت فکس ارسال کرد‪.‬‬

‫شکل ‪4-12‬‬
‫یا‬

‫شکل ‪5-12‬‬
‫‪ )4‬اســتفاده از ‪ : VoIP‬یکی دیگر از قابلیت‌های اســتفاده از شــبکه های ویپ امکان ارسال و دریافت فکس‬
‫اســت‪ .‬در سیســتم تلفنی استریســک این قابلیت وجود دارد که بتوان به ســهولت به ارسال یا دریافت فکس‌ ‬
‫پرداخت‪.‬‬

‫پروتکل ‪T.38‬‬

‫این پروتکل اســتاندارد ارسال و دریافت فکس در شــبکههای کامپیوتری است‪ .‬ازآنجاکه دادهها در فکس‪،‬‬
‫بهصورت آنالوگ منتقل میشــود‪ ،‬پروتکلهای رایج در شــبکهی دیجیتــال‪ ،‬اطالعات فکس را به کمک‬
‫‪357‬‬ ‫فاکس‬

‫ایــن پروتکل‪ ،‬از آنالوگ به دیجیتال تبدیل میکنند ایــن پروتکل‪ ،‬در مبدأ دادههای آنالوگ را به دادههای‬
‫دیجیتال تبدیل و به شــبکهی ‪ IP‬ارسال میکند؛ ســپس در مقصد نیز به کمک همین پروتکل‪ ،‬این عملیات‬
‫بهصورت وارونه )یعنی تبدیل دادههای دیجیتالی به دادههای آنالوگ( صورت میگیرد‪.‬‬
‫این اســتاندارد در سال ‪ ۱۹۹8‬تحت عنوان اســتاندارد ‪ RFC3362‬و زیر نظر سازمان ‪ ITU‬منتشر گردید‪.‬‬
‫یکی از تفاوتهای اصلی این پروتکل با پروتکل ‪ T.37‬در این اســت که این پروتکل اطالعات را بهصورت‬
‫‪ RealTime‬ارسال میکند‪ ،‬در صورتی که پروتکل ‪ ، T.37‬دادهها را نخست ذخیره و سپس ارسال میکند‪.‬‬
‫یکی از قابلیتهای مهم پروتکل ‪ ،T.38‬مکانیســم ‪ Multi-Level-Redundancy‬اســت‪ .‬با توجه به اینکه‬
‫در شبکه ‪ Packet Lost‬و یا ‪Jitter‬‬ ‫ارســال اطالعات در شــبکهی ‪ IP‬بهصورت ‪ UDP‬است‪ ،‬در صورتی که‬
‫رخ دهد‪ ،‬احتمال از بین رفتن دادهها وجود دارد‪ .‬این استاندارد به گونهای تعریف شده که به ازای هر بستهی‬
‫اطالعاتی‪ ،‬تعدادی رونوشــت تهیه میکند تا در صورتی که یکی از بستهها به مقصد نرسید‪ ،‬از رونوشت آن‬
‫استفاده شود‪.‬‬

‫ارسال و دریافت فکس با استریسک‬


‫در استریسک میتوان هم ارسال و هم دریافت فکس داشت‪ ،‬البته نه به این معنی که خود استریسک فکسها‬
‫را ارســال یا دریافت کند‪ ،‬بلکه به این مفهوم که استریســک با اســتفاده از پروتکلها و ماژولهای ارسال و‬
‫دریافــت فکس ایــن عملیات را انجام میدهد‪ .‬ماژول ‪ SpanDSP‬یکی از مهمترین ماژولها در استریســک‬
‫است که به همین منظور بهکار گرفته میشود‪.‬‬

‫ماژول ‪SpanDSP‬‬
‫ماژول ‪ ،۱ DSP‬کتابخانهای از پردازش سیگنالهای دیجیتالی است که بهوسیله آن میتوان تصاویر یا متنهایی‬
‫را به ســیگنال )صدا( تبدیل کــرد و پس از انتقال آنها‪ ،‬مجددا ً این ســیگنالها )صداها( را به متن یا تصویر‬
‫برگرداند‪ .‬از این کتابخانه استریسک میتوان برای ارسال و دریافت فکس استفاده کرد‪.‬‬
‫الزم به ذکر است که در سیستم تلفنی استریسک‪ ،‬این ماژول تحت عنوان ‪ res_fax_spandsp.so‬وجود‬
‫دارد‪ ،‬ولی استفاده از آن به الیسنس خاصی نیاز دارد‪ .‬اگر در محیط کامندالین استریسک دستور زیر را اجرا‬
‫کنید‪ ،‬متوجه فعالیت این ماژولها خواهید شد‪.‬‬
‫‪CLI> module show like res_fax‬‬
‫‪Module Description Use Count Status Support Level‬‬
‫‪res_fax.so Generic FAX Applications 1 Running core‬‬
‫‪res_fax_spandsp.so Spandsp G.711 and T.38 FAX Technologies 0 Running extended‬‬

‫‪1- Digital Signal Processing‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪358‬‬

‫‪2 modules loaded‬‬


‫>‪CLI‬‬

‫• ماژول ‪ :res_fax_spandsp‬به‌وســیله این ماژول‪ ،‬می‌توان از کتابخانه‌ی پردازش سیگنال‌های دیجیتالی در‬
‫استریسک استفاده کرد تا بتوان بوق فکس را شبیه‌سازی نمود‪.‬‬
‫• ماژول ‪ :res_fax‬از این ماژول برای ارسال و دریافت فکس در برنامه‌نویسی استریسک استفاده می‌شود‪ .‬با‬
‫فعال بودن این ماژول‪ ،‬دستورات زیر در برنامه‌نویسی استریسک قابل استفاده خواهند بود‪.‬‬
‫‪CLI> core show application SendFAX‬‬
‫]‪[Syntax‬‬
‫)]‪SendFAX([filename2[&...]][,options‬‬

‫‪ubuntu14*CLI> core show application ReceiveFAX‬‬


‫]‪[Syntax‬‬
‫)]‪ReceiveFAX(filename[,options‬‬

‫در ادامه‪ ،‬مراحل نصب این ماژول در توزیعهای لینوکس توضیح داده میشوند‪.‬‬

‫نصب ماژول ‪ Spandsp‬در توزیع‌های لینوکس‬


‫برای نصب ماژول ‪ Spandsp‬در توزیعهای مختلف‪ ،‬بهصورت زیر عمل کنید‪ .‬ابتدا نیازمندیهای این ماژول‬
‫را نصب کنید‪.‬‬
‫‪;RHEL‬‬
‫‪#yum install -y libtiff-devel‬‬

‫‪;ubuntu‬‬
‫‪#apt-get install libtiff-dev‬‬

‫سپس ماژول ‪ Spandsp‬را مطابق زیر دانلود و نصب کنید‪:‬‬


‫‪#cd /usr/src/‬‬
‫‪#wget https://www.soft-switch.org/downloads/spandsp/spandsp-0.0.6pre21.tgz‬‬
‫‪#tar –zxvf spandsp-0.0.6.tar.gz‬‬
‫‪#cd spandsp-0.0.6‬‬
‫‪#./configure‬‬
‫‪#make‬‬
‫‪#make install‬‬

‫بعــد از نصــب ماژول ‪ ،spandsp‬برای اســتفاده از کتابخانه های آن به‌وســیله ســایر ســرویس‌ها (از جمله‬
‫استریسک) در لینوکس‪ ،‬باید مسیر فایل‌های کتابخانه ای آن را به مسیر فایل‌های کتابخانه ای لینوکس معرفی‬
‫کنید‪.‬‬
‫‪#echo /usr/local/lib >> /etc/ld.so.conf.d/usrlocallib.conf‬‬

‫پس از آن با دستور زیر مسیر فایل‌ها را آپدیت کنید‪:‬‬


‫‪#sudo ldconfig‬‬
‫‪359‬‬ ‫فاکس‬

‫اکنون استریســک را مجــددا ً کامپایل نمایید تا اســتفاده از توابع کتابخانهای مــاژول ‪ res_fax_spandsp‬را‬
‫بهدســت آورید‪ .‬برای این منظور به مســیر نصب فایلهای استریســک بروید و مراحل کامپایل برنامه را طی‬
‫کنید‪.‬‬
‫‪;source_asterick‬‬
‫‪#./configure‬‬
‫‪#make menuselect‬‬

‫همانطورکــه مالحظــه میکنیــد در قســمت ‪ ،Resource Modules‬مــاژول فــوق بایــد بــه صــورت‬
‫‪ [*] res_fax_spandsp‬باشد‪.‬‬

‫شکل ‪6-12‬‬

‫اکنون استریسک را دوباره نصب کنید‪:‬‬


‫‪#make‬‬
‫‪#make install‬‬

‫در مرحله بعد استریسک را ‪ restart‬کنید‪.‬‬


‫‪#/etc/init.d/asterisk restart‬‬

‫چنانچه پس از نصب استریســک به محیط کامند الین استریسک وارد شوید‪ ،‬میتوانید از نصب ماژول فوق‬
‫اطمینان حاصل کنید‪:‬‬
‫‪CLI> module show like res_fax_spandsp.so‬‬
‫‪Module‬‬ ‫‪Description Use Count Status Support Level‬‬
‫‪res_fax_spandsp.so‬‬ ‫‪Spandsp‬‬ ‫‪G.711 and T.38 FAX Technologies 0‬‬
‫‪Running‬‬ ‫‪extended‬‬
‫‪1 modules loaded‬‬
‫>‪CLI‬‬

‫هم اکنون در استریســک میتوانید از دستورات ‪ SendFAX‬و ‪ ReceiveFAX‬برای ارسال و دریافت فکس‬
‫استفاده کنید‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪360‬‬

‫دریافت فکس در استریسک‬


‫فکسهای دریافتی معموالً با فرمت ‪ ۱ TIFF‬دریافت میشــوند‪ .‬ازآنجاکه این فرمت چندان شــناخته شــده‬
‫نیست‪ ،‬بهتر است آن را به فرمتهای شناخته شدهتر مانند ‪ JPEG ، GIF‬و یا حتی‪ PDF‬تبدیل کنید‪.‬‬
‫برای این منظور باید بستههای زیر را نصب کنید‪:‬‬
‫‪;RHEL:‬‬
‫‪#yum install libtiff‬‬
‫‪;Ubuntu‬‬
‫‪#apt-get install libtiff-tools‬‬

‫پس از نصب بستهها‪ ،‬میتوانید با فراخوانی دستور زیر‪ ،‬فایلها را از فرمت ‪ TIFF‬به فرمت ‪ pdf‬تبدیل کنید‪.‬‬
‫‪#tiff2pdf filename.tiff > filename.pdf‬‬

‫برای دریافت فکس می توان از روش های زیر استفاده کرد‪:‬‬


‫‪ -۱‬استفاده از دستور ‪ ReceiveFAX‬در استریسک؛‬
‫‪ -۲‬استفاده از مودمهای مجازی )‪ (IAXmodem‬برای دریافت فکس ؛‬
‫‪ -۳‬استفاده از دستگاههای ماشین فکس در شبکه ویپ )‪. (Fax Pass-Through‬‬
‫در ادامه این دستورات شرح داده میشوند‪.‬‬

‫استفاده از دستور ‪ ReceiveFAX‬در استریسک‬


‫میتوان فکسهای ورودی به سیســتم تلفنی استریسک را بهوسیله دستور ‪ ReceiveFAX‬دریافت کرد‪ .‬برای‬
‫آشنا شدن با این دستور‪ ،‬عبارت زیر را در محیط کامندالین استریسک وارد نمایید‪.‬‬
‫‪CLI> core show application ReceiveFAX‬‬
‫]‪[Syntax‬‬
‫)]‪ReceiveFAX(filename[,options‬‬

‫مثال( فرض کنید در یک سیستم تلفنی‪ ،‬داخلی ‪ ۹‬را برای دریافت فکس تعیین کردهاید‪ .‬اکنون اگر فردی با‬
‫شما تماس بگیرد و کلید شماره ‪ ۹‬را فشار دهد‪ ،‬سیستم شما آماده دریافت فکس میشود‪ .‬مثال زیر را ببینید‪:‬‬
‫]‪[form-pstn‬‬
‫)(‪exten => _X. ,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,BackGround(Welcome‬‬
‫)‪same => n,waitExten(5‬‬
‫)(‪exten => 1,1,NoOp‬‬
‫)(‪exten => 2,1,NoOp‬‬
‫)‪exten => 9,1,Goto(fax-incoming,s,1‬‬
‫)‪exten => i,1,Goto(operator,1‬‬

‫)‪1- Tagged Image File Format (TIFF‬‬


‫‪361‬‬ ‫فاکس‬

‫]‪[fax-incoming‬‬
‫)‪exten => s,1,Verbose(3,Incoming fax‬‬
‫)‪same => n,Set(FAXDEST=/tmp‬‬
‫)})‪same => n,Set(TEMPFAX=${STRFTIME(,,%C%y%m%d%H%M‬‬
‫)‪same => n,ReceiveFax(${FAXDEST}/${ TEMPFAX }.tif‬‬
‫)}‪same => n,Verbose(3,- Fax receipt completed with status: ${FAXSTATUS‬‬

‫همانطورکه مالحظه میکنید فکس بهوســیله دستور ‪ ReceiveFax‬در مسیر تعیینشده‪ ،‬ذخیره میشود‪ .‬بعد‬
‫از دریافت فکس‪ ،‬میتوان بهوسیله متغیر ‪ FAXSTATUS‬وضعیت آن را مشاهده کرد‪ .‬توجه داشته باشید که‬
‫تا وقتی فکس دریافت نشود )یا خطایی در دریافت فکس مشاهده نشود(‪ ،‬کنترل اجرای برنامه به خط بعدی‬
‫نخواهد رفت‪.‬‬
‫میتــوان بالفاصله بعــد از دریافت موفقیتآمیز فکــس‪ ،‬آن را به فرمت ‪ pdf‬تبدیل کــرد‪ .‬این عملیات‬
‫بهوسیله دستور ‪ System‬در استریسک اجرا میشود‪ .‬به مثال زیر توجه کنید‪:‬‬
‫)‪same => n,System (tiff2pdf ${FAXDEST}/${ TEMPFAX }.tiff > ${FAXDEST}/${ TEMPFAX }.pdf‬‬

‫استفاده از مودم‌های مجازی(‪ )IAXmodem‬برای دریافت فکس‬


‫‪ IAXModem‬یک نرمافزار نگارششده به زبان ‪ C‬است که ازطریق ‪ IAXchannel‬به سیستم تلفنی استریسک‬
‫متصل میشود و با استفاده از ‪ DSPlibrary‬فکسها را دریافت میکند‪.‬‬
‫دریافت یک فکس از این روش بهصورت شکل ‪ 7-۱۲‬است‪:‬‬

‫شکل ‪7-12‬‬

‫نکتــه مهم‪ :‬نرم افزار ‪ IAXModem‬بهتنهایی نمیتواند فکس ارســال یا دریافت کنــد‪ .‬برای این کار باید از‬
‫فکس ســرور )در اینجا ‪ (HylaFAX‬اســتفاده کنید‪ .‬به عبارت دیگر‪ ،‬با استفاده از مودمهای مجازی و فکس‬
‫سرور‪ ،‬میتوانید اقدام به ارسال و دریافت فکس کنید‪.‬‬

‫نصب مودم‌های مجازی در لینوکس‬


‫برای نصب این مودمها باید نرم افزار ‪ IAXModem‬را مطابق زیر نصب کنید‪:‬‬
‫ابتدا از مسیر زیر ‪ IAXModem‬را دانلود کنید‪.‬‬
‫‪https://sourceforge.net/projects/iaxmodem/files‬‬

‫سپس دستورات زیر را اجرا کنید‪:‬‬


‫‪#tar -zxvf iaxmodem-1.2.0.tar.gz‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪362‬‬

‫‪#cd iaxmodem-1.2.0/lib/spandsp/‬‬
‫‪#./configure‬‬
‫‪#make‬‬
‫‪#make install‬‬
‫‪#cd ..‬‬
‫‪#cd libiax2/‬‬
‫‪#./configure‬‬
‫‪#make‬‬
‫‪#make install‬‬
‫‪#cd ..‬‬
‫‪#./configure‬‬
‫‪#make‬‬

‫بعد از نصب ‪ ،IAXModem‬باید بتوانید آن را بهصورت سرویس دربیاورید‪ .‬دستورات زیر را انجام دهید‪:‬‬
‫‪#cp iaxmodem /usr/sbin/‬‬
‫‪#cp iaxmodem.init.debian /etc/init.d/iaxmodem‬‬
‫‪#chmod 755 /etc/init.d/iaxmodem‬‬

‫سپس فایل ‪ iaxmodem‬را از مسیر زیر باز و تغییرات الزم را وارد کنید‪:‬‬
‫‪#vim /etc/init.d/iaxmodem‬‬
‫‪DAEMON=/usr/sbin/iaxmodem‬‬

‫سپس باید به مقدار مورد نیاز‪ ،‬مودم مجازی ایجاد کنیم و آنها را پیکربندی نماییم‪:‬‬
‫عالوه بر این‪ ،‬برای ثبت گزارشــات و الگهای مودم مجازی )‪ ،(IAXModem‬باید یک پوشهی جدید‬
‫در مسیر الگهای سیستم بهصورت زیر ایجاد کنید‪:‬‬
‫‪# mkdir /var/log/iaxmodem‬‬

‫پیکربندی مودم‌های مجازی در لینوکس‬


‫در مســیر فایلهای نصب شده‪ ،‬فایل نمونهای با اســم ‪ iaxmodem-cfg.ttyIAX‬وجود دارد‪ .‬برای پیکربندی‬
‫مودمهای مجازی کافی اســت از این فایل‪ ،‬یک نســخه کپی تهیه کنید و در مســیر ‪ /etc/iaxmodem‬ذخیره‬
‫نمایید‪ .‬اکنون دو مودم مجازی ایجاد خواهیم کرد‪.‬‬
‫‪# mkdir /etc/iaxmodem‬‬
‫‪#cp iaxmodem-cfg.ttyIAX /etc/iaxmodem/axmodem-cfg.ttyIAXModem1‬‬
‫‪#cp iaxmodem-cfg.ttyIAX /etc/iaxmodem/iaxmodem-cfg.ttyIAXModem2‬‬

‫بهصورت زیر است‪:‬‬ ‫محتویات هر فایل‬


‫‪# vim /etc/iaxmodem/iaxmodem-cfg.ttyIAXModem1‬‬
‫‪device‬‬ ‫‪/dev/ttyIAX‬‬
‫‪owner‬‬ ‫‪uucp:uucp‬‬
‫‪mode‬‬ ‫‪660‬‬
‫‪port‬‬ ‫‪4570‬‬
‫‪refresh‬‬ ‫‪300‬‬
‫‪server‬‬ ‫‪127.0.0.1‬‬
‫‪363‬‬ ‫فاکس‬

‫‪peername‬‬ ‫‪iaxmodem‬‬
‫‪secret‬‬ ‫‪password‬‬
‫‪cidname‬‬ ‫‪John Doe‬‬
‫‪cidnumber‬‬ ‫‪8005551212‬‬
‫‪codec‬‬ ‫‪slinear‬‬

‫مهمترین پارامترهایی که باید تنظیم شوند‪ ،‬از قرار زیرند‪:‬‬


‫‪ :device‬پورت سریال در نظر گرفتهشده برای این مودم مجازی را مشخص میکند‪.‬‬
‫‪ :port‬شماره پورت جهت رجیستر شدن در استریسک را مشخص میکند‪.‬‬
‫‪ :server‬آدرس سرور استریسک را تعیین میکند‪ .‬در اینجا می تواند سرور استریسک مستقل از فکس سرور‬
‫باشد‬
‫‪ :peername‬نام کاربری )از نوع پروتکل ‪ (IAX2‬است که باید وارد شود‪.‬‬
‫‪ :secret‬رمز عبور برای کاربر )از نوع پروتکل ‪ (IAX2‬است که باید وارد شود‪.‬‬
‫‪ :cidname‬با این پارامتر میتوانید یک نام دلخواه برای مودم مجازی انتخاب کنید‪.‬‬
‫‪ :cidnumber‬با این پارامتر میتوانید یک شماره برای مودم در نظر بگیرید‪ .‬این شماره میتواند با ‪peername‬‬
‫یکسان باشد‪.‬‬
‫قبــل از تنظیــم مودم مجازی‪ ،‬ابتدا باید دو کاربر جدید از نوع ‪ IAX2‬در استریســک ایجادکنید‪ .‬به این‬
‫منظور فایل ‪ iax.conf‬را باز و کاربرها را بهصورت زیر تعریف کنید‪.‬‬
‫‪#vim /etc/asterisk/iax.conf‬‬
‫]‪[v-fax1‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪secret=123123‬‬
‫‪transfer=no‬‬
‫‪context=incoming-fax‬‬
‫‪host=dynamic‬‬
‫‪type=friend‬‬
‫‪port=4569‬‬
‫‪qualify=yes‬‬
‫‪disallow=all‬‬
‫‪allow=ulaw,alaw‬‬

‫]‪[v-fax2‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=0.0.0.0/0.0.0.0‬‬
‫‪secret=123123‬‬
‫‪transfer=no‬‬
‫‪context=incoming-fax‬‬
‫‪host=dynamic‬‬
‫‪type=friend‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 364

port=4569
qualify=yes
disallow=all
allow=ulaw,alaw

.‫[ را در استریسک ایجاد کنیم‬incoming-fax] ‫سپس باید کانتکست‬


;extensions.conf
[incoming-fax]
exten => 8000,1,NoOp(This is v-fax1)
same => n,Dial(IAX2/v-fax1)

exten => 8001,1,NoOp(This is v-fax2)


same => n,Dial(IAX2/v-fax2)

‫ آماده دریافت‬v-fax۱ ‫ فکس مجازی‬،‫ گرفته شــود‬8۰۰۰ ‫در تعریف باال مشــخص کردیم که اگر شــماره‬
.‫ آماده دریافت فکس خواهد بود‬v-fax۲ ‫ فکس مجازی‬،‫ گرفته شود‬8۰۰۱ ‫فکس خواهد بود و اگر شماره‬
:‫ نمایید‬reload ‫ وارد محیط کامندالین استریسک شوید و ماژول فوق را‬،‫پس از تعریف کاربران جدید‬
CLI> iax2 reload
CLI> iax2 show peers
Name/Username Host Mask Port Status Description
v-fax1 (null) (D) (null) (null) UNKNOWN
v-fax2 (null) (D) (null) (null) UNKNOWN
2 iax2 peers [0 online, 2 offline, 0 unmonitored]
CLI>

.‫به این ترتیب دو کاربر جدید در استریسک تعریف میشوند‬


:‫اکنون باید تنظیمات فایلهای مربوط به مودمهای مجازی را مطابق زیر انجام دهید‬
# vim /etc/iaxmodem/iaxmodem-cfg.ttyIAXModem1
device /dev/ttyIAX1
owner uucp:uucp
mode 660
port 4570
refresh 300
server 127.0.0.1
peername v-fax1
secret 123123
cidname v-fax1
cidnumber 8005551212
codec slinear

:‫این تنظیمات برای مودم مجازی دوم بهصورت زیر خواهد بود‬
# vim /etc/iaxmodem/iaxmodem-cfg.ttyIAXModem2
device /dev/ttyIAX2
owner uucp:uucp
mode 660
port 4570
refresh 300
‫‪365‬‬ ‫فاکس‬

‫‪server‬‬ ‫‪127.0.0.1‬‬
‫‪peername‬‬ ‫‪v-fax2‬‬
‫‪secret‬‬ ‫‪123123‬‬
‫‪cidname‬‬ ‫‪v-fax2‬‬
‫‪cidnumber‬‬ ‫‪8005551212‬‬
‫‪codec‬‬ ‫‪slinear‬‬

‫پس از انجام تغییرات الزم در هر دو فایل‪ ،‬سرویس ‪ IAXModem‬را مجددا ً راه اندازی نمایید‪.‬‬
‫‪# /etc/init.d/iaxmodem stop‬‬
‫‪# /etc/init.d/iaxmodem start‬‬

‫با اجرای دستور باال‪ ،‬باید هر دو مودم مجازی ‪ v-fax۱‬و ‪ v-fax۲‬در استریسک رجیستر شوند‪.‬‬
‫اگر هیچیک از مودمها در استریسک رجیستر نبودند‪ ،‬تنظیمات زیر را در فایل ‪ iax.conf‬انجام دهید‪:‬‬
‫‪; iax.conf‬‬
‫‪calltokenoptional=127.0.0.1/255.255.255.255‬‬
‫‪requirecalltoken=no‬‬

‫در اینجا باید آدرس ســرور استریســک را وارد نماییم‪ .‬شــما مــی توانید این آدرس را بــه صورت عمومی‬
‫‪ 0.0.0.0/0.0.0.0‬در نظر بگیرید‪.‬‬
‫ســپس سرویس استریسک و بعد ســرویس مودم‌های مجازی را مجددا ً راه‌اندازی نمایید‪ .‬در نهایت وضعیت‬
‫مودم‌های مجازی در استریسک به‌صورت زیر خواهد بود‪:‬‬
‫‪CLI> iax2 show peers‬‬
‫‪Name/Username Host‬‬ ‫‪Mask Port Status Description‬‬
‫‪v-fax1‬‬ ‫)‪127.0.0.1 (D) (null) 4570 OK (1 ms‬‬
‫‪v-fax2‬‬ ‫)‪127.0.0.1 (D) (null) 57121 OK (1 ms‬‬
‫]‪2 iax2 peers [2 online, 0 offline, 0 unmonitored‬‬
‫>‪CLI‬‬

‫تا اینجا مودمهای مجازی نصب و فعال شدند؛ اکنون برای دریافت و ارسال فکس باید فکس سرور را نصب‬
‫نمایید‪.‬‬

‫نصب سرویس فکس در لینوکس‬


‫اینجا ما از ســرویس ‪ HylaFax‬در لینوکس اســتفاده میکنیم‪ .‬برای نصب ‪ HylaFax‬ابتدا باید آن را دانلود‬
‫کنید‪ .‬برای دانلود‪ ،‬دستورات زیر را بر اساس نسخهی لینوکس اجرا کنید‪.‬‬
‫‪;RHEL‬‬
‫‪#yum -y install ghostscript sharutils‬‬
‫‪#wget http://yum.trixbox.org/centos/5/RPMS/hylafax-4.4.4-1rhel5.i386.rpm‬‬
‫‪#rpm -Uvh /var/ftp/hylafax-4.4.4-1rhel5.i386.rpm‬‬
‫‪;ubuntu‬‬
‫‪#apt-get install Hylafax-server Hylafax-client‬‬

‫سپس دستور زیر را اجرا کنید‪:‬‬


‫‪#faxsetup‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪366‬‬

‫با اجرای این دستور‪ ،‬هنگام نصب سؤاالتی از شما پرسیده میشود‪ .‬به سؤاالت عموما پاسخ پیشفرض دهید‪.‬‬
‫یکی از این سؤاالت بهصورت زیر است‪:‬‬
‫?]‪Do you want to run faxaddmodem to configure another modem [yes‬‬

‫ازآنجاکه دو مودم مجازی وجود دارد‪ ،‬با تأیید سؤال باال‪ ،‬به قسمت تنظیمات فکسهای مجازی وارد شوید‪.‬‬
‫ابتدا این سؤال از شما پرسیده میشود‪:‬‬
‫?]‪Serial port that modem is connected to [ttyS0‬‬

‫ســؤال باال از شما درخواســت میکند که سریال پورت درنظرگرفتهشــده برای مودم مجازی را وارد کنید‪.‬‬
‫ازآنجاکه در تنظیمات فایلهای مودم مجازی‪ ،‬ســریال پورت ها را ‪ ttyIAX1‬و ‪ ttyIAX2‬درنظر گرفتهایم؛‬
‫به سؤال فوق بهصورت زیر پاسخ دهید‪.‬‬
‫‪Serial port that modem is connected to [ttyS0]? ttyIAX1‬‬

‫پس از وارد کردن ســریال پورت مودم مجازی اول )‪ ،(ttyIAX1‬ســایر سؤاالت را نیز بهصورت پیشفرض‬
‫پاســخ دهید و دکمه ‪ Enter‬را بزنید‪ .‬این ســؤال برای تنظیمکردن سایر مودمهای مجازی‪ ،‬تکرار خواهدشد‪،‬‬
‫بنابراین برای مودم مجازی دوم هم سریال پورت ‪ ttIAX2‬را بهصورت زیر وارد کنید‪.‬‬
‫‪Serial port that modem is connected to [ttyS0]? ttyIAX2‬‬

‫پس از تنظیم هر دو مودم‪ ،‬چنانچه سؤال تکرار شد‪ ،‬پاسخ ‪ no‬داده و مراحل نصب را تکمیل نمایید‪.‬‬

‫‪Do you want to run faxaddmodem to configure another modem [yes]? n‬‬
‫ِ‬
‫تنظیمات مربوط به فکسهای ساخته شده در مسیر زیر خواهند بود‪:‬‬ ‫با تکمیل دستور ‪،faxsetup‬‬
‫‪#ls /etc/hylafax/config.ttyIAX1‬‬
‫‪#ls /etc/hylafax/config.ttyIAX2‬‬

‫اکنون باید سرویس فکس ‪ HylaFax‬را راهاندازی کنید‪:‬‬


‫‪# /etc/init.d/hylafax start‬‬

‫با اجرای دســتور فوق‪ ،‬ســرویس فکس اجرا میشــود و دو فکس تعریف شــده در مودمهای مجازی فعال‬
‫میشوند‪ .‬برای مشاهده فکسهای فعال‪ ،‬دستور زیر را اجرا نمایید‪:‬‬
‫‪# faxstat‬‬
‫‪HylaFAX scheduler on ubuntu14: Running‬‬
‫‪Modem ttyIAX2 (+1.999.555.1212): Running and idle‬‬
‫‪Modem ttyIAX1 (+1.999.555.1212): Running and idle‬‬

‫همانطورکه مالحظه میکنید‪ ،‬هر دو فکس آماده دریافت و ارسال فکساند‪.‬‬


‫نکته مهم‪ :‬چون اکثر تنظیمات را بهصورت پیشفرض تایید کردهایم‪ ،‬برچسب شمارهی فکسها‪ ،‬بهصورت‬
‫فوق نمایش داده میشود‪.‬‬
‫اکنون اگر در محیط کامندالین استریســک‪ ،‬دستور زیر را اجرا کنید‪ ،‬پس از پاسخ دادن به تماس‪ ،‬بوق‬
‫‪367‬‬ ‫فاکس‬

‫فکس را خواهید شنید‪.‬‬


‫‪CLI> channel originate SIP/100 application Dial IAX2/v-fax1‬‬

‫در این حالت وضعیت فکسهای ما بهصورت زیر خواهد بود‪:‬‬


‫‪# faxstat‬‬
‫‪HylaFAX scheduler on ubuntu14: Running‬‬
‫‪Modem ttyIAX2 (+1.999.555.1212): Running and idle‬‬
‫‪Modem ttyIAX1 (+1.999.555.1212): Answering the phone‬‬

‫‪# faxstat‬‬
‫‪HylaFAX scheduler on ubuntu14: Running‬‬
‫‪Modem ttyIAX2 (+1.999.555.1212): Running and idle‬‬
‫‪Modem ttyIAX1 (+1.999.555.1212): Receiving facsimile‬‬

‫خــوب تــا اینجا ما تنظیمات مربوط به مودمهای مجازی و ســرور فکس را انجام دادیــم‪ .‬اما چنانچه تصمیم‬
‫داشتید از این طریق‪ ،‬فکس دریافت کنید‪ ،‬برنامه زیر را اجرا کنید‪:‬‬
‫]‪[form-pstn‬‬
‫)(‪exten => _X. ,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,BackGround(Welcome‬‬
‫)‪same => n,waitExten(5‬‬
‫)(‪exten => 1,1,NOOP‬‬
‫)(‪exten => 2,1,NOOP‬‬
‫)‪exten => 9,1,Goto(fax-incoming,s,1‬‬
‫)‪exten => i,1,Goto(operator,1‬‬

‫]‪[fax-incoming‬‬
‫)‪exten => fax,1,Verbose(3,Incoming fax‬‬
‫)‪same => n,Dial(IAX2/v-fax1,20‬‬
‫)‪same => n,Dial(IAX2/v-fax2,20‬‬

‫همانطورکه مالحظه میکنید‪ ،‬با ارسال تماس به مودم مجازی ‪ v-fax1‬و ‪ ،v-fax2‬تماس بهوسیله آنها پاسخ‬
‫داده میشود و به دریافت فکس اقدام میکنند‪.‬‬

‫استفاده از دستگاه‌های ماشین فکس در شبکه ویپ (‪)Fax Pass-Through‬‬


‫بهشــکل تئوری‪ ،‬این قابلیت باید وجود داشته باشد که با متصلکردن یک ماشین فکس به یک شبکه ‪VoIP‬‬
‫و ســرور استریسک از طریق دستگاه های ‪ ،FXS ATA‬بتوان فکسهای دریافتی را مستقیماً به دستگاه ماشین‬
‫فکس ارســال نمود‪ .‬به این قابلیت ‪ Fax Pass-Through‬میگویند‪ .‬شــاید این روش سادهترین روش استفاده‬
‫از فکس در شبکههای ‪ VoIP‬باشد‪ .‬از جمله امتیازات این روش عبارتند از‪:‬‬
‫‪ -۱‬میتوانید از ماشینهای فکس خود همانند قبل استفاده کنید‪.‬‬
‫‪ -۲‬حداقل تنظیمات و دانش را برای راهاندازی آن نیاز دارید‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪368‬‬

‫درشکل ‪ 8-۱۲‬دو روش ‪ Fax pass through‬را مشاهده میکنید‪.‬‬

‫شکل ‪8-12‬‬

‫در حالت اول بهوسیله یک ‪ ،FXS ATA‬دستگاه فکس به شبکه ‪ VoIP‬متصل شده است‪ .‬در حالت دوم با یک‬
‫‪ FXS Module‬اتصال دستگاه فکس به شبکه ‪ VoIP‬برقرار گردیده است‪.‬‬
‫متأســفانه در هر دو حالت‪ ،‬نتایج نمیتواند مورد قبول واقع شــوند‪ .‬به دلیــل خطاهایی که این روش در‬
‫ارســال و دریافت فکس دارد‪ ،‬این روش بهعنوان یک روش غیر مطمئن و غیر پایدار محسوب میشود‪ .‬البته‬
‫با افزایش تعداد برگهای ارسالی فکس )‪ ،(Multi Pages‬اثر این ناپایداری‪ ،‬قابللمستر خواهدبود‪.‬‬

‫فعال کردن پروتکل ‪ T.38‬و تجهیزات وابسته در استریسک‬


‫در این روش‪ ،‬هم ســرور استریسک و هم دســتگاه ‪ ،FXS ATA‬هر دو باید پروتکل ‪ T.38‬را پشتیبانی کنند‪.‬‬
‫برای فعالکردن پروتکل ‪ T.38‬در استریسک باید بهصورت زیر اقدام کنید‪:‬‬
‫‪; sip.conf‬‬
‫‪t38pt_udptl = yes‬‬

‫در خصــوص فعال کردن پروتکل ‪ T.38‬برای دســتگاه ‪ ،FXS ATA‬باید به تنظیمات آن رجوع کنید ) دقت‬
‫کنید ممکن اســت دســتگاه ‪ FXS ATA‬از پروتکل ‪ T.38‬پشــتیبانی نکند‪ ،‬در این صورت باید از تجهیزاتی‬
‫استفاده کنید که پروتکل ‪ T.38‬را پشتیبانی میکنند(‪.‬‬

‫بررسی عامل تاخیر‪ 1‬در ارسال و دریافت فکس‬


‫از آنجا که فکس به تغییرات تأخیر بســیار حساستر اســت و این عوامل )خطاهای ‪ ( Timing‬منجر به بروز‬
‫خطا در دریافت و ارســال فکــس میگردند‪ ،‬میتوان از ‪Buffer‬های ‪ DAHDI‬اســتفاده کرد‪Buffer .‬ها در‬
‫فکــس صرفا برای جلوگیری از خطاهای ‪ Timing‬اســتفاده میشــوند‪ .‬برای نمونــه تنظیمات زیر را در فایل‬
‫‪ chan_dahdi.conf‬اعمال کنید‪:‬‬
‫‪;chan_dahdi.conf‬‬
‫‪faxbuffers => 12, half‬‬

‫از آنجــا کــه در ‪ DAHDI‬از کدک ‪ G711‬اســتفاده میشــود و در این نوع کــدک‪ ،‬هر ‪ 8ms‬یکبار‬

‫‪1- Jitter‬‬
‫‪369‬‬ ‫فاکس‬

‫نمونهبــرداری انجام میشــود‪ ،‬مثال برای تعدیل در تغییرات‪ ،‬باید نمونه بــرداری را به ‪ ۱۲‬برابر افزایش دهیم‪.‬‬
‫بنابراین طول بافر از ‪ 8ms‬به ‪ ۹۶ms‬افزایش مییابد‪.‬‬
‫‪Buffer = 12(buffer)*8ms=96ms‬‬

‫ارسال فکس در استریسک‬


‫برای ارسال فکس‪ ،‬همانند دریافت فکس میتوان به سه روش اقدام کرد‪:‬‬
‫‪ -۱‬استفاده از دستور ‪ SendFAX‬در استریسک‬
‫‪ -۲‬استفاده از مودمهای مجازی )‪ (IAXModem‬برای ارسال فکس‬
‫‪(Fax Pass-Through) VoIP‬‬ ‫‪ -۳‬استفاده ازدستگاه های ماشینهای فکس در شبکه‬

‫استفاده از دستور ‪SendFAX‬‬


‫میتوان بهوســیله دستور ‪ SendFAX‬فکس ارسال کرد‪ .‬برای آشنایی با این دستور ‪ ،‬عبارت زیر را در محیط‬
‫کامندالین استریسک وارد نمایید‪:‬‬
‫‪CLI> core show application SendFAX‬‬
‫]‪[Syntax‬‬
‫)]‪SendFAX([filename2[&...]][,options‬‬

‫مثال( چنانچه در سیســتم تلفنی خود داخلی ‪ ۹‬را برای ارســال فکس در نظر گرفته باشــید‪ ،‬اگر فردی با شما‬
‫تماس بگیرد و عدد ‪ ۹‬را فشــار دهد‪ ،‬سیســتم شما آماده ارســال یک فایل بهصورت فکس خواهد شد‪ .‬مثال‬
‫زیر را ببینید‪:‬‬
‫]‪[form-pstn‬‬
‫)(‪exten => _X. ,1,NoOp‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,BackGround(Welcome‬‬
‫)‪same => n,waitExten(5‬‬
‫)(‪exten => 1,1,NoOp‬‬
‫)(‪exten => 2,1,NoOp‬‬
‫)‪exten => 9,1,Goto(outboundfax,s,1‬‬
‫)‪exten => i,1,Goto(operator,1‬‬

‫]‪[outboundfax‬‬
‫)‪exten => s,1,NoOp(send a fax‬‬
‫)‪same => n,Wait(5‬‬
‫)}‪same => n,Set(FAXOPT(filename)=${FAXFILE‬‬
‫)‪same => n,Set(FAXOPT(ecm)=yes‬‬
‫)}‪same => n,Set(FAXOPT(headerinfo)=${FAXHEADER‬‬
‫)}‪same => n,Set(FAXOPT(localstationid)=${LOCALID‬‬
‫)‪same => n,Set(FAXOPT(maxrate)=14400‬‬
‫)‪same => n,Set(FAXOPT(minrate)=2400‬‬
‫)‪same => n,SendFAX(${FAXFILE},df‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪370‬‬

‫سپس میتوانید اطالعاتی در خصوص ارسال موفق یا ناموفق فکس بهصورت زیر داشته باشید‪:‬‬
‫)})‪exten => h,1,NoOp(FAXOPT(ecm) : ${FAXOPT(ecm‬‬
‫)}‪same => n,NoOp(FaxStatus : ${FAXSTATUS‬‬
‫)}‪same => n,NoOp(FaxStatusString : ${FAXSTATUSSTRING‬‬
‫)}‪same => n,NoOp(FaxError : ${FAXERROR‬‬
‫)}‪same => n,NoOp(RemoteStationID : ${REMOTESTATIONID‬‬
‫)}‪same => n,NoOp(FaxPages : ${FAXPAGES‬‬
‫)}‪same => n,NoOp(FaxBitRate : ${FAXBITRATE‬‬
‫)}‪same => n,NoOp(FaxResolution : ${FAXRESOLUTION‬‬

‫استفاده از مودم‌های مجازی (‪ )IAXModem‬برای ارسال فکس‬


‫میتوان از دســتورات ســرور فکس ‪ ،HylaFax‬اقدام به ارسال فکس نمود‪ .‬ازآنجاکه سرور فکس دارای دو‬
‫مودم مجازی تعریفشده )‪ ttyIAX1‬و ‪ (ttyIAX2‬است‪ ،‬با دستور زیر میتوان فکس ارسال کرد‪:‬‬
‫>‪# sendfax -D -h <Fax-Machine> -n -d <Destination-Number> <Filename‬‬

‫پارامتــر ‪ :Fax-Machine‬به‌وســیله این پارامتر مشــخص می‌کنیم از کدام فکس مجازی برای ارســال فکس‬
‫می‌خواهیم اســتفاده کنیم‪ .‬اینجا منظور فکس‌های ‪ v-fax1‬و ‪ v-fax2‬اســت که ســریال پورت مجازی آن‌ها‬
‫(‪ ttyIAX1‬و ‪ )ttyIAX2‬است‪.‬‬
‫پارامتر ‪ :Destination-Number‬به‌وسیله این پارامتر شماره مقصد را مشخص می‌کنیم‪.‬‬
‫پارامتر ‪ :Filename‬به‌وسیله این پارامتر فایلی را که می‌خواهیم فکس کنیم‪ ،‬ارسال می‌کنیم‪.‬‬
‫مثــال( قصد داریم از طریق مودم مجازی ‪ ، v-fax1‬یک فکس برای مودم مجازی ‪ v-fax2‬ارســال کنیم‪ .‬در‬
‫این صورت باید دستور زیر را اجرا کنید‪ .‬اینجا فایل ‪ /etc/passwd‬را ارسال خواهید کرد‪ .‬برای مشاهده این‬
‫فایل میتوانید دستور زیر را اجرا نمایید‪.‬‬
‫‪#cat /etc/passwd‬‬

‫برای ارسال فکس دستور زیر را اجرا کنید‪:‬‬


‫'‪# sendfax -D -h 'ttyIAX1@127.0.0.1' -n -d '8001' '/etc/passwd‬‬
‫)‪request id is 1 (group id 1) for host 127.0.0.1 (1 file‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬یک درخواســت جدید برای ارســال فکس )‪ (group id 1‬ایجاد و ارســال‬
‫میشود‪ .‬در این شرایط‪ ،‬گزارشات در کامندالین استریسک بهصورت زیر خواهد بود‪:‬‬
‫>‪CLI‬‬
‫‪Accepting AUTHENTICATED call from 127.0.0.1:54932:‬‬
‫‪> requested format = slin,‬‬
‫‪> requested prefs = (),‬‬
‫‪> actual format = ulaw,‬‬
‫‪> host prefs = (ulaw|alaw),‬‬
‫‪> priority = mine‬‬
‫‪Executing [8001@incoming-fax:1] NoOp("IAX2/v-fax1-1172", "This is v-fax2") in new stack‬‬
‫‪Executing [8001@incoming-fax:2] Dial("IAX2/v-fax1-1172", "IAX2/v-fax2") in new stack‬‬
‫)‪Call accepted by 127.0.0.1:4570 (format ulaw‬‬
371 ‫فاکس‬

Called IAX2/v-fax2
Format for call is (ulaw)
IAX2/v-fax2-14515 is ringing
IAX2/v-fax2-14515 answered IAX2/v-fax1-1172
Channel IAX2/v-fax2-14515 joined 'simple_bridge' basic-bridge <38a8e23d-74a4-4023-
b5f4-bd0440d7f72b>
Channel IAX2/v-fax1-1172 joined 'simple_bridge' basic-bridge <38a8e23d-74a4-4023-b5f4-
bd0440d7f72b>
CLI>

:‫ وضعیت مودمهای مجازی بهصورت زیر است‬،‫همچنین هنگام ارسال فکس‬


# faxstat
HylaFAX scheduler on ubuntu14: Running
Modem ttyIAX2 (+1.999.555.1212): Receiving facsimile
Modem ttyIAX1 (+1.999.555.1212): Sending job 2s

‫ در حال‬v-fax2 ‫ در حال ارســال و فکس مجــازی‬v-fax1 ‫ فکس مجازی‬،‫همانطورکــه مالحظــه میکنید‬


.‫ فکسهای دریافتی بهصورت پیشفرض در مسیر زیر ذخیره میشوند‬.‫دریافت فکس است‬
# ls –lh /var/spool/hylafax/recvq/

.‫ فکس دریافت شده را بهصورت زیر نشان میدهد‬۹-۱۲ ‫برای مثال شکل‬

9-12 ‫شکل‬

.‫ تبدیل کنید‬pdf ‫ در صورت نیاز شما میتوانید فرمت آن را به‬.‫ ذخیره شدهاست‬tif ‫این فکس با فرمت‬
#tiff2pdf /var/spool/hylafax/recvq/fax000000003.tif > /tmp/fax000000003.pdf
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪372‬‬

‫مثال( فرض کنید برنامه زیر را در استریسک داشته باشیم‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[incoming-fax‬‬
‫)(‪exten => _X.,1,NoOp‬‬
‫)})‪same => n,Verbose(caller: ${CALLERID(num‬‬
‫)}‪same => n,Verbose(callee: ${EXTEN‬‬
‫)})})‪same => n,Set(caller=${FILTER(A-Za-z0-9\\x28-\\x2F,${CALLERID(name‬‬
‫)}‪same => n,Verbose(${caller‬‬
‫)})‪same => n,Verbose(${CALLERID(num‬‬
‫)‪same => n,Set(FAXDEST=/tmp‬‬
‫)})‪same => n,Set(tempfax=${STRFTIME(,,%C%y%m%d%H%M‬‬
‫)‪same => n,ReceiveFax(${FAXDEST}/${tempfax}.tif,df‬‬
‫)}‪same => n,Verbose(3,- Fax receipt completed with status: ${FAXSTATUS‬‬
‫)‪same => n,System(tiff2pdf ${FAXDEST}/${tempfax}.tif > ${FAXDEST}/${tempfax}.pdf‬‬

‫اکنون دوباره دستور ‪ sendfax‬را بهصورت زیر اجرا کنید‪.‬‬

‫'‪# sendfax -D -h 'ttyIAX1@127.0.0.1' -n -d '88657489' '/etc/passwd‬‬

‫در این حالت بهوســیله دســتور ‪ ،ReceiveFax‬فکس مورد نظر دریافت و در مســیر مشــخص شده ذخیره‬
‫میگردد وپس از آن با دستور ‪ tiff2pdf‬به ‪ pdf‬تبدیل میشود‪.‬‬

‫استفاده از ماشین‌های فکس در شبکه ‪)Fax Pass-Through) VOIP‬‬


‫در این روش کاربر خیلی ســاده و راحت‪ ،‬میتواند با دســتگاه فکس خود‪ ،‬همانند قبل فکس ارســال کند‪.‬‬
‫دستگاه ماشین فکس از طریق ‪ FXS ATA‬با سرور استریسک در ارتباط است‪.‬‬

‫تشخیص اتوماتیک فکس (‪)Fax Detection‬‬


‫گاهی الزم میشود بهصورت خودکار فکسهای ورودی را تشخیص دهیم و آنها را دریافت کنیم‪ .‬برخی‬
‫از ماشینهای فکس این قابلیت را دارند و با پخش بوق فکس‪ ،‬بالفاصله بهصورت خودکار فکس را دریافت‬
‫میکنند‪ .‬در سیستم تلفنی استریسک‪ ،‬قابلیتی بهنام ‪ Fax Detection‬وجود دارد‪ .‬استریسک قادر است تماس‬
‫جدیــد را برای چند ثانیه بهصورت خودکار پاســخ دهد و با پخش بوق فکــس‪ ،‬بالفاصله کنترل برنامه را به‬
‫ســمت اکستنشــن ‪ fax‬منتقل میکند‪ .‬ایــن قابلیت هم برای ماژول ‪ DAHDI‬و هم بــرای ماژول ‪ SIP‬قابل‬
‫استفاده است‪.‬‬
‫بهعنــوان مثال برای تشــخیص استریســک از دریافت فکس از طریــق خطوط مخابراتــی‪ ،‬باید پارامتر‬
‫‪ faxdetect‬را در فایل ‪ chan_dahdi.conf‬با یکی از مقادیر جدول ‪ ۱-۱۲‬تنظیم کنید‪.‬‬
373 ‫فاکس‬

Value Description
Enables fax detection on inbound calls. When a fax is detected, applies the
incoming faxbuffers option if it has been set and redirects the call to the fax extension
in the dialplan.
Enables fax detection on outbound calls. The dialplan is not executing on an
outbound channel. If a fax is detected, the faxbuffers option will be applied,
outgoing
and the channel will be redirected and start executing the dialplan at the fax
extension.
both Enables fax detection for both incoming and outgoing calls.
no Disables fax detection. This is the default.
1-12 ‫جدول‬

sip. ‫ را در فایل‬faxdetect ‫ باید پارامتر‬،SIP‫برای تشــخیص استریســک از دریافت فکس از طریق پروتکل‬
.‫ تنظیم کنید‬۲-۱۲ ‫ با یکی از مقادیر جدول‬conf

Value Description
Enables fax detection by watching the audio for a CNG tone. If a CNG tone is
cng
detected, redirects the call to the fax extension in the dialplan.
Redirects the call to the fax extension in the dialplan if a T.38 reinvite is
t.38
received.
yes Enables both cng and t38 fax detection.
no Disables fax detection. This is the default.
2-12 ‫جدول‬

.‫برای مثال برنامه زیر این کار را انجام میدهد‬


[from-pstn]
exten => _X.,1,Answer()
same => n,Wait(3) //if fax, then goto fax extension
same => n,Playback(welcome)
same => n,Goto(IVR,s,1)

exten => fax,1,Verbose(Incoming fax detect)


same => n,Verbose(caller: ${CALLERID(num)})
same => n,Verbose(callee: ${EXTEN})
same => n,Set(caller=${FILTER(A-Za-z0-9\\x28-\\x2F,${CALLERID(name)})})
same => n,Verbose(${caller})
same => n,Verbose(${CALLERID(num)})
same => n,Set(FAXDEST=/tmp)
same => n,Set(tempfax=${STRFTIME(,,%C%y%m%d%H%M)})
same => n,ReceiveFax(${FAXDEST}/${tempfax}.tif,df)
same => n,Verbose(3,- Fax receipt completed with status: ${FAXSTATUS})
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪374‬‬

‫)(‪same => n,Hangup‬‬

‫در این روش میتوان فکس را از طریق مودمهای مجازی نیز دریافت کرد‪.‬‬
‫]‪[from-pstn‬‬
‫)(‪exten => _X.,1,Answer‬‬
‫)‪same => n,Wait(3‬‬ ‫‪//if fax, then goto fax extension‬‬
‫)‪same => n,Playback(welcome‬‬
‫)‪same => n,Goto(IVR,s,1‬‬

‫)‪exten => fax,1,Verbose(3,Incoming fax‬‬


‫)‪same => n,Dial(IAX/v-fax1,20‬‬
‫)‪same => n,Dial(IAX/v-fax2,20‬‬

‫همانطورکه مالحظه میکنید‪ ،‬ابتدا استریســک تماس را پاســخ میدهد و برای مدتی منتظر میماند تا بوق‬
‫فکس را تشخیص دهد‪ ،‬اگر بوق فکس بهوسیله استریسک تشخیص داده شد‪ ،‬کنترل برنامه به اکستنشن ‪fax‬‬
‫منتقل و دســتورات آن اجرا میشوند‪ ،‬ولی اگر در مدت زمان مشخص شده‪ ،‬بوق فکس تشخیص داده نشد‪،‬‬
‫دستورات با اولویت بعدی اجرا و به کانتکست ]‪ [IVR‬منتقل میشوند‪.‬‬

‫نتیجه‌گیری‬
‫امروزه علیرغم پیشــرفت تکنولوژی‪ ،‬فکس هنوز هم کاربردهای ویژهای دارد‪ .‬لذا سیســتمهای نسل جدید‬
‫مخابراتی باید بتوانند با این تکنولوژی ســازگاری داشــته باشند‪ .‬استریسک بهعنوان یک سافت سوئیچ تلفنی‬
‫میتواند در زمینههای مختلفی این سازگاری را ایجاد نماید‪ .‬در این فصل با نحوه چگونگی ایجاد یک فکس‬
‫سرور )‪ (Hylafax‬و کاربرد آن آشنا شدید‪.‬‬
‫فصل سیزدهم‬

‫ابزار مدیریتی استریسک‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪376‬‬

‫ابزار مدیریتی استریسک‬


‫‪1‬‬

‫یکی از ابزارهای قدرتمند استریســک برای مانیتورینگ و مدیریت استریسک‪ ،‬واسط مدیریتی ‪ AMI‬است‪.‬‬
‫با اســتفاده از این ابزار میتوان رویدادهای استریسک و رفتار استریسک را بهصورت لحظهای مشاهده کرد‪.‬‬
‫این رویدادها بهشکل پیامهایی در استریسک ایجاد میشوند‪.‬‬
‫ســرویس استریسک‪ ،‬یک سرویس رویدادگراست و در سیستمهای رویدادگرا‪ ،‬رویدادها غالبا بهشکل‬
‫پیامهای متنی )‪ (Messaging‬هستند‪ .‬استریسک برای هر فعالیتی که انجام میدهد یک رویداد‪ ۲‬صادر میکند‬
‫که میتوان با گوشدادن به این رویدادها و تحلیل آنها‪ ،‬رفتار استریسک را بازبینی کرد‪.‬‬
‫در استریســک رویدادهای متفاوتی داریم که هر کدام رفتار منحصر به فرد خود را دارند‪ .‬در ادامه این‬
‫رویدادها بررسی میشوند‪.‬‬

‫انواع رویداد‌ها در استریسک‬


‫رویدادهای استریسک به دو دسته اصلی تقسیم میشوند‪:‬‬
‫‪ -۱‬رویدادهای مبتنی بر ‪Manager Event‬‬
‫‪ -۲‬رویدادهای مبتنی بر ‪Manager Action‬‬

‫)‪1- Asterisk Manager Interface (AMI‬‬


‫‪2- Event‬‬
‫‪377‬‬ ‫ابزار مدیریتی استریسک‬

‫رویدادهای مبتنی ‪Manager Event‬‬


‫در این رویداد‪ ،‬سیســتم تبادل پیامها بهصورت یک طرفه است‪ .‬شکل ‪ ۱-۱۳‬نحوه تبادل پیامها را در این نوع‬
‫رویدادها نمایش میدهد‪.‬‬

‫شکل ‪1-13‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در این روش استریسک صرفا در حال ارسال رویدادها به کالینت‪ ۱‬است )به‬
‫عبارت دیگر‪ ،‬یوزر اکانت ‪ AMI‬درحال گوش دادن به تمام رویدادهای استریسک است(‪.‬‬

‫رویداد‌های مبتنی بر ‪Manager Action‬‬


‫در این نوع رویدادها‪ ،‬ابتدا از طرف یوزر اکانت‪ AMI‬یک فرمان ایجاد و برای استریســک ارســال میشود‬
‫و در پاســخ به این فرمان‪ ،‬استریســک نتایج اجرای دســتور را بهصورت رویدادی برای یوزر اکانت ارســال‬
‫میکند‪ .‬شکل ‪ ۲-۱۳‬نحوه تبادل پیامها در این نوع رویداد را نمایش میدهد‪.‬‬

‫شکل ‪2-13‬‬
‫در شکل ‪ ۲-۱۳‬یوزر اکانت ‪ ،AMI‬با ایجاد یک رویداد ‪ Manager Action‬و ارسال آن به سمت استریسک‪،‬‬
‫یک پاســخ ‪ Action Response‬از طرف استریســک دریافت میکند‪ .‬برای مثال‪ ،‬چنانچه رویداد بررســی‬

‫‪1- AMI-Client‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪378‬‬

‫وضعیت یک اپراتور برای استریســک ارســال شود‪ ،‬در پاسخ‪ ،‬استریســک وضعیت اپراتور مربوطه را نشان‬
‫خواهد داد‪.‬‬
‫نوع دیگری از رویداد وجود داردکه باعث میشوند چندین پاسخ از طرف استریسک برای یوزر اکانت‬
‫ارسال شود‪ .‬شکل ‪ ۳-۱۳‬را در نظر بگیرید‪.‬‬

‫شکل ‪3-13‬‬

‫در شکل ‪ ،۳-۱۳‬یوزر اکانت ‪ AMI‬یک درخواست برای استریسک ارسال میکند‪ .‬سپس چند پاسخ از‬
‫طرف استریســک برای یوزر اکانت ارســال میشود‪ .‬برای مثال چنانچه فرمان »‪ «Active Channel‬بهوسیله‬
‫یوزر اکانت به سمت استریسک ارسال شود‪ ،‬چون احتمال دارد بیش از یک »‪ «Active Channel‬در سیستم‬
‫موجود باشد‪ ،‬استریسک رویدادهایی را برای یوزر اکانت به عنوان پاسخ برمیگرداند‪.‬‬

‫پیکر‌بندی ابزار مدیریتی ‪AMI‬‬

‫پیــش از ورود بــه بحث اصلی‪ ،‬نخســت با تنظیمات اولیه ابــزار مدیریتی ‪ AMI‬در استریســک و چگونگی‬
‫فعالشدن آن در استریسک آشنا شوید‪ .‬در استریسک برای استفاده از ابزار مدیریتی ‪ ،AMI‬باید آن را فعال‬
‫کنید‪ .‬برای این منظور در مسیر فایلهای پیکربندی استریسک‪ ،‬فایل زیر را باز کنید‪:‬‬
‫‪#vim /etc/asterisk/manager.conf‬‬

‫در بخش تنظیمات عمومی‪ ،‬قسمت ]‪ ،[general‬پارامترها بهصورت زیرند‪:‬‬


‫]‪[general‬‬
‫‪enabled = no‬‬
‫‪port = 5038‬‬
‫‪bindaddr = 0.0.0.0‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬این ابزار بهصورت پیشفرض غیرفعال اســت‪ .‬بنابراین آن را بهصورت زیر‬
‫فعال کنید‪.‬‬
‫‪enabled = yes‬‬

‫با فعال کردن این ابزار در استریســک‪ ،‬در همه اینترفیسهای شــبکه و در پورت ‪ ، ۵۰۳8‬قابلیت ‪ AMI‬فعال‬
‫‪379‬‬ ‫ابزار مدیریتی استریسک‬

‫میشود‪.‬‬
‫درصورت لزوم میتوان برای امنیت بیشت ِر سرور استریسک‪ ،‬آن را به اینترفیسهای خاصی محدود کرد‬
‫و یا پورت آن را از پورت پیشفرض تغییر داد‪ .‬برای مثال چنانچه تصمیم داشــته باشــید ابزار ‪ AMI‬را صرفا‬
‫روی اینترفیس لوکال در سرور استریسک فعال و پورت آن را تعویض کنید‪ ،‬تنظیمات زیر را انجام دهید‪:‬‬
‫‪;manager.conf‬‬
‫]‪[general‬‬
‫‪enabled = yes‬‬
‫‪port = 8305‬‬
‫‪bindaddr = 127.0.0.1‬‬

‫پس از انجام تنظیمات عمومی‪ ،‬باید برای اتصال به ‪ AMI‬در استریسک‪ ،‬یک یوزر اکانت ایجاد کنید‪ .‬برای‬
‫ساختن یوزر اکانت ‪ AMI‬در استریسک‪ ،‬در فایل ‪ manager.conf‬به شکل زیر عمل کنید‪:‬‬
‫‪;manager.conf‬‬
‫]‪[hello‬‬
‫‪secret=world‬‬
‫‪read=all ; Receive all types of events‬‬
‫‪write=all ; Allow this user to execute all actions‬‬

‫اینجا یک یوزر اکانت ‪ AMI‬جدید بهنام ‪ hello‬با پســورد ‪ world‬ســاختید‪ .‬در قســمت پارامتر ‪ ، read‬مقدار‬
‫‪ all‬به این معنی است که کلیه رویدادهای مبتنی بر ‪ ، Manager Event‬قابل دریافت است‪ .‬در پارامتر ‪write‬‬
‫مقدار ‪ all‬به معنی اجرای همه رویدادهای مبتنی بر ‪ Manager Action‬است‪.‬‬
‫اکنون به محیط کامندالین استریسک بروید و دستور زیر را اجرا نمایید‪.‬‬
‫‪CLI> manager reload‬‬

‫برای نمایش همه یوزر اکانتهای استریسک‪ ،‬دستور زیر را اجرا کنید‪.‬‬
‫‪CLI> manager show users‬‬
‫‪username‬‬
‫‪--------‬‬
‫‪hello‬‬
‫‪-------------------‬‬
‫‪1 manager users configured.‬‬

‫یوزر اکانت ‪ AMI‬جدید تعریف شــد‪ .‬اکنون باید ازطریق این یوزر اکانت به استریســک متصل شوید‪ .‬دو‬
‫روش برای اتصال به استریسک ازطریق یوزر اکانت وجود دارد‪:‬‬
‫‪AMI over TCP -۱‬‬
‫‪AMI over HTTP -۲‬‬

‫‪AMI over TCP‬‬


‫این روش یکی از روشهای متداول در اتصال به استریســک از طریق ‪ AMI‬اســت‪ .‬برای مثال مراحل زیر را‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪380‬‬

‫برای برقراری اتصال انجام میدهیم‪ .‬ابتدا بهوسیله دستور ‪ telnet‬روی سرور استریسک به آیپی )‪(127.0.0.1‬‬
‫و پورت پیش فرض ‪ 5038‬متصل میشویم‪:‬‬
‫‪#telnet 127.0.0.1 5038‬‬
‫‪Trying 127.0.0.1...‬‬
‫‪Connected to localhost.‬‬
‫‪Escape character is '^]'.‬‬
‫‪Asterisk Call Manager/1.1‬‬

‫با اجرای دستور فوق‪ ،‬به محیط ‪ AMI‬استریسک وارد شوید و با اطالعات یوزر اکانت‪ ،‬مراحل اعتبارسنجی‬
‫‪۱‬‬

‫را انجام دهید‪ .‬اطالعات یوزر اکانت ‪ AMI‬را وارد کنید و کلید ‪ enter‬را دوبار بزنید‪.‬‬
‫‪Action: Login‬‬
‫‪Username: hello‬‬
‫‪Secret: world‬‬

‫پــس از ورود اطالعات الزم )هرکدام در ســطری جداگانه(‪ ،‬درصورت صحــت اطالعات‪ ،‬پیامی از طرف‬
‫استریسک مبنی بر اتصال موفق به ‪ AMI‬به شما نمایش داده میشود‪.‬‬
‫‪Response: Success‬‬
‫‪Message: Authentication accepted‬‬

‫در این لحظه میتوان هر رویداد موجود در استریسک را مشاهده و بازبینی کرد‪ .‬به عنوان تمرین سعی کنید‬
‫یک تماس در استریســک ایجاد کنید‪ .‬کلیه رویدادهای استریســک قابل مشاهده خواهد بود‪ .‬ازآنجاکه در‬
‫گزارش رویدادها هیچ فیلتری مشخص نشده است‪ ،‬استریسک کلیه رویدادها را برای این یوزر اکانت ارسال‬
‫میکند‪.‬‬
‫ازآنجاکه این یوزر اکانت‪ ،‬مجوز ‪ write‬دارد میتوانید یک ‪ Action‬خیلی ساده برای استریسک ارسال‬
‫کنید‪ .‬پس از آن استریسک پاسخ رویداد را خواهد فرستاد‪ .‬برای مثال فرمان زیر را در نظر بگیرید‪.‬‬
‫‪Action:ping‬‬
‫‪Response: Success‬‬
‫‪Ping: Pong‬‬
‫‪Timestamp: 1472378967.990017‬‬

‫اینجا فرمان ‪ ping‬ازطریق یوزر اکانت ‪ AMI‬برای استریســک ارســال شــده است‪ ،‬و استریسک در پاسخ به‬
‫فرمان فوق‪ ،‬رویداد )پاسخ( ‪ pong‬را ارسال میکند‪.‬‬
‫‪ ،AMI‬فرمان » ‪ « logoff‬را برای استریسک ارسال کنید‪:‬‬ ‫برای خروج از یوزر اکانت‬
‫‪Action:logoff‬‬
‫‪Response: Goodbye‬‬
‫‪Message: Thanks for all the fish.‬‬
‫‪Connection closed by foreign host.‬‬
‫‪AMI over HTTP‬‬
‫در استریسک این قابلیت وجود دارد که برای ارتباط با ‪ AMI‬از پروتکل ‪ HTTP‬بهجای ‪ TCP‬استفاده کرد‪.‬‬

‫‪1- Authentication‬‬
381 ‫ابزار مدیریتی استریسک‬

.‫ برای استفاده از این پروتکل تنظیمات بیشتری نیاز است‬.‫نحوه ارتباط برای هر دو روش کامال یکسان است‬
‫ پارامتر‬manager.conf ‫ نخست در فایل‬،‫ برای انجام آن‬.‫این تنظیمات در دو فایل مســتقل صورت میگیرند‬
.‫زیر را فعال کنید‬
;manager.conf
webenabled=yes

.‫ این قابلیت را فعال کنید‬http.conf ‫سپس در فایل‬


;HTTP.conf
enable=yes

.‫ میتوان از دستورات زیر استفاده نمود‬، HTTP ‫برای ارتباط با یوزر اکانت از طریق‬
wget "http://localhost:8088/rawman?action=login&username=hello&secret=world" --save-
cookies cookies.txt -O –

:‫همچنین میتوان بهشکل زیر فرمانهایی را برای استریسک ارسال کرد‬


wget "http://localhost:8088/rawman?action=ping" --load-cookies cookies.txt -O –
wget "http://localhost:8088/rawman?action=logoff" --load-cookies cookies.txt -O -

AMI ‫پیکربندی عمومی‬


‫ به استریسک متصل شویم و‬HTTP ‫ یا‬TCP ‫ ایجاد شــد و توانســتیم بهوسیله‬AMI ‫تا اینجا یک یوزر اکانت‬
.‫ اهمیت دارد‬AMI ‫ در این بخش آشــنایی با ســایر پارامترهای فایل پیکربندی‬.‫رویدادها را مشــاهده نماییم‬
.‫[ توضیح میدهد‬general] ‫ را در بخش‬manager.conf ‫ پارامترهای فایل‬۱-۱۳ ‫جدول‬

Options Value/Example Description


enable yes Enables the AMI. The default is no.
webenabled yes Allows access to the AMI through the built-
in HTTP server. The default is no.
port 5038 Sets the port number to listen on for AMI
connections. The default is 5038.
bindaddr 127.0.0.1 Sets the address to listen on for AMI
connections. The default is to listen on all
addresses (0.0.0.0). However, it is highly
recommended to set this to 127.0.0.1.
tlsenable yes Enables listening for AMI connections
using TLS. The default is no. It is highly
recommended to expose connectivity only
via the TLS outside the local machine.
tlsbindport 5039 Sets the port to listen on for TLS
connections to the AMI. The default is 5039.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 382

Options Value/Example Description


tlsbindaddr 0.0.0.0 Sets the address to listen on for TLS-based
AMI connections. The default is to listen on
all addresses (0.0.0.0).
tlscertfile /var/lib/asterisk/key/asterisk.pem Sets the path to the server certificate for
TLS. This is required if tlsenable is set to yes.
tlsprivatekey /var/lib/asterisk/key/private.pem Sets the path to the private key for TLS. If
this is not specified, the tlscertfile will be
checked to see if it also contains the private
key.
tlscipher <cipher stright> Specifies a list of ciphers for OpenSSL to
use. Setting this is optional. To see a list of
available ciphers, run openssl ciphers -v at
the command line.
allowmultiplelogin no Allows the same account to make more
than one connection at the same time. The
default is yes.
displayconnects yes Reports connections to the AMI as verbose
messages printed to the Asterisk console.
This is usually useful, but it can get in the
way on a system that uses scripts that make
a alot of connections to the AMI. The default
is yes.
timestampevents no Adds a Unix epoch-based timestamp to
every event reported to the AMI. The
default is no.
brokeneventsaction yes Restores previously broken behavior for the
Events AMI action, where a response would
not be sent in some circumstances. This
option is there for the sake of
backward compatibility for applications that
worked around a bug; it should not be used
unless absolutely necessary. The default is
no.
channelvars VAR1,VAR2,VAR3 Specifies a list of channel variables to
include with all manager events that are
[,VAR4[...]] channel-oriented. The default is to include
no channel variables.
debug no Enables some additional debugging in
the AMI code. This is primarily there for
developers of the Asterisk C code. The
default is no.
httptimeout 60 Sets the HTTP timeout, in seconds. This
timeout affects users of the AMI over HTTP:
it sets the Max-Age of the HTTP cookie, sets
how long events are cached to
allow retrieval of the events over HTTP
using the WaitEvents action, and the
amount of time that the HTTP server keeps
a session alive after completing an AMI
action. The default is 60 seconds.
1-13 ‫جدول‬
383 ‫ابزار مدیریتی استریسک‬

AMI ‫پیکربندی یوزر اکانت در‬


‫ هر رویداد عضو‬،‫ به عبارت دیگر‬.‫ کلیه رویدادها بهصورت کالسبندیشده تعریف میشوند‬،‫در استریسک‬
‫ نام کالس مربوطه را در پارامترهای‬،‫کالس خاصی است و میتوان برای دسترسی به رویدادهای هر کالس‬
.‫ ذکر نمود‬write ‫ و‬read
:‫ انواع کالسهای از قبل تعریف شده برای رویدادها را نمایش میدهد‬۲-۱۳ ‫جدول‬

Permission identifier read Write


all shorthand way of specifying that this user Grants users all privilege options.
should have access to all privilege options.
system Allows user to receive general system Allows user to perform Asterisk system
information, such as notifications of management commands such as Restart, Reload,
configuration reloads. or Shutdown. This permission also grants users the
ability to run system commands outside of Asterisk.
Granting this permission is equivalent to providing
shell access as the user/group that the Asterisk
process is running as. This is another good reason
why Asterisk should not by run as root.
call Allows user to receive events about channels Allows user to set information on channels.
on the system.
log Gives user access to logging information. read-only
verbos Gives user access to verbose logging read-only
information.
agent Gives user access to events regarding the Enables user to perform actions for managing and
status of agents from the app_queue and retrieving the status of queues and agents.
chan_agent modules.
user Grants access to user-defined events, as Lets user perform the UserEvent manager
well as events about Jabber/XMPP users. action, which provides the ability to request that
Asterisk generate a user-defined event.c
config write-only Allows user to retrieve, update, and reload
configuration files.
command write-only Allows user to execute Asterisk CLI commands over
the AMI.
dtmf Allows user to receive events generated as read-only
DTMF passes through the Asterisk core.
reporting Gives user access to call-quality events, Enables user to execute a range of actions to
such as jitterbuffer statistics or RTP Control retrieve statistics and status information from across
Protocol (RTCP) reports. the system.
CDR Grants user access to CDR records reported read-only
by the cdr_manager module.
dialplan Allows user to receive events generated read-only
when variables are set or new extensions
are created.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 384

Permission identifier read Write


originate write-only Allows user to execute the Originate action, which
allows an AMI client to request that Asterisk create
a new call.
agi Allows user to receive events generated Enables user to perform actions for managing
when AGI commands are processed. channels that are running AGI in its asynchronous
mode.
cc Allows user to receive events related to read-only
Call Completion Supplementary Services
(CCSS).
aoc Lets user see Advice of Charge events Allows user to execute the AOCMessage manager
generated as AOC events are received. action, for sending out AOC messages.
2-13 ‫جدول‬

‫کنترل رویدادها در استریسک‬


‫فرمت استاندارد و یکسانی دارند‬Manager Action ‫ و‬Manager Event ‫همه رویدادهای استریسک اعم از‬
‫ بهراحتی میتوان آنها را در برنامههای کاربردی تجزیه و تحلیل‬،‫و ازآنجاکــه این رویدادها قابلخواندناند‬
.‫کرد‬
:‫ بهصورت زیر است‬Manager Event ‫قالب استاندارد برای کلیه رویدادهای‬
Event : evnt-name <CRLF>
Key1 : value1 <CRLF>
Key2 : value2 <CRLF>
.
.
.
Key n : value n <CRLF>
<CRLF>

:‫ بهصورت زیر است‬Manager Action ‫قالب استاندارد برای کلیه رویدادهای‬


Action : action-name <CRLF>
Key1 : value1 <CRLF>
Key2 : value2 <CRLF>
.
.
.
Key n : value n <CRLF>
Variable : <variable1> = <value1> <CRLF>
Variable : < variable2> = <value2> <CRLF>
.
.
.
Variable n : < variable n> = <value n> <CRLF>
<CRLF>
‫‪385‬‬ ‫ابزار مدیریتی استریسک‬

‫آنچه در تمامی رویدادها دیده میشــود این اســت که بعد از هر ‪ key:value‬برای اجرای دســتور باید کلید‬
‫"‪ "enter‬فشرده شود‪ .‬برای نمونه به رویداد زیر توجه کنید‪:‬‬
‫‪Event: Hangup‬‬
‫‪Privilege: call,all‬‬
‫‪Channel: SIP/Phone_1-00000000‬‬
‫‪Uniqueid: 1283108164.0‬‬
‫‪CallerIDNum: 5131770‬‬
‫‪CallerIDName: 5131770‬‬
‫‪Cause: 16‬‬
‫‪Cause-txt: Normal Clearing‬‬

‫همانطورکه مالحظه میکنید‪ ،‬هر رویداد با کلمه کلیدی ‪ Event‬ایجاد میشود که در ادامه نام آن را مشاهده‬
‫میکنید‪ .‬نکته مهم بعدی اینکه کالس این رویداد بهوســیله پارامتر ‪ Privilege‬نشــان داده میشود و این بیان‬
‫میکنــد که برای نمایش رویداد مورد نظــر‪ ،‬یوزر اکانت ‪ AMI‬باید مجوز ‪ read=call , all‬را داشتهباشــد‪،‬‬
‫درغیر اینصورت این رویداد نمایش داده نمیشود‪ .‬سایر پارامترها هرکدام مقادیری را خواهند داشت‪.‬‬
‫برای مشاهده کلیه رویدادهای استریسک‪ ،‬به محیط کامندالین بروید و دستور زیر را اجرا کنید‪:‬‬
‫‪CLI > manager show events‬‬
‫>‪CLI > manager show event <event name‬‬

‫با این دستور میتوانید با ساختار رویدادها )پارامترهای ورودی و خروجی( آشنا شوید و در برنامههای خود‬
‫از آن استفاده کنید‪ .‬به عنوان تمرین و برای آشنایی با رویداد ‪ Hangup‬دستور زیر را اجرا کنید‪:‬‬
‫‪Cli > manager show event hangup‬‬

‫برای مشاهده تمامی ‪Action‬ها در استریسک کافی است در محیط کامندالین استریسک دستور زیر را اجرا‬
‫کنید‪:‬‬
‫‪Cli > manager show commands‬‬
‫>‪Cli > manager show command <Action-name‬‬

‫با استفاده از این دستور شما میتوانید با ساختار ‪ Manager Action‬ها و پارامترهای ورودی و خروجی آن ها‬
‫آشنا شده و در برنامههای خود از آن استفاده کنید‪ .‬برای مثال فرمت ‪ Action=Login‬بهصورت زیر است‪:‬‬
‫‪Cli > manager show command Login‬‬
‫]‪[Syntax‬‬
‫‪Action: Login‬‬
‫>‪[ActionID:] <value‬‬
‫>‪Username: <value‬‬
‫>‪[Secret:] <value‬‬

‫]‪[Synopsis‬‬
‫‪Login Manager.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪386‬‬

‫]‪[Description‬‬
‫‪Login Manager.‬‬

‫]‪[Arguments‬‬
‫‪ActionID‬‬
‫‪ActionID for this transaction. Will be returned.‬‬
‫‪Username‬‬
‫‪Username to login with as specified in manager.conf.‬‬
‫‪Secret‬‬
‫‪Secret to login with as specified in manager.conf.‬‬

‫]‪[See Also‬‬
‫‪Not available‬‬

‫استفاده از ابزار مدیریتی ‪ AMI‬در برنامه کاربردی‬


‫تا اینجا مطالب مرتبط با ‪ AMI‬و نحوه ارتباط با آن شرح داده شد اما چگونه میتوان بهصورت کاربردی از‬
‫‪ AMI‬استفاده کرد؟‬
‫همانطورکه پیش از این اشــاره شــد‪ ،‬ازطریق ‪ AMI‬میتوان رویدادهای استریســک را بازبینی نمود و‬
‫بهوســیله آن رفتار استریســک را زیر نظر گرفت‪ .‬همچنین توضیح داده شــد که این رویدادها قابلخواندن‬
‫)‪ (Text Base‬هســتند‪ .‬شــاید اســتفاده از ‪ AMI‬ازطریق پروتکل ‪ TCP‬یا ‪ HTTP‬کمی دشوار بهنظر برسد‪،‬‬
‫بنابراین بهتر است در خصوص بهرهبردن از ‪ AMI‬از ابزارهایی استفاده کنیم که بهصورت کالس در زبانهای‬
‫سطح باال از قبیل ‪ c#, vb.net, java, javascript, perl, php, python‬طراحی شدهاند‪ .‬بهواسطه این کالسها‬
‫میتــوان از طریــق یک یوزر اکانت ‪ AMI‬به استریســک متصل شــد و کلیه رویدادهای استریســک را در‬
‫زبانهای سطح باال‪ ،‬کنترل و مدیریت کرد‪.‬‬
‫پیش از استفاده از کالسهای ‪ AMI‬در زبانهای سطح باال‪ ،‬بهتر است با یک مثال از کار با رویدادها در‬
‫‪ AMI‬بدون استفاده از کالسها کار را آغاز کنیم‪.‬‬
‫برنامه زیر که با زبان ‪ Python‬نوشته شده است را درنظر بگیرید‪.‬‬
‫‪#!/usr/bin/python‬‬
‫‪# telnet program example‬‬
‫‪import socket‬‬
‫‪import select‬‬
‫‪import string‬‬
‫‪import sys‬‬
‫‪import threading‬‬
‫‪import subprocess‬‬

‫‪#function for threading worker‬‬


‫‪def handler(data):‬‬
387 ‫ابزار مدیریتی استریسک‬

#split data based on \n\n


events = data.strip().lower().split("\n\n")
#parse each event sperately.
for event in events :
if event.find("event: agentcalled") != -1 :
AgentCalledEvent(event)
elif event.find("event: agentringnoanswer") != -1 :
AgentRingNoAnswerEvent(event)
elif event.find("event: queuecallerabandon") != -1 :
QueueCallerAbandonEvent(event)
elif event.find("event: agentconnect") != -1 :
AgentConnectEvent(event)
elif event.find("event: agentcomplete") != -1 :
AgentCompleteEvent(event)
else :
not_important = "not important"
return

#main function
if __name__ == "__main__":

#########################################################
# if(len(sys.argv) < 3) :
# print 'Usage : python telnet.py hostname port'
# sys.exit()
# host = sys.argv[1]
# port = int(sys.argv[2])
#########################################################
host = 'localhost'
port = 5038

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)

# connect to remote host


try :
s.connect((host, port))
except :
# print 'Unable to connect'
sys.exit()

# print 'Connected to remote host'


runlevel = 0
threads = []
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪388‬‬

‫‪while 1:‬‬
‫]‪socket_list = [sys.stdin, s‬‬
‫‪# Get the list sockets which are readable‬‬
‫)][ ‪read_sockets, write_sockets, error_sockets = select.select(socket_list , [],‬‬
‫‪for sock in read_sockets:‬‬
‫‪#incoming message from remote server‬‬
‫‪if sock == s :‬‬
‫ ‬ ‫‪if runlevel == 0 :‬‬
‫‪ runlevel = 1‬‬
‫;"‪ msg = "action:login\nusername:hello\nsecret:world\r\n\n‬‬
‫)‪ s.send(msg‬‬
‫)‪data = sock.recv(4096‬‬
‫‪if not data :‬‬
‫)(‪sys.exit‬‬
‫‪else :‬‬
‫ ‬ ‫‪#listen data and handle it with threading function‬‬
‫ ‬ ‫))‪t = threading.Thread(target=handler,args=(data,‬‬
‫)‪threads.append(t‬‬
‫ ‬ ‫)(‪t.start‬‬
‫)(‪t.join‬‬
‫‪#user entered a message‬‬
‫‪else :‬‬
‫)(‪msg = sys.stdin.readline‬‬
‫)‪s.send(msg‬‬

‫در ایــن برنامه ابتدا از طریق پروتکل ‪ TCP‬در ســرور یک ارتباط ایجــاد مینماییم تا اطالعات یوزر اکانت‬
‫‪ ،AMI‬برای احراز هویت در استریســک‪ ،‬ارائه شــوند‪ .‬اگر اطالعات درست باشــند‪ ،‬برنامه وارد یک حلقه‬
‫میشــود و دائماً روی این کانکشــنِ ایجاد شــده‪ ،‬در انتظار خواندن رویدادها میمانــد و بهمحض دریافت‬
‫رویدادی جدید‪ ،‬یک ‪ thread‬ایجاد میکند که وظیفهی اصلی آن تحلیل رویداد دریافتشده است و سپس‬
‫کنترل اصلی برنامه مجددا منتظر دریافت رویداد جدید میماند‪ .‬تابع تحلیل رویداد )تابع ‪ (handler‬بهصورت‬
‫»همزمان« شــروع به تحلیل رویدادها و اجرای دســتورات مربوطه میکند‪ .‬در این تابع بر اساس نام رویداد‪،‬‬
‫توابع مربوطه فراخوانی میشوند‪ .‬همانطورکه در برنامه‪ ،‬مشخص )‪ (Bold‬شدهاست‪ ،‬ما رویدادها را براساس‬
‫نامشان تشخیص میدهیم و توابع متفاوتی را فراخوانی میکنیم‪.‬‬
‫در این برنامه رویدادهای زیر بررسی می‌شوند‪.‬‬
‫رویداد ‪ :agentcalled‬زمانی اتفاق می‌افتد که تماس برای یک اپراتور به صف ارسال شود‪.‬‬
‫رویداد ‪ :agentringnoanswer‬زمانی اتفاق‌ می‌افتد که اپراتور تماس را پاسخ ندهد‪.‬‬
‫رویداد ‪ :queuecallerabandon‬زمانی اتفاق می‌افتد که اپراتور تماس خود را رد کند‪.‬‬
‫رویداد ‪ :agentconnect‬زمانی اتفاق می‌افتد که اپراتور تماس خود را پاسخ دهد‪.‬‬
‫‪389‬‬ ‫ابزار مدیریتی استریسک‬

‫رویداد ‪ :agentcomplete‬زمانی اتفاق می‌افتد که اپراتور تماس خود را با موفقیت به پایان رساند‪.‬‬
‫روال اصلی کالسها در زبانهای سطح باال برای کنترل مدیریت استریسک بهوسیله ‪ ،AMI‬به همین صورت‬
‫اســت ولی کار با آنها بسیار آسانتر اســت‪ .‬به عنوان تمرین فرض کنید بخواهیم برنامه باال را با کالسی در‬
‫‪ Python‬بنویسیم‪ .‬در این حالت برنامه بهصورت زیر خواهد بود‪.‬‬
‫* ‪from asterisk.manager import‬‬
‫‪from logger import logger‬‬
‫‪import time‬‬

‫'‪HOST = 'localhost‬‬
‫'‪PORT = '5038‬‬
‫'‪USERNAME = 'hello‬‬
‫'‪SECRET = 'world‬‬
‫)(‪ami = Manager‬‬
‫)‪ami.connect(HOST, PORT‬‬
‫)‪ami.login(USERNAME, SECRET‬‬
‫)‪ami.register_event('agentcalled', event_AgentCalledEvent‬‬
‫)‪ami.register_event('agentringnoanswer', event_AgentRingNoAnswerEvent‬‬
‫)‪ami.register_event('queuecallerabandon', event_QueueCallerAbandonEvent‬‬
‫)‪ami.register_event('agentconnect', event_AgentConnectEvent‬‬
‫)‪ami.register_event('agentcomplete', event_AgentCompleteEvent‬‬
‫‪while true:‬‬
‫‪pass‬‬

‫اینجــا از کالس ‪ asterisk.manager‬در زبــان برنامه نویســی ‪ Python‬اســتفاده کردیم‪ .‬این کالس شــامل‬
‫مجموعــهای از توابع کتابخانهای اســت که به برنامهنویســان اجازه میدهد بتوانند بــه راحتی ازطریق آن به‬
‫استریسک متصل شوند و برنامههای خود را اجرا نمایند‪.‬‬
‫همانطورکه مالحظه میکنید‪ ،‬در این روش کافی است پارامترهای مورد نیاز را بهصورت متغیر تعریف‬
‫کنید‪ .‬ســپس از کالس ‪ Manager‬یک نمونه ایجاد کنید و بهوســیله تابع ‪ connect‬و ‪ login‬به ‪ AMI‬متصل‬
‫شوید‪ .‬در انتها رویدادهای الزم را بهوسیله تابع )(‪ register_event‬مشخص و دستورات الزم را اجرا کنید‪.‬‬
‫همانطورکه مالحظه میکنید در هر دو روش‪ ،‬رویدادهای خاصی درنظر گرفته شد‪ ،‬ولی کار با کالسها‬
‫در برنامهنویســی بســیار سادهتر اســت‪ .‬اکنون چگونه میتوان از این کالسها استفاده کرد‪ .‬برای این منظور‬
‫ابتدا باید بســتههای مورد نیاز را دانلود و نصب کنید‪ .‬برای نصب بسته ‪ pyst‬و استفاده از آن در برنامه نویسی‬
‫‪ Python‬ابتدا آن را از مسیر زیر دانلود کنید‪:‬‬
‫‪#cd /usr/src/‬‬
‫‪#svn co svn://svn.code.sf.net/p/pyst/svn/pyst/trunk pyst‬‬

‫سپس وارد مسیر فایل ‪ pyst‬شوید و آن را نصب کنید‪:‬‬


‫‪#cd pyst‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪390‬‬

‫‪#python setup.py install --prefix=/usr/local‬‬

‫پس از اجرای دســتور فوق‪ ،‬کالس ‪ pyst‬با موفقیت در سیســتم نصب میشود و میتوان با اضافه کردن‬
‫خط زیر در در برنامه ‪ ،Python‬از کالس ‪ pyst‬استفاده نمود‪:‬‬
‫* ‪from asterisk.manager import‬‬

‫استفاده از سایر کالسها در سایر زبانهای برنامهنویسی نیز به همین صورت است که بررسی آنها به خواننده‬
‫واگذار میشود‪.‬‬

‫استفاده از ‪‌Call Files‬ها در استریسک‬


‫‪Callfiles‬های استریســک که از آنها بهعنوان »‪ «Auto Dialer‬یاد میشود‪ ،‬یک شیوه برای ایجاد خودکار‬
‫تماس خروجی در استریسک است‪ .‬با استفاده از این روش میتوان تماسهای خروجی را بهصورت خودکار‬
‫ایجاد و پس از برقراری تماس‪ ،‬برنامه را اجرا نمود‪.‬‬
‫در این روش یک فایل متنی جدید ایجاد میکنیم‪ .‬سپس فایل را باز و پارامترهایی را همراه با مقادیرشان‬
‫در آن تعریف میکنیم‪ .‬ســپس این فایل را در مســیر مشخصشــدهای در استریســک کپی کــرده یا انتقال‬
‫میدهیم‪ .‬به محض کپی شدن این فایل در مسیر‪ ،‬استریسک آن را باز و اجرا میکند‪.‬‬
‫اجراشدن ‪Call Files‬ها در استریسک به دو روش صورت میگیرد‪:‬‬
‫‪ -۱‬استفاده از پارامترهای ‪ Application‬و ‪ Data‬که به کمک دستور خاصی صورت میگیرد‪.‬‬
‫‪ -۲‬اســتفاده از پارامترهــای ‪ Context, Extension, Priority‬کــه در این صورت دســتورات خاص در آن‬
‫کانتکست اجرا میشوند‪.‬‬
‫‪Call Files‬ها برای اجرا شدن در بستر استریسک باید در مسیر زیر کپی شوند‪:‬‬
‫‪/var/spool/asterisk/outgoing/‬‬

‫بعد از اجرای ‪ Call Files‬ها‪ ،‬این فایلها از مسیر حذف )یا آرشیو( میشوند‪.‬‬
‫در استریســک برای اســتفاده از ‪Call Files‬ها باید ماژول ‪ pbx_spool‬فعال باشد‪ .‬برای مشاهده وضعیت‬
‫این ماژول دستور زیر را اجرا کنید‪:‬‬
‫‪Cli > module show like pbx_spool.so‬‬

‫بهعنوان یک تمرین ساده‪ ،‬برای استفاده از ‪Call Files‬های استریسک‪ ،‬ابتدا فایلی با نام ‪ sample.call‬ایجاد و‬
‫موارد زیر را در آن کپی کنید‪ .‬در این مثال از پارامتر ‪ Application‬و ‪ Data‬استفاده میکنیم‪.‬‬

‫‪channel : SIP/Phone_1‬‬
‫‪Application : playback‬‬
‫‪Data : demo_congrats‬‬

‫اینجــا به دنبال این هســتیم که ابتدا با کاربر ‪ Phone_1‬تماس برقرار شــود و بهمحــض برقراری تماس‪ ،‬فایل‬
‫‪391‬‬ ‫ابزار مدیریتی استریسک‬

‫صوتی ‪ demo_congrats‬بهوســیله دستور ‪ Playback‬پخش شــود‪ .‬میتوانید به جای مقدار ‪،SIP/Phone_1‬‬


‫نام یکی از داخلیهای تعریف شده در سیستم خود را جایگزین نمایید‪.‬‬
‫اکنون این فایل را باید در مسیر اجرای ‪Call Files‬ها در استریسک کپی کنید یا انتقال دهید‪.‬‬
‫‪#cp sample.call /var/spool/asterisk/outgoing/‬‬

‫بالفاصلــه پس از اجرای دســتور فوق‪ ،‬داخلی موردنظــر )که در پارامتر ‪ channel‬مقــدار آن را داده بودید(‬
‫شروع به زنگ خوردن میکند‪ .‬چنانچه تماس را پاسخ دهید‪ ،‬فایل صوتی ‪ demo_congrats‬برای شما پخش‬
‫خواهدشد‪.‬‬
‫این تمرین را میتوان به روش دیگری هم نوشت‪ .‬فایل ‪ sample2.call‬را ایجاد کنید و موارد زیر را در‬
‫آن کپی کنید‪.‬‬
‫‪channel : SIP/Phone_1‬‬
‫‪context: callfiles‬‬
‫‪extension:s‬‬
‫‪priority:1‬‬

‫پس از ســاختن فایل باال‪ ،‬باید یک کانتکســت ]‪ [callfiles‬در فایل ‪ extensions.conf‬بهصورت زیر ایجاد‬
‫کنید‪.‬‬
‫]‪[callfiles‬‬
‫)‪exten => s,1,NoOp(Call Files‬‬
‫)‪same => n,Playback(demo-congrats‬‬
‫)(‪same => n,Hangup‬‬

‫ســپس تغییرات را ذخیره و استریســک را ‪ reload‬کنید‪ .‬اکنون به محض کپیشــدن فایل در مسیر مشخص‬
‫شــده‪ ،‬تماس با ‪ SIP/Phone_1‬برقرار میشــود‪ .‬اگر کاربر تماس را پاسخ دهد‪ ،‬اجرای کنترل برنامه به مسیر‬
‫کانتکست میرود و دستورات باال اجرا میشوند‪.‬‬
‫همانطورکــه مالحظــه میکنید‪ ،‬این یک تمرین خیلی ســاده از هر دو روش ایجــاد ‪Call Files‬ها در‬
‫استریسک بهوســیله قابلیت »‪ «Auto Dialer‬است‪ .‬برای ســاختن ‪ Call Files‬ها در استریسک‪ ،‬پارامترهای‬
‫زیادی وجود دارد‪ .‬در زیر این پارامترها شرح داده شدهاند‪:‬‬
‫‪ :Channel‬مقصــد تمــاس خروجی را مشــخص میکند‪ .‬به عبارت دیگر‪ ،‬استریســک ابتــدا تالش میکند‬
‫با مقصد مشــخص شــده تماس برقــرار کند‪ .‬این مقصد میتوانــد هر چیزی )از هر نــوع تکنولوژی از قبیل‬
‫)‪ (SIP,DAHDI,IAX‬باشد‪.‬‬
‫‪ :Context‬زمانی که تماس با مقصد مشــخصی برقرار شــد‪ ،‬اجرای برنامه از جانب این کانتکســت ادامه پیدا‬
‫میکنــد‪ .‬اگر از این پارامتر اســتفاده میکنیــد‪ ،‬باید پارامترهــای ‪ Extension‬و ‪ Priority‬را هم مقدار دهید‪.‬‬
‫‪ Application‬و ‪ Data‬استفاده شود‪ ،‬نباید از پارامتر ‪ Context‬استفاده کنید‪.‬‬ ‫چنانچه از پارامترهای‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪392‬‬

‫‪ :Extension‬مشخص کننده اکستنشن مورد نظر در کانتکست اعالم شده است‪.‬‬


‫‪ :Priority‬مشخص میکند دستورات از کدام اولویت شروع به اجرا شوند‪.‬‬
‫‪ :Application‬نام دستوری است که میخواهیم اجرا شود‪.‬‬
‫‪ :Data‬همزمان با پارامتر ‪ Application‬استفاده میشود و دادههای مورد نیاز برای اجرای خود بهوسیله پارامتر‬
‫‪ Application‬را مشخص میکند‪.‬‬
‫‪ :MaxRetries‬اگر مقصد‪ ،‬به تماس پاســخ ندهد‪ ،‬بهوسیله این پارامتر اعالم میکنیم که استریسک باید چند‬
‫بار اجرای این ‪ Call Files‬را تکرار کند‪.‬‬
‫‪ :RetryTime‬اگر مقصد‪ ،‬به تماس پاســخ ندهد‪ ،‬بهوســیله این پارامتر اعالم میکنیم که استریســک پس از‬
‫گذشت چه مدت )برحسب ثانیه( تکرار را انجام دهد‪.‬‬
‫‪ :WaitTime‬تعیین میکند که برای هر بار تالش‪ ،‬چند ثانیه باید منتظر پاسخ تماس بماند‪.‬‬
‫‪ :CallerID‬بهوسیله این پارامتر‪ ،‬میتوان کالرآیدی تماس خروجی را تنظیم کرد‪.‬‬
‫‪ :Set‬بهوسیله این پارامتر میتوان متغیرهایی را هنگام ساخت ‪ Call Files‬ها ایجاد کرد و هنگام اجرای برنامه‬
‫از آنها استفاده کرد‪.‬‬
‫‪ :Archive‬کلیه ‪‌Call Files‬ها بعد از اجرا باید آرشیو شوند‪ .‬مسیر آرشیو در فایل زیر خواهد بود‪.‬‬
‫‪/var/spool/asterisk/outgoing_done/‬‬

‫برای مثال ‪ Call Files‬زیر را در نظر بگیرید‪:‬‬


‫‪Channel: SIP/TRUNK1/15117671‬‬
‫‪WaitTim: 30‬‬
‫‪callerid: 31770‬‬
‫‪Archive: yes‬‬
‫‪Context: callfiles‬‬
‫‪Extension: 15117671‬‬
‫‪Priority: 1‬‬
‫‪Set: phone=15117671‬‬
‫‪Set: TrunkName=TRUNK1‬‬

‫اکنون چنانچه برنامه زیر را داشته باشیم‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[callfiles‬‬
‫)‪exten => _X.,1,NoOp(Call Files‬‬
‫)}‪same => n,NoOp(Phone=${Phone‬‬
‫)}‪same => n,NoOp(TrunkName=${TrunkName‬‬

‫مالحظه میشود که از متغیرهایی که در ‪ Call Files‬ها تعریف کردهایم‪ ،‬در برنامه ما استفاده شده است‪.‬‬
‫بهعنــوان یک تمرین دیگــر فرض کنید بخواهیم با خارج از مجموعه تمــاس بگیریم و پس از برقراری‬
‫تماس‪ ،‬آن را به اپراتور وصل کنیم‪ .‬میتوان این کار را بهوسیله ‪ Call Files‬ها بهصورت زیر انجام دهیم‪.‬‬
‫‪393‬‬ ‫ابزار مدیریتی استریسک‬

‫ابتدا ‪ Call Files‬با نام ‪ sample3.call‬را بهصورت زیر تعریف میکنیم‪.‬‬


‫>‪Channel : DAHDI/g0/<number‬‬
‫‪MaxRetries :2‬‬
‫‪RetryTime: 60‬‬
‫‪Waittime : 30‬‬
‫‪Context : callfiles‬‬
‫‪Extension : s‬‬
‫‪Priority : 1‬‬

‫اکنون دستور زیر را اجرا میکنیم‪:‬‬


‫‪# sudo cp sample3.call /var/spool/asterisk/outgoing/‬‬

‫بعد از اجرای دستور فوق‪ ،‬استریسک شروع به ایجاد تماس با شماره داده شده از طریق کانالهای مخابراتی‬
‫‪ PSTN‬میکند‪ .‬اگر تماس پاســخ داده شود‪ ،‬کنترل اجرای برنامه به کانتکست ]‪ [Callfiles‬رفته و دستورات‬
‫اجرا میشوند‪.‬‬
‫در فایل ‪ extensions.conf‬چنین مقادیری داریم‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[callfiles‬‬
‫)‪exten => s,1,NoOp(Call Files‬‬
‫)‪same => n, Queue(support‬‬
‫)(‪same => n,hangup‬‬

‫اکنون اگر فرد مورد نظر پس از گذشــت ‪ ۳۰‬ثانیه تماس را پاســخ ندهد‪ ،‬استریســک به مدت ‪ ۶۰‬ثانیه صبر‬
‫میکنــد و دوباره تمــاس ایجاد میکند و این بار هم ‪ ۳۰‬ثانیه منتظر پاســخ فرد مورد نظــر میماند‪ .‬این کار‬
‫بهوسیله استریسک‪ ،‬سهبار )تماس برای بار اول به همراه دو بار تالش مجدد( تکرار میشود‪.‬‬
‫همانطورکه مالحظه میکنید‪ ،‬میتوان بهراحتی از طریق یک پایگاه دادهای‪ ،‬شمارههای مورد نظر را خواند‬
‫و بهوســیله زبان برنامهنویســی ‪ php‬یا ‪ python‬فایلهایی ایجاد کرد و در مســیر مشخص شده کپی نمود‪ .‬در‬
‫این صورت یک برنامه ‪ Auto Dialer‬ساخته میشود که به ازای هر شماره‪ ،‬عملیات برقراری تماس را آغاز‬
‫میکند‪.‬‬
‫نکته مهم در خصوص ‪ Auto Dialer‬ها و ماژول ‪ pbx_spool‬این است که در این ماژولها هیچ کنترلی‬
‫روی تعداد کانالهای دردســترس وجــود ندارد‪ .‬برای مثال چنانچه از یک لینــک ‪ E۱‬که دارای ‪ ۳۰‬کانال‬
‫همزمان اســت‪ ،‬از طریق ‪ auto-diler‬برای تماس اســتفاده کنید‪ ،‬در چنین حالتی نمیتوانید بیش از ‪ ۳۰‬فایل‬
‫در مسیر ‪ /var/spool/asterisk/outgoing‬قرار دهید‪ .‬با توجه به اینکه تعداد کانالهای موجود محدود است‪،‬‬
‫تماسهای اضافی بالفاصله از بین خواهند رفت‪.‬‬
‫البته روش دیگری برای تولید تماس وجود دارد که با ابزار ‪ AMI‬صورت میگیرد‪ .‬دراین روش میتوان‬
‫تماسهایی دقیقاً مانند ‪ Call Files‬ها ایجاد کرد‪ .‬برای تمرین تماســی را با ابزار ‪ AMI‬ایجاد میکنیم‪ .‬برنامه‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪394‬‬

‫زیر را در نظر بگیرید‪:‬‬


‫* ‪from asterisk.manager import‬‬
‫‪import time‬‬

‫'‪HOST = 'localhost‬‬
‫'‪PORT = '5038‬‬

‫'‪USERNAME = 'hello‬‬
‫'‪SECRET = 'world‬‬

‫)(‪ami = Manager‬‬
‫)‪ami.connect(HOST, PORT‬‬
‫)‪ami.login(USERNAME, SECRET‬‬

‫'‪CHANNEL = 'DAHDI/g0/09151176713‬‬
‫'‪EXTEN = 's‬‬
‫'‪CONTEXT = 'callfiles‬‬
‫‪PRIORITY = 1‬‬
‫‪TIMEOUT = 30000‬‬
‫‪CALLERID = 31770‬‬
‫'‪SYNC = 'true‬‬
‫}'‪VARIABLES = {'age': '10‬‬

‫‪ami.originate(CHANNEL, EXTEN, CONTEXT, PRIORITY, TIMEOUT, CALLERID, SYNC,‬‬


‫)‪ACCOUNTCODE, VARIABLES‬‬
‫))(‪print(ami.status‬‬

‫)(‪ami.logoff‬‬
‫)(‪ami.close‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬راه دیگر اســتفاده از ‪ Auto Dialer‬برای برقراری تماس‪ ،‬اســتفاده از ‪AMI‬‬
‫اســت‪ .‬بهوســیله دســتور ‪ originate‬میتوان تماسهایی در استریســک ایجاد کرد‪ .‬برای آشــنا شدن با این‬
‫‪ Action‬دستور زیر را اجرا کنید‪:‬‬
‫‪CLI > manger show command originate‬‬

‫در هر یک از زبانهای برنامهنویسی‪ ،‬کالسهایی برای استفاده و کار با ‪ AMI‬طراحی شدهاند که میتوانید با‬
‫توجه به نیاز خود‪ ،‬از آنها در زبانهای برنامهنویسی استفاده کنید‪ .‬در این کتاب بیشتر روی زبان برنامهنویسی‬
‫‪ Python‬تمرکز میکنیم‪.‬‬

‫نتیجه‌گیری‬
‫ابزار ‪ AMI‬در استریســک یکی از ابزارهای مهم برای مدیریت‪ ،‬کنترل و مانیتورینگ سرورهای استریسکی‬
‫است‪ .‬به کمک این ابزار‪ ،‬میتوان پنلهای مانیتورینگ طراحی کرد‪ .‬بهعنوان مثال ‪ Flash oprator panel‬یا‬
‫‪ FOP‬از جمله پنلهای مدیریتیای است که بهوسیله ‪ AMI‬طراحی شدهاست‪.‬‬
‫فصل چهاردهم‬

‫ابزارهای برنامه‌نویسی‬
‫استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪396‬‬

‫‪1‬‬
‫ابزار‌های برنامه‌نویسی استریسک‬
‫برنامهنویسی در استریســک‪ ،‬مرکز اصلی تصمیمگیری‪ ،‬کنترل و مدیریت تماسهاست‪ .‬هر تماس جدیدی‬
‫که وارد سیســتم تلفنی میشــود‪ ،‬بهوسیله برنامهنویسی در مســیر اجرایی قرار میگیرد‪ .‬از طرف دیگر‪ ،‬کلیه‬
‫تماسهای خروجی هم بهوسیله برنامهنویسی کنترل و مدیریت میشوند‪ .‬نوشتن برخی برنامهها در استریسک‬
‫خیلی ساده است و با چند عبارت محاسباتی و منطقی‪ ،‬میتوان تماسها را کنترل و مدیریت کرد‪ ،‬ولی هدف‬
‫برخی از برنامهها در استریســک‪ ،‬ایجاد برقراری تماس با شخص خاصی نیست‪ ،‬بلکه هدف‪ ،‬اجرای یکسری‬
‫از دستورات محاسباتی و تراکنشها با دیتابیس است‪.‬‬
‫در استریسک دو مفهوم مهم و کاربردی بهنامهای ‪ 2 AA‬و ‪ 3 IVR‬وجود دارد که در ادامه به آنها خواهیم‬
‫پرداخت‪.‬‬

‫مفهوم ‪AA‬‬
‫در اغلب سیستمهای تلفنی‪ ،‬سیستم پاسخگوی خودکار که به همه تماسهای ورودی اجازه میدهد مستقیماً‬
‫به شخص مورد نظر متصل شوند‪ ،‬وجود دارد‪ .‬به عبارت دیگر‪ ،‬یک سیستم پاسخگویی خودکار‪ ،‬این قابلیت‬
‫را فراهم میآورد که بر اساس یک منوی انتخاب‪ ،‬افراد به مقصدهای متفاوتی مرتبط شوند‪ .‬به این سیستم ها‬
‫در اصطالح ‪ AA‬میگویند‪ .‬این مفهوم گاهی به اشتباه ‪ IVR‬نامیده میشود‪ .‬در طراحی منو برای ‪ AA‬معموالً‬
‫از گزینههای مشابه زیر استفاده میشود‪.‬‬
‫‪ -‬برای ارتباط با مدیریت عدد‪...‬؛‬

‫)‪1- Asterisk Gateway Interface (AGI‬‬


‫)‪2- Automatic Attendant (AA‬‬
‫)‪3- Interactive Voice Response (IVR‬‬
397 ‫ابزارهای برنامه‌نویسی استریسک‬

‫؛‬...‫ برای ارتباط با معاونت عدد‬-


‫؛‬...‫ برای ارتباط با بخش فروش عدد‬-
‫؛‬...‫ برای ارتباط با بخش پشتیبانی عدد‬-
‫؛‬...‫ برای ارسال فکس عدد‬-
. ...‫ برای ارتباط با اپراتور عدد‬-
‫ بهعنوان‬.‫ هستند‬AA ‫ از نوع‬،‫در فصل پنجم )برنامهنویســی مقدماتی در استریسک( اکثر مثالهای مطرحشده‬
:‫یک تمرین برنامه زیر را در نظر بگیرید‬
[from-pstn]
exten => start,1,Answer()
same => n,BackGround(welcome)
same => n,WaitExten(5)

exten => 1,1,Dial(SIP/Phone_Secretary1,20)


same => n,Playback(vm-nobodyavail)
same => n,Hangup()

exten => 2,1,Dial(SIP/Phone_Secretary2,20)


same => n,Playback(vm-nobodyavail)
same => n,Hangup()

exten => 3,1,Queue(sales)


same => n,Playback(vm-nobodyavail)
same => n,Hangup()

exten => 4,1,Queue(support)


same => n,Playback(vm-nobodyavail)
same => n,Hangup()

exten => 5,1,Goto(RecvFax,s,1)

exten => 6,1,Dial(SIP/Operator1)


same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => i,1,Playback(pbx-invalid)
same => n,Goto(start,1)

exten => t,1,Playback(vm-goodbye)


same => n,Hangup()

‫ مثال باال یک مثال ساده‬.‫ در هر مورد ارتباط با فردی خاص صورت میگیرد‬،‫همانطورکه مالحظه میکنید‬
.‫ در سیستم تلفنی استریسک است‬AA ‫و معمولی از طراحی‬
‫ چیست؟‬IVR ‫حال ممکن است این سوال مطرح شود که‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪398‬‬

‫مفهوم ‪Interactive Voice Response‬‬


‫معمــوالً در ‪ IVR‬ابتدا یکســری اطالعات از کاربر گرفته میشــود )و یا در برخی موارد بر اســاس شــماره‬
‫کالرآیدی اســت(‪ ،‬ســپس بر اســاس این اطالعات‪ ،‬جســتجوهایی در دیتابیسها و تراکنشهایی صورت‬
‫میگیرد‪ .‬دســت آخر نتیجه عملیات به تماس گیرنده اطالع داده میشــود‪ .‬معموالً طراحی سیستمهای ‪IVR‬‬
‫بسیار پیچیده و پرهزینه است‪.‬‬
‫امروزه با سیســتمهای پرداخت تلفنی قبوض آشنا هســتیم‪ .‬همه این سیستمها دارای ‪IVR‬های پیچیدهای‬
‫هســتند کــه با دیتابیسهای مهــم در ارتباطاند؛ بنابرایــن‪ ،‬در طراحی سیســتمهای ‪ ، IVR‬حفظ اطالعات و‬
‫محرمانه بودن آنها بســیار حائز اهمیت اســت و وجود هرگونه ضعف امنیتی در چنین سیســتمهایی‪ ،‬موجب‬
‫خسارتهای جبرانناپذیری به مجموعه میشود‪.‬‬
‫بهعنــوان یــک نمونه دیگر‪ ،‬امروزه اکثر ما با سیســتمهای نظرســنجی و یا نوبتدهی تلفنی آشــناییم و‬
‫دستکم یک بار با آنها کار کردهایم‪ .‬در بستر همه این سیستمها‪ ،‬یک ‪ IVR‬هوشمند طراحی شده که با شما‬
‫در تعامل است و اطالعات الزم را از شما میگیرد و تراکنشهای الزم را انجام میدهد‪.‬‬
‫از آنجاکه طراحی چنین سیســتمهایی در برنامهنویســی استریســک دشوار اســت و به برنامهای منظم و‬
‫قابلتوسعه منتهی نمیشــود‪ ،‬بهتر است از ابزار قدرتمندی در استریسک بهنام ‪ AGI‬استفاده کنیم‪ .‬همانطور‬
‫که پیشتر نیز بیان شد‪ ،‬در استریسک میتوان به سه روش برنامه نوشت‪:‬‬
‫‪ –۱‬اســتفاده از روش اســتاندارد در فایل ‪) extensions.conf‬در این کتاب بیشتر روی این روش تمرکز شده‬
‫است(‪.‬‬
‫‪ –۲‬استفاده از ‪ AEL1‬در فایل ‪.extensions.ael‬‬
‫‪ –۳‬استفاده از ‪ LUA‬درفایل ‪.extensions.lua‬‬
‫امروزه برنامهنویسان‪ ،‬غالبا از زبانهای سطح باالتر )از قبیل ‪ (PERL, PHP, Python, C#, .NET‬استفاده‬
‫میکنند‪ .‬واضح اســت برای این دسته از برنامهنویســان‪ ،‬کار با این زبانها بسیار راحتتر و لذت بخشتر از‬
‫برنامهنویسی در استریسک است‪.‬‬
‫‪ AGI‬یکــی از ابزارهای قدرتمند استریســک اســت که این قابلیت را به برنامهنویــس میدهد که بتواند‬
‫بهراحتــی اجرا‪ ،‬کنتــرل و مدیریت تماسها را در زبانهای ســطح باال انجام دهد‪ .‬اینکــه از چه زبانی برای‬
‫برنامهنویســی ‪ AGI‬اســتفاده کنیم‪ ،‬به تسلط ما به یک زبان برنامهنویســی مرتبط است‪ .‬برای آشنایی بیشتر با‬
‫برنامهنویسی ‪ ، AGI‬با یک برنامه بسیار ساده کار را شروع میکنیم‪.‬‬
‫بهعنوان یک تمرین‪ ،‬برنامه ساده زیر را در نظر بگیرید‪.‬‬

‫‪1- Asterisk Extention Logic‬‬


399 ‫ابزارهای برنامه‌نویسی استریسک‬

;extensions.conf
[LocalSets]
exten => 500,1,NoOp(hello-world)
same => n,Playback(hello-world)

‫ خود‬AGI ‫ کافی است فایل‬extensions.conf ‫ در فایل‬.‫ ایجاد کنیم‬AGI ‫میخواهیم این برنامه را بهصورت‬
.‫را فراخوانی کنیم تا اجرای دستورات به آن فایل منتقل و دستورات آن اجرا شوند‬
;extensions.conf
[LocalSets]
exten => 500,1,NoOp(hello-world)
same => n,AGI(hello-world.sh)

.‫بیایید برنامه باال را تست کنیم‬


CLI> console dial 500@LocalSets
-- Executing [500@LocalSets:1] NoOp("Console/dsp", "") in new stack
-- Executing [500@LocalSets:2] AGI("Console/dsp", "hello-world.sh") in new stack
[Aug 29 01:17:59] WARNING[60964][C-00000002]: res_agi.c:1851 launch_script: Failed to
execute '/var/lib/asterisk/agi-bin/hello-world.sh': File does not exist.
-- Executing [500@LocalSets:3] Hangup("Console/dsp", "") in new stack
<< Hangup on console >>
CLI>

hello-world. ‫ دنبال فایل‬/var/lib/asterisk/agi-bin/ ‫ استریسک در مســیر‬،‫همانطورکه مالحظه میکنید‬


‫ اکنون باید در مســیر‬.‫ را نمایش میدهد‬WARNING ‫ پیام‬،‫ میگــردد و چون نمیتوانــد آن را پیدا کند‬sh
.‫ را ایجاد کنیم‬hello-world.sh ‫ فایل‬،‫پیشفرض استریسک‬
‫[ تعریف‬directories] ‫ در قســمت‬asterisk.conf ‫مســیر فایلهای پیشفرض در استریســک در فایــل‬
.‫شدهاست‬
;asterisk.conf
[directories]
astetcdir => /etc/asterisk
astmoddir => /usr/lib/asterisk/modules
astvarlibdir => /var/lib/asterisk
astagidir => /var/lib/asterisk/agi-bin
astspooldir => /var/spool/asterisk
astrundir => /var/run/asterisk
astlogdir => /var/log/asterisk
astdatadir => /var/lib/asterisk

:‫ را بهصورت زیر ایجاد کنید‬hello-world.sh ‫فایل‬


#!/bin/bash
# Consume all variables sent by Asterisk
while read VAR && [ -n ${VAR} ] ; do : ; done
# Answer the call.
echo "ANSWER"
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 400

read RESPONSE
# Say the letters of "Hello World"
echo "STREAM FILE hello-world \"\" "
read RESPONSE
exit 0

:‫ دوباره دستور زیر را اجرا میکنیم‬،hello-world.sh ‫بعد از ایجاد کردن فایل‬


CLI> console dial 500@LocalSets
-- Executing [500@LocalSets:1] NoOp("Console/dsp", "") in new stack
-- Executing [500@LocalSets:2] AGI("Console/dsp", "hello-world.sh") in new stack
-- Launched AGI Script /var/lib/asterisk/agi-bin/hello-world.sh
hello-world.sh: Failed to execute '/var/lib/asterisk/agi-bin/hello-world.sh': Permission denied
[Aug 29 01:28:38] WARNING[61044][C-00000006]: res_agi.c:3933 run_agi: unable to send
SIGHUP to AGI process 61045: No such process
-- Executing [500@LocalSets:3] Hangup("Console/dsp", "") in new stack
CLI>

hello-world.sh ‫ به دلیل دردسترس نبودن مجوز الزم برای اجرای فایل‬، WARNING ‫این بار نمایش پیام‬
.‫ این فایلها مجوزهای الزم را داشته باشند‬، AGI ‫ باید پیش از استفاده از فایلهای‬،‫ بنابراین‬.‫است‬
.‫دستور زیر را برای تغییر سطح دسترسی و مجوز دادن به فایلها در لینوکس اجرا کنید‬
#chmod 655 /var/lib/asterisk/agi-bin/hello-world.sh

‫ میتوانید هر مجوزی را‬.‫ دادهایم‬hello-world.sh ‫ما اینجا حداقل مجوز الزم برای اجرا شدن را به فایل‬
.‫ برای مثال با دستور زیر مجوز کامل به این فایل میدهیم‬.‫ در نظر بگیرید‬،‫که مطلوب بدانید‬
#chmod 777 /var/lib/asterisk/agi-bin/hello-world.sh

.‫ با موفقیت اجرا خواهد شد‬hello-world.sh ‫ فایل‬،‫اکنون اگر دوباره دستور زیر را اجرا کنید‬
CLI> console dial 500@LocalSets
-- Executing [500@LocalSets:1] NoOp("Console/dsp", "") in new stack
-- Executing [500@LocalSets:2] AGI("Console/dsp", "hello-world.sh") in new stack
-- Launched AGI Script /var/lib/asterisk/agi-bin/hello-world.sh
-- <Console/dsp> Playing 'hello-world.gsm' (escape_digits=) (sample_offset 0) (language
'en')
-- <Console/dsp>AGI Script hello-world.sh completed, returning 0
-- Executing [500@LocalSets:3] Hangup("Console/dsp", "") in new stack
<< Hangup on console >>
CLI>

‫ نکته مهم در خصوص‬.‫ استفاده کردیم‬AGI ‫ برای ساختن فایل‬۱‫در این مثال ما از زبان برنامهنویسی لینوکس‬
‫ دارد که باید از‬AGI ‫ این است که استریسک یکسری دستورات مهم برای برنامهنویسی‬AGI ‫برنامهنویســی‬
‫ کمی دشوار‬AGI ‫ این گونه استفاده از دستورات‬،‫ همانطور که در مثال باال مشاهده کردید‬.‫آنها استفاده کرد‬

1- Shell Script
‫‪401‬‬ ‫ابزارهای برنامه‌نویسی استریسک‬

‫اســت‪ .‬در اکثر زبانهای برنامهنویسی سطح باال‪ ،‬برای اســتفاده از دستورات ‪ ،AGI‬کالسی طراحی شده که‬
‫میتوانید با استفاده از آن‪ ،‬کدهای خواناتری ایجاد کنید‪.‬‬
‫بهعنوان تمرین فرض کنید بخواهیم تمرین قبلی را دوباره با زبان ‪ php‬بنویســیم‪ .‬در این صورت باید از‬
‫کالس ‪ PHPAGI‬اســتفاده کنیم‪ .‬در واقع این کالس از همان دســتورات مثال قبلی استفاده میکند ولی کار‬
‫با آن برای ما راحتتر است‪.‬‬
‫در این تمرین فرض کنید فایل ‪ hello-world.php‬زیر را داشته باشیم‪:‬‬
‫‪;hello-world.php‬‬
‫‪#!/usr/bin/php -q‬‬
‫‪<?php‬‬
‫;)'‪require_once('phpagi.php‬‬
‫;)‪error_reporting(E_ALL‬‬

‫;)(‪$agi = new AGI‬‬


‫;)(‪$agi->answer‬‬
‫;)"‪$agi->stream_file("hello-world", "#‬‬
‫;)(‪$agi->hangup‬‬
‫>?‬

‫همانطور که مالحظه میکنید‪ ،‬ابتدا فایل ‪ phpagi.php‬را که حاوی کالس برای استفاده از دستورات ‪AGI‬‬
‫در زبان برنامهنویسی ‪ PHP‬است‪ ،‬در برنامه خود استفاده نمودیم‪ .‬ابتدا دو فایل زیر را در مسیر فایلهای ‪AGI‬‬
‫قرار میدهیم‪ .‬این فایلها را میتوانید از اینترنت دانلود و یا از یک سرور الستیکس کپی کنید‪:‬‬
‫‪• phpagi.php‬‬
‫‪• phpagi-asmanager.php‬‬

‫سپس یک نمونه از کالس ‪ AGI‬میسازیم و بهوسیله تابع ‪ ، stream_file‬یک فایل صوتی مشخص را پخش‬
‫میکنیم‪ .‬برای تست برنامه ‪ AGI‬در محیط لینوکس‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫‪#php /var/lib/asterisk/agi-bin/hello-world.php‬‬

‫در پاسخ به اجرای برنامه ممکن است این خروجی را ببینید‪:‬‬


‫‪The program 'php' is currently not installed. You can install it by typing:‬‬
‫‪apt-get install php5-cli‬‬

‫این پیام نشان میدهد که باید ابزار مورد نیاز برای اجرای دستور را قبال کرده باشید‪ .‬برای نصب آن‪ ،‬دستور‬
‫زیر را اجرا کنید‪.‬‬
‫‪# apt-get install php5-cli‬‬

‫پس از نصب‪ ،‬دستور قبلی را مجددا ً اجرا نمایید‪.‬‬


‫‪# php /var/lib/asterisk/agi-bin/hello-world.php‬‬
‫‪ANSWER‬‬
‫‪STREAM FILE hello-world "#" 0‬‬
‫‪HANGUP‬‬

‫برنامه ‪ AGI‬شــروع به اجرا میکند‪ .‬اینجا منظور از اجرا شــدن‪ ،‬اجرای خط به خط دســتورات اســت‪ .‬ابتدا‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪402‬‬

‫تماس ‪ Answer‬میشــود و سپس دستور ‪ Stream File‬اجرا میشود‪ .‬با اینکار از صحت برنامه خود مطمئن‬
‫میشوید‪ .‬حال میخواهیم از این فایل ‪ AGI‬در برنامه خود استفاده کنیم‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 500,1,NoOp(hello-world‬‬
‫)‪same => n,AGI(hello-world.php‬‬

‫اگر از طریق یک داخلی‪ ،‬شماره ‪ ۵۰۰‬را شمارهگیری کنید‪ ،‬متوجه پخش فایل صوتی خواهید شد‪.‬‬
‫>‪CLI‬‬
‫‪-- Executing [500@LocalSets:1] NoOp("SIP/100-00000022", "") in new stack‬‬
‫‪-- Executing [500@LocalSets:2] AGI("SIP/100-00000022", "hello-world.php") in new stack‬‬
‫‪-- Launched AGI Script /var/lib/asterisk/agi-bin/hello-world.php‬‬
‫)‪-- <SIP/100-00000022> Playing 'hello-world.gsm' (escape_digits=#) (sample_offset 0‬‬
‫)'‪(language 'en‬‬
‫‪-- <SIP/100-00000022>AGI Script hello-world.php completed, returning 4‬‬
‫'‪== Spawn extension (LocalSets, 500, 2) exited non-zero on 'SIP/100-00000022‬‬
‫>‪CLI‬‬

‫تــا اینجــا ما به ســاختن یک فایل ‪ AGI‬ســاده پرداختیــم و مهمترین دســتورات قابل اســتفاده در ‪ AGI‬را‬
‫معرفینمودیم‪ .‬اکنون به این موضوع میپردازیم که چگونه یک فایل ‪ AGI‬فراخوانی میشود و کار میکند‪.‬‬

‫یک فایل ‪ AGI‬چگونه کار می‌کند‬


‫استریسک بهوسیله ابزار قدرتمند ‪ ، AGI‬این توانایی را ایجاد میکند که برنامهنویسان بتوانند به واسطهی آن‪،‬‬
‫ساختارهای ‪ IVR‬پیچیدهای طراحی کنند‪ .‬سؤالی که اینجا مطرح میشود این است که استریسک چگونه با‬
‫یک فایل ‪ AGI‬ارتباط برقرار میکند و اطالعات بین استریسک و فایل ‪ AGI‬چگونه منتقل میشوند؟‬
‫برای درک بهتر این موضوع‪ ،‬شکل ‪ ۱-۱4‬را ببینید‪.‬‬

‫شکل ‪1-14‬‬
‫‪403‬‬ ‫ابزارهای برنامه‌نویسی استریسک‬

‫همانطورکه مالحظه میکنید این ارتباط بهوســیله جریانهای دادهای‪) ۱‬هر دادهای که از طرف استریســک‬
‫بهسمت فایل ‪ AGI‬وارد شود بهصورت جریانهای داده ورودی و هر دادهای که از طرف فایل ‪ AGI‬به طرف‬
‫استریســک ارسال شــود بهصورت جریان دادهای خروجی( معرفی میشــوند‪ .‬ایدهی استفاده از جریانهای‬
‫دادهای ‪ stdin/stdout‬در برنامههای کاربردی‪ ،‬یک تکنولوژی قدیمی محســوب میشود‪ .‬بهعنوان مثال حتی‬
‫در زبانهای برنامه نویســی ‪ c‬یــا ‪ ،c#‬از جریانهای دادهای ‪ stdin/stdout‬ازطریق توابع کتابخانهای اســتفاده‬
‫میشود‪.‬‬

‫جریان‌های اجرایی فایل‌های ‪AGI‬‬


‫هنگام اجرای یک فایل ‪ ،AGI‬یک جریان بین استریسک و فایل ‪ AGI‬برقرار میشود‪ .‬شکل ‪ ۲-۱4‬مراحل و‬
‫ترتیب اجرای دستورات را نشان میدهد‪:‬‬

‫شکل ‪2-14‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬مراحل )‪ (۳-۲-۱‬در فایل ‪ AGI‬برای برقراری ارتباط بین استریســک و‬
‫فایل ‪ AGI‬انجام میشوند‪ .‬در مراحل ‪ 4‬و ‪ ، ۵‬ارتباط بین استریسک و فایل ‪ AGI‬برقرار شده و اطالعات الزم‬
‫برای تبادل بین این دو‪ ،‬ازطریق ‪ stdin/stdout‬فراهم میشــود‪ .‬مراحل ‪ ۶‬و ‪ 7‬برای پایان تماس و بازگشــت‬
‫کنترل اجرای برنامه به استریسک انجام میشود‪.‬‬

‫دستورات ‪AGI‬‬
‫بهوسیله دستور زیر میتوان لیست همه دستورات ‪ AGI‬را با توضیحات مربوطه مشاهده نمود‪:‬‬
‫‪CLI> agi show commands‬‬

‫جدول ‪ ۱-۱4‬لیست کاملی از دستورات ‪ AGI‬را نشان میدهد‪ .‬به کمک این دستورات و با استفاده از واسط‬
‫‪ ،AGI‬برنامهنویسان میتوانند برنامههای خود را اجرا نمایند‪.‬‬

‫)‪1- Standard Input/Output (stdin/stdout‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 404

AGI Command Description


ANSWER Answer the incoming call
ASYNCAGI BREAK End an async AGI session and have the channel return to the Asterisk dialplan.
CHANNEL STATUS Retrieve the status of the channel. This is used to retrieve the current state of the
channel,
such as up (answered), down (hung up), or ringing.
DATABASE DEL Delete a key/value pair from the built-in AstDB
DATABASE DELTREE Delete a tree of key/value pairs from the built-in AstDB
DATABASE GET Retrieve the value for a key in the AstDB.
DATABASE PUT Set the value for a key in the AstDB
EXEC Execute an Asterisk dialplan application on the channel. This command is very
powerful in
that between EXEC and GET FULL VARIABLE, you can do anything with the call that
you can do from the Asterisk dialplan.
GET DATA Read digits from the caller.
GET FULL VARIABLE Evaluate an Asterisk dialplan expression. You can send a string that contains variables
and/or dialplan functions, and Asterisk will return the result after making the
appropriate
substitutions. This command is very powerful in that between EXEC and GET FULL
VARIABLE, you can do anything with the call that you can do from the Asterisk
dialplan.
GET OPTION Stream a sound file while waiting for a digit from the caller. This is similar to the Back
ground() dialplan application
GET VARIABLE Retrieve the value of a channel variable.
HANGUP Hang up the channel.
NOOP Do nothing. You will get a result response from this command, just like any other. It
can be
used as a simple test of the communication path with Asterisk
RECEIVE CHAR Receive a single character. This only works for channel types that support it, such as
IAX2
using TEXT frames or SIP using the MESSAGE method
RECEIVE TEXT Receive a text message. This only works in the same cases as RECEIVE CHAR
RECORD FILE Record the audio from the caller to a file. This is a blocking operation similar to the Re
cord() dialplan application. To record a call in the background while you perform other
operations, use EXEC Monitor or EXEC MixMonitor
SAY ALPHA Say a string of characters. You can find an example of this in “Quick Start” on page
583. To
get localized handling of this and the other SAY commands, set the channel language
either in the device configuration file (e.g., sip.conf) or in the dialplan, by setting the
CHAN
NEL(language) dialplan function
SAY DIGITS Say a string of digits. For example, 100 would be said as “one zero zero” if the
channel’s
language is set to English.
SAY NUMBER Say a number. For example, 100 would be said as “one hundred” if the channel’s
language is set to English
SAY PHONETIC Say a string of characters, but use a common word for each letter (Alpha, Bravo,
Charlie…).
SAY DATE Say a given date.
405 ‫ابزارهای برنامه‌نویسی استریسک‬

AGI Command Description


SAY TIME Say a given time.
SAY DATETIME Say a given date and time using a specified format.
SEND IMAGE Send an image to a channel. IAX2 supports this, but there are no actively developed
IAX2
clients that support it that we know of
SEND TEXT Send text to a channel that supports it. This can be used with SIP and IAX2 channels,
at
least.
SET AUTOHANGUP Schedule the channel to be hung up at a specified point in time in the future.
SET CALLERID Set the caller ID name and number on the channel
SET CONTEXT Set the current dialplan context on the channel
SET EXTENSION Set the current dialplan extension on the channel.
SET MUSIC Start or stop music on hold on the channel
SET PRIORITY Set the current dialplan priority on the channel
SET VARIABLE Set a channel variable to a given value
STREAM FILE Stream the contents of a file to a channel
CONTROL STREAM FILE Stream the contents of a file to a channel, but also allow the channel to control the
stream.
For example, the channel can pause, rewind, or fast-forward the stream.
TDD MODE Toggle the TDD (Telecommunications Device for the Deaf) mode on the channel.
VERBOSE Send a message to the verbose logger channel. Verbose messages show up on the
Asterisk console if the verbose setting is high enough. Verbose messages will also go
to any logfile that has been configured for the verbose logger channel in /etc/asterisk/
logger.conf
WAIT FOR DIGIT Wait for the caller to press a digit
SPEECH CREATE Initialize speech recognition. This must be done before using other speech AGI
commands.
SPEECH SET Set a speech engine setting. The settings that are available are specific to the speech
recognition engine in use.
SPEECH DESTROY Destroy resources that were allocated for doing speech recognition. This command
should
be the last speech command executed.
SPEECH LOAD GRAMMAR Load a grammar
SPEECH UNLOAD GRAMMAR Unload a grammar
SPEECH ACTIVATE GRAMMAR Activate a grammar that has been loaded.
SPEECH DEACTIVATE GRAMMAR Deactivate a grammar
SPEECH RECOGNIZE Play a prompt and perform speech recognition, as well as wait for digits to be pressed.
GOSUB Execute a dialplan subroutine. This will perform in the same way as the GoSub()
dialplan
application.

1-14 ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪406‬‬

‫انواع روش‌های فراخوانی فایل‌های ‪AGI‬‬


‫در استریســک میتوان از روشهای متعددی برای فراخوانی ‪ AGI‬استفاده کرد‪ .‬در هر روش‪ ،‬استریسک به‬
‫شیوههای متفاوتی‪ ،‬با فایل ‪ AGI‬ارتباط برقرار میکند و دادهها را انتقال میدهد‪.‬‬
‫برای مثال در روش پیشین )روش فراخوانی فایل ‪ ،(AGI‬ارتباط ازطریق جریانهای دادهای ‪stdin/stdout‬‬
‫برقرار شد‪ .‬از روشهای دیگری مانند روش ‪ Process Base‬نیز میتوان برای برقراری ارتباط بین استریسک‬
‫و فایلهای ‪ AGI‬استفاده کرد که در ادامه بررسی میشوند‪.‬‬

‫استفاده از دستور ‪ AGI‬در استریسک‬


‫فراخوانی یک فایل ‪ AGI‬با این دســتور‪ ،‬یکی از ســادهترین روشهاســت‪ .‬در ایــن روش با فراخوانی فایل‬
‫‪ ،AGI‬کنترل اجرای دســتورات به فایل مورد نظر منتقل میشود‪ .‬درصورت لزوم‪ ،‬ضمن فراخوانی‪ ،‬مقادیری‬
‫را میتــوان بهصورت پارامتر برای فایل ‪ AGI‬ارســال کرد که در این صــورت از فرمت زیر برای فراخوانی‬
‫استفاده میشود‪:‬‬
‫)]]]‪AGI(command[,arg1[,arg2[,...‬‬

‫نکته مهم‪ :‬هنگام فراخوانی‪ ،‬فایلها باید مجوزهای الزم برای اجرا را داشتهباشند‪.‬‬

‫استفاده از ‪ Dead AGI‬در استریسک‬


‫در نسخههای اولیه استریسک‪ ،‬گاهی الزم میشد در کانالهای غیرفعال‪ ،۱‬دستوراتی اجرا و یا حتی فایلهای‬
‫‪ AGI‬فراخوانی شوند‪ .‬به این منظور از دستور ‪ Dead AGI‬استفاده میشد‪ .‬در ورژنهای جدیدتر استریسک‪،‬‬
‫اســتفاده از این دستور کمتر توصیه میشــود؛ در عوض میتوان از دستور ‪ AGI‬برای اجرا کردن فایل ‪AGI‬‬
‫در کانالهای غیرفعال اســتفاده نمود‪ .‬در استریسک بهوسیله اکستنشن ‪ ،h‬میتوان جریان کانالهای غیرفعال‬
‫را کنترل نمود‪.‬‬
‫بهعنوان تمرین فرض کنید برنامه زیر را داشتهباشیم‪:‬‬
‫]‪[from-pstn‬‬
‫)‪exten=> _X.,1,NoOp(incoming call‬‬
‫)‪same => n,AGI(incoming.py‬‬

‫)‪exten => h,1,NoOp(hangup call‬‬


‫)‪same=> n,AGI(hangup.py‬‬

‫همانطورکه مالحظه میکنید‪ ،‬هنگام قطع تماس‪ ،‬کنترل اجرای دستورات به اکستنشن ‪ h‬منتقل و دستورات‬
‫آنجا اجرا میشــود‪ .‬بــرای فایلهای ‪ AGI‬که در کانالهای فیزیکی غیرفعال فراخوانی میشــوند‪ ،‬باید دقت‬

‫‪1- Inactive Channels‬‬


‫‪407‬‬ ‫ابزارهای برنامه‌نویسی استریسک‬

‫شــودکه کانال‪ ،‬دوباره ‪ Answer‬نشــود‪ ،‬بلکه در این نوع از فایلها‪ ،‬باید دستورات مورد نیاز و گزارشهای‬
‫الزم‪ ،‬استخراج شوند و تماس فورا قطع گردد‪.‬‬
‫فراخوانی فایلهای ‪ AGI‬و ارتباط با آن‪ ،‬ازطریق جریانهای دادهای ‪ stdin/stdout‬بســیار ســاده اســت؛‬
‫ولی به ازای هربار فراخوانی‪ ،‬یک پروســهی جدید ازسوی سرور ایجاد میشود‪ .‬اجرای این روش فراخوانیِ‬
‫فایلهای ‪ AGI‬در حجمهای باالی تماس‪ ،‬میتواند به افت کارایی سیستم تلفنی استریسک منتهی شود‪ .‬برای‬
‫جلوگیری از بروز چنین مشکالتی باید از ‪ FastAGI‬استفاده کرد‪.‬‬

‫استفاده از ‪ FastAGI‬در استریسک‬


‫اســتفاده از روش ِمبتنی بر پردازش‪ ۱‬در استریســک‪ ،‬یکی دیگر از روشهای فراخوانی فایلهای ‪ AGI‬است‪.‬‬
‫دراین روش بین استریسک و فایل ‪ ،AGI‬یک ارتباط در بستر پروتکل ‪ TCP‬ایجاد میشود و چنانچه دادهای‬
‫مورد نیاز باشد ازطریق این بستر منتقل میشود‪.‬‬
‫امتیاز این روش در این است که بین دو پروسه )استریسک و فایل ‪ (AGI‬ارتباط برقرار میشود و بهازای‬
‫هر بار فراخوانی فایل ‪ ،AGI‬پروســهی جدیدی ایجاد نخواهد شــد و بنابراین سرعت اجرای برنامه و کارایی‬
‫سیستم افزایش پیدا میکند‪.‬‬
‫برای فراخوانی فایل ‪ FastAGI‬به یکی از صورت های زیر عمل کنید‪:‬‬
‫)‪exten => 1234,1,AGI(agi://127.0.0.1:4574‬‬
‫)‪exten => 1234,1,FastAgi(127.0.0.1:4574‬‬

‫پورت پیشفرض در این روش‪ ،‬پورت ‪ 4۵74‬اســت‪ .‬در این روش میتوان ازهر پورت دلخواهی اســتفاده‬
‫نمود‪ .‬همانند فراخوانی فایل ‪ AGI‬بهوسیله دستور ‪ AGI‬میتوان پارامترهایی در زمان فراخوانی‪ ،‬به سوی فایل‬
‫‪ FastAGI‬ارسال کرد‪.‬‬
‫فرمت زیر نحوه ارسال پارامترها را نشان میدهد‪:‬‬
‫)‪exten => 1234,1,AGI(agi://127.0.0.1,arg1,arg2,….‬‬

‫نکتــه مهــم دیگر در این روش این اســت کــه میتوان از یک ســرور دیگر برای راه انــدازی فایل ‪ AGI‬و‬
‫فراخوانی آن بهوســیله استریسک استفاده کرد‪ .‬همچنین میتوان با بهرهگیری از ‪ 2 DNS‬بهجای ‪ ،IP‬افزایش‬
‫کارایی سیستم تلفنی را نتیجه گرفت‪.‬‬
‫از جمله مزایای استفاده از ‪ DNS‬به جای ‪ IP‬میتوان به موارد زیر اشاره کرد‪:‬‬
‫‪ – ۱‬اختصاص چندین آیپی به یک ‪.DNS‬‬
‫‪ – ۲‬افزایش ‪ HA‬برای سرویس اجرا شده بهوسیله فایل ‪. AGI‬‬
‫‪ – ۳‬اجرای سرویس فایل ‪ FastAGI‬روی سرورهای مختلف و ایجاد یک ‪ loadbalancing‬در سطح ‪. DNS‬‬

‫‪1- Process Base‬‬


‫‪2- Domain Name Server‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 408

:‫ به یکی از صورت های زیر است‬، IP ‫ بهجای‬DNS ‫ از طریق‬FastAGI ‫شیوه فراخوانی فایل‬
exten => 1234,1,AGI(hagi://localhost)
exten => 1234,1,FastAGI(Mydomain.com)

FastAGI ‫نمونه‌ای از برنامه‌نویسی‬


‫ در این برنامه ما از ماژول‬،‫ برای نمونه‬.‫ میتوان از کالسهای متعددی استفاده کرد‬FastAGI ‫در برنامهنویسی‬
.‫ ابتدا آن را از آدرس زیر دانلود کنید‬pystrisx ‫ برای نصب ماژول‬.‫ استفاده میکنیم‬pystrisx
https://github.com/flan/pystrix

‫ برای نصب آن وارد‬.‫ روی سیســتم شما نصب شده باشد‬Python2.7 ‫ باید نســخه‬،‫پیش از نصب این ماژول‬
‫ خروجی آن بهصورت زیر‬،‫ درصورت نصب موفق ماژول‬.‫ شــوید و دســتور زیر را اجرا کنید‬pystrix ‫فولدر‬
.‫خواهد بود‬
#cd /usr/src/pystrix/
# python2.7 setup.py install
running install
running build
running build_py
running install_lib
running install_egg_info
Writing /usr/local/lib/python2.7/dist-packages/pystrix-0.9.7.egg-info

‫ برای اســتفاده از آنها ابتدا از مســیر زیر‬.‫ وجود دارد‬FastAGI ‫ نمونه مثالهایی از‬،pystrix ‫در فولدر اصلی‬
.‫ را در مسیر دیگری کپی کنید‬fastagi.rst ‫فایل‬
# cp /usr/src/pystrix/doc/examples/fastagi.rst /root/fastagi.py

.‫ شدهاند‬Bold ‫ پارامترهای مهم برنامه‬.‫ را باز و تغییرات زیر را اعمال کنید‬fastagi.py ‫سپس فایل‬
import re
import threading
import time
import pystrix

class FastAGIServer(threading.Thread):
"""
A simple thread that runs a FastAGI server forever.
"""
_fagi_server = None #The FastAGI server controlled by this thread

def __init__(self):
threading.Thread.__init__(self)
self.daemon = True

self._fagi_server = pystrix.agi.FastAGIServer()
409 ‫ابزارهای برنامه‌نویسی استریسک‬

self._fagi_server.register_script_handler(re.compile('incoming'), self._demo_handler)

def _demo_handler(self, agi, args, kwargs, match, path):


agi.execute(pystrix.agi.core.Answer()) #Answer the call

response = agi.execute(pystrix.agi.core.StreamFile('hello-world', escape_digits=(''))


if response:
(dtmf_character, offset) = response #The key pressed by the user and the playback
time

agi.execute(pystrix.agi.core.Hangup()) #Hang up the call

def kill(self):
self._fagi_server.shutdown()

def run(self):
self._fagi_server.serve_forever()

if __name__ == '__main__':
fastagi_core = FastAGIServer()
fastagi_core.start()

while fastagi_core.is_alive():
time.sleep(1)
fastagi_core.kill()

:‫فراخوانی این فایل بهصورت زیر است‬


exten => 500,1,NoOp(Calling FastAgi)
same => n,AGI(agi://127.0.0.1:4573/incoming)

AGI ‫ هنگام فراخوانی یک فایل‬AGI ‫انواع متغیر‌های‬


‫ یک ســری متغیرهای محلی‬،‫ در شــروع ایجاد نشســت در استریســک‬،AGI ‫هنــگام فراخوانــی یک فایل‬
‫ فهرست این متغیرها در‬.‫ میتوان دسترســی کاملی به این متغیرها داشت‬AGI ‫ در فایل‬.‫مقداردهی میشــوند‬
.‫ آورده شده است‬۲-۱4 ‫جدول‬

Variable Value/Example Description


agi_request hello-world.sh The first argument that was passed to the AGI() or
EA GI() application. For process-based AGI, this
is the name of
the AGI application that has been executed. For
FastAGI, this would be the URL that was used to
reach the FastAGI server.
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 410

Variable Value/Example Description


agi_channel SIP/0004F2060EB4-00000009 The name of the channel that has executed the
AGI() or EAGI() application.
agi_language en The language set on agi_channel.
agi_type SIP The channel type for agi_channel.
agi_uniqueid 1284382003.9 The uniqueid of agi_channel.
agi_version 1.8.0.beta4 The Asterisk version in use.
agi_callerid 12565551212 The full caller ID string that is set on agi_channel.
agi_callerid name Russel Bryant The caller ID name that is set on agi_channel.
agi_callingpres 0 The caller presentation associated with the caller
ID set on agi_channel. For more information, see
the output of core show function CALLERPRES at
the Asterisk CLI.
agi_callingani2 0 The caller ANI2 associated with agi_channel.
agi_callington 0 The caller ID TON (Type of Number) associated
with agi_channel.
agi_callingtons 0 The dialed number TNS (Transit Network Select)
associated with agi_channel.
agi_dnid 7010 The dialed number associated with agi_channel.
agi_rdnis unknown The redirecting number associated with agi_
channel.
agi_context phones The context of the dialplan that agi_channel was in
when it executed the AGI() or EAGI() application.
agi_extension 500 The extension in the dialplan that agi_channel
was executing when it ran the AGI() or EAGI()
application.
agi_priority 1 The priority of agi_extension in agi_context that
executed AGI() or EAGI().
agi_enhanced 0.0 An indication of whether AGI() or EAGI() was used
from the dialplan. 0.0 indicates that AGI() was
used. 1.0
indicates that EAGI() was used.
agi_accountcode myaccount The accountcode associated with agi_channel.
2-14 ‫جدول‬

‫ میتوان همه‬،AGI ‫ هنگام فراخوانیِ یک فایل‬،‫اگر در محیط کامندالین استریسک دستور زیر را اجرا کنید‬
:‫متغیرها را به همراه مقادیرشان مشاهده کرد‬
CLI> AGI set debug on

‫ استفاده‬AGI ‫ میتوان از هر زبان برنامهنویسیای برای ایجاد فایلهای‬،‫همانطورکه پیشتر نیز اشاره شد‬
،‫ در زبانهای برنامهنویســی مختلف‬framework ‫ برای مثال فهرســت کالسهای تعریف شــده بــرای‬.‫کرد‬
:‫ آورده شدهاست‬۳-۱4 ‫درجدول‬
411 ‫ابزارهای برنامه‌نویسی استریسک‬

Framework Language URL


Adhearsion Ruby http://adhearsion.com/
Asterisk-JAVA Java http://asterisk-java.org/
Asterisk-perl Perl http://asterisk.gnuinter.net/
PHPAGI PHP http://phpagi.sourceforge.net/
StarPy Python http://starpy.sourceforge.net/
3-14 ‫جدول‬

‫ این برنامه به‬.‫ را در یک برنامه نوبتدهی اینترنتی بررسی میکنیم‬AGI ‫ بخشی از فایل‬،‫بهعنوان یک تمرین‬
‫ در این برنامه هر فرد میتواند انتخاب کند که آیا مایل است از مشاورهی تلفنی‬.‫ نوشته شده است‬PHP ‫زبان‬
‫ این برنامه بیشتر‬.‫ شــدهاند‬Bold ‫ پارامترهای مهم‬AGI ‫ در برنامه‬.‫اســتفاده کند یا از سیســتم نوبتدهی تلفنی‬
.‫جنبه آموزشی دارد و برای اهداف کاربردی طراحی نشده است‬
#!/usr/bin/php -q
<?php
set_time_limit(30);
require('phpagi.php');
error_reporting(E_ALL);

$agi = CreateAGI();
WelcomeToHospital($agi);
return;
?>

<?php
function CreateAGI()
{
$agi = new AGI();
$agi->answer();
return $agi;
}
function WelcomeToHospital($agi)
{
$maxtry = 3;
$loop = 0;
do{
$agi->stream_file("record/welcometohospitalannounce");
$choose = $agi->get_data('record/chooseconsultorreservationannoun
ce', 5000, 1);
if (is_numeric($choose['result'])) {
if($choose['result'] == 1){
$result = ConsultWithDoctor($agi);
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 412

if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 2){
$result = ChooseDoctor($agi);
if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 0){
$loop = 3;
break;
}else{
$loop++;
}
} else {
$loop++;
}
}while($loop < $maxtry);
$agi->stream_file("record/thank");
return;
}
function ConsultWithDoctor($agi)
{
$maxtry = 3;
$loop = 0;
do{
$choose = $agi->get_data('record/counsultwithdoctorannounce', 5000,
1);
if (is_numeric($choose['result'])) {
if($choose['result'] == 1){
$agi->stream_file("record/waiting");
$agi->exec_dial("SIP/annoucement2","09151176713");
$loop = 3;
} elseif($choose['result'] == 9){
$loop = 3;
return 9;
} else{
$loop++;
}
} else {
$loop++;
}
}while($loop < $maxtry);
413 ‫ابزارهای برنامه‌نویسی استریسک‬

return 0;
}
function ChooseDoctor($agi)
{
$maxtry = 3;
$loop = 0;
do{
$choose = $agi->get_data('record/choosedoctorannounce', 5000, 1);
$doctorId = $choose['result'];
if (is_numeric($choose['result'])) {
if($choose['result'] == 1){
//Doctor 1
$result = Reservation($agi,$doctorId);
if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 2){
//Doctor 2
$result = Reservation($agi,$doctorId);
if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 3){
//Doctor 3
$result = Reservation($agi,$doctorId);
if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 4){
//Doctor 4
$result = Reservation($agi,$doctorId);
if($result == 9)
$loop = 0;
else
$loop = 3;
} elseif($choose['result'] == 5){
//Doctor 5
$result = Reservation($agi,$doctorId);
if($result == 9)
$loop = 0;
else
$loop = 3;
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪414‬‬

‫ ‬ ‫{)‪} elseif($choose['result'] == 9‬‬


‫‪ //return to main menu‬‬
‫;‪ $loop = 3‬‬
‫;‪ return 9‬‬
‫{‪ } else‬‬
‫‪ //Callback again‬‬
‫;‪ $loop++‬‬
‫} ‬
‫ ‬ ‫{ ‪} else‬‬
‫ ;‪ $loop++‬‬
‫} ‬
‫;)‪}while($loop < $maxtry‬‬
‫;‪return‬‬
‫}‬

‫در فصل قبل‪ ،‬از کالس ‪ pyst‬برای ارتباط استریســک با ‪ AMI‬اســتفاده شــد‪ .‬اینجا نیز از همان کالس برای‬
‫ساخت فایلهای ‪ AGI‬استفاده میشود‪ .‬به عنوان تمرین‪ ،‬برنامه سادهای که در شروع فصل آوردیم را با زبان‬
‫برنامهنویسی ‪ Python‬دوباره مینویسیم‪:‬‬
‫‪#!/usr/bin/env python‬‬
‫* ‪from asterisk.agi import‬‬
‫‪#import Queue‬‬

‫)(‪agi=AGI‬‬
‫)"‪agi.stream_file("hello-world‬‬
‫)(‪agi.hangup‬‬

‫به عنوان یک مثال دیگر‪ ،‬نمونه ای از برنامهنویسی ‪ AGI‬به زبانهای ‪ php‬و ‪ python‬را بررسی میکنیم‪.‬‬

‫مثال( فرض کنید تصمیم داریم برنامهای بنویسیم که همه متغیرهای ‪ AGI‬در آن بهکار روند‪ .‬این برنامه را با‬
‫زبانهای برنامهنویسی ‪ PHP‬و ‪ Python‬مینویسیم‪.‬‬
‫این برنامه در زبان ‪ PHP‬بهصورت زیر است‪:‬‬
‫‪;Php, show-var.php‬‬
‫‪#!/usr/bin/php -q‬‬
‫‪<?php‬‬
‫;)‪set_time_limit(30‬‬
‫;)'‪require('phpagi.php‬‬
‫;)‪error_reporting(E_ALL‬‬

‫;)(‪$agi = new AGI‬‬

‫;)]"‪$agi->conlog($agi->request["agi_request‬‬
‫;)]"‪$agi->conlog($agi->request["agi_channel‬‬
415 ‫ابزارهای برنامه‌نویسی استریسک‬

$agi->conlog($agi->request["agi_language"]);
$agi->conlog($agi->request["agi_uniqueid"]);
$agi->conlog($agi->request["agi_callerid"]);
$agi->conlog($agi->request["agi_dnid"]);
$agi->conlog($agi->request["agi_rdnis"]);
$agi->conlog($agi->request["agi_context"]);
$agi->conlog($agi->request["agi_extension"]);
$agi->conlog($agi->request["agi_priority"]);
$agi->conlog($agi->request["agi_enhanced"]);
$agi->conlog($agi->request["agi_accountcode"]);
$agi->conlog($agi->request["agi_network"]);
$agi->conlog($agi->request["agi_network_script"]);

:‫ بهصورت زیر است‬Python ‫این برنامه در زبان‬


;Python, show-var.py
from asterisk.manager import *
from myclass import Employee

agi = AGI()
agi.answer()
agi_request = agi.env['agi_request']
agi_channel = agi.env["agi_channel"]
agi_language = agi.env["agi_language"]
agi_uniqueid = agi.env["agi_uniqueid"]
agi_callerid = agi.env["agi_callerid"]
agi_dnid = agi.env["agi_dnid"]
agi_rdnis = agi.env["agi_rdnis"]
agi_context = agi.env["agi_context"]
agi_extension = agi.env["agi_extension"]
agi_priority = agi.env["agi_priority"]
agi_enhanced = agi.env["agi_enhanced"]
agi_accountcode = agi.env["agi_accountcode"]
agi_threadid = agi.env["agi_threadid"]

agi.verbose("agi_request: %s" % agi_request)


agi.verbose("agi_channel: %s" % agi_channel)
agi.verbose("agi_language: %s" % agi_language)
agi.verbose("agi_uniqueid: %s" % agi_uniqueid)
agi.verbose("agi_callerid: %s" % agi_callerid)
agi.verbose("agi_dnid: %s" % agi_dnid)
agi.verbose("agi_rdnis: %s" % agi_rdnis)
agi.verbose("agi_context: %s" % agi_context)
agi.verbose("agi_extension: %s" % agi_extension)
agi.verbose("agi_priority: %s" % agi_priority)
agi.verbose("agi_enhanced: %s" % agi_enhanced)
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪416‬‬

‫)‪agi.verbose("agi_accountcode: %s" % agi_accountcode‬‬


‫)‪agi.verbose("agi_threadid: %s" % agi_threadid‬‬

‫)"‪agi.verbose("This is test agi samples‬‬


‫)'‪data = agi.stream_file('demo-congrats‬‬
‫)‪agi.verbose(data‬‬
‫)(‪agi.hangup‬‬

‫نتیجه‌گیری‬
‫ابتدای فصل‪ ،‬در خصوص دو مفهوم مهم ‪ AA‬و ‪ IVR‬شرح داده شد و سپس با توجه به مفهوم ‪ IVR‬و طراحی‬
‫آن بهوســیله زبانهای برنامهنوسی‪ ،‬با ابزار ‪ AGI‬آشنا شــدید‪ .‬انواع فایلهای ‪ AGI‬و کالسهای متعددی از‬
‫آن بررســی شدند و نشان داده شــد که چگونه استریسک با فایلهای ‪ AGI‬ارتباط برقرار میکند‪ .‬دستورات‬
‫مهم ‪ AGI‬و استفاده از آنها در انواع زبانهای برنامهنویسی‪ ،‬در این فصل از اهمیت باالیی برخوردارند‪ .‬سایر‬
‫امور به تجربه برنامهنویس و تســلط وی به نوشــتن برنامهها و ‪IVR‬های هوشــمند‪ ،‬بازمیگردد‪ .‬در این فصل‬
‫صرفا آشنایی و نحوه استفاده از دستورات مهم برنامهنویسی ‪ AGI‬در زبانهای سطح باال مورد نظر است‪.‬‬
‫فصل پانزدهم‬

‫ابزارهای ‪RESTful‬‬
‫در استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪418‬‬

‫ابزارهای ‪ RESTful‬در استریسک‬


‫‪1‬‬

‫همانطور که در فصل دوم )معماری استریســک( درباره استریســک به تفصیل بیان شد‪ ،‬ساختار استریسک‬
‫بهصورت ماژوالر طراحی شدهاست یعنی کلیه برنامهها و دستورات استریسک بهصورت ماژول به آن اضافه‬
‫شــدهاند‪ .‬این قابلیت باعث میشود که اکثر توسعهدهندگان قادر باشند بهراحتی برنامههای خود را طراحی و‬
‫سپس آن را بهصورت ماژول به استریسک اضافه کنند‪.‬‬
‫اکثر برنامهها در استریسک به زبان برنامهنویسی ‪ C‬نوشته شدهاست و طبعاً چنانچه توسعهدهندهای تصمیم‬
‫بگیرد برنامهای جدید برای استریسک طراحی کند‪ ،‬باید بتواند این برنامه را با زبان برنامهنویسی ‪ C‬پیادهسازی‬
‫کند‪ .‬این کار کمی دشوار بهنظر میرسد‪ .‬به همین دلیل‪ ،‬در طراحی استریسک از واسطههایی برای سهولت‬
‫در برنامهنویسی استفاده میشود‪.‬‬
‫در ادامه بحث‪ ،‬مهمترین واســطههای استریسک برای سهولت در برنامهنویسی و توسعهی راحتتر آن‪،‬‬
‫شرح داده میشوند‪.‬‬

‫ابزار مدیریتی در استریسک‬


‫بهوســیله این ابزارها‪ ،‬میتوان به شــکل همزمان‪ ،‬استریســک را مدیریت و نظارت کرد‪ .‬به عبارت دیگر‪ ،‬به‬
‫واسطه این ابزارها میتوان تمام رویدادهایی که در استریسک اتفاق میافتد را مشاهده نمود‪.‬‬

‫)‪1- Asterisk RESTful Interface (ARI‬‬


‫‪419‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫ابزارهای برنامه‌نویسی در استریسک‬


‫بهوســیله این ابزارها‪ ،‬بهصــورت غیرهمزمان میتوان دســتورات و برنامههایی را در استریســک برای کلیه‬
‫کانالها اجرا کرد‪ .‬بهعبارتدیگر‪ ،‬بهوســیله برنامهنویســی ‪ ،AGI‬میتوان برنامههایی بهوسیله سایر زبانهای‬
‫برنامهنویسی طراحی و ایجاد نمود‪.‬‬
‫هر ابزار وظایف مشــخصی دارد و باید بتوان با بهکارگیری این ابزارها در کنار هم‪ ،‬برنامههای مورد نظر‬
‫را طراحی کرد‪ .‬البته این کار کمی دشواربهنظر میرسد‪.‬‬
‫از طــرف دیگــر اســتفاده از مفاهیم و تکنولوژیهــای جدید در برنامهنویســی برای انتقــال دادهها بین‬
‫ســرویسهای مختلف )از قبیل ‪ 1SOAP ، XML/JSON-RPC‬و ‪ (REST‬باعث میشــود که به یک روش‬
‫جدید در استریســک نیاز داشــته باشــیم‪ .‬ابزار ‪ ARI‬این بســتر را فراهم میکند تا از طریق ‪ WebSocket‬و‬
‫‪ RESTful‬و تکنولوژیهای وابســته به آنها‪ ،‬برنامهنویسی سادهتری با استریسک داشته باشیم‪ .‬این فصل برای‬
‫تمام برنامهنویسانی که با این مفاهیم کار میکنند‪ ،‬کاربردی و مفید است‪.‬‬
‫در واقــع با اســتفاده از ‪ ARI‬میتــوان برنامههای جدیدی در استریســک طراحی کرد‪ .‬بــا این قابلیت‪،‬‬
‫برنامهنویســان درگیر چالشهای برنامهنویســی ‪ C‬و طراحی ماژولهای جدید برای استریسک نخواهند بود‪.‬‬
‫با اســتفاده از برنامهنویســی ‪ ARI‬میتوان از ایجاد یک کانال تا کنترل و مدیریت کانال و ســپس انتقال آن‬
‫به بخشهای مختلف را در برنامهها داشــت‪ .‬به عبارت دیگر‪ ،‬با اســتفاده از ‪ ARI‬میتوان یک سافتسوئیچ‬
‫کنترلــر ایجاد کرد که وظیفه اصلی آن‪ ،‬مدیریت و کنترل تمامی تماسها باشــد‪ .‬در چنین شــرایطی وظیفه‬
‫استریســک‪ ،‬تنها انتقال تماس به سافتســوئیچ کنترلر طراحی شده با ‪ ARI‬خواهدبود‪ .‬برنامه نویسی ‪ ARI‬از‬
‫سه بخش مهم تشکیل شدهاست‪:‬‬

‫تکنولوژی ‪RESTful‬‬
‫‪ REST‬یک وب ســرویس بر پایهی معماری وب اســت‪ .‬این معماری برای برنامههای تحت شــبکه طراحی‬
‫گردیدهاست‪ .‬ایده اصلی ایجاد ‪ REST‬این است که بهجای استفاده از روشهای پیچیدهای همچون ‪COR-‬‬
‫‪2‬‬

‫‪ BA، 3RPC ، SOAP‬بــرای ارتبــاط بین نــرم افزارها و انتقال دادهها بین آنها؛ میتوان از پروتکل ســادهی‬
‫‪ HTTP‬استفادهکرد‪ .‬برنامههای تحت ‪ RESTful‬از پروتکل ‪ HTTP‬برای ارسال اطالعات‪ ،‬خواندن اطالعات‬
‫و حذف اطالعات استفاده میکند‪ RESTful .‬جایگزینی سبک و کارآمد برای مکانیزمهایی همچون ‪RPC‬‬
‫و وب سرویسهایی مانند ‪ SOAP ، 4WSDL‬و غیره است‪ REST .‬با وجود سادگی‪ ،‬قابلیتهای بسیار زیادی‬

‫)‪1- Simple Object Access Protocol (SOAP‬‬


‫)‪2- Common Object Request Broker Architecture (CORBA‬‬
‫‪3- Remote Procedure Call‬‬
‫‪4- Web Services Description Language‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪420‬‬

‫دارد‪ .‬تقریباً هیچ سیســتمی وجود ندارد که با وب ســرویس قابل پیادهسازی باشد‪ ،‬اما با معماری ‪RESTful‬‬
‫اجرا نشود‪.‬‬

‫تکنولوژی ‪WebSocket‬‬
‫بر طبق استاندارد ‪ RFC6455‬یک پروتکل ارتباطی دوطرفه بین سرور و کالینت است‪ .‬در این ارتباط‪ ،‬دادهها‬
‫میان ســرور و کالینت بهصورت ‪ JSON‬منتقل میشــوند‪ .‬در برنامهنویســی ‪ ،ARI‬ابتدا کالینت باید ازطریق‬
‫‪ ،WebSocket‬با سرور )استریسک( ارتباط برقرار کند‪ ،‬سپس سرور تمام وقایع و رویدادهای خود را ازطریق‬
‫این کانکشن و بهصورت ‪ JSON‬برای کالینت ارسال میکند‪ .‬این رویدادها میتوانند به صورت زیر باشند‪:‬‬
‫{‬
‫‪"application": "hello-world",‬‬
‫‪"args": [],‬‬
‫{ ‪"channel":‬‬
‫‪"accountcode": "",‬‬
‫{ ‪"caller":‬‬
‫‪"name": "100",‬‬
‫"‪"number": "100‬‬
‫‪},‬‬
‫{ ‪"connected":‬‬
‫‪"name": "",‬‬
‫"" ‪"number":‬‬
‫‪},‬‬
‫‪"creationtime": "2016-09-13T21:25:21.027+0430",‬‬
‫{ ‪"dialplan":‬‬
‫‪"context": "LocalSets",‬‬
‫‪"exten": "1000",‬‬
‫‪"priority": 3‬‬
‫‪},‬‬
‫‪"id": "1473785721.135",‬‬
‫‪"language": "en",‬‬
‫‪"name": "SIP/100-00000010",‬‬
‫"‪"state": "Up‬‬
‫‪},‬‬
‫‪"timestamp": "2016-09-13T21:25:21.085+0430",‬‬
‫"‪"type": "StasisStart‬‬
‫}‬

‫‪Stasis‬‬
‫بــا این مکانیزم‪ ،‬استریســک میتوانــد روال مدیریتی و کنتــرل تماسها را به یک برنامــه ‪ ARI‬انتقال دهد‪.‬‬
‫در ادامــه با ‪ Stasis‬آشــنایی بیشــتری خواهید یافت‪ .‬به عنــوان تمرین‪ ،‬برای فراخوانی یــک برنامه ‪ ARI‬در‬
‫‪421‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫استریسک‪ ،‬بهصورت زیر عمل کنید‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[ari‬‬
‫)(‪exten => 1000,1,NoOp‬‬
‫)(‪same=>n,Answer‬‬
‫)‪same=>n,Stasis(hello-world‬‬
‫)(‪same=>n,Hangup‬‬

‫اینجا ‪ hello-word‬نام برنامهی نوشته شدهای است که به استریسک اضافه شدهاست‪.‬‬

‫تنظیمات و پیکربندی ‪ WebSocket‬در استریسک‬


‫برای فعالکردن ‪ WebSocket‬در استریســک‪ ،‬فایل ‪ http.conf‬را از مسیر فایلهای پیکربندی استریسک باز‬
‫کنید‪:‬‬
‫‪# vim /etc/asterisk/http.conf‬‬
‫]‪[general‬‬
‫‪enabled=yes‬‬
‫‪bindaddr=0.0.0.0‬‬

‫تنظیمات و پیکربندی ‪ ARI‬در استریسک‬


‫بــرای فعالکــردن ‪ ARI‬و ایجاد یک اکانت جدید و اتصال کالینتها‪ ،‬فایل ‪ ari.conf‬را از مســیر فایلهای‬
‫پیکربندی استریسک باز کنید و تنظیمات زیر را انجام دهید‪.‬‬
‫‪# vim /etc/asterisk/ari.conf‬‬
‫]‪[general‬‬
‫‪enabled = yes‬‬
‫‪pretty = yes‬‬

‫برای ایجاد یک اکانت جدید و اتصال کالینت‪ ،‬اطالعات زیر را وارد نمایید‪:‬‬
‫]‪[hello‬‬
‫‪type = user‬‬
‫‪read_only = no‬‬
‫‪password = world‬‬

‫ازآنجاکه برای اجرا شــدن برنامههای ‪ ARI‬و انتقال دادهها‪ ،‬بایــد بتوان ابتدا از طریق ‪ WebSocket‬و اکانت‬
‫ایجاد شده‪ ،‬به استریسک متصل شد‪ ،‬چند نمونه از این روشها را در ادامه بررسی میکنیم‪.‬‬

‫استفاده از ‪wscat‬‬
‫‪ wscat‬یکی از سادهترین روشها برای بررسی و درستی تنظیمات پیکربندی است‪ .‬برای این منظور باید آن‬
‫را نصب کنید‪ .‬برای نصب ‪ wscat‬دستورات زیر را اجرا کنید‪:‬‬
‫‪# npm install -g wscat‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 422

:‫ دستور زیر را اجرا کنید‬WebSocket ‫سپس برای اتصال به استریسک از طریق‬


#wscat -c "ws://localhost:8088/ari/events?api_key=hello:world&app=hello-world"

connected (press CTRL+C to quit)


>

‫ در‬.‫ ایجاد میشود‬WebSocket ‫ ارتباط با استریسک از طریق‬،‫همانطورکه مالحظه میکنید با اجرای دستور‬
:‫ این پیام نمایش داده خواهد شد‬،‫محیط کامندالین استریسک‬
CLI>
Activating Stasis app 'hello-world'
== WebSocket connection from '127.0.0.1:49512' for protocol '' accepted using version '13'
Activating Stasis app 'hello-world'
CLI>

‫استفاده از جاوا اسکریپت‬


‫ بهصورت زیر یک ارتباط با استریســک‬،WebSocket ‫میتوان با اســتفاده از کد جاوا اســکریپت از طریق‬
.‫ایجاد کرد‬
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
url = "ws://localhost:8088/ari/events?app=hello-world&api_key=hello:world"
var exampleSocket = new WebSocket(url);
exampleSocket.onopen = function (event) {
console.log('opened')
};
</script>
</body>
</html>

Python ‫استفاده از‬


‫ بهصورت زیر یک ارتباط با استریســک ایجاد‬،WebSocket ‫میتوان با اســتفاده از برنامهی پایتون از طریق‬
:‫کرد‬
#!/usr/bin/env python

import json
import sys
import websocket
423 ‫ در استریسک‬RESTful ‫ابزارهای‬

import threading
import Queue
import requests

class ARIInterface(object):
def __init__(self, server_addr, username, password):
self._req_base = "http://%s:8088/ari/" % server_addr
self._username = username
self._password = password

class ARISample(object):
def __init__(self, server_addr):
app_name = 'hello-world'
username = 'hello'
password = 'world'
url = "ws://%s:8088/ari/events?app=%s&api_key=%s:%s" % (server_addr, app_name,
username, password)
ari = ARIInterface(server_addr, username, password)
ws = websocket.create_connection(url)

if __name__ == "__main__":
app = ARIApp('localhost')

‫ شما می توانید آن را با آدرس‬.‫ در نظر گرفته شده است‬localhost ‫ در اینجا آدرس ســرور استریســک‬:‫نکته‬
.‫سیستم تلفنی استریسک خود جایگزین نمایید‬

‫ در استریسک‬ARI ‫فراخوانی برنامه‬


‫ اکنون باید بتوان در‬.‫ نوشــته شــده به استریسک متصل شده است‬ARI ‫ برنامه‬،WebSocket ‫تا اینجا از طریق‬
.‫ سپرد‬ARI ‫ اجرا و مدیریت آن را به برنامه‬،‫ را فراخوانی کرد و کنترل‬Stasis ‫ دستور‬،‫برنامهنویسی استریسک‬
.‫ منتقل میشود‬ARI ‫ کنترل و اجرای برنامه به‬،‫برای مثال با اجرای برنامه زیر در استریسک‬
;extensions.conf
[LocalSets]
exten => 1000,1,NoOp()
same => n,Answer()
same => n,Stasis(hello-world)
same => n,Hangup()

‫ در اینجــا خروجی زیر را به‬.‫ را شــمارهگیری کنید‬۱۰۰۰ ‫ شــماره‬،‫ با یک تلفن‬،‫اکنــون برای اجرای برنامه‬
.‫تفکیک خواهیم داشت‬
:‫ خروجی در کامندالین استریسک‬-
CLI>
== Using SIP RTP CoS mark 5
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪424‬‬

‫‪-- Executing [1000@LocalSets:1] NoOp("SIP/100-00000014", "") in new stack‬‬


‫‪-- Executing [1000@LocalSets:2] Answer("SIP/100-00000014", "") in new stack‬‬
‫‪-- Executing [1000@LocalSets:3] Stasis("SIP/100-00000014", "hello-world") in new stack‬‬
‫>‪CLI‬‬

‫‪ -‬خروجی رویداد دریافتشده از طریق ‪ WebSocket‬در برنامه ‪:ARI‬‬


‫خروجی برنامه در ‪ ARI‬بهصورت زیر اســت‪ .‬ازآنجاکه این ارتباط تازه ایجاد شــده است‪ ،‬در ‪ ARI‬رویداد‬
‫‪ StasisStart‬بهصورت زیر دریافت میشود‪:‬‬
‫{‬
‫‪"type": "StasisStart",‬‬
‫‪"timestamp": "2016-09-14T00:44:22.656+0430",‬‬
‫‪"args": [],‬‬
‫{ ‪"channel":‬‬
‫‪"id": "1473797662.191",‬‬
‫‪"name": "SIP/100-00000015",‬‬
‫‪"state": "Up",‬‬
‫{ ‪"caller":‬‬
‫‪"name": "100",‬‬
‫"‪"number": "100‬‬
‫‪},‬‬
‫{ ‪"connected":‬‬
‫‪"name": "",‬‬
‫"" ‪"number":‬‬
‫‪},‬‬
‫‪"accountcode": "",‬‬
‫{ ‪"dialplan":‬‬
‫‪"context": "LocalSets",‬‬
‫‪"exten": "1000",‬‬
‫‪"priority": 3‬‬
‫‪},‬‬
‫‪"creationtime": "2016-09-14T00:44:22.597+0430",‬‬
‫"‪"language": "en‬‬
‫‪},‬‬
‫"‪"application": "hello-world‬‬
‫}‬

‫روش‌های مختلف فراخوانی ‪RESTful API‬‬


‫در فراخوانی ‪REST API‬ها از شــیوههای مختلفی میتوان اســتفاده کرد‪ .‬این شــیوهها در برخی مدلها اجرا‬
‫میشــوند‪ .‬در ادامه همین فصل درباره مدلهای استریســک توضیح ارائه میشود‪ .‬مهمترین شیوه های رایج‬
‫عبارتند از‪:‬‬
‫• ‪ :GET‬برای گرفتن اطالعات از یک مدل اســتفاده می‌شود‪ .‬با فراخوانی این متد در ‪ ،REST API‬اطالعاتی‬
‫بر اساس مدل‌های داده‌ای به‌وسیله ‪ WebSocket‬دریافت می‌شود‪.‬‬
‫‪425‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫• ‪ :POST‬برای ایجاد یک مدل جدید از این متد اســتفاده می‌شود‪ .‬با فراخوانی این متد در ‪ ،REST API‬یک‬
‫مدل جدید و مشخص‌شده‌ای ایجاد می‌شود‪.‬‬
‫• ‪ :DELETE‬برای حذف یک مدل از این متد اســتفاده می‌شــود‪ .‬با فراخوانی این متد در ‪ ،REST API‬یک‬
‫مدل حذف می‌شود‪.‬‬
‫• ‪ :PUT‬بــرای آپدیت‌کــردن اطالعات یک مدل اســتفاده می‌شــود‪ .‬با فراخوانی این متــد در ‪،REST API‬‬
‫اطالعات یک مدل آپدیت می‌شود‪.‬‬
‫تا اینجا ارتباط برنامه ما از طریق ‪ WebSocket‬با استریســک برقرار شــد و برنامه ‪ ARI‬هم فعال اســت‪.‬‬
‫اکنون از طریق ‪ RESTful‬و ‪ WebSocket‬به استریسک فرمان میدهیم تا یک فایل را پخش کند‪ .‬این فرآیند‬
‫میتواند درون خود برنامه ‪ ARI‬اجرا شود‪ .‬اینجا ما یک روش ساده )استفاده از ‪ (curl‬را بررسی میکنیم‪.‬‬

‫استفاده از ‪ curl‬و ‪ RESTful‬برای ارسال داده‌ها از برنامه ‪ ARI‬به استریسک‬


‫ســادهترین روش برای ارسال دادهها بهصورت ‪ RESTful‬استفاده از دســتور ‪ curl‬در توزیع لینوکس است‪.‬‬
‫برای مثال دستور ‪ curl‬بهصورت ‪ RESTful‬به استریسک فرمان میدهد که فایل صوتی ‪ hello-world‬پخش‬
‫شود‪.‬‬
‫‪# curl -v -u hello:world -X POST http://localhost:8088/ari/channels/CHANNEL-ID/‬‬
‫‪play?media=sound:hello-world‬‬

‫توجه داشــته باشید که باید بهجای ‪ ،CHANNEL-ID‬یک مقدار برای هر کانال جایگزین کنید‪ .‬برای کانال‬
‫ایجاد شده در مثال قبل‪ ،‬دستور بهصورت زیر باید اجرا شود‪.‬‬
‫‪#curl -v -u hello:world -X POST http://localhost:8088/ari/channels/1473797662.191/‬‬
‫‪play?media=sound:hello-world‬‬

‫با اجرای دســتور بــاال‪ ،‬فایل صوتــی ‪ hello-world‬برای کاربر پخش خواهد شــد‪ .‬خروجــی این اجرا در‬
‫کامندالین استریسک و رویدادهای دریافت شده از طریق ‪ WebSocket‬در برنامه ‪ ARI‬بهصورت زیر است‪:‬‬
‫‪ -‬خروجی در کامندالین استریسک‪:‬‬
‫>‪CLI‬‬
‫)'‪-- <SIP/100-00000015> Playing 'hello-world.gsm' (language 'en‬‬
‫>‪CLI‬‬

‫‪ -‬خروجی رویداد دریافتشده از طریق ‪ WebSocket‬در برنامه ‪: ARI‬‬


‫{<‬
‫‪"type": "PlaybackStarted",‬‬
‫{ ‪"playback":‬‬
‫‪"id": "9769c8c6-7864-442c-9863-18bacfe49d5f",‬‬
‫‪"media_uri": "sound:hello-world",‬‬
‫‪"target_uri": "channel:1473797662.191",‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪426‬‬

‫‪"language": "en",‬‬
‫"‪"state": "playing‬‬
‫‪},‬‬
‫"‪"application": "hello-world‬‬
‫}‬
‫{<‬
‫‪"type": "PlaybackFinished",‬‬
‫{ ‪"playback":‬‬
‫‪"id": "9769c8c6-7864-442c-9863-18bacfe49d5f",‬‬
‫‪"media_uri": "sound:hello-world",‬‬
‫‪"target_uri": "channel:1473797662.191",‬‬
‫‪"language": "en",‬‬
‫"‪"state": "done‬‬
‫‪},‬‬
‫"‪"application": "hello-world‬‬
‫}‬

‫توجه داشــته باشید که نوع فراخوانی ‪ RESTful‬اســت‪ .‬میتوانید از همین الگو در برنامههای ‪ ARI‬استفاده‬
‫کنید‪.‬‬

‫استفاده از افزونه ‪ POSTMAN‬در مرورگر ‪Chrome‬‬


‫میتوانید با نصب افزونه ‪ Postman‬در مرورگر ‪ ،Chrome‬از ‪ RESTful‬برای ارسال دستورات به استریسک‬
‫اســتفاده کنید‪ .‬برای مثال دستور اجرای فایل صوتی ‪ hello-world‬بهوسیله افزونه ‪ Postman‬بهصورت شکل‬
‫‪ ۱-۱۵‬خواهد بود‪.‬‬

‫شکل ‪1-15‬‬
‫‪427‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫همانطورکه در شــکل مالحظه میکنید‪ ،‬نوع ارســال دســتور بهصورت ‪ POST‬مشخص شدهاست‪ .‬در‬
‫قســمت ‪ Params‬دادههای مورد نیاز و از قســمت ‪ Autorization‬اطالعات نام کاربری و رمز عبور را وارد‬
‫میکنیم‪ .‬سپس درصورتیکه ارتباط ‪ WebSocket‬برقرار باشد‪ ،‬فایل صوتی ‪ hello-world‬پخش خواهد شد‪.‬‬
‫تا اینجا ســاختار مهم برنامهنویســی ‪ ARI‬خیلی ساده شرح داده شد‪ .‬در ادامه درباره ساختار برنامهنویسی‬
‫‪ ARI‬توضیحات بیشتری خواهد آمد‪.‬‬

‫بررسی ساختار ‪ RESTful API‬در استریسک‬


‫• ‪ : RESTful API‬مجموعه‌‌ای از ابزارهاست که با استفاده از آن‌ها‪ ،‬می‌توان برنامه نوشت و از آن‌ها استفاده‬
‫نمود‪ .‬این ابزار‌ها به حوزه‌های متفاوتی تقسیم می‌شوند و هر حوزه شامل ‪ API‬های متنوع با ساختار مشخص‬
‫است‪ .‬تقسیم‌بندی ‪ RESTful API‬به‌صورت زیر است‪:‬‬
‫‪• Asterisk REST Data Models‬‬
‫‪• Asterisk REST API‬‬
‫‪• Asterisk Bridges REST API‬‬
‫‪• Asterisk Channels REST API‬‬
‫‪• Asterisk Endpoints REST API‬‬
‫‪• Asterisk Events REST API‬‬
‫‪• Asterisk Recordings REST API‬‬
‫‪• Asterisk Sounds REST API‬‬
‫‪• Asterisk Applications REST API‬‬
‫‪• Asterisk Playbacks REST API‬‬
‫‪• Asterisk Devicestates REST API‬‬

‫در ادامه هر بخش را شرح خواهیم داد‪.‬‬

‫‪Asterisk REST Data Models‬‬


‫در واقع این بخش به معرفی انواع مدلســازی دادهها در ‪ RESTful‬میپردازد‪ .‬ما میتوانیم با بررســی انواع‬
‫مدلها‪ ،‬با دادهها و ساختار آنها آشنا شویم‪ .‬در این بخش مدلها بهصورت ‪ JSON‬تعریف میشوند و الگوی‬
‫تعریف آنها بهصورت زیر است‪:‬‬
‫{ ‪"name":‬‬
‫‪"key1": value1,‬‬
‫‪"key2": "value2",‬‬
‫"‪"description": "Some things.‬‬
‫‪},‬‬

‫بــرای مثال مدل ‪ AsteriskInfo‬را بررســی میکنیم‪ .‬هــدف از طراحی این مدل آمادهســازی اطالعاتی در‬
‫خصوص سیستم تلفنی استریسک در قالب مدل است‪ .‬این مدل بهصورت زیر تعریف میشود‪:‬‬
‫{‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 428

"properties": {
"status": {
"required": false,
"type": "StatusInfo",
"description": "Info about Asterisk status"
},
"config": {
"required": false,
"type": "ConfigInfo",
"description": "Info about Asterisk configuration"
},
"build": {
"required": false,
"type": "BuildInfo",
"description": "Info about how Asterisk was built"
},
"system": {
"required": false,
"type": "SystemInfo",
"description": "Info about the system running Asterisk"
}
},
"id": "AsteriskInfo",
"description": "Asterisk system information"
}

:‫ از چهار مدل دیگر نیز استفاده شد‬Asterisk Info ‫همانطورکه مالحظه میکنید در تعریف مدل‬
last_relaod_ ‫ سرویس استریسک و وضعیت‬startup_time ‫ به‌وسیله این مدل وضعیت‬:StatusInfo ‫• مدل‬
:‫ به‌صورت زیر ارائه شوند‬،‫ برای مثال این اطالعات می‌تواند ازطریق مدل‬.‫ استریسک مشخص می‌شود‬time
"status": {
"startup_time": "2016-09-14T01:26:36.408+0430",
"last_reload_time": "2016-09-14T01:26:36.408+0430" }

‫ اطالعاتی در خصوص پیکربندی و تنظیمات استریســک تعیین‬،‫ به‌وســیله این مــدل‬:ConfigInfo ‫• مدل‬
.‫ برای مثال مدل زیر پیکربندی سیستم تلفنی استریسک را نشان می‌دهد‬.‫می‌شود‬
"config": {
"name": "",
"default_language": "en",
"setid": {
"user": "",
"group": ""
},
"max_channels": 10
},
429 ‫ در استریسک‬RESTful ‫ابزارهای‬

‫ دیده میشود که اطالعاتی در خصوص نامکاربری و نام گروهی که مجوز‬SetId ‫اینجا یک مدل دیگر بنام‬
.‫ مشخص میکند‬،‫اجرای استریسک دارند‬
‫ زمان و تاریخ نصب استریسک‬،‫ کرنل‬،‫ این مدل اطالعاتی در خصوص نســخه لینوکس‬:BuildInfo ‫• مدل‬
.‫را نشان می‌دهد‬
"build": {
"os": "Linux",
"kernel": "3.19.0-25-generic",
"machine": "x86_64",
"options": "LOADABLE_MODULES, OPTIONAL_API",
"date": "2016-08-21 09:13:09 UTC",
"user": "root"
},

.‫ این مدل اطالعاتی در خصوص نسخه نصب شده استریسک را نشان می‌دهد‬:SystemInfo ‫• مدل‬
"system": {
"version": "13.10.0",
"entity_id": "00:0c:29:f1:95:8e"
},

Asterisk RESTful ‫بررسی انواع مدل‌های‬


‫ انواع مدلها و کاربردشــان در‬۱-۱۵ ‫ در جدول‬.‫ انواع زیادی از مدلها وجود دارد‬Asterisk RESTful ‫در‬
.‫ نمایش داده شده است‬ARI ‫برنامهنویسی‬

Data Models Purpose


AsteriskInfo Asterisk system Information
Buildinfo Info about how Asterisk was built
ConfigInfo Info about Asterisk configuartion
Sctld Effective user/group id
StatusInfo Info about Asterisk
SystemInfo The Value of a channel variable
Variable
The endpoint is uniquely identified by the technology/resource pair
Endpoint
TextMessage A text message
TextMessageVariable A key/value pair variable in a text message
CallerID Caller identification
Channel A specific communication connection between Asterisk and Endpoint
Dialed Dialed channel informnation
DialplanCEP Dialplan location (context/extension/prioority)
Bridge The merging of media from one or more channels
LiveRecording A recording that is in progress
StoredRecording A past recording that may be played back
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 430

Data Models Purpose


FormatLangPair Identifies the format and language of a sound file
Sound A media file that may be played back
Playback Object representing the playback of a media to a channel
DeviceStatc Represents the state of a device
Mailbox Represents the state of a mailbox
ApplicationReplaced Notification that another WebSocket has taken over for an application
BridgeAttendedTransfer Notification that an attended transfer has occured
BridgeBlindTransfer Notification that a blind transfer has occured
BridgeCreated Notification that a bridge has been created
BridgeDestroyed Notification that a bridge has been destroyed
BridgeMerged Notification that one bridge has merged into another
ChannelCallerId Channel Changed Caller ID
ChannelCreated Notification that a channel has been created
ChannelDestroyed Notification that a channel has been destroyed
ChannelDialplan Channel changed location in the dialplan
ChannelDtmfRecieved DTMF recieved on a channel
ChannelEnteredBridge Notification on that a channel has entered a bridge
ChannelHangupRequest A hangup was requested on the channel
ChannelLeftBridge Notification that a channel has left a bridge
ChannelStateChange Notification of a channel's state change
ChannelTalkingFinnished Talking is no longer detected on the channel
ChannelTalkingStarted Talking was detected on the channel
User-generated event which additional user-defined fields in the
ChannelUserevent
object
ChannelVarset Channel varriable changed
DeviceStateChanged Notification that a device state has changed
Dial Dialing state has changed
EndpointStateChange Endpoint state changed
Event Base type for a asynchronous events from Asterisk
Message Base tyoe for errors and events
MissingParams Error event sent when required params are missing
PlaybackFinnished Event showing the completion of a media playback operation
PlaybackStarted Event showing start of a media playback operation
RecordingFailed Event showing failure of a recording operation
RecordingFinished Event showing the compeletion of a recording operation
RecordingStarted Event showing the start of a recording operation
StasisEnd Notification that a channel has left a Stasis application
StasisStart Notification that a channel has entered a Stasis application
TextMessageRecieved A text message was recieved from an endpoint
Application Detailes of a Stasis application

1-15 ‫جدول‬
‫‪431‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫پیشتــر هم توضیح داده شــد یک برنامــه ‪ ARI‬از طریق ‪ ، WebSocket‬دادهها را از استریســک دریافت و‬
‫درخواستهای خود را بهصورت ‪ RESTful‬به سمت استریسک ارسال میکند )شکل ‪.(۲-۱۵‬‬

‫شکل ‪2-15‬‬

‫نکته مهم در انواع فراخوانیها بهصورت ‪ ،RESTful‬آدرس محل مورد اســتفاده اســت که همانطورکه در‬
‫فراخوانی با دستور ‪ curl‬یا افزونه ‪ Postman‬گفته شد‪ ،‬آدرس فراخوانی بهصورت زیر است‪:‬‬
‫‪http://IP-ADDRESS:8088/ari/‬‬

‫در ادامه در خصوص انواع ‪REST API‬ها در استریسک مطالبی ذکر خواهد شد‪ .‬در راهنمای استفاده از هر‬
‫‪ ، REST API‬نوع متد مورد استفاده مشخص شده است‪.‬‬

‫استفاده از ‪Asterisk REST API‬‬


‫جدول ‪ ۲-۱۵‬انواع فراخوانیها و نوع مدل دادههای خروجی را نشان میدهد‪:‬‬

‫‪Method‬‬ ‫‪Path‬‬ ‫‪Return Model‬‬ ‫‪Summary‬‬


‫‪GET‬‬ ‫‪/asterisk/info‬‬ ‫‪AsteriskInfo‬‬ ‫‪Gets Asterisk system information.‬‬
‫‪GET‬‬ ‫‪/asterisk/variable‬‬ ‫‪Variable‬‬ ‫‪Get the value of a global variable.‬‬
‫‪POST‬‬ ‫‪/asterisk/variable‬‬ ‫‪void‬‬ ‫‪Set the value of a global variable.‬‬
‫جدول ‪2-15‬‬

‫به عنوان تمرین فرض کنید برای فراخوانی متد ‪ Info‬بهصورت زیر عمل کنیم‪.‬‬
‫"‪#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/asterisk/info‬‬

‫بــا فراخوانی ایــن ‪ ،RESTful‬خروجی زیر بهصــورت مــدل دادهای ‪ AsteriskInfo‬از طریق ‪WebSocket‬‬
‫دریافت میشود‪.‬‬
‫{‬
‫{ ‪"build":‬‬
‫‪"os": "Linux",‬‬
‫‪"kernel": "3.19.0-25-generic",‬‬
‫‪"machine": "x86_64",‬‬
‫‪"options": "LOADABLE_MODULES, OPTIONAL_API",‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪432‬‬

‫‪"date": "2016-08-21 09:13:09 UTC",‬‬


‫"‪"user": "root‬‬
‫‪},‬‬
‫{ ‪"system":‬‬
‫‪"version": "13.10.0",‬‬
‫"‪"entity_id": "00:0c:29:f1:95:8e‬‬
‫‪},‬‬
‫{ ‪"config":‬‬
‫‪"name": "",‬‬
‫‪"default_language": "en",‬‬
‫{ ‪"setid":‬‬
‫‪"user": "",‬‬
‫"" ‪"group":‬‬
‫‪},‬‬
‫‪"max_channels": 10‬‬
‫‪},‬‬
‫{ ‪"status":‬‬
‫‪"startup_time": "2016-09-14T01:26:36.408+0430",‬‬
‫"‪"last_reload_time": "2016-09-14T01:26:36.408+0430‬‬
‫}‬
‫}‬

‫همچنین فرض کنید ‪ RESTful‬زیر فراخوانی شود‪:‬‬


‫‪#curl -X GET -u hello:world "http:// IP-ADDRESS:8088/ari/asterisk/‬‬

‫"‪variable?variable=CONSOLE‬‬

‫خروجی فراخوانی آن بهصورت زیر است‪:‬‬


‫{‬
‫"‪"value": "Console/dsp‬‬
‫}‬

‫درواقع بهوســیله این نوع فراخوانی‪ ،‬مقدار متغیر سراســری ‪ CONSOLE‬در استریســک را میتوان خواند‪.‬‬
‫مقدار هر متغیر سراسری را که در برنامه ‪ ARI‬به آن نیاز داشته باشید‪ ،‬با این روش میتوانید بخوانید‪.‬‬

‫استفاده از ‪Bridge REST API‬‬


‫جدول ‪ ۳-۱۵‬انواع فراخوانیها و نوع مدل دادههای خروجی را برای این ‪ REST API‬نشان میدهد‪.‬‬
‫بــرای مثــال جهت گرفتن فهرســت همه ‪Bridge‬ها در استریســک باید متــد ‪ bridges‬را بهصورت زیر‬
‫فراخوانی کنیم‪.‬‬
‫"‪#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/bridges‬‬
433 ‫ در استریسک‬RESTful ‫ابزارهای‬

Method Path Return Model Summary


GET /bridges List[Bridge] List all active bridges in Asterisk.
POST /bridges Bridge Create a new bridge.
POST /bridges/{bridgeId} Bridge Create a new bridge or updates an existing
one.
GET /bridges/{bridgeId} Bridge Get bridge details.
DELETE /bridges/{bridgeId} void Shut down a bridge.
POST /bridges/{bridgeId}/ void Add a channel to a bridge.
addChannel
POST /bridges/{bridgeId}/ void Remove a channel from a bridge.
removeChannel
POST /bridges/{bridgeId}/moh void Play music on hold to a bridge or change
the MOH class that is playing.
DELETE /bridges/{bridgeId}/moh void Stop playing music on hold to a bridge.
POST /bridges/{bridgeId}/play Playback Start playback of media on a bridge.
POST /bridges/{bridgeId}/play/ Playback Start playback of media on a bridge.
{playbackId}
POST /bridges/{bridgeId}/record LiveRecording Start a recording.
3-15 ‫جدول‬

‫ باال بهصورت مدل زیر‬RESTful ‫ خروجی‬،‫ تماس بگیرد و با هم صحبت کنند‬۱۰۱ ‫ با کاربر‬۱۰۰‫اگــر کاربر‬
:‫ دریافت میشود‬WebSocket ‫از طریق‬
[
{
"id": "99af098c-44d2-4038-a9c4-a00203f4da12",
"technology": "simple_bridge",
"bridge_type": "mixing",
"bridge_class": "basic",
"creator": "",
"name": "",
"channels": [
"1473808263.43",
"1473808263.40"
]
}
]

.‫ میتوانید استفاده کنید‬ARI ‫ های باال در برنامه‬REST API ‫از هر یک از‬

Channel REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬4-۱۵ ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 434

Method Path Return Model Summary


GET /channels List[Channel] List all active channels in Asterisk.
POST /channels Channel Create a new channel (originate).
GET /channels/{channelId} Channel Channel details.
POST /channels/{channelId} Channel Create a new channel (originate
with id).
DELETE /channels/{channelId} void Delete (i.e. hangup) a channel.
POST /channels/{channelId}/continue void Exit application; continue execution
in the dialplan.
POST /channels/{channelId}/answer void Answer a channel.
POST /channels/{channelId}/ring void Indicate ringing to a channel.
DELETE /channels/{channelId}/ring void Stop ringing indication on a channel
if locally generated.
POST /channels/{channelId}/dtmf void Send provided DTMF to a given
channel.
POST /channels/{channelId}/mute void Mute a channel.
DELETE /channels/{channelId}/mute void Unmute a channel.
POST /channels/{channelId}/hold void Hold a channel.
DELETE /channels/{channelId}/hold void Remove a channel from hold.
POST /channels/{channelId}/moh void Play music on hold to a channel.
DELETE /channels/{channelId}/moh void Stop playing music on hold to a
channel.
POST /channels/{channelId}/silence void Play silence to a channel.
DELETE /channels/{channelId}/silence void Stop playing silence to a channel.
POST /channels/{channelId}/play Playback Start playback of media.
POST /channels/{channelId}/play/ Playback Start playback of media and specify
{playbackId} the playbackId.
POST /channels/{channelId}/record LiveRecording Start a recording.
GET /channels/{channelId}/variable Variable Get the value of a channel variable
or function.
POST /channels/{channelId}/variable void Set the value of a channel variable
or function.
POST /channels/{channelId}/snoop Channel Start snooping.
POST /channels/{channelId}/snoop/ Channel Start snooping.
{snoopId}
4-15 ‫جدول‬

‫ را بهصورت زیر فراخوانی‬channels ‫مثال برای گرفتن لیســت کلیه کانالهای فعال در استریســک باید متد‬
:‫کنید‬
#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/channels"
435 ‫ در استریسک‬RESTful ‫ابزارهای‬

:‫ بهصورت زیر است‬،‫ در صورتی که کانال فعال در استریسک وجود داشته باشد‬RESTful ‫خروجی‬
[
{
"id": "1473809017.84",
"name": "SIP/100-0000000a",
"state": "Up",
"caller": {
"name": "100",
"number": "100"
},
"connected": {
"name": "",
"number": ""
},
"accountcode": "",
"dialplan": {
"context": "LocalSets",
"exten": "1000",
"priority": 3
},
"creationtime": "2016-09-14T03:53:37.048+0430",
"language": "en"
}
]

Endpoints REST API ‫استفاده از‬


:‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬۵-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /endpoints List[Endpoint] List all endpoints.
PUT /endpoints/sendMessage void Send a message to some
technology URI or endpoint.
GET /endpoints/{tech} List[Endpoint] List available endoints for a
given endpoint technology.
GET /endpoints/{tech}/{resource} Endpoint Details for an endpoint.
PUT /endpoints/{tech}/{resource}/sendMessage void Send a message to some
endpoint in a technology.
5-15 ‫جدول‬

.‫ را بهصورت زیر فراخوانی کنید‬Endpoints REST ‫ باید‬،‫برای مثال جهت گرفتن لیست همه کاربران‬
#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/endpoints"
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 436

‫ در این خروجی همه داخلیهای تعریف شــده در استریسک نشان‬.‫ بهصورت زیر اســت‬RESTful ‫خروجی‬
.‫داده میشوند‬
[
{
"technology": "SIP",
"resource": "100",
"state": "online",
"channel_ids": []
},
{
"technology": "SIP",
"resource": "101",
"state": "online",
"channel_ids": []
},
{
"technology": "IAX2",
"resource": "demo",
"state": "unknown",
"channel_ids": []
},
{
"technology": "SIP",
"resource": "op100",
"state": "unknown",
"channel_ids": []
},
{
"technology": "SIP",
"resource": "op101",
"state": "unknown",
"channel_ids": []
},
{
"technology": "SIP",
"resource": "op102",
"state": "unknown",
"channel_ids": []
}
]

.‫ نشان داده میشود‬state ‫ وضعیت هر داخلی هم بهوسیله پارامتر‬،‫همانطورکه مالحظه میکنید‬


437 ‫ در استریسک‬RESTful ‫ابزارهای‬

Event REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬۶-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /events Message WebSocket connection for events.
POST /events/user/{eventName} void Generate a user event.
6-15 ‫جدول‬

Recording REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬7-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /recordings/stored List[StoredRecording] List recordings that are
complete.
GET /recordings/stored/ StoredRecording Get a stored recording's
{recordingName} details.
DELETE /recordings/stored/ void Delete a stored recording.
{recordingName}
POST /recordings/stored/ StoredRecording Copy a stored recording.
{recordingName}/copy
GET /recordings/live/{recordingName} LiveRecording List live recordings.
DELETE /recordings/live/{recordingName} void Stop a live recording and
discard it.
POST /recordings/live/{recordingName}/ void Stop a live recording and
stop store it.
POST /recordings/live/{recordingName}/ void Pause a live recording.
pause
DELETE /recordings/live/{recordingName}/ void Unpause a live recording.
pause
POST /recordings/live/{recordingName}/ void Mute a live recording.
mute
DELETE /recordings/live/{recordingName}/ void Unmute a live recording.
mute
7-15 ‫جدول‬

‫ برای مثال با فراخوانی‬.‫ در استریسک استفاده میشود‬Recording ‫ها غالبا برای مدیریت و کنترل‬API ‫از این‬
.‫ فهرست همه فایلهای رکورد شده نمایش داده میشود‬، stored‫متد‬
#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/recordings/stored"
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 438

Sounds REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬8-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /sounds List[Sound] List all sounds.
GET /sounds/{soundId} Sound Get a sound's details.
8-15 ‫جدول‬

‫ را بهصورت زیر فراخوانی‬sounds ‫ باید متد‬،‫مثال برای مشــاهده فهرست همه فایلهای صوتی در استریسک‬
:‫کنید‬
#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/sounds"

.‫ قسمتی از خروجی را نمایش میدهیم‬،‫ طوالنی است‬REST API ‫چون خروجی این‬
[
{
"id": "vm-review",
"text": "press 1 to accept this recording press 2 to listen to it press 3 to rerecord your
message",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "vm-nomore",
"text": "No more messages.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
},
{
"id": "conf-now-unmuted",
"text": "The conference is now unmuted.",
"formats": [
{
"language": "en",
"format": "gsm"
439 ‫ در استریسک‬RESTful ‫ابزارهای‬

}
]
},
{
"id": "enter-num-blacklist",
"text": "Please enter the number to be blacklisted.",
"formats": [
{
"language": "en",
"format": "gsm"
}
]
}
]

.‫ همه فایلهای صوتی یک به یک بهصورت مدل نمایش داده میشوند‬،‫همانطورکه مالحظه میکنید‬

Applications REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬۹-۱۵ ‫جدول‬

Method Path Return Model Summary


DELETE /applications/{applicationName}/ Application Unsubscribe an application
subscription from an event source.
GET /applications List[Application] List all applications.
GET /applications/{applicationName} Application Get details of an application.
POST /applications/{applicationName}/ Application Subscribe an application to
subscription a event source.
9-15 ‫جدول‬

.‫ در استریسک نمایش داده میشود‬ARI ‫ فهرست برنامه های‬،‫ زیر‬Applications ‫به عنوان مثال با متد‬
#curl -X GET -u hello:world "http://IP-ADDRESS:8088/ari/applications"

.‫خروجی دستور بهصورت زیر است‬


[
{
"name": "hello-world",
"channel_ids": [],
"bridge_ids": [],
"endpoint_ids": [],
"device_names": []
}
]
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 440

Playbacks REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬۱۰-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /playbacks/{playbackId} Playback Get a playback's details.
DELETE /playbacks/{playbackId} void Stop a playback.
POS /playbacks/{playbackId}/control void Control a playback.
10-15 ‫جدول‬

‫ نشــان‬ARI ‫ فایلهای صوتیِ در حال اجرا در برنامهی‬،‫ بهصورت زیر‬Playback ‫بــرای مثال با فراخوانی متد‬
.‫ را وارد کنید‬playbackId ‫ باید‬،REST API ‫ هنگام استفاده از این‬.‫داده میشوند‬
#curl -X GET -u hello:world "http:// IP-ADDRESS:8088/ari/playbacks/6597563f-cb8d-4c3b-
96ad-0683dbf91819"

.‫خروجی دستور بهصورت زیر است‬


{
"id": "6597563f-cb8d-4c3b-96ad-0683dbf91819",
"media_uri": "sound:demo-congrats",
"target_uri": "channel:1473819187.140",
"language": "en",
"state": "playing"
}

Devicestates REST API ‫استفاده از‬


.‫ نشان میدهد‬REST API ‫ انواع فراخوانیها و نوع مدل دادههای خروجی را برای این‬۱۱-۱۵ ‫جدول‬

Method Path Return Model Summary


GET /deviceStates List[DeviceState] List all ARI controlled device states.
GET /deviceStates/{deviceName} DeviceState Retrieve the current state of a device.
PUT /deviceStates/{deviceName} void Change the state of a device controlled by
ARI. (Note - implicitly creates the device
state).
DELETE /deviceStates/{deviceName} voi Destroy a device-state controlled by ARI.
11-15 ‫جدول‬

‫ با اجرای متد‬.‫ ایجاد کنیم‬REST API ‫ جدید بهوســیله‬Devicestates ‫بــرای مثال فرض کنید بخواهیم یک‬
.‫ ایجاد میکنیم‬Stasis:mystate ‫ جدید بهنام‬DeviceStates ‫ یک‬، DeviceStates
‫‪441‬‬ ‫ابزارهای ‪ RESTful‬در استریسک‬

‫‪#curl -v -u hello:world -X POST "http://IP-ADDRESS:8088/ari/deviceStates/‬‬


‫"‪Stasis:mystate?deviceState=NOT_INUSE‬‬

‫همچنین میتوان با استفاده از متد ‪ DeviceStates‬زیر‪ ،‬وضعیت انواع ‪Devicestates‬ها را مشاهده کرد‪.‬‬
‫‪#curl -X GET -u hello:world "http:// IP-ADDRESS:8088/ari/devicestates‬‬

‫خروجی دستور بهصورت زیر است‪.‬‬


‫[‬
‫{‬
‫‪"name": "Stasis:mystate",‬‬
‫"‪"state": "NOT_INUSE‬‬
‫}‬
‫]‬

‫نتیجه گیری‬
‫در شــروع فصل در خصوص تکنیکهای انتقال دادهها بین ســرویسهای مختلف مطالبی ذکر شــد‪ ،‬سپس‬
‫بیان شــد که ابزار ‪ ARI‬این بســتر را برای ما فراهم میکند که بتوانیم از طریق ‪ WebSocket‬و ‪ RESTful‬و‬
‫تکنولوژیهای وابسته‪ ،‬با استریسک ارتباط برقرار کنیم‪ .‬برنامهنویسی ‪ ARI‬در استریسک این قابلیت را برای‬
‫مــا فراهم میآورد که بتوانیم از قابلیتهای برنامهنویســی ‪ AGI‬و ‪ AMI‬با هــم و در کنار هم‪ ،‬اما بهصورت‬
‫سادهتر استفاده کنیم‪ .‬هدف این فصل‪ ،‬آشنایی با سبک نوشتن برنامه نویسی ‪ ARI‬در استریسک بود و چون‬
‫این روش برنامهنویســی در استریسک نسبتاً جدید اســت برای دریافت آخرین تغییرات و اطالعات بیشتر به‬
‫آدرس زیر مراجعه کنید‪:‬‬
‫‪https://wiki.asterisk.org/wiki/display/AST/Getting+Started+with+ARI‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪442‬‬
‫فصل شانزدهم‬

‫استفاده از ماژول ‪PJSIP‬‬


‫در استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪444‬‬

‫مقدمه‬
‫در فصل دوم )معماری استریســک( شرح داده شــد که به واسطه ماژولهای ‪ Channel Drivers‬میتوان از‬
‫پروتکلهای مختلفی برای ایجاد تماس در استریســک اســتفاده کرد‪ .‬به عنــوان مثال میتوان ماژولهایی از‬
‫قبیل ‪ chan_sip ، chan_iax ، chan_H323‬و غیره را نام برد که هر کدام قابلیتهایی دارند و ویژگیهایی‬
‫را به استریسک اضافه میکنند‪.‬‬
‫در نسخههای جدیدتر استریسک ) نسخه ‪ ۱۲‬به بعد(‪ ،‬یک ماژول به نام ‪ res_pjsip‬اضافه شده است‪ .‬هدف‬
‫و کاربرد اصلی این ماژول‪ ،‬اضافه کردن قابلیت پروتکل ‪ SIP‬در استریسک است‪ .‬شاید این سوال مطرح شود‬
‫که این پروتکل بهوســیله ماژول ‪ chan_sip‬در استریســک وجود دارد‪ ،‬بنابراین طراحی و اضافهشدن ماژول‬
‫جدید ‪ res_pjsip‬چه دلیلی دارد؟‬

‫درباره ‪pjsip‬‬
‫‪ pjsip‬یک کتابخانه برای انتقال دادههای رســانهای اســت که از پروتکلهای ‪ SIP ، SDP‬و ‪ RTP‬پشــتیبانی‬
‫میکند‪ .‬این پروتکل بهوســیله شرکت ‪ Teluu.Ltd‬طراحی شده است‪ .‬ازآنجاکه این کتابخانه رایگان است‪،‬‬
‫میتوانید از آن در طراحی نرمافزارهای رسانهای استفاده کنید‪.‬‬
‫‪445‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫این کتابخانه بهصورت ‪ Portable‬طراحی شدهاست و میتوان از آن در برنامههای ویندوزی‪ ،‬لینوکسی و‬


‫حتی برنامههای موبایل از قبیل اندروید و ‪ IOS‬نیز استفاده کرد‪ .‬در نسخههای استریسک ‪ ۱۲‬به بعد‪ ،‬به جای‬
‫استفاده از ماژول ‪ chan_sip‬میتوان از ماژول ‪ pjsip‬استفاده کنید‪.‬‬
‫در ادامه به نصب این ماژول و استفاده از آن در استریسک میپردازیم‪.‬‬

‫نصب ماژول ‪ pjsip‬در استریسک‬


‫در استریسک ‪ ۱۲‬و نسخههای پس از آن برای پشتیبانی از پروتکل ‪ ، SIP‬میتوان از دو ماژول استفاده کرد‪.‬‬
‫ماژول ‪ chan_sip‬بهصورت پیشفرض در زمان نصب استریسک‪ ،‬نصب میشود‪ .‬این درحالی است که برای‬
‫اســتفاده از ماژول ‪ ،pjsip‬باید آن را نصب نمود‪ .‬برای دریافت آخرین نسخه ماژول ‪ pjsip‬میتوانیدبه سایت‬
‫‪ www.pjsip.org‬مراجعه و ماژول را دانلود کنید‪.‬‬
‫برای دانلود آن میتوانید از سه روش زیر استفاده کنید‪.‬‬
‫‪ -۱‬دانلود با استفاده از روش ‪wget‬‬
‫‪#cd /usr/src/‬‬
‫‪# wget http://www.pjsip.org/release/2.4.5/pjproject-2.4.5.tar.bz2‬‬
‫‪# tar -xjvf pjproject-2.4.5.tar.bz2‬‬

‫‪ -۲‬دانلود با استفاده از روش ‪svn‬‬


‫‪#cd /usr/src/‬‬
‫‪# svn co http://svn.pjsip.org/repos/pjproject/trunk/ pjproject-trunk‬‬

‫در این روش ممکن است دستور ‪ snv‬در سیستم لینوکس نصب نشده باشد‪ .‬با استفاده از دستور زیر ابتدا آن‬
‫را نصب کنید‪.‬‬
‫‪;RHEL‬‬
‫‪yum install subversion‬‬

‫‪;ubuntu‬‬
‫‪apt-get install subversion‬‬

‫‪ -۳‬دانلود با استفاده از روش ‪git‬‬


‫‪#cd /usr/src/‬‬
‫‪# git clone https://github.com/asterisk/pjproject pjproject‬‬

‫در این روش ممکن اســت دســتور ‪ git‬در سیستم لینوکس نصب نشده باشد‪ .‬با استفاده از دستور زیر ابتدا آن‬
‫را نصب کنید‪.‬‬
‫‪;RHEL‬‬
‫‪yum install git‬‬

‫‪;ubuntu‬‬
‫‪apt-get install git‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 446

:‫ شده و دستورات زیر را اجرا کنید‬pjproject ‫ وارد فولدر‬، pjsip ‫بعد از دانلود‬
#cd pjproject
#./configure --prefix=/usr --enable-shared --disable-sound --disable-resample --disable-video
--disable-opencore-amr CFLAGS='-O2 -DNDEBUG'

:‫ دستورات زیر را اجرا کنید‬pjsip ‫ کردن‬Build ‫سپس برای‬


#make dep
#make
#make install

‫ خروجی‬.‫ را بررســی نمود‬pjsip ‫ با اســتفاده از دســتورات زیر میتوان صحــت نصب‬pjsip ‫بعــد از نصب‬
:‫دستورات مانند زیر خواهد بود‬
#ldconfig
#ldconfig -p | grep pj
libpjsua2.so.2 (libc6,x86-64) => /usr/local/lib/libpjsua2.so.2
libpjsua2.so (libc6,x86-64) => /usr/local/lib/libpjsua2.so
libpjsua.so.2 (libc6,x86-64) => /usr/local/lib/libpjsua.so.2
libpjsua.so (libc6,x86-64) => /usr/local/lib/libpjsua.so
libpjsip.so.2 (libc6,x86-64) => /usr/local/lib/libpjsip.so.2
libpjsip.so (libc6,x86-64) => /usr/local/lib/libpjsip.so
libpjsip-ua.so.2 (libc6,x86-64) => /usr/local/lib/libpjsip-ua.so.2
libpjsip-ua.so (libc6,x86-64) => /usr/local/lib/libpjsip-ua.so
libpjsip-simple.so.2 (libc6,x86-64) => /usr/local/lib/libpjsip-simple.so.2
libpjsip-simple.so (libc6,x86-64) => /usr/local/lib/libpjsip-simple.so
libpjnath.so.2 (libc6,x86-64) => /usr/local/lib/libpjnath.so.2
libpjnath.so (libc6,x86-64) => /usr/local/lib/libpjnath.so
libpjmedia.so.2 (libc6,x86-64) => /usr/local/lib/libpjmedia.so.2
libpjmedia.so (libc6,x86-64) => /usr/local/lib/libpjmedia.so
libpjmedia-videodev.so.2 (libc6,x86-64) => /usr/local/lib/libpjmedia-videodev.so.2
libpjmedia-videodev.so (libc6,x86-64) => /usr/local/lib/libpjmedia-videodev.so
libpjmedia-codec.so.2 (libc6,x86-64) => /usr/local/lib/libpjmedia-codec.so.2
libpjmedia-codec.so (libc6,x86-64) => /usr/local/lib/libpjmedia-codec.so
libpjmedia-audiodev.so.2 (libc6,x86-64) => /usr/local/lib/libpjmedia-audiodev.so.2
libpjmedia-audiodev.so (libc6,x86-64) => /usr/local/lib/libpjmedia-audiodev.so
libpjlib-util.so.2 (libc6,x86-64) => /usr/local/lib/libpjlib-util.so.2
libpjlib-util.so (libc6,x86-64) => /usr/local/lib/libpjlib-util.so
libpj.so.2 (libc6,x86-64) => /usr/local/lib/libpj.so.2
libpj.so (libc6,x86-64) => /usr/local/lib/libpj.so

‫ برای این منظور به فولدرنصب استریسک بروید‬.‫ استریســک باید مجددا ً کامپایل شود‬، pjsip ‫پس از نصب‬
:‫و دستور زیر را اجرا کنید‬
#./configure

‫ اطمینان‬make menuselect ‫ ابتدا بهوسیله دســتور‬،‫بعد از اجرای دســتور و قبل از نصب مجدد استریســک‬
:‫ به درستی نصب و بهوسیله استریسک شناخته شده باشد‬pjsip ‫حاصل کنید که ماژول‬
#make menuselect
‫‪447‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫شکل ‪1-16‬‬

‫سپس استریسک را دوباره کامپایل کنید‪.‬‬


‫‪#make‬‬
‫‪#make install‬‬

‫مهاجرت از ‪ chan_sip‬به ‪ pjsip‬در استریسک‬


‫بعد از نصب موفق ماژول ‪ pjsip‬در استریسک‪ ،‬باید در فایل پیکربندی ماژولهای استریسک‪ ،‬ماژول _‪chan‬‬
‫‪ sip‬را غیرفعال و ماژول ‪ pjsip‬و ســایر ماژولهای وابســته به آن را فعالکنید‪ .‬بنابراین‪ ،‬تغییرات باید به شکل‬
‫زیر انجام گیرد‪:‬‬
‫‪;madules.conf‬‬
‫‪noload=>chan_sip.so‬‬
‫‪load=>res_pjsip.so‬‬

‫بعد از ویرایش فایل مدیریت و پیکربندی ماژولها‪ ،‬باید استریسک را مجددا ً راهاندازی نمایید‪.‬‬
‫‪# /etc/init.d/asterisk restart‬‬

‫بــا فعال کردن ماژول ‪ ، pjsip‬میتــوان از طریق فایل ‪ ،pjsip.conf‬ماژول ‪ pjsip‬را پیکربندی کرد‪ .‬ازآنجاکه‬
‫ماژول ‪ chan_sip.so‬غیرفعال شــده اســت‪ ،‬نمیتوان برای تعریف کاربران جدید از فایل ‪ sip.conf‬استفاده‬
‫نمود‪ .‬با توجه به اینکه فرمت و نوع پیکربندی این دو ماژول )‪ chan_sip‬و ‪ (pjsip‬با هم متفاوت اســت‪ ،‬ابتدا‬
‫باید با ساختار و نوع پیکربندی فایل ‪ pjsip.conf‬آشنا شوید‪.‬‬
‫ابتدا برای آشــنایی اولیه با ســاختار فایل ‪ ،pjsip.conf‬مثالهایی از پیکربندیهای یکسان در هر دو فایل‬
‫را نشان خواهیم داد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 448

pjsip ‫تعریف کاربران جدید در ماژول‬


sip.conf ‫ تنظیمــات این کاربــران در فایل‬.‫ داشــته باشــیم‬۶۰۰۲ ‫ و‬۶۰۰۱ ‫بــرای مثال فرض کنید دو کاربر‬
:‫بهصورت زیر است‬
;sip.conf
[general]
udpbindaddr=0.0.0.0

[6001]
type=friend
host=dynamic
disallow=all
allow=ulaw
context=internal
secret=1234

[6002]
type=friend
host=192.0.2.1
disallow=all
allow=ulaw
context=internal
secret=1234

:‫ بهصورت زیر است‬pjsip ‫معادل تنظیمات باال برای ماژول‬


;pjsip.conf
[simpletrans]
type=transport
protocol=udp
bind=0.0.0.0

[6001]
type = endpoint
transport = simpletrans
context = internal
disallow = all
allow = ulaw
aors = 6001
auth = auth6001

[6001]
type = aor
max_contacts = 1

[auth6001]
type=auth
449 ‫ در استریسک‬PJSIP ‫استفاده از ماژول‬

auth_type=userpass
password=1234
username=6001

[6002]
type = endpoint
transport = simpletrans
context = internal
disallow = all
allow = ulaw
aors = 6002
auth = auth6002

[6002]
type = aor
contact = sip:6002@192.0.2.1:5060

[auth6002]
type=auth
auth_type=userpass
password=1234
username=6001

pjsip ‫) در ماژول‬SIP-Trunk( ‫تعریف ترانک‌ها‬


‫ بهصورت زیر‬sip.conf ‫ در فایل‬،‫ ایجاد کنیم‬MyTrunk ‫چنانچه بخواهیم یک ترانک در استریســک به نام‬
:‫تنظیماتی را انجام دهید‬
[general]
udpbindaddr=0.0.0.0

register => myaccountname:1234567890@203.0.113.1:5060

[MyTrunk]
type=friend
secret=1234567890
username=myaccountname
host=203.0.113.1
disallow=all
allow=ulaw
context=from-external

:‫ بهصورت زیر است‬pjsip ‫معادل تنظیمات باال برای ماژول‬


[simpletrans]
type=transport
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 450

protocol=udp
bind=0.0.0.0

[MyTrunk]
type=registration
transport=simpletrans
outbound_auth=mytrunk
server_uri=sip:myaccountname@203.0.113.1:5060
client_uri=sip:myaccountname@192.0.2.1:5060

[MyTrunk]
type=auth
auth_type=userpass
password=1234567890
username=myaccountname

[MyTrunk]
type=aor
contact=sip:203.0.113.1:5060

[MyTrunk]
type=endpoint
transport=simpletrans
context=from-external
disallow=all
allow=ulaw
outbound_auth=mytrunk
aors=mytrunk

[MyTrunk]
type=identify
endpoint=mytrunk
match=203.0.113.1

‫ ولی جای هیچ گونه نگرانی‬،‫ کمی دشوار به نظر برسد‬pjsip ‫شــاید این تفاوت در ســاختار پیکربندی ماژول‬
‫ تبدیل‬pjsip.conf ‫ را به‬sip.conf ‫ در استریسک اسکریپتی وجود دارد که پیکربندی و تنظیمات فایل‬.‫نیست‬
:‫ فایل در مسیر زیر قرار دارد‬.‫میکند‬
# /path/to/asterisk/source/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py --help
Usage: sip_to_pjsip.py [options] [input-file [output-file]]
input-file defaults to 'sip.conf'
output-file defaults to 'pjsip.conf'
Options:
-h, --help show this help message and exit
-p PREFIX, --prefix=PREFIX
451 ‫ در استریسک‬PJSIP ‫استفاده از ماژول‬

output prefix for include files

‫ با تنظیمات‬sip_user.conf ‫ فرض کنید فایلی به نام‬.‫ مثالی را بررســی میکنیم‬،‫برای روشــنتر شــدن مطلب‬
:‫زیر داشتهباشیم‬
;sip_user.conf
[user](!)
qualify=yes
host=dynamic
nat=force_rport,comedia
port=5060
type=friend
context=python_agi
disallow=all
allow=ulaw,alaw
canreinvite=no
directmedia=no
callcounter=yes
permit=0.0.0.0/0.0.0.0
deny=0.0.0.0/0.0.0.0

[Phone_1](user)
secret=123123
context=LocalSets

[Phone_2](user)
secret=123123
context=LocalSets

pjsip ‫ ایجاد خواهدشــد که معادل تنظیمات ماژول‬pjsip_user.conf ‫ فایلی با نام‬،‫با اســتفاده از دســتور زیر‬
:‫خواهد بود‬
#cd /usr/src/asterisk-13.10.0/contrib/scripts/sip_to_pjsip/
#python sip_to_pjsip.py /etc/asterisk/sip_user.conf /etc/asterisk/pjsip_user.conf
Reading /etc/asterisk/sip_user.conf
Converting to PJSIP...
Writing /etc/asterisk/pjsip_user.conf

pjsip.conf ‫ برای این منظور فایل‬.‫ اضافه کنید‬pjsip.conf ‫ را به فایل اصلی‬pjsip_user.conf ‫اکنون باید فایل‬
:‫ فایل جدید را اضافه کنید‬،‫را باز و در انتهای آن‬
;pjsip.conf
#include pjsip_user.conf

pjsip. ‫ را به پیکربندی فایل‬sip.conf ‫ این اســکریپت میتواند پیکربندیهای فایل‬،‫با توجه به توضیحات باال‬
:‫ بهصورت زیر خواهد بود‬pjsip_user.conf ‫ محتویات فایل‬.‫ تبدیل و از آن استفاده کند‬conf
;pjsip_user.conf
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 452

[transport-udp]
type = transport
protocol = udp
bind =

[Phone_1]
type = aor
max_contacts = 1

[Phone_1]
type = auth
username = Phone_1
password = 123123

[Phone_1]
type = endpoint
context = LocalSets
disallow = all
allow = ulaw,alaw
rtp_symmetric = yes
force_rport = yes
rewrite_contact = yes
direct_media = no
auth = Phone_1
outbound_auth = Phone_1
aors = Phone_1

[acl]
type = acl
deny = 0.0.0.0/0.0.0.0
permit = 0.0.0.0/0.0.0.0

[Phone_2]
type = aor
max_contacts = 1

[Phone_2]
type = auth
username = Phone_2
password = 123123
[Phone_2]
type = endpoint
context = LocalSets
disallow = all
allow = ulaw,alaw
‫‪453‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫‪rtp_symmetric = yes‬‬
‫‪force_rport = yes‬‬
‫‪rewrite_contact = yes‬‬
‫‪direct_media = no‬‬
‫‪auth = Phone_2‬‬
‫‪outbound_auth = Phone_2‬‬
‫‪aors = Phone_2‬‬

‫استفاده از ماژول ‪ pjsip‬در محیط کامندالین استریسک‬


‫برای مشاهده وضعیت کاربرهای تعریف شده در استریسک‪ ،‬میتوان از دستورات زیر استفاده نمود‪ .‬میتوان‬
‫و خروجی آن را مشاهده نمود‪:‬‬ ‫هر یک از دستورات زیر را اجرا‬
‫‪CLI> pjsip show endpoints‬‬
‫‪CLI> pjsip show registration‬‬
‫‪CLI> pjsip show aor‬‬
‫‪CLI> pjsip show subscriptions‬‬
‫‪CLI> pjsip show settings‬‬

‫برای مثال با اجرای دستور زیر‪ ،‬کاربرهای ‪ Phone_1‬و ‪ Phone_2‬نشان داده میشوند‪:‬‬

‫‪CLI> pjsip show endpoints‬‬


‫‪Endpoint: Phone_1‬‬ ‫‪Unknown‬‬ ‫‪0 of inf‬‬
‫‪OutAuth: Phone_1/Phone_1‬‬
‫‪InAuth: Phone_1/Phone_1‬‬
‫‪Endpoint: Phone_2‬‬ ‫‪Unknown‬‬ ‫‪0 of inf‬‬
‫‪OutAuth: Phone_2/Phone_2‬‬
‫‪InAuth: Phone_2/Phone_2‬‬

‫استفاده از ماژول ‪ pjsip‬در برنامه‌نویسی استریسک‬


‫تا اینجا درباره نصب ماژول ‪ pjsip‬و پیکربندی آن توضیحاتی آمد‪ .‬برای استفاده از این ماژول در برنامهنویسی‬
‫استریسک باید بهصورت زیر عمل کنید‪:‬‬
‫‪;extensions.conf‬‬
‫)}‪exten => _6XXX,1,Dial(PJSIP/${EXTEN‬‬
‫)}‪exten => _9.,1,Dial(PJSIP/MyTrunk/${EXTEN:1‬‬

‫همانطورکه مالحظه میکنید استفاده از ماژول ‪ pjsip‬در برنامهنویسی استریسک‪ ،‬هیچ فرقی با سایر ‪Channel‬‬
‫‪Drive‬ها )از قبیل ‪ (… ,SIP,DAHDI,IAX‬ندارد‪.‬‬
‫در ادامه درباره پیکربندی فایل ‪ pjsip.conf‬بیشتر شرح خواهیم داد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪454‬‬

‫پیکربندی فایل ‪pjsip‬‬


‫فایــل ‪ ،pjsip.conf‬یــک فایل متنی و قابل خواندن اســت‪ .‬این فایل بخشهای مختلفــی دارد که هر بخش‬
‫با نام دلخواهی‪ ،‬نامگذاری میشــود‪ .‬معموالً بخشها با عالمت ] [ از هم جدا میشــوند و هر بخش شــامل‬
‫پارامترهایی با مقادیر معلوم است‪ .‬فرمت تعریف هر بخش بهصورت زیر است‪:‬‬
‫]>‪[<section name‬‬
‫>‪type=<value‬‬
‫>‪<ConfigOption1>=<value1‬‬
‫>‪<ConfigOption2>=<value2‬‬

‫در هر بخش پارامتری بنام ‪ type‬وجود دارد که مشــخصکننده نوع بخش و پارامترهای وابسته به پیکربندی‬
‫است‪ .‬در ادامه به بررسی انواع مقادیر پارامتر ‪ type‬میپردازیم‪.‬‬
‫• ‪ :Endpoint‬در حالت پیش‌فرض‪ ،‬اگر تصمیم داشــته باشــیم یک کاربر از نوع پروتکل ‪ SIP‬تعریف کنیم‪،‬‬
‫باید از مقدار ‪ type=endpoint‬اســتفاده کنیم‪ .‬در این حالت کاربر به عنوان یک عضو جدید در استریســک‬
‫درنظر گرفته می‌شــود (این روش همانند تعریف یک کاربر معمولی در فایل ‪ sip.conf‬با مقدار ‪type=friend‬‬
‫است)‪.‬‬
‫]‪[6001‬‬
‫‪type=endpoint‬‬
‫‪context=internal‬‬
‫‪disallow=all‬‬
‫‪allow=ulaw‬‬
‫‪transport=simpletrans‬‬
‫‪auth=auth6001‬‬
‫‪aors=6001‬‬

‫• ‪ :Transport‬می‌توان نحوه‌ی انتقال بسته‌ها را برای یک کاربر خاص‪ ،‬با پارامتر ‪ Transport‬مشخص کرد‪.‬‬
‫در این صورت پارامترهای این بخش‪ ،‬معرفی‌کننده‌ی نوع پروتکل ارتباطی هســتند‪ .‬می‌توان از پروتکل‌های‬
‫‪ TCP،UDP‬و ‪ TLS‬برای این بخش اســتفاده نمود‪ .‬به‌عنوان مثال چنانچه یک بخش جدید ایجاد و در آن از‬
‫پروتکل ارتباطی ‪ UDP‬استفاده کنیم‪ ،‬داریم‪:‬‬
‫]‪[transport-udp‬‬
‫‪type=transport‬‬
‫‪protocol=udp‬‬
‫‪bind=0.0.0.0‬‬

‫• ‪ :AUTH‬این بخش پارامترهای مرتبط با اعتبارسنجی تماس‌های ورودی و خروجی را نگه‌داری می‌کند‪ .‬در‬
‫این بخش‪ ،‬اعتبارسنجی تماس‌های ورودی و خروجی مرتبط با یک کاربر می‌تواند براساس ‪ IP‬و یا براساس‬
‫نام کاربری و رمز عبور (یا هر دو) صورت گیرد‪ .‬به مثال زیر توجه کنید‪.‬‬
‫]‪[auth6001‬‬
‫‪type=auth‬‬
‫‪auth_type=userpass‬‬
‫‪455‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫‪password=6001‬‬
‫‪username=6001‬‬

‫چنانچه بخواهیم کلمه عبور را بهصورت ‪ MD5‬ذخیره کنیم‪ ،‬در این صورت خواهیم داشت‪:‬‬
‫]‪[auth6001‬‬
‫‪type=auth‬‬
‫‪auth_type=md5‬‬
‫‪md5_cred=51e63a3da6425a39aecc045ec45f1ae8‬‬
‫‪username=6001‬‬

‫همانطورکه مالحظه میکنید در این مثال‪ ،‬اعتبارسنجی براساس الگوریتم ‪ MD5‬مشخص میشود‪.‬‬
‫• ‪ :AOR‬عبارت ‪ Address Of Record‬بیانگر آدرس کاربر در شــبکه اســت که به‌وسیله آن به سیستم تلفنی‬
‫استریســک رجیســتر شــده اســت‪ .‬به عبارت دیگر‪ AOR ،‬معرف آدرس آی‌پی یک کاربر است که سرور‬
‫استریســک در صورت نیاز‪ ،‬از طریق آن به کاربر دسترســی خواهد داشــت‪ .‬بدون ‪ ،AOR‬دسترسی به کاربر‬
‫امکان‌پذیر نیست‪ .‬هنگام رجیستر شدن یک کاربر‪ ،‬اطالعات ‪ AOR‬برای کاربر در استریسک ذخیره می‌گردد‪.‬‬
‫مثال‌هایی از کاربر ‪ AOR‬در نمونه زیر آمده است‪:‬‬
‫]‪[6001‬‬
‫‪type=aor‬‬
‫‪max_contacts=1‬‬

‫در این نمونه‪ ،‬رجیســتر شــدن داخلی ‪ ۶۰۰۱‬به یک دیوایس محدود شده اســت)در اینجا منظور از دیوایس‬
‫همان ‪ SIPPhone‬می باشــد(‪ ،‬یعنــی در هر لحظه فقط یک ‪ AOR‬برای کاربر ‪ ۶۰۰۱‬در استریســک ذخیره‬
‫میشــود‪ .‬به عبارت دیگر‪ ،‬اگر بهوســیله یک دیوایس روی ‪ ۶۰۰۱‬رجیستر شــویم‪ ،‬بهوسیله سایر دیوایسها‬
‫امکان رجیستر شدن وجود ندارد )در واقع مشکل ‪ Multi Registration‬در پروتکل ‪ chan_sip‬در این ماژول‬
‫برطرف شده است(‪ .‬برای روشنتر شدن موضوع‪ ،‬دو مثال را با هم بررسی میکنیم‪.‬‬
‫فرض کنید تنظیمات زیر را برای کاربر ‪ ۶۰۰۱‬داشته باشیم‪:‬‬
‫]‪[6001‬‬
‫‪type=aor‬‬
‫‪max_contacts=1‬‬

‫ازآنجاکــه پارامتر ‪ max_contacts=1‬تنظیم شدهاســت‪ ،‬تنها از روی یک دیوایس میتوان کاربر ‪۶۰۰۱‬‬
‫را رجیســتر نمود‪ .‬پس از رجیسترشــدن اولین دیوایس‪ ،‬اطالعات آن در کامندالین استریسک قابل مشاهده‬
‫خواهدبود‪:‬‬
‫>‪CLI‬‬
‫‪-- Added contact 'sip:6001@192.168.1.20:50982;rinstance=01c89ee48803955d' to AOR‬‬
‫‪'6001' with expiration of 120 seconds‬‬
‫‪== Contact 6001/sip:Phone_2@192.168.1.20:50982;rinstance=01c89ee48803955d has‬‬
‫‪been created‬‬
‫‪== Endpoint 6001 is now Reachable‬‬
‫>‪CLI‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪456‬‬

‫همچنین خروجی دستور ‪ pjsip show endpoints‬بهصورت زیر است‪:‬‬


‫‪CLI> pjsip show endpoints‬‬
‫ ‪Endpoint: 6001‬‬ ‫‪Not in use 0 of inf‬‬
‫‪OutAuth: 6001/6001‬‬
‫‪InAuth: 6001/6001‬‬
‫‪Aor: 6001‬‬ ‫‪1‬‬
‫‪Contact: 6001/sip:6001@192.168.1.20:5060;rins 81941ac707 Unknown nan‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید آدرس کاربر در شبکه‪ ،‬در پارامتر ‪ Contact‬نمایش داده میشود‪ .‬استریسک‬
‫از این آدرس برای ارسال تماس به ‪ ،۶۰۰۱‬استفاده میکند‪.‬‬
‫در مثال بعدی برای کاربر ‪ ۶۰۰۲‬پارامتر ‪ max_contacts=2‬تنظیم میشود‪ .‬در این وضعیت‪ ،‬کاربر ‪۶۰۰۲‬‬
‫میتواند تا حداکثر دو بار از دیوایسهای متفاوت رجیســتر شــود‪ aor .‬هم شــامل دو رکورد از اطالعات‬
‫رجیستر است‪ .‬این تنظیمات برای کاربر ‪ ۶۰۰۲‬به این صورت خواهد بود‪:‬‬
‫]‪[6002‬‬
‫‪type=aor‬‬
‫‪max_contacts=2‬‬

‫خروجی دستور ‪ pjsip show endpoints‬نیز بهصورت زیر نمایش داده میشود‪:‬‬
‫>‪CLI‬‬
‫ ‪Endpoint: 6002‬‬ ‫ ‪Not in use‬‬ ‫‪0 of inf‬‬
‫‪OutAuth: 6002/6002‬‬
‫‪InAuth: 6002/6002‬‬
‫‪Aor: 6002‬‬ ‫‪2‬‬
‫‪Contact: 6002/sip:6002@192.168.1.22:5060;rins 1fa557280a Unknown‬‬ ‫‪nan‬‬
‫‪Contact: 6002/sip:6002@192.168.1.27:5060;rins 81941ac707 Unknown‬‬ ‫‪nan‬‬
‫>‪CLI‬‬

‫همانطورکه مالحظه میکنید‪ ،‬اطالعات ‪ AOR‬مربوط به هر دو دیوایس‪ ،‬در استریســک ذخیره شده است‪.‬‬
‫در این حالت اگر استریسک به ارسال تماسی برای ‪ ۶۰۰۲‬اقدام کند‪ ،‬مالک آخرین دیوایسی خواهد بود که‬
‫‪ AOR‬آن برای استریسک ارسال شده است‪.‬‬
‫بهعنوان آخرین تمرین از این بخش‪ ،‬میتوان عملیات رجیسترشدن روی یک کاربر را برای یک آدرس‬
‫آیپی محدود کرد‪ .‬یعنی چنانچه درخواســت رجیسترشــدن از سوی یک آدرس آیپی معلوم ارسال شود‪،‬‬
‫درخواستی مورد قبول خواهد بود که مشابه پارامتر ‪ host‬در فایل ‪ sip.conf‬باشد‪ .‬برای مثال تنظیمات زیر را‬
‫برای کاربر ‪ ۶۰۰۳‬در نظر بگیرید‪:‬‬
‫]‪[6003‬‬
‫‪type=aor‬‬
‫‪contact=sip:6003@192.1681.32:5060 ; or contact=sip:192.1681.32:5060‬‬

‫دراین حالت اگر درخواست رجیسترشدن برای کاربر ‪ ۶۰۰۳‬از طرف آدرس آیپی ‪ 192.168.1.32‬دریافت‬
‫شود‪ ،‬مورد قبول واقع خواهد شد‪.‬‬
‫‪457‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫• ‪ :Registration‬گاهی نیاز است برای ایجاد تماس خروجی‪ ،‬عملیات رجیسترشدن را قبال انجام داده باشیم‪.‬‬
‫این نوع عملیات غالبا در شرایطی پیش می‌آید که بخواهیم از ‪ ‌ITSP‬هایی استفاده کنیم که ازطریق عملیات‬
‫‪1‬‬

‫‪ ،registration‬تماس‌ها را می‌پذیرند‪ .‬در غیر این صورت هیچ تماسی را نخواهند پذیرفت‪.‬‬
‫]‪[mytrunk‬‬
‫‪type=registration‬‬
‫‪transport= transport-udp‬‬
‫‪outbound_auth=mytrunk‬‬
‫‪server_uri=sip:myaccountname@203.0.113.1:5060‬‬
‫‪client_uri=sip:myaccountname@192.0.2.1:5060‬‬
‫‪retry_interval=60‬‬

‫یا از معادل آن بهصورت زیر استفاده میکنیم‪:‬‬


‫]‪[mytrunk‬‬
‫‪type=registration‬‬
‫‪transport=simpletrans‬‬
‫‪outbound_auth=mytrunk‬‬
‫‪server_uri=sip:sip.example.com‬‬
‫‪client_uri=sip:1234567890@sip.example.com‬‬
‫‪retry_interval=60‬‬

‫• ‪ :Domain_Alias‬می‌تــوان برای ‪‌Domain‬ها در تعریف پیکربندی‪ ،‬از ‪ alias‬اســتفاده کرد‪ .‬به‌عنوان مثال‬
‫فرض کنید بخواهیم در مثال قبل برای ‪ example.com‬یک ‪ alias‬جدید ایجاد کنیم ‪:‬‬
‫]‪[example2.com‬‬
‫‪type=domain_alias‬‬
‫‪domain=example.com‬‬

‫• ‪ :ACL‬گاهی نیاز اســت تماس‌های ورودی به استریســک کنترل و مدیریت شود‪ ،‬در این صورت می‌توان‬
‫از ‪ ACL‬استفاده نماییم‪.‬‬
‫]‪[acl‬‬
‫‪type=acl‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=209.16.236.0‬‬
‫‪permit=209.16.236.1‬‬

‫همچنین میتوان بهجای استفاده از آدرس آی پی ‪ ،‬از ‪ contact headrs‬در فیلدهای ذخیره شده پروتکل ‪SIP‬‬
‫استفاده نمود‪ .‬در این صورت ‪ ACL‬بهصورت زیر تعریف میشود‪:‬‬
‫]‪[acl‬‬
‫‪type=acl‬‬
‫‪contactdeny=0.0.0.0/0.0.0.0‬‬
‫‪contactpermit=209.16.236.0‬‬
‫‪contactpermit=209.16.236.1‬‬

‫ازآنجاکه فیلد ‪ header‬در پروتکل ‪ SIP‬از آی پی محلی کاربر استفاده میکند‪ ،‬در این نوع از سیاستگذاری‬
‫‪1- Internet Telephony Service Provider‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪458‬‬

‫هدف ما اعمال سیاستگذاری روی فیلد ‪ header‬در پروتکل ‪ SIP‬است‪.‬‬


‫• ‪ :Identify‬با این پارامتر مشــخص می‌کنیم که تماس‌های ورودی از طرف یک ‪ endpoint‬باید با آی پی‬
‫مورد نظر مطابقت داشته باشد تا استریسک آن‌ها را بپذیرد‪:‬‬
‫]‪[6001‬‬
‫‪type=identify‬‬
‫‪endpoint=6001‬‬
‫‪match=203.0.113.1‬‬

‫تعیینشده‪ ،‬تماس وارد شود‪ ،‬پذیرفته خواهد شد‪.‬‬ ‫در این حالت اگر از طرف کاربر ‪ ۶۰۰۱‬و آی پی‬
‫• ‪ : Contact‬در بخــش مربــوط بــه ‪ AOR‬توضیح داده شــد که می‌تــوان صریحاً آدرس آی پــی را برای‬
‫کاربر تعیین کرد‪ ،‬به‌طوری‌که در تماس‌های ورودی‪ ،‬در صورتی که درخواســتی از ســوی این آی پی باشد‪،‬‬
‫استریســک آن را به‌صورت ‪ Trust IP‬در‌نظر‌ بگیرد و تماس ورودی را ثبت نماید‪ .‬می‌توان به‌صورت کام ً‬
‫ال‬
‫مســتقل‪ ،‬یک بخش مرتبط با ‪ contact‬برای هر کاربر در نظر گرفت و اطالعات مورد نیاز را در آن قرار داد‪.‬‬
‫در واقــع در ایــن بخش‪ ،‬اطالعاتی در خصوص اعتبارســنجی تماس‌های ورودی به استریســک قرار خواهد‬
‫گرفت‪.‬‬
‫تا اینجا انواع بخش‌هایی بررســی شــدکه در پیکربندی فایل ‪ pjsip‬ازآن‌ها استفاده می‌شود‪ .‬برای درک‬
‫بهتر هر یک از این مفاهیم‪ ،‬باید پیکربندی‌های مختلفی را در فایل ‪ sip.conf‬ایجاد وسپس به‌وسیله اسکریپت‬
‫‪ sip_to_pjsip.py‬به فایل ‪ pjsip.conf‬تبدیل کرد‪ .‬در این روش‪ ،‬هر بخش بهتر درک می‌شود‪.‬‬
‫شکل ‪ 2-16‬ارتباط میان انواع ‪‌type‬ها در پیکربندی فایل ‪ pjsip‬را نمایش می‌دهد‪.‬‬

‫شکل ‪2-16‬‬
‫‪459‬‬ ‫استفاده از ماژول ‪ PJSIP‬در استریسک‬

‫نتیجه‌گیری‬
‫همانطورکه پیشتر توضیح دادیم‪ ،‬ماژول ‪ pjsip‬از نســخه استریســک ‪ ۱۲‬به بعد اضافه شدهاست‪ .‬استفاده از‬
‫این ماژول قابلیتهای بسیاری را در اختیار ما قرار میدهد و میتوان از آن بهجای ماژول ‪ chan_sip‬استفاده‬
‫کرد‪ .‬این فصل نصب و راهاندازی ماژول ‪ pjsip‬در استریسک بررسی شد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪460‬‬
‫فصل هفدهم‬
‫مانیتورینگ و بررسی گزارش‌ها‬
‫در استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪462‬‬

‫مقدمه‬
‫در گذشتههای نه چندان دور تنها دو نوع شبکه داشتیم‪ :‬شبکههای مخابراتی‪ 1‬و شبکههای کامپیوتری‪. 2‬‬
‫شبکه‌های مخابراتی عمدتاً برای ارائه سرویس‌های مخابراتی استفاده می‌شدند و کاربرد دیگری نداشتند‪،‬‬
‫در مقابل‪ ،‬شبکه‌های کامپیوتری عمدتاً برای انتقال دیتا استفاده می‌شوند‪.‬‬
‫در چند ســال اخیر با رشــد هر دو شــبکه‪ ،‬این دو با هم‪ ،‬همگرا‪ ۳‬و به هم نزدیکتر شــدهاند‪ ،‬بهطوریکه‬
‫تکنولوژیای که در هر شــبکه مورد اســتفاده قرار میگیرد‪ ،‬در سایر شبکهها نیز استفاده میشود و میتوانند‬
‫از سرویسهای یکدیگر اســتفاده کنند‪ .‬بهعنوان مثال سرویس‪ ،Voice‬قب ً‬
‫ال بهوسیله شبکههای مخابراتی ارائه‬
‫شده بود‪ ،‬ولی امروزه از سرویس )‪ (Voice Over IP‬در شبکههای ‪ IP‬استفاده میشود‪.‬‬
‫ادغام شبکهها با یکدیگر باعث شده مدیریت این شبکهها پیچیدهتر شود‪ .‬در سیستم مدیریت شبکه باید‬
‫تجهیزات ســختافزاری و سرویسهای داخل شبکه را دائماً مانیتور کرد تا عملکرد صحیحی داشته باشند و‬
‫شبکهها در حالت »‪ «Up&Running‬قرار گیرند‪.‬‬
‫اصطالح »‪ «Up&Running‬در یک شــبکه‪ ،‬به معنای زنده بودن و فعالبودن شــبکه اســت‪ .‬برای مثال‬
‫روترها‪ ،‬ســرورها و ســرویسها و کلیه ارتباطات میان آنها باید عملکرد صحیحی داشته باشند تا شبکهها به‬
‫درســتی کار کنند‪ .‬مثال فرض کنید یک شــبکه ویپ طراحی کرده باشید‪ .‬ابتدا به علت تعداد کم مشتری و‬

‫‪1- Telecom Network‬‬


‫‪2- Computer Network‬‬
‫‪3- Converge‬‬
‫‪463‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫نبود ترافیک باال‪ ،‬شــبکه دائما در حال »‪ «Up&Running‬اســت‪ .‬پس از گذشت مدتی‪ ،‬با افزایش مشتریان‪،‬‬
‫شبکه نمیتواند به خوبی سرویس دهد و منجر به نارضایتی مشتریان از سرویسهای ارائه میشود و در نهایت‬
‫شــبکه‪ ،‬کارایی خود را از دســت میدهد‪ .‬در چنین شــرایطی مدیریت شــبکه باید بتواند به درستی شبکه را‬
‫مدیریت کند تا شبکه در وضعیت »‪ «Up&Running‬بماند‪.‬‬
‫تعریــف ســاده ای از ‪ Up&Running‬بودن یک شــبکه را اصطالحــا ‪ OAM&P‬میگویند که در ادامه‬
‫بررسی خواهد شد‪.‬‬

‫چهار حوزه مدیریت متفاوت شبکه‬


‫‪ : Operation -1‬فعالیت‌هــا و کار‌هــای روزمره‌ای که باید برای شــبکه انجام دهیــد از قبیل کانفیگ‌کردن‬
‫تجهیزات‪ ،‬مانیتور کردن و ‪. ...‬‬
‫‪ : Administration -2‬شامل تصمیمات کلی در روند اجرای شبکه است‪ .‬این حوزه در یک سطح باالتر از‬
‫‪ operation‬است‪.‬‬
‫‪ :Maintenance -3‬شامل خرابی‌هایی است که در شبکه رخ می‌دهد و بالفاصله باید تشخیص داده و برطرف‬
‫شوند‪.‬‬
‫‪ :Provisioning -4‬شامل ارائه سرویس به مشتریان است‪ .‬درواقع هر شبکه باید خدماتی به مشتریان ارائه دهد‪.‬‬

‫مدیریت شبکه (‪)Network Manager System‬‬

‫مدیریت شــبکه شامل همه ابزارها و امکانات‪ ،‬پروتکلها و فرآیندهایی است که با استفاده از آنها‪ ،‬عملیات‬
‫‪ OAM&P‬انجام میشود‪).‬شکل ‪(۱-۱7‬‬

‫شکل ‪1-17‬‬

‫نکته مهم برای مدیریت شبکه این است که تعاریف و دستهبندیهای دیگری از مدیریت شبکهها نیز میتوان‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪464‬‬

‫داشــت که هر یک از زاویهای خاص‪ ،‬مدیریت شــبکه را بررسی میکنند‪ ،‬ولی همگی یک هدف مشترک‬
‫را دنبال میکنند‪.‬‬

‫انواع تقسیم بندی‌های مدیریت شبکه‬


‫مدیریت شبکه را می توان از دیدگاه های متفاوتی بررسی کرد که در ذیل آنها را معرفی می کنیم‪.‬‬
‫‪ (۱‬مدیریت شبکه از نظر ابزارها‪ ،‬فرایندها و پروتکلها )‪ (OAM&P‬؛‬
‫‪ (۲‬مدیریت شبکه از نظر فعالیت‪ ۱‬در شبکه از نگاه سازمان استاندارد ‪(FCAPS) ISO‬؛‬
‫‪ (۳‬مدیریت شبکه از نظر الیهبندی‪ ۲‬از نگاه سازمان استاندارد ‪(TMN) ITU‬؛‬
‫‪ (4‬مدیریت شبکه از نظر مدل تجاری‪.(eTOM) ۳‬‬

‫اهمیت مدیریت شبکه‌های ‪VoIP‬‬


‫دیدگاه تجاری‪ ،‬یکی از دیدگاههای غالب در بخش مدیریت شبکههای ‪ VoIP‬است‪ .‬شبکههای مخابراتی و‬
‫شــبکههای زیرساخت‪ ،‬از جمله شــبکههای تجاری بزرگاند که نگاه مدیریتی در آنها‪ ،‬نگاه تجاری است‪.‬‬
‫هدف اصلی این نوع شبکهها‪ ،‬ایجاد درآمد است و به دو فاکتور مهم درآمد در مقابل هزینه توجه میشود‪.‬‬
‫استریســک بهعنوان یک سافت سوئیچ در شــبکههای ‪ VoIP‬میتواند در بخشهای مختلف‪ ،‬ماژولهای‬
‫متفاوتی را برای مانیتورینگ در اختیار گذارد‪.‬‬
‫خواهیم پرداخت‪.‬‬ ‫در ادامه فصل به بررسی ماژولهای مانیتورینگ و مدیریت در استریسک‬

‫فایل پیکربندی ‪ logger‬در استریسک‬


‫یکی از ابزارهای مفید و کاربردی برای خطایابی در سیستم تلفنی استریسک‪ ،‬استفاده از فایل‪ logger‬است‪.‬‬
‫این فایل در مسیر زیر قرار دارد‪:‬‬
‫‪#vim /etc/asterisk/logger.conf‬‬

‫در این فایل میتوان کلیه گزارشها و الگهای سرویس استریسک را در سطوح مختلف تنظیم و سپس در‬
‫فایلهای مشخصی ذخیره نمود‪ .‬فرمت تعریف این گزارشها در این فایل بهصورت زیر است‪:‬‬
‫]]]‪filename => type[,type[,type[,...‬‬

‫برای مثال فایل ‪ logger.conf‬در استریسک را باز و پیکربندی آن را مشاهده کنید‪:‬‬


‫‪; logger.conf‬‬
‫]‪[general‬‬
‫]‪[logfiles‬‬
‫‪console => notice,warning,error,dtmf‬‬

‫‪1- function‬‬
‫‪2- layers‬‬
‫‪3- business‬‬
465 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

:‫ گزارشها در سطح زیر نمایش داده میشوند‬،‫ استریسک‬console ‫ در محیط‬،‫همانطورکه مالحظه میکنید‬
• notice
• warning
• error
• dtmf

/var/log/asterisk/ ‫همچنین میتوان گزارشهایی )در ســطوح مختلف و مورد نظر( در فایلهایی در مســیر‬
‫ در‬،‫ فرض کنید بخواهیم گزارشهای کاملی از استریســک در تمامی ســطوح‬،‫ بهعنوان تمرین‬.‫ذخیره کرد‬
.‫ داشته باشیم‬/var/log/asterisk ‫ در مسیر‬full ‫فایل‬
:‫ وارد کنیم‬logger.conf ‫در این صورت باید تغییرات زیر را در فایل‬
full => notice,warning,error,debug,verbose,dtmf,fax

reload ‫ را‬logger ‫ ماژول‬،‫ باید در محیط کامندالین استریســک‬logger.conf ‫پس از ورود تغییرات در فایل‬
:‫نماییم‬
CLI> loger reload

‫ گزارش های کاملی از استریســک در تمامی ســطوح در فایل زیر ایجاد‬،‫ کردن ماژول فوق‬reload ‫بعد از‬
.‫خواهد شد‬
/var/log/asterisk/full

‫ انواع گزارشها را نشان‬۱-۱7‫ جدول‬.‫ ســطوح متفاوتی برای ایجاد گزارشها و الگ داریم‬logger ‫در فایل‬
.‫میدهد‬

Type Description
notice You will see a lot of these during a reload, but they will also happen during normal call flow. A notice is
simply any events that Asterisk wishes to inform you.
warning A warning represents a problem that could be severe enough to affect a call (including disconnecting a call
because call flow cannot continue). Warnings need to be addressed.
error Errors represent significant problems in the system that must be addressed immediately.
debug Debugging is only useful if you are troubleshooting a problem with the asterisk code itself. You would not
use debug to troubleshoot your dialplan, but you would use it if the Asterisk developers asked you to provide
logs for a problem you were reporting. Do not use debug in production, as the amount of detailes stored can
fill up a hard drive in matter of days.
verbose This is the most useful of the logging type, but it is also one of the more risky to leave unattended, due to
the possibility of the output filling your hard drive.
dtmf Logging DTMF can be helpful if you are getting complaints that calls are not routing from the auto attendant
correctly
fax This type of logging causes fax-related messages from the fax technology backend (res_fax_spandsp or
res_fax_digium) to be logged to the fax logger.
* This will log EVERYTHING (and we mean everything). Do not use this unless you understand the
implication of storing this amount of data. It will not end well.
1-17 ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪466‬‬

‫در استریســک برای مشــاهده وضعیت ‪ logger‬ها میتوانید از دســتور زیر در کامندالین استریسک استفاده‬
‫نمایید‪:‬‬
‫‪CLI> logger show channels‬‬
‫‪Channel‬‬ ‫‪Type Status Configuration‬‬
‫‪-------‬‬ ‫‪---- ------ -------------‬‬
‫‪/var/log/asterisk/full‬‬ ‫‪File Enabled - DEBUG NOTICE WARNING ERROR VERBOSE‬‬
‫‪DTMF FAX‬‬
‫‪/var/log/asterisk/messages File Enabled - NOTICE WARNING ERROR‬‬
‫‪Console Enabled - NOTICE WARNING ERROR‬‬
‫>‪CLI‬‬

‫همچنیــن میتوانید در فایل ‪ logger.conf‬تنظیماتی صورت دهید تا گزارشهایی از عملکرد سیســتم تلفنی‬
‫استریسک را در ‪ syslog‬به شما نمایش دهد‪ .‬برای مثال این تنظیمات را در فایل ‪ logger.conf‬انجام دهید‪.‬‬
‫‪syslog.local0 => notice,warning,error‬‬

‫اکنون اگر بهوســیله دســتور ‪ tail‬محتویات فایل ‪ syslog‬را بررسی کنید‪ ،‬گزارشات زیر از طرف استریسک‬
‫در این فایل ثبت خواهدشد‪.‬‬
‫‪# tail -f /var/log/syslog‬‬
‫‪Aug 29 06:40:50 ubuntu14 asterisk[1099]: NOTICE[64124][C-00000034]: chan_sip.c:6812 in‬‬
‫‪update_call_counter: Call to peer '100' rejected due to usage limit of 1‬‬
‫‪Aug 29 06:40:54 ubuntu14 asterisk[1099]: NOTICE[64126][C-00000035]: chan_sip.c:6812 in‬‬
‫‪update_call_counter: Call to peer '100' rejected due to usage limit of 1‬‬
‫‪Aug 29 06:41:07 ubuntu14 asterisk[1099]: NOTICE[64127][C-00000036]: app_queue.c:7733‬‬
‫'‪in aqm_exec: Added interface 'SIP/100' to queue 'myqueue‬‬
‫‪Aug 29 06:41:15 ubuntu14 asterisk[1099]: NOTICE[64128][C-00000037]: app_queue.c:7659‬‬
‫'‪in rqm_exec: Removed interface 'SIP/100' from queue 'myqueue‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در استریسک گزارشهای این ماژول میتواند در سطوحی متفاوت‪ ،‬اطالعات‬
‫در اختیار ما قرار دهد‪.‬‬

‫گزارش جزئیات تماس‌ها در استریسک‬


‫پیشتر نیز اشــاره شد که ماژول ‪ ۱ CDR‬در استریســک‪ ،‬مسئول کنترل و مدیریت کلیه الگهای تماسهای‬
‫ورودی و خروجی در سیســتم تلفنی اســت‪ .‬این ماژول بهصورت پیشفرض‪ ،‬کلیه گزارشهای تماسهای‬
‫ورودی و خروجی را در فایلی به نام ‪ Master.csv‬ذخیره میکند‪ .‬این فایل در مسیر فایلهای الگ استریسک‬
‫‪ /var/log/asterisk/cdr-csv/Master.csv‬قرار دارد‪ .‬به عبارت دیگر فایل‪ Master.csv‬یک فایل متنی است‬
‫که کلیه گزارش های ‪ CDR‬در آن نوشته و با کاما از هم جدا شدهاند‪ .‬برای مثال این فایل را باز و محتویات‬
‫آن را بررسی کنیم‪ .‬بنابراین دستور زیر را اجرا کنید‪:‬‬

‫‪1- Call Detail Records‬‬


467 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

# vim /var/log/asterisk/cdr-csv/Master.csv

‫ کلیه اطالعات و فیلدهای مربوط به هر تماس ثبت شده‬،‫از اطالعات این فایل مشاهده میشود که در هر سطر‬
.‫است که در ادامه به بررسی سطرها و فیلدهای موجود در آنها خواهیم پرداخت‬

CDR ‫فیلدهای موجود در ماژول‬


‫ جدول‬.‫ فیلدهایی را در نظر گرفته است و آنها را مقداردهی میکند‬،‫این ماژول برای ثبت گزارش تماسها‬
.‫ استفاده میشوند را نشان میدهد‬CDR ‫ فیلدهای مهمی که در ماژول‬۲-۱7

Options Value/Example Notes


accountcode 12345 An account ID. This field is user-defined and is empty by deafult.
src 12565551212 The calling party's caller ID number. It is set automatically and is read-only.
dst 102 The destination extension for the call. The field is set automatically and is
read-only.
dcontext Public Extension The destination context for the call. The field is set automatically and is
read-only.
clid "Big Bird" The full caller ID, including the name, of the calling party. This field is set
<12565551212> automatically and is read-only.

channel SIP/0004F2040808 - The calling party's channel. This held is set automaticaly and is read-only.
ab1bc23et
dstchannel SIP/ The called part channel_ This field is set automatically and is read-only.
0004F2046969-9786b0b0
lastapp Dial The last dialpian application that was executed. This field is set automatically
and is read-only.
lastdata SIP/ The arguments passed to the las t app. This field is set automatically and is
0004F2046969,30,tT read-only.
start 2010-10-26 12:00:00 The start tune of the cal. This field is set automatically and is read-only.
answer 2010-10-26 12:00:15 The answered time of the call This field is set automatxally and is read-only.
end 2010-10-26 12:03:15 The end time of the call. This field is set automatically and is read-only.
duration 195 The nurnber of seconds between the start and end times for the call. This
field is set automatically and is read-only.
billsec 180 The number of seconds between the answer and end times for the call This
field is set automatically and is read-only.
disposition ANSWERED An indication of what happened to the call. This may be NO ANSWER,
FAILED, BUSY, ANSWERED, or UNKNOWN.
amaflags DOCUMENTATION The Automatic Message Accounting (AMA) flag associated with this call.
This may be one of the followng. WIT, BILL INC, DOCUME N TAT ION, or
Unknown.
userfield PerMinuteCharge:0.02 A vneral-purpose use field. This field is empty by default and can be set to a
user -defined string.'
Uniqueid 1288112400.1 The unique ID for the sr c channel This field is set automatically and is
read-only.
2-17 ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪468‬‬

‫گزارشهای ذخیره شــده در هر ســطر از فایل ‪ ، Master.csv‬در واقع مقادیر تعریف شــده برای هر یک از‬
‫فیلدهای جدول ‪ ۲-۱7‬است که با عالمت "کاما" از هم جدا شدهاند‪.‬‬
‫در برنامهنویســی استریسک میتوان با استفاده از تابع ‪ ،CDR‬به هر یک از فیلدها دسترسی داشت‪ .‬برای‬
‫آشــنایی بیشتر با نحوهی اســتفاده از این تابع در برنامهنویسی‪ ،‬دســتور زیر را در کامندالین استریسک اجرا‬
‫نمایید‪:‬‬
‫‪CLI> core show function CDR‬‬

‫همانطورکه مالحظه میکنید‪ ،‬میتوان هر فیلد مورد نیاز را با استفاده از این تابع در برنامه استریسک بهکار‬
‫برد‪ .‬برای مثال فرض کنید برنامه زیر را داشته باشیم‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 600,1,Answer‬‬
‫)})‪same => n,NoOp(Call start time:${CDR(start‬‬
‫)‪same => n,Wait(5‬‬
‫)})‪same => n,NoOp(Call duration:${CDR(duration‬‬

‫خروجی برنامه باال بهصورت زیر است‪:‬‬


‫‪CLI> console dial 600@LocalSets‬‬
‫‪-- Executing [600@LocalSets:1] Answer("Console/dsp", "") in new stack‬‬
‫>> ‪<< Console call has been answered‬‬
‫‪-- Executing [600@LocalSets:2] NoOp("Console/dsp", "Call start time:2016-08-29‬‬
‫‪09:03:55") in new stack‬‬
‫‪-- Executing [600@LocalSets:3] Wait("Console/dsp", "5") in new stack‬‬
‫‪-- Executing [600@LocalSets:4] NoOp("Console/dsp", "Call duration:5") in new stack‬‬
‫'‪-- Auto fallthrough, channel 'Console/dsp' status is 'UNKNOWN‬‬
‫>‪CLI‬‬

‫در این مثال از برنامه خواســتیم که زمان شــرو ِع تماس و مدت زمانی که تماس طول کشــیده را نشان دهد‪.‬‬
‫بــا این روش میتوان بــه راحتی هر کدام از فیلدهای مورد نیاز از تابع ‪ CDR‬را در برنامه داشــت و از آنها‬
‫استفاده کرد‪.‬‬
‫نکتــه مهم در خصوص فیلدهای ماژول ‪ CDR‬این اســت که اکثر آنها خاصیــت ‪ Readonly‬دارند و ما‬
‫نمیتوانیم در برنامههای خود مقدار آنها را تغییر دهیم‪ .‬برای مثال برنامهی زیر را در نظر بگیرید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 601,1,Answer‬‬
‫)})‪same => n,NoOp(Call start time:${CDR(start‬‬
‫)‪same => n,Wait(5‬‬
‫)})‪same => n,NoOp(Call duration:${CDR(duration‬‬
‫)‪same => n,Set(CDR(duration)=0‬‬
‫)})‪same => n,NoOp(Call duration after reset:${CDR(duration‬‬
469 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

:‫خروجی برنامه بهصورت زیر است‬


CLI> console dial 601@LocalSets
-- Executing [601@LocalSets:1] Answer("Console/dsp", "") in new stack
<< Console call has been answered >>
-- Executing [601@LocalSets:2] NoOp("Console/dsp", "Call start time:2016-08-29
09:05:53") in new stack
-- Executing [601@LocalSets:3] Wait("Console/dsp", "5") in new stack
-- Executing [601@LocalSets:4] NoOp("Console/dsp", "Call duration:5") in new stack
-- Executing [601@LocalSets:5] Set("Console/dsp", "CDR(duration)=0") in new stack
[Aug 29 09:05:59] ERROR[1178]: cdr.c:2941 ast_cdr_setvar: Attempt to set the 'duration'
read-only variable!
-- Executing [601@LocalSets:6] NoOp("Console/dsp", "Call duration after reset:5") in new
stack
-- Auto fallthrough, channel 'Console/dsp' status is 'UNKNOWN'
CLI>

‫ نمایش داده‬،‫ است‬Readonly ‫ مبنی بر اینکه این تابع بهصورت‬ERROR ‫ پیام‬،‫همانطورکه مالحظه میکنید‬
.‫شده است‬
‫ برای مثال‬.‫ اضافه کنیم‬Master.csv ‫ و فایل‬CDR ‫گاهی الزم میشــود که فیلدهای جدید را به جــدول‬
‫ تصمیم داریم تماسهای خاصی را که مسیر از قبل تعیینشدهای را در‬،‫تصور کنید که در برنامه استریســک‬
‫ هرچند‬.‫ بهتر اســت مثال را کمی واضحتر و ســادهتر مطرح کنیم‬.‫ مشــخص کنیم‬CDR ‫ در‬،‫پیش میگیرند‬
‫ اینجا بیشــتر کاربرد فیلد‬،‫این فرایند خیلی ســاده اســت و حتماً روشهای بهتری برای انجام آن وجود دارد‬
.‫ مد نظر است‬CDR ‫ در ماژول‬userfield
‫ و چند درصد به‬،‫فرضکنیــد قصد داریم تعییــن کنیم که چند درصد از تماسهای ما به بخــش فروش‬
‫ فیلد‬،‫ اینجا سادهترین کار این اســت که ابتدای اجرای برنامه در هر بخش‬.‫بخش پشــتیبانی متصل میشــود‬
:‫ برای مثال این برنامه را در نظر بگیرید‬.‫ را با مقداری مناسب مقداردهی کنیم‬userfiled
[from-pstn]
exten => start,1,Answer()
same => n,BackGround(welcome)
same => n,WaitExten(5)

exten => 1,1,Set(CDR(userfiled)=sales queue)


same => n,Queue(sales)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()

exten => 2,1,Set(CDR(userfiled)=support queue)


same => n,Queue(support)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪470‬‬

‫)‪exten => i,1,Playback(pbx-invalid‬‬


‫)‪same => n,Goto(start,1‬‬

‫)‪exten => t,1,Playback(vm-goodbye‬‬


‫)(‪same => n,Hangup‬‬

‫در ایــن مثال‪ ،‬مقدار فیلــد ‪ userfiled‬را قبل از اجرای برنامه در هر بخــش‪ ،‬مقداردهی کردیم‪ .‬اینجا از فیلد‬
‫‪ userfiled‬استفاده شد‪ .‬حتی میتوان یک فیلد جدید در ماژول ‪ CDR‬ایجاد و آنها را مقداردهی کرد‪ .‬برای‬
‫اینکار باید از ‪ CDR backend‬استفاده کنید‪.‬‬
‫همانطور که قب ً‬
‫ال توضیح داده شــد‪ ،‬در یک سیســتم تلفنی‪ ،‬داشتن گزارش کامل از تماسهای ورودی‬
‫و خروجــی و همچنین نحوهی اســتفاده از ایــن گزارشها‪ ،‬از اهمیت باالیی برخوردار اســت‪ .‬ازآنجاکه در‬
‫استریســک بهصورت پیشفرض گــزارش کلیهی تماسها در فایــل ‪ master.csv‬ذخیره میشــود‪ ،‬بازیابی‬
‫اطالعات و نحوه اســتفاده از آنها‪ ،‬کاری دشوار و پیچیده است‪ .‬برای انجام اینکار باید از ‪CDR backend‬‬
‫استفادهکنید‪.‬‬

‫استفاده از ‪ CDR Backend‬در استریسک‬


‫استریسک بهوسیله این ماژول‪ ،‬این قابلیت را فراهم میآورد که بتوان گزارش کلیه تماسها را در پایگاههای‬
‫داده ذخیره کرد‪ .‬برای اســتفاده از هر نوع پایگاه داده )‪ MySQL, PostgreSQL‬و غیره(‪ ،‬باید ماژول مربوط‬
‫به آن را مشخص کرد و تنظیمات الزم را انجام داد‪.‬‬
‫ازآنجاکه این فصل بسیار به فصل یازدهم )ارتباط استریسک با پایگاه های دادهای( وابسته است‪ ،‬چنانچه‬
‫ابهامی در مفاهیم وجود داشته باشد‪ ،‬به فصل یازدهم مراجعه کنید‪.‬‬
‫در این فصل فرض میکنیم ‪ ODBC Connector‬ها نصب هستند و ارتباط آنها با استریسک برقرار شده‬
‫است‪ .‬اکنون باید پیکربندی و تنظیمات انواع ماژولهای ذخیرهسازی گزارشها در پایگاههای داده را انجام‬
‫داد‪.‬‬
‫همانطورکــه پیش از این گفته شــد‪ ،‬استریســک باید بتواند بــا ‪ ODBC‬ها ارتباط برقــرار کند‪ .‬بعد از‬
‫اینکــه یک ‪ ODBC Connector‬ایجاد شــد‪ ،‬باید بتوان ارتباط آن را با هر پایــگاه دادهای برقرار نمود‪ .‬این‬
‫ارتباط ازطریق تنظیمات پیکربندی در فایل ‪ res_odbc.conf‬ایجاد میشود‪ .‬برای مثال این تنظیمات میتواند‬
‫بهصورت زیر باشد‪:‬‬
‫‪;res_odbc.conf‬‬
‫]‪[asterisk‬‬
‫‪enabled => yes‬‬
‫‪dsn => asterisk-connector‬‬
‫‪username => root‬‬
‫‪password => 123123‬‬
‫‪471‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫‪pooling => no‬‬


‫‪limit => 1‬‬
‫‪pre-connect => yes‬‬

‫بــرای پیکربندی گزارشــات جزئیات تمــاس در پایگاههــای دادهای )‪ (CDR Backend‬میتوان از دو فایل‬
‫استفاده کرد؛ )‪ (۱‬استفاده از فایل ‪ cdr_mysql.conf‬و )‪ (۲‬استفاده از فایل ‪.cdr_adaptive_odbc.conf‬‬
‫اســتفاده از روش دوم بسیار مرسومتر اســت‪ .‬همانطور که از اسم آن )‪ (adaptive‬پیداست‪ ،‬دارای یک‬
‫ساختار انطباقی است‪ .‬در این روش اگر فیلدهایی از ‪ CDR‬در جدول وجود نداشته باشد و یا یک فیلد اضافه‬
‫در جدول وجود داشته باشد‪ ،‬ماژول از آنها صرفنظر کرده و سایر فیلدهای موجود در جدول را مقداردهی‬
‫میکند‪ .‬در مقابل‪ ،‬در روش اول چنین انطباقی وجود ندارد که شــما را با مشکالتی مواجه میکند‪ .‬بنابراین‪،‬‬
‫در این فصل از روش دوم استفاده خواهیم کرد‪.‬‬

‫استفاده از فایل ‪cdr_adaptive_odbc.conf‬‬


‫برای این منظور از فایل ‪ cdr_adaptive_odbc.conf‬برای پیکربندی ‪ CDR Backend‬اســتفاده میکنیم‪ .‬این‬
‫فایل در مسیر زیر قرار دارد‪:‬‬
‫‪# vim /etc/asterisk/cdr_adaptive_odbc.conf‬‬

‫قبل از ادامه بحث‪ ،‬باید یک جدول بهنام ‪ cdr‬در دیتابیس ‪ asterisk‬ایجاد کنید‪ .‬دستورات زیر را در کامندالین‬
‫‪ MySQL‬انجام دهید‪:‬‬
‫‪# mysql –uroot –p‬‬
‫‪Enter password:‬‬
‫;‪mysql>CREATE DATABASE asterisk‬‬

‫با اجرای این دستور یک دیتابیس جدید بهنام ‪ asterisk‬در ‪ MySQL‬ایجاد شد‪ .‬اکنون باید جدول ‪ cdr‬را در‬
‫آن ایجاد کنید‪ .‬بنابراین‪ ،‬دستورات زیر را اجرا کنید‪:‬‬
‫;‪mysql>use asterisk‬‬
‫‪Database changed‬‬
‫( ‪mysql> CREATE TABLE cdr‬‬
‫>‪-‬‬ ‫‪calldate datetime NOT NULL default '0000-00-00 00:00:00',‬‬
‫>‪-‬‬ ‫‪clid varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪src varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪dst varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪dcontext varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪channel varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪dstchannel varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪lastapp varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪lastdata varchar(80) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪duration int(11) NOT NULL default '0',‬‬
‫>‪-‬‬ ‫‪billsec int(11) NOT NULL default '0',‬‬
‫>‪-‬‬ ‫‪disposition varchar(45) NOT NULL default '',‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪472‬‬

‫>‪-‬‬ ‫‪amaflags int(11) NOT NULL default '0',‬‬


‫>‪-‬‬ ‫‪accountcode varchar(20) NOT NULL default '',‬‬
‫>‪-‬‬ ‫‪uniqueid varchar(32) NOT NULL default '',‬‬
‫>‪-‬‬ ‫'' ‪userfield varchar(255) NOT NULL default‬‬
‫;) >‪-‬‬
‫)‪Query OK, 0 rows affected (0.04 sec‬‬
‫>‪mysql‬‬

‫اینجا جدول ‪ cdr‬ساخته شد‪ .‬برای مشاهده جدول دستور زیر را اجرا کنید‪:‬‬
‫;‪mysql> describe cdr‬‬

‫همانطورکه مالحظه میکنید‪ ،‬نمایش کاملی از مشخصات جدول ‪ cdr‬نشان داده میشود‪.‬‬
‫اکنــون به ادامه پیکربندی ‪ CDR Backend‬در استریســک برمیگردیم‪ .‬بــرای این منظور از فایل _‪cdr‬‬
‫‪ adaptive_odbc‬برای پیکربندی ‪ CDR Backend‬استفاده میکنیم‪.‬‬
‫‪; cdr_adaptive_odbc.conf‬‬
‫]‪[cdr_backend‬‬
‫‪connection=asterisk‬‬
‫‪table=cdr‬‬
‫‪usegmtime=yes‬‬

‫در سیستم تلفنی استریسک این قابلیت وجود دارد که بهصورت همزمان چندین ارتباط ‪ ODBC‬با پایگاههای‬
‫دادهای مختلف ایجاد شود‪ ،‬بهطوریکه برای هر کدام باید مستقال تنظیمات پیکربندی انجام شود‪.‬‬
‫فایل ‪ cdr_adaptive_odbc.conf‬دارای پارامترهای مهمی اســت که در ادامه مهمترین آنها را توضیح‬
‫خواهیم داد‪.‬‬
‫• ‪ :connection‬نام شناسه تعریف شده در فایل ‪‌res_odbc.conf‬است‪.‬‬
‫• ‪ :table‬نام جدولی که داده‌ها در آن باید ذخیره شوند‪.‬‬
‫• ‪ :usegmtime‬برای ذخیره‌‌کردن تاریخ و زمان براساس استاندارد ‪.GMT‬‬
‫• ‪ :alias‬اگــر بخواهیم فیلدهــای موجود در ماژول ‪ CDR‬با نام دیگری در جدول ذخیره شــود‪ ،‬از این فیلد‬
‫استفاده می‌کنیم‪.‬‬
‫فرمت استفاده از پارامتر ‪ alias‬بهصورت زیر است‪:‬‬
‫>‪alias <CDR filed> => <column name‬‬

‫بــرای مثــال فرض کنید بخواهیم فیلد ‪ src‬از ماژول ‪ CDR‬را در ســتونی بهنــام ‪ source‬ذخیره کنیم؛ در این‬
‫صورت باید آن را بهصورت زیر بنویسید‪:‬‬
‫]‪[cdr_backend‬‬
‫‪connection=asterisk‬‬
‫‪table=cdr‬‬
‫‪usegmtime=yes‬‬
‫‪alias src => source‬‬
‫‪473‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫اینجا دادههای مربوط به فیلد ‪ src‬در ماژول ‪ CDR‬در ستون مربوط به ‪ source‬در جدول نگاشت می شود‪.‬‬
‫• ‪ :filter‬گاهی الزم است گزارش های خاصی از ‪ CDR‬در جدول پایگاه داده ذخیره شود‪ .‬در این صورت‬
‫از پارامتر ‪ filter‬به‌صورت زیر استفاده کنید‪:‬‬
‫>‪filter <CDR variable> => <content‬‬

‫بهعنــوان مثال فرض کنید در تمرین قبل بخواهیم فقط رکوردهایی از ‪ CDR‬را در جدول پایگاه داده ذخیره‬
‫کنیم که فیلد »‪ «accountCode‬آن برابر»‪ «۱۲۳‬باشد‪ .‬در این صورت‪ ،‬باید تنظیمات زیر را انجام دهید‪:‬‬
‫]‪[cdr_backend‬‬
‫‪connection=asterisk‬‬
‫‪table=cdr‬‬
‫‪usegmtime=yes‬‬
‫‪alias src => source‬‬
‫‪alias start =>calldate‬‬
‫‪filter accountcode=>123‬‬

‫با مشــاهده جدول و اطالعات ذخیره شــدهی آن‪ ،‬مشــاهده خواهید کرد که فیلد ‪ accountcode‬در تمامی‬
‫رکوردها ‪ ۱۲۳‬است‪.‬‬
‫از این تکنیک میتوان برای دستهبندی و ذخیرهسازی گزارشها‪ ،‬در جداول مورد نظر استفاده نمود )در‬
‫واقع میتوان ‪ view‬های متفاوتی از جدول ‪ CDR‬براساس فیلترهای متفاوت ایجاد نمود(‪.‬‬
‫• ‪ :static‬گاهی نیاز است یک فیلد خاص در جدول با مقدار «پیش‌فرض» وجود داشته باشد‪ .‬در این حالت‬
‫از پارامتر ‪ static‬به‌صورت زیر استفاده کنید‪.‬‬
‫‪static "My Content" => my_identifier‬‬

‫بهعنوان مثال فرض کنید بخواهیم در ستونی از جدول به نام ‪ mycolumn‬مقدار پیشفرض »‪«my_column‬‬
‫را برای همه رکوردها داشته باشیم‪ .‬در این صورت خواهیم داشت‪:‬‬
‫]‪[cdr_backend‬‬
‫‪connection=asterisk‬‬
‫‪table=cdr‬‬
‫‪usegmtime=yes‬‬
‫‪alias src => source‬‬
‫‪alias start =>calldate‬‬
‫‪filter accountcode=>123‬‬
‫‪static "My Content" => my_column‬‬

‫پیکربندی فایل ‪ cdr.conf‬در استریسک‬


‫پیکربندی اصلی ماژول ‪ CDR‬در استریســک بهوســیله فایل ‪ cdr.conf‬انجام میشود‪ .‬این فایل در مسیر زیر‬
‫است‪:‬‬
‫‪#vim /etc/asterisk/cdr.conf‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪474‬‬

‫در استریسک بهصورت پیشفرض‪ ،‬تمام گزارش ها در فایل ‪ Master.csv‬ذخیره میشوند‪ .‬همچنین بهصورت‬
‫پیشفرض فقط گزارش های پاسخ دادهشده‪ ۱‬ذخیره میشوند‪.‬‬
‫برای تنظیم و پیکربندی ماژول ‪ ،CDR‬این فایل را باز کنید و تنظیمات زیر را انجام دهید‪:‬‬
‫‪;cdr.conf‬‬
‫]‪[general‬‬
‫‪enable=yes‬‬
‫‪unanswered=yes‬‬
‫‪congestion=yes‬‬

‫همچنین تنظیمات مخصوص به ثبت گزارش ها در فایل را در قسمت زیر از فایل ‪ cdr.conf‬مشاهده کنید‪.‬‬

‫‪;cdr.conf‬‬
‫]‪[csv‬‬
‫‪usegmtime=yes‬‬
‫‪loguniqueid=yes‬‬
‫‪loguserfield=yes‬‬
‫‪accountlogs=yes‬‬

‫اگر فایل ‪ Master.csv‬را با یک ویرایشــگر باز کنید‪ ،‬متوجه میشــوید که در ایــن فایل متنی تمامی فیلدها‬
‫بهوسیله کاما از هم جدا شدهاند‪ .‬ترتیب فیلدهای ذخیره شده در این فایل بهصورت زیر است‪:‬‬
‫‪<accountcode>,<src>,<dst>,<dcontext>,<clid>,<channel>,<dstchannel>,<lastapp>,‬‬
‫‪<lastadata>,<start>,<answer>,<end>,<duration>,<billsec>,<disposition>,‬‬
‫]>‪<amaflags>[,<uniqueid>][,<userfield‬‬

‫پیکربندی فایل ‪ cdr_custom‬در استریسک‬


‫گاهــی نیاز داریم تغییراتی در نحوه و ترتیب گزارشهای ‪ CDR‬در استریســک ایجــاد کنیم‪ .‬برای اینکار‬
‫کافی اســت در این فایل‪ ،‬گزارشهای الزم را ایجاد کنیم‪ .‬در این صورت فایلهای جدید در مســیر ‪var//‬‬
‫‪ /log/asterisk/cdr-custom‬ایجاد خواهند شــد‪ .‬برای مثال فرضکنید بخواهیم گزارشــی را ایجاد کنیم که‬
‫فقط زمان ایجاد تماس‪ ،‬مدت زمان تماس و شــماره تماس گیرنده را نشــان دهد‪ .‬در این صورت تغییرات را‬
‫بهصورت زیر انجام دهید‪:‬‬
‫‪;cdr_custom.conf‬‬
‫]‪[mapping‬‬
‫_‪sample.csv=>${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(start)})},${CSV‬‬
‫})})‪QUOTE(${CDR(duration,f‬‬

‫بعد از انجام تغییرات‪ ،‬اگر تماس جدیدی ایجاد شود‪ ،‬در مسیر زیر و در فایل ‪ sample.csv‬ایجاد و گزارش‬
‫ها در آنجا درج میشوند‪.‬‬
‫‪#vim /var/log/asterisk/cdr-custom/sample.csv‬‬

‫‪1- Answered‬‬
‫‪475‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫پیکربندی فایل ‪ cdr_manager‬در استریسک‬


‫همانطور که قب ً‬
‫ال توضیح داده شــد‪ ،‬در استریســک میتوان کلیه رویدادها را بهوســیله ‪ AMI‬مشاهده نمود‪.‬‬
‫در فصل ســیزدهم )ابزار مدیریتی استریســک( درباره آن به تفصیل توضیح داده شــد‪ .‬برای مثال فرضکنید‬
‫بخواهیم رویدادهای مربوط به ‪ CDR‬را بهوســیله یوزر اکانت ‪ AMI‬مشــاهده کنیم‪ .‬در اینجا باید تنظیمات‬
‫متفاوتی را در هر دو فایل برای فعال کردن این رویداد انجام دهیم‪.‬‬
‫‪ (۱‬ســطح دسترســی از کالس مشــخص برای یوزر اکانت ‪ AMI‬در فایل ‪ manager.conf‬تعریف شود‪ .‬این‬
‫تنظیمات بهصورت زیر اســت‪ .‬توجه داشته باشید که اگر مقدار ‪ all‬را برای پارامتر ‪ read‬در نظر گرفتهباشید‪،‬‬
‫نیازی به تغییرات زیر نخواهید داشت‪.‬‬
‫‪;manager.conf‬‬
‫]‪[hello‬‬
‫‪secret=world‬‬
‫‪read=cdr‬‬

‫‪ (۲‬فایل ‪ cdr_manager.conf‬برای مدیریت و کنترل کلیه رویدادهای مرتبط با ‪ CDR‬در استریســک است‪.‬‬
‫با فعال کردن این بخش از تنظیمات استریسک‪ ،‬میتوان گزارشهای مرتبط با ‪ CDR‬را بهوسیله یوزر اکانت‬
‫‪ AMI‬مشاهده کرد‪.‬‬
‫‪;cdr_manager.conf‬‬
‫]‪[general‬‬
‫‪enabled = yes‬‬

‫اکنون اگر به واســطه یوزر اکانت ‪ AMI‬به استریســک متصل شویم‪ ،‬رویدادهای مربوط به ‪ CDR‬را مشاهده‬
‫خواهیــم کرد‪ .‬معموالً رویداد ‪ CDR‬به همراه رویداد ‪ Hangup‬ظاهر میشــود‪ .‬به عبارت دیگر ابتدا رویداد‬
‫‪ Hangup‬رخ میدهد و سپس به دنبال آن رویداد ‪ CDR‬رخ خواهد داد‪:‬‬
‫‪Event: Hangup‬‬
‫‪Privilege: call,all‬‬
‫‪Channel: Console/dsp‬‬
‫‪ChannelState: 6‬‬
‫‪ChannelStateDesc: Up‬‬
‫>‪CallerIDNum: <unknown‬‬
‫>‪CallerIDName: <unknown‬‬
‫>‪ConnectedLineNum: <unknown‬‬
‫>‪ConnectedLineName: <unknown‬‬
‫‪Language: en‬‬
‫‪AccountCode:‬‬
‫‪Context: LocalSets‬‬
‫‪Exten: 600‬‬
‫‪Priority: 5‬‬
‫‪Uniqueid: 1472729355.20‬‬
‫‪Linkedid: 1472729355.20‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 476

Cause: 0
Cause-txt: Unknown

Event: Cdr
Privilege: cdr,all
AccountCode:
Source:
Destination: 600
DestinationContext: LocalSets
CallerID: "" <>
Channel: Console/dsp
DestinationChannel:
LastApplication: NoOp
LastData: Call duration:5
StartTime: 2016-09-01 15:59:15
AnswerTime: 2016-09-01 15:59:15
EndTime: 2016-09-01 15:59:20
Duration: 5
BillableSeconds: 5
Disposition: ANSWERED
AMAFlags: DOCUMENTATION
UniqueID: 1472729355.20
UserField:

‫[ است که مدیریت‬mapping] ‫ اســتفاده از قســمت‬،cdr_manager.conf ‫یکی از قابلیتهای ممتاز در فایل‬


CDR ‫ در این بخش میتــوان فیلدهای جدیدی را به رویداد‬.‫ را بــه عهده دارد‬AMI ‫ در‬CDR ‫رویدادهــای‬
.‫ برای توضیح بیشتر بهتر است به مثالی بپردازیم‬.‫اضافه کرد‬
:‫[ موارد زیر را اضافه کنید‬mapping] ‫در بخش‬
;cdr_manager.conf
[mappings]
rate => Rate
carrier => Carrier

:‫ فیلدهای جدید را مقداردهی کنید‬،CDR ‫ بهوسیله تابع‬، ‫در برنامه استریسک‬


;extensions.conf
[LocalSets]
exten => 700,1,Answer()
same => n,Set(CDR(rate)=0.02)
same => n,Set(CDR(carrier)=BS&S)
same => n,Hangup()

:‫ تماس جدیدی را ایجاد کنید‬،‫سپس بهوسیله دستور زیر در محیط کامندالین استریسک‬
CLI> console dial 700@LocalSets
477 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

:‫ مشاهده کنید‬CDR ‫ فیلدهای جدید را در رویدادهای‬،AMI ‫اکنون باید در گزارشهای ایجاد شده در‬
Event: Cdr
Privilege: cdr,all
AccountCode:
Source:
Destination: 700
DestinationContext: LocalSets
CallerID: "" <>
Channel: Console/dsp
DestinationChannel:
LastApplication: Hangup
LastData:
StartTime: 2016-09-01 16:15:57
AnswerTime: 2016-09-01 16:15:57
EndTime: 2016-09-01 16:15:58
Duration: 0
BillableSeconds: 0
Disposition: ANSWERED
AMAFlags: DOCUMENTATION
UniqueID: 1472730357.24
UserField:
Rate: 0.02
Carrier: BS&S

‫ اضافه‬CDR ‫ بهعنوان فیلدهای جدید در رویداد‬Carrier ‫ و‬Rate ‫ اینجا دو فیلد‬،‫همانطورکه مالحظه میکنید‬
.‫شدهاند که پیش از این در برنامه استریسک تعریف و مقداردهی شده بودند‬

syslog ‫ در فایل‬CDR ‫ثبت گزارش های‬


‫ برای این منظور‬.‫ ثبت نماییم‬syslog ‫ را در فایل‬CDR ‫در استریسک این قابلیت وجوددارد که گزارشهای‬
‫ تغییرات زیر‬،‫ بر این اســاس‬.‫ اعمال نمود‬cdr_syslog.conf ‫ و فایل‬syslog.conf ‫باید تغییراتی در فایلهای‬
:‫را در هر فایل انجام دهید‬
:‫ را از مسیر زیر باز و تغییرات زیر را درآن انجام دهید‬syslog.conf ‫ابتدا فایل‬
#vim /etc/rsyslog.conf
local4.* /var/log/asterisk/asterisk-cdr.log

:‫ را از مسیر فایلهای پیکربندی استریسک باز و تغییرات زیر را انجام دهید‬cdr_syslog.conf ‫سپس فایل‬
#vim /etc/asterisk/cdr_syslog.conf
[cdr]
facility = local4
priority = info
template = "We received a call from ${CDR(src)}"
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪478‬‬

‫بعد از انجام این تغییرات و ‪ reload‬کردن استریسک‪ ،‬میتوان گزارشها را بهصورت زیر مشاهده نمود‪:‬‬

‫‪#cat /var/log/asterisk/asterisk-cdr.log‬‬
‫"‪Sep 16 10:45:36 pbx cdr: "We received a call from 100‬‬

‫گزارشهای ایجاد شــده در سیســتم تلفنی استریسک تا اینجا بررسی شــدند‪ .‬عالوه بر این‪ ،‬انواع متفاوت و‬
‫ضروری از گزارش های ‪ CDR‬را در استریسک می توان ایجاد و از آنها استفاده کرد‪ .‬همچنین مثالهایی‬
‫که در این بخش از کتاب آمد‪ ،‬جملگی بر اساس پایگاه دادهای ‪ MySQL‬بود‪ .‬میتوانید از هر پایگاه دادهای‬
‫که نیاز دارید اســتفاده کنید‪ .‬نحوهی پیکربندی سایر پایگاههای دادهای مشابه پایگاه دادهای ‪ MySQL‬است‬
‫که به خواننده کتاب واگذار میشود‪.‬‬
‫در ادامه فصل به معرفی گزارش‌های ‪ CEL‬در استریسک و کاربرد آنها می‌پردازیم‪.‬‬

‫گزارش رویدادها در استریسک ‪CEL‬‬


‫‪1‬‬

‫همانطورکه پیشتر نیز آمد‪ ،‬استریســک یک ســرویس رویدادگراســت که در فصل ســیزدهم )ابزارهای‬
‫مدیریتی در استریســک( بهصورت مفصل شــرح دادهشــد‪ .‬بهوســیله ماژول گزارشگیــری ‪ CEL‬میتوان‬
‫رویدادهایی را که در استریسک اتفاق میافتد‪ ،‬ذخیره نمود‪ .‬با توجه به اینکه این ماژول گزارشهای بیشتری‬
‫را نســبت به ماژول ‪ CDR‬ایجاد میکند‪ ،‬از آن در سیســتمهایی میتوان استفاده کرد که محاسبات ‪billing‬‬
‫را دقیقتر انجام میدهند‪.‬‬
‫برای روشنتر شدن مطلب بهتر است به یک مثال بپردازیم‪ .‬فرض کنید برنامهی ساده زیر را داشته باشید‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 701,1,Answer‬‬
‫)‪same => n,Playback(hello-world‬‬
‫)(‪same => n,Hangup‬‬

‫اکنون گزارشهای ‪ CDR‬و ‪ CEL‬این برنامه را در استریســک بررســی میکنیم‪ .‬اگر گزارش ایجاد شــده‬
‫بهوسیله ماژول ‪ CDR‬را مالحظه کنید‪ ،‬این گزارش بهصورت زیر خواهد بود‪:‬‬
‫‪"","100","701","LocalSets","""100"" <100>","SIP/100-0000000b","","Hangup","","2016-09-01‬‬
‫‪12:53:27","2016-09-01 12:53:27","2016-09-01 12:53:29",1,1,"ANSWERED","DOCUMENTATI‬‬
‫""‪ON","1472734407.51",‬‬

‫گزارشهای ایجاد شده بهوسیله ماژول ‪ CDR‬به سواالت زیر پاسخ میدهند‪:‬‬
‫• شماره کالر آی دی چیست؟‬
‫• شماره مقصد تماس چیست؟‬

‫‪1- Call Event Logger‬‬


‫‪479‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫• تماس در چه زمانی ایجاد شده است؟‬


‫• آیا تماس پاسخ داده شده است یا خیر؟‬
‫• مدت زمان مکالمه چقدر بوده است؟‬
‫در کنار این نوع گزارشها‪ ،‬اگر گزارش ایجاد شــده بهوســیله ماژول ‪ CEL‬را بررســی کنید‪ ،‬بهصورت‬
‫زیر خواهد بود‪:‬‬
‫‪"CHAN_START","1472734668.462191","100","100","","","","701","LocalSets","SIP/100-‬‬
‫""‪0000000d","","","3","","1472734668.61","1472734668.61","","","",‬‬
‫‪"ANSWER","1472734668.466848","100","100","100","","701","701","LocalSets","SIP/100-‬‬
‫""‪0000000d","Answer","","3","","1472734668.61","1472734668.61","","","",‬‬
‫‪"HANGUP","1472734669.941828","100","100","100","","701","701","LocalSets","SIP/100-‬‬
‫‪0000000d","","","3","","1472734668.61","1472734668.61","","","","{""hangupcause"":16,""dia‬‬
‫"}""‪lstatus"":"""",""hangupsource"":""dialplan/builtin‬‬
‫‪"CHAN_END","1472734669.944781","100","100","100","","701","701","LocalSets","SIP/100-‬‬
‫""‪0000000d","","","3","","1472734668.61","1472734668.61","","","",‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬گزارشهای ایجاد شــده بهوســیله ماژول ‪ CEL‬در واقع نشــان دهنده رفتار‬
‫استریسک در هر مرحله است‪ .‬گزارشهای ایجاد شده بهوسیله ماژول ‪ CEL‬به سؤاالت زیر پاسخ میدهند‪:‬‬
‫• کانال مربوط به تماس گیرنده‪ ،‬چه زمانی در استریسک ایجاد شده است؟‬
‫• این کانال به‌وسیله استریسک چه زمانی پاسخ داده شده است؟‬
‫• این کانال به‌وسیله استریسک چه زمانی قطع شده است؟‬
‫• این کانال چه زمانی در استریسک از بین رفته است؟‬
‫همانطورکه مالحظه میکنید‪ ،‬در گزارش ایجاد شــده بهوســیله ماژول ‪ CDR‬خالصهای از ایجاد تماس‬
‫نشان داده میشود‪ ،‬ولی در گزارش تولید شده بهوسیله ماژول ‪ CEL‬جزئیات مربوط به زمان ایجادشدن کانال‬
‫در استریسک‪ ،‬زمان پاسخ دادن به کانالها‪ ،‬زمان اجرای دستورها بر روی کانال‪ ،‬زمان خاتمه یافتن دستور در‬
‫کانال‪ ،‬زمان قطع شدن تماس و زمان از بین رفتن کانال در استریسک‪ ،‬مشخص میشود‪.‬‬
‫ازآنجاکه در استریســک رویدادهای زیادی داریم‪ ،‬میتوانیم در گزارش های ایجاد شده بهوسیله ماژول‬
‫‪ ،CEL‬نوع رویدادهایی را که نیاز داریم مشــخص کنیم‪ .‬در ادامه به معرفی انواع رویدادها در ماژول ‪CEL‬‬
‫میپردازیم‪.‬‬

‫انواع رویداد ‪ CEL‬در استریسک‬


‫همانطور که در مثال باال آمد‪ ،‬در هر ســطر از گزارش های ماژول ‪ ،CEL‬رویداد خاصی نمایش داده شــد‪.‬‬
‫هر ســطر گزارش‪ ،‬وابســته به رویدادی است که در داخل استریسک در حال اجرا شدن است‪ .‬جدول ‪۳-۱7‬‬
‫انواع رویدادها در ماژول ‪ CEL‬را نمایش میدهد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 480

CEL Event type Description


CHAN_START A channel has been created.
CHAN_END A channel has been destroyed.
LINKEDID_END The last channel with a given linkedid has been destroyed.
ANSWER A channel has been answered. On a channel created for an outbound call, this Trent will
be generated when the remote end answers.
HANGUP A channel has hung up. Generally, this event w be followed wry shortly by a CHAN_END
event. The difference is that this event OCCUR as soon as a hangup request is received,
whereas CHAN_END occurs after Asterisk has completed post -call dean* and all resources
associated with that channel have been released.
APP_START A tracked application his started executing on a channel. tracked applications are set in
the main CEL configuration file, which is covered in «(drool› on page 657.
APP_END A tracked application has stopped executing on a channel.
PARK_START A channel has been parked.
PARK_END A channel has left the parking lot.
BRIDGE_START A channel bridge has started. This ment occurs when two channels are bridged tooer her
bq an application such as Dial( ) or Queue( ).
BRIDGE_END A channel bridge has ended
BRIDGE_UPDATE An update to a bridge has occurred. This event will reflect if a channel›s name or other
inforrnation has changed during a bridge.
BLINDTRANSFER A channel has executed a blind transfer.
ATTENDEDTRANSFER A channel has executed an attended transfer.
USER_DEFINED A user -defined channel event has occurred. These events are generated by using the
CELGenUser Event ( ) application.

3-17 ‫جدول‬

‫ در استریسک‬CEL ‫انواع فیلدها در گزارش سطری رویدادهای‬


‫ مربوط به نوع رویداد است که در جدول‬،‫ اولین فیلد‬،CEL ‫در هر ســطر از رویدادهای ایجاد شده از ماژول‬
‫ سایر فیلدها در هر سطر باید بهوسیله استریسک در زمان اجرای هر رویداد‬.‫ انواع آن را بررســی کردیم‬،‫قبل‬
‫ لیست فیلدها‬4-۱7 ‫ در جدول‬.‫ است‬CDR ‫ این فیلدها بسیار شبیه به فیلد گزارشها در ماژول‬.‫مقداردهی شود‬
.‫ نمایش داده شده است‬CEL ‫در ماژول‬

Field name Value/Example Notes


eventtype CHAN_START The name of the event. The lst of events that may occure can be found in
Table 24-7.
eventtime 2010-08-19 07:27:19 The time that the event occured.
cidname Juliet Bryant The caller ID name set on the channel associated with this event.
cidnum 18435551212 The caller ID number set on the channel associated with this event.
cidani 18435551212 The Autornstmatic Number Identification (ANI) rnumber set on the
channel associated with this event.
481 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

Field name Value/Example Notes


cidrdnis 18435551234 The redirecting number set on the channel associated with this event.
ciddnid 18435550987 The dialed number set on the channel associated with this event.
exten 101 The extension in the dialplan that is currently being executed.
context LocalSets The context for the extension in the dialplan that is currently being
executed.
channame SIP/0004F2860EB4-00008010 The name of the the channel associated with this event.
appname Dial The name of the the dialplan application currently being executed.
appdata SIP/0004F2860Ess The arguments that were passed to the dialplan application that is
currently being executed.
amaflags DOCUMENTATION The Automatic Message Accounting (AMA) flag associated with this call.
This may be one of the following: OMI, BILLING, DOCUMENTATION, or
Unknown.
accountcode 1234 An account ID. This field is user-defiled and is empty by default.
uniqueid 1282218999.18 The unique ID for the channel that is associated with this event.
userfield I like waffles! User-defined event content.
linkedid 1282218999.18 The per-call ID. This ID helps tie together multiple events from multiple
channels that are all in part of the same logical call. The ID Comes from
the uniqueid of the first channel in the call.
peer SIP/0004F2860Ess- The name of the channel bridged to the channel identified by channame.
00000020
4-17 ‫جدول‬

‫ در برنامه‌نویسی استریسک‬CELGenUserEvent ‫استفاده از دستور‬


.‫ آنها را ثبت نمود‬،‫میتوان در برنامهنویسی استریسک رویدادهایی را به دلخواه ایجاد کرد و در گزارش ها‬
‫ ولی برای خطایابی در برنامههای نوشته شده و سیستم‬،‫شــاید استفاده از این دستورات چندان مرسوم نباشــد‬
app_celgenuserevent. ‫ در استریســک ماژولی به نام‬.‫تلفنی استریســک میتواند مورد استفاده قرار گیرد‬
.‫ در استریسک استفاده کرد‬CELGenUserEvent ‫ وجود دارد که به واسطه این ماژول میتوان از دستور‬so
:‫برای مشاهده وضعیت ماژول فوق در استریسک دستور زیر را اجرا کنید‬
CLI> module show like app_celgenuserevent.so
Module Description Use Count Status Support Level
app_celgenuserevent.so Generate an User-Defined CEL event 0 Running
core
1 modules loaded

‫ برای آشــنا شــدن با‬.‫ این ماژول در استریســک نصب شــده و فعال اســت‬،‫همانطورکه مشــاهده میکنید‬
.‫ دستور زیر را در کامندالین استریسک اجرا کنید‬، CELGenUserEvent
CLI> core show application CELGenUserEvent
[Syntax]
CELGenUserEvent(event-name[,extra])
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪482‬‬

‫]‪[Arguments‬‬
‫‪extra‬‬
‫‪Extra text to be included with the event.‬‬

‫برای روشــنتر شــدن موضوع بهتر اســت در مثالی از آن اســتفاده کنیم‪ .‬فرض کنید بــرای الگگیری در‬
‫برنامههای خود‪ ،‬در بخشی از برنامه تصمیم داشته باشیم رویدادهایی ایجاد کنیم‪ .‬این کار بهوسیله استریسک‬
‫ِ‬
‫اجرای دســتورات نوشتهشــده صورت میگیرد‪ .‬اینجــا رویدادی با نــام »‪ «my-Event-log‬را ایجاد‬ ‫هنگام‬
‫خواهیم کرد‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 702,1,NoOp‬‬
‫…‬
‫)”‪same => n,CELGenUserEvent(My-EVENT-Log,”Here is my logger in asterisk dialplan‬‬

‫درصورتیکه استریســک به اجرای این خط برســد وآن را اجرا نماید‪ ،‬رویدادی با نام »‪ «My-Event‬را در‬
‫گزارشهای خود ثبت خواهد کرد‪.‬‬

‫پیکربندی فایل ‪ cel.conf‬در استریسک‬


‫پیکربندی فایل ‪ cel.conf‬در استریســک بســیار شــبیه به پیکربندی فایل ‪ cdr.conf‬است‪ .‬برای فعالکردن و‬
‫پیکربندی ماژول ‪ CEL‬باید فایل ‪ cel.conf‬از مسیر ‪ /etc/asterisk‬را باز کنید‪:‬‬
‫‪# vim /etc/asterisk/cel.conf‬‬

‫مهمترین پارامترهای این ماژول برای پیکربندی‪ ،‬در زیر توضیح داده شدهاند‪:‬‬
‫• پارامتــر ‪ :enable‬این پارامتر برای فعال‌کردن گزارش‌ها در ‪ CEL‬اســت که به‌صورت پیش‌فرض غیر‌فعال‬
‫است‪.‬‬
‫• پارامتر ‪ :Apps‬به‌وســیله این پارامتر می‌توان مشــخص نمود که برای اجرای کدامیک از دســتورات باید‬
‫گزارش‌های ‪ CEL‬تولید شود‪.‬‬
‫• پارامتر ‪ :events‬این پارامتر مشخص می‌کند که چه نوع رویدادی باید به‌وسیله ماژول ‪ CEL‬گزارش شود‪.‬‬
‫لیست انواع رویدادها در جدول ‪ 5-17‬آورده شده است‪.‬‬
‫• پارامتر ‪ :dateformat‬این پارامتر تاریخ و زمان اجرا شــدن رویداد را نشــان می‌دهد‪ .‬به‌عنوان مثال فرمت«‬
‫‪ »%F %T‬زمان را به‌صورت « ‪ » year-manth-day h:m:s‬نمایش می‌دهد‪.‬‬
‫گزارشهای ایجاد شده بهوسیله ماژول ‪ ، CEL‬همانند ماژول ‪ CDR‬بهصورت پیشفرض در فایل ‪Master.‬‬
‫‪ csv‬در مسیر ‪ /var/log/asterisk/cel_custom‬ذخیره میشوند‪ .‬میتوان این گزارشها را در پایگاههای داده‬
‫با استفاده از ‪ CEL Backend‬ذخیره نمود‪.‬‬
483 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

Event Type Integer Value


CHANNEL_START 1
CHANNEL_END 2
HANGUP 3
ANSWER 4
APP_START 5
APP_END 6
BRIDGE_START 7
BRIDGE_END 8
CONF_START 9
CONF_END 10
PARK_START 11
PARK_END 12
BLINDTRANSFER 13
ATTENDEDTRANSFER 14
TRANSFER 15
HOOKFLASH 16
3WAY_START 17
3WAY_END 18
CONF_ENTER 19
CONF_EXIT 20
USER_DEFINED 21
LINKED_END 22
BRIDGE_UPDATE 23
PICKUP 24
FORWARD 25
5-17 ‫جدول‬

)CEL Backend( ‫ در پایگاه داده‬CEL ‫ثبت گزارش های ماژول‬


‫ در‬cel ‫ ازآنجاکه ماژول‬.‫ را در پایگاه داده ذخیره کرد‬cel ‫ میتوان گزارشهای‬، CDR ‫همانند گزارشهای‬
.‫ تنظیمات و پیکربندی برای این دو تقریبا یکسان است‬،‫ شبیه است‬CDR ‫استریسک بسیار به ماژول‬
:‫ داشتهباشیم‬cel_odbc.conf ‫ فرضکنید تنظیمات زیر را در فایل‬،‫بهعنوان تمرین‬
;cel_odbc.conf
[cel_backend]
connection = asterisk
table = cel

mysql ‫ برای این منظــور به کامندالین‬.‫ ایجاد کنید‬MySQL ‫ را در پایــگاه دادهای‬cel ‫اکنــون بایــد جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 484

:‫بروید‬
# mysql -uroot -p
Enter password:
mysql>

:‫ را در آن ایجاد کنید‬cel ‫ را انتخاب و سپس جدول‬asterisk ‫ابتدا دیتابیس‬


mysql> use asterisk;
Database changed
mysql>

:‫ به‌صورت زیر عمل کنید‬cel ‫برای ساختن جدول‬


mysql> CREATE TABLE IF NOT EXISTS `cel` (
`id` int(11) NOT NULL auto_increment,
`eventtype` varchar(30) NOT NULL,
`eventtime` datetime NOT NULL,
`cid_name` varchar(80) NOT NULL,
`cid_num` varchar(80) NOT NULL,
`cid_ani` varchar(80) NOT NULL,
`cid_rdnis` varchar(80) NOT NULL,
`cid_dnid` varchar(80) NOT NULL,
`exten` varchar(80) NOT NULL,
`context` varchar(80) NOT NULL,
`channame` varchar(80) NOT NULL,
`src` varchar(80) NOT NULL,
`dst` varchar(80) NOT NULL,
`channel` varchar(80) NOT NULL,
`dstchannel` varchar(80) NOT NULL,
`appname` varchar(80) NOT NULL,
`appdata` varchar(80) NOT NULL,
`amaflags` int(11) NOT NULL,
`accountcode` varchar(20) NOT NULL,
`uniqueid` varchar(32) NOT NULL,
`linkedid` varchar(32) NOT NULL,
`peer` varchar(80) NOT NULL,
`userdeftype` varchar(255) NOT NULL,
`eventextra` varchar(255) NOT NULL,
`userfield` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `uniqueid_index` (`uniqueid`),
KEY `linkedid_index` (`linkedid`)
);

:‫ جدول را مشاهده کنید‬،‫ میتوانید به کمک دستور زیر‬cel ‫بعد از ساختن جدول‬
mysql> describe cel;

cel_odbc. ‫ به این منظــور باید هنگام پیکربندی فایل‬.‫میتوان نام فیلدها را هنگام ســاختن جداول تغییر داد‬
‫‪485‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫‪ conf‬بهوسیله پارامتر ‪ ، alias‬نام فیلدهای جدید را اعالم کنید‪.‬‬


‫>‪alias <CEL field> => <column name‬‬

‫بهعنــوان مثال فرض کنید بخواهیم به جای فیلد »‪ «eventtype‬در ســاخت جــدول از فیلد »‪«eventname‬‬
‫استفاده کنیم‪ .‬در این صورت باید آن را به شکل زیر در فایل ‪ cel_odbc.conf‬تغییر دهید‪:‬‬
‫‪;cel_odbc.conf‬‬
‫]‪[cel_backend‬‬
‫‪connection = asterisk‬‬
‫‪table = cel‬‬
‫‪alias eventtype => evenename‬‬

‫همچنیــن میتوانید از پارامتر ‪ filter‬در صورت نیاز به فیلترکردن گزارشهای ماژول ‪ CEL‬در جدول پایگاه‬
‫داده‪ ،‬استفاده کنید‪:‬‬
‫>‪filter <CEL field> => <content‬‬

‫چنانچه بخواهیم فقط گزارشهای مربوط به دستور »‪ «Dial‬را در جدول ذخیره کنیم‪ ،‬در این صورت داریم‪:‬‬
‫‪;cel_odbc.conf‬‬
‫]‪[cel_backend‬‬
‫‪connection = asterisk‬‬
‫‪table = cel‬‬
‫‪filter appname => dial‬‬

‫پارامتر ‪ static‬برای اســتفاده از یک فیلد خاص در جدول گزارشهای ‪ CEL‬با مقادیر پیشفرض بهصورت‬
‫زیر بهکار برده میشود‪:‬‬
‫>‪static <"Static Content Goes Here"> => <column name‬‬

‫برای مثال از یک پارامتر ‪ static‬می توان بهصورت زیر استفاده کرد‪:‬‬


‫‪static "My Content" => my_identifier‬‬

‫پیکربندی فایل ‪ CEL_manager‬در استریسک‬


‫زمانیکه ماژول ‪ CEL‬در استریســک گزارش رویدادی را ثبت میکند‪ ،‬این رویداد بهوســیله یوزر اکانت‬
‫‪ AMI‬قابل مشاهده خواهد بود‪ .‬در اینجا فایلی به نام ‪ CEL_manager.conf‬وجود ندارد‪ ،‬بلکه بجای آن در‬
‫فایل ‪ ،cel.conf‬بخش ]‪ [manager‬تنظیمات این قسمت صورت میگیرد‪.‬‬
‫بهعنــوان مثال فرض کنید بخواهیم گزارش رویدادهایی که ماژول ‪ CEL‬ایجاد میکند را بهوســیله یک‬
‫یوزر اکانت ‪ AMI‬مشــاهده کنیم‪ .‬بــرای این کار ابتدا باید در بخــش ]‪ [manager‬از فایل ‪ cel.conf‬پارامتر‬
‫‪ enable‬را فعالکنیم‪.‬‬
‫‪;cel.conf‬‬
‫]‪[manager‬‬
‫‪enabled = yes‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪486‬‬

‫بعــد از انجام تغییرات و ‪ reload‬کردن استریســک‪ ،‬خروجی گزارش رویداد ‪ CEL‬در ‪ AMI‬بهصورت زیر‬
‫خواهد بود‪:‬‬
‫‪Event: CEL‬‬
‫‪Privilege: call,all‬‬
‫‪EventName: CHAN_END‬‬
‫‪AccountCode:‬‬
‫‪CallerIDnum: 100‬‬
‫‪CallerIDname: 100‬‬
‫‪CallerIDani: 100‬‬
‫‪CallerIDrdnis:‬‬
‫‪CallerIDdnid: 702‬‬
‫‪Exten: 702‬‬
‫‪Context: LocalSets‬‬
‫‪Channel: SIP/100-00000013‬‬
‫‪Application:‬‬
‫‪AppData:‬‬
‫‪EventTime: 2016-09-01 19:27:51‬‬
‫‪AMAFlags: DOCUMENTATION‬‬
‫‪UniqueID: 1472741871.99‬‬
‫‪LinkedID: 1472741871.99‬‬
‫!‪Userfield: I like waffles‬‬
‫‪Peer:‬‬
‫‪PeerAccount:‬‬
‫‪Extra:‬‬

‫همانطورکــه مالحظه میکنید‪ ،‬گزارش رویداد ‪ CEL‬ایجاد میشــود و بهوســیله یــوزر اکانت ‪ AMI‬قابل‬
‫مشاهده است‪.‬‬
‫تا اینجا در خصوص گزارشهای سیســتمی از قبیل ‪ ، logger ، syslog‬گزارش جزئیات تماس )‪(CDR‬‬
‫و گزارش رویدادهای استریســک )‪ (CEL‬توضیحات الزم داده شــد‪ .‬در ادامه به یکی از پروتکلهای مهم‬
‫مدیریتی در شبکه خواهیم پرداخت و نحوه اتصال آن به استریسک را شرح خواهیم داد‪.‬‬

‫پروتکل مدیریت شبکه (‪) 1SNMP‬‬


‫پروتکل ‪ SNMP‬بخشــی از پروتکل ‪ TCP/IP‬اســت و در الیه ‪ Application‬در مدل الیهای ‪ OSI‬قرار دارد‬
‫که توانایی مدیریت و یافتن خطاهای شبکه و اطالعرسانی این خطا به مدیر سیستم را داراست‪ .‬این پروتکل‬
‫شامل دو قسمت اصلی است‪ (۱) :‬مدیریت شبکه‪ ۲‬و )‪ (۲‬تجهیزات شبکه‪.۳‬‬
‫ســاختار ‪ SNMP‬به این گونه اســت که یک ســرور مدیریت شــبکه وجود دارد و تجهیزاتی که نیاز به‬
‫مانیتنورینگ دارند باید نســخه کاربــری‪ 4‬را نصب و فعال نمایند تا بتواننــد اطالعات و گزارش‌های خود را‬

‫‪1- Simple Network Management Protocol‬‬


‫‪2- SNMP Manager‬‬
‫‪3- Network Equipment‬‬
‫‪4- Client‬‬
‫‪487‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫تحت پروتکل مدیریت شبکه‪ ،‬به سرور مدیریت شبکه منتقل نمایند‪ .‬هر بخش شامل وظایفی می باشد که در‬
‫ذیل به آنها ارشاره شده است‪:‬‬

‫وظایف تجهیزات در شبکه‬


‫ • ذخیره‌سازی اطالعات مدیریتی در قالب ‪MIB‬‬
‫ • اطالع‌رسانی به سرور در مورد هرگونه اتفاق غیرعادی‬

‫وظایف مدیریت شبکه‬

‫ • تهیه آمار از کاربران‬


‫ • اعالم خطاها به مدیریت سیستم‬

‫‪SNMP Community‬‬
‫برای اســتفاده از پروتکل ‪ ، SNMP‬ویژگی آن باید بهوســیله تجهیزات مورد نیاز فعال شــود و گزارشها به‬
‫ســرور مدیریت شبکه ارســال گردند‪ .‬ولی فقط اطالعاتی معتبرند که از طرف تجهیزات مشخص شده برای‬
‫ســرور ارســال شوند‪ .‬به همین منظور از یک نام اشتراکی با عنوان ‪ SNMP Community‬استفاده میشود و‬
‫تا زمانی که در انتقال اطالعات از این نام استفاده نشود‪ ،‬آن ارتباط غیرمعتبر شناخته میشود و ارزشی ندارد‪.‬‬
‫با این تکنیک از جایگزینی ســرور مدیریت شبکه بهجای ســرورهای جعلی و یا تجهیزات جعلی جلوگیری‬
‫میشود‪ .‬شکل ‪ ۲-۱7‬چگونگی ارتباط تجهیزات در شبکه‪ ،‬سرور مدیریت شبکه و پروتکل ‪ SNMP‬را نشان‬
‫می دهد‪.‬‬

‫شکل ‪2-17‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪488‬‬

‫نصب ماژول ‪ SNMP‬در استریسک‬


‫در زمان نصب استریسک‪ ،‬ماژول ‪ SNMP‬بهصورت پیشفرض نصب نخواهد شد‪ .‬برای نصب و فعال کردن‬
‫ماژول ‪ SNMP‬ابتدا باید این ماژول را در ســرور خود نصب کنید‪ .‬برای این منظور دســتور زیر را با توجه به‬
‫هسته لینوکسی اجرا کنید‪:‬‬ ‫توزیع‬
‫‪;RHEL‬‬
‫‪#yum install net-snmp-devel‬‬

‫‪;Ubuntu‬‬
‫‪#apt-get install snmp snmpd libsnmp-dev snmp-mibs-downloader‬‬

‫بعد از نصب ماژول ‪ ،SNMP‬باید استریسک را مجددا ً کامپایل کنید تا این ماژول بهوسیله استریسک شناخته‬
‫و نصب شود‪.‬‬
‫‪#cd ~/src/asterisk-complete/‬‬
‫‪#./configure‬‬
‫‪#make menuselect‬‬

‫چنانچه این دستور اجرا شود‪ ،‬مشاهده میکنید که ماژول ‪ res_snmp.so‬در استریسک فعال شدهاست‪).‬شکل‬
‫‪(۳-۱7‬‬

‫شکل ‪3-17‬‬

‫در ادامه‪ ،‬دستورات زیر را برای نصب مجدد استریسک اجرا کنید‪:‬‬
‫‪#make‬‬
‫‪#make install‬‬
489 ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫ را از مســیر زیر‬res_snmp.conf ‫ باید فایل‬،‫ در استریســک‬SNMP ‫بــرای پیکربنــدی و فعال کردن ماژول‬
:‫ویرایش نمایید‬
# vim /etc/asterisk/res_snmp.conf
[general]
subagent=yes
enabled=yes

:‫ خروجی دستورها بهصورت زیر است‬.‫ را ریست کنید‬SNMP ‫سپس ماژول‬


CLI> module unload res_snmp.so
Unloaded res_snmp.so
Unloading [Sub]Agent Module
== Terminating SubAgent
CLI> module load res_snmp.so
Loaded res_snmp.so
== Parsing '/etc/asterisk/res_snmp.conf': == Found
Loading [Sub]Agent Module
Loaded res_snmp.so => (SNMP [Sub]Agent for Asterisk)
== Starting SubAgent

‫ برای این منظور باید فایل‬.‫ بروید و تنظیمات زیر را انجــام دهید‬SNMP ‫اکنــون بایــد به فایلهای پیکربندی‬
:‫ را از مسیر زیر باز و این موارد را به انتهای آن اضافه کنید‬snmpd.conf
#vim /etc/snmpd/snmpd.conf
#agentAddress udp:<local ip- agent ip>:161
#rocommunity public <remote ip- nms ip>

agentAddress udp:192.168.1.6:161
rocommunity public 192.168.1.4

#com2sec notConfigUser default public


com2sec readonly default public

group notConfigGroup v1 notConfigUser


group notConfigGroup v2c notConfigUser

view all included .1


view system included .iso.org.dod.internet.mgmt.mib-2.system

access notConfigGroup "" any noauth exact all none none


syslocation Iran, ON
syscontact Mojtaba Esfandiari.S mespio@gmail.com

master agentx
agentXSocket /var/agentx/master
agentXPerms 0660 0775 nobody root
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪490‬‬

‫‪sysObjectID .1.3.6.1.4.1.22736.1‬‬

‫در این تنظیمات دقت داشــته باشــید کــه پارامترهــای ‪ agentAddress‬و ‪ rocommunity‬را لزوما با آدرس‬
‫آیپیهای متناســب مقداردهی کنید‪ .‬همچنین جهت امنیت بیشــتر ‪ rocommunity‬را از مقدار پیش فرض‬
‫‪ public‬تغییر دهید‪.‬‬
‫برای اینکه ماژول ‪ SNMP‬بتواند استریســک را مانیتور و مدیریت نماید‪ ،‬باید فایلهای ‪ MIB‬مرتبط به‬
‫استریسک را در مسیر فایلهای ‪ MIB‬سیستم‪ ،‬در مسیر زیر اضافه کنید‪ ،‬هرچند که با درنظرگرفتن توزیعهای‬
‫متفاوت لینوکس‪ ،‬این مسیر میتواند متفاوت باشد‪:‬‬
‫‪;REHL‬‬
‫‪/usr/share/snmp/mibs/‬‬

‫‪;Ubuntu‬‬
‫‪/usr/share/snmp/mibs/‬‬

‫سپس باید فایلهای ‪ MIB‬مربوط به استریسک را از اینترنت دانلود و در مسیر فایل های ‪ MIB‬کپی نمایید‪:‬‬
‫‪# mv DIGIUM_MIB.txt /usr/share/snmp/mibs/‬‬
‫‪# mv Asterisk_MIB.txt /usr/share/snmp/mibs/‬‬

‫اکنون سرویس ‪ snmpd‬را ریست کنید‪.‬‬


‫‪#service snmpd restart‬‬

‫تا اینجا ســرویس مدیریت شبکه ‪ snmpd‬در لینوکس نصب شد و ماژول ‪ res_snmp.so‬در استریسک فعال‬
‫گردید‪ .‬اکنون برای تست مدیریت استریسک بهوسیله ‪ SNMP‬میتوان از ابزار ‪ snmpwalk‬استفاده کرد‪.‬‬
‫در زیر مثالهایی را بررسی میکنیم‪:‬‬
‫برای مشاهده نسخه لینوکس دستور زیر را اجرا کنید‪:‬‬
‫‪;Linux uname -a‬‬
‫‪#snmpget -OQv -v2c -c public 127.0.0.1 SNMPv2-MIB::sysDescr.0‬‬

‫برای مشاهده مقدار زمان ‪ uptime‬سیستم‪ ،‬دستور زیر را اجرا کنید‪:‬‬


‫‪;System uptime‬‬
‫‪#snmpget -OQv -v2c -c public 127.0.0.1 SNMPv2-MIB::sysUpTime.0‬‬

‫این دستور تعداد ‪ interface‬های شبکه را نشان میدهد‪:‬‬


‫‪;List network interfaces‬‬
‫‪#snmpwalk -OQv -v2c -c public 127.0.0.1 IF-MIB::ifDescr‬‬

‫برای مشاهده ساختار درختی ‪ SNMP‬در استریسک‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫‪;Walk Asterisk SNMP tree‬‬
‫‪#snmpwalk -v2c -c public 127.0.0.1 ASTERISK-MIB::asterisk‬‬

‫برای مشاهده ورژن استریسک نصب شده روی سیستم‪ ،‬دستور زیر را اجرا نمایید‪:‬‬
‫‪;Asterisk Version‬‬
‫‪#snmpget -OQv -v2c -c public 127.0.0.1 ASTERISK-MIB::astVersionString.0‬‬
‫‪491‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫این دستور تعداد کانالهای فعال در استریسک را نشان میدهد‪:‬‬


‫‪;Number of active channels‬‬
‫‪#snmpget -OQv -v2c -c public 127.0.0.1 ASTERISK-MIB::astNumChannels.0‬‬

‫برای مشاهده لیست کلیه کانالهای استریک‪ ،‬دستور زیر را اجرا کنید‪:‬‬
‫‪;List active channels‬‬
‫‪#snmpwalk -OQv -v2c -c public 127.0.0.1 ASTERISK-MIB::astChanName‬‬

‫همانطور که مالحظه میکنید کلیه این دســتورات برای تســت ماژول ‪ SNMP‬در خود سیســتم بهصورت‬
‫لوکال اجرا شدهاست‪ .‬دقت کنید در صورتی که در تنظیمات مقدار ‪ rocommunity‬را تغییر داده باشید‪ ،‬باید‬
‫مقدار آن را با ‪ public‬در دستورات فوق جایگزین نمایید‪.‬‬
‫ازآنجاکه برای مدیریت و نظارت بر شــبکه از نرمافزارهای مدیریت شــبکه اســتفاده میشود‪ ،‬میتوانید‬
‫ســرور استریســک خود را با یکی از این نرمافزارها پیکربندی کنید تا اطالعات برای آن نرمافزار مدیریت‬
‫شبکه ارسال شود‪.‬‬
‫نرم افزارهای مدیریت شبکه زیادی وجود دارند و میتوانید از هر یک از آنهایی که قابلیت ‪ SNMP‬را‬
‫دارا هستند‪ ،‬استفاده کنید‪ .‬ازآنجاکه توضیح در خصوص نرمافزارهای مدیریت شبکه‪ ،‬خارج از بحث کتاب‬
‫اســت‪ ،‬آن را به خواننده کتاب واگذار میکنیم‪ .‬بهعنوان مثال نمودارهایی از سیستم نرم افزار مدیریت شبکه‬
‫‪ openNMS‬را در شکل )‪ (4-۱7‬مشاهده میکنید‪.‬‬

‫شکل ‪4-17‬‬

‫شــکل ‪ 4-۱7‬تعداد تماس همزمان در واحد زمان را نمایش میدهد‪ .‬همانطور که پیداست میانگین‪ ،‬حداقل‪،‬‬
‫و حداکثر طول مکالمات نسبت به ساعت نمایش داده میشود‪.‬‬
‫در استریسک به ازای هر دو ‪ Active Channel‬یک ‪ Brdidge‬اتفاق میافتد‪ .‬این اتفاق غالبا زمانی رخ‬
‫میدهد که داخلیهای یک سیســتم با هم مکالمه داشتهباشــند‪ .‬شــکل ‪ ۵-۱7‬گزارشهای آماری هر دو نوع‬
‫کانال را نمایش میدهد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪492‬‬

‫شکل ‪5-17‬‬

‫شکل ‪6-17‬‬

‫در شکل ‪ ۶-۱7‬تعداد مکالمه همزمان نسبت به ساعت‪ ،‬نمایش داده شده و در شکل ‪ 7-۱7‬مکالمات بر اساس‬
‫ساعت‪/‬طول مدت مکالمه‪ ،‬نمایش داده شده است‪.‬‬

‫شکل ‪7-17‬‬

‫مدیریت و خطایابی سیستم تلفنی استریسک با استفاده از قابلیت ‪BACKTRACE‬‬

‫گاهی ممکن اســت سیستم تلفنی استریسک‪ crash ،‬کند و ســرویس بهطور ناخواسته ‪ stop‬کند‪ .‬پیدا کردن‬
‫چنین خطاهایی به ســادگی نخواهد بود‪ .‬حتی برخی از خطاها ممکن اســت بــه دلیل بروز یک خطا در کد‬
‫برنامه )ســورس کد استریســک( باشــد‪ .‬همچنین برخی از خطاها به دلیل عدم اســتفاده صحیــح از توابع و‬
‫دستورات در استریسک بهوجود میآید که منجر به ‪crash‬کردن استریسک میشود‪.‬‬
‫‪493‬‬ ‫مانیتورینگ و بررسی گزارش‌ها در استریسک‬

‫معموالً اولین کاری که در چنین شــرایطی باید صورت گیرد‪ ،‬استفاده از الگهای استریسک و ‪syslog‬‬
‫لینوکس اســت‪ .‬ولی چنین خطاهایی هیچ الگی را در گزارشــات استریسک ایجاد نمیکنند‪ .‬تنها میتوانید‬
‫به گزارشهای ‪ syslog‬لینوکس اکتفا کنید‪ .‬برای مثال فرض کنید سیســتم تلفنی استریســک شما بهصورت‬
‫ناخواســته و بدون هیچ دلیلی ‪ crash‬کرده و هیچ الگی هم در گزارشهای استریســک دیده نمیشود‪ .‬تنها‬
‫الگ قابل مشاهده در گزارشهای ‪ syslog‬الگ زیر است‪:‬‬
‫‪15:17:05 root kernel: [39097649.573062] asterisk[13835] segfault at 0 ip (null) sp‬‬
‫]‪00007f309d4da3f8 error 14 in asterisk[400000+209000‬‬

‫با یک جستجوی ساده در اینترنت متوجه میشوید که با راه اندازی مجدد استریک مشکل موقتا رفع خواهد‬
‫هیچ تضمینی در ‪ crash‬نکردن دوباره سیستم استریسک وجود ندارد‪.‬‬ ‫شد‪ .‬ولی‬
‫قابلیــت ‪ BackTrace‬این امکان را فراهم مــیآورد که درصورت مواجهه با چنین خطاهایی‪ ،‬بتوان آنها‬
‫را پیدا و برطرف کرد‪.‬‬
‫اولین اقدام برای حل چنین مشــکالتی این است که به استریسک بگویید چنانچه خطایی در سورسها و‬
‫یا هر جای دیگری اتفاق افتاد‪ ،‬آن را الگ کند و در اختیارتان بگذارد‪ .‬برای این منظور باید از آپشن ‪ –g‬در‬
‫اجرای سرویس استریسک استفاده کنید‪ .‬برای مثال دستور زیر را اجرا کنید‪:‬‬
‫‪# ps -C asterisk u‬‬
‫‪USER‬‬ ‫‪PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND‬‬
‫? ‪root 32675 106 4.7 2881000 47780‬‬ ‫‪Rsl 15:27 0:05 /usr/sbin/asterisk‬‬

‫همانطورکه مالحظه میکنید‪ ،‬در این شــرایط سرویس استریسک از آپشن ‪ –g‬استفاده نکرده است‪ .‬لذا‬
‫باید سرویس استریسک را ‪ stop‬و مجددا ً آن را با روش زیر ‪ start‬کنید‪.‬‬
‫‪# /etc/init.d/asterisk stop‬‬
‫‪# safe_asterisk‬‬

‫اکنون دستور قبلی را مجددا اجرا کنید‪:‬‬


‫‪# ps -C asterisk u‬‬
‫‪USER‬‬ ‫‪PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND‬‬
‫‪root 32796 83.0 2.9 2051452 29588 pts/0 Sl 15:29 0:01 /usr/sbin/asterisk -f -vvvg -c‬‬

‫در این وضعیت‪ ،‬ســرویس استریســک با آپشــن ‪ –g‬اجرا شــده اســت‪ .‬اکنون باید منتظر بمانید تا سرویس‬
‫استریســک دوباره بهصورت ناخواسته ‪ crash‬کند‪ .‬در این حالت استریسک یک فایل الگ در مسیر ‪/tmp/‬‬
‫ذخیره میکند‪ .‬فایل الگ ممکن است بهصورت زیر باشد‪.‬‬
‫‪/tmp/ core.Asterisk-2016-07-25T21_56_40+0000‬‬

‫سپس از دستور دیباگر ‪ gdb‬در لینوکس استفاده کنید تا بتوانید محتویات فایل را بهصورت متنی مشاهده‬
‫کنید‪ .‬برای مثال دستور زیر یک فایل متنی در مسیر ‪ /tmp/backtrace.txt‬ایجاد میکند‪.‬‬
‫‪# gdb -se "asterisk" -ex "bt full" -ex "thread apply all bt" --batch -c /tmp/ core.Asterisk-2016-‬‬
‫‪07-25T21_56_40+0000‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪494‬‬

‫‪> /tmp/backtrace.txt‬‬

‫بهطور حتم با مطالعه و بررســی فنی این فایل‪ ،‬میتوانید علت ‪crash‬کردن استریســک را بفهمید و آن را‬
‫برطرف کنید‪.‬‬

‫نتیجه‌گیری‬
‫مدیریت سیســتمهای شــبکه از جمله وظایف مهم یک مدیر شبکه اســت‪ .‬در این امر شبکههای ویپ استثنا‬
‫نیســتند و یک مدیر شــبکه ویپ باید بتواند بهصورت کامل‪ ،‬شــبکهی خود را زیر نظر داشته باشد‪ .‬مدیریت‬
‫در شــبکههای ویپ از جنبههای متفاوتی بســیار حســاس اســت‪ ،‬چون عالوه بر مدیریت بر عملکرد صحیح‬
‫تجهیزات‪ ،‬باید روی گزارشهای صورت حسابها و ‪ billing‬ها نیز نظارت کامل و دقیقی داشت‪ .‬پارهای از‬
‫حمالت در شبکههای ویپ به قصد اختالل در صورتحسابهای کاربران روی میدهد‪ ،‬بنابراین باید بتوانید‬
‫گزارشهای متعددی در سطوح مختلف ایجاد کنید و سیستم را از این لحاظ‪ ،‬به درستی پیکربندی کنید‪.‬‬
‫فصل هجدهم‬

‫امنیت در سیستم تلفنی‬


‫استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪496‬‬

‫مقدمه‬
‫تا اینجا در خصوص آشــنایی با قابلیتها و تواناییهای سیســتم تلفنی استریســک مطالبی ذکر شــد‪ .‬در این‬
‫فصل همانطور که از نام آن پیداست ابتدا به معرفی و شناخت انواع حملهها به شبکههای ویپ میپردازیم‪،‬‬
‫زیرا تا شناختی نسبت به شبکههای ویپ و انواع حملههای ممکن به آنها نداشته باشیم‪ ،‬نمیتوانیم امنیت را‬
‫تضمین کنیم‪.‬‬
‫از ایــن رو‪ ،‬در شــروع فصل مقدمهای در خصوص امنیت و بررســی انواع حملهها در شــبکههای ویپ‬
‫خواهیم داشت‪ ،‬سپس در ادامه‪ ،‬فرآیندهای امن کردن یک سیستم تلفنی استریسک را معرفی خواهیم کرد‪.‬‬
‫پرواضح اســت که برقراری امنیت در یک شبکه‪ ،‬تشکیل شــده است از مجموعه اقداماتی که هر یک‪،‬‬
‫بخشی از برقراری امنیت را برعهده دارد‪ .‬صرفا با برخورداری از یک فایروال قدرتمند یا استفاده از » ‪SBC‬‬
‫‪ «1‬در مرزهای ورودی شبکه‪ ،‬نمیتوان امنیت یک شبکه ویپ را تضمین نمود‪.‬‬

‫امنیت یک شبکه چیست؟‬


‫دقت داشــته باشــید که منظور از امنیت یک شبکه‪ ،‬خرید یک فایروال قدرتمند‪ ،‬سیستمهای ‪ IPS , IDS‬و یا‬

‫‪1- Session Border Controller‬‬


‫‪497‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫خرید یک ‪ SBC‬قدرتمند در شبکههای ویپ نیست‪ ،‬بلکه امنیت یک سیاست است که افرادی باید آنها را‬
‫وضع و افرادی هم باید آنها را اجرا کنند‪.‬‬
‫پــس در یک تعریف صحیــح از امنیت‪ ،‬میتوان گفت امنیت یک فرآیند اســت که در این فرآیند‪ ،‬هر‬
‫اقدامی که در آن صورت گیرد باعث میشــود بخشــی از سیستم امن شود‪ .‬در تعاریف باال عنوان کردیم که‬
‫برقراری امنیت یک سیاســت است‪ .‬منظور از سیاست امنیتی‪ ،‬بیان رسمیای از قوانینی است که باید بهوسیله‬
‫مدیران ‪ IT‬مطرح شوند‪ .‬در ‪ RFC2196‬سیاستهای کلی امنیت در شبکههای کامپیوتری بیان شدهاست‪.‬‬

‫انواع آسیب‌پذیری‌های حمله‌ها‬


‫معموالً اقدام به حمله به یک شــبکه بهدلیل وجود ضعف در آن اســت‪ .‬این ضعفها که باعث آسیبپذیری‬
‫در شبکه میشود میتواند حاصل یکی از موارد زیر باشد‪:‬‬
‫‪ )1‬آسیب‌پذیری نرم‌افزاری‪ :‬این آسیب‌پذیری حاصل وجود ضعف‌هایی در برنامه‌ها و سرویس‌های مورد‬
‫اســتفاده در شــبکه است‪ .‬برای مثال اگر هنگام نوشتن برنامه در استریســک یا به‌وسیله ‪ ،AGI‬نکات امنیتی را‬
‫رعایت نکنیم‪ ،‬آسیب در ایمنی سیستم تلفنی استریسک اجتناب‌ناپذیر است‪.‬‬
‫‪ )2‬آســیب‌پذیری سخت افزاری‪ :‬این حالت نســبت به حالت اول کمتر شایع است ولی از آن طرف بسیار‬
‫خطرناک‌تر و آسیب‌پذیرتراست‪.‬‬
‫‪ )3‬آســیب‌پذیری پیکربندی‪ :‬به دلیل حجم باالی پیکربندی‌ها و پیچیدگی آن‌ها‪ ،‬خطا در آن امری شــایع‬
‫است‪ .‬البته هر چقدر اطالعات بیشتری در این خصوص داشته‌باشیم‪ ،‬خطا در این بخش کمتر خواهد شد‪ .‬برای‬
‫مثال پیکربندی یک سیستم تلفنی استریسک می‌تواند در حفظ امنیت استریسک نقش به‌سزایی داشته باشد‪.‬‬
‫‪ )4‬آســیب‌پذیری سیاست‪ :‬اگر در تعریف سیاست‌ها و یا پیاده‌ســازی آن‌ها‪ ،‬ضعفی وجود داشته باشد‪ ،‬به‬
‫شبکه آسیب می‌رسد‪.‬‬
‫‪ )5‬آسیب‌پذیری کاربرد‪ :‬اگر کاربران سیستم‪ ،‬سیاست‌های شبکه را نقض کنند‪ ،‬باعث آسیب‌پذیری‌ سیستم‬
‫می‌شوند‪.‬‬

‫نتایج انواع حمله‌ها در شبکه‌ها‬


‫زمانی که یک حمله در شــبکه‌ای رخ می‌دهد‪ ،‬این حمله نتایجی را به همراه دارد‪ .‬نتایج حمله به شــبکه‌های‬
‫ویپ‪ ،‬قابل‌تعمیم است‪ .‬این نتایج را بصورت زیر بررسی می‌کنیم‪:‬‬
‫‪ )1‬افشای اطالعات‪ : 1‬منظور انتشار اطالعات میان افرادی است که مجاز نیستند‪ .‬این اطالعات می‌تواند شامل‬

‫‪1- Disclosure of information‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪498‬‬

‫رمز عبور‪ ،‬اطالعات محرمانه و غیره باشد‪.‬‬


‫‪ )2‬تخریب اطالعات‪ : 1‬این بخش شامل تغییر یا تحریف اطالعات به‌صورت غیر‌مجاز است‪ ،‬مانند هک شدن‬
‫یک سایت‪ ،‬حمله مرد میانی ‪ MITM‬و دستکاری اطالعات ‪ RTP‬در شبکه‌های ویپ‪.‬‬
‫‪ )3‬منع خدمت‪ : 2‬منع خدمت عبارت اســت از کاهش یا مسدود کردن منابع شبکه به‌طوری که سرور نتواند‬
‫خدمات خود را به‌درستی ارائه دهد‪ .‬برای مثال حمله سیل‌‌آسا یا ‪ Flooding‬از این نوع است‪.‬‬
‫‪ )4‬دزدی خدمت‪ : 3‬منظور دسترسی غیرمجاز به شبکه و استفاده از سرویس‌های آن است‪.‬‬
‫‪ )5‬دسترســی بیشتر‪ : 4‬منظور این است که افراد در یک شبکه دسترســی‌های متفاوتی دارند‪ .‬ارائه دسترسی‬
‫بیشتر به افراد غیرمجاز خود می‌تواند یک نوع تهدید برای شبکه محسوب شود‪.‬‬

‫بررسی انواع حمله‌ها در شبکه‌های ویپ‬


‫حمله ‪DOS‬‬
‫این حمله‪ ،‬قابلیت استفاده‪ ۵‬از شبکه را در معرض خطر قرار میدهد و یکی از رایجترین وجدیترین حملهها‬
‫در شــبکههای ویپ اســت‪ .‬این حمله بهمنظور از کار انداختن خدمتگزار برای دریافت‪ ،‬ارسال یا نگهداری‬
‫تماس اســت‪ .‬هدف از این حمله میتواند از کار انداختن تمام یا بخشی از سیستم تلفنی باشد‪ .‬حملهها شامل‬
‫قابلیت استفاده از شبکههای ‪ PSTN‬نیست‪ ،‬چون قابلیت استفاده در این شبکهها ‪ %۹۹,۹۹۹‬است‪ .‬برای فراگیر‬
‫شدن شبکههای ویپ باید راهکاری برای جلوگیری از این حملهها پیدا شود‪.‬‬

‫‪6‬‬
‫شنود‬
‫این حمله‪ ،‬ویژگی محرمانگی‪ 7‬را در معرض خطر قرار میدهد‪ .‬حمله به شنود یعنی گوش دادن به مکالمات‪،‬‬
‫دادهها یا دورنگارهای فرد موردنظر بهصورت نامحسوس و با اهداف جاسوسی‪ .‬در شبکههای ‪ PSTN‬به دلیل‬
‫استفاده از خط خصوصی برای هر نفر و استفاده از یک بستر امن‪ ،‬امکان شنود بسیار پایین است‪.‬‬

‫‪8‬‬
‫تغییر در جریان صدا‬
‫‪۹‬‬
‫این حمله‪ ،‬دو ویژگی محرمانگی و صحت را در معرض خطر قرار میدهد‪ .‬یکنوع حمله از نوع ‪MITM‬‬
‫اســت که هکر میتواند به گفتگوی دو نفر گوش بدهد و این دادهها را تغییر دهد‪ ،‬مانند تبدیل کردن بله به‬

‫‪1- Corruption of Information‬‬


‫‪2- Denial of Service‬‬
‫‪3- Theft of Service‬‬
‫‪4- Increased Access‬‬
‫‪5- Availability‬‬
‫‪6- Eavesdropping‬‬
‫‪7- Confidentially‬‬
‫‪8- Alteration of Voice Stream‬‬
‫‪9- Man In The Middle‬‬
‫‪499‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫خیر و بالعکس یا واژه فروش به خرید و بالعکس‪ ،‬ولی به دلیل غیرقابلپیشبینی بودن گفتگوی انسانها‪ ،‬فقط‬
‫بخش کمی از این دادهها قابلتغییر اســت‪ .‬نوع دیگر این حمله بدین گونه اســت؛ زمانی که برداشت وجهی‬
‫از حساب کاربر صورت میگیرد تلفن گویا بهجای گفتن حساب فعلی‪ ،‬حساب قبلی را به کاربر میگوید و‬
‫کاربر تصور میکند که برداشت وجهی از حساب او صورت نگرفته است‪.‬‬

‫‪1‬‬
‫سوء استفاده رایگان از حساب‬
‫این حمله صحت را در معرض خطر قرار میدهد‪ .‬در این حمله هکر با ســوء استفاده از حساب و شمارههای‬
‫دیگران‪ ،‬سعی در برقراری تماس میکند‪ .‬مث ً‬
‫ال فرد هکر با سوء استفاده از شماره ‪ ۹۰۰‬که در مالکیت مخاطب‬
‫دیگری است‪ ،‬تماس برقرار میکند ولی قبض شارژ آن را باید صاحب آن شماره پرداخت کند‪ ،‬این حملهها‬
‫در شــبکههای مخابراتی مرسوم است و یکی از راههای جلوگیری از آن‪ ،‬استفاده از دستگاههای تشخیص و‬
‫جلوگیری از نفوذ به نام ‪ ۲ IDS‬است‪.‬‬

‫‪3‬‬
‫تغییر مسیر تماس‌ها‬
‫این حمله‪ ،‬دو ویژگی صحت و محرمانگی را در معرض خطر قرار میدهد‪ .‬یکی از ویژگیهای خوب شبکه‬
‫تلفن ویپ‪ ،‬دارابودن یک شــماره و انتقال تماس به نقاط مختلف جهان با همان شــماره است‪ .‬هکر میتواند‬
‫شماره فرد موردنظر را به مکان خود منتصب کند و تماسهای گرفتهشده به آن شماره‪ ،‬به گوشی هکر تغییر‬
‫مسیر یابد‪ .‬این قابلیت در تلفنهای قدیمی نیست‪ ،‬بنابراین این نوع حملهها برای شبکههای قدیمی بیمعناست‪.‬‬

‫‪4‬‬
‫دست‌کاری در داده‌های حساب کاربر‬
‫ایــن حمله‪ ،‬دو ویژگی صحت و محرمانگی را در معرض خطر قرار میدهد‪ .‬در بانک اطالعاتی حســابها‬
‫برای هر شمارهی متعلق به یک فرد‪ ،‬رکوردی به نام ‪ ۵ CDR‬وجود دارد که شامل این اطالعات است‪ :‬شماره‬
‫کســی که تماس گرفته )‪ ،(src‬شــماره کسی که با وی تماس گرفتهشــده )‪ ،(dst‬زمان تماس‪ ،‬طول تماس و‬
‫اطالعات دیگر که با دسترسی به این بانک‪ ،‬هکر میتواند الگوی تماسها را آنالیز و به مسائل مهمی دست‬
‫ال میتواند به تماس بین دو فرد یا شرکت تجاری مهم دست پیدا کند‪ .‬اگر حق دسترسی نوشتن‬ ‫پیدا کند‪ .‬مث ً‬
‫را نیــز روی پایگاه بهدســت بیاورد‪ ،‬میتواند دادههــای خاصی را نیز پاک کند‪ .‬ایــن کار میتواند بهمنظور‬
‫سوءاســتفاده از شــارژ حســاب یا پوشــاندن کارهای مجرمانه صورت پذیرد‪ .‬این نوع حملهها در شبکههای‬

‫‪1- Toll Fraud‬‬


‫‪2- Intrusion Detection System‬‬
‫‪3- Redirection of Call‬‬
‫‪4- Accounting Data Manipulation‬‬
‫‪5- call data records‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪500‬‬

‫مخابراتی صورت میگیرد ولی به دلیل جدا بودن داده از صدا و قرار داشتن بانک داده در یک محل امن و‬
‫شبکه اختصاصی‪ ،‬دسترسی به آن برای هکر بسیار مشکل است‪.‬‬

‫جعل هویت شناسه تماس‬


‫‪1‬‬

‫این حمله‪ ،‬صحت را در معرض خطر قرار میدهد‪ .‬هر تلفن‪ ،‬یک شناســه دارد که همان شــماره تلفن است‪.‬‬
‫در این حمله‪ ،‬هکر شــماره تلفن مخاطب را جعل میکند و میتواند از شماره تلفن جعلشده با مخاطبهای‬
‫مختلف تماس بگیرد یا تماسهای گرفتهشــده به آن شــماره را به گوشــی خود انتقال دهد‪ .‬این حمله برای‬
‫سیســتمهای بانکی که با ســرویس شناســه مخاطب میتواند به حســابهای او دسترســی پیدا کنند‪ ،‬بسیار‬
‫مخاطرهآمیز اســت‪ .‬در سیستمهای تلفن قدیمی‪ ،‬احتمال این حمله بسیار ضعیف است‪ ،‬به دلیل اینکه در این‬
‫شبکهها یک ناظر مرکزی وجود دارد که جلوی این حملهها را میگیرد‪ .‬در شبکههای تلفن ویپ نیز باید از‬
‫این نوع حملهها جلوگیری شود‪.‬‬

‫تماس‌های ناخواسته یا ‪SPIT‬‬


‫ایــن حمله‪ ،‬دو ویژگی صحت و قابلیت اســتفاده را در معرض خطر قرار میدهد و باعث پرشــدن پیغامگیر‬
‫صوتی تلفن مخاطب میشــود‪ .‬اکثر این تماسها‪ ،‬تماسهای تبلیغاتی هســتند‪ .‬این حملهها مانند هرزنامههای‬
‫پســت الکترونیک )‪ (SPAM‬هســتند‪ .‬به هرزنامههای صوتی نیز ‪ SPIT‬میگویند‪ .‬این حملهها در شبکههای‬
‫مخابراتی هم وجود دارد ولی بهدلیل هزینه پایین و بهدستآوردن راحت لیست تلفنها‪ ،‬این نوع حملهها در‬
‫شبکههای ویپ رایجتر است ‪.‬‬
‫جدول ‪ ۱-۱8‬تهدیدات امنیتی در ویپ و تأثیر آنها بر سیستم را مرور میکند‪:‬‬

‫‪Security Concern‬‬ ‫‪Confidentiality‬‬ ‫‪Integrity‬‬ ‫‪Availability‬‬


‫‪Denial of Service‬‬ ‫‪X‬‬
‫‪Eavesdropping‬‬ ‫‪X‬‬
‫‪Alteration of Voice Stream‬‬ ‫‪X‬‬ ‫‪X‬‬
‫‪Toall Fraud‬‬ ‫‪X‬‬
‫‪Redirection of Call‬‬ ‫‪X‬‬ ‫‪X‬‬ ‫‪X‬‬
‫‪Accounting Data Manipulation‬‬ ‫‪X‬‬ ‫‪X‬‬
‫‪Caller ID Impersionation‬‬ ‫‪X‬‬
‫‪Unwanted Calls and Messages‬‬ ‫‪X‬‬ ‫‪X‬‬
‫جدول ‪1-18‬‬

‫در ادامه به بررسی انواع حملهها روی پروتکل ‪ SIP‬و ‪ RTP‬در شبکههای ویپ میپردازیم‪.‬‬

‫‪1- Caller Identification ID Impersonation‬‬


501 ‫امنیت در سیستم تلفنی استریسک‬

‫خصیصه‌های دفاعی در شبکه‌های ویپ و چالش‌های حیاتی‬


‫ خالصه و لیست‬۲-۱8 ‫خطرات دیگری در سیســتم ویپ وجود دارند که براساس الیهبندی شبکه در جدول‬
‫ محل اتفاق افتادن آن چالش ازلحاظ منطق ســاختار شــبکه را مشــخص‬،‫ فیلد الیه در جدول زیر‬.‫شــدهاند‬
‫ خدمتگزارها و دیگر جاهای شــبکه‬،‫ برای مثال حمله به سیســتمعامل میتواند در گروههای انتهایی‬.‫میکند‬
‫ حملههایی که خاص شبکه‬.‫اتفاق بیفتد ولی تمام این حملهها در الیه برنامه کاربردی در شبکه واقع میشوند‬
IP ‫ مشترک در شبکه‬،‫ با سایه خاکستری رنگ مشخصشدهاند و سایر حملهها‬۲-۱8 ‫ در جدول‬،‫ویپ هستند‬
.‫ اند‬PSTN ‫و شبکههای‬

LAYER Attack Mechanism Confidentiality Integrity Availability


Physiacal Physical Attack X X
Network ARP Cache Poison X X X

MAC Spoofing X X X

Data Link Device IP Spoofing X X X

Malformed Packets X
Transport TCP or UDP Floods X

TCP or UDP reply X


Application TFTP Server Insertion X

DHCP Starvation X

ICMP Floods X

Buffer Overflow X X X

Operating System X X X

Viruses and Malware X X X

Databas Attacks X X

SIP Attack:
Registeration HiJacking X X X

Message Modification X X

Cancel/Bye Attack X

Malformed Command X

Redirect X X

RTP Attacks:
RTP Playload X

RTP Tampering X X X
2-18 ‫جدول‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪502‬‬

‫‪1‬‬
‫ربودن ثبت‌نام در پروتکل ‪SIP‬‬
‫پروتکل ‪ SIP‬برای نظارت بر الیهی برنامه کاربردی در شــبکه اســت و وظیفه آن در شبکه ویپ‪ ،‬برقراری‪،‬‬
‫تغییر و خاتمه جلسات در تماسهای تلفنی است‪ .‬یک کاربر )تلفن( برای استفاده از شبکه ویپ ابتدا باید در‬
‫ســرور استریسک یا سرور پراکسی ثبتنام کند‪ .‬ربودن ثبتنام‪ ،‬زمانی رخ میدهد که هکر‪ ،‬خود را بهجای‬
‫یک شــخص قانونی در شــبکه جا بزند و آدرس خود را در شــبکه ثبت کند‪ .‬این حمله باعث میشــود که‬
‫تماسهای دریافتی با مخاطب‪ ،‬به تلفن هکر منتقل شــود و تماسهای ارسالی به تلفن مخاطب را از بین ببرد‪.‬‬
‫این حمله میتواند برای یک فرد یا گروهی از افراد واقع شــود و شــمارههای آنها را بلوکه کند تا نتوانند از‬
‫افــراد مختلف‪ ،‬تماس دریافت کنند‪ .‬درحالحاضــر‪ ،‬اطالعات ثبتنام روی پروتکلهای حمل مانند ‪ TCP‬و‬
‫‪ UDP‬انجام میشود که با استفاده از امنسازی الیه حمل‪ ،‬پروتکل ‪ TLS‬پدیدۀ حمل ارتباطات امن با احراز‬
‫هویت در یک فضای باز ناامن برای مقابله با ربوده شدن ثبتنام را ایجاد میکند‪.‬‬

‫‪2‬‬
‫تغییر پیام پروتکل ‪SIP‬‬
‫پروتکل ‪ ، SIP‬مکانیســم کاری صحیحی برای ارزیابی ندارد و با انجام حملههای ‪ MITM‬مانند دستکاری‬
‫در آدرس سختافزاری شبکه‪ ،‬آدرس ‪ ،IP‬اطالعات ثبتنام در پروتکل ‪ ،SIP‬هکر میتواند پیامهای ‪ SIP‬را‬
‫قطع یا دستکاری کند؛ مانند متصل کردن تماس یک فرد یا گروه به فرد یا گروه دلخواه دیگر‪ ،‬خط روی‬
‫خــط انداختــن که با محافظت از پروتکلهای الیه حمل ‪ TCP‬و ‪ UDP‬و اســتفاده از پروتکل ‪ TLS‬میتوان‬
‫از محتوای پیامهای ‪ SIP‬محافظت کرد‪ .‬با این کار هکر قادر به خواندن یا تغییر محتوای پیام ‪ SIP‬نیست‪.‬‬

‫‪3‬‬
‫حمله لغو ‪ /‬خداحافظی در ‪SIP‬‬
‫در این حمله‪ ،‬هکر پیام لغو یا خداحافظی را در بســتههای ‪ SIP‬میســازد و آن را به گرهها و نودهای انتهایی‬
‫)تلفنها( مخاطب میفرســتد‪ .‬این پیام باعث قطع تماس مخاطبین حین مکالمه میشــود‪ .‬اگر هکر بهصورت‬
‫ثابت و مداوم این پیامها را به تلفن قربانی بفرستد‪ ،‬فرد قربانی دیگر قادر به گرفتن یا دریافت تماس نخواهد‬
‫بــود‪ .‬ایــن حمله اگر به تعــداد زیادی از تلفنهــا صورت گیرد میتواند سیســتم تلفنی یا قســمتی از آن را‬
‫مختل کند‪ .‬با ســختکردن احــراز هویت میتوان از این حمله جلوگیری کــرد‪ ،‬بهطوریکه پیامهای لغو و‬
‫خداحافظی فقط از گرههایی که صالحیت آنها تأییدشده قبول شود و بقیه رد شوند‪ .‬شکل ‪ ۱-۱8‬این حمله‬
‫را به تصویر کشیده است‪.‬‬

‫‪1- SIP Registration Hijacking‬‬


‫‪2- SIP Message Modification‬‬
‫‪3- MAC‬‬
‫‪503‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫شکل ‪1-18‬‬

‫‪1‬‬
‫حمله بازگشت در ‪SIP‬‬
‫در حملــه بازگشــت در ‪ ، SIP‬دو گــروه داور و ارجاعکننده داریم که گروه داور بــه گروه ارجاعکننده‬
‫‪۳‬‬ ‫‪۲‬‬

‫میتواند متصل شــود یا پیام بفرســتد‪ .‬هنگام ردوبدلشدن پیام میان این دو گروه‪ ،‬حملههای ‪ MITM‬و شنود‬
‫میتوانــد صــورت گیرد و اطالعاتی از هر دو گــروه را به هکر بدهد‪ .‬یکی از راههــای اجتناب از این کار‪،‬‬
‫استفاده از روش رمز نگاری ‪ SMIME‬است که بستههای پیام را بهصورت رمزینه میفرستد تا هکر نتواند آن‬
‫را بخواند و در آن تغییر صورت دهد‪.‬‬

‫‪4‬‬
‫حمله دعوت مجدد در ‪SIP‬‬
‫زمانی که اولین جلسه میان دو مخاطب برقرار شود‪ ،‬در درخواستهای بعدی ممکن است بخواهند تغییراتی‬
‫در پارامترهای این جلســه کاری بدهند؛ مانند تغییر در آدرس آی پی و درگاه که ممکن است بهوسیله یک‬
‫هکر صورت گرفته باشد‪ ،‬به همین علت‪ ،‬تغییرات غیرمجاز بهوسیله پیامهای دعوت مجدد در ‪ SIP‬امکان از‬
‫کار انداختن سیستم تلفنی را دارند‪ .‬این حمله در شکل ‪ ۲-۱8‬نشان دادهشده است‪.‬‬

‫‪5‬‬
‫حمله به‌روزرسانی در ‪SIP‬‬
‫خاصیت بهروزرســانی‪ ،‬به کاربر امکانات مختلفی را میدهد‪ ،‬ازجمله بیصدا کردن تلفن‪ ،‬گذاشــتن گوشی‬
‫روی حالت انتظار و تطبیق کیفیت ســرویس و دیگر صفات یک جلسه‪ .‬این حمله مانند حمله دعوت مجدد‬

‫‪1- REFER ATTACK‬‬


‫‪2- Referrer‬‬
‫‪3- Referee‬‬
‫‪4- Re-INVITE ATTACK‬‬
‫‪5- UPDATE ATTACK‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪504‬‬

‫اســت‪ ،‬با این تفاوت که دعوت مجدد پس از برقراری یک جلســه صورت میگیرد ولی بهروزرسانی برای‬
‫تغییر پارامترهای جلســه‪ ،‬پیش از ارسال اولین پیام دعوت صورت میگیرد‪ .‬این حمله در شکل ‪ ۳-۱8‬نمایش‬
‫دادهشــده اســت‪ .‬حمله بهروزرســانی عموماً برای تغییر در کیفیت ســرویس یا عوض کــردن آدرس ‪ IP‬یا‬
‫درگاهها صورت میگیرد‪.‬‬

‫شکل ‪2-18‬‬

‫شکل ‪3-18‬‬

‫‪1‬‬
‫حمله اطالعات‬
‫گاهی پروتکل ‪ SIP‬ممکن است واسط دو شبکه ‪ PSTN‬باشد که به آن فناوری ‪ SIP-T‬گفته میشود‪ .‬روش‬
‫حمل اطالعات‪ ،‬مکانیســمی برای حمل اطالعات الیه برنامه کاربردی از طریق ســیگنالینگ ‪ SIP‬اســت که‬
‫یک تونل اطالعاتی میسازد‪ .‬اطالعات مبادله شده ازطریق ‪ STP-T‬شامل اطالعات شبکه ‪ ،PSTN‬اطالعات‬
‫‪1- Re-INVITE ATTACK‬‬
‫‪505‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫صورتحساب مشتری و ‪ ...‬است که هکر میتواند به این اطالعات در شبکه واسط ‪ SIP‬حمله کند‪ .‬پیامدهای‬
‫این حمله‪ ،‬اشتباه شدن صورتحساب کاربران‪ ،‬از کار انداختن سیستم و دسترسی غیرمجاز به تماسهاست‪.‬‬

‫‪1‬‬
‫ایجاد ناهنجاری در دستورات ‪SIP‬‬
‫محتــوای پیــام در ‪ ، SIP‬متنی و مانند پروتکل ‪ HTML‬اســت کــه از مزایــای آن‪ ،‬انعطافپذیری و وجود‬
‫ویژگیهای زیاد اســت‪ .‬از معایب آن پیادهســازی دشــوار تجزیهگر اســت که یک نقطــه ضعف برای آن‬
‫محســوب میشــود و هکرها از همین نقطهضعف اســتفاده میکننــد و پیام ‪ SIP‬را تغییــر میدهند‪ ،‬ورودی‬
‫نامعتبر به تجزیهگر میفرســتند و گره مربوطه یا کل سیســتم تلفنی را دچار مشــکل میکنند‪ .‬اعتبارســنجی‬
‫تجزیهگرها بســیار دشوار اســت‪ .‬یکی از راههای آزمودن‪ ،‬استفاده از دستگاههای آزمایشی فازی است که با‬
‫تولید درخواست نامعتبر سعی در کشف اشکاالت و خطاهای دستوری تجزیهگر دارند‪.‬‬

‫‪2‬‬
‫حمله تغییر مسیر در ‪SIP‬‬
‫یکی از قابلیتهای شــبکههای ‪ SIP‬این اســت که شخص ‪ A‬میتواند به شــخص ‪ B‬بدون توجه به موقعیت‬
‫جغرافیایی او و فقط با دانســتن شماره تلفن شــخص ‪ B‬ارتباط برقرار کند که این ارتباط از طریق تغییر مسیر‬
‫در سرورهای پراکسی صورت میگیرد‪ .‬حال اگر فرد هکر تماسهای فرد ‪ A‬را به تلفن خودش یا یک جای‬
‫نامعتبر تغییر مســیر دهد میتواند سیســتم را از کار بیاندازد‪ .‬علت این حمله ضعف در مکانیسم احراز هویت‬
‫در ‪ SIP‬است که با بهکارگیری پروتکل ‪ TLS‬و داشتن پسورد پیچیده میتوان از این حمله پیشگیری کرد‪.‬‬

‫‪3‬‬
‫حمله با ِر کاری ‪RTP‬‬
‫پروتکل ‪ RTP‬برای حمل صدا بین دو گره است که از پروتکل الیه حمل ‪ UDP‬استفاده میکند‪ .‬با حملههای‬
‫‪ MITM‬میتوان دسترســی به پروتکل ‪ RTP‬بین دو گره را پیــدا کرد و هکر میتواند با ِر کاری در پروتکل‬
‫‪ RTP‬را شــنود کند یا تغییر دهد‪ .‬دســتکاری در با ِر کاری‪ ،‬مانند اضافه کردن نویز در مکالمات و کاهش‬
‫کیفیت سرویس است‪ .‬با استفاده از پروتکل ‪ RTP‬امن شده ‪ SRTP‬میتوان جلوی این حملهها را گرفت‪.‬‬

‫‪4‬‬
‫دست‌کاری ‪RTP‬‬
‫با دستکاری در شماره‪ ،‬ترتیب یا تاریخ سرآیند بستهها‪ ،‬میتوان ارتباط بین دو گره بهوسیله پروتکل ‪RTP‬‬
‫را ناپایدار کرد یا در برخی از پیادهسازیها میتوان باعث خراب شدن گره دریافتکننده پیام شد‪ .‬با استفاده‬

‫‪1- Malformed SIP Command‬‬


‫‪2- SIP Redirect‬‬
‫‪3- RTP Payload‬‬
‫‪4- RTP Tampering‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪506‬‬

‫از پروتکل ‪ SRTP‬میتوان مطمئن شد که سرآیند بستهها در ‪ RTP‬تغییر نکردهاند‪ .‬راه دیگر جداسازی مسیر‬
‫داده از مســیر صوت است که با اســتفاده از فناوری ‪ VLAN‬در شبکه انجام میگیرد؛ یعنی برای هر یک از‬
‫داده و صوت‪ ،‬مسیر جداگانه مجازی در نظر گرفته میشود‪.‬‬

‫انواع حمله‌ها در شبکه‌های ‪IP‬‬

‫این حملهها‪ ،‬حملههای خاص ویپ نیستند بلکه حملههایی هستند که در شبکههای مبتنی بر آی پی مشترکاند‬
‫و چون بستر ارتباطی شبکههای ویپ هم روی آی پی است‪ ،‬این نوع حملهها نیز مورد توجه است‪ .‬انواع این‬
‫حملهها عبارتند از‪:‬‬

‫‪1‬‬
‫حمله فیزیکی‬
‫دســتکاری فیزیکی اجزای شبکه ویپ مانند اتصاالت‪ ،‬گوشیها‪ ،‬پروکسی ها‪ .‬این حمله‪ ،‬قابلیت استفاده و‬
‫محرمانگی را از بین میبرد‪ .‬اجزای فیزیکی شــبکه مانند اتصاالت‪ ،‬پروکسی ها و سوئیچها نباید در دسترس‬
‫همه باشــند و باید از وسایل امنیتی فیزیکیای همچون دربهای قفلدار‪ ،‬محافظ اتصاالت و کابلها استفاده‬
‫کرد‪.‬‬

‫حمله ‪ARP‬‬
‫هکر با ســاختن بسته ‪ ARP‬جعلی و فرستادن آن به شبکه‪ ،‬ســعی میکند آدرس سختافزاری کارت شبکه‬
‫خود را به آدرس آی پی فرد موردحمله نسبت دهد تا بتواند خود را در ظاهر او درآورد و در تلفن و سیستم‬
‫تلفنی وی اختالل ایجاد کند‪.‬‬

‫‪2‬‬
‫جعل آدرس سخت‌افزاری‬
‫ســاخت یک گره با یک آدرس سختافزاری تکراری در شبکه است‪ .‬این حمله باعث از کار انداختن گره‬
‫اصلی با آدرس ســختافزاری مشــابه میگردد و میتواند خود را بهجای آن گره که قب ً‬
‫ال در شــبکه احراز‬
‫هویت شده‪ ،‬جا بزند‪ .‬یکراه حل برای مقابله با این حمله این است که نگذاریم گره جدیدی به شبکه اضافه‬
‫شود‪ ،‬قبل از اینکه از طریق درگاه ارتباطی احراز هویت شود‪.‬‬

‫‪3‬‬
‫جعل آدرس ‪IP‬‬
‫با این حمله‪ ،‬هکر میتواند بدون احراز هویت به شــبکه یا رایانه دیگری با جعل آدرس آی پی متصل شــود‪.‬‬

‫‪1- Physical Attack‬‬


‫‪2- MAC Spoofing‬‬
‫‪3- IP Spoofing‬‬
‫‪507‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫این فن برای به دســتگرفتن کنترل گرههای انتهایی در شــبکه ویپ به کار میرود‪ .‬برای جلوگیری از این‬
‫حمله‪ ،‬مســیریاب نباید به بســتههایی آی پی دهد که آدرس مقصد آنها شبکه داخلی است و بستهها چنانچه‬
‫آدرس مبدأ در آنها ذکر نشده باشد‪ ،‬نباید اجازه مسیریابی به بیرون را داشته باشند‪.‬‬

‫بسته‌های نامعتبر‬
‫‪1‬‬

‫در این روش‪ ،‬هکر در شــبکه ســعی در تولید بســتههای معیوب میکند‪ ،‬به نحوی که پردازش این بستههای‬
‫معیوب باعث مصرف منابع شبکه شود‪ .‬جلوگیری از این حمله شامل دو فاز است‪ .‬فاز اول‪ ،‬تمام تلفنها باید‬
‫دارای نرمافزار بهروز باشــند و در فاز دوم‪ ،‬شبکه باید دارای یک دیوار آتشین با قابلیت باال برای جلوگیری‬
‫از ورود بستههای معیوب باشد‪.‬‬

‫‪2‬‬
‫حمله سیل‌آسای پیام ‪ SYN‬در پروتکل ‪TCP‬‬
‫در این حمله‪ ،‬هکر بســتههای زیادی با آدرسهای مقصد تصادفــی تولید میکند که در همگی آنها پرچم‬
‫‪ SYN‬به گونهای تنظیمشــده است که درخواســت بافر از گره پذیرنده این پیامها را داشته باشند‪ .‬با پر شدن‬
‫فضــای بافــر گره‪ ،‬قربانی قادر به برقــراری تماس نخواهد بود‪ .‬راهحل مقابله با این حمله‪ ،‬اســتفاده از دیواره‬
‫آتش با توانایی باال و داشتن پیامهای تصدیق پیام ‪ ACK‬بر اساس ترتیب ارسال‪ ،‬پیش از پر شدن فضای بافر‬
‫گره مربوطه است‪.‬‬

‫‪3‬‬
‫حمله بازپخش پروتکل ‪ UDP‬و ‪TCP‬‬
‫در این حمله‪ ،‬هکر بســتههای اطالعاتیای نظیر احراز هویت‪ ،‬مکالمات صوتی و ‪ ...‬را به دســت میآورد و‬
‫میتواند این پیامها را در شــبکه دوباره بازپخش کند‪ .‬یکی از راههای جلوگیری از این حمالت‪ ،‬رمزنگاری‬
‫شماره ترتیب جلسات و بازگشایی رمز در مقصد برای به دست آوردن شماره مقصد درست است‪.‬‬

‫حمله ‪TFTP‬‬
‫تلفنهای ویپ در شــبکه‪ ،‬تنظیمات و نرمافزارهای بهروز خود را از فایل سرور با پروتکل ‪ TFTP‬میگیرند‪.‬‬
‫هکر میتواند با ســاختن یک فایل در ســرور مجازی‪ ،‬تنظیمات اشــتباهی را به کاربران اختصاص دهد که‬
‫ممکن است باعث دستکاری صورتحسابها شود‪ .‬یکی از راههای جلوگیری از این حمالت‪ ،‬استفاده از‬
‫پروتکل ‪ TLS‬و امنسازی ارتباطات بهوسیله پروتکل ‪ SSL‬است‪.‬‬

‫‪1- Malformed Packet‬‬


‫‪2- TCP SYN Flood‬‬
‫‪3- TCP or UDP Replay‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪508‬‬

‫حمله ‪DHCP‬‬
‫در این حمله‪ ،‬هکر با تولید تصادفی آدرسهای سختافزاری شبکه و گرفتن آی پی از سرور ‪ DHCP‬سعی‬
‫در پر کردن استخر آی پی در سرور ‪ DHCP‬دارد و هیچیک ازتجهیزات دیگر نمیتوانند از سرور ‪،DHCP‬‬
‫آی پــی بگیرند‪ .‬یکراه جلوگیری از این حمله‪ ،‬احراز هویت آدرس ســختافزاری کارت شــبکه هنگام‬
‫فرستادن درخواست آی پی است‪.‬‬

‫حمله ‪ICMP‬‬
‫در این حمله‪ ،‬هکر با فرســتادن بستههای زیاد ‪ ICMP‬ســعی در پایین آوردن کارایی گره قربانی دارد‪ .‬یکی‬
‫از راههای جلوگیری از این حمله‪ ،‬بلوک کردن بستههای ‪ ICMP‬غیرضروری است و یکی دیگر از راههای‬
‫مقابله‪ ،‬جداسازی شبکه داده از صدا بهوسیله ایجاد شبکه مجازی‪ ۱‬جداگانه است‪.‬‬

‫حمله سرریز بافر‬


‫حمله ســرریز بافر با تولید ضعف در سیســتم‪ ،‬سعی در پر کردن بیشازحد بافر گره قربانی دارند‪ .‬سرریز بافر‬
‫ممکن اســت منجر به نفوذ به کدهای همســایه آن نیز بشــود‪ .‬در این حمله کنترل گره قربانی در دست هکر‬
‫اســت‪ .‬برای جلوگیری از این حمله‪ ،‬باید وصلههای امنیتی را در سیســتمعاملهایی مانند لینوکس و ویندوز‬
‫نصب کرد‪.‬‬

‫حمله به سیستم‌عامل‬
‫بســیاری از حملهها‪ ،‬شــناخته و ناشــناخته روی تلفنهای ویپ به علت ضعف در سیستمهای عامل است که‬
‫میتوان تلفنهای نرمافزاری را روی میز کار این سیســتمعاملها نصب کرد‪ .‬برای جلوگیری از این حملهها‬
‫باید از وصلههای امنیتی بهروز برای سیستمعامل استفاده کرد‪.‬‬

‫ویروس‌ها‬
‫ویروسها نیز از ضعف سیســتمعامل استفاده میکنند‪ ،‬به سیســتم گرههای انتهایی و دروازهها نفوذ میکنند‬
‫و باعث کاهش کارایی گره مربوطه میشــوند‪ .‬روش مقابله با این حمله‪ ،‬اســتفاده از وصلههای امنیتی بهروز‬
‫برای سیستمعامل است‪.‬‬

‫حمله به پایگاه داده‬


‫حملــه به پایگاه داده در سیســتم ویپ عمومــاً حمله به دادههای ثبــت وقایع کاربران با نام ‪ CDR‬اســت‪ .‬با‬

‫‪1- VLAN‬‬
‫‪509‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫حملههای شناختهشــده به پایگاههای معروف میتوان بهراحتی دادههای ‪ CDR‬را دســتکاری کرد به همین‬
‫منظور یکی از راههای مقابله با این حملهها‪ ،‬جداســازی پایگاه داده و قرار دادن آن در یک شــبکه مجازی‬
‫جداگانه است‪ .‬این جداسازی جلوی ارسال و دریافت دادههای غیرمجاز را میگیرد‪.‬‬

‫امنیت سیگنالیک در پروتکل ‪SIP‬‬

‫پروتکل ‪ SIP‬یک پروتکل متنی و قابل خواندن است‪ ،‬بهطوریکه اگر محتویات آن را مشاهده کنیم‪ ،‬متوجه‬
‫نوع درخواست و ‪ session‬آن خواهیم شد‪ .‬برای مثال برنامه زیر را در نظر بگیرید‪:‬‬
‫‪INVITE sip:marconi@radio.org SIP/2.0‬‬
‫‪Via: SIP/2.0/UDP lab.high-voltage.org:5060;branch=z9hG4bKf‬‬
‫‪Max -Forwards: 70‬‬
‫>‪To: G. Marconi <sip:MarconiOradio.org‬‬
‫‪From: Nikola Tesla <sip:n.teslaehigh-voltage.org>;tag=7634‬‬
‫‪Call -ID: 123456789@lab.high-voltage.org‬‬
‫‪CSeq: 1 INVITE‬‬
‫‪Subject: About That Power Outage...‬‬
‫>‪Contact: <sip:n.tesla@lab.high-voltage.org‬‬
‫‪Content -Type: application/sdp‬‬
‫‪Content -Length: 158‬‬
‫‪v=0‬‬
‫‪o=Tesla 2890844526 2890844526 IN IP4 lab.high-voltage.org‬‬
‫‪s=Phone Call‬‬
‫‪c=IN 1P4 100.101.102.103‬‬
‫‪t=0 0‬‬
‫‪m=audio 49170 RTP/AVP 0‬‬
‫‪a=rtpmap:0 PCMU/8000‬‬

‫در بدنه پروتکل ‪ ،SIP‬پروتکل ‪ SDP‬هم وجود دارد‪ .‬به واسطه این پروتکل‪ ،‬میتوان نیازمندیهای الزم برای‬
‫برقراری ‪ session‬را مشــاهده کرد؛ همچنین اطالعاتی نظیر نوع کدک مورد اســتفاده‪ ،‬پورت برای دریافت‬
‫دادههای صوتی و تصویری و ‪ ...‬در این نوع پروتکل بهصورت متنی ذخیره میشوند‪ .‬همین امر سبب میشود‬
‫که هکرها بهراحتی بتوانند این پروتکل را مورد حمله و نفوذ قرار دهند‪.‬‬
‫پروتــکل ‪ SIP‬میتوانــد در الیه انتقال‪ ،‬از پروتکلهای‪ TCP‬و ‪ UDP‬اســتفاده کنــد‪ .‬در صورت نیاز به‬
‫کدگــذاری این پروتــکل‪ ،‬بهگونهایکه دیگر قابل خواندن نباشــند‪ ،‬باید از پروتــکل ‪ ۱ TLS‬در الیه انتقال‬
‫استفاده کرد‪.‬‬

‫استفاده از پروتکل ‪ TLS‬در سیگنالینگ شبکه‌های ویپ‬


‫با توجه به این که پروتکل ‪ ، SIP‬پروتکل ســیگنالینگ در شــبکههای ویپ است‪ ،‬استفاده از پروتکل ‪TLS‬‬

‫‪1- Transport Layer Security‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪510‬‬

‫برای انتقال سیگنالینگ در شبکههای ویپ باعث میشود این پروتکل رمزنگاری شود؛ از طرف دیگر برای‬
‫انتقال دادههای صوت )‪ (RTP‬باید از پروتکل رمزنگاری ‪ RTP‬به نام ‪ SRTP‬یا ‪ ZRTP‬استفاده کرد‪ .‬در این‬
‫صورت هم سیگنالیک و هم مدیا در شبکههای ویپ رمزنگاری میشوند‪.‬‬
‫ابتدا برای استفاده از پروتکل ‪ TLS‬در شبکههای ویپ باید بستههای مورد نیاز را نصب کنید‪:‬‬
‫‪;RHEL‬‬
‫‪yum install openssl-devel‬‬

‫‪;Ubuntu‬‬
‫‪apt-get install libssl-dev‬‬

‫بعد از نصب نیازمندیهای فوق باید در فایل ‪ sip.conf‬استفاده از پروتکل ‪ TLS‬را فعال کنید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[general‬‬
‫‪tlsenable = yes‬‬
‫‪;tlsbindaddr = ::‬‬

‫را تولید و به استریسک معرفی نمایید‪.‬‬ ‫در مرحله بعد باید کلیدهای رمز نگاری‬
‫اجــازه دهیــد اینجا دو ســناریوی متفاوت را بررســی کنیم‪ .‬در حالــت اول فرض کنید بخواهیم دو ســرور‬
‫استریســک با هم یک ارتباط امن داشــته باشــند و در حالت دوم کالینتهایی هستند که قرار است با سرور‬
‫استریسک ارتباط امن داشته باشند‪.‬‬
‫در هر دو حالت به این نیاز داریم که کلیدهای رمزنگاری تولید شــوند و از آنها در ســرورهای استریسک‬
‫و کالینتها اســتفاده کنیم‪ .‬در مســیر فایلهای اصلی استریســک‪ ،‬اســکریپتی وجود دارد که به واسطه آن‬
‫میتوان فایلها و کلیدهای رمزنگاری را تولید نمود‪ .‬همچنین میتوان از ابزار ‪ openSSL‬برای ایجاد فایلها‬
‫و کلیدهای رمزنگاری استفاده کرد‪ .‬اینجا از روش اول استفاده میکنیم‪.‬‬

‫ایجاد کلیدهای رمزنگاری به‌وسیله اسکریپت ‪ast_tls_cert‬‬


‫در این روش از اسکریپت ‪ ast_tls_cert‬موجود در فایلهای اصلی استریسک که در مسیر زیر وجود دارد‪،‬‬
‫استفاده میکنیم‪ .‬برای این منظور به مسیر زیر بروید‪.‬‬
‫‪# cd asterisk-source/contrib/scripts‬‬

‫ابتدا یک فایل با نام دلخواه ایجاد کنید تا بتوانید فایلها و کلیدهای رمزنگاری را در آن ذخیره کنید‪.‬‬
‫‪# mkdir /etc/asterisk/certificates‬‬

‫سپس اسکریپت را بهصورت زیر فراخوانی کنید‪.‬‬


‫‪# ./ast_tls_cert -C 192.168.1.101 -O "Company Name" -d /etc/asterisk/certificates‬‬

‫با اجرای دســتور باال‪ ،‬از شــما درخواست میشــود که رمز عبوری را مشخص و وارد نمایید‪ .‬اینجا باید یک‬
‫رمز عبور به دلخواه وارد کنید‪ .‬در ادامه مهمترین پارامترهای استفاده از اسکریپت فوق را شرح میدهیم‪.‬‬
‫‪511‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫• پارامتر ‪ : -C‬برای مشــخص کردن آدرس آی پی یا ‪ DNS‬ســرور استریسک است(این پارامتر اختیاری می‬
‫باشد و در صورت لزوم باید آدرس آی پی سرور استریسک خود را جایگزین نمایید)‪.‬‬
‫• پارامتر ‪ : -O‬برای مشخص کردن نام شرکت استفاده می‌شود‪.‬‬
‫• پارامتر ‪ : -d‬آدرس مسیر برای ذخیره کردن فایل‌ها و کلید‌های رمزنگاری است‪.‬‬
‫پس از اجرای دستور فوق‪ ،‬باید فایلهای زیر در مسیر مشخص شده ایجاد شده باشند‪.‬‬
‫‪#ls /etc/asterisk/certificates/‬‬
‫‪asterisk.crt asterisk.csr asterisk.key asterisk.pem ca.cfg ca.crt ca.key tmp.cfg‬‬

‫سپس تغییرات زیر را در فایل ‪ sip.conf‬در سرور استریسک ایجاد کنید‪.‬‬


‫‪;sip.conf‬‬
‫‪tlsenable=yes‬‬
‫‪tlsbindaddr=0.0.0.0‬‬
‫‪tlscertfile=/etc/asterisk/certificates/asterisk.pem‬‬
‫‪tlscafile=/etc/asterisk/certificates/ca.crt‬‬
‫‪tlscipher=ALL‬‬
‫‪tlsclientmethod=tlsv1‬‬

‫پس از انجام تغییرات فوق‪ ،‬باید سرور استریسک را مجددا راه اندازی کنید‪ .‬برای این منظور در کامند الین‬
‫استریسک دستور زیر را اجرا کنید‪.‬‬
‫‪CLI> sip reload‬‬
‫‪Reloading SIP‬‬
‫‪== Parsing '/etc/asterisk/sip.conf': Found‬‬
‫‪== Parsing '/etc/asterisk/sip_custom.conf': Found‬‬
‫‪== Parsing '/etc/asterisk/users.conf': Found‬‬
‫‪== Using SIP CoS mark 4‬‬
‫‪== TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled‬‬
‫‪== TLS/SSL certificate ok‬‬
‫‪== Parsing '/etc/asterisk/sip_notify.conf': Found‬‬

‫همانطورکه مالحظه میکنید ‪ TLS‬فعال شده است‪ .‬همچنین میتوانید صحت فعال بودن ‪ TLS‬در استریسک‬
‫بهصورت زیر بررسی نمایید‪.‬‬ ‫را روی پورت ‪۵۰۶۱‬‬
‫‪#netstat -nlpt | grep 5061‬‬
‫‪tcp‬‬ ‫‪0 0 0.0.0.0:5061‬‬ ‫*‪0.0.0.0:‬‬ ‫‪LISTEN‬‬ ‫‪1275/asterisk‬‬

‫برقراری ارتباط امن بین کالینت‌ها و سرور استریسک‬


‫در ایــن حالــت باید فایل و کلیدهای رمزنگاری را در اختیار کالینتها قرار دهید‪ .‬برای این منظور ابتدا باید‬
‫آنها را بهصورت زیر ایجاد کنید‪.‬‬
‫‪#./ast_tls_cert -m client -c /etc/asterisk/certificates/ca.crt -k /etc/asterisk/certificates/ca.key‬‬
‫‪-C 192.168.1.21 -O "Company Name" -d /etc/asterisk/certificates -o Phone_1‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪512‬‬

‫با اجرای دستور فوق‪ ،‬باید رمز عبور قبلی را وارد کنید‪ .‬در این مرحله بر اساس فایلها و کلیدهای رمزنگاری‪،‬‬
‫فایلهایی ایجاد میشــوند که کالینتها به واســطه آنها‪ ،‬اطالعات خود را رمزنگاری و برای سرور ارسال‬
‫میکنند‪.‬‬
‫در ادامه به مهم‌ترین پارامترهای استفاده از اسکریپت فوق می‌پردازیم‪.‬‬
‫• پارامتــر ‪ : –m client‬بــا ایــن پارامتر مشــخص می‌کنیم که کلید تولید شــده برای کالینت‌ها (نه ســرور‬
‫استریسک) قابل استفاده است‪.‬‬
‫• پارامتر ‪ : –c‬نام فایل ‪ CA‬تولید‌شده به‌وسیله اسکریپت در استریسک را مشخص می‌کند‪.‬‬
‫• پارامتر ‪ : –k‬نام فایل حاوی کلید برای فایل ‪ CA‬را مشخص می‌کند‪.‬‬
‫• پارامتر ‪ : –C‬می‌توانیم آدرس آی‌پی کالینت را به‌وســیله این پارامتر مشخص‌کنیم(این پارامتر اختیاری می‬
‫باشد و در صورت لزوم باید آدرس آی پی کالینت خود را جایگزین نمایید)‪.‬‬
‫• پارامتر ‪ : –O‬برای مشخص کردن نام شرکت استفاده می‌‌شود‪.‬‬
‫• پارامتر ‪ : –d‬آدرس مسیر برای ذخیره کردن فایل‌ها و کلید‌های رمزنگاری است‪.‬‬
‫• پارامتر ‪ : –o‬نام فایل‌ها و کلید‌های جدید به‌وسیله این پارامتر مشخص می‌شود و برای کالینت‌ قابل استفاده‬
‫است‪.‬‬
‫اکنون اگر فایل ‪ certificates‬را مجددا ً بررسی کنیم‪ ،‬محتویات آن به‌صورت زیر خواهد بود‪:‬‬
‫‪# ls /etc/asterisk/certificates/‬‬
‫‪asterisk.crt asterisk.csr asterisk.key asterisk.pem ca.cfg ca.crt ca.key Phone_1.crt‬‬
‫‪Phone_1.csr Phone_1.key Phone_1.pem tmp.cfg‬‬

‫سپس باید یک کاربر جدید در استریسک بهصورت زیر ایجاد کنید‪:‬‬


‫‪;sip.conf‬‬
‫]‪[Phone_1‬‬
‫‪type=friend‬‬
‫‪secret=123123‬‬
‫‪host=dynamic‬‬
‫‪port=5061‬‬
‫‪context=LocalSets‬‬
‫‪dtmfmode=rfc2833‬‬
‫‪disallow=all‬‬
‫‪allow=ulaw,alaw‬‬
‫‪transport=tls‬‬
‫‪qualify=yes‬‬
‫‪encryption=yes‬‬

‫پارامتر مهم برای تعریف این کاربر‪ ،‬مشــخص کردن پروتکل ‪ TLS‬برای ارتباط با ســرور استریسک‪ ،‬پورت‬
‫و اســتفاده از ‪ SRTP‬برای رمز کردن صداست‪ .‬در نظر داشتهباشید که باید فایلهای ‪Phone_1.pem‬‬ ‫‪۵۰۶۱‬‬
‫‪513‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫و ‪ ca.crt‬را در اختیار کالینت قرار دهید‪ .‬با این تنظیمات کاربر ‪ Phone_1‬از طریق پروتکل ‪ tls‬باید به سرور‬
‫استریسک رجیستر شود‪.‬‬

‫برقراری ارتباط امن میان سرورهای استریسک‬


‫فرض کنید بخواهیم بین دو ســرور استریســک ارتباطی بهصورت امن از طریق پروتکل ‪ TLS‬برقرار کنیم‪.‬‬
‫بنابراین باید فایلها و کلیدهای رمزنگاری را برای ســرور دوم هم تولید کنیم‪ .‬برای این منظور ابتدا آنها را‬
‫بهصورت زیر ایجاد کنید‪:‬‬
‫‪#./ast_tls_cert -d /etc/asterisk/certificates/ -C 192.168.1.102 -o serverB -c /etc/asterisk/‬‬
‫‪certificates/ca.crt -k /etc/asterisk/certificates/ca.key‬‬

‫اینجا باید آدرس ســرور دوم استریســک )‪ (192.168.1.102‬را وارد نمایید‪ .‬فایلها و کلیدهای رمزنگاری‬
‫با نام ‪ serverB‬ایجاد خواهند شــد‪ .‬اکنون باید تنظیمات تعریف ترانک را در هر ســرور بهصورت جداگانه‬
‫انجام دهید‪.‬‬
‫نحوهی تنظیمات برای سرور استریسک را قب ً‬
‫ال توضیح دادهایم‪ .‬این تنظیمات بهصورت زیر است‪:‬‬
‫‪;ServerA‬‬
‫‪;sip.conf‬‬
‫‪tlsenable=yes‬‬
‫‪tlsbindaddr=0.0.0.0‬‬
‫‪tlscertfile=/etc/asterisk/certificates/asterisk.pem‬‬
‫‪tlscafile=/etc/asterisk/certificates/ca.crt‬‬
‫‪tlscipher=ALL‬‬
‫‪tlsclientmethod=tlsv1‬‬

‫در ‪ ServerB‬تنظیمات به این صورت است‪:‬‬


‫‪;serverB‬‬
‫‪;sip.conf‬‬
‫‪tlsenable=yes‬‬
‫‪tlsbindaddr=0.0.0.0‬‬
‫‪tlscertfile=/etc/asterisk/certificates/serverB.pem‬‬
‫‪tlscafile=/etc/asterisk/certificates/ca.crt‬‬
‫‪tlscipher=ALL‬‬
‫‪tlsclientmethod=tlsv1‬‬

‫پس از انجام تنظیمات فوق در هر دو ســرور‪ ،‬باید یک ترانک بین دو ســرور ایجاد کنید و نوع پروتکل را‬
‫‪ TLS‬انتخاب نمایید‪ .‬برای مثال در سمت سرور استریسک تنظیمات تعریف ترانک بهصورت زیر است‪:‬‬
‫‪;serverA‬‬
‫‪;sip.conf‬‬
‫]‪[serverB‬‬
‫‪type = peer‬‬
‫‪host = 192.168.1.102‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 514

defaultuser = serverA
secret = apples
context = incoming
disallow = all
allow = ulaw,alaw
transport = tls
canreinvite=no
directmedia=no
deny=0.0.0.0/0.0.0.0
permit=0.0.0.0/0.0.0.0
insecure=invite,port
qualify=yes
encryption=yes

:‫ این تنظیمات بهصورت زیر است‬ServerB ‫در‬


;serverB
;sip.conf
[serverA]
type = peer
host = 192.168.1.101
defaultuser = serverB
secret = apples
context = incoming
disallow = all
allow = ulaw,alaw
transport = tls
canreinvite=no
directmedia=no
deny=0.0.0.0/0.0.0.0
permit=0.0.0.0/0.0.0.0
insecure=invite,port
qualify=yes
encryption=yes

‫ به این منظور در محیط‬.‫ کنیم‬reload ‫ را‬chan_sip ‫ باید ماژول‬،‫پس از انجام تنظیمات فوق برای هر دو سرور‬
:‫کامندالین استریسک دستور زیر را برای هر دو سرور اجرا کنید‬
CLI> sip reload

‫ چنین خطایی در کامندالین استریسک در هر دو سرور‬،‫ کردن ماژول‬reload ‫ ممکن است بعد از‬:‫نکته مهم‬
:‫مشاهده شود‬
[Oct 26 15:07:47] ERROR[1899]: tcptls.c:209 handle_tcptls_connection: Certificate did not
verify: certificate signature failure
[Oct 26 15:04:30] ERROR[2401]: tcptls.c:666 handle_tcptls_connection: Certificate common
name did not match (192.168.1.26)
‫‪515‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫ایــن خطــا زمانــی رخ میدهد که آدرس ســرورها را هنگام تعریف کلید رمزنگاری به درســتی مشــخص‬
‫نکردهباشید‪ .‬برای حل این خطا یا باید دوباره کلیدهای رمزنگاری را بر اساس آدرس سرورها ایجاد کنید و‬
‫یا از طریق فایل ‪ ، sip.conf‬تنظیمات بررسی آی پی سرورها را در هر دو سرور استریسک غیرفعال نمایید‪:‬‬
‫‪;sip.conf‬‬
‫‪tlsdontverifyserver=yes‬‬

‫سپس باید مجددا ً ماژول ‪ chan_sip‬را ‪ reload‬کنید‪ .‬پس از انجام تنظیمات فوق برای هر دو سرور‪ ،‬باید یک‬
‫ارتباط سیگنالینگ از نوع رمز شده ایجاد شدهباشد‪.‬‬
‫اکنون میتوان دربرنامهنویســی استریســک از طریق تنظیم کردن تابع ‪ CHANNEL‬ارتباط رمزشده را‬
‫بهصورت زیر ایجاد کرد‪:‬‬
‫‪;serverA‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => 800,1,Set(CHANNEL(secure_bridge_signaling)=1‬‬
‫)‪same => n,Dial(SIP/1234@serverB‬‬

‫در ســمت دیگر میتوان بررســی کرد که آیا ارتباط تماس ورودی جدید از نوع رمزنگاری شده است یا نه‪.‬‬
‫این کار بهوسیله تابع ‪ CHANNEL‬بهصورت زیر انجام میشود‪:‬‬
‫‪;serverB‬‬
‫‪;extensions.conf‬‬
‫]‪[incoming‬‬
‫)(‪exten => _X.,1,Answer‬‬
‫)‪same => n,GotoIf($["${CHANNEL(secure_signaling)}" = "1"]?secure:insecure‬‬
‫)‪same => n(secure),NoOp(Signaling is encrypted.‬‬
‫)(‪same => n,Hangup‬‬
‫)‪same => n(insecure),NoOp(Signaling is not encrypted.‬‬
‫)(‪same => n,Hangup‬‬

‫تا اینجا سیگنالیگ را در سرور استریسک رمزنگاری کردیم‪ .‬اکنون فرض کنید بخواهیم مدیا )صدا( را هم‬
‫رمزنگاری کنیم‪ .‬ازآنجاکه دادهها از طریق پروتکل ‪ RTP‬در شــبکه جابجا میشوند‪ ،‬در ادامه به آن خواهیم‬
‫پرداخت‪.‬‬

‫امنیت مدیا (‪ )RTP‬در شبکه‌های ویپ‬


‫پــس از انجام مراحل ســیگنالینگ )‪ (Call Setup‬در شــبکههای ویپ‪ ،‬ارتباط ‪ RTP‬میان دو ســرور برقرار‬
‫میشــود و دادههای صوت و تصویر منتقل میشــوند‪ .‬ازآنجاکه دادهها در پروتکل ‪ ،RTP‬رمزنگاریشــده‬
‫نیســت‪ ،‬باید بتوان بهواسطه ســایر پروتکلها‪ ،‬آنها را رمزنگاری کرد‪ .‬برای این منظور از پروتکل ‪ SRTP‬یا‬
‫‪ ZRTP‬استفاده کنید‪.‬‬
‫برای استفاده از پروتکل ‪ SRTP‬ابتدا باید ماژول ‪ res_srtp.so‬را در استریسک فعال کنید‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪516‬‬

‫استفاده از ‪res_srtp.so‬‬
‫با توجه به اینکه ماژول ‪ res_srtp.so‬بهصورت پیشفرض غیرفعال اســت‪ ،‬بنابراین برای اســتفاده از آن ابتدا‬
‫باید آن را فعال کنید‪ .‬به همین منظور ابتدا نیازمندیهای ماژول را نصب وسپس استریسک را مجددا ً کامپایل‬
‫کنید‪:‬‬
‫‪;RHEL‬‬
‫‪yum install libsrtp-devel‬‬

‫‪;Ubuntu‬‬
‫‪apt-get install libsrtp-dev‬‬

‫بعد از نصب باید استریسک را راه‌اندازی کنید‪:‬‬


‫‪#./configure‬‬
‫‪#make menuselect‬‬

‫چنانچه هم اکنون ماژول را بررســی کنید‪ ،‬مشــاهده خواهید کرد که ماژول به درستی نصب شده و بهوسیله‬
‫استریسک قابل شناسایی است )شکل ‪.(4-۱8‬‬

‫شکل ‪4-18‬‬
‫سپس ادامه نصب استریسک را انجام دهید‪:‬‬
‫‪#make‬‬
‫‪#make install‬‬

‫پس از نصب استریسک‪ ،‬به محیط کامندالین استریسک بروید و قسمت نصب ماژول ‪ res_srtp.so‬را بررسی‬
‫کنید‪:‬‬
‫‪CLI> module show like res_srtp.so‬‬
‫‪Module Description Use Count‬‬
‫‪res_srtp.so Secure RTP (SRTP) 0‬‬
‫‪1 modules loaded‬‬
‫‪517‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫از ‪ SRTP‬در استریسک میتوان بهصورت زیر استفاده کرد‪:‬‬


‫]‪[LocalSets‬‬
‫)‪exten => 8001,1,Set(CHANNEL(secure_bridge_signaling)=1‬‬
‫)‪same => n,Set(CHANNEL(secure_bridge_media)=1‬‬
‫)‪same => n,Dial(SIP/1234@serverB‬‬

‫همانطور که مشاهده میکنید‪ ،‬بهوسیله تابع ‪ CHANNEL‬دادههای ‪ RTP‬را میتوان بهصورت رمزنگاریشده‬
‫‪ SRTP‬انتقال داد‪.‬‬
‫در نمونههای قبل‪ ،‬ارتباطات را میان دو »ســرور استریسک« بهصورت رمزنگاری شده انتقال دادیم‪ .‬این‬
‫سرویس میتواند بین »یک سرور استریسک« و »کالینتها« نیز انجام پذیرد‪.‬‬

‫امنیت در پروتکل ‪IAX‬‬

‫بــرای فعال کردن رمزنگاری در پروتکل ‪ ، IAX۲‬مراحل کار به مراتب ســادهتر از دو پروتکل قبلی خواهد‬
‫بود‪ .‬این سرویس با تنظیم پارامترهای زیر در فایل ‪ iax.conf‬فعال میشود‪.‬‬
‫‪iax.canf‬‬
‫]‪[general‬‬
‫‪encryption = yes‬‬
‫‪forceencryption = yes‬‬

‫راهکارهای امنیتی در سیستم تلفنی استریسک‬


‫تا اینجا بهصورت اجمالی انواع رمزنگاری در سیســتم تلفنی استریســک بررســی شد‪ .‬همانطور که پیشتر‬
‫نیز اشــاره شــد‪ ،‬برای برقراری امنیت در شــبکههای ویپ‪ ،‬باید فرآیندهایی صورت گیرد تا شبکه‪ ،‬مطمئن و‬
‫غیرقابلنفوذ شود‪ .‬در ادامه در خصوص برقراری امنیت درسیستم تلفنی استریسک مواردی بیان خواهد شد‪:‬‬
‫‪ -۱‬در سیستم تلفنی استریسک بهتر است از )‪ (non- numeric‬برای استفاده از نامکاربری و رمزعبور استفاده‬
‫شود‪ ،‬بهطوریکه بهراحتی قابل حدسزدن نباشد‪.‬‬
‫‪ -۲‬پارامتر ‪ alwaysauthreject=yes‬را در استریســک تنظیم کنید‪ .‬این پارامتر بهصورت پیش فرض »‪«yes‬‬
‫است‪.‬‬
‫بهتر است با مثالی پارامتر فوق را بررسی کنیم‪:‬‬
‫فــرض کنید پارامتــر ‪ alwaysauthreject=no‬باشــد‪ .‬اکنون اگر بخواهیم با یــک نامکاربری نامعتبر به‬
‫سیستم تلفنی استریسک رجیستر شویم‪ ،‬به دلیل بیاعتباربودن‪ ،‬خروجی زیر را خواهیم داشت‪:‬‬
‫‪CLI>[Aug 22 15:17:15] NOTICE[25690] chan_sip.c: Registration from‬‬
‫‪'"123"<sip:123@127.0.0.1>' failed for '203.86.167.220:5061' - No matching peer found‬‬

‫همانطــور کــه مالحظه میکنید‪ ،‬پیــام » ‪ « No matching peer found‬بیان میکنــد که چنین کاربری در‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪518‬‬

‫سیستم تلفنی تعریف نشده است‪ .‬پس هکر بهراحتی میتواند متوجه این موضوع شود و نوع حملههای خود‬
‫را هوشمندانهتر انجام دهد‪.‬‬
‫شــاید این ســوال مطرح شــود که خروجی در محیط کامندالین استریسک اســت و شخص هکر نمیتواند‬
‫دسترسی به این صفحه مدیریتی داشته باشد‪ ،‬پس چطور متوجه این موضوع خواهد شد؟ در پاسخ باید گفت‬
‫که اگر با وایرشارک‪ 1‬پیامها را بررسی کنیم‪ ،‬خروجی بهصورت زیر خواهد بود )شکل ‪.(۵-۱8‬‬

‫شکل ‪5-18‬‬

‫همانطور که مالحظه میکنید‪ ،‬استریســک پیام » ‪ « SIP 2.0 404 not found‬را ارسال میکند که مشخص‬
‫کننده این است که کاربر در سیستم تلفنی استریسک نامعتبر است‪.‬‬
‫اکنون اگر پارامتر ‪ alwaysauthreject=yes‬باشد‪ ،‬نتیجه دستورات در کامندالین استریسک و وایرشارک‬
‫بهصورت زیر خواهد بود‪:‬‬
‫‪SIP/2.0 401 Unauthorized‬‬
‫‪Via: SIP/2.0/UDP 81.18.114.4:33292;branch=z9hG4bK-d8754z-c7410756b53dfb75-1---‬‬
‫‪d8754z-;received=81.18.114.4;rport=33292‬‬
‫‪From: "221"<sip:221@XXX.XXX.XXX.XXX>;tag=0b6ed73e‬‬
‫‪To: "221"<sip:221@XXX.XXX.XXX.XXX:5060>;tag=as3ca2a3e1‬‬
‫‪Call-ID: ODQyZjQyM2FlZWE1NmUzYWIyZTNmMGE0Nzk0Yjk4YjQ.‬‬
‫‪CSeq: 1 REGISTER‬‬
‫‪User-Agent: Asterisk PBX‬‬
‫‪Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY‬‬
‫‪Supported: replaces‬‬
‫"‪WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="484340d0‬‬
‫‪Content-Length: 0‬‬

‫و یا در وایرشارک این پیام را مشاهده خواهید کرد )شکل ‪.(۶-۱8‬‬


‫همانطــور کــه مالحظــه میکنید‪ ،‬پیام بــه وجود آمده در ایــن بخش‪ ،‬مربوط به چالــش رمز عبور در‬
‫استریســک است و این در حالی است که اص ً‬
‫ال چنین کاربری وجود ندارد‪ .‬با این روش‪ ،‬هکر متوجه نامعتبر‬
‫بودن کاربر نخواهد شد‪.‬‬

‫‪1- wireshark‬‬
‫‪519‬‬ ‫امنیت در سیستم تلفنی استریسک‬

‫شکل ‪6-18‬‬

‫‪ -۳‬حتماًَ از پسوردهای دشوار استفاده کنید‪ .‬نرم افزارهایی هستند که پسوردهای پیچیده تولید میکنند‪.‬‬
‫‪ -4‬اگر از پروتکل ‪ SIP‬اســتفاده میکنید حتما ‪ TLS‬را فعال کنید و اگر از پروتکل ‪ IAX۲‬اســتفاده میکنید‬
‫حتما از ‪ key-base authentication‬استفاده کنید‪.‬‬
‫‪ -۵‬از نرم افزار ‪ fail2ban‬استفاده کنید‪ .‬این نرم افزار ‪ syslog‬استریسک را میخواند و براساس آن ‪firewall‬‬
‫سیستم را ‪ update‬میکند )نصب ‪ fail2ban‬را به خواننده واگذار میکنیم(‪.‬‬
‫‪ -۶‬برای رمزنگاری دادههای ‪ ، RTP‬حتماً از ‪ SRTP‬استفاده کنید و یا اگر از پروتکل ‪ IAX2‬استفاده میکنید‬
‫حتماً پارامترهای ‪ encryption=yes‬و ‪ forceencryption = yes‬را فعال نمایید‪.‬‬
‫‪ -7‬در برنامهنویســی استریسک‪ ،‬سطوح دسترسی را در تعریف کانتکستها رعایت کنید‪ .‬به این صورت که‬
‫امکان دسترسی غیرقانونی برای داخلیهای سیستم و سایر افراد وجود نداشته باشد‪.‬‬
‫‪ -8‬بــرای جلوگیری از حمله » ‪ ، «dialplan injection‬حتما از تابع )(‪ FILTER‬در برنامههای خود اســتفاده‬
‫نمایید‪ .‬نحوه استفاده از این تابع بهصورت زیر خواهد بود‪:‬‬
‫‪CLI> core show function FILTER‬‬
‫]‪[Syntax‬‬
‫)‪FILTER(allowed-chars,string‬‬

‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)})}‪exten => _X.,1,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN‬‬
‫)‪same => n,Dial(IAX2/otherserver/${SAFE_EXTEN},30‬‬

‫‪ -۹‬اگر از ‪ FastAGI‬و یا ‪ AMI‬اســتفاده میکنید‪ ،‬چون دادهها روی شــبکه منتقل میشــوند‪ ،‬حتماً آنها را‬
‫رمزنگاری کنید و یا در شــبکهای امن آنها را انتقال دهید )بهعنوان مثال دسترســی به ‪ FastAGI‬را محدود‬
‫کنید و برای انتقال رویدادها از طریق ‪ AMI‬از پروتکل ‪ TLS‬استفاده کنید(‪.‬‬
‫‪ -۱۰‬در پروتکل ‪ IAX‬پارامترهایی برای کنترل حملههای ‪ DDOS‬وجود دارد‪ ،‬بهتر است آنها را بسته به نیاز‬
‫خود تنظیم کنید‪ .‬این پارامتر در زیر لیست شدهاند‪.‬‬
‫‪• Calltokenoptional‬‬
‫‪• Maxcallnumbers‬‬
‫‪• Maxcallnumber‬‬
‫‪• Nonvalidated‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪520‬‬

‫‪ -۱۱‬حتما پارامترهای ‪ deny‬و ‪ permit‬را در تعریف داخلیها تنظیم کنید )برای راحتی کار و پرهیز از تکرار‬
‫میتوانید از ‪ACL‬ها استفاده کنید(‪ .‬بهعنوان مثال فرض کنید بخواهیم برای داخلیها‪ ،‬یک رول تعریفکنیم‪.‬‬
‫برای تعریف رولها از فایل ‪ acl.conf‬در مسیر زیر استفاده کنید‪.‬‬
‫‪#vim /etc/asterisk/acl.conf‬‬
‫]‪[local_phones‬‬
‫‪deny=0.0.0.0/0.0.0.0‬‬
‫‪permit=192.168.1.0/255.255.255.0‬‬

‫اکنون در تعریف کاربران‪ ،‬نیازی به تعریف پارامترهای ‪ deny‬و ‪ permit‬وجود ندارد‪ .‬به جای آنها‪ ،‬پارامتر‬
‫‪ acl‬را مقدار دهید‪ .‬فرض کنید بخواهیم داخلی ‪ phoneA‬را تعریف کنیم‪:‬‬
‫‪;sip.conf‬‬
‫]‪[phoneA‬‬
‫‪;deny=0.0.0.0/0.0.0.0‬‬
‫‪;permit=192.168.1.0/255.255.255.0‬‬
‫‪acl= local_phones‬‬
‫‪type=friend‬‬

‫‪ -۱۲‬از پارامتــر ‪ call-limit‬بــرای محدودکردن تعداد تماسهای همزمان اســتفاده کنید )این پارامتر هنگام‬
‫تعریف ترانکها مورد اســتفاده قرار میگیرد(‪ .‬الزم به توضیح است که استفاده از این پارامتر در نسخههای‬
‫جدید استریســک کمتر توصیه شده است و بهجای آن اســتفاده از توابع ‪ Group‬و ‪ Group_Count‬پیشنهاد‬
‫میشــود‪ .‬در فصل بیستم )آشنایی با دستورات و توابع پرکاربرد استریسک( با این توابع آشنایی بیشتری پیدا‬
‫خواهید کرد‪.‬‬
‫‪;sip.conf‬‬
‫]‪[SIPTrunklimit‬‬
‫‪type=friend‬‬
‫‪host=server2_IP_add‬‬
‫‪call-limit=1‬‬
‫‪context=from-Trunk‬‬

‫‪ -۱۳‬دسترسی به محیط کامندالین استریسک برای همگان فعال نباشد و فقط در اختیار مدیر سیستم باشد‪.‬‬

‫نتیجه‌گیری‬
‫از مهمترین ســرفصلهای امنیت‪ ،‬امنیت تجهیزات مخابراتی و شبکههای ویپ است‪ .‬عدم رعایت مالحظات‬
‫امنیتی در این نوع شــبکهها‪ ،‬میتواند خســارات جبرانناپذیری بهوجود آورد‪ .‬ازآنجاکه نفوذ به یک شــبکه‬
‫ویــپ به منزله دسترســی کامل به شــبکه و ایجاد تماسهــای بدون محدودیت اســت‪ ،‬از جنبههای مختلف‬
‫اقتصادی‪ ،‬سیاسی و امنیتی میتواند آسیبهای جدی به شبکه وارد شود‪ .‬متأسفانه امروزه به دلیل عدم رعایت‬
‫مالحظات امنیتی در سافتسوئیچهای نرمافزاری‪ ،‬شاهد هزینههای هنگفت در قبوض مشتریان هستیم‪ .‬در این‬
‫فصل سعی کردیم مهمترین مالحظات امنیتی در خصوص سافتسوئیچ استریسک را مطرح کنیم‪.‬‬
‫فصل نوزدهم‬
‫ازریابیعملکردسیستم‌هایتلفنی‬
‫‪ IPPBX‬و تجهیزات وابسته‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪522‬‬

‫مقدمه‬
‫انتقــال صــدا ازطریق اینترنت یا فنــاوری ویپ نه تنها باعث بهوجود آمدن نســلی جدیــد در زمینه برقراری‬
‫ارتباطات با هزینههای کمتر شده بلکه به یک ابزار ضروری و سودمند برای بسیاری از بازارهای تجاری دنیا‬
‫و کمپانیهای تولید کننده تجهیزات ویپ‪ ،‬تبدیل شدهاست‪.‬‬
‫یکی از دالیل اصلی توســعه و رشــد ســریع شــبکههای ویپ‪ ،‬کاهش هزینههای مکالمات تلفنی است‪.‬‬
‫ویژگیهایی مانند قابل حمل بودن‪ ،‬دســترسپذیری و همگرایی این شــبکهها‪ ،‬از مهمترین دالیلی است که‬
‫شــبکههای ویپ را بســیار جذاب و ســودمند کرده اســت‪ .‬پروتکلهای ‪ SIP، IAX‬و ‪ H.323‬از مهمترین‬
‫پروتکلهایی هســتند که در شــبکه های ویپ استفاده میشوند‪ .‬همچنین با گســترش استفاده از آی پی در‬
‫شبکههای مخابراتی و افزایش قابلیت این شبکهها در پشتیبانی از تماسهای چندرسانهای‪ ،‬استفاده از پروتکل‬
‫‪ SIP‬نیز رواج بیشتری یافته اســت و به دلیل سادگی و پتانســیلی که دارد‪ ،‬برای توسعهی پهناور‪ ،‬قابل قبول‬
‫اســت‪ SIP .‬پروتکل الیهکاربرد اســت که برای نگهداری و به پایان رساندن جلسههای چندرسانهای استفاده‬
‫میشود‪ .‬از همین رو اکثر کمپانیها برای تولید تجهیزات خود از این پروتکل پشتیبانی میکنند‪.‬‬
‫کیفیت سرویس در تجهیزات ویپ از دیگر مسائلی است که از اهمیت ویژهای برخوردار است‪ .‬از یک‬
‫طرف چون ویپ از بســتر آی پی برای برقراری یک نشســت ارتباطی اســتفاده میکند‪ ،‬هیچ گونه تضمینی‬
‫در خصــوص کیفیت ســرویس ارائه نمیدهد و از طــرف دیگر اگر تجهیزات ویپ از اســتانداردهای الزم‬
‫برخوردار نباشند‪ ،‬کارایی و کیفیت سرویس را کاهش میدهند‪ .‬بنابراین‪ ،‬استفاده از محصوالت و تجهیزات‬
‫ویپ که دارای استانداردهای الزم باشند از اهمیت ویژهای برخوردار است‪.‬‬
‫‪523‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫اکنون این ســؤال مطرح میشود که چگونه میتوان کیفیت ســرویس تجهیزات در شبکه های ویپ را‬
‫بررسی کرد؟ و یا اینکه چگونه میتوان مطمئنشد تجهیزات دارای استانداردهای الزم هستند؟‬

‫طرح سؤاالت کلیدی هنگام استفاده از سیستم‌های تلفنی ‪IPPBX‬‬


‫ازآنجاکه در پروتکل آی پی کیفیت سرویس تضمین شده نیست‪ ،‬سؤاالت زیر باید پرسیده شوند‪:‬‬
‫• چگونه میتوان کیفیت سرویس را در شبکههای ویپ مبتنی بر آی پی بررسی کرد؟‬
‫• تجهیزات ویپ چگونه میتوانند کیفیت سرویس مطلوب را برای ما فراهم آورند؟‬
‫• با داشتن چه اطالعاتی میتوان کیفیت تجهیزات ویپ را اندازهگیری کرد؟‬
‫• چه معیارهایی برای سنجش کیفیت سرویس در تجهیزات ویپ ضروری هستند؟‬
‫• چگونه میتوان پارامترهای بررسی کیفیت سرویس تجهیزات را اندازهگیری کرد؟‬
‫• برای بررسی کیفیت سرویس شبکههای ویپ آیا سنجش کیفیت شبکه ‪ IP‬مدنظر است یا سنجش کیفیت‬
‫تجهیزات شبکه؟‬
‫• با فرض داشتن یک شبکه با پهنای باند تضمین شده‪ ،‬چگونه میتوان کیفیت سرویسهای ارائه شده در‬
‫یک سوئیچ را ارزیابی کرد؟‬
‫• چگونه میتوان تأخیر در صدا را تشخیص داد و اندازهگیری کرد؟‬
‫• چگونه میتوان تغییرات تأخیر را اندازهگیری کرد؟‬
‫• چگونه میتوان درصد از بین رفتن بستهها را مشخص کرد؟‬
‫• تغییرات کدک چه تأثیری در ارائه کیفیت سرویس خواهد داشت؟‬
‫• چگونه میتوان ظرفیت اسمی و علمی سوئیچها را تشخیص داد و آنها را از هم تفکیک کرد؟‬
‫• ضریب نفوذ به سوئیچ چه رابطهای با کیفیت سرویس در سوئیچ دارد؟ یعنی درحالتیکه سوئیچ ترافیک‬
‫کمتری پردازش میکند در مقایسه با حالتی که ترافیک بیشتری در کنترل دارد‪ ،‬آیا دارای یک کیفیت‬
‫سرویس است؟‬
‫• آیا برای تســت تجهیزات ویپ‪ ،‬سختافزارهایی مورد نیاز است؟ و آیا این سختافزارها به راحتی قابل‬
‫دسترساند؟‬
‫• ازآنجاکــه در شــبکههای ویــپ پروتکلهای متفاوتی وجــود دارند‪ ،‬آیا میتوان شــبکههای ویپ را با‬
‫پروتکلهای متفاوت‪ ،‬تست و بررسی کرد؟‬
‫• آیا میتوان این تجهیزات تست را به شبکههای مخابراتی امروزی )‪ (PSTN‬تعمیم داد؟‬
‫• آیا نوع تســت برای تجهیــزات متفاوت مثل ‪ SIPServer, SIPProxy, IPPhone, SBC‬و غیره یکســان‬
‫هستند یا سناریوهای متفاوتی دارند؟‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪524‬‬

‫• تســت انطباق با تســت کارکرد و کارایی چه تفاوتی دارد و هر یک برای کدامیک از تجهیزات انجام‬
‫خواهد شد؟‬
‫• مدت زمان تعریف شده برای تست تجهیزات چگونه تعریف میشود؟‬
‫• توزیع ارالنگ‪ ۱‬برای یک سوئیچ تلفنی چگونه تعریف میشود؟ آیا برای تست کارکرد و کارایی‪ ،‬این‬
‫توزیع الزم است؟‬
‫پرواضح اســت که این‌گونه ســؤاالت و صد‌ها سؤال دیگر مستلزم داشــتن یک بستر مطمئن و امن برای‬
‫برآوردن نیاز‌های اولیه و سنجش دقیق سوئیچ‌های تلفنی تحت شبکه خواهد بود‪.‬‬

‫اهداف اصلی سواالت و ارائه راه حل‌های مناسب‬


‫با توجه به ســؤاالت مطرح شــده در قسمت قبل‪ ،‬این پرســش پیش می‌آید که چگونه این امکان وجود دارد‬
‫چنین شــبکه‌ای را بتوان مورد ســنجش قرار داد‪ .‬آنچه در ظاهر امر پیداست‪ ،‬پیاده‌سازی (نه شبیه‌سازی) چنین‬
‫سیستمی بسیار پر‌حاشیه و پر چالش خواهد بود‪ ،‬به این دلیل که باید بتوانیم سوئیچ‌ها را از دو نقطه نظر تست‬
‫کنیم‪:‬‬
‫‪ -1‬اول اینکه بتوان با توجه به ظرفیت ســوئیچ‪ ،‬مقدار زیادی ترافیک تماس به آن وارد کرد و منابع مصرفی‬
‫را تحلیل و آنالیز نمود‪.‬‬
‫‪ -2‬دوم باید در شرایط متفاوت‪ ،‬کیفیت سرویس تماس‌های جاری را بررسی و ارزیابی کرد‪.‬‬
‫هدف از طرح این سواالت‪ ،‬طراحی سیستم کنترلی و آنالیز سوئیچ‌های تلفنی مبتنی بر شبکه است تا بتوان‬
‫آن‌ها را از جنبه کام ً‬
‫ال متفاوت بررسی و تحلیل کرد‪:‬‬
‫ • ایجاد تماس مبتنی بر ظرفیت تعریف شده سوئیچ و بررسی منابع مصرف شده و آزاد‪.‬‬
‫ • بررسی کیفیت سرویس در تماس‌ها و تحلیل پارامتر‌های کیفیت سرویس‪.‬‬
‫ • به‌دست آوردن ضریب افزایش تماس‌ها بر کیفیت سرویس ارائه شده‪.‬‬

‫بررسی آزمایشگاه‌های سیستم‌های تلفنی ‪ IPPBX‬در ایران‬


‫امروزه در ایران‪ ،‬بســتر مخابرات همچنان از ‪ PSTN‬اســتفاده میکند‪ .‬در سالهای اخیر‪ ،‬فعالیتهای بزرگ‬
‫و ارزنــدهای در زمینــه معرفی و اســتفاده از تکنولوژی ویپ صورت گرفته اســت‪ .‬از یک طرف راهاندازی‬
‫شــبکههای ‪ NGN/IMS‬در چند اســتان و صدور مجوز فعالیت از سوی ســازمان تنظیم مقررات و از سویی‬

‫‪ -1‬توزیع ارالنگ‪ :‬این توزیع از انواع توزیع‌های احتمال پیوسته است که مدت زمان الزم برای وقوع ‪ n‬رویداد کام ً‬
‫ال تصادفی را‬
‫نشان می‌دهد‪ .‬این توزیع بیشتر در مباحث تئوری صف‪ ،‬ترافیک (مکالمات تلفنی)‪ ،‬تعداد تماس‌های همزمان به یک مرکز سوئیچ‬
‫مخابرات استفاده می‌شود‪.‬‬
‫‪525‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫دیگر تغییر مجوز ‪ PAP‬به ‪ FCP‬همگی نزدیکشدن به یک تحول و انقالب در زمینه مخابرات و سیستمهای‬
‫تلفنی را نوید میدهند‪.‬‬
‫در همین راستا‪ ،‬تحقیق و پژوهش در این عرصه نیز سرعت بیشتری به خود گرفته و وجود آزمایشگاههای‬
‫مجهز به تجهیزات تســت و آزمایش‪ ،‬امری بدیهی به حســاب میآید‪ .‬سازمان تنظیم مقررات که مجری اول‬
‫و قانونگذار در این عرصه اســت‪ ،‬مراکزی تحقیقاتی در بدنه خود دارد که هرکدام در حوزهای تخصصی‬
‫در این زمینه فعالیت میکنند‪.‬‬
‫آزمایشــگاه تســت تجهیزات ‪ IPPBX‬دانشگاه فردوسی مشهد یکی از آزمایشــگاههای معتبر در کشور‬
‫است که با مجوز سازمان تنظیم مقررات و ارتباطات کشور‪ ،‬در این راستا تحقیقات و فعالیت میکند‪ .‬مسلماً‬
‫چنین آزمایشگاههایی مجهز به تجهیزات پیشرفته و البته گران قیمت خواهد بود‪ .‬برای مثال آزمایشگاه تست‬
‫تجهیزات ‪ IPPBX‬دانشــگاه فردوســی مشــهد از تجهیزات ‪ Spirent‬برای تست سیســتمهای تلفنی ‪IPPBX‬‬
‫استفاده میکند‪.‬‬
‫در این فصل قصد داریم به بررسی و ارزیابی عملکرد سیستمهای تلفنی ‪ IPPBX‬و تست تجهیزات ویپ‬
‫بپردازیم‪ .‬یکی از عوامل مؤثر در بررسی و ارزیابی عملکرد شبکههای تلفنی و تجهیزات ویپ این است که‬
‫بتوان یک شبکه ویپ را بهصورت یک »مدل« معرفی کرد‪.‬‬

‫مدل سازی چیست؟‬


‫امروزه میتوان اکثر مســائل و پدیدهها را بهصورت مدل )به زبان ریاضی( تعریف و ســپس نتایج را ارزیابی‬
‫کرد‪ .‬بهعنوان مثال اگر بخواهیم یک سیســتم تلفنی را ارزیابی و عملکرد آن را بررســی نماییم‪ ،‬میتوانیم با‬
‫مدلکردن آن سیستم و تعریف پارامترهای وضعیت‪ ،‬سیستم را ارزیابی کنیم‪.‬‬

‫انواع روش‌های ارزیابی یک سیستم تلفنی‬


‫برای ارزیابی یک سیستم تلفنی روشهای متفاوتی وجود دارد‪:‬‬
‫• اندازه‌گیری‪ :‬در این حالت‪ ،‬سیستم تلفنی از قبل طراحی شده و در حال استفاده است‪ .‬در این روش باید‬
‫سیستم را بتوان مورد آزمایش قرار داد و ارزیابی کرد‪.‬‬
‫• شبیه‌سازی‪ :‬در این حالت‪ ،‬سیستم تلفنی به معنای واقعی وجود ندارد‪ ،‬بلکه باید آن را به‌وسیله ابزار‌هایی در‬
‫ابعاد کوچکتر‪ ،‬شبیه‌سازی و سپس ارزیابی کرد‪.‬‬
‫• مدل‌ســازی‪ :‬در این روش باید سیســتم تلفنی را با روش‌های ریاضی مدل‌سازی کرد و سپس پارامتر‌های‬
‫وضعیت سیستم را ارزیابی نمود‪ .‬در این روش از مدل‌های صف‌بندی و روش‌های کنترل خطی در حل مسائل‬
‫ریاضی استفاده می‌شود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪526‬‬

‫برای مثال میخواهیم در یک سیســتم تلفنی طراحی شــده‪ ،‬حداکثر تعداد تماس قابل پذیرش بهوســیله‬
‫سیســتم را اندازهگیری کنیم‪ .‬آنچه بهعنوان هدف در طراحی‪ ،‬مطرح میشود حداکثر تعداد تماسهای قابل‬
‫پذیرش است که باید آن را بهصورت مدل بیان کنیم‪.‬‬
‫‪Goal: Max Call‬‬
‫∀‬ ‫‪all states is normal conditions‬‬

‫در تعریف مدل باال‪ ،‬هدف طراحی سیستم را بهصورت مدل ریاضی بیان کردهایم‪.‬‬

‫«حداکثر تعداد تماس در شرایطی که همه پارامتر‌های وضعیت در سیستم در حالت نرمال باشند‪».‬‬

‫بررسی وضعیت یک سیستم‬


‫معموالً در هر سیســتم‪ ،‬پارامترهایی تعریف میشوند که در اصطالح به آنها »‪ «state‬میگویند‪ .‬معموالً این‬
‫پارامترها بهصورت یک ســری متغیر و بهصورت قابل شــمارش تعریف میشوند‪ .‬در تشخیص وضعیت یک‬
‫ِ‬
‫تعریف متغیرها‪،‬‬ ‫سیســتم‪ ،‬باید این متغیرها را بررسی و مورد ارزیابی قرار داد‪ .‬در اصطالح علمی‪ ،‬به این نوع‬
‫رویدادهای گسسته‪ ۱‬میگویند‪.‬‬
‫علت گسستهبودن رویدادها این است که هیچ وابستگی بین رویدادها وجود ندارد‪ .‬برای مثال فرض کنید‬
‫وضعیت ‪ ،RAM‬وضعیت ‪ ، CPU‬وضعیت تعداد کانالهای فعال و کیفیت ســرویس صدا )‪ (MOS‬هر کدام‬
‫یک وضعیت )‪ (State‬را نشان میدهد‪.‬‬
‫بهعنوان مثال فرض کنید بخواهیم تعداد اپراتورهای موجود در یک صف را بهصورت ‪Discrete Event‬‬
‫بیان کنیم‪ .‬در این صورت داریم‪:‬‬
‫ • در صورت اضافه‌شدن اپراتور به صف‪ state ،‬آن تغییر خواهد کرد‪.‬‬
‫‪N  N+1‬‬
‫ • اگر اپراتوری از صف خارج شود‪ state ،‬متغیر‪ ،‬تغییر خواهد کرد‪.‬‬
‫‪N  N-1‬‬
‫همان‌طور که مالحظه می‌کنید می‌توان با مدل‌کردن یک سیســتم‪ ،‬وضعیت آن را بصورت‌ لحظه‌ای بررســی‬
‫نمود‪.‬‬

‫بررسی دو دیدگاه متفاوت از مدل‌سازی‬


‫برای مدل‌سازی دو دیدگاه متفاوت وجود دارد‪:‬‬
‫الف) از نگاه کاربران سیستم‪:‬‬
‫در این مدل‌سازی‪ ،‬بیشتر کیفیت صدا (سرویس ارائه‌ شده) و دردسترس‌بودن سرویس‌ها مدنظر است‪.‬‬
‫‪3‬‬ ‫‪2‬‬

‫‪1- Discrete Event‬‬


‫)‪2- Quality of Service (QoS‬‬
‫‪3- Availability‬‬
‫‪527‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫ب)‌ از نگاه مدیران سیستم‪:‬‬


‫در این مدل‌سازی‪ ،‬استفاده بهینه از سیستم و کاهش نرخ خرابی و افزایش درآمد سیستم‪ ،‬مدنظر است‪.‬‬

‫مراحل مدل‌سازی یک سیستم‬


‫هنگام مدل‌سازی یک سیستم‪ ،‬معموالً باید مراحلی را به‌صورت زیر انجام دهید‪:‬‬
‫‪ )1‬تعریف اهداف مدل؛‬
‫‪ )2‬ملزومات پروژه (طرح پروژه باید بسیار نزدیک به سیستم واقعی باشد)؛‬
‫‪ )3‬درنظر گرفتن کاربران در مدل‌سازی؛‬
‫‪ )4‬ابزار‌های شبیه‌سازی ؛‬
‫‪ )5‬جمع‌آوری اطالعات اولیه؛‬
‫‪ )6‬مستند‌سازی ایده‌ها ؛‬
‫‌‪ )7‬تست‪ ،‬بررسی نتایج و ارزیابی آن‌ها‪.‬‬

‫ابزار‌های شبیه‌سازی‬
‫واضح اســت که استفاده از ابزار‌های مناسب برای شبیه‌سازی یک سیســتم‪ ،‬می‌تواند در طراحی یک سیستم‬
‫کمک شایانی‌ کند‪.‬‬
‫ابزارهای شبیه‌سازی به سه دسته تقسیم می‌شوند‪:‬‬
‫‪ -1‬استفاده از نرم‌افزار‌های برنامه‌نویسی چند منظوره‪ ،‬از قبیل ‪ C , C++ , java‬و ‪. ...‬‬
‫‪. GPSS , SIM Script II.5‬‬ ‫‪ -2‬استفاده از زبان‌های برنامه‌نویسی شبیه‌سازی‪ ،‬از قبیل‬
‫‪ -3‬استفاده از ابزار‌های شبیه‌سازی‪ ،‬از قبیل ‪. ns2, opnet, network II.5‬‬
‫در این فصل عمدتا با ابزارهای تست سیستمهای تلفنی ‪ IPPBX‬آشنا میشوید‪ .‬الزمه ایجاد چنین تستهایی‪،‬‬
‫شــناخت کافی از سیستمهای تلفنی و پروتکلهای وابسته اســت‪ .‬برای مثال فرض کنید بخواهیم یک تست‬
‫انطباق )بررســی سیگنالیگ ‪ SIP‬روی تجهیزات( را طراحی کنیم‪ .‬مسلماً بدون شناختن پروتکل سیگنالینگ‬
‫‪ ،SIP‬نمیتوانیم این سناریوهای تست را طراحی کنیم‪.‬‬
‫برای مثال فرض کنید یک سیستم تلفنی ‪ IPPBX‬در اختیار دارید و میخواهید آن را تست کنید‪ .‬تست‬
‫شما در دو حالت قابل تعریف است‪:‬‬
‫• تســت کارآمدی‪ 1‬سیستم‪ :‬در این حالت‪ ،‬سیســتم تلفنی را بر اســاس نیاز‌های موجود (شبیه‌سازی محیط‬
‫استفاده کننده) تست و نتایج را بررسی می‌کنید‪.‬‬
‫‪1- Performance‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪528‬‬

‫• تست انطباق‪ 1‬سیســتم‪ :‬در این حالت‪ ،‬عملکرد سیستم را بر اســاس متابعــت از پروتکل مورد نظر بررسی‬
‫می‌کنید‪ .‬برای مثال تست عملکرد صحیح سیستم برای پروتکل ‪ SIP‬به منزله این است که پیام‌های سیگنالینگ‬
‫پروتکل ‪ SIP‬برای سیستم ارسال می‌شود و انتظار می‌رود که سیستم تلفنی پاسخ‌های مناسبی بدهد‪.‬‬
‫ابزارهای زیادی برای شبیهسازی سناریوها وجود دارد‪ .‬در این کتاب از ابزار ‪ SIPP‬استفاده خواهیم کرد‪.‬‬
‫ولی پیش از آن باید با پیامهای سیگنالینگ پروتکل ‪ SIP‬آشنا شوید‪.‬‬

‫انواع پیام‌ها در پروتکل ‪SIP‬‬

‫پروتکل ‪ SIP‬یک پروتکل مبتنی بر ایجاد نشســت در شــبکههای ویپ است که بهوسیله ‪ 2 IETF‬بهصورت‬
‫یک استاندارد در ‪ RFC3261‬درآمده است‪ .‬در این پروتکل آدرس کاربران در شبکه بهصورت زیر تعریف‬
‫میشود‪.‬‬
‫‪• User1@SipDomainA.com‬‬
‫‪• 552548@SipDomainB.com‬‬
‫‪• 5131770@SipDomainC.com‬‬
‫در این پروتکل‪ ،‬هر کاربر شبکه میتواند پیامهایی را ارسال و دریافت کند‪ .‬مهمترین پیامها در جدول ‪۱-۱۹‬‬
‫لیست شدهاند‪.‬‬

‫‪Message‬‬ ‫‪Description‬‬ ‫‪RFC‬‬


‫‪ACK‬‬ ‫‪Acknowledge an INVITE‬‬ ‫‪RFC3261‬‬
‫‪BYE‬‬ ‫‪Terminate an existing session‬‬ ‫‪RFC3261‬‬
‫‪CANCEL‬‬ ‫‪Cancel a pending registration‬‬ ‫‪RFC3261‬‬
‫‪INFO‬‬ ‫‪Mid-call signaling information‬‬ ‫‪RFC2976‬‬
‫‪INVITE‬‬ ‫‪Session establishment‬‬ ‫‪RFC3261‬‬
‫‪MESSAGE‬‬ ‫‪Instant message transport‬‬ ‫‪RFC3428‬‬
‫‪NOTIFY‬‬ ‫‪Send information after subscribe‬‬ ‫‪RFC3265‬‬
‫‪PUBLISH‬‬ ‫‪Upload status information to the server‬‬ ‫‪RFC3903‬‬
‫‪REGISTER‬‬ ‫‪Register the user and update the location lable‬‬ ‫‪RFC3261‬‬
‫‪SUBSCRIBE‬‬ ‫‪Establish a session to recieve future update‬‬ ‫‪RFC3265‬‬
‫جدول ‪1-19‬‬

‫پیام ‪ :ACK‬این پیام به منزله تأیید برقراری نشســت بین دو کاربر اســت‪ .‬زمانی که کاربری تماس را پاســخ‬
‫می‌‌دهد‪ ،‬بعد از ارســال پیام ‪ 200OK‬باید منتظر پیام ‪ ACK‬باشــد‪ .‬اگر این پیام دریافت نشود‪ ،‬تماس بعد از‬

‫‪1- Conformance‬‬
‫‪2- Internet Engineering Task Force‬‬
‫‪529‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫چند ثانیه قطع خواهد شد‪.‬‬


‫پیام ‪ :BYE‬این پیام برای اتمام تماس و قطع آن است‪.‬‬
‫پیام ‪ :CANCEL‬این پیام برای کنسل کردن عملیات رجیستر شدن است‪.‬‬
‫پیام ‪ :INFO‬از این پیام برای ارســال ‪ DTMF‬که از آن به‌عنوان ‪ Mid-Call Signaling‬یاد می‌شــود‪ ،‬استفاده‬
‫می‌گردد‪.‬‬
‫پیام ‪ :INVITE‬برای ایجاد یک نشست و آغاز عملیات ایجاد تماس‪ ،‬از این پیام استفاده می‌شود‪.‬‬
‫پیام ‪ : MESSAGE‬از این پیام برای ارسال متن در شبکه‌های ویپ استفاده می‌شود‪.‬‬
‫پیام ‪ :NOTIFY‬از این پیام برای ارسال اطالعات وضعیت استفاده می‌شود‪.‬‬
‫پیام ‪ : PUBLISH‬از این پیام برای ارسال اطالعات وضعیت در سرور استفاده می‌شود‪.‬‬
‫پیام ‪ :REGISTER‬از این پیام برای آغاز عملیات رجیســتر شــدن در یک سرور ‪ SIP-REGISTER‬استفاده‬
‫می‌شود‪.‬‬
‫پیام ‪ :SUBSCRIBE‬از این پیام برای درخواست دریافت اطالعات وضعیت استفاده می‌شود‪.‬‬

‫سناریوهای مهم شبکه‌های ویپ‬


‫مهمترین سناریوها در شبکه‌‌های ویپ‪ ،‬به‌صورت زیر است‪:‬‬
‫سناریو ‪ :Registraion‬مراحل انجام این سناریو به‌صورت زیر است‪:‬‬

‫شکل ‪1-19‬‬

‫همانطورکه مالحظه میکنید‪ ،‬ابتدا یک پیام ‪ REGISTER‬از طرف کاربر برای استریســک ارسال میشود‪.‬‬
‫استریســک با به چالش کشــیدن کاربر‪ ،‬از او درخواســت اطالعات امنیتی )نام کاربری و رمزعبور( میکند‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 530

‫ اگر‬.‫ را به همراه اطالعات نام کاربری و رمزعبور ارســال کند‬REGISTER ‫ســپس کاربر باید دوباره پیــام‬
‫ با‬Registration ‫ از طرف استریســک ارسال خواهد شــد و عملیات‬200OK ‫ پیام‬،‫اطالعات درســت باشــد‬
.‫ در زیر لیست این پیامها به ترتیب شکل نمایش داده میشود‬.‫موفقیت انجام میشود‬
REGISTER sip:192.168.141.128:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-2a10d04cd243b01e-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: "100"<sip:100@192.168.141.128:5060>
From: "100"<sip:100@192.168.141.128:5060>;tag=257afb7c
Call-ID: OGZhNWM4OWY2MjkxZjA3Nzc1NjdhYmEyZTk4NDViMWU.
CSeq: 1 REGISTER
Expires: 120
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO,
MESSAGE
Supported: replaces
User-Agent: 3CXPhone 6.0.20943.0
Content-Length: 0

SIP/2.0 401 Unauthorized


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-2a10d04cd243b01e-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=257afb7c
To: "100"<sip:100@192.168.141.128:5060>;tag=as5a1ea03c
Call-ID: OGZhNWM4OWY2MjkxZjA3Nzc1NjdhYmEyZTk4NDViMWU.
CSeq: 1 REGISTER
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="7bfa9049"
Content-Length: 0

REGISTER sip:192.168.141.128:5060 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-b517fd12c8731669-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: "100"<sip:100@192.168.141.128:5060>
From: "100"<sip:100@192.168.141.128:5060>;tag=257afb7c
Call-ID: OGZhNWM4OWY2MjkxZjA3Nzc1NjdhYmEyZTk4NDViMWU.
CSeq: 2 REGISTER
Expires: 120
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO,
531 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

MESSAGE
Supported: replaces
User-Agent: 3CXPhone 6.0.20943.0
Authorization: Digest username="100",realm="asterisk",nonce="7bfa9049",uri="sip:192.168.
141.128:5060",response="bf4f7fdc6c060e0c8818886d7a6e0509",algorithm=MD5
Content-Length: 0

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-b517fd12c8731669-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=257afb7c
To: "100"<sip:100@192.168.141.128:5060>;tag=as5a1ea03c
Call-ID: OGZhNWM4OWY2MjkxZjA3Nzc1NjdhYmEyZTk4NDViMWU.
CSeq: 2 REGISTER
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
Expires: 120
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>;expires=120
Date: Tue, 13 Sep 2016 04:32:10 GMT
Content-Length: 0

.‫ مراحل انجام این سناریو به‌صورت زیر است‬:Invite ‫سناریوی‬


2-19 ‫شکل‬

‫ کاربر یک درخواست جدید برای ایجاد تماس )پیام‬،‫ هنگام شروع یک تماس‬،‫همانطورکه مالحظه میکنید‬
‫ از او درخواست اطالعات‬،‫ استریسک با به چالش کشیدن کاربر‬.‫( برای استریسک ارسال میکند‬INVITE
‫ به استریسک این موضوع را تایید‬ACK ‫ کاربر با ارسال پیام‬،‫احراز هویت )نام کاربری و رمز عبور( می کند‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 532

‫( به همراه اطالعات‬INVITE ‫می کند و مجددا اقدام به ارســال درخواســت جدید برای ایجاد تماس )پیــام‬
‫ به طرف استریسک‬100Trying ‫پیام‬،‫اگر اطالعات درســت باشــد‬،‫هویتی)نام کاربری و رمز عبور( می کند‬
‫ نمایش داده شده است )فیلدهای مهم در پیام‬،‫ در زیر فهرســت این پیامها بهترتیب شکل‬.‫ارســال خواهدشد‬
.(‫ شده نمایش داده شده است‬Bold ‫بصورت‬

INVITE sip:101@192.168.141.128:5060 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-5f6e0c486621f707-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: <sip:101@192.168.141.128:5060>
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO,
MESSAGE
Content-Type: application/sdp
Supported: replaces
User-Agent: 3CXPhone 6.0.20943.0
Content-Length: 407

v=0
o=3cxVCE 28455225 295798545 IN IP4 192.168.141.1
s=3cxVCE Audio Call
c=IN IP4 192.168.141.1
t=0 0
m=audio 40024 RTP/AVP 0 8 3 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 GSM/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ptime:20
a=sendrecv
m=video 40022 RTP/AVP 34
c=IN IP4 192.168.141.1
a=rtpmap:34 H263/90000
a=fmtp:34 QCIF=1;CIF=1;SQCIF=1;CIF4=1;
a=sendrecv

SIP/2.0 401 Unauthorized


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-5f6e0c486621f707-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
To: <sip:101@192.168.141.128:5060>;tag=as6b11c514
533 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 1 INVITE
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="7cf5b422"
Content-Length: 0

ACK sip:101@192.168.141.128:5060 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-5f6e0c486621f707-1---
d8754z-;rport
Max-Forwards: 70
To: <sip:101@192.168.141.128:5060>;tag=as6b11c514
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 1 ACK
Content-Length: 0

INVITE sip:101@192.168.141.128:5060 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-dc159e3e28332601-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: <sip:101@192.168.141.128:5060>
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 2 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO,
MESSAGE
Content-Type: application/sdp
Supported: replaces
User-Agent: 3CXPhone 6.0.20943.0
Authorization: Digest username="100",realm="asterisk",nonce="7cf5b422",uri="sip:101@19
2.168.141.128:5060",response="1a2a7453e3be93a353e25dcfeb1c90db",algorithm=MD5
Content-Length: 407

v=0
o=3cxVCE 28455225 295798545 IN IP4 192.168.141.1
s=3cxVCE Audio Call
c=IN IP4 192.168.141.1
t=0 0
m=audio 40024 RTP/AVP 0 8 3 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 GSM/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ptime:20
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 534

a=sendrecv
m=video 40022 RTP/AVP 34
c=IN IP4 192.168.141.1
a=rtpmap:34 H263/90000
a=fmtp:34 QCIF=1;CIF=1;SQCIF=1;CIF4=1;
a=sendrecv

SIP/2.0 100 Trying


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-dc159e3e28332601-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
To: <sip:101@192.168.141.128:5060>
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 2 INVITE
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
Contact: <sip:101@192.168.141.128:5060>
Content-Length: 0

SIP/2.0 180 Ringing


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-dc159e3e28332601-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
To: <sip:101@192.168.141.128:5060>;tag=as557be705
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 2 INVITE
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
Contact: <sip:101@192.168.141.128:5060>
Content-Length: 0

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-dc159e3e28332601-1---
d8754z-;received=192.168.141.1;rport=61668
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
To: <sip:101@192.168.141.128:5060>;tag=as557be705
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 2 INVITE
Server: Asterisk PBX 13.10.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH,
MESSAGE
Supported: replaces, timer
Contact: <sip:101@192.168.141.128:5060>
Content-Type: application/sdp
Content-Length: 292
535 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

v=0
o=root 1403396204 1403396204 IN IP4 192.168.141.128
s=Asterisk PBX 13.10.0
c=IN IP4 192.168.141.128
t=0 0
m=audio 13418 RTP/AVP 0 8 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=maxptime:150
a=sendrecv
m=video 0 RTP/AVP 34

ACK sip:101@192.168.141.128:5060 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.1:61668;branch=z9hG4bK-d8754z-4a2aa53bfb5dae72-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: <sip:101@192.168.141.128:5060>;tag=as557be705
From: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 2 ACK
User-Agent: 3CXPhone 6.0.20943.0
Authorization: Digest username="100",realm="asterisk",nonce="7cf5b422",uri="sip:101@19
2.168.141.128:5060",response="1a2a7453e3be93a353e25dcfeb1c90db",algorithm=MD5
Content-Length: 0

BYE sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484 SIP/2.0


Via: SIP/2.0/UDP 192.168.141.128:5060;branch=z9hG4bK196959c9;rport
Max-Forwards: 70
From: <sip:101@192.168.141.128:5060>;tag=as557be705
To: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.
CSeq: 102 BYE
User-Agent: Asterisk PBX 13.10.0
Proxy-Authorization: Digest username="100", realm="asterisk", algorithm=MD5,
uri="sip:192.168.141.128", nonce="7cf5b422", response="61a51ad51971c61750bf5183b4
bd2895"
X-Asterisk-HangupCause: Normal Clearing
X-Asterisk-HangupCauseCode: 16
Content-Length: 0

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.141.128:5060;branch=z9hG4bK196959c9;rport=5060
Contact: <sip:100@192.168.141.1:61668;rinstance=57e8c42255f0c484>
To: "100"<sip:100@192.168.141.128:5060>;tag=e4125f3a
From: <sip:101@192.168.141.128:5060>;tag=as557be705
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪536‬‬

‫‪Call-ID: MjgzODcxZmVkMzIwZTUzMjMxYThkOThiMGZmM2MxNjc.‬‬
‫‪CSeq: 102 BYE‬‬
‫‪User-Agent: 3CXPhone 6.0.20943.0‬‬
‫‪Content-Length:‬‬

‫معرفی ابزار ‪SIPP‬‬

‫ابزار ‪ SIPP‬یکی از ابزارهای مهم و پرکاربرد برای تســت سیســتمهای تلفنی ‪ IPPBX‬اســت‪ .‬در ‪ SIPP‬این‬
‫قابلیت وجود دارد که بتوان ســناریوهای خود را با جزئیات )نزدیک به واقعیت( طراحی کرد و سیســتمهای‬
‫تلفنی را تست و مورد ارزیابی قرار داد‪.‬‬
‫ســناریوها در ‪ SIPP‬با زبان ‪ XML‬طراحی میشــوند که در ادامه درباره آنها توضیح خواهیم داد ولی‬
‫پیش از آن باید ابزار ‪ SIPP‬را نصب کنیم‪.‬‬
‫برای نصب ‪ SIPP‬ابتدا نیازمندیهای آن را نصب میکنیم‪:‬‬
‫‪#apt-get install dh-autoreconf ncurses-dev build-essential libssl-dev libpcap-dev libncurses5-‬‬
‫‪dev libsctp-dev lksctp-tools‬‬

‫آخرین نسخه ‪ SIPP-3.4.1‬را از مسیر زیر دانلود و نصب کنید‪:‬‬


‫‪#wget https://github.com/SIPp/sipp/archive/v3.4.1.tar.gz‬‬
‫‪#tar -xzvf v3.4.1.tar.gz‬‬
‫‪# cd sipp-3.4.1‬‬
‫‪# ./configure or # ./configure --with-sctp --with-pcap --with-openssl‬‬
‫‪# make‬‬

‫فرمت استفاده از ابزار ‪ SIPP‬بهصورت زیر است‪:‬‬


‫]‪#./sipp remote_host[:remote_port] [options‬‬

‫در زیر مهمترین پارامترهای فیلد ‪ options‬را بررسی میکنیم‪:‬‬


‫‪ : -sf‬بهوســیله این پارامتر‪ ،‬ســناریوی اجرایی از فایل تعیینشده لود و اجرا میشود‪ .‬این فایل بهصورت یک‬
‫فایل ‪ XML‬است‪.‬‬
‫>‪-sf <filename.xml‬‬

‫‪ : -inf‬در صورت تمایل به اســتفاده از دادههای پویا در ســناریو‪ ،‬میتــوان دادهها را در یک فایل بهصورت‬
‫‪ CSV‬ذخیره کرد‪:‬‬
‫>‪-inf <filename.csv‬‬

‫‪ : -r‬سرعت اجرای سناریو در واحد زمان بهوسیله این پارامتر مشخص میشود‪ .‬بهصورت پیشفرض اجرای‬
‫سناریو در هر یک ثانیه )‪ (۱۰۰۰ms‬است‪.‬‬
‫>‪-r <rate in ms‬‬

‫‪ : -rp‬اجرای ســناریو در فواصل زمانی را مشــخص میکند‪ .‬برای مثال دســتور زیر یعنی در هر ثانیه‪ ۱۰ ،‬بار‬
‫‪537‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫سناریو اجرا شود‪.‬‬


‫‪#./sip –sf scenario.xml –inf data.csv –r 10 –rp 1000‬‬

‫‪ : -t‬در صورت تمایل به اســتفاده از پروتکل ‪ TCP‬به جای ‪ ،UDP‬می‌توان آن را به‌وسیله این آپشن مشخص‬
‫نمود‪.‬‬
‫‪-t tcp‬‬

‫‪ : -m‬حداکثر تعداد کل تماس‌هایی که به‌وســیله ‪ SIPP‬ایجاد می‌شــود را مشــخص می‌کند‪ .‬برای مثال یک‬
‫سیستم تلفنی را برای ‪ 100‬تماس به صورت زیر تست می‌کنیم‪:‬‬
‫‪-m 100‬‬

‫بررسی انواع سناریوها در ‪SIPP‬‬


‫پیشتر توضیح دادیم که میتوان انواع سناریوها در ‪ SIPP‬را بهصورت ‪ XML‬طراحی نمود‪ .‬اما قبل از اینکه‬
‫به طراحی سناریو بپردازیم‪ ،‬بهتر است سناریوهای پیشفرض در ‪ SIPP‬را شرح دهیم‪.‬‬
‫سناریو ‪ :uas‬برای اجرا شدن این سناریو‪ ،‬دستور زیر را در مسیر فولدر نصب شده ‪ SIPP‬اجرا کنید‪.‬‬
‫‪# cd sipp-3.4.1‬‬
‫‪# ./sipp -sn uas –p 5061‬‬

‫همانطور که مالحظه میکنید‪ ،‬با اجرای این دستور‪ ،‬شرح سناریو بهصورت شکل ‪ ۳-۱۹‬نمایش داده خواهد‬
‫شد‪.‬‬

‫شکل ‪3-19‬‬

‫ابتدا یک پیام ‪ INVITE‬دریافت میشــود‪ ،‬ســپس پیام ‪) 180Ringing‬به منزلهی این که گوشی در حال‬
‫زنگ خوردن است( ارسال خواهدشد‪ .‬بعد از آن پیام ‪) 200OK‬به منزلهی اینکه تماس پاسخ داده شدهاست(‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪538‬‬

‫ارسال میشود‪ .‬پس از آن باید منتظر دریافت پیام ‪) ACK‬تأیید تماس( باشیم‪ .‬اکنون تماس برقرار شده است‪.‬‬
‫در این ســناریو تا زمانی که پیام ‪) BYE‬خاتمه تماس( دریافت نشــود‪ ،‬تماس فعال باقی میماند‪ .‬بعد از‬
‫دریافت پیام ‪ ،BYE‬پیام ‪ ۲۰۰OK‬ارسال و بعد از ‪ 4‬ثانیه تماس قطع میشود‪.‬‬
‫همانطورکه مالحظه میکنید‪ ،‬در طراحی سناریوها‪ ،‬باید تکتک پیامها را با دقت طراحی کرد و آنها‬
‫را در زمان تعیین شده ارسال کرد‪ .‬هر گونه نقصان در طراحی سناریو‪ ،‬باعث میشود نتوانیم سیستمهای تلفنی‬
‫‪ IPPBX‬و سایر تجهیزات را دقیقاً تست و بررسی کنیم‪.‬‬
‫سناریوی ‪ :uac‬برای استفاده از سناریوی ‪ ،uac‬این دستور را اجرا کنید‪:‬‬
‫‪# cd sipp-3.4.1‬‬
‫>‪# ./sipp -sn uac <remote-server><:remot-port‬‬

‫برای مثال فرض کنید بهصورت زیر آن را اجرا کنیم‪:‬‬


‫‪# ./sipp -sn uac 127.0.0.1:5061‬‬

‫شکل ‪4-19‬‬

‫در این سناریو‪ ،‬ابتدا پیام ‪ INVITE‬ایجاد میشود و برای سرور با پورت مشخصی )‪ (۱۲7,۰,۰,۱:۵۰۶۱‬ارسال‬
‫میگردد‪ .‬پس از ارســال آن‪ ،‬ســناریو منتظر دریافت پیامهــای ‪100Trying، 180Ringing، 183Session‬‬
‫‪ Progress‬و ‪ 200OK‬به ترتیب میماند و پس از دریافت پیامهای باال‪ ،‬پیام ‪ ACK‬را ارســال میکند‪ .‬ســپس‬
‫)به منزله اینکه تماس ‪ ۱۰‬ثانیه طول میکشــد( و بالفاصله بهوســیله ارســال پیام ‪BYE‬‬ ‫برای ‪ ۱۰‬ثانیه توقف‬
‫تماس را قطع میکند‪.‬‬
‫اکنون اگر ابتدا ســناریوی ‪ uas‬و سپس ســناریوی ‪ uac‬را اجرا کنید‪ ،‬متوجه میشوید که این شبیهسازی‬
‫بهوسیله خود ابزار ‪ SIPP‬در حال اجرا و تولید تماس است‪.‬‬
‫‪539‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫در ادامه به بررسی مثالهایی از سناریوهای مختلف و طراحی آنها میپردازیم‪.‬‬

‫طراحی سناریوی ‪OPTIONS‬‬


‫دیاگرام این سناریو به‌صورت زیر است‪:‬‬

‫شکل ‪5-19‬‬

‫در این سناریو باید یک پیام ‪ OPTIONS‬ایجاد و سپس آن را برای سیستم تلفنی ‪ IPPBX‬ارسال کنیم‪ .‬در‬
‫پاســخ باید پیام ‪ 200OK‬را از ســمت سرور دریافت کنیم‪ .‬لذا ابتدا یک فایل به اسم ‪ OPTIONS.xml‬ایجاد‬
‫و سناریوی خود را در آن طراحی میکنیم‪.‬‬
‫‪#vim OPTIONS.xml‬‬
‫>? "‪<?xml version="1.0" encoding="utf-8‬‬
‫>"‪<!DOCTYPE scenario SYSTEM "sipp.dtd‬‬

‫>"‪<scenario name="OPTIONS‬‬
‫>‪<send‬‬
‫[‪<![CDATA‬‬
‫‪OPTIONS sip:[remote_ip] SIP/2.0‬‬
‫]‪Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch‬‬
‫]‪From: <sip:sipp@[local_ip]>;tag=[call_number‬‬
‫>]‪To: <sip:sipp@[remote_ip‬‬
‫]‪Call-ID: [call_id‬‬
‫‪CSeq: [cseq] OPTIONS‬‬
‫]‪Contact: sip:sipp@[local_ip]:[local_port‬‬
‫‪Max-Forwards: 10‬‬
‫‪User-Agent: SIPp/Linux‬‬
‫‪Content-Length: 0‬‬
‫‪Accept: text/plain‬‬
‫>]]‬
‫>‪</send‬‬
‫>"‪<recv response="200‬‬
‫>‪</recv‬‬
‫>‪</scenario‬‬

‫در فایــل ســناریو‪ ،‬در تگ >‪ <send‬در فایل ‪ ،xml‬پیــام ‪ OPTIONS‬را در قالب پروتکل ‪ SIP‬پیادهســازی‬
‫میکنیم‪ .‬در تگ >‪ <recv‬پیامهایی که باید از طرف مقابل )ســرور ویپ( ارســال شود‪ ،‬دریافت خواهد شد‪.‬‬
‫در اکثر ســناریوهای ‪ ،SIPP‬از تگ>‪ <send‬برای ارســال پیام ‪ SIP‬و از تگ >‪ <recv‬برای دریافت پیامهای‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪540‬‬

‫‪ SIP‬استفاده میشود‪.‬‬
‫در این مثال ســرور استریسک ما دارای آی پی ‪ 192.168.141.128‬است‪ .‬بعد از تکمیل سناریو‪ ،‬آن را‬
‫بهصورت زیر اجرا کنید‪ .‬خروجی دستور بهصورت زیر خواهد بود‪:‬‬
‫‪#./sipp -sf OPTIONS.xml 192.168.141.128:5060 -r 1‬‬

‫شکل ‪6-19‬‬

‫میتوان ســرعت اجرای ســناریو را بهصورت زیر افزایش داد‪ .‬برای مثال در سیستم تلفنی خود بررسی کنید‬
‫که تا چه اندازه میتوانید سرعت سناریو را افزایش دهید‪.‬‬
‫‪#./sipp -sf OPTIONS.xml 192.168.141.128:5060 -r 100‬‬

‫شکل ‪7-19‬‬

‫اگر سرعت اجرای سناریو را باال ببرید‪ ،‬بعد از سپری شدن زمانی محدود‪ ،‬اکثر پیامها ارسال مجدد )‪(Retrans‬‬
‫میشوند و این به منزله شروع رسیدن به حد آستانه ظرفیت سیستم تلفنی است و میتواند شرایط بحرانی برای‬
‫سیستم تلفنی ایجاد کند‪.‬‬

‫طراحی سناریوی ‪REGISTER‬‬


‫دیاگرام این سناریو بهصورت شکل ‪ 8-۱۹‬است‪.‬‬
541 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

8-19 ‫شکل‬

‫( در سیستم تلفنی استریسک ایجاد و سپس سناریوی زیر را‬SIP ‫ ابتدا تعدادی داخلی )کاربر‬،‫در این سناریو‬
.‫اجرا میکنیم‬
#vim register_ok_example_book.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<scenario name="REGISTER">
<send retrans="500">
<![CDATA[
REGISTER sip:[field0]@[remote_ip] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
To: <sip:[field0]@[local_ip]>
Call-ID: [call_id]
CSeq: [cseq] REGISTER
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Expires: 120
User-Agent: SIPp/Win32
Content-Length: 0
]]>
</send>

<recv response="100" optional="true"></recv>


<recv response="401" auth="true"></recv>
<send retrans="500">
<![CDATA[
REGISTER sip:[field0]@[remote_ip] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
To: <sip:[field0]@[local_ip]>
Call-ID: [call_id]
CSeq: [cseq] REGISTER
Contact: sip:[field0]@[local_ip]:[local_port]
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪542‬‬

‫]‪[field1‬‬
‫‪Max-Forwards: 10‬‬
‫‪Expires: 12000‬‬
‫‪User-Agent: SIPp/Win32‬‬
‫‪Content-Length: 0‬‬
‫>]]‬
‫>‪</send‬‬
‫>‪<recv response="100" optional="true"></recv‬‬
‫>‪<recv response="200" ></recv‬‬
‫>‪</scenario‬‬

‫همانطور که در فایل مالحظه میکنید‪ ،‬پارامترهای پیام ]‪ [field0‬و ]‪ [field1‬را داریم‪ .‬قرار است این پارامترها‬
‫در اجرای ســناریو مقداردهی شوند‪ .‬برای مقداردهی این پارامترها‪ ،‬از فایل ‪register_ok_example_book.‬‬
‫‪ csv‬بهصورت زیر استفاده میکنیم‪:‬‬
‫‪# vim register_ok_example_book.csv‬‬
‫‪SEQUENTIAL‬‬
‫;]‪op100;[authentication username=op100 password=op100‬‬

‫همانطور که مالحظه میکنید‪ ،‬این مقادیر بهصورت زیر نگاشته میشوند‪:‬‬


‫‪SEQUENTIAL‬‬
‫;]‪[field0];[field1]; [field2]; [field3]; …;[fieldn‬‬

‫در هر بار اجرای ســناریو‪ ،‬یک رکــورد از فایل ‪ register_ok_example_book.csv‬برداشــته و مقادیر آن‬
‫جایگزین پارامترهای فایل ‪ register_ok_example_book.xml‬میشوند‪.‬‬
‫برای اجرای سناریو از دستور زیر استفاده کنید‪:‬‬
‫‪#./sipp -sf REGISTER.xml –inf REGISTER.csv 192.168.141.128:5060 -m 10‬‬

‫خروجی سناریو به صورت شکل ‪ ۹-۱۹‬خواهد بود‪:‬‬

‫شکل ‪9-19‬‬

‫با اجرای این سناریو در سرعت و تعداد باال‪ ،‬میتوانید سیستم تلفنی ‪ IPPBX‬را در عملیات رجیستر شدن‬
‫کاربران‪ ،‬تحلیل و آنالیز نمایید‪.‬‬
‫بهعنوان مثال فرض کنید بخواهیم عملکرد ســرور استریســک را در عملیات رجیســتر شدن برای ‪۱۰۰۰‬‬
‫کاربر‪ ،‬بهطوری که در هر لحظه ‪ ۱۰‬نفر در سیستم رجیستر شوند را بررسی کنیم‪.‬‬
‫‪543‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫برای تســت ‪ ۱۰۰۰‬کاربر لزومی ندارد حتماً ‪ ۱۰۰۰‬کاربر تعریف کنید‪ ،‬بلکه میتوانید همان دســتور باال‬
‫را ‪ ۱۰۰۰‬بار اجرا کنید‪.‬‬
‫‪#./sipp -sf REGISTER.xml –inf REGISTER.csv –r 10 –rp 1000 192.168.141.128:5060 -m 1000‬‬

‫با اجرای این دستور‪ ،‬در هر ثانیه ‪ ۱۰‬کاربر در سیستم تلفنی رجیستر میشوند‪ .‬این کار برای ‪ ۱۰۰۰‬کاربر‬
‫اجرا خواهد شد‪ .‬میتوانید با تغییر پارامترهای وضعیت‪ ،‬نتایج حاصل را ارزیابی کنید‪.‬‬

‫طراحی سناریوی ‪INVITE‬‬


‫سناریوی ایجاد تماس بهصورت زیر است‪:‬‬

‫شکل ‪10-19‬‬

‫ابتدا یک فایل ایجاد و ســناریوی ‪ INVITE‬را بهوسیله ‪ SIPP‬بهصورت زیر طراحی میکنیم )فیلدهای مهم‬
‫در پیام بهصورت ‪ Bold‬نمایش داده شده است(‪:‬‬
‫‪#vim invite_auth_book_example.xml‬‬
‫>? "‪<?xml version="1.0" encoding="ISO-8859-1‬‬
‫>"‪<scenario name=" INVITE + BYE‬‬

‫>"‪<send retrans="500‬‬
‫[‪<![CDATA‬‬
‫‪INVITE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0‬‬
‫]‪Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch‬‬
‫]‪From: sipp <sip:[field0]@[local_ip]>;tag=[call_number‬‬
‫>]‪To: <sip:[field2]@[local_ip]:[remote_port‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 544

Call-ID: [call_id]
CSeq: [cseq] INVITE
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Type: application/sdp
Content-Length: [len]

v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv response="100" optional="true"></recv>
<recv response="180" optional="true"></recv>
<recv response="183" optional="true"></recv>
<recv response="401" auth="true"></recv>
<send>
<![CDATA[
ACK sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
Call-ID: [call_id]
CSeq: [cseq] ACK
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
INVITE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:[field0]@[local_ip]>;tag=[call_number]
To: <sip:[field2]@[local_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: [cseq] INVITE
Contact: sip:[field0]@[local_ip]:[local_port]
[field1]
Max-Forwards: 10
Content-Type: application/sdp
545 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

Content-Length: [len]

v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv response="100" optional="true"></recv>
<recv response="180" optional="true"></recv>
<recv response="183" optional="true"></recv>
<recv response="200"></recv>
<send>
<![CDATA[
ACK sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
Call-ID: [call_id]
CSeq: [cseq] ACK
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
BYE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
Call-ID: [call_id]
CSeq: [cseq] BYE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 10
Content-Length: 0
]]>
</send>
<recv response="100" optional="true"></recv>
<recv response="200" crlf="true"></recv>
</scenario>
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪546‬‬

‫فایل ‪ invite_auth_book_example.csv‬بهصورت زیر خواهدبود‪:‬‬


‫‪#vim invite_auth_book_example.csv‬‬
‫‪SEQUENTIAL‬‬
‫‪op100;[authentication username=op100 password=op100];100‬‬

‫برای اجرای سناریو باید دستور زیر را اجرا کنیم‪:‬‬


‫‪# ./sipp -sf invite_auth_book_example.xml -inf invite_auth_book_example.csv -r 1 -rp 1000‬‬
‫‪192.168.141.128 -m 1‬‬

‫خروجی سناریو بهصورت شکل ‪ ۱۱-۱۹‬است‪.‬‬

‫شکل ‪11-19‬‬

‫طبق آنچه انجام دادیم‪ ،‬سناریو به ترتیب اجرا و یک تماس ازطریق کاربر ‪ op۱۰۰‬شبیهسازی میشود‪.‬‬
‫قبل از ادامه بحث بهتر است درباره این سناریو بیشتر صحبت کنیم‪ .‬همانطور که مالحظه میکنید در این‬
‫سناریو‪ ،‬تنها عملیات ایجاد تماس جدید پیادهسازی شده است‪ .‬واقعیت این است که بعد از ایجاد تماس‪ ،‬ما‬
‫باید بتوانیم دادههای ‪ RTP‬را تولید کنیم‪ .‬اینکه چگونه این دادهها را ایجاد کنیم‪ ،‬در قسمت بعد توضیح داده‬
‫میشود ولی قبل از آن بهتر است این سناریو را در حجم باال بررسی کنیم‪.‬‬
‫فرض کنید بخواهیم عملیات ‪ Call Setup‬را در حجم باال برای یک سیســتم تلفنی ‪ IPPBX‬بررســی و‬
‫ارزیابی کنیم‪ .‬هدف سناریو میتواند به صورت زیر تعریف شود‪:‬‬
‫• بررسی و ارزیابی فرایند ‪ Call Setup‬در سیستم تلفنی ‪IPPBX‬‬
‫• بررسی و ارزیابی فرایند اعتبارسنجی در سیستم تلفنی ‪IPPBX‬‬
‫به عبارت دیگر هردو هدف باال به دنبال این هستند که سیستم تلفنی ‪ IPPBX‬در شرایطی سخت ارزیابی‬
‫شود تا مشخص شود که سیستم‪ ،‬در هر ثانیه حداکثر چه تعداد میتواند فرایند ایجاد تماس جدید را پوشش‬
‫دهد‪ .‬برای مثال ســرعت ســناریوی قبل را بهصورت مرحله به مرحله افزایش دهید و این کار را تا زمانی که‬
‫‪547‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫پیامها ارسال مجدد نشدهاند‪ ،‬ادامه دهید‪ .‬ولی قبل از آن باید تغییر کوچکی در استریسک انجام دهید‪.‬‬
‫ابتدا پارامتر کانتکست برای کاربر ‪ op۱۰۰‬را بهصورت زیر تغییر دهید‪:‬‬
‫‪;sip.conf‬‬
‫]‪[op100‬‬
‫‪Context=sip_test‬‬

‫سپس این برنامه را به استریسک اضافه کنید‪:‬‬


‫‪;extensions.conf‬‬
‫]‪[sipp_test‬‬
‫)(‪exten => _X.,1,NoOp‬‬
‫)(‪same => n,Ringing‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => n,NoOp(Wait For Hangup‬‬

‫بعد از ‪ reload‬کردن استریسک‪ ،‬سناریو را بهصورت زیر اجرا کنید‪:‬‬


‫‪#./sipp -sf invite_auth_book_example.xml -inf invite_auth_book_example.csv -r 1 -rp 1000‬‬
‫‪192.168.141.128 -m 1‬‬

‫اینجا تماس به ســمت استریســک میرود و استریسک آن را پاســخ میدهد ولی به محض پاسخ دادن‪ ،‬پیام‬
‫ِ‬
‫تماس جدید و‬ ‫‪ BYE‬ارسال و تماس قطع میشود‪ .‬در این سناریو‪ ،‬هدف صرفا بهوجود آوردن فرآیند ایجاد‬
‫قطع آن اســت‪ .‬اکنون ســرعت اجرای سناریو را باال برده و سیستم تلفنی خود را تست کنید‪ .‬در مثال زیر در‬
‫هر ثانیه ‪ ۱۰‬تماس جدید خواهیم داشت‪ .‬این سناریو برای ‪ ۲۰۰‬تماس اجرا خواهد شد‪.‬‬
‫‪#./sipp -sf invite_auth_book_example.xml -inf invite_auth_book_example.csv -r 10 -rp 1000‬‬
‫‪192.168.141.128 -m 200‬‬

‫همانطــور کــه پیشتر نیز توضیح دادیم‪ ،‬برای ایجاد یک تماس واقعی بایــد بتوانیم دادههای ‪ RTP‬را ایجاد‬
‫کنیم‪ .‬ازآنجاکه در سناریو قبل به محض ایجاد تماس جدید‪ ،‬تماس را قطع میکردیم‪ ،‬دادههای ‪ RTP‬تولید‬
‫نمیشدند‪ .‬لذا باید تغییراتی را در سناریو ایجاد کنیم‪ .‬برای ایجاد دادههای ‪ RTP‬از کد زیر در سناریو ‪SIPP‬‬
‫استفاده میکنیم‪:‬‬
‫>‪<nop‬‬
‫>‪<action‬‬
‫>‪<exec play_pcap_audio="pcap/g711a.pcap"/‬‬
‫>‪</action‬‬
‫>‪</nop‬‬

‫سناریوی قبل را بهصورت زیر تغییر دهید‪:‬‬


‫‪# vim invite_auth__RTP_book_example.xml‬‬
‫>? "‪<?xml version="1.0" encoding="ISO-8859-1‬‬
‫>"‪<scenario name="INVITE + RTP‬‬

‫>"‪<send retrans="500‬‬
‫[‪<![CDATA‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 548

INVITE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0


Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:[field0]@[local_ip]>;tag=[call_number]
To: <sip:[field2]@[local_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: [cseq] INVITE
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Type: application/sdp
Content-Length: [len]

v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv response="100" optional="true"></recv>
<recv response="180" optional="true"></recv>
<recv response="183" optional="true"></recv>
<recv response="401" auth="true"></recv>
<send>
<![CDATA[
ACK sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
Call-ID: [call_id]
CSeq: [cseq] ACK
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
INVITE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:[field0]@[local_ip]>;tag=[call_number]
To: <sip:[field2]@[local_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: [cseq] INVITE
549 ‫ و تجهیزات وابسته‬IPPBX ‫ارزیابی عملکرد سیســتم‌های تلفنی‬

Contact: sip:[field0]@[local_ip]:[local_port]
[field1]
Max-Forwards: 10
Content-Type: application/sdp
Content-Length: [len]

v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv response="100" optional="true"></recv>
<recv response="180" optional="true"></recv>
<recv response="183" optional="true"></recv>
<recv response="200"></recv>
<send>
<![CDATA[
ACK sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
Call-ID: [call_id]
CSeq: [cseq] ACK
Contact: sip:[field0]@[local_ip]:[local_port]
Max-Forwards: 10
Content-Length: 0
]]>
</send>
<pause milliseconds="2000"/>
<nop>
<action>
<exec play_pcap_audio="pcap/g711a.pcap"/>
</action>
</nop>
<pause milliseconds="10000"/>
<send retrans="500">
<![CDATA[
BYE sip:[field2]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field0]@[local_ip]>;tag=[call_number]
[last_To:]
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪550‬‬

‫]‪Call-ID: [call_id‬‬
‫‪CSeq: [cseq] BYE‬‬
‫]‪Contact: sip:sipp@[local_ip]:[local_port‬‬
‫‪Max-Forwards: 10‬‬
‫‪Content-Length: 0‬‬
‫>]]‬
‫>‪</send‬‬
‫>‪</scenario‬‬

‫اکنون باید تغییرات زیر را در استریسک ایجاد کنید‪:‬‬


‫]‪[sipp_test‬‬
‫)(‪exten => _X.,1,NoOp‬‬
‫)(‪same => n,Ringing‬‬
‫)(‪same => n,Answer‬‬
‫)(‪same => n,MusicOnHold‬‬

‫سپس دستور زیر را اجرا کنید‪:‬‬


‫‪# ./sipp -sf invite_auth_book_example.xml -inf invite_auth_book_example.csv -r 1 -rp 1000‬‬
‫‪192.168.141.128 -i 192.168.141.129 -m 1‬‬

‫با اجرای دستور باال‪ ،‬تماس ایجاد میشود و دادههای ‪ RTP‬بین ‪ SIPP‬و استریسک بهصورت دو طرفه ارسال‬
‫میشوند‪ .‬برای مشاهده دادههای ‪ RTP‬دستور زیر را در محیط کامندالین استریسک اجرا کنید‪.‬‬
‫‪CLI> rtp set debug on‬‬

‫خروجی دستور بهصورت شکل ‪ ۱۲-۱۹‬خواهد بود‪:‬‬

‫شکل ‪12-19‬‬

‫میتوان با ایجاد تماسهای بیشتر‪ ،‬سیستم تلفنی ‪ IPPBX‬را در تعداد تماسهای همزمان تست کرد‪ .‬برای مثال‬
‫در دستور زیر در هر ثانیه‪ ۱۰ ،‬تماس جدید )به همراه انتقال دادههای ‪ (RTP‬ایجاد میکنیم‪.‬‬
‫‪# ./sipp -sf invite_auth_book_example.xml -inf invite_auth_book_example.csv -r 10 -rp 1000‬‬
‫‪192.168.141.128 -i 192.168.141.129 -m 100‬‬
‫‪551‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫بررسی تأثیر عوامل مؤثر بر مصرف منابع سیستم‌های تلفنی ‪IPPBX‬‬


‫یکی از عوامل مؤثر بر منابع سرورهای شبکه تعداد تماسهای ورودی شبکه در واحد زمان است‪.‬‬
‫همچنین از دیگر عوامل مؤثر منابع برای کنترل بهینه منابع میتوان به ارسال مدیا )‪ (RTP‬از سرورها اشاره‬
‫کرد‪ .‬ازآنجاکه در استریسک فرآیند سیگنالینگ و مدیا از هم جدا نیستند‪ ،‬در ادامه به بررسی تأثیر مدیا نیز‬
‫خواهیم پرداخت‪.‬‬

‫تاثیرمیزان تماس ورودی بر منابع سیستم تلفنی‬


‫در ایــن قســمت تأثیر تعداد تماس همزمان در واحــد زمان )‪ (CPS‬بر مصرف منابع را خواهیم ســنجید‪ .‬لذا‬
‫سناریوی زیر را برای تست سیگنالینگ در نظر گرفتهایم‪:‬‬

‫شکل ‪13-19‬‬

‫همانگونهکــه در شــکل ‪ ۱۳-۱۹‬مالحظه میشــود‪ ،‬زمان ‪ Pause‬را صفــر در نظر گرفتهایم تــا فع ً‬
‫ال در این‬
‫آزمایش درگیر ارســال مدیا نشــویم‪ .‬همانطور که پیشتر هم توضیح داده شد‪ ،‬با افزایش مقدار پارامتر ‪، r‬‬
‫میزان تماسهای ورودی افزایش مییابد‪ .‬تأثیر این پارامتر بر میزان مصرفی ‪ RAM‬و ‪ CPU‬بهصورت شــکل‬
‫‪ ۱4-۱۹‬است‪:‬‬
‫با توجه به شکل ‪ ۱4-۱۹‬میتوان فهمید که افزایش بار ورودی‪ ،‬به میزان بیشتری بر ‪ CPU‬و با شیب کمتری‬
‫بر ‪ RAM‬تأثیرگذار اســت‪ .‬همچنین میتوان حدس زد که ظرفیت این ســرور مشخص‪ ،‬حدود ‪ ۲۰۰‬تا ‪۲۵۰‬‬
‫تماس بر ثانیه اســت‪ ،‬چرا که با افزایش ‪ r‬به بیش از این مقدار‪ ،‬پیامهای ســیگنالینگ به طرف سرور سرازیر‬
‫میشوند و این بدین معنی است که سرور ظرفیت و بهعبارتی منابع الزم برای پاسخگویی به همهی تماسها‬
‫را نداشته و ناچار به رد آنهاست‪ ،‬در نتیجه ‪ SIPP‬نیز آنها را دوباره ارسال میکند‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪552‬‬

‫شکل ‪14-19‬‬
‫تأثیر مدیا (‪ )RTP‬بر منابع سیستم تلفنی‬
‫در این آزمایش فرض میکنیم که ‪ r‬یا تعداد تماسهای ارسالی در ثانیه برابر با یک باشد تا بتوانیم تنها تأثیر‬
‫‪ RTP‬بــر منابع را بســنجیم‪ .‬تأثیر تعداد تماسهای همزمان )با در نظر گرفتــن انتقال دادههای ‪ (RTP‬بر میزان‬
‫مصرفی ‪ RAM‬و ‪ CPU‬بهصورت شکل ‪ ۱۵-۱۹‬است‪.‬‬

‫شکل ‪15-19‬‬
‫‪553‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫همان‌گونه که در شــکل‌های ‪ ۱4-۱۹‬و ‪ ۱۵-۱۹‬مشــاهده می‌شــود‪ ،‬با افزایش ‪ RTP‬منابع مصرفی نیز بیشــتر‬
‫می‌شود‪ ،‬اما این افزایش به‌طور چشم‌گیری در ‪ CPU‬بیشتر از ‪ RAM‬است‪.‬‬

‫بررسی کیفیت سرویس (‪ )Quality of Service‬در سیستم‌های تلفنی ‪IPPBX‬‬


‫تا اینجا پیادهسازی انواع سناریوها برای ایجاد تماس بررسی شد‪ .‬میتوان بر اساس این سناریوها‪ ،‬یک سیستم‬
‫تلفنی را از جنبههای گوناگون بررســی کرد‪ .‬یک پرســش مهم اینکه آیا میتوان کیفیت سرویس ارائه شده‬
‫در سیســتم تلفنی را بررســی و تســت نمود؟ به عبارت دیگر آیا پس از ایجاد تماس و انتقال دادههای ‪،RTP‬‬
‫آیا کیفیت صدا خوب است یا نه؟‬
‫امروزه اکثر دادهها را میتوان ازطریق پروتکل ‪ IP‬انتقال داد‪ .‬از جملهی این دادهها میتوان به سرویسهای‬
‫‪ email ، FTP‬و مانند اینها اشاره کرد‪ .‬در اینگونه موارد‪ ،‬انتقال صدا ازطریق ‪ IP‬از اهمیت ویژهای برخوردار‬
‫است‪ .‬از بزرگترین چالشهای انتقال صدا در بستر ‪ ، IP‬حفظ کیفیت صوت و پهنای باند موجود برای انتقال‬
‫آن است‪ .‬البته این امر در انتقال همه دادهها رخ میدهد‪.‬‬
‫برای مثال هنگام انتقال یک فایل ازطریق ‪ FTP‬ممکن اســت با چالش کمبود پهنای باند مواجه شــویم و‬
‫این کمبود باعث کاهش ســرعت انتقال شــود‪ ،‬ولی در خصوص دادههای ‪ Real Time‬این موارد باعث افت‬
‫شدید کیفیت سرویس میشود و اثرات منفیای در ارائه سرویس و خدمات به مشتریان دارد‪.‬‬
‫امروزه هم اینترنت و هم افرادی که از اینترنت اســتفاده میکنند‪ ،‬به سرعت در حال افزایشاند‪ ،‬به همین‬
‫دلیل اســتفاده از ‪ VoIP‬نیز به ســرعت در حال گسترش اســت و بنابراین ممکن است نتوان کیفیت سرویس‬
‫مطلوبی برای ویپ ارائه داد و حداقل پهنای باند تضمین شده به مشتری عرضه نمود‪.‬‬
‫همانطــور که اطــالع دارید پروتکل ‪ IP‬یک پروتکل ‪) Best Effort‬حداکثر تالش( اســت و هیچگونه‬
‫مالحظاتی برای کیفیت سرویس ندارد‪ BE .‬به این معنی است که حداکثر تالش خود را برای انتقال صحیح‬
‫دادهها انجام میدهد ولی هیچ تضمینی هم در تحویل صحیح بستهها ندارد‪ .‬این شبکهها را ‪Packet Switch‬‬
‫میگویند‪ ،‬به این صورت که دادهها بهصورت بســته بســته در شــبکه مســیریابی و از مبدأ به مقصد ارســال‬
‫میشــوند‪ .‬فرآیند مســیریابی بستهها‪ ،‬در ســطح الیهسوم شبکه انجام میشــود‪ ،‬بنابراین‪ ،‬ممکن است در این‬
‫فرآیند‪ ،‬بســتههایی هیچگاه به مقصد نرســند و درمیانه راه از بین بروند‪ .‬شــکل ‪ ۱۶-۱۹‬شــبکهای از ‪Packet‬‬
‫‪ Switch‬را نشان میدهد‪.‬‬
‫برای بررسی کیفیت صدا باید پارامترهای مختلفی را ارزیابی کرد‪ .‬این پارامترها عبارتند از‪:‬‬

‫‪1‬‬
‫از بین رفتن بسته‌ها‬
‫تعداد بسته‌هایی که در میانه راه از بین می‌روند‪.‬‬

‫‪1- Packet Lost‬‬


‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪554‬‬

‫شکل ‪16-19‬‬

‫‪1‬‬
‫تاخیر‬
‫مدت زمانی که طول میکشــد‪ ،‬بسته از فرســتنده به گیرنده برسد را ‪ delay‬مینامند‪ .‬در شبکههای ویپ این‬
‫تاخیر تا حدی قابل قبول است ولی اگر مقدار آن زیاد شود‪ ،‬اثرات نامطلوبی روی شبکه خواهد داشت‪ .‬برای‬
‫مثال به شکل ‪ ۱7-۱۹‬توجه کنید‪.‬‬

‫شکل ‪17-19‬‬

‫با توجه به شکل )‪ ،(۱7-۱۹‬پارامتر تأخیر بهصورت زیر محاسبه میشود‪:‬‬

‫)‪delay= (t2-t1) + (t4-t3‬‬


‫به عبارتی دیگر اگر ‪ Si‬زمان ارســال بســته ‪ i‬ام در ســرور مبدأ و ‪ Ri‬زمان دریافت بســته ‪ i‬ام در مقصد باشد‪،‬‬
‫زمان انحرافی برای دو بســته ‪ i‬ام و ‪ j‬ام داریم‪ .‬شــکل )‪ (۱7-۱۹‬محاسبه تاخیر برای نمونههای مختلف را نشان‬
‫میدهد‪.‬‬

‫)‪D(i,j) = (R j- Ri) - (S j- Si ) = (Rj - Sj ) - (Ri - Si‬‬

‫‪2‬‬
‫تغییرات تأخیر‬
‫یکی دیگر از پارامترهای کیفیت ســرویس‪ ،‬تغییرات تأخیر )‪ (jitter‬اســت‪ .‬به عبارت دیگر تغییرات آماری‬
‫در فاصلهی بین بستههای دریافتی در واحد زمان را تغییرات تأخیر میگویند‪ .‬در پروتکل ‪ ،RTP‬این محاسبه‬

‫‪1- delay‬‬
‫‪2- Jitter‬‬
‫‪555‬‬ ‫ارزیابی عملکرد سیســتم‌های تلفنی ‪ IPPBX‬و تجهیزات وابسته‬

‫بر اســاس زمان ارسال و دریافت بستهها انجام میشود‪ .‬برای مثال‪ ،‬اگر نرخ نمونهبرداری از فرکانس صدا در‬
‫واحد زمان ‪ 8۰۰۰‬بار باشد‪ ، ۱‬اینجا باید زمان واحد را بر ‪ 8۰۰۰‬تقسیم کنیم‪.‬‬
‫پارامتر ‪ Jitter‬در شــبکه‌های ویپ بسیار حساس است و تاحدی تغییرات آن قابل قبول است‪ .‬برای اینکه‬
‫تغییرات دقیق‌تر محاســبه شــود‪ ،‬آن را بر عدد ‪( 16‬که نشان دهنده تغییرات تأخیر برای ‪ 16‬بسته قبلی دریافت‬
‫شده است) تقسیم می‌کنند‪ .‬فرمول زیر‪ ،‬محاسبه ‪ jitter‬را برای نمونه‌های مختلف نشان می‌دهد‪.‬‬
‫‪J(i)= J(i-1)+(| D(i-1,i) | - J(i-1)) / 16‬‬
‫جدول ‪ ۱۹-۲‬تاخیر و تغییرات تاخیر را برای ‪ si‬و ‪ Ri‬های مختلف نشان میدهد‪.‬‬

‫‪I‬‬ ‫‪Si‬‬ ‫‪Ri‬‬ ‫)‪D(i, i-1‬‬ ‫)‪J(i‬‬


‫‪1‬‬ ‫‪0‬‬ ‫‪10‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪2‬‬ ‫‪20‬‬ ‫‪30‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪3‬‬ ‫‪40‬‬ ‫‪49‬‬ ‫‪-1‬‬ ‫‪0.0625‬‬
‫‪4‬‬ ‫‪60‬‬ ‫‪74‬‬ ‫‪5‬‬ ‫‪0.3711‬‬
‫‪5‬‬ ‫‪80‬‬ ‫‪90‬‬ ‫‪-4‬‬ ‫‪0.5979‬‬
‫‪6‬‬ ‫‪100‬‬ ‫‪111‬‬ ‫‪1‬‬ ‫‪0.6230‬‬
‫‪7‬‬ ‫‪120‬‬ ‫‪139‬‬ ‫‪8‬‬ ‫‪1.0841‬‬
‫‪8‬‬ ‫‪140‬‬ ‫‪150‬‬ ‫‪-9‬‬ ‫‪1.5788‬‬
‫‪9‬‬ ‫‪160‬‬ ‫‪170‬‬ ‫‪0‬‬ ‫‪1.4802‬‬
‫‪10‬‬ ‫‪180‬‬ ‫‪191‬‬ ‫‪1‬‬ ‫‪1.4501‬‬
‫‪11‬‬ ‫‪200‬‬ ‫‪210‬‬ ‫‪-1‬‬ ‫‪1.4220‬‬
‫‪12‬‬ ‫‪220‬‬ ‫‪229‬‬ ‫‪-1‬‬ ‫‪1.3956‬‬
‫‪13‬‬ ‫‪240‬‬ ‫‪250‬‬ ‫‪1‬‬ ‫‪1.3709‬‬
‫‪14‬‬ ‫‪260‬‬ ‫‪271‬‬ ‫‪1‬‬ ‫‪1.3477‬‬
‫جدول ‪2-19‬‬

‫پارامتر ‪ 2 MOS‬در شبکه‌های ویپ‬


‫از مهمترین پارامترهای سنجش کیفیت سرویس در شبکههای ویپ‪ ،‬پارامتر ‪ MOS‬است‪ .‬میتوان با ارزیابی‬
‫عدد بهدســتآمده برای ‪ MOS‬در شــبکههای ویپ‪ ،‬کیفیت صدا را اندازهگیری نمود‪ .‬جدول ‪ ۳-۱۹‬مقادیر‬
‫‪ MOS‬را نمایش میدهد‪.‬‬

‫‪ -1‬طبق استاندارد ‪PCM‬‬


‫‪2- Mean Opinion Score‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪556‬‬

‫‪MOS‬‬ ‫‪Quality‬‬ ‫‪Impairment‬‬


‫‪5‬‬ ‫‪Excellent‬‬ ‫‪Imperceptible‬‬
‫‪4‬‬ ‫‪Good‬‬ ‫‪Perceptible but not annoying‬‬
‫‪3‬‬ ‫‪Fair‬‬ ‫‪Slightly annoying‬‬
‫‪2‬‬ ‫‪Poor‬‬ ‫‪Annoying‬‬
‫‪1‬‬ ‫‪Bad‬‬ ‫‪Very annoying‬‬
‫جدول ‪3-19‬‬

‫همچنین جدول ‪ ،4-۱۹‬حد قابل قبول برای انواع پارامترها و ‪ MOS‬را در شبکههای ویپ بر اساس کدکهای‬
‫مختلف نشان میدهد‪.‬‬

‫‪CODEC‬‬ ‫‪BirRate‬‬ ‫‪MOS‬‬ ‫‪Delay‬‬


‫‪Kbps‬‬ ‫‪ms‬‬
‫‪G.711‬‬ ‫‪64‬‬ ‫‪4.5‬‬ ‫‪0.125‬‬
‫‪G723.1‬‬ ‫‪5.3‬‬ ‫‪3.6‬‬ ‫‪30‬‬
‫‪6.3‬‬ ‫‪3.98‬‬
‫‪G726‬‬ ‫‪16-24-32-40‬‬ ‫‪4.2‬‬ ‫‪0.125‬‬
‫‪Most Commonly used 32‬‬
‫‪G.728‬‬ ‫‪16‬‬ ‫‪4.2‬‬ ‫‪2.5‬‬
‫‪G.729‬‬ ‫‪8‬‬ ‫‪4.2‬‬ ‫‪10‬‬
‫جدول ‪4-19‬‬

‫پرواضح اســت که با بهدست آوردن این پارامترها برای یک سیستم تلفنی ‪ ،IPPBX‬میتوان بهصورت دقیق‬
‫کیفیت ســرویس آن را ارزیابی کــرد و اقدامات الزم برای بهبود کیفیت ســرویس را انجام داد‪ .‬برای مثال‬
‫میتوان سرویسی طراحی کرد که پس از اجرای آن بهوسیله ابزار ‪ ،SIPP‬کلیه اطالعات الزم را جمعآوری‬
‫کند و کیفیت سرویس مطلوبی را برای ما فراهم آورد‪.‬‬

‫نتیجه‌گیری‬
‫در این فصل ابتدا مفاهیم اولیه و انواع مدلسازی بررسی شدند و پس از آن به اهداف مدلسازی و نتایج آن‬
‫در طراحی یک سیســتم تلفنی پرداخته شد‪ .‬سپس ابزار ‪ SIPP‬معرفی شد‪ .‬در مرحله بعد‪ ،‬مهمترین سناریوها‬
‫بررسی شدند و نمونههایی از آنها نیز انجام شد‪ .‬در انتها به بررسی کیفیت سرویس در شبکههای ویپ اشاره‬
‫شد و انواع پارامترهای آن بررسی گردید‪ .‬امید است با شناخت کامل از این سیستم‪ ،‬بتوانید سناریوهای موفق‬
‫و درستی طراحی و اجرا کنید‪.‬‬
‫فصل بیستم‬
‫آشنایی با دستورات و توابع مهم‬
‫و پرکاربرد در استریسک‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪558‬‬

‫مقدمه‬
‫در استریســک دســتورات و توابع زیادی وجود دارد که میتوان از آنها در برنامهنویسی استریسک و یا در‬
‫برنامهنویسی ‪ AGI‬استفاده کرد‪ .‬در فصل پنجم )برنامهنویسی مقدماتی در استریسک( و هشتم )برنامه نویسی‬
‫پیشــرفته در استریســک( با برخی از آنها آشنا شدید‪ .‬ازآنجاکه برخی دســتورات و توابع در برنامهنویسی‪،‬‬
‫کاربرد زیادی دارند‪ ،‬در این فصل ســعی داریم برخی از مهمترین آنها را بررســی کنیم و مثالیهایی انجام‬
‫دهیم‪.‬‬
‫همانطورکه پیشتر هم توضیح دادهشــد‪ ،‬برای مشاهده انواع دستورات و توابع در استریسک میتوانید‬
‫از دستورات زیر در کامندالین استریسک استفاده کنید‪:‬‬
‫‪CLI> core show applications‬‬

‫برای مشاهده توابع از دستور زیر استفاده کنید‪:‬‬


‫‪CLI> core show functions‬‬

‫با اجرای هر یک از دســتورات باال‪ ،‬لیستی از دستورات و توابع در استریسک نمایش داده میشود‪ .‬نکته‬
‫مهم این است که اگر ماژولی در استریسک غیرفعال باشد‪ ،‬نام دستور و یا تابع آن در استریسک نمایش داده‬
‫نخواهد شــد‪ .‬پس بهتر اســت جمله قبلی را به این شکل اصالح کنیم که با اجرای هر یک از دستورات باال‪،‬‬
‫لیستی از دستورات و توابع ماژولهای فعال در استریسک نمایش داده خواهد شد‪.‬‬
‫‪559‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫ابتدا به معرفی دســتورات مهم در استریســک میپردازیم‪ .‬ازآنجاکه دســتورات استریســک را میتوان‬
‫دستهبندی کرد‪ ،‬لذا آنها را دستهبندی و مرتبکرده و شرح میدهیم‪.‬‬

‫دستورات ایجاد یک تماس در استریسک‬


‫به عنوان یک مدیر سیستم‪ ،‬باید بتوانید بهراحتی تماسهایی در استریسک ایجاد کنید‪ .‬اکثر این تماسها برای‬
‫بررسی وضعیت کاربران در سیستم و یا بررسی برنامههای نوشته شده است‪.‬‬
‫برای مثال ممکن اســت برخی از کاربران در سیســتم تلفنی استریسک گزارش دهند که نمیتوانند یک‬
‫برنامه خاص را اجرا کنند و یا اینکه نمیتوانند با یک شــخص خاصی تماس بگیرند‪ .‬در این شــرایط شما به‬
‫عنوان یک مدیر سیستم باید بتوانید خیلی سریع این مورد را شخصا تست و بررسی کنید‪.‬‬
‫در طول کتاب با یکی از روشهای تست برنامهها در استریسک آشنا شدید‪ .‬اینجا ضمن مرور آن روش‪،‬‬
‫ســایر روشها را نیز بررســی خواهیم کرد‪ .‬نکته مهم این اســت که اکثر این دستورات در محیط کامندالین‬
‫استریسک اجرا میشوند‪.‬‬

‫دستور ‪console‬‬
‫بهوسیله این دستور بهراحتی میتوانید یک تماس ایجاد کنید تا یک برنامه تعیینشده را اجرا نماید‪ .‬برای مثال‬
‫فرض کنید برنامهای بهصورت زیر در استریسک داشته باشیم‪:‬‬
‫]‪[my-sample‬‬
‫)(‪exten => wait,1,Answer‬‬
‫)‪same => n,Wait(300‬‬
‫)(‪same => n,Hangup‬‬

‫)‪exten => newexten,1,Verbose(1,I wonder if my CUT() works...‬‬


‫)‪same => n,Set(VAR=one-two-three‬‬
‫)})‪same => n,Verbose(1,one = ${CUT(VAR,-,1‬‬

‫برای تست برنامه‪ ،‬در کامندالین استریسک دستورات زیر را اجرا کنید‪:‬‬
‫‪CLI>console dial wait@my-sample‬‬
‫‪CLI>console dial newexten@my-sample‬‬

‫دستور ‪originate‬‬
‫بهوسیله این دستور‪ ،‬یک تماس برای مقصد مشخصی ایجاد میشود‪ .‬چنانچه تماس پاسخ داده شود‪ ،‬برنامهای‬
‫که تعیین کردهاید‪ ،‬اجرا خواهد شد‪ .‬برای مثال‪ ،‬برنامه قبل را با روش زیر تست میکنیم‪.‬‬
‫‪CLI>channel originate SIP/100 extension wait@my-sample‬‬
‫‪CLI> channel originate SIP/100 extension newexten@my-sample‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪560‬‬

‫اینجا یک تماس با کاربر ‪ ۱۰۰‬گرفته میشود‪ .‬چنانچه او تماس را پاسخ دهد‪ ،‬برنامهی مورد نظر اجرا میشود‪.‬‬
‫میتوان هر برنامهی دیگری را که مایل باشید بهوسیله این دستور اجرا کنید‪ .‬در زیر مثالهایی از استفاده‬
‫از این دستور آورده شده است‪.‬‬
‫‪CLI>channel originate SIP/100 application Playback demo-congrats‬‬
‫‪CLI>channel originate SIP/100 application Dial DAHDI/g0/09151176713‬‬
‫‪CLI>channel originate Local/wait@default extension newexten@dafault‬‬

‫دستورات مربوط به کنترل تماس‌ها (‪)Call Handling‬‬


‫دستور ‪Answer‬‬
‫بهوســیله این دســتور‪ ،‬تماسها در استریسک پاســخ داده میشــوند‪ .‬میتوانید یک تماس را در استریسک‬
‫پاســخ دهید و ســپس آن را مدیریت و کنترل نمایید‪ .‬برای مثال برنامه زیر را در نظر بگیرید‪ .‬تمام تماسهای‬
‫ورودی از سمت شبکه مخابراتی ‪ PSTN‬وارد کانتکست ]‪ [from-pstn‬شده و بعد از پاسخ داده شدن بهوسیله‬
‫استریسک وارد صف پشتیبانی میشود‪.‬‬
‫]‪[from-pstn‬‬
‫)‪exten => s,1,Verbose(2,Incoming call handler‬‬
‫)(‪same => n,Answer‬‬
‫)‪same => Queue(support‬‬
‫)(‪same => Hangup‬‬

‫دستور ([‪Busy([Timeout‬‬
‫بهوسیله این دستور‪ ،‬استریسک میتواند بوق مشغولی )‪ (Busy Dial Tone‬برای تماس ایجاد کند‪ .‬برای مثال‬
‫در برنامه زیر در صورتی که کاربر ‪ Phone_1‬در حال مکالمه باشــد‪ ،‬استریســک بوق مشغولی را برای یک‬
‫زمان مشخص شده‪ ،‬پخش خواهد کرد‪.‬‬
‫)‪exten => 100,1,Verbose(3,Calling SIP/Phone_1‬‬
‫)‪same => n,Dial(SIP/Phone_1,20‬‬
‫)‪same => n,Goto(s-${DIALSTATUS},1‬‬

‫)‪exten => s-NOANSWER,1,VoiceMail(Phone_1@default,u‬‬

‫)‪exten => s-BUSY,1,Busy(5‬‬


‫)‪same => n,VoiceMail(Phone_1@default,b‬‬

‫دستور ‪Progress‬‬
‫این دســتور همانند دســتور ‪ Answer‬است‪ .‬با این تفاوت که در دســتور ‪ Answer‬پیام سیگنالینگ ‪۲۰۰OK‬‬
‫ارســال خواهد شد و تماس بهصورت واقعی پاسخ داده میشــود ولی در دستور ‪ Progress‬پیام سیگنالینگ‬
‫‪561‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫‪ 183Session Progress‬ارسال میشود و کانال برای انتقال مدیا )صوت( آماده خواهد شد ولی هنوز تماس‬
‫پاسخ داده نشده است‪ .‬این دستور در شبکههای سیگنالینگ پروتکل ‪ SIP‬قابل استفاده است‪.‬‬
‫)‪exten => _XXX,1,NoOp(Calling local extensions‬‬
‫)(‪same => n,Progress‬‬
‫)‪same => n,Dial(SIP/${EXTEN},30‬‬
‫)(‪same => n,Hangup‬‬

‫دستور (‪DISA (Direct Inward System Access‬‬


‫یکی از قابلیتهای بسیار مهم در استریسک دسترسی از راه دور به سیستم تلفنی استریسک و آزاد گذاشتن‬
‫بوق اســت‪ .‬برای مثال فرض کنید بتوان از راه دور با استریســک تماس گرفت و سپس استریسک به ما بوق‬
‫آزاد بدهد‪ .‬در این حالت استریسک به مانند یک کاربر داخلی رفتار خواهد کرد‪ .‬برای آشنایی بیشتر با این‬
‫دستور‪ ،‬فرمان زیر را در کامندالین استریسک اجرا کنید‪:‬‬
‫‪CLI> core show application DISA‬‬
‫]‪[Syntax‬‬
‫)]]]]‪DISA(passcode|filename[,context[,cid[,mailbox[@context][,options‬‬

‫برای مثال برنامه زیر را در نظر بگیرید‪:‬‬


‫]‪[from-pstn‬‬
‫)(‪exten => 1010,1,Answer‬‬
‫)‪same => n,DISA(1234,LocalSets‬‬

‫]‪[LocalSets‬‬
‫)}‪exten => _XXX,1,Dial(SIP/${EXTEN‬‬

‫همانطورکه مالحظه میکنید‪ ،‬باید پســورد را برای اجرا شــدن دســتور ‪ DISA‬وارد کنید‪ .‬همچنین میتوان‬
‫در فراخوانی دستور ‪ DISA‬نام فایلی که پسوردها در آن ذخیره شده است را بهصورت زیر استفاده کنید‪.‬‬
‫]‪[from-pstn‬‬
‫)(‪exten => 1010,1,Answer‬‬
‫)‪same => n,DISA(/usr/src/passdisa.txt‬‬

‫اکنون باید فایل ‪ passdisa.txt‬را بهصورت زیر ایجاد کنید‪:‬‬


‫‪#vim /usr/src/passdisa.txt‬‬
‫‪1234|LocalSets‬‬
‫‪1212|feautres‬‬

‫اینجا قسمت اول‪ ،‬پسورد و قسمت دوم‪ ،‬نام کانتکست است‪.‬‬


‫اگر بخواهید بدون درنظرگرفتن پســورد‪ ،‬از دســتور ‪ DISA‬اســتفاده کنید‪ ،‬باید بهصورت زیر از »‪no-‬‬
‫‪ «password‬استفاده کنید‪.‬‬
‫)‪same => n,DISA(no-password,LocalSets‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪562‬‬

‫دستور ‪FollowMe‬‬
‫همانطورکه از نام آن پیداســت‪ FollowMe ،‬برای پیگیری افراد در سیستم تلفنی استریسک بهکار میرود‪.‬‬
‫بــرای مثال فرضکنید بخواهیم با یک کاربر در سیســتم تماس بگیریم‪ .‬چنانچه کاربر تماس خود را پاســخ‬
‫ندهد‪ ،‬میتوان ازطریق دستور ‪ FollowMe‬با او تماس برقرار کرد‪ .‬برای درک بهتر‪ ،‬مثال زیر را ببینید‪.‬‬
‫مثال( ابتدا فایل ‪ FollowMe.conf‬را از مسیر زیر باز و تغییرات زیر را در انتهای فایل وارد کنید‪.‬‬
‫‪# vim /etc/asterisk/followme.conf‬‬
‫]‪[100‬‬
‫‪context=followme‬‬
‫‪number=100,20‬‬
‫‪number=Phone_1,20‬‬
‫‪number=09151176713,20‬‬

‫سپس در برنامه استریسک این تغییرات را انجام دهید‪.‬‬


‫‪;extensions.conf‬‬
‫]‪[locals‬‬
‫)‪exten => 100,1,FollowMe(100‬‬

‫]‪[followme‬‬
‫)‪exten => 100,1,Dial(SIP/100‬‬
‫)‪exten => Phone_1,1,Dial(SIP/Phone_1‬‬
‫)}‪exten => _0X.,1,Dial(DAHDI/g0/${EXTEN‬‬

‫اکنون چنانچه دستور زیر را اجرا کنید‪:‬‬


‫‪CLI>console dial 100@locals‬‬

‫در این صورت‪ ،‬دستور ‪ FollowMe‬اجرا میشود و شمارههای تعیینشده بر اساس اولویت‪ ،‬به ترتیب شروع‬
‫به زنگ خوردن میکنند‪.‬‬

‫دستورات مربوط به کنترل‌های شرطی و ‪ Timeout‬در استریسک‬


‫دستور ‪While‬‬
‫با این دســتور مجموعهای از برنامهها تا زمان درســت بودن یک شرط‪ ،‬اجرا میشوند‪ .‬این دستور معموالً در‬
‫کنار دســتورات ‪ EndWhile‬یا ‪ ContinueWhile‬استفاده میشود‪ .‬برنامه ساده زیر استفاده از هر دو روش را‬
‫نشان میدهد‪:‬‬
‫]‪[appendix‬‬
‫)(‪exten => 1011,1,Answer‬‬
‫)‪same => n,Set(i=1‬‬
‫)]‪same => n,While($[${i} < 5‬‬
‫)}‪same => n,SayNumber(${i‬‬
‫)]‪same => n,Set(i=$[${i} + 1‬‬
‫‪563‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫)(‪same => n,EndWhile‬‬

‫)(‪exten => 1012,1,Answer‬‬


‫)‪same => n,Set(i=1‬‬
‫)]‪same => n,While($[${i} < 5‬‬
‫)}‪same => n,SayNumber(${i‬‬
‫)]‪same => n,Set(i=$[${i} + 1‬‬
‫)(‪same => n,ContinueWhile‬‬

‫چنانچه قصد داشــته باشــید از حلقه خارج شوید‪ ،‬باید از دســتور ‪ ExitWhile‬استفاده کنید‪ .‬این دستور مانند‬
‫استفاده از ‪ Break‬در برنامهنویسی است‪.‬‬

‫دستور ‪Exec‬‬
‫این دســتور کاربرد بســیار زیادی در برنامهنویســی ‪ AGI‬دارد‪ .‬بهوسیله این دســتور میتوان کلیه دستورات‬
‫استریسک را اجرا کرد‪ .‬شاید استفاده از آن در برنامهنویسی استریسک کاربرد زیادی نداشته باشد ولی از آن‬
‫در برنامهنویسی ‪ AGI‬به وفور استفاده میشود‪ .‬برای مثال برنامه زیر را ببینید‪:‬‬
‫)(‪exten => 1013,1,Answer‬‬
‫))‪same => n,Set(app=Playback(demo-congrats‬‬
‫)}‪same => n,Exec(${app‬‬

‫برای مثال فرض کنید بخواهیم برنامه باال را بهصورت ‪ AGI‬داشته باشیم‪.‬‬
‫‪#!/usr/bin/php -q‬‬
‫‪<?php‬‬
‫;)'‪require_once('phpagi.php‬‬
‫;)‪error_reporting(E_ALL‬‬

‫;)(‪$agi = new AGI‬‬


‫;)(‪$agi->answer‬‬
‫;)"‪$agi->Exec("Playback","demo-congrats‬‬
‫;)(‪$agi->hangup‬‬
‫>?‬

‫ازآنجاکه دســتورات موجود در برنامهنویســی ‪ AGI‬محدودند‪ ،‬میتوان از کلیه دستورات استریسک به این‬
‫شکل در برنامهنویسی ‪ AGI‬استفاده کرد‪.‬‬

‫دستور ‪TryExec‬‬
‫این دســتور همانند دســتور ‪ Exec‬اســت‪ ،‬با این تفاوت که اگر خطایی در اجرای برنامه اتفاق بیفتد‪ ،‬تماس‬
‫قطع نخواهد شــد و دستورات بعدی اجرا میشــوند‪ .‬بهوسیله متغیر }‪ ${TRYSTATUS‬میتوان وضعیت آن‬
‫را بررسی نمود‪.‬‬
‫• ‪ :Success‬در این حالت مقدار متغیر برابر ‪ 0‬خواهد بود‪.‬‬
‫• ‪ :Failed‬در این حالت مقدار متغیر برابر ‪ 1‬خواهد بود‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪564‬‬

‫دستورات ‪ ExecIf‬و ‪ExecIfTime‬‬


‫این دســتورات مانند دســتور ‪ Exec‬است‪ ،‬با این تفاوت که شــرطی را بررسی میکند و درصورتیکه مقدار‬
‫»‪ «True‬باشد‪ ،‬اجرا میشود‪ .‬برای نمونه برنامه زیر را در نظر بگیرید‪.‬‬ ‫شرط مورد نظر‬
‫)(‪exten => 1014,1,Answer‬‬
‫))‪same => n,ExecIf($[${CALLERID(num)} = 100]?SayAlpha(Hello‬‬
‫)‪same => n,SayAlpha(World‬‬

‫)(‪exten => 1015,1,Answer‬‬


‫))‪same => n,ExecIfTime(9:00-17:00,mon-fri,*,*?SayAplha(YES‬‬
‫)‪same => n,SayAlpha(NO‬‬

‫دستورات مربوط به فراخوانی ماکروها در استریسک‬


‫دستور ‪Macro‬‬
‫همانطور که در فصل هشــتم )برنامهنویسی پیشرفته در استریسک( توضیح دادهایم‪ ،‬بهوسیله این دستور یک‬
‫ماکرو فراخوانی میشود‪ .‬برای اطالعات بیشتر به این فصل مراجعه نمایید‪.‬‬

‫دستور ‪MacroExclusive‬‬
‫این دستور همانند دستور قبل است‪ ،‬با این تفاوت که در هر لحظه تنها یک نمونه از آن قابل اجراست‪ .‬برای‬
‫مثال برنامه زیر را در نظر بگیرید‪.‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)(‪exten => 142,1,NoOp‬‬
‫)‪same => n,MacroExclusive(lab‬‬
‫)(‪same => n,Hangup‬‬

‫]‪[macro-lab‬‬
‫)(‪exten => s,1,NoOp‬‬
‫)}‪same => n,NoOP(${EXTEN‬‬
‫)} ‪same => n,NoOp(${MACRO_ CONTEXT‬‬
‫)}‪same => n,NoOp(${MACRO_EXTEN‬‬
‫)}‪same => n,NoOp(${MACRO_PRIORITY‬‬

‫در این شرایط در هر لحظه تنها یک تماس میتواند دستورات داخل ماکرو را اجرا کند‪.‬‬

‫دستور ‪MacroIf‬‬
‫بهوســیله این دستور‪ ،‬ابتدا عبارتی محاسبه میشــود و سپس در صورتی که مقدار آن »‪ «True‬ارزیابی شود‪،‬‬
‫ماکرو فراخوانی میشود‪ .‬نحوهی استفاده از این دستور بهصورت زیر است‪:‬‬
‫)]]‪MacroIf(expression?macronameA[,argA1][:macronameB[,argB1‬‬
‫‪565‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫دستورات مربوط به ‪ CDR‬در استریسک‬


‫دستور ‪ForkCDR‬‬
‫بهوسیله این دستور در زمان اجرا‪ ،‬یک گزارش ‪ CDR‬جدید در جداول درج میشود‪ .‬برای مثال فرض کنید‬
‫در زمان اجرای برنامه خواســته باشیم یک تماس جدید ایجاد کنیم‪ .‬بهوسیله این دستور یک گزارش جدید‬
‫‪ CDR‬از زمان اجرای دستور ایجاد میشود‪.‬‬

‫دستور ‪ResetCDR‬‬
‫بهوســیله اجرای این دستور‪ ،‬مقادیر فعلی ‪ CDR‬همگی ریست میشــوند‪ .‬میتوان قبل از ریستشدن ‪CDR‬‬
‫ابتدا آن را ذخیره و سپس ریست کرد‪ .‬برای این منظور از آپشن ‪ w‬استفاده کنید‪.‬‬

‫دستور ‪NoCDR‬‬
‫بهوسیله اجرای این دستور‪ ،‬به استریسک اعالم میکنیم که گزارش ‪ CDR‬را برای تماس فعلی ایجاد نکند‪.‬‬

‫دستورات مربوط به اجرای فایل‌های صوتی و موزیک انتظار در استریسک‬


‫دستور ‪SayAlpha‬‬
‫بهوســیله این دســتور‪ ،‬رشته واردشــده‪ ،‬بهصورت آرگومان و حرفبهحرف پخش میشود‪ .‬به عبارت دیگر‬
‫رشــته واردشــده بهصورت آرگومان ‪ Spell‬خواهد بود‪ .‬برای مثال )‪ SayAlpha(hello‬بهصورت کاراکتر به‬
‫کاراکتر )‪ (h,e,l,l,o‬پخش میشود‪.‬‬
‫)‪exten => 1017,1,SayAlpha(hello‬‬

‫دستور ‪SayDigits‬‬
‫بهوســیله ایــن دســتور‪ ،‬عدد وارد شــده‪ ،‬بهصــورت آرگومان و رقــم به رقم پخش میشــود‪ .‬بــرای مثال‬
‫)‪ ۱۲۳)SayDigits‬بهصورت )یک دو سه( پخش خواهد شد‪.‬‬
‫)‪exten => 1018,1,SayDigits(123‬‬

‫دستور ‪SayNumber‬‬
‫بهوســیله این دستور‪ ،‬عدد وارد شــده‪ ،‬بهصورت آرگومان و کامل پخش میشــود‪ .‬برای مثال )‪SayNum-‬‬
‫‪ ber(123‬بهصورت )صد و بیست و سه( پخش میشود‪.‬‬
‫‪; Say in English:‬‬
‫)‪exten => 1019,1,Set(LANGUAGE=en‬‬
‫)‪same => n,SayNumber(1234‬‬
‫"‪; "one - thousand - two - hundred - and - thirty - four‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪566‬‬

‫‪; Say in Norwegian:‬‬


‫)‪exten => 1020,1,Set(LANGUAGE=no‬‬
‫)‪same => n,SayNumber(1234‬‬

‫دستور ‪SayPhonetic‬‬
‫بهوســیله این دســتور‪ ،‬رشــته واردشــده‪ ،‬بهصورت آرگومان و کلمــهی کامل پخش میشــود‪ .‬برای مثال‬
‫)‪ SayPhonetic(hello‬بهصورت کلمهی کامل )‪ (hello‬پخش خواهد شد‪.‬‬
‫)‪exten => 1021,1,Set(LANGUAGE=en‬‬
‫)‪same => n,SayPhonetic(asterisk‬‬

‫)‪exten => 1022,1,Set(LANGUAGE=de‬‬


‫)‪same => n,SayPhonetic(asterisk‬‬

‫دستور ‪MusicOnHold‬‬
‫بهوسیله این دستور‪ ،‬موزیک انتظار برای کاربر پخش میشود‪.‬‬
‫)(‪exten => 1023,1,Answer‬‬
‫)‪same => n,Playback(tt-allbusy‬‬
‫)‪same => n,MusicOnHold(default‬‬
‫)‪same => n,Goto(2‬‬

‫دستورات مربوط به ‪ DTMF‬و خواندن اطالعات‬


‫دستور ‪Read‬‬
‫بهوسیله این دستور‪ ،‬میتوان از کاربر داده )‪ (DTMF‬دریافت و بر اساس آن برنامههایی را اجرا نمود‪ .‬کاربرد‬
‫این دســتور عمدتا در طراحی سیستمهای ‪ IVR‬است‪ .‬البته توصیه میشــود برای نوشتن سیستمهای ‪ IVR‬از‬
‫برنامهنویسی ‪ AGI‬استفاده شود‪ .‬فرمت استفاده از این دستور بهصورت زیر است‪:‬‬
‫‪CLI> core show application Read‬‬
‫]‪[Syntax‬‬
‫)]]]]]‪Read(variable[,filename[&filename2[&...]][,maxdigits[,options[,attempts[,timeout‬‬

‫برای آشنایی با این دستور‪ ،‬برنامه زیر را در نظر بگیرید‪.‬‬


‫)(‪exten => 1024,1,Answer‬‬
‫)‪same => n,Read(VOTE,${AUDIOFILE},1,,,5‬‬
‫)}‪same => n,SayNumber(${VOTE‬‬
‫)‪same => n,Goto(InsertData,1‬‬

‫در این مثال‪ ،‬با اجرای دســتور ‪ ،Read‬ابتدا فایل صوتی تعیینشــده در متغیر ‪ AUDIOFILE‬پخش میشود و‬
‫همزمــان منتظر دریافت اطالعات )حداکثر ‪ ۱‬رقم( از طرف کاربر میماند‪ .‬بعد از اتمام فایل صوتی حداکثر‬
‫‪ ۵‬ثانیه منتظر میماند تا کاربر اطالعات را وارد کند‪ .‬اطالعات وارد شده در متغیر ‪ VOTE‬ذخیره میشود‪.‬‬
‫‪567‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫دستور ‪SendDTMF‬‬
‫بهوسیله این دستور میتوان دادههایی را بهصورت ‪ DTMF‬در کانال‪ ،‬ایجاد و ارسال کرد‪:‬‬
‫‪CLI> core show application SendDTMF‬‬
‫]‪[Syntax‬‬
‫)]]]‪SendDTMF(digits[,timeout_ms[,duration_ms[,channel‬‬

‫برای مثال برنامه زیر‪ ،‬دادههای ‪ ۵۶84‬را بهصورت ‪ DTMF‬ارسال میکند‪:‬‬


‫)(‪exten => 1025,1,Answer‬‬
‫)‪same => n,SendDTMF(5684,200‬‬

‫دستورات مربوط به مانیتورینگ و ضبط کردن‬


‫دستور ‪ChanSpy‬‬
‫بهوسیله این دستور میتوان قابلیت شنود را برای کانالهای فعال در استریسک ایجاد کرد‪ .‬فرمت استفاده از‬
‫این دستور در استریسک بهصورت زیر است‪:‬‬
‫‪CLI> core show application ChanSpy‬‬
‫]‪[Syntax‬‬
‫)]‪ChanSpy([chanprefix][,options‬‬

‫آپشنهایی که این دستور در اختیار ما میگذارد بسیار مهم هستند‪ .‬این آپشنها عبارتند از‪:‬‬

‫‪ :b‬فقــط کانالهایی که ‪ bridge‬شدهباشــند را در نظر میگیرد‪ .‬به عبارت دیگــر فقط تماسهایی که هر دو‬
‫طرف در حال مکالمه باشند‪ ،‬در نظر گرفتهمیشود‪.‬‬

‫‪ :q‬در این حالت بوق ‪ beep‬در زمان شروع شنود پخش نخواهد شد‪.‬‬

‫‪ : g‬اگــر این پارامتر فعال باشــد‪ ،‬هنگام جابجا شــدن کانالها برای شــنود‪ ،‬هیچگونه پیــام یا آالرمی پخش‬
‫نمیشود‪.‬‬

‫‪ : r‬این آپشن‪ session ،‬ایجاد شده برای شنود را ضبط میکند‪.‬‬

‫‪ : w‬در این حالت فردی که در حال شنود است‪ ،‬میتواند با فردی که در حال مکالمه است‪ ،‬صحبت کند ولی‬
‫‪ remote user‬صدای او را نخواهد شنید‪ .‬میتوان از این قابلیت برای مشاورهدادن استفاده کرد‪.‬‬

‫البته این دســتور پارامترهای زیادی دارد که برای آشنایی بیشتر با آنها میتوانید دستور باال را در محیط‬
‫کامندالین استریسک اجرا کنید‪.‬‬
‫)‪exten => 1026,1,Read(SPYNUM,extension‬‬
‫)‪same => n,ChanSpy(SIP/${SPYNUM},q‬‬

‫هنگام شنود‪ ،‬میتوان برای باال بردن صدا‪ ،‬دکمه ‪ #‬و برای شنود سایر کانالها دکمه * را ارسال کرد‪.‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪568‬‬

‫دستور ‪ExtenSpy‬‬
‫بهوســیله این دستور میتوان یک اکستنشن خاص را مشخص و شنود نمود‪ .‬البته مثالی که در باال آمد‪ ،‬دقیقا‬
‫همین سناریو را انجام میدهد‪.‬‬

‫دستور ‪MixMonitor‬‬
‫بهوســیله این دســتور میتوان مکالمات مورد نظر را ضبط کرد‪ .‬فرمت اســتفاده از این دستور بهصورت زیر‬
‫است‪:‬‬
‫‪CLI> core show application MixMonitor‬‬
‫]‪[Syntax‬‬
‫)]]‪MixMonitor(filename.extension[,options[,command‬‬

‫آپشنهای قابل استفاده در این دستور بهصورت زیرند‪:‬‬


‫آپشــن ‪ b‬در این دستور مشــخص میکند که ضبط مکالمه زمانی شروع شود که کانالها با هم ‪bridge‬‬
‫شــده باشــند و تماس برقرار باشد‪ .‬استفاده از این آپشن‪ ،‬بســیار کاربردی است‪ .‬برای مثال وقتی فردی زنگ‬
‫میزند و وارد صف میشود‪ ،‬لزومی ندارد تا زمانی که اپراتوری تماس او را پاسخ نداده‪ ،‬تماسش ضبط شود‪.‬‬
‫)‪exten => 1027,1,NoOp(Recording‬‬
‫)‪same => n,MixMonitor(Phone_1.wav,b‬‬
‫)‪same => n,Dial(SIP/Phone_1,40‬‬
‫)(‪same => n,Hangup‬‬

‫اســتفاده از فرمت ‪ wav‬در ضبط مکالمات‪ ،‬باعث افزایش فضای مصرفی میشــود‪ .‬بهتر اســت پس از اتمام‬
‫‪ wav‬به ‪mp۳‬‬ ‫ضبط مکالمات‪ ،‬آن را به فرمت ‪ mp۳‬تبدیل کنید‪ .‬روشهای زیادی برای تبدیل فایل صوتی‬
‫وجود دارد‪ .‬اینجا از دستور ساده ‪ lame‬استفاده میکنیم‪ .‬برای نصب آن ابتدا باید دستور زیر را در لینوکس‬
‫اجرا کنید‪:‬‬
‫‪# apt-get install lame‬‬

‫پس از نصب‪ ،‬فرمت استفاده از دستور بهصورت زیر خواهد بود‪:‬‬


‫‪#lame --help‬‬
‫]‪usage: lame [options] <infile> [outfile‬‬

‫برای مثال فرض کنید بخواهیم یک فایل صوتی با پسوند ‪ wav‬را به فایل ‪ mp۳‬تبدیل کنیم‪:‬‬
‫‪#lame -f file.wav file.mp3‬‬

‫برای اســتفاده از این دســتور در استریســک میتوان بهصورت زیر‪ ،‬پس از تمام شدن مکالمه‪ ،‬این دستور را‬
‫اجرا کرد‪:‬‬
‫‪;extensions.conf‬‬
‫]‪[LocalSets‬‬
‫)‪exten => h,1,NoOp(Hangup calls, Convert wav audio to mp3 audio‬‬
‫‪569‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫)‪same => n,Set(PATH_AUDIO=/var/spool/asterisk/monitor/‬‬


‫)}‪same => n,Set(FILE_AUDIO=${CHANEEL‬‬
‫_‪same => n,System(lame –f ${PATH_AUDIO}${FILE_AUDIO}.wav ${PATH_AUDIO}${FILE‬‬
‫)‪AUDIO}.mp3‬‬
‫)‪same => n,NoOp(Delete origin File Audio‬‬
‫)‪same => n,System(rm ${PATH_AUDIO}${FILE_AUDIO}.wav‬‬

‫دستور ‪Record‬‬
‫بهوســیله این دســتور میتــوان صدا را ازطریق یــک کانال ضبط کــرد‪ .‬برای مثال با مشــخص کردن یک‬
‫اکستنشــن‪ ،‬صدا شروع به ضبط شدن میکند‪ .‬معموالً از این دســتور برای ضبط اعالنها و پیامها در سیستم‬
‫تلفنی استریسک استفاده میشود‪ .‬این دستور بیشتر شبیه به یک رکوردر عمل میکند‪ .‬فرمت استفاده از این‬
‫زیر است‪:‬‬ ‫دستور بهصورت‬
‫‪CLI> core show application Record‬‬
‫]‪[Syntax‬‬
‫)]]]‪Record(filename.format[,silence[,maxduration[,options‬‬

‫برای مثال برنامه زیر را در نظر بگیرید‪:‬‬


‫)(‪exten => 1028,1,Answer‬‬
‫)‪same => n,Record(en/welcome.gsm‬‬
‫)‪same => n,Wait(1‬‬
‫)‪same => n,Playback(welcome‬‬
‫)(‪same => n,Hangup‬‬

‫نکته مهم هنگام استفاده از دستور ‪ Record‬این است که باید بعد از اتمام ضبط صدا‪ ،‬دکمه ‪ #‬را بزنید‪.‬‬

‫سایر دستورات کاربردی در استریسک‬


‫دستور ‪Authenticate‬‬
‫بهوســیله این دستور میتوان کاربر را وادار کرد‪ ،‬رمز عبور خود را وارد کند و برای ادامه اجرای دستورات‪،‬‬
‫از سیستم تایید بگیرد‪ .‬البته این کار را میتوان با نوشتن یک برنامه ساده انجام داد‪ ،‬ولی استفاده از این دستور‬
‫میتواند بسیار کاربردی باشد‪ .‬فرمت استفاده از این دستور بهصورت زیر است‪:‬‬

‫‪CLI> core show application Authenticate‬‬


‫]‪[Syntax‬‬
‫)]]]‪Authenticate(password[,options[,maxdigits[,prompt‬‬

‫برای مثال فرض کنید برای اســتفاده از دســتور ‪ ChanSpy‬نیاز به رمز عبور داشته باشیم‪ .‬برنامه زیر را در نظر‬
‫بگیرید‪:‬‬
‫)‪exten => 1025,1,Authenticate(1234‬‬
‫)‪same => n,Read(SPYNUM,extension‬‬
‫)‪same => n,ChanSpy(SIP/${SPYNUM},q‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ ‫‪570‬‬

‫دستور ‪VMAuthenticate‬‬
‫این دســتور همانند دســتور ‪ Authentication‬اســت‪ ،‬با این تفاوت که عملیات اعتبارســنجی را بر اســاس‬
‫‪ VoiceMail‬انجام میدهد‪ .‬فرمت استفاده از این دستور بهصورت زیر است‪:‬‬
‫‪CLI> core show application VMAuthenticate‬‬
‫]‪[Synopsis‬‬
‫‪Authenticate with Voicemail passwords.‬‬

‫برای مثال برنامه زیر برای اعتبارسنجی‪ ،‬از اطالعات ‪) VoiceMail‬رمزعبور( استفاده میکند‪:‬‬
‫]‪[Authentication‬‬
‫)‪exten => 1026,1,Verbose(2,Attempting to authenticate caller with voicemail creds.‬‬
‫)‪same => n,Playback(silence/1‬‬
‫)‪same => n,VMAuthenticate(@default‬‬
‫)}‪same => n,SayDigits(${AUTH_MAILBOX‬‬
‫)‪same => n,Verbose(2,The caller was authenticated if we execute this line.‬‬

‫اینجا اگر هر پســوردی از ‪ VoiceMail‬وارد کنید‪ ،‬درصورتیکه درســت باشد‪ ،‬آن را تأیید میکند‪ .‬در این‬
‫صورت بهوســیله متغیر } ‪ ${AUTH_MAILBOX‬میتــوان فهمید که از اطالعات کدام ‪ VoiceMail‬برای‬
‫اعتبارسنجی استفاده شده است‪:‬‬
‫)‪same => n,VMAuthenticate(${EXTEN}@default‬‬

‫اینجا پسورد ‪ VoiceMail=1026‬برای اعتبارسنجی در نظر گرفته خواهد شد‪.‬‬

‫دستور ‪System‬‬
‫گاهی الزم اســت برخی دستورات لینوکســی را در برنامهنویسی استریسک استفاده کنیم‪ .‬در این صورت از‬
‫دستور ‪ System‬استفاده میکنیم‪ .‬فرمت بهکارگیری این دستور بهصورت زیر است‪:‬‬
‫‪CLI> core show application System‬‬
‫]‪[Syntax‬‬
‫)‪System(command‬‬

‫همانطورکه مالحظه میکنید‪ ،‬باید کامند مورد نظر خود را بهصورت آرگومان برای دســتور ارســال کنید‪.‬‬
‫بــرای مثال فرض کنید بخواهیم برخی از اطالعات تمــاس را در فایلی ذخیره کنیم‪ .‬در این صورت میتوان‬
‫از دستور زیر استفاده نمود‪:‬‬
‫)(‪exten => s,1,Answer‬‬
‫‪same => n,System(echo '${DATETIME} - ${CALLERID} - ${CHANNEL}' >> /var/log/asterisk/‬‬
‫)‪myinfo‬‬

‫یا به عنوان یک مثال کاربردی‪ ،‬گاهی نیاز داریم که کانالها بعد از اتمام تماس‪ ،‬آزاد شــوند‪ .‬این برنامه‬
‫غالبا در مواقعی اســتفاده میشــود که کانالهای ‪ FXO‬داشته باشیم یا از گیتویهای ‪ FXO‬استفاده کنیم و‬
‫نیاز داریم که کانالها بعد از اســتفاده‪ ،‬حتما آزاد شــوند‪ .‬ازآنجاکه این دستورات باید در زمان خاتمه تماس‬
‫اجرا شوند‪ ،‬آنها را در اکستنشن ‪ h‬در برنامه خود قرار میدهیم‪.‬‬
‫‪571‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫)'})‪exten => h,1,System(asterisk -rx 'hangup request ${CDR(dstchannel‬‬


‫)'})‪same => n,System(asterisk -rx 'hangup request ${CDR(channel‬‬

‫معرفی توابع مهم و پرکاربرد در استریسک‬


‫تا اینجا دســتورات پرکاربرد در برنامهنویسی استریســک توضیح داده شد‪ .‬در ادامه مهمترین توابع پرکاربرد‬
‫استریسک را معرفی خواهیم کرد‪.‬‬

‫تابع ‪ARRAY‬‬
‫بهوســیله این تابع میتوان بهصورت همزمان‪ ،‬چند متغییــر را مقدار دهی کرد‪ .‬برای مثال برنامه زیررا در نظر‬
‫بگیرید‪.‬‬
‫)‪exten => 2000,1,Set(VAR1=1‬‬
‫)‪same => n,Set(VAR2=2‬‬
‫)‪same => n,Set(VAR3=3‬‬
‫)‪same => n,Set(VAR4=4‬‬

‫میتوان از تابع ‪ ARRAY‬بهصورت زیر استفاده کرد‪:‬‬


‫)‪exten => 2000,1,Set(ARRAY(VAR1,VAR2,VAR3)=1,2,3‬‬

‫تابع ‪ BASE64_ENCODE‬و ‪BASE64_DECODE‬‬


‫بهوسیله این تابع‪ ،‬میتوان یک رشته را رمزنگاری و سپس دوباره آن را رمزگشایی کرد‪.‬‬
‫)})"‪exten => 2001,1,Set(foo=${BASE64_ENCODE("Hello, World‬‬
‫)})}‪same => n, NoOp(${BASE64_DECODE(${foo‬‬

‫تابع ‪CALLERID‬‬
‫بهوســیله این تابع‪ ،‬میتوان اطالعاتی درباره کالرآیدی شخصی که تماس گرفته است‪ ،‬بهدست آورد‪ .‬برنامه‬
‫زیر کاربردهایی از این تابع را نشان میدهد‪.‬‬
‫)‪exten => 2002,1,NoOp(Info about caller‬‬
‫)})‪same => n,NoOp(name=${CALLERID(name‬‬
‫)})‪same => n,NoOp(num=${CALLERID(num‬‬
‫)})‪same => n,NoOp(all=${CALLERID(all‬‬
‫)})‪same => n,NoOp(dnid=${CALLERID(dnid‬‬

‫تابع ‪CDR‬‬
‫بهوســیله این تابع میتوان به کلیه فیلدهای موجود در ماژول ‪ CDR‬دسترســی پیدا کرد‪ .‬برنامه زیر‪ ،‬کاربرد‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 572

.‫این تابع را نمایش میدهد‬


exten => 2003,1,NoOp(CDR fileds)
same => n,NoOp(clid=${CDR(clid)})
same => n,NoOp(src=${CDR(src)})
same => n,NoOp(dst=${CDR(dst)})
same => n,NoOp(dcontext=${CDR(dcontext)})
same => n,NoOp(channel=${CDR(channel)})
same => n,NoOp(dstchannel=${CDR(dstchannel)})
same => n,NoOp(lastapp=${CDR(lastapp)})
same => n,NoOp(lastdata=${CDR(lastdata)})
same => n,NoOp(start=${CDR(start)})
same => n,NoOp(answer=${CDR(answer)})
same => n,NoOp(end=${CDR(end)})
same => n,NoOp(duration=${CDR(duration)})
same => n,NoOp(billsec=${CDR(billsec)})
same => n,NoOp(disposition=${CDR(disposition)})
same => n,NoOp(amaflags=${CDR(amaflags)})
same => n,NoOp(uniqueid=${CDR(uniqueid)})

CURL ‫تابع‬
‫ برنامه زیر‬،‫ برای نمونه‬.‫بهوســیله این تابع میتوان یک صفحه ســایت را باز و اطالعاتی از آن استخراج کرد‬
.‫را در نظر بگیرید‬
exten => 2004,1,Set(CID=${CALLERID(num)})
same => n,Set(foo=${CURL(http://example.com/page.php?cid=CID)})

CUT ‫تابع‬
‫ فرمت استفاده از این تابع‬.‫ از هم جدا کرد‬،‫بهوســیله این تابع میتوان یک رشــته را بر اســاس یک کاراکتر‬
.‫بهصورت زیر است‬
CLI> core show function CUT
[Syntax]
CUT(varname,char-delim,range-spec)

‫ جدا میشــود و دسترسی به بخش اول یا ســایر بخشها ازطریق‬char-delim ‫ رشــته بر اســاس‬،‫در این تابع‬
.‫ برقرار میشود‬range-spec
.‫برای نمونه برنامه زیر را در نظر بگیرید‬. .‫این تابع کاربردهای فراوانی دارد‬
exten => 2006,1,NoOp()
same => n,NoOp(TOPOLOGY=${CUT(CHANNEL,/,1)})
same => n,NoOp(OPERATOR=${CUT(TOPOLOGY,-,1)})

ENV ‫تابع‬
.‫بهوسیله این تابع میتوان به متغیرهای محیطی در لینوکس دسترسی پیدا کرد‬
‫‪573‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫‪;read HOME‬‬
‫)})‪exten => 2007,1,Set(foo=${ENV(HOME‬‬

‫‪; set HOME‬‬


‫)‪exten => 2007,1,Set(ENV(HOME)=/usr/src/asterisk-source‬‬

‫تابع ‪EXIST‬‬
‫بهوســیله این تابع میتوان بررســی نمود که آیا متغییری در استریسک تعریف شده است یا نه‪ .‬خروجی این‬
‫تابع بهصورت "‪ "True‬و یا "‪ "False‬در نظر گرفته میشود‪.‬‬
‫)‪exten => 2007,1,Set(VAR1=test‬‬
‫)})}‪same => n,Set(foo=${EXISTS(${VAR1‬‬
‫)})}‪same => n,Set(foo=${EXISTS(${VAR2‬‬

‫تابع ‪ GROUP‬و ‪GROUP_COUNT‬‬


‫بهوســیله این دو تابع میتوان تعداد تماسهای خروجی یا ورودی به سیستم تلفتی استریسک را کنترل کرد‪.‬‬
‫برای نمونه برنامه زیر را برای ایجاد تماس خروجی از روی یک ترانک در نظر بگیرید‪ .‬در این مثال ظرفیت‬
‫ترانک‪ ،‬پنج تماس بهطور همزمان است‪.‬‬
‫)‪exten => _00X.,1,Set(GROUP(outbound)=myprovider‬‬
‫)})‪same => n,Set(COUNT=${GROUP_COUNT(myprovider@outbound‬‬
‫)‪same => n,NoOp(There are ${COUNT} calls for myprovider.‬‬
‫)‪same => n,GotoIf($[${COUNT} > 5]?denied:continue‬‬
‫)‪same => n(denied),NoOp(There are too many calls up already. Hang up.‬‬
‫)(‪same => n,Hangup‬‬
‫)}‪same => n(continue),GoSub(callmyprovider,${EXTEN},1‬‬

‫در نسخههای جدید استریسک‪ ،‬بهجای پارامتر ‪ call-limit‬در پیکربندی فایل ‪ ،sip.conf‬استفاده از این توابع‬
‫توصیه شده است‪ .‬میتوانید بهراحتی تعداد تماسهای همزمان برای تماسهای ورودی و خروجی به سیستم‬
‫تلفنی استریسک را کنترل و مدیریت نمایید‪.‬‬

‫تابع ‪IF‬‬
‫بهوسیله این تابع میتوان شرطهایی در برنامه استریسک برقرار کرد‪.‬‬
‫‪; If ${VAR}=123456, return yes, otherwise return no:‬‬
‫)})‪exten => 123,1,Set(foo=${IF($[ ${VAR} = 123456]?yes:no‬‬

‫تابع ‪ISNULL‬‬
‫بهوسیله این تابع میتوان بررسی کرد که آیا مقدار یک متغیر ‪ Null‬است یا نه‪.‬‬
‫)(‪exten => 2009,1,NoOp‬‬
‫)})‪same => n,Set(COUNT=${DB(test/count‬‬
‫مرجع آموزش ویپ با سافت‌سوئیچ استریسک‬ 574

same => n,GotoIf($[${ISNULL(${COUNT})}]?:continue)


same => n,Set(DB(test/count)=1)
same => n,Goto(1)
same => n(continue),NoOp()

IFTIME ‫تابع‬
.‫ خروجی دستور متفاوت خواهد بود‬،‫بهوسیله این تابع بر اساس زمان سیستم‬
exten => 2010,1,Set(foo=${IFTIME(08:00-18:00|mon|1-15|dec?5:0)})
exten => 2010,1,Set(foo=${IFTIME(*|sat-sun|*|*?5:0)})

LEN ‫تابع‬
.‫ طول رشتهی وارد شده به تابع را بر میگرداند‬،‫این تابع‬
exten => 2011,1,Set(TEST="Hello, Wolrd")
same => n,Set(foo=${LEN(${TEST})})
same => n,NoOp(${foo})

RAND ‫تابع‬
.‫این تابع یک عدد تصادفی بین دو عدد تعیینشده را انتخاب میکند‬
; Game of chance:
exten => 2012,1,GotoIf($[${RAND(0,100)} < 25]?won:lost)
exten => won,1,Playback(won)
same => n,Goto(123,1)
exten => lost,1,Playback(lost)
same => n,Goto(123,1)

SIP_HEADER ‫تابع‬
‫ یک پروتکل متنی اســت و از فیلدهایی تشکیل‬SIP ‫پیشتر نیز توضیح داده شــد که پروتکل ســیگنالینگ‬
.‫شده است‬
:‫ زیر را در نظر بگیرید‬INVITE ‫برای نمونه پیام‬
INVITE sip:2013@192.168.141.128:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.141.1:53138;branch=z9hG4bK-d8754z-0d576a0e86274001-1---
d8754z-;rport
Max-Forwards: 70
Contact: <sip:100@192.168.141.1:53138;rinstance=bd162d0f928961cf>
To: <sip:2013@192.168.141.128:5060>
From: "100"<sip:100@192.168.141.128:5060>;tag=be129c0a
Call-ID: ZTE3ZGQ5NWQ4NGYyYTNiYzRmZDczMzA5ODhkNDE4ZjU.
CSeq: 1 INVITE
‫‪575‬‬ ‫آشــنایی با دستورات و توابع مهم و پرکاربرد در استریسک‬

‫‪Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REGISTER, SUBSCRIBE, NOTIFY, REFER, INFO,‬‬
‫‪MESSAGE‬‬
‫‪Content-Type: application/sdp‬‬
‫‪Supported: replaces‬‬
‫‪User-Agent: 3CXPhone 6.0.20943.0‬‬
‫‪Content-Length: 407‬‬

‫اکنون چنانچه بخواهیم مقدار پارامتر ‪ To‬را در برنامه استریسک خود داشته باشیم‪.‬‬
‫)})‪exten => 2013,1,Set(DN=${SIP_HEADER(TO‬‬

‫تابع ‪REGEX‬‬
‫بهوســیله این تابع میتوان از ‪ Reqular Experssion‬ها در استریســک اســتفاده کرد‪ .‬فرمت اســتفاده از این‬
‫دستور بهصورت زیر است‪.‬‬
‫‪CLI> core show function REGEX‬‬
‫]‪[Syntax‬‬
‫)‪REGEX("regular expression" string‬‬

‫برای مثال برنامه زیر را در نظر بگیرید‪.‬‬


‫)})‪exten => 2014,1,Set(foo=${REGEX("[abc][0-9]" b3‬‬

‫خروجی تابع در برنامه‪ "True" ،‬است‪.‬‬

‫نتیجه‌گیری‬
‫مسلما توضیح در خصوص همه دستورات و توابع در استریسک بسیار وقتگیر است‪ .‬در این بخش به معرفی‬
‫دستورات و توابع پرکاربرد در برنامهنویسی استریسک پرداختیم؛ با وجود این‪ ،‬استفاده از راهنمای استریسک‬
‫برای آشــنایی بیشتر با این دستورات و توابع‪ ،‬امری ضروری است‪ .‬در واقع هدف اصلی این فصل چگونگی‬
‫استفاده از استریسک و آشنایی با دستورات و توابع آن است‪ .‬امیدواریم با اطالعاتی که از این کتاب دریافت‬
‫نمودید‪ ،‬بتوانید به سهولت از دستورات و توابع استریسک‪ ،‬در برنامههای خود استفاده کنید‪.‬‬

You might also like