42 #include <sys/socket.h> 43 #include <netinet/in.h> 44 #include <netinet/tcp.h> 45 #include <sys/ioctl.h> 49 #include <arpa/inet.h> 148 #define DEBUG_GENERAL (1 << 1) 149 #define DEBUG_SUB (1 << 2) 150 #define DEBUG_PACKET (1 << 3) 151 #define DEBUG_AUDIO (1 << 4) 152 #define DEBUG_LOCK (1 << 5) 153 #define DEBUG_TEMPLATE (1 << 6) 154 #define DEBUG_THREAD (1 << 7) 155 #define DEBUG_HINT (1 << 8) 156 #define DEBUG_KEEPALIVE (1 << 9) 157 #define SKINNY_DEBUG(type, verb_level, text, ...) \ 159 if (skinnydebug & (type)) { \ 160 ast_verb(verb_level, "[%d] " text, ast_get_tid(), ##__VA_ARGS__); \ 164 #define SKINNY_DEBUG(type, verb_level, text, ...) 170 static const char tdesc[] =
"Skinny Client Control Protocol (Skinny)";
171 static const char config[] =
"skinny.conf";
186 #define DEFAULT_SKINNY_PORT 2000 187 #define DEFAULT_SKINNY_BACKLOG 2 188 #define SKINNY_MAX_PACKET 2000 189 #define DEFAULT_AUTH_TIMEOUT 30 190 #define DEFAULT_AUTH_LIMIT 50 199 }
qos = { 0, 0, 0, 0, 0, 0 };
212 #if __BYTE_ORDER == __LITTLE_ENDIAN 213 #define letohl(x) (x) 214 #define letohs(x) (x) 215 #define htolel(x) (x) 216 #define htoles(x) (x) 218 #if defined(HAVE_BYTESWAP_H) 219 #include <byteswap.h> 220 #define letohl(x) bswap_32(x) 221 #define letohs(x) bswap_16(x) 222 #define htolel(x) bswap_32(x) 223 #define htoles(x) bswap_16(x) 224 #elif defined(HAVE_SYS_ENDIAN_SWAP16) 225 #include <sys/endian.h> 226 #define letohl(x) __swap32(x) 227 #define letohs(x) __swap16(x) 228 #define htolel(x) __swap32(x) 229 #define htoles(x) __swap16(x) 230 #elif defined(HAVE_SYS_ENDIAN_BSWAP16) 231 #include <sys/endian.h> 232 #define letohl(x) bswap32(x) 233 #define letohs(x) bswap16(x) 234 #define htolel(x) bswap32(x) 235 #define htoles(x) bswap16(x) 237 #define __bswap_16(x) \ 238 ((((x) & 0xff00) >> 8) | \ 239 (((x) & 0x00ff) << 8)) 240 #define __bswap_32(x) \ 241 ((((x) & 0xff000000) >> 24) | \ 242 (((x) & 0x00ff0000) >> 8) | \ 243 (((x) & 0x0000ff00) << 8) | \ 244 (((x) & 0x000000ff) << 24)) 245 #define letohl(x) __bswap_32(x) 246 #define letohs(x) __bswap_16(x) 247 #define htolel(x) __bswap_32(x) 248 #define htoles(x) __bswap_16(x) 258 .resync_threshold = 1000,
266 #define MESSAGE2STR_BUFSIZE 35 270 #define DEVICE2STR_BUFSIZE 15 273 #define CONTROL2STR_BUFSIZE 100 276 #define SUBSTATE2STR_BUFSIZE 15 279 #define CALLSTATE2STR_BUFSIZE 15 285 #define KEEP_ALIVE_MESSAGE 0x0000 288 #define REGISTER_MESSAGE 0x0001 302 #define IP_PORT_MESSAGE 0x0002 304 #define KEYPAD_BUTTON_MESSAGE 0x0003 312 #define ENBLOC_CALL_MESSAGE 0x0004 314 char calledParty[24];
317 #define STIMULUS_MESSAGE 0x0005 324 #define OFFHOOK_MESSAGE 0x0006 330 #define ONHOOK_MESSAGE 0x0007 336 #define CAPABILITIES_RES_MESSAGE 0x0010 346 #define SKINNY_MAX_CAPABILITIES 18 353 #define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A 358 #define LINE_STATE_REQ_MESSAGE 0x000B 363 #define TIME_DATE_REQ_MESSAGE 0x000D 364 #define BUTTON_TEMPLATE_REQ_MESSAGE 0x000E 365 #define VERSION_REQ_MESSAGE 0x000F 366 #define SERVER_REQUEST_MESSAGE 0x0012 368 #define ALARM_MESSAGE 0x0020 371 char displayMessage[80];
376 #define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE 0x0022 391 #define SOFT_KEY_SET_REQ_MESSAGE 0x0025 393 #define SOFT_KEY_EVENT_MESSAGE 0x0026 400 #define UNREGISTER_MESSAGE 0x0027 401 #define SOFT_KEY_TEMPLATE_REQ_MESSAGE 0x0028 402 #define HEADSET_STATUS_MESSAGE 0x002B 403 #define REGISTER_AVAILABLE_LINES_MESSAGE 0x002D 405 #define SERVICEURL_STATREQ_MESSAGE 0x0033 410 #define REGISTER_ACK_MESSAGE 0x0081 413 char dateTemplate[6];
419 #define START_TONE_MESSAGE 0x0082 427 #define STOP_TONE_MESSAGE 0x0083 434 #define SET_RINGER_MESSAGE 0x0085 442 #define SET_LAMP_MESSAGE 0x0086 449 #define SET_SPEAKER_MESSAGE 0x0088 455 #define SET_MICROPHONE_MESSAGE 0x0089 460 #define START_MEDIA_TRANSMISSION_MESSAGE 0x008A 492 #define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B 499 #define CALL_INFO_MESSAGE 0x008F 501 char callingPartyName[40];
502 char callingParty[24];
503 char calledPartyName[40];
504 char calledParty[24];
508 char originalCalledPartyName[40];
509 char originalCalledParty[24];
510 char lastRedirectingPartyName[40];
511 char lastRedirectingParty[24];
514 char callingPartyVoiceMailbox[24];
515 char calledPartyVoiceMailbox[24];
516 char originalCalledPartyVoiceMailbox[24];
517 char lastRedirectingVoiceMailbox[24];
521 #define FORWARD_STAT_MESSAGE 0x0090 530 char fwdnoanswernum[24];
533 #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091 536 char speedDialDirNumber[24];
537 char speedDialDisplayName[40];
540 #define LINE_STAT_RES_MESSAGE 0x0092 543 char lineDirNumber[24];
544 char lineDisplayName[24];
548 #define DEFINETIMEDATE_MESSAGE 0x0094 561 #define BUTTON_TEMPLATE_RES_MESSAGE 0x0097 573 #define STIMULUS_REDIAL 0x01 574 #define STIMULUS_SPEEDDIAL 0x02 575 #define STIMULUS_HOLD 0x03 576 #define STIMULUS_TRANSFER 0x04 577 #define STIMULUS_FORWARDALL 0x05 578 #define STIMULUS_FORWARDBUSY 0x06 579 #define STIMULUS_FORWARDNOANSWER 0x07 580 #define STIMULUS_DISPLAY 0x08 581 #define STIMULUS_LINE 0x09 582 #define STIMULUS_VOICEMAIL 0x0F 583 #define STIMULUS_AUTOANSWER 0x11 584 #define STIMULUS_SERVICEURL 0x14 585 #define STIMULUS_DND 0x3F 586 #define STIMULUS_CONFERENCE 0x7D 587 #define STIMULUS_CALLPARK 0x7E 588 #define STIMULUS_CALLPICKUP 0x7F 589 #define STIMULUS_NONE 0xFF 592 #define BT_REDIAL STIMULUS_REDIAL 593 #define BT_SPEEDDIAL STIMULUS_SPEEDDIAL 594 #define BT_HOLD STIMULUS_HOLD 595 #define BT_TRANSFER STIMULUS_TRANSFER 596 #define BT_FORWARDALL STIMULUS_FORWARDALL 597 #define BT_FORWARDBUSY STIMULUS_FORWARDBUSY 598 #define BT_FORWARDNOANSWER STIMULUS_FORWARDNOANSWER 599 #define BT_DISPLAY STIMULUS_DISPLAY 600 #define BT_LINE STIMULUS_LINE 601 #define BT_VOICEMAIL STIMULUS_VOICEMAIL 602 #define BT_AUTOANSWER STIMULUS_AUTOANSWER 603 #define BT_SERVICEURL STIMULUS_SERVICEURL 604 #define BT_DND STIMULUS_DND 605 #define BT_CONFERENCE STIMULUS_CONFERENCE 606 #define BT_CALLPARK STIMULUS_CALLPARK 607 #define BT_CALLPICKUP STIMULUS_CALLPICKUP 613 #define BT_CUST_LINESPEEDDIAL 0xB0 614 #define BT_CUST_LINE 0xB1 623 #define VERSION_RES_MESSAGE 0x0098 628 #define DISPLAYTEXT_MESSAGE 0x0099 633 #define CLEAR_NOTIFY_MESSAGE 0x0115 634 #define CLEAR_DISPLAY_MESSAGE 0x009A 639 #define CAPABILITIES_REQ_MESSAGE 0x009B 641 #define REGISTER_REJ_MESSAGE 0x009D 646 #define SERVER_RES_MESSAGE 0x009E 653 uint32_t serverListenPort[5];
654 uint32_t serverIpAddr[5];
657 #define RESET_MESSAGE 0x009F 662 #define KEEP_ALIVE_ACK_MESSAGE 0x0100 664 #define OPEN_RECEIVE_CHANNEL_MESSAGE 0x0105 675 #define CLOSE_RECEIVE_CHANNEL_MESSAGE 0x0106 682 #define SOFT_KEY_TEMPLATE_RES_MESSAGE 0x0108 684 char softKeyLabel[16];
688 #define BKSP_REQ_MESSAGE 0x0119 694 #define KEYDEF_ONHOOK 0 695 #define KEYDEF_CONNECTED 1 696 #define KEYDEF_ONHOLD 2 697 #define KEYDEF_RINGIN 3 698 #define KEYDEF_OFFHOOK 4 699 #define KEYDEF_CONNWITHTRANS 5 700 #define KEYDEF_DADFD 6 701 #define KEYDEF_CONNWITHCONF 7 702 #define KEYDEF_RINGOUT 8 703 #define KEYDEF_OFFHOOKWITHFEAT 9 704 #define KEYDEF_UNKNOWN 10 705 #define KEYDEF_SLAHOLD 11 706 #define KEYDEF_SLACONNECTEDNOTACTIVE 12 707 #define KEYDEF_RINGOUTWITHTRANS 13 709 #define SOFTKEY_NONE 0x00 710 #define SOFTKEY_REDIAL 0x01 711 #define SOFTKEY_NEWCALL 0x02 712 #define SOFTKEY_HOLD 0x03 713 #define SOFTKEY_TRNSFER 0x04 714 #define SOFTKEY_CFWDALL 0x05 715 #define SOFTKEY_CFWDBUSY 0x06 716 #define SOFTKEY_CFWDNOANSWER 0x07 717 #define SOFTKEY_BKSPC 0x08 718 #define SOFTKEY_ENDCALL 0x09 719 #define SOFTKEY_RESUME 0x0A 720 #define SOFTKEY_ANSWER 0x0B 721 #define SOFTKEY_INFO 0x0C 722 #define SOFTKEY_CONFRN 0x0D 723 #define SOFTKEY_PARK 0x0E 724 #define SOFTKEY_JOIN 0x0F 725 #define SOFTKEY_MEETME 0x10 726 #define SOFTKEY_PICKUP 0x11 727 #define SOFTKEY_GPICKUP 0x12 728 #define SOFTKEY_DND 0x13 729 #define SOFTKEY_IDIVERT 0x14 730 #define SOFTKEY_FORCEDIAL 0x15 732 #define KEYMASK_ALL 0xFFFFFFFF 733 #define KEYMASK_NONE (1 << 0) 734 #define KEYMASK_REDIAL (1 << 1) 735 #define KEYMASK_NEWCALL (1 << 2) 736 #define KEYMASK_HOLD (1 << 3) 737 #define KEYMASK_TRNSFER (1 << 4) 738 #define KEYMASK_CFWDALL (1 << 5) 739 #define KEYMASK_CFWDBUSY (1 << 6) 740 #define KEYMASK_CFWDNOANSWER (1 << 7) 741 #define KEYMASK_BKSPC (1 << 8) 742 #define KEYMASK_ENDCALL (1 << 9) 743 #define KEYMASK_RESUME (1 << 10) 744 #define KEYMASK_ANSWER (1 << 11) 745 #define KEYMASK_INFO (1 << 12) 746 #define KEYMASK_CONFRN (1 << 13) 747 #define KEYMASK_PARK (1 << 14) 748 #define KEYMASK_JOIN (1 << 15) 749 #define KEYMASK_MEETME (1 << 16) 750 #define KEYMASK_PICKUP (1 << 17) 751 #define KEYMASK_GPICKUP (1 << 18) 752 #define KEYMASK_DND (1 << 29) 753 #define KEYMASK_IDIVERT (1 << 20) 754 #define KEYMASK_FORCEDIAL (1 << 21) 760 #define OCTAL_REDIAL "\200\001" 761 #define OCTAL_NEWCALL "\200\002" 762 #define OCTAL_HOLD "\200\003" 763 #define OCTAL_TRANSFER "\200\004" 764 #define OCTAL_CFWDALL "\200\005" 765 #define OCTAL_CFWDBUSY "\200\006" 766 #define OCTAL_CFWDNOAN "\200\007" 767 #define OCTAL_BKSPC "\200\010" 768 #define OCTAL_ENDCALL "\200\011" 769 #define OCTAL_RESUME "\200\012" 770 #define OCTAL_ANSWER "\200\013" 771 #define OCTAL_INFO "\200\014" 772 #define OCTAL_CONFRN "\200\015" 773 #define OCTAL_PARK "\200\016" 774 #define OCTAL_JOIN "\200\017" 775 #define OCTAL_MEETME "\200\020" 776 #define OCTAL_PICKUP "\200\021" 777 #define OCTAL_GPICKUP "\200\022" 778 #define OCTAL_CUROPTS "\200\023" 779 #define OCTAL_OFFHOOK "\200\024" 780 #define OCTAL_ONHOOK "\200\025" 781 #define OCTAL_RINGOUT "\200\026" 782 #define OCTAL_FROM "\200\027" 783 #define OCTAL_CONNECTED "\200\030" 784 #define OCTAL_BUSY "\200\031" 785 #define OCTAL_LINEINUSE "\200\032" 786 #define OCTAL_CALLWAITING "\200\033" 787 #define OCTAL_CALLXFER "\200\034" 788 #define OCTAL_CALLPARK "\200\035" 789 #define OCTAL_CALLPROCEED "\200\036" 790 #define OCTAL_INUSEREMOTE "\200\037" 791 #define OCTAL_ENTRNUM "\200\040" 792 #define OCTAL_PARKAT "\200\041" 793 #define OCTAL_PRIMONLY "\200\042" 794 #define OCTAL_TMPFAIL "\200\043" 795 #define OCTAL_HAVEVMAIL "\200\044" 796 #define OCTAL_FWDEDTO "\200\045" 797 #define OCTAL_CANTCOMPCNF "\200\046" 798 #define OCTAL_NOCONFBRDG "\200\047" 799 #define OCTAL_NOPRIMARYCTL "\200\050" 800 #define OCTAL_INVALCONFPART "\200\051" 801 #define OCTAL_INCONFALREADY "\200\052" 802 #define OCTAL_NOPARTINFO "\200\053" 803 #define OCTAL_MAXPARTEXCEED "\200\054" 804 #define OCTAL_KEYNOTACTIVE "\200\055" 805 #define OCTAL_ERRNOLIC "\200\056" 806 #define OCTAL_ERRDBCFG "\200\057" 807 #define OCTAL_ERRDB "\200\060" 808 #define OCTAL_ERRPASSLMT "\200\061" 809 #define OCTAL_ERRUNK "\200\062" 810 #define OCTAL_ERRMISMATCH "\200\063" 811 #define OCTAL_CONFERENCE "\200\064" 812 #define OCTAL_PARKNO "\200\065" 813 #define OCTAL_PRIVATE "\200\066" 814 #define OCTAL_INSUFBANDW "\200\067" 815 #define OCTAL_UNKNUM "\200\070" 816 #define OCTAL_RMLSTC "\200\071" 817 #define OCTAL_VOICEMAIL "\200\072" 818 #define OCTAL_IMMDIV "\200\073" 819 #define OCTAL_INTRCPT "\200\074" 820 #define OCTAL_SETWTCH "\200\075" 821 #define OCTAL_TRNSFVM "\200\076" 822 #define OCTAL_DND "\200\077" 823 #define OCTAL_DIVALL "\200\100" 824 #define OCTAL_CALLBACK "\200\101" 825 #define OCTAL_NETCNGREROUT "\200\102" 826 #define OCTAL_BARGE "\200\103" 827 #define OCTAL_BARGEFAIL "\200\104" 828 #define OCTAL_BARGEEXIST "\200\105" 829 #define OCTAL_INCOMPATDEV "\200\106" 830 #define OCTAL_PARKNONUM "\200\107" 831 #define OCTAL_PARKREVERSION "\200\110" 832 #define OCTAL_SRVNOTACTIVE "\200\111" 833 #define OCTAL_HITRAFFIC "\200\112" 834 #define OCTAL_QRT "\200\113" 835 #define OCTAL_MCID "\200\114" 836 #define OCTAL_DIRTRFR "\200\115" 837 #define OCTAL_SELECT "\200\116" 838 #define OCTAL_CONFLIST "\200\117" 839 #define OCTAL_IDIVERT "\200\120" 840 #define OCTAL_CBARGE "\200\121" 841 #define OCTAL_CANTCOMPLXFER "\200\122" 842 #define OCTAL_CANTJOINCALLS "\200\123" 843 #define OCTAL_MCIDSUCCESS "\200\124" 844 #define OCTAL_NUMNOTCFG "\200\125" 845 #define OCTAL_SECERROR "\200\126" 846 #define OCTAL_VIDBANDWNA "\200\127" 847 #define OCTAL_VIDMODE "\200\130" 848 #define OCTAL_CALLDURTIMEOUT "\200\131" 849 #define OCTAL_HOLDDURTIMEOUT "\200\132" 850 #define OCTAL_OPICKUP "\200\133" 856 #define OCTAL_EXTXFERRESTRICT "\200\141" 860 #define OCTAL_MACADD "\200\145" 861 #define OCTAL_HOST "\200\146" 862 #define OCTAL_DOMAIN "\200\147" 863 #define OCTAL_IPADD "\200\150" 864 #define OCTAL_SUBMASK "\200\151" 865 #define OCTAL_TFTP1 "\200\152" 866 #define OCTAL_ROUTER1 "\200\153" 867 #define OCTAL_ROUTER2 "\200\154" 868 #define OCTAL_ROUTER3 "\200\155" 869 #define OCTAL_ROUTER4 "\200\156" 870 #define OCTAL_ROUTER5 "\200\157" 871 #define OCTAL_DNS1 "\200\160" 872 #define OCTAL_DNS2 "\200\161" 873 #define OCTAL_DNS3 "\200\162" 874 #define OCTAL_DNS4 "\200\163" 875 #define OCTAL_DNS5 "\200\164" 876 #define OCTAL_VLANOPID "\200\165" 877 #define OCTAL_VLANADID "\200\166" 878 #define OCTAL_CM1 "\200\167" 879 #define OCTAL_CM2 "\200\170" 880 #define OCTAL_CM3 "\200\171" 881 #define OCTAL_CM4 "\200\172" 882 #define OCTAL_CM5 "\200\173" 883 #define OCTAL_URLINFO "\200\174" 884 #define OCTAL_URLDIRS "\200\175" 885 #define OCTAL_URLMSGS "\200\176" 886 #define OCTAL_URLSRVS "\200\177" 1040 #define SOFT_KEY_SET_RES_MESSAGE 0x0109 1043 uint8_t softKeyTemplateIndex[16];
1044 uint16_t softKeyInfoIndex[16];
1055 #define SELECT_SOFT_KEYS_MESSAGE 0x0110 1063 #define CALL_STATE_MESSAGE 0x0111 1071 #define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112 1074 char promptMessage[32];
1080 #define CLEAR_PROMPT_MESSAGE 0x0113 1086 #define DISPLAY_NOTIFY_MESSAGE 0x0114 1089 char displayMessage[100];
1092 #define ACTIVATE_CALL_PLANE_MESSAGE 0x0116 1097 #define DIALED_NUMBER_MESSAGE 0x011D 1099 char dialedNumber[24];
1104 #define MAX_SERVICEURL 256 1105 #define SERVICEURL_STAT_MESSAGE 0x012F 1109 char displayName[40];
1112 #define MAXCALLINFOSTR 256 1113 #define MAXDISPLAYNOTIFYSTR 32 1115 #define DISPLAY_PRINOTIFY_MESSAGE 0x0120 1122 #define CLEAR_PRINOTIFY_MESSAGE 0x0121 1127 #define CALL_INFO_MESSAGE_VARIABLE 0x014A 1140 #define DISPLAY_PRINOTIFY_MESSAGE_VARIABLE 0x0144 1147 #define DISPLAY_PROMPT_STATUS_MESSAGE_VARIABLE 0x0145 1236 static struct hostent *
hp;
1241 #define SKINNY_DEVICE_UNKNOWN -1 1242 #define SKINNY_DEVICE_NONE 0 1243 #define SKINNY_DEVICE_30SPPLUS 1 1244 #define SKINNY_DEVICE_12SPPLUS 2 1245 #define SKINNY_DEVICE_12SP 3 1246 #define SKINNY_DEVICE_12 4 1247 #define SKINNY_DEVICE_30VIP 5 1248 #define SKINNY_DEVICE_7910 6 1249 #define SKINNY_DEVICE_7960 7 1250 #define SKINNY_DEVICE_7940 8 1251 #define SKINNY_DEVICE_7935 9 1252 #define SKINNY_DEVICE_ATA186 12 1253 #define SKINNY_DEVICE_7941 115 1254 #define SKINNY_DEVICE_7971 119 1255 #define SKINNY_DEVICE_7914 124 1256 #define SKINNY_DEVICE_7985 302 1257 #define SKINNY_DEVICE_7911 307 1258 #define SKINNY_DEVICE_7961GE 308 1259 #define SKINNY_DEVICE_7941GE 309 1260 #define SKINNY_DEVICE_7931 348 1261 #define SKINNY_DEVICE_7921 365 1262 #define SKINNY_DEVICE_7906 369 1263 #define SKINNY_DEVICE_7962 404 1264 #define SKINNY_DEVICE_7937 431 1265 #define SKINNY_DEVICE_7942 434 1266 #define SKINNY_DEVICE_7945 435 1267 #define SKINNY_DEVICE_7965 436 1268 #define SKINNY_DEVICE_7975 437 1269 #define SKINNY_DEVICE_7905 20000 1270 #define SKINNY_DEVICE_7920 30002 1271 #define SKINNY_DEVICE_7970 30006 1272 #define SKINNY_DEVICE_7912 30007 1273 #define SKINNY_DEVICE_7902 30008 1274 #define SKINNY_DEVICE_CIPC 30016 1275 #define SKINNY_DEVICE_7961 30018 1276 #define SKINNY_DEVICE_7936 30019 1277 #define SKINNY_DEVICE_SCCPGATEWAY_AN 30027 1278 #define SKINNY_DEVICE_SCCPGATEWAY_BRI 30028 1280 #define SKINNY_SPEAKERON 1 1281 #define SKINNY_SPEAKEROFF 2 1283 #define SKINNY_MICON 1 1284 #define SKINNY_MICOFF 2 1286 #define SKINNY_OFFHOOK 1 1287 #define SKINNY_ONHOOK 2 1288 #define SKINNY_RINGOUT 3 1289 #define SKINNY_RINGIN 4 1290 #define SKINNY_CONNECTED 5 1291 #define SKINNY_BUSY 6 1292 #define SKINNY_CONGESTION 7 1293 #define SKINNY_HOLD 8 1294 #define SKINNY_CALLWAIT 9 1295 #define SKINNY_TRANSFER 10 1296 #define SKINNY_PARK 11 1297 #define SKINNY_PROGRESS 12 1298 #define SKINNY_CALLREMOTEMULTILINE 13 1299 #define SKINNY_INVALID 14 1301 #define SKINNY_INCOMING 1 1302 #define SKINNY_OUTGOING 2 1304 #define SKINNY_SILENCE 0x00 1305 #define SKINNY_DIALTONE 0x21 1306 #define SKINNY_BUSYTONE 0x23 1307 #define SKINNY_ALERT 0x24 1308 #define SKINNY_REORDER 0x25 1309 #define SKINNY_CALLWAITTONE 0x2D 1310 #define SKINNY_ZIPZIP 0x31 1311 #define SKINNY_ZIP 0x32 1312 #define SKINNY_BEEPBONK 0x33 1313 #define SKINNY_BARGIN 0x43 1314 #define SKINNY_NOTONE 0x7F 1316 #define SKINNY_LAMP_OFF 1 1317 #define SKINNY_LAMP_ON 2 1318 #define SKINNY_LAMP_WINK 3 1319 #define SKINNY_LAMP_FLASH 4 1320 #define SKINNY_LAMP_BLINK 5 1322 #define SKINNY_RING_OFF 1 1323 #define SKINNY_RING_INSIDE 2 1324 #define SKINNY_RING_OUTSIDE 3 1325 #define SKINNY_RING_FEATURE 4 1327 #define SKINNY_CFWD_ALL (1 << 0) 1328 #define SKINNY_CFWD_BUSY (1 << 1) 1329 #define SKINNY_CFWD_NOANSWER (1 << 2) 1332 #define SKINNY_CX_SENDONLY 0 1333 #define SKINNY_CX_RECVONLY 1 1334 #define SKINNY_CX_SENDRECV 2 1335 #define SKINNY_CX_CONF 3 1336 #define SKINNY_CX_CONFERENCE 3 1337 #define SKINNY_CX_MUTE 4 1338 #define SKINNY_CX_INACTIVE 4 1341 static const char *
const skinny_cxmodes[] = {
1371 #define SUBSTATE_UNSET 0 1372 #define SUBSTATE_OFFHOOK 1 1373 #define SUBSTATE_ONHOOK 2 1374 #define SUBSTATE_RINGOUT 3 1375 #define SUBSTATE_RINGIN 4 1376 #define SUBSTATE_CONNECTED 5 1377 #define SUBSTATE_BUSY 6 1378 #define SUBSTATE_CONGESTION 7 1379 #define SUBSTATE_HOLD 8 1380 #define SUBSTATE_CALLWAIT 9 1381 #define SUBSTATE_PROGRESS 12 1382 #define SUBSTATE_DIALING 101 1384 #define DIALTYPE_NORMAL 1<<0 1385 #define DIALTYPE_CFWD 1<<1 1386 #define DIALTYPE_XFER 1<<2 1420 #define SKINNY_LINE_OPTIONS \ 1423 char accountcode[AST_MAX_ACCOUNT_CODE]; \ 1424 char exten[AST_MAX_EXTENSION]; \ 1425 char context[AST_MAX_CONTEXT]; \ 1426 char language[MAX_LANGUAGE]; \ 1427 char cid_num[AST_MAX_EXTENSION]; \ 1428 char cid_name[AST_MAX_EXTENSION]; \ 1429 char lastcallerid[AST_MAX_EXTENSION]; \ 1431 char call_forward_all[AST_MAX_EXTENSION]; \ 1432 char call_forward_busy[AST_MAX_EXTENSION]; \ 1433 char call_forward_noanswer[AST_MAX_EXTENSION]; \ 1434 char mailbox[AST_MAX_MAILBOX_UNIQUEID]; \ 1435 char vmexten[AST_MAX_EXTENSION]; \ 1436 char regexten[AST_MAX_EXTENSION]; \ 1437 char regcontext[AST_MAX_CONTEXT]; \ 1438 char parkinglot[AST_MAX_CONTEXT]; \ 1439 char mohinterpret[MAX_MUSICCLASS]; \ 1440 char mohsuggest[MAX_MUSICCLASS]; \ 1441 char lastnumberdialed[AST_MAX_EXTENSION]; \ 1442 char dialoutexten[AST_MAX_EXTENSION]; \ 1443 char dialoutcontext[AST_MAX_CONTEXT]; \ 1444 ast_group_t callgroup; \ 1445 ast_group_t pickupgroup; \ 1446 struct ast_namedgroups *named_callgroups; \ 1447 struct ast_namedgroups *named_pickupgroups; \ 1450 int threewaycalling; \ 1452 int cancallforward; \ 1453 int callfwdtimeout; \ 1459 int nonCodecCapability; \ 1494 .callfwdtimeout = 20000,
1539 char displayName[40];
1544 #define SKINNY_DEVICECONTAINER 1 1545 #define SKINNY_LINECONTAINER 2 1546 #define SKINNY_SUBLINECONTAINER 3 1547 #define SKINNY_SDCONTAINER 4 1561 #define SKINNY_DEVICE_OPTIONS \ 1564 char version_id[16]; \ 1565 char vmexten[AST_MAX_EXTENSION]; \ 1567 int protocolversion; \ 1569 int lastlineinstance; \ 1570 int lastcallreference; \ 1583 struct sockaddr_in addr;
1584 struct in_addr ourip;
1616 struct timeval start;
1617 struct sockaddr_in sin;
1625 struct timeval last_keepalive;
1657 .description =
tdesc,
1741 for (i = 0; i < 4; i++)
1748 for (i = 0; i < 4; i++)
1749 (btn++)->buttonDefinition =
BT_NONE;
1750 for (i = 0; i < 13; i++)
1758 for (i = 0; i < 2; i++)
1760 for (i = 0; i < 4; i++)
1762 (btn++)->buttonDefinition =
BT_HOLD;
1770 (btn++)->buttonDefinition =
BT_LINE;
1771 (btn++)->buttonDefinition =
BT_HOLD;
1777 for (i = 0; i < 2; i++)
1786 for (i = 0; i < 6; i++)
1794 for (i = 0; i < 2; i++)
1799 for (i = 0; i < 2; i++)
1800 (btn++)->buttonDefinition =
BT_LINE;
1803 (btn++)->buttonDefinition =
BT_LINE;
1809 for (i = 0; i < 8; i++)
1819 (btn++)->buttonDefinition =
BT_LINE;
1820 (btn++)->buttonDefinition =
BT_HOLD;
1824 for (i = 0; i < 4; i++)
1828 for (i = 0; i < 6; i++)
1844 ast_log(
LOG_WARNING,
"Unsupported device type '%d (7914)' found. Expansion module registered by itself?\n", d->type);
1848 ast_log(
LOG_WARNING,
"Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
1857 if (!strcasecmp(a->
type,
"7914")) {
1858 for (i = 0; i < 14; i++)
1877 req->
e =
htolel(response_message);
1893 if (l->instance == instance)
1898 ast_log(
LOG_WARNING,
"Could not find line with instance '%d' on device '%s'\n", instance, d->name);
1911 int checkdevice = 0;
1914 at = strchr(line,
'@');
1924 if (checkdevice && tmpl)
1926 else if (!checkdevice) {
1928 }
else if (!strcasecmp(d->name, device)) {
1935 if (!strcasecmp(l->name, line)) {
1960 if (!strcasecmp(subline->
name, dest)) {
1962 ast_verb(2,
"Ambiguous subline name: %s\n", dest);
1966 tmpsubline = subline;
1982 if (subline->
callid == callid) {
1998 if ((varval = strchr(varname,
'='))) {
2001 tmpvar->
next = list;
2010 if (sub && sub->
owner) {
2017 if (sub && sub->
owner) {
2055 if (sub->
callid == reference)
2060 ast_log(
LOG_WARNING,
"Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
2073 if (sub->
callid == reference)
2081 ast_log(
LOG_WARNING,
"Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
2084 ast_log(
LOG_WARNING,
"Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
2100 ast_log(
LOG_WARNING,
"Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
2107 switch (skinnycodec) {
2160 ast_copy_string(l->call_forward_all, cfwd,
sizeof(l->call_forward_all));
2164 ast_copy_string(l->call_forward_busy, cfwd,
sizeof(l->call_forward_busy));
2168 ast_copy_string(l->call_forward_noanswer, cfwd,
sizeof(l->call_forward_noanswer));
2172 l->cfwdtype &= ~SKINNY_CFWD_ALL;
2173 memset(l->call_forward_all, 0,
sizeof(l->call_forward_all));
2176 l->cfwdtype &= ~SKINNY_CFWD_BUSY;
2177 memset(l->call_forward_busy, 0,
sizeof(l->call_forward_busy));
2180 l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
2181 memset(l->call_forward_noanswer, 0,
sizeof(l->call_forward_noanswer));
2189 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[
AST_MAX_CONTEXT];
2191 while ((oldcontext =
strsep(&old,
"&"))) {
2192 stalecontext =
NULL;
2195 while ((newcontext =
strsep(&stringp,
"&"))) {
2196 if (strcmp(newcontext, oldcontext) == 0) {
2198 stalecontext =
NULL;
2200 }
else if (strcmp(newcontext, oldcontext)) {
2201 stalecontext = oldcontext;
2219 while ((ext =
strsep(&stringp,
"&"))) {
2220 if ((context = strchr(ext,
'@'))) {
2223 ast_log(
LOG_WARNING,
"Context %s must exist in regcontext= in skinny.conf!\n", context);
2244 while ((ext =
strsep(&stringp,
"&"))) {
2245 if ((context = strchr(ext,
'@'))) {
2248 ast_log(
LOG_WARNING,
"Context %s must exist in regcontext= in skinny.conf!\n", context);
2264 struct sockaddr_in sin;
2297 if (getsockname(s->
fd, (
struct sockaddr *)&sin, &slen)) {
2301 d->
ourip = sin.sin_addr;
2313 l->instance = instance;
2326 blob =
ast_json_pack(
"{s: s}",
"peer_status",
"Registered");
2338 pthread_cancel(s->
t);
2348 return "SKINNY_OFFHOOK";
2350 return "SKINNY_ONHOOK";
2352 return "SKINNY_RINGOUT";
2354 return "SKINNY_RINGIN";
2356 return "SKINNY_CONNECTED";
2358 return "SKINNY_BUSY";
2360 return "SKINNY_CONGESTION";
2362 return "SKINNY_PROGRESS";
2364 return "SKINNY_HOLD";
2366 return "SKINNY_CALLWAIT";
2466 char *fromname,
char *fromnum,
char *toname,
char *tonum,
int calldirection,
char *origtonum,
char *origtoname)
2488 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting CALL_INFO_MESSAGE to %s, to %s(%s) from %s(%s), origto %s(%s) (dir=%d) on %s(%d)\n",
2489 d->name, toname, tonum, fromname, fromnum, origtoname, origtonum, calldirection, d->name, instance);
2494 char *fromname,
char *fromnum,
char *toname,
char *tonum,
int calldirection,
char *origtonum,
char *origtoname)
2498 char *thestrings[13];
2515 thestrings[0] = fromnum;
2518 thestrings[2] = tonum;
2519 thestrings[3] = origtonum;
2530 thestrings[9] = fromname;
2531 thestrings[10] = toname;
2532 thestrings[11] = origtoname;
2533 thestrings[12] =
"";
2537 for(i = 0; i < 13; i++) {
2538 if (thestrings[i]) {
2540 strptr += strlen(thestrings[i]) + 1;
2541 callinfostrleft -= strlen(thestrings[i]) + 1;
2549 req->
len = req->
len - (callinfostrleft & ~0x3);
2551 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting CALL_INFO_MESSAGE_VARIABLE to %s, to %s(%s) from %s(%s), origto %s(%s) (dir=%d) on %s(%d)\n",
2552 d->name, toname, tonum, fromname, fromnum, origtoname, origtonum, calldirection, d->name, instance);
2592 ast_verb(1,
"Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
2596 if (d->protocolversion < 17) {
2639 ast_verb(1,
"Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
2643 if (d->protocolversion < 17) {
2655 unsigned int framing;
2670 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting OPEN_RECEIVE_CHANNEL_MESSAGE to %s, confid %u, partyid %u, ms %u, fmt %d, echo %d, brate %d\n",
2688 d->name, tone, instance, reference);
2701 d->name, instance, reference);
2711 for(x = 0; x <
ARRAY_LEN(soft_key_default_definitions); x++) {
2712 if (softkeymode[x].
mode == keyset) {
2715 for (y = 0; y < softkeymode[x].
count; y++) {
2716 if (intmask & (1 << (defaults[y]))) {
2717 extmask |= (1 << ((y)));
2741 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting SELECT_SOFT_KEYS_MESSAGE to %s, inst %d, callid %d, softkey %d, mask 0x%08x\n",
2742 d->name, instance, callid, softkey, (
unsigned)newmask);
2758 d->name, stimulus, instance, indication);
2857 if ((
char)*text ==
'\200') {
2858 int octalstrlen = strlen(text);
2861 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting DISPLAY_PRINOTIFY_MESSAGE to %s, '\\%03o\\%03o', '%s', timeout=%d, priority=%d\n",
2862 d->name, (
unsigned)*text, (
unsigned)*(text+1), extratext, timeout, priority);
2866 d->name, text, timeout, priority);
2883 if ((
char)*text ==
'\200') {
2884 int octalstrlen = strlen(text);
2888 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting DISPLAY_PRINOTIFY_MESSAGE_VARIABLE to %s, '\\%03o\\%03o', '%s', timeout=%d, priority=%d\n",
2889 d->name, (
unsigned)*text, (
unsigned)*(text+1), extratext, timeout, priority);
2893 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting DISPLAY_PRINOTIFY_MESSAGE_VARIABLE to %s, '%s', timeout=%d, priority=%d\n",
2894 d->name, text, timeout, priority);
2897 req->
len = (packetlen & ~0x3) + 4;
2904 if (d->protocolversion < 17) {
2922 if ((
char)*text ==
'\200') {
2923 int octalstrlen = strlen(text);
2927 d->name, (
unsigned)*text, (
unsigned)*(text+1), extratext);
2947 if ((
char)*text ==
'\200') {
2948 int octalstrlen = strlen(text);
2953 d->name, (
unsigned)*text, (
unsigned)*(text+1), extratext);
2960 req->
len = (packetlen & ~0x3) + 4;
2967 if (d->protocolversion < 17) {
2985 d->name, instance, callid);
3001 d->name, text, instance, callid);
3016 d->name, 0, sub->
callid);
3030 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting STOP_MEDIA_TRANSMISSION_MESSAGE to %s, confid %d, passthrupartyid %u\n",
3031 d->name, 0, sub->
callid);
3040 if (d->protocolversion < 17) {
3068 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting START_MEDIA_TRANSMISSION_MESSAGE to %s, callid %u, passthrupartyid %u, ip %s:%d, ms %u, fmt %d, prec 127\n",
3083 d->name, l->instance);
3144 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting FORWARD_STAT_MESSAGE to %s, inst %d, all %s, busy %s, noans %s, acitve %d\n",
3145 d->name, l->instance, l->call_forward_all, l->call_forward_busy, l->call_forward_noanswer, anyon ? 7 : 0);
3210 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting DEFINETIMEDATE_MESSAGE to %s, date %u %u %u dow %u time %u:%u:%u.%u\n",
3258 keydefcount =
ARRAY_LEN(soft_key_default_definitions);
3262 for (x = 0; x < keydefcount; x++) {
3266 for (y = 0; y < softkeymode->
count; y++) {
3268 if (defaults[y] == i+1) {
3295 soft_key_template_default,
3296 sizeof(soft_key_template_default));
3298 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting SOFT_KEY_TEMPLATE_RES_MESSAGE to %s, offset 0, keycnt %u, totalkeycnt %u, template data\n",
3316 d->name, (fullrestart) ?
"Restarting" :
"Resetting");
3355 SKINNY_DEBUG(
DEBUG_PACKET, 3,
"Transmitting REGISTER_ACK_MESSAGE to %s, keepalive %d, datetemplate %s, seckeepalive %d, res 0x%04x, res2 0x%08x\n",
3385 d->name, instance, callid);
3479 if (subline->
callid == 0) {
3588 ast_verb(3,
"Skinny mwi_event_cb found %d new messages\n", l->
newmsgs);
3602 *instance = sub->
vrtp;
3626 *instance = sub->
rtp;
3630 if (!l->directmedia || l->nat){
3646 struct sockaddr_in us = { 0, };
3647 struct sockaddr_in them = { 0, };
3665 unsigned int framing;
3679 if (!(l->directmedia) || (l->nat)){
3682 us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->
ourip.s_addr;
3712 strcpy(ptr,
"general ");
3717 strcpy(ptr,
"sub ");
3722 strcpy(ptr,
"audio ");
3727 strcpy(ptr,
"packet ");
3732 strcpy(ptr,
"lock ");
3737 strcpy(ptr,
"template ");
3742 strcpy(ptr,
"thread ");
3747 strcpy(ptr,
"hint ");
3752 strcpy(ptr,
"keepalive ");
3757 strncpy(--ptr,
"\0", 1);
3764 const char *debugOpts[]={
"all",
"audio",
"hint",
"keepalive",
"lock",
"off",
"packet",
"show",
"sub",
"template",
"thread",
NULL };
3765 char *wordptr = (
char *)word;
3768 int buflen =
sizeof(
buf);
3773 if (*word ==
'+' || *word ==
'-' || *word ==
'!') {
3779 wordlen = strlen(wordptr);
3781 while (debugOpts[i]) {
3782 if (!strncasecmp(wordptr, debugOpts[i], wordlen) && ++which > state) {
3804 "Usage: skinny debug {audio|hint|keepalive|lock|off|packet|show|sub|template|thread}\n" 3805 " Enables/Disables various Skinny debugging messages\n";
3815 if (a->
argc == 3 && !strncasecmp(a->
argv[e->
args-1],
"show", 4)) {
3820 for(i = e->
args; i < a->argc; i++) {
3824 if (!strncasecmp(arg,
"off", 3)) {
3829 if (!strncasecmp(arg,
"all", 3)) {
3834 if (!strncasecmp(arg,
"-", 1) || !strncasecmp(arg,
"!", 1)) {
3837 }
else if (!strncasecmp(arg,
"+", 1)) {
3844 if (!strncasecmp(arg,
"general", 7)) {
3846 }
else if (!strncasecmp(arg,
"sub", 3)) {
3848 }
else if (!strncasecmp(arg,
"packet", 6)) {
3850 }
else if (!strncasecmp(arg,
"audio", 5)) {
3852 }
else if (!strncasecmp(arg,
"lock", 4)) {
3854 }
else if (!strncasecmp(arg,
"template", 8)) {
3856 }
else if (!strncasecmp(arg,
"thread", 6)) {
3858 }
else if (!strncasecmp(arg,
"hint", 4)) {
3860 }
else if (!strncasecmp(arg,
"keepalive", 9)) {
3863 ast_cli(a->
fd,
"Skinny Debugging - option '%s' unknown\n", a->
argv[i]);
3889 "Usage: skinny reload\n" 3890 " Reloads the chan_skinny configuration\n";
3907 int wordlen = strlen(word), which = 0;
3910 if (!strncasecmp(word, d->name, wordlen) && ++which > state) {
3926 static const char *
const completions[] = {
"all",
NULL };
3932 }
else if (pos == 3) {
3933 static const char *
const completions[] = {
"restart",
NULL };
3945 int wordlen = strlen(word), which = 0;
3949 if (!strncasecmp(word, l->name, wordlen) && ++which > state) {
3954 }
else if (pos == 4) {
3955 static const char *
const completions[] = {
"on",
NULL };
3957 }
else if (pos == 5) {
3972 "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n" 3973 " Causes a Skinny device to reset itself, optionally with a full restart\n";
3985 if (!strcasecmp(a->
argv[2], d->id) || !strcasecmp(a->
argv[2], d->name) || !strcasecmp(a->
argv[2],
"all")) {
3989 if (a->
argc == 4 && !strcasecmp(a->
argv[3],
"restart"))
4069 return "IP Communicator";
4075 return "SCCPGATEWAY_AN";
4077 return "SCCPGATEWAY_BRI";
4093 char idtext[256] =
"";
4094 int total_devices = 0;
4099 snprintf(idtext,
sizeof(idtext),
"ActionID: %s\r\n",
id);
4110 ast_cli(fd,
"Name DeviceId IP Type R NL\n");
4111 ast_cli(fd,
"-------------------- ---------------- --------------- --------------- - --\n");
4122 ast_cli(fd,
"%-20s %-16s %-15s %-15s %c %2d\n",
4131 "Event: DeviceEntry\r\n%s" 4132 "Channeltype: SKINNY\r\n" 4133 "ObjectName: %s\r\n" 4134 "ChannelObjectType: device\r\n" 4138 "Devicestatus: %s\r\n" 4139 "NumberOfLines: %d\r\n",
4145 d->
session?
"registered":
"unregistered",
4152 *total = total_devices;
4161 const char *
a[] = {
"skinny",
"show",
"devices"};
4180 e->
command =
"skinny show devices";
4182 "Usage: skinny show devices\n" 4183 " Lists all devices known to the Skinny subsystem.\n";
4207 if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
4208 int numlines = 0, numaddons = 0, numspeeddials = 0, numserviceurls = 0;
4227 ast_cli(fd,
"Name: %s\n", d->name);
4228 ast_cli(fd,
"Id: %s\n", d->id);
4229 ast_cli(fd,
"version: %s\n",
S_OR(d->version_id,
"Unknown"));
4236 ast_cli(fd,
"Lines: %d\n", numlines);
4238 ast_cli(fd,
" %s (%s)\n", l->name, l->label);
4240 ast_cli(fd,
"Addons: %d\n", numaddons);
4244 ast_cli(fd,
"Speeddials: %d\n", numspeeddials);
4248 ast_cli(fd,
"ServiceURLs: %d\n", numserviceurls);