23 |
24 |
25 |
--------------------------------------------------------------------------------
/asterisk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:jessie
2 |
3 | ARG PJSIP_PORT=5060
4 |
5 | RUN useradd --system --uid 202 asterisk
6 |
7 | RUN apt-get update -qq && \
8 | DEBIAN_FRONTEND=noninteractive \
9 | apt-get install -y --no-install-recommends \
10 | autoconf \
11 | build-essential \
12 | libedit-dev \
13 | libsrtp-dev \
14 | libjansson-dev \
15 | libogg-dev \
16 | libsqlite3-dev \
17 | libssl-dev \
18 | libxml2-dev \
19 | libxslt1-dev \
20 | uuid \
21 | uuid-dev \
22 | binutils-dev \
23 | libpopt-dev \
24 | libspandsp-dev \
25 | libvorbis-dev \
26 | libresample1-dev \
27 | libcurl4-openssl-dev \
28 | vim \
29 | curl \
30 | wget \
31 | xmlstarlet \
32 | python-dev \
33 | python-pip \
34 | && \
35 | pip install j2cli && \
36 | apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
37 |
38 | ENV ASTERISK_VERSION=14.2.0-rc1
39 | ENV RESPOKE_VERSION=v1.3.3
40 |
41 | COPY build-asterisk.sh /usr/src/build/
42 | COPY configs /usr/src/build/etc-asterisk/
43 | COPY keys /usr/src/build/keys
44 | COPY docker-entrypoint.sh /
45 |
46 | RUN /usr/src/build/build-asterisk.sh
47 |
48 | EXPOSE ${PJSIP_PORT}/udp 8088 5038
49 |
50 | ENTRYPOINT ["/docker-entrypoint.sh"]
51 |
52 | CMD ["/usr/sbin/asterisk", "-f"]
53 |
--------------------------------------------------------------------------------
/asterisk/keys/asterisk.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDTTCCATUCAQEwDQYJKoZIhvcNAQELBQAwMTEcMBoGA1UEAxMTQXN0ZXJpc2sg
3 | UHJpdmF0ZSBDQTERMA8GA1UEChMIQXN0ZXJpc2swHhcNMTYxMTAxMTkxMDMzWhcN
4 | MTcxMTAxMTkxMDMzWjAsMRcwFQYDVQQDEw5tam9yZGFuLWxhcHRvcDERMA8GA1UE
5 | ChMIQXN0ZXJpc2swgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO151bZIuBmH
6 | 7hW6/xqoXBvTztMP9suv7MKvQ4m3M4pLJpLJI477NRdHyNqswCTK8Mq9wxkhg9cN
7 | sNcKAhsdrJG5tjPEbIUpo6Stj3jObbvWNXExG2zvjsGZp3ttNfFYF97XziIppZ5a
8 | rcpAPeJLWhtpPPTAOw3yoj71wpzBn297AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
9 | AB8ogB+RWEDbs9Ikr2oNhkqCijZ7CfKe41nyMNFZfm+oLEbXvQ5m9COwBPLssS22
10 | NVsSD+v3qAFulEmAiSlqrYhD11uWapr1UZlTvzhZGrRKVKatqgZQH7AxTBxwSnHG
11 | q848UK8vyKbwSc2dgIfaVoGR5PYvIOc8so6izwR8NZPAsZD8huUVYQKOMxDYgbzh
12 | 4c6gL2prpkC8QC1FfTQBYFEEgaVntCYid6qQT2/zkMNFPrBzfJ+9fS7KXcbuI8uI
13 | pBXtmvqKXt/9ligiKO10VSIV2noMTz1eBXbYcP/d87873M/4XLEVCar1OyuNHhr9
14 | PENMvfarzEu4eo9G3hLmDqsuriG/zH2JTiSYc/Zdg1m2lkhxwh5c5VUbXXlh7uL7
15 | 3tsUwFcBTWBEGlbXFWF+H3z+GzI3FWgR6l0ATvHtbfp5ykyxNZj4bzPBZZpXSgLC
16 | KCntspPJNiEFR3B/SmGt7BsIv/iNdBcbPxKWGkk5TYKDEyrJhJGr3akRKsPLQmHH
17 | 7BHDImm/OTnk7NxonaOVzw+5l9VWW2fJ+Gncw1nn1TVCJ4o2GMNkPAS5Ocrrmyyi
18 | OJVqR69BkKMiU7F8Rr7ZoI9WZuto0frAL9XC8pExvc4xZJbiMuuVk/6t+fUH2S7n
19 | Om9uSEahsoNDx7oqkmEnfGOcsjF5oFldxg/drjW8a+2w
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/asterisk/Makefile:
--------------------------------------------------------------------------------
1 | IMAGE_NAME := asterisk-iot
2 | DOCKER_REPO_NAME := $(IMAGE_NAME)
3 |
4 | GIT_BRANCH_NAME := $(shell git rev-parse --abbrev-ref HEAD | sed "sX/X-Xg")
5 | GIT_TAG_NAME := $(shell git describe --always HEAD)
6 |
7 | TAGS := $(GIT_BRANCH_NAME) $(GIT_TAG_NAME)
8 |
9 | ifeq ($(GIT_BRANCH_NAME),master)
10 | TAGS += latest
11 | endif
12 |
13 | #
14 | # default build target
15 | #
16 | all: build
17 | .PHONY: all
18 |
19 | #
20 | # docker pull latest dependencies.
21 | #
22 | pull:
23 | docker pull $(shell sed -n 's/^FROM // p' Dockerfile)
24 | .PHONY: pull
25 |
26 | #
27 | # docker build the image
28 | #
29 | build:
30 | docker build -t $(DOCKER_REPO_NAME) .
31 | .PHONY: build
32 |
33 | #
34 | # docker tag the build
35 | #
36 | tag: build
37 | echo $(TAGS) | xargs -n 1 docker tag $(DOCKER_REPO_NAME)
38 | .PHONY: tag
39 |
40 | #
41 | # docker push the tags to the respoke registry
42 | #
43 | push: tag
44 | echo $(TAGS) | xargs -n 1 docker push
45 | .PHONY: push
46 |
47 | #
48 | # quick cleanup; leaves things that are expensive to remove or rebuild
49 | #
50 | clean:
51 | rm -rf build/
52 | rm -f version.txt
53 | .PHONY: clean
54 |
55 | #
56 | # remove any images generated by this build
57 | #
58 | clean-images:
59 | docker images -f 'label=cirrus.name=$(IMAGE_NAME)' \
60 | --format="{{.Repository}} {{.Tag}} {{.ID}}" | \
61 | awk '{ \
62 | if ($$2=="") { \
63 | print $$3 \
64 | } else { \
65 | print $$1 ":" $$2 \
66 | } \
67 | }' | \
68 | xargs docker rmi
69 | .PHONY: clean-images
70 |
71 | #
72 | # clean up even the stuff that's expensive to build
73 | #
74 | really-clean: clean clean-images
75 | .PHONY: really-clean
76 |
77 | #
78 | # bamboo build process
79 | #
80 | bamboo: pull build tag push
81 | echo $(GIT_TAG_NAME) > version.txt
82 | .PHONY: bamboo
--------------------------------------------------------------------------------
/awesome-conference/src/services/respoke.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Respoke = require('respoke-admin');
4 | const log = require('../lib/log');
5 |
6 | class RespokeWrapper {
7 |
8 | constructor(config) {
9 | this.app_id = config.respoke.app_id;
10 | this.app_secret = config.respoke.app_secret;
11 | this.endpoint_role_id = config.respoke.endpoint_role_id;
12 | this.client = null;
13 | }
14 |
15 | connect() {
16 | let that = this;
17 |
18 | if (this.client) {
19 | return Promise.reject('Client already connected');
20 | }
21 |
22 | log.info('Connecting to Respoke');
23 |
24 | return new Promise(resolve => {
25 | that.client = new Respoke({
26 | appId: that.app_id,
27 | 'App-Secret': that.app_secret,
28 | autoreconnect: true
29 | });
30 | that.client.auth.connect({ endpointId: 'backend' });
31 | that.client.on('connect', () => {
32 | log.info('Connected to Respoke');
33 | resolve(that.client);
34 | });
35 | });
36 | }
37 |
38 | register_endpoint(endpointId) {
39 | const that = this;
40 |
41 | if (!this.client) {
42 | return Promise.reject('Client not connected');
43 | }
44 |
45 | return this.client.auth.endpoint({
46 | endpointId,
47 | roleId: that.endpoint_role_id
48 | }).then( authData => {
49 | log.info(`Providing auth for endpoint ${endpointId}`)
50 | return Promise.resolve({
51 | appId: that.app_id,
52 | tokenId: authData.tokenId
53 | });
54 | });
55 | }
56 | }
57 |
58 | module.exports.RespokeWrapper = RespokeWrapper;
59 |
--------------------------------------------------------------------------------
/asterisk/keys/ca.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIE3jCCAsYCCQCLLhOlYo+5+DANBgkqhkiG9w0BAQsFADAxMRwwGgYDVQQDExNB
3 | c3RlcmlzayBQcml2YXRlIENBMREwDwYDVQQKEwhBc3RlcmlzazAeFw0xNjExMDEx
4 | OTEwMzBaFw0xNzExMDExOTEwMzBaMDExHDAaBgNVBAMTE0FzdGVyaXNrIFByaXZh
5 | dGUgQ0ExETAPBgNVBAoTCEFzdGVyaXNrMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
6 | MIICCgKCAgEA4QpYA7C3p2iX3M/zbBQRvrhSAgsu1ThniNkJZBko+2mbUYbw9D+I
7 | iCstGOhzcNgYPNYghubmLbV1Xfi30KoEHoiLxizlKTqp8wXEVbe2JbrPPAtBCphb
8 | gpZalWaX9RoVMDAwhtR9Y3FqLs0knC9ilKhVp1LTTlsjjvQjUimWFzCSSIR5vo18
9 | 7xgyt32yeC9ksi+nuJo5n8ZczUGnPoK+t1/ZcXX5kze2ap4PG4r0RJesfBFkTk1W
10 | vIyypHYCZ+ebfZ0+zHIBIH68hLc0gTA2bSxpTg04aO+tkOTLBs+HeLm7KFWqU8T/
11 | HqnMhx+2wEp2CGrlwz0mJexMdJUBoidT0d5wuBGn3qF4zpBKd8IKfkFv0HsMCi4y
12 | q0c7BgxlzjZjt2jNLbOZwKUEFdCJuaXegFSLbhYys6fD6lkRqFFcdIewMi0oOQL5
13 | 4SAwq34U/heNsCrkZ3fk2GUHaBOKAni4xEJCIkb+9gypZu70SFn1qzTamR0SfeIM
14 | HWP3tcmbM+28qlMWPs5c5P8ZrNg1v7XV6c6xJHGvoC/IGY/2FnAkL+m3xTIgYFRc
15 | A+Alo+AfZbwhcYWRSEei5jr1OibrZYKCP/BZzQnFYDEKR7WQTzIR823jV2RqGu44
16 | EwEbHmmtqqEorm3jYVULLtcJJxWJsrCfB0oXZzf6//J7nycz8O2VQ/UCAwEAATAN
17 | BgkqhkiG9w0BAQsFAAOCAgEAxX0aIDNc+S1AJ1EgZFlSeTW/j3uB5eDf+RKhUXjK
18 | P05fjaJ/1OC72pZ+Ar1HVX44ITW255MXB5ny55MvDKkYOeQMkVOhuIVIB4qbTUGo
19 | t+/Wznp+VXFJqZIkTftUokYfyk3cg9AUiKCIa98pHU8zFSqK801suuxeFFtMviP4
20 | 0bLy4SrrtUBGtFeB+OpNw5O8sSGy87g1esPXuaM1gabuddjc/8kesbGqO86rvA/k
21 | 0PCURiTUkl35etsIsRl1t7zuZT6o7EtBnOLt60WpPtHLfDk0vxp6MsnMuGCDBgXm
22 | 7GoFGhzKr9NVrCq8bb0+cRvPCVnuIDQHMer+9JRwNSi9LHc4kXGbPsMuc0euqXxP
23 | jw88TpZjrkKNnHDmHBJxD0sVVBhJCtkfeOKRbGhzmYmR0d6Xqmjgz/XkO4JAb+Rh
24 | Y4zoWIqpkorubg11eq3gYEUtKhkTKQErZ6cUZ5mO0gyvuF/gUYfL8Z/iYLswcsDb
25 | oj7pf0M2qWHDc0toEiJrQ74II4mIPPD1qLXAxaNztGPu82NAH13R+FbeiF4P8eab
26 | 253BMuCMiLDmpZ6opgxHEkkguQ46ka6917l1V1Hq/MZyDYSb5iMdrA45fu1x2GFM
27 | +gBqk7mzYrLDlxZyQl5hFr83BZUji+2lWOsXrtD6uRGxjwOy6Bk+y7K+KRyF5z15
28 | /o8=
29 | -----END CERTIFICATE-----
30 |
--------------------------------------------------------------------------------
/asterisk/keys/asterisk.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXgIBAAKBgQDtedW2SLgZh+4Vuv8aqFwb087TD/bLr+zCr0OJtzOKSyaSySOO
3 | +zUXR8jarMAkyvDKvcMZIYPXDbDXCgIbHayRubYzxGyFKaOkrY94zm271jVxMRts
4 | 747Bmad7bTXxWBfe184iKaWeWq3KQD3iS1obaTz0wDsN8qI+9cKcwZ9vewIDAQAB
5 | AoGATB+R8iy9VvHL0AtxWwo8/G6ZDe9AHWr3ajDkZXDkhKAybTssutir3BqWuAJI
6 | VYL4TQUnVRb5PCaXWVdL9YU9m5riXNchGrygUL2eYMNmDWlkOp/C2Wt/YUF4c+Pr
7 | jVOrvaXq2bAi9IZrPPIPzWOtZr+xxPNbDSbJ0PBYdW+GjwECQQD7FU6J1MmZexYX
8 | zxqfeRHx8EYijGBGR6BKhuXPLystH0kTIB7b392NPeum3ZOx3ScXIi54sX7JFHbC
9 | UEUYFVXTAkEA8iBQWTqDPlR1Q3vBywvbCCATBspnifmR/ko+UD0oDc88D3IpMJE/
10 | navhXJWKm+Qpx1/u92c83HRXYe5GaEWuuQJBAMT4yR09zk3WjtVsxrD2lMpdOVgf
11 | EePwiuIMg7qOgWurkHMtjqflLnSAcB7+0sAFA4aVbSmH7TOoFyaHPD0Rd7sCQQCM
12 | pVKnEkMskLjxM1FWFhPse10yA57zWeKBWTUrPOsoYmnb+w+MI8NVXoNxWXiDp5zR
13 | MJvKYNDMqlQcEeIaLegZAkEA5ujL1HXihts4Cwwh9tzIujMRVnhWPY7hK7cXbwFL
14 | dRhK6nIvEv+5HvvPFw5iTO5LF+lKqls0lyHD0f792Qk5zA==
15 | -----END RSA PRIVATE KEY-----
16 | -----BEGIN CERTIFICATE-----
17 | MIIDTTCCATUCAQEwDQYJKoZIhvcNAQELBQAwMTEcMBoGA1UEAxMTQXN0ZXJpc2sg
18 | UHJpdmF0ZSBDQTERMA8GA1UEChMIQXN0ZXJpc2swHhcNMTYxMTAxMTkxMDMzWhcN
19 | MTcxMTAxMTkxMDMzWjAsMRcwFQYDVQQDEw5tam9yZGFuLWxhcHRvcDERMA8GA1UE
20 | ChMIQXN0ZXJpc2swgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO151bZIuBmH
21 | 7hW6/xqoXBvTztMP9suv7MKvQ4m3M4pLJpLJI477NRdHyNqswCTK8Mq9wxkhg9cN
22 | sNcKAhsdrJG5tjPEbIUpo6Stj3jObbvWNXExG2zvjsGZp3ttNfFYF97XziIppZ5a
23 | rcpAPeJLWhtpPPTAOw3yoj71wpzBn297AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
24 | AB8ogB+RWEDbs9Ikr2oNhkqCijZ7CfKe41nyMNFZfm+oLEbXvQ5m9COwBPLssS22
25 | NVsSD+v3qAFulEmAiSlqrYhD11uWapr1UZlTvzhZGrRKVKatqgZQH7AxTBxwSnHG
26 | q848UK8vyKbwSc2dgIfaVoGR5PYvIOc8so6izwR8NZPAsZD8huUVYQKOMxDYgbzh
27 | 4c6gL2prpkC8QC1FfTQBYFEEgaVntCYid6qQT2/zkMNFPrBzfJ+9fS7KXcbuI8uI
28 | pBXtmvqKXt/9ligiKO10VSIV2noMTz1eBXbYcP/d87873M/4XLEVCar1OyuNHhr9
29 | PENMvfarzEu4eo9G3hLmDqsuriG/zH2JTiSYc/Zdg1m2lkhxwh5c5VUbXXlh7uL7
30 | 3tsUwFcBTWBEGlbXFWF+H3z+GzI3FWgR6l0ATvHtbfp5ykyxNZj4bzPBZZpXSgLC
31 | KCntspPJNiEFR3B/SmGt7BsIv/iNdBcbPxKWGkk5TYKDEyrJhJGr3akRKsPLQmHH
32 | 7BHDImm/OTnk7NxonaOVzw+5l9VWW2fJ+Gncw1nn1TVCJ4o2GMNkPAS5Ocrrmyyi
33 | OJVqR69BkKMiU7F8Rr7ZoI9WZuto0frAL9XC8pExvc4xZJbiMuuVk/6t+fUH2S7n
34 | Om9uSEahsoNDx7oqkmEnfGOcsjF5oFldxg/drjW8a+2w
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/awesome-conference/src/public/index.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;
3 | font-size: 13px;
4 | font-weight: 600;
5 | text-align: center;
6 | background: #275480;
7 | padding-bottom: 50px;
8 | }
9 |
10 | /* keep the webcam snapper video hidden */
11 | camera {
12 | display: none;
13 | }
14 |
15 | /* Person picture and video cards */
16 |
17 | .main {
18 | height: 70vh;
19 | }
20 |
21 | .people {
22 | height: 20vh;
23 | overflow-x: auto;
24 | overflow-y: hidden;
25 | }
26 |
27 | .person {
28 | background: rgb(94, 94, 94); /* same as grayscale respoke logo */
29 | color: #33699E;
30 | border: 0;
31 | border-bottom: 3px solid #1C364E;
32 | width: 160px;
33 | height: 120px;
34 | display: inline-block !important;
35 | margin: 10px;
36 | border-top-left-radius: 40px;
37 | border-bottom-left-radius: 5px;
38 | border-top-right-radius: 5px;
39 | border-bottom-right-radius: 40px;
40 | overflow-x: hidden;
41 | overflow-y: hidden;
42 | }
43 |
44 | .videoSource {
45 | background: rgb(94, 94, 94); /* same as grayscale respoke logo */
46 | color: #33699E;
47 | outline-color: orange;
48 | outline-style: solid;
49 | border: 0;
50 | border-bottom: 3px solid #1C364E;
51 | width: 160px;
52 | height: 120px;
53 | display: inline-block !important;
54 | margin: 10px;
55 | border-top-left-radius: 40px;
56 | border-bottom-left-radius: 5px;
57 | border-top-right-radius: 5px;
58 | border-bottom-right-radius: 40px;
59 | overflow-x: hidden;
60 | overflow-y: hidden;
61 | }
62 |
63 | .img, video {
64 | margin: 0;
65 | padding: 0;
66 | }
67 | img {
68 | filter: grayscale(100%);
69 | -webkit-filter: grayscale(100%);
70 | }
71 | video {
72 | border-top-left-radius: 40px;
73 | border-bottom-left-radius: 5px;
74 | border-top-right-radius: 5px;
75 | border-bottom-right-radius: 40px;
76 | }
77 |
78 | /* Footer */
79 |
80 | .respoke, .github, .instructions {
81 | position: fixed;
82 | bottom: 8px;
83 | color: #ccc !important;
84 | text-decoration: none;
85 | }
86 | .github {
87 | left: 13px;
88 | }
89 | .respoke {
90 | right: 13px;
91 | }
92 | .instructions {
93 | right: 50%;
94 | margin-right: -100px;
95 | width: 200px;
96 | font-weight: normal;
97 | }
--------------------------------------------------------------------------------
/awesome-conference/src/bootstrap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const config = require('config');
3 | const express = require('express');
4 | const session = require('express-session');
5 | const path = require('path');
6 | const uuid = require('uuid');
7 | const asterisk = require('./services/asterisk');
8 | const conference = require('./services/conference');
9 | const respoke = require('./services/respoke');
10 |
11 | function boot() {
12 | return new Promise(resolve => {
13 | const app = express();
14 | let respokeWrapper;
15 |
16 | app.set('x-powered-by', false);
17 | app.set('trust proxy', true);
18 |
19 | app.use(express.static(path.join(__dirname, 'public')));
20 |
21 | app.use(session({
22 | secret: uuid.v4(),
23 | cookie: {},
24 | resave: false,
25 | saveUninitialized: false
26 | }));
27 |
28 | app.get('/token', (req, res, next) => {
29 | if (!req.query.endpointId) {
30 | let err = new Error(`Missing required query param 'endpointId'`);
31 | err.status = 400;
32 | next(err);
33 | }
34 |
35 | if (respokeWrapper) {
36 | respokeWrapper.register_endpoint(req.query.endpointId)
37 | .then( authToken => {
38 | res.json(authToken);
39 | });
40 | } else {
41 | res.sendStatus(500);
42 | }
43 | });
44 |
45 | app.use((req, res, next) => {
46 | let err = new Error(`Not Found: ${req.url}`);
47 | err.status = 404;
48 | next(err);
49 | });
50 |
51 | const asteriskWrapper = new asterisk.AsteriskWrapper(config);
52 | asteriskWrapper.connect()
53 | .then(() => {
54 | return asteriskWrapper.provision();
55 | })
56 | .then(() => {
57 | respokeWrapper = new respoke.RespokeWrapper(config);
58 | let respokeClient;
59 |
60 | return respokeWrapper.connect()
61 | .then((_respokeClient) => {
62 | respokeClient = _respokeClient;
63 |
64 | return asteriskWrapper.connectConferenceApp();
65 | })
66 | .then(ariClient => {
67 | const conf = new conference.Conference(respokeClient, ariClient);
68 |
69 | resolve(app);
70 | });
71 | });
72 | });
73 | }
74 |
75 | module.exports = { boot };
76 |
--------------------------------------------------------------------------------
/asterisk/build-asterisk.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PROGNAME=$(basename $0)
4 | SOURCE_DIR="/usr/src/build"
5 |
6 | MENUSELECT_DISABLE=(
7 | app_talkdetect app_adsiprog app_alarmreceiver
8 | app_amd app_chanisavail app_dictate app_externalivr app_festival
9 | app_getcpeid app_ices app_image app_minivm app_morsecode app_mp3
10 | app_nbscat app_sms app_test app_url app_waitforring app_waitforsilence
11 | app_zapateller cdr_custom cdr_manager cdr_syslog cdr_sqlite3_custom
12 | cel_custom cel_manager cel_sqlite3_custom chan_iax2 chan_alsa
13 | chan_console chan_mgcp chan_oss chan_phone chan_sip chan_skinny
14 | chan_unistim func_audiohookinherit pbx_ael pbx_dundi pbx_realtime
15 | res_fax res_ael_share res_fax_spandsp res_phoneprov
16 | res_pjsip_phoneprov_provider BUILD_NATIVE CORE-SOUNDS-EN-GSM
17 | )
18 |
19 | MENUSELECT_ENABLE=(
20 | BETTER_BACKTRACES res_endpoint_stats res_mwi_external res_stasis_mailbox
21 | res_ari_mailboxes codec_opus CORE-SOUNDS-EN-WAV CORE-SOUNDS-EN-ULAW
22 | EXTRA-SOUNDS-EN-WAV EXTRA-SOUNDS-EN-ULAW
23 | )
24 |
25 | if test -z ${ASTERISK_VERSION}; then
26 | echo "${PROGNAME}: ASTERISK_VERSION required" >&2
27 | exit 1
28 | fi
29 |
30 | set -ex
31 |
32 | mkdir -p ${SOURCE_DIR}/asterisk
33 | mkdir -p ${SOURCE_DIR}/cache
34 | cd ${SOURCE_DIR}/asterisk
35 |
36 | # Build Asterisk
37 | curl -vsL http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${ASTERISK_VERSION}.tar.gz |
38 | tar --strip-components 1 -xz
39 |
40 | # 1.5 jobs per core works out okay
41 | : ${JOBS:=$(( $(nproc) + $(nproc) / 2 ))}
42 |
43 | ./configure --with-resample --with-pjproject-bundled --with-externals-cache=${SOURCE_DIR}/cache
44 | make menuselect/menuselect menuselect-tree menuselect.makeopts
45 |
46 | for i in "${MENUSELECT_DISABLE[@]}"; do
47 | menuselect/menuselect --disable $i menuselect.makeopts
48 | done
49 |
50 | for i in "${MENUSELECT_ENABLE[@]}"; do
51 | menuselect/menuselect --enable $i menuselect.makeopts
52 | done
53 |
54 | make -j ${JOBS} all
55 | make install
56 |
57 | mkdir chan_respoke
58 | cd chan_respoke
59 | # Build chan_respoke
60 | curl -vsL https://github.com/respoke/chan_respoke/releases/download/${RESPOKE_VERSION}/chan_respoke-${RESPOKE_VERSION}.tar.gz |
61 | tar --strip-components 1 -xz
62 | make -j ${JOBS}
63 | make install
64 | cd ..
65 |
66 | # copy config files into place
67 | mkdir -p /etc/asterisk/
68 | mkdir -p /etc/asterisk/keys
69 | cp -a ${SOURCE_DIR}/etc-asterisk/* /etc/asterisk/
70 | cp -a ${SOURCE_DIR}/keys/* /etc/asterisk/keys
71 |
72 | chown -R asterisk:asterisk /var/*/asterisk
73 | chown -R asterisk:asterisk /etc/asterisk
74 | chmod a+r /etc/asterisk/keys
75 | chown -R asterisk:asterisk /usr/sbin/asterisk
76 | chown -R asterisk:asterisk /var/lib/asterisk/sounds
77 | chmod -R 750 /var/spool/asterisk
78 |
--------------------------------------------------------------------------------
/asterisk/configs/musiconhold.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; Music on Hold -- Sample Configuration
3 | ;
4 | ;[general]
5 | ;cachertclasses=yes ; use 1 instance of moh class for all users who are using it,
6 | ; decrease consumable cpu cycles and memory
7 | ; disabled by default
8 |
9 |
10 | ; valid mode options:
11 | ; files -- read files from a directory in any Asterisk supported
12 | ; media format
13 | ; quietmp3 -- default
14 | ; mp3 -- loud
15 | ; mp3nb -- unbuffered
16 | ; quietmp3nb -- quiet unbuffered
17 | ; custom -- run a custom application (See examples below)
18 |
19 | ; =========
20 | ; File-based (native) music on hold
21 | ; =========
22 | ;
23 | ; This plays files directly from the specified directory, no external
24 | ; processes are required. Files are played in normal sorting order
25 | ; (same as a sorted directory listing), and no volume or other
26 | ; sound adjustments are available. If the file is available in
27 | ; the same format as the channel's codec, then it will be played
28 | ; without transcoding (same as Playback would do in the dialplan).
29 | ; Files can be present in as many formats as you wish, and the
30 | ; 'best' format will be chosen at playback time.
31 | ;
32 | ; The path specified can be either an absolute path (starts with '/'),
33 | ; or a relative path; relative paths are interpreted as being relative
34 | ; to the 'astdatalibdir' in asterisk.conf, which defaults to
35 | ; /var/lib/asterisk.
36 | ;
37 | ; NOTE:
38 | ; If you are not using "autoload" in modules.conf, then you
39 | ; must ensure that the format modules for any formats you wish
40 | ; to use are loaded _before_ res_musiconhold. If you do not do
41 | ; this, res_musiconhold will skip the files it is not able to
42 | ; understand when it loads.
43 | ;
44 |
45 | [default]
46 | mode=files
47 | directory=moh
48 | ;
49 | ;[native-random]
50 | ;mode=files
51 | ;directory=moh
52 | ;digit=# ; If this option is set for a class, then when callers are
53 | ; ; listening to music on hold, they can press this digit, and
54 | ; ; they will switch to listening to this music class.
55 | ;announcement=queue-thankyou ;If this option is set for a class, then
56 | ; ; when callers get put on hold, the specified sound will be
57 | ; ; be played to them. Also, if using modes that Asterisk
58 | ; ; controls the playlist for (files, mp3, etc), the same
59 | ; ; sound will also be played between MOH songs.
60 | ;sort=random ; Sort the files in random order
61 |
62 | ;[native-alphabetical]
63 | ;mode=files
64 | ;directory=moh
65 | ;sort=alpha ; Sort the files in alphabetical order. If this option is
66 | ; ; not specified, the sort order is undefined.
67 |
68 | ; =========
69 | ; Other (non-native) playback methods
70 | ; =========
71 |
72 | ;[manual]
73 | ;mode=custom
74 | ; Note that with mode=custom, a directory is not required, such as when reading
75 | ; from a stream.
76 | ;directory=/var/lib/asterisk/mohmp3
77 | ;application=/usr/bin/mpg123 -q -r 8000 -f 8192 -b 2048 --mono -s
78 |
79 | ;[ulawstream]
80 | ;mode=custom
81 | ;application=/usr/bin/streamplayer 192.168.100.52 888
82 | ;format=ulaw
83 |
84 | ; mpg123 on Solaris does not always exit properly; madplay may be a better
85 | ; choice
86 | ;[solaris]
87 | ;mode=custom
88 | ;directory=/var/lib/asterisk/mohmp3
89 | ;application=/site/sw/bin/madplay -Q -o raw:- --mono -R 8000 -a -12
90 |
--------------------------------------------------------------------------------
/asterisk/keys/ca.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,1155DE3A44A4E2CC
4 |
5 | LjO6P6vjBKeoGi/7SY6BYwiqCKgv2l5JKTvg/07Hsz8drsTj4VxtD5K3jrKETzqv
6 | rj/ahHPrI1UWa4UPCZkhgoaVmeIQDAA7N+7XNI8Z/U7lX6+BcchnGpUdEI7+Gt5T
7 | aMSOx+QUcUAxmTKo51IhORaMeu+BUKeShAmtn/14WS0ccaLLsRHpBszqRs0yxsSC
8 | RLpHwxMJSYzdCu70AlAt/LAa7nZLfYrcj8lbrTcWYGYtVSxnpKvK4s2so1HYsPVw
9 | s1Zj5LHSCSX08Bj6PAkVrSUPSKgvMI5JWmLiSZqBblNuQ2N73ypoxU0o7NWibER6
10 | BdVaxVmr9y35WZ7ljC5BaWTHAvYjv2SHue+LX+tqo20kmxX0nEpmtHwe/ZAPXVar
11 | 59TXFd6XTCqbHYcen3qGfAI/7nRCxvL+AsvenRoKFjq0g0kLzdDl3m60d/fFS6eJ
12 | mipcz3i41m2JAj9rUuYzaqjyvLzs0ZWYIMIOSxMOMZg9PZemD7HlCwhv51N3Zib8
13 | lllWMbhDABNB4Y1wwq0dTqbhV9I6O5vNe7/0AdlC7b1r49nXtWnVWA9n5TsIdcaO
14 | WnvM9jlru1ReOVx/FG2PgAGO9sU7t8wB+RHJN3c62wtWYQ4W0uSun8ZobF8Em1i/
15 | AW44A03dz1k6tbnxPCZpVbPHk5pDjoRjk3+jzVkNUw+xwi7QkQxMP1HEMpGIoTaY
16 | AqO9b3mGicS+bWIo6++3Q7Nttb0S3iqbS9p3Z/2RWKnXYSyjPXKndeMBz0zYeUQM
17 | PWXYZIjIq8B7thrKsqUHHEaL2f7en3pzckRSK8F+GC8wp2JY47eTaR9AG5s6fd8m
18 | RI6rPq1JW0ysZvTymD6yrBjLltGV6O9W6D6kxjXfleUEbQmC42j860xUacEHJXWM
19 | dG1RtUr2rDOtLj2mzR7+EWNdt5SACd76XMTiIGTpsf/D4j7m9oqXEjLIkAtw5hrP
20 | bhj26/MaF922wIgmPD+JbEkL7it8hy05kYcjpMe8P0TCsPhFFMo2H/hf4fQ0viWY
21 | oWVt99e0iiumSGYFJluxwGx0tljCVkmBnERPUmvhRmMLwF/k5NrcMm7dphli+gTD
22 | gi/NXBh5Ccan8CXQFTbJT11rnTUthQO0/EtBt1zk0Q0knVWJjggmMC7alpkmnJMP
23 | X+R/jLZE1nK++FgC2Majjk+GE9eoDaVdEJpUK68Or+tUyN2pcWwgrcudQXkQzkIi
24 | 1LXq+Uk16naO/tP0yFoaJHLRIGujsCeOhL9z1BMxoP/cwuwFb9BhItoW4uElvzej
25 | uGCGfLlISTtZ91ZLZJW8KQk21UOJF/EfCW7ZrAWWc8PezjtXGIWbu/XTnlsrIgaP
26 | dOzKv8yfhK+e3sArRA0Wj8HTTAvk00ghE1713+mH12BienQih6lVYYRWWSFx24qZ
27 | OeztCLZtrPAK6c7+UtLH7VvqwqgmOrWxT8cz2B+bGOHs8QpKYgsR3hrOmTiFn6sy
28 | G/6eG9Ph1kydVr7OLpPqso/av8+5Wl94ocnmkHTCRNm22BhKKyntbOcA75LW/5VO
29 | zFXiK2M9gT89RXaP2eYikcp5mHN7Kqo0iG6atka7dL3eUvVeGTtYm1yrbrwHw5n8
30 | nmOVccxgbtF1E5ziUxx4soZ3PNSc13/zaIHqu7KkNnSftnH0R4d0d0KxKbHp0d4Z
31 | ZGZUd6WF81Gz2N4ut5+GZW2WoszwI0jp8yI04ZX4jqPWWwGPQjRtbCIqqo+gOoNB
32 | 3z22pDFHfF2BJiQ7lVZfJVJTKSy9aLxpykBLXb8e/IP5zkS7ut0bThF9zepiZaym
33 | sUKO/yXTG8Is82WvckdrWwJv1ld0nMwnQHlnls9aHBds3OkYYn3Zhmg0RygVmQZD
34 | Iv/P/1AULB9gBxAxXF+RA0fgfH6UU81Ao2lcPGxwW6YXWV0lbb/U/tlafhTZpMcA
35 | wvrg9djx+ua1GvTtRg/MNhOaHgwM7nhf1Pga73aROpZRZJs/nH1CxtWOpzaLRG74
36 | 4aHW9v0zzYXHf428FZBCh0CbT18GNFbGjBeq05DpqHjJRrJb3E1XKh9x+NmnmV4o
37 | UgVGNgOf3A0zcSBwC4dK5Mpzy17WvSkscZbpjgj6ApzajkjRbHVsqOaWZl1NblR/
38 | fC1kMUupYLvkP2AssC1NGMt/HF4eAB2FMnnc8SkPoPnYPXALUtwEEKLKVsrS+Xo4
39 | gymzQAJkO0gxU7gtdKTQE71jaCq05WMTdBQyRcJ+bIY3+97Ri1x7BF9R3Fli0VPl
40 | 7xUS/CWHbmCNzQ5VRxlEGk93ztEgO+ibKu05kDkBCbU0En4zKmmvZkXCas3tjgLs
41 | +Xk2h4Du/wNToCNoUI8pP8rOiYy/+l6PzNNKTeVfbpyAqwKBd+ZvaJx1Q1v0mpCm
42 | gcM+Gl8t291txyrIVtMpTv/0oaNLYwbjMlIYxv+nDWYctJvzHPqyCKfx6gqb+EPc
43 | Ii8Qv/8j+ozgZJIIeoVfDQYtw6FpC7+UkOMxmq9WGjvOf4jRJSFL8NiGpQICDg3r
44 | ai7T22ei/9IO6eL8QyQTDpTzP6FzQXPOrLsJjn4a+8HbaahWrYSSm5DUSTbnwXb0
45 | Uzec4vxyY4IEaMxkcVGY558+1vvJFYebZVOjCzYVmj4i43DwgVJCMRnJD7njceF4
46 | D1k0BMPEt50Cn/aNKCOZZAiOiEuMMRBYqFkM87bDLRRakxCpSzpe9248ueJD7YD0
47 | 8qoIIjj+FKinu/JhVcWOL4NPfp1VqLkGQciv4IpO2vGMQnEjKtaxWKdAoIR9fzCQ
48 | NivT9+nlogo0xXMSJWDyq7G5oBsldE8fv8rBZcMepsehesUJ7ReiNPwWK55LCOGb
49 | DaqOxlY10ViB2F/jUZ6EdIqfmn4tGI1sH1jVFdH5tpMyH8+g3w7Oi68A+OVWoiw/
50 | AA24Ii3a1QaSserDvD+Z9lrm0F0yprd94c7HBMuNmUabwuZ8XygzEK9yiYafE3Ae
51 | n9hN6gYvhovVyeX0zjmklNUBQTfr4+Dia6V73q6TrSLmcsKfz80vf/AFS0M5tth8
52 | Xusxw+fYz22zd6slowRbJlh9GjPJO1D7sb1VId5DIrLED6WB3avRcszXz+1ne6Cj
53 | Cxb8hL3Seogm0+rXFhD1kGMFU8+QBsUphEFqy38Wz+vAbNrp6tfKLkHI7nJEN+/q
54 | -----END RSA PRIVATE KEY-----
55 |
--------------------------------------------------------------------------------
/asterisk/configs/http.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; Asterisk Builtin mini-HTTP server
3 | ;
4 | ;
5 | ; Note about Asterisk documentation:
6 | ; If Asterisk was installed from a tarball, then the HTML documentation should
7 | ; be installed in the static-http/docs directory which is
8 | ; (/var/lib/asterisk/static-http/docs) on linux by default. If the Asterisk
9 | ; HTTP server is enabled in this file by setting the "enabled", "bindaddr",
10 | ; and "bindport" options, then you should be able to view the documentation
11 | ; remotely by browsing to:
12 | ; http://:/static/docs/index.html
13 | ;
14 | [general]
15 | ;
16 | ; Whether HTTP/HTTPS interface is enabled or not. Default is no.
17 | ; This also affects manager/rawman/mxml access (see manager.conf)
18 | ;
19 | enabled=yes
20 | ;
21 | ; Address to bind to, both for HTTP and HTTPS. You MUST specify
22 | ; a bindaddr in order for the HTTP server to run. There is no
23 | ; default value.
24 | ;
25 | bindaddr=0.0.0.0
26 | ;
27 | ; Port to bind to for HTTP sessions (default is 8088)
28 | ;
29 | bindport=8088
30 | ;
31 | ; Prefix allows you to specify a prefix for all requests
32 | ; to the server. The default is blank. If uncommented
33 | ; all requests must begin with /asterisk
34 | ;
35 | ;prefix=asterisk
36 | ;
37 | ; sessionlimit specifies the maximum number of httpsessions that will be
38 | ; allowed to exist at any given time. (default: 100)
39 | ;
40 | ;sessionlimit=100
41 | ;
42 | ; session_inactivity specifies the number of milliseconds to wait for
43 | ; more data over the HTTP connection before closing it.
44 | ;
45 | ; Default: 30000
46 | ;session_inactivity=30000
47 | ;
48 | ; session_keep_alive specifies the number of milliseconds to wait for
49 | ; the next HTTP request over a persistent connection.
50 | ;
51 | ; Set to 0 to disable persistent HTTP connections.
52 | ; Default: 15000
53 | ;session_keep_alive=15000
54 | ;
55 | ; Whether Asterisk should serve static content from static-http
56 | ; Default is no.
57 | ;
58 | enablestatic=yes
59 | ;
60 | ; Redirect one URI to another. This is how you would set a
61 | ; default page.
62 | ; Syntax: redirect=
63 | ; For example, if you are using the Asterisk-gui,
64 | ; it is convenient to enable the following redirect:
65 | ;
66 | ;redirect = / /static/config/index.html
67 | ;
68 | ; HTTPS support. In addition to enabled=yes, you need to
69 | ; explicitly enable tls, define the port to use,
70 | ; and have a certificate somewhere.
71 | ;tlsenable=yes ; enable tls - default no.
72 | ;tlsbindaddr=0.0.0.0:8089 ; address and port to bind to - default is bindaddr and port 8089.
73 | ;
74 | ;tlscertfile= ; path to the certificate file (*.pem) only.
75 | ;tlsprivatekey= ; path to private key file (*.pem) only.
76 | ; If no path is given for tlscertfile or tlsprivatekey, default is to look in current
77 | ; directory. If no tlsprivatekey is given, default is to search tlscertfile for private key.
78 | ;
79 | ; To produce a certificate you can e.g. use openssl. This places both the cert and
80 | ; private in same .pem file.
81 | ; openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
82 | ;
83 | ; The post_mappings section maps URLs to real paths on the filesystem. If a
84 | ; POST is done from within an authenticated manager session to one of the
85 | ; configured POST mappings, then any files in the POST will be placed in the
86 | ; configured directory.
87 | ;
88 | ;[post_mappings]
89 | ;
90 | ; NOTE: You need a valid HTTP AMI mansession_id cookie with the manager
91 | ; config permission to POST files.
92 | ;
93 | ; In this example, if the prefix option is set to "asterisk", then using the
94 | ; POST URL: /asterisk/uploads will put files in /var/lib/asterisk/uploads/.
95 | ;uploads = /var/lib/asterisk/uploads/
96 | ;
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Asterisk "Awesome Conference"
2 |
3 | An awesome conference, consisting of:
4 | * An [Asterisk](http://asterisk.org)/ARI driven video conferencing application
5 | * A [Respoke](https://www.respoke.io) driven WebRTC client
6 |
7 | To run the awesome conference, you will need a valid [Respoke](https://www.respoke.io) account.
8 |
9 | 
10 |
11 | ## Asterisk/ARI
12 |
13 | Asterisk is deployed in a Docker container bound to the host network. The configuration of Asterisk is static, and all relevant configuration bits as well as control of the ARI application is done by the remote application implemented in `awesome-conference`.
14 |
15 | The ARI application will toss all inbound Respoke WebRTC channels into a mixing bridge. The mixing bridge, by default, will relay the active speaker's video stream to the other participants. If a signal is received from a participant to lock onto a particular video source, then the video stream in the bridge will be set to that participant.
16 |
17 | ## Respoke
18 |
19 | The Respoke client displays the video stream from the conference, along with small pictures of all of the participants in the conference. The pictures of the participants update periodically. If a picture is selected, the video stream is switched to that participant.
20 |
21 | # Configuration
22 |
23 | Because Docker is used to build and run the services, all configuration of the services is done via environment variables passed into the Docker container. Configuration for your deployment should be done in the `docker-compose.yml` file.
24 |
25 | ## Mandatory Configuration
26 |
27 | ### `awesome-conference`
28 |
29 | * `APP_SECRET`: Your Respoke App Secret
30 | * `APP_ID`: Your Respoke App ID
31 | * `ENDPOINT_ROLE_ID`: A role ID that you've created for you application. The role should have full Global Group Permissions and full Event permissions.
32 |
33 | ## Optional Configuration
34 |
35 | ### `asterisk`
36 |
37 | * `APPLICATION_NAME`: The name of the Respoke application.
38 | * `ARI_PASSWORD`: Our ARI password. Change this if you want to be secure, leave it as is to live dangerously.
39 | * `RESPOKE_ENDPOINT`: The name of the Respoke endpoint Asterisk uses that other clients will establish a call to.
40 |
41 | ### `awesome-conference`
42 |
43 | * `PORT`: The port the conference runs on. Defaults to `3000`.
44 | * `HOST`: The external IP address that we advertise. This should be provided automatically by the `up.sh` script.
45 | * `APPLICATION_NAME`: The name of the Respoke application.
46 | * `ARI_PASSWORD`: Our ARI password. Change this if you want to be secure, leave it as is to live dangerously.
47 | * `RESPOKE_ENDPOINT`: The name of the Respoke endpoint Asterisk uses that other clients will establish a call to.
48 |
49 | # Building/Running
50 |
51 | This project uses [Docker-Compose](https://docs.docker.com/compose/) for fun, profit, and/or pain. Because we have to pass in the determined external IP address, it is recommended that you use the `up.sh` script to invoke the services.
52 |
53 | ```
54 | $ ./up.sh
55 | ```
56 |
57 | # Notes
58 |
59 | * The project assumes your Respoke application is in development mode, despite asking for a `ENDPOINT_ROLE_ID`. That should probably be fixed.
60 | * My CSS skills are abysmal. In my defense, I copied most of it from Jeff Parrish's awesome [YoDude](https://github.com/respoke/yodude).
61 | * It should go without saying that this is a demo application. Take everything with a healthy dose of skepticism. You should also assume that just about everything is not as secure as it should be.
62 | * The certificate used is self-signed.
63 | * New participants won't be informed of the current video source. Making that function is an exercise for the reader.
64 | * If your picture box remains gray, then for some reason, the client application couldn't grab the webcam. Refresh.
65 | * No video is provided when there is only one participant.
66 |
--------------------------------------------------------------------------------
/awesome-conference/src/services/conference.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const log = require('../lib/log');
4 |
5 | /**
6 | * Our super awesome conference
7 | */
8 | class Conference {
9 |
10 | constructor(respokeClient, ariClient) {
11 | let endpointsToChannels = {};
12 | let channelsToEndpoints = {};
13 |
14 | respokeClient.groups.join({groupId: 'conference'});
15 | respokeClient.on('pubsub', (message) => {
16 | if (message.message.messageType !== 'updateVideoSource') {
17 | return;
18 | }
19 |
20 | log.debug({respokeMessage: message.message}, 'Received');
21 |
22 | const endpointId = message.message.endpointId;
23 | const channel = endpointsToChannels[endpointId];
24 |
25 | if (!channel) {
26 | log.warn({endpointId}, 'Unable to find channel');
27 | return;
28 | }
29 |
30 | ariClient.bridges.list()
31 | .then(bridges => {
32 | const bridge = bridges.filter(candidate => candidate.name === 'awesome-conference');
33 |
34 | if (!bridge) {
35 | return Promise.reject();
36 | }
37 |
38 | // There should be only one
39 | return bridge[0].setVideoSource({channelId: channel});
40 | });
41 | });
42 |
43 | function bridge_video_source_change(event, bridge) {
44 | const endpointId = channelsToEndpoints[bridge.video_source_id];
45 |
46 | if (!endpointId) {
47 | return;
48 | }
49 |
50 | respokeClient.groups.publish({
51 | groupId: 'conference',
52 | message: { messageType: 'videoSourceSet', endpointId }
53 | });
54 | log.info({bridge, endpointId}, `Video source is now ${endpointId} (${bridge.video_source_id})`);
55 | }
56 |
57 | function stasis_start_handler(event, channel) {
58 | channel.answer()
59 | .then(() => {
60 | return channel.getChannelVar({
61 | variable: 'CHANNEL(remote)'
62 | }).then(variable => {
63 | endpointsToChannels[variable.value] = channel.id;
64 | channelsToEndpoints[channel.id] = variable.value;
65 | log.info(`Participant ${variable.value} is ${channel.id}`);
66 | });
67 | })
68 | .then(() => {
69 | // Create or obtain the one and only conference bridge
70 | return ariClient.bridges.list();
71 | })
72 | .then(bridges => {
73 | const bridge = bridges.filter(candidate => candidate.name === 'awesome-conference');
74 |
75 | if (bridge.length === 0) {
76 | log.info('Creating our awesome conference');
77 |
78 | return ariClient.bridges.create({
79 | type: 'mixing,dtmf_events',
80 | name: 'awesome-conference'
81 | });
82 | }
83 | return Promise.resolve(bridge[0]);
84 | })
85 | .then(bridge => {
86 | // Join the bridge!
87 | log.info({ channel, bridge }, 'Joining bridge');
88 | return bridge.addChannel({ channel: channel.id });
89 | });
90 | }
91 |
92 | function stasis_end_handler(event, channel) {
93 | log.info({channel}, 'Left app/bridge');
94 | const endpointId = channelsToEndpoints[channel.id];
95 | delete channelsToEndpoints[channel.id];
96 | delete endpointsToChannels[endpointId];
97 | }
98 |
99 | ariClient.on('StasisStart', stasis_start_handler);
100 | ariClient.on('StasisEnd', stasis_end_handler);
101 | ariClient.on('BridgeVideoSourceChanged', bridge_video_source_change);
102 | }
103 | }
104 |
105 | module.exports.Conference = Conference;
106 |
--------------------------------------------------------------------------------
/asterisk/configs/asterisk.conf:
--------------------------------------------------------------------------------
1 | [directories](!)
2 | astetcdir => /etc/asterisk
3 | astmoddir => /usr/lib/asterisk/modules
4 | astvarlibdir => /var/lib/asterisk
5 | astdbdir => /var/lib/asterisk
6 | astkeydir => /var/lib/asterisk
7 | astdatadir => /var/lib/asterisk
8 | astagidir => /var/lib/asterisk/agi-bin
9 | astspooldir => /var/spool/asterisk
10 | astrundir => /var/run/asterisk
11 | astlogdir => /var/log/asterisk
12 | astsbindir => /usr/sbin
13 |
14 | [options]
15 | ;verbose = 3
16 | ;debug = 3
17 | ;alwaysfork = yes ; Same as -F at startup.
18 | ;nofork = yes ; Same as -f at startup.
19 | ;quiet = yes ; Same as -q at startup.
20 | ;timestamp = yes ; Same as -T at startup.
21 | ;execincludes = yes ; Support #exec in config files.
22 | ;console = yes ; Run as console (same as -c at startup).
23 | ;highpriority = yes ; Run realtime priority (same as -p at
24 | ; startup).
25 | ;initcrypto = yes ; Initialize crypto keys (same as -i at
26 | ; startup).
27 | ;nocolor = yes ; Disable console colors.
28 | ;dontwarn = yes ; Disable some warnings.
29 | ;dumpcore = yes ; Dump core on crash (same as -g at startup).
30 | ;languageprefix = yes ; Use the new sound prefix path syntax.
31 | ;systemname = my_system_name ; Prefix uniqueid with a system name for
32 | ; Global uniqueness issues.
33 | autosystemname = yes ; Automatically set systemname to hostname,
34 | ; uses 'localhost' on failure, or systemname if
35 | ; set.
36 | ;mindtmfduration = 80 ; Set minimum DTMF duration in ms (default 80 ms)
37 | ; If we get shorter DTMF messages, these will be
38 | ; changed to the minimum duration
39 | ;maxcalls = 10 ; Maximum amount of calls allowed.
40 | ;maxload = 0.9 ; Asterisk stops accepting new calls if the
41 | ; load average exceed this limit.
42 | ;maxfiles = 1000 ; Maximum amount of openfiles.
43 | ;minmemfree = 1 ; In MBs, Asterisk stops accepting new calls if
44 | ; the amount of free memory falls below this
45 | ; watermark.
46 | ;cache_record_files = yes ; Cache recorded sound files to another
47 | ; directory during recording.
48 | ;record_cache_dir = /tmp ; Specify cache directory (used in conjunction
49 | ; with cache_record_files).
50 | ;transmit_silence = yes ; Transmit silence while a channel is in a
51 | ; waiting state, a recording only state, or
52 | ; when DTMF is being generated. Note that the
53 | ; silence internally is generated in raw signed
54 | ; linear format. This means that it must be
55 | ; transcoded into the native format of the
56 | ; channel before it can be sent to the device.
57 | ; It is for this reason that this is optional,
58 | ; as it may result in requiring a temporary
59 | ; codec translation path for a channel that may
60 | ; not otherwise require one.
61 | ;transcode_via_sln = yes ; Build transcode paths via SLINEAR, instead of
62 | ; directly.
63 | runuser = asterisk ; The user to run as.
64 | rungroup = asterisk ; The group to run as.
65 | ;lightbackground = yes ; If your terminal is set for a light-colored
66 | ; background.
67 | ;forceblackbackground = yes ; Force the background of the terminal to be
68 | ; black, in order for terminal colors to show
69 | ; up properly.
70 | defaultlanguage = en ; Default language
71 | documentation_language = en_US ; Set the language you want documentation
72 | ; displayed in. Value is in the same format as
73 | ; locale names.
74 | ;hideconnect = yes ; Hide messages displayed when a remote console
75 | ; connects and disconnects.
76 | ;lockconfdir = no ; Protect the directory containing the
77 | ; configuration files (/etc/asterisk) with a
78 | ; lock.
79 | ;stdexten = gosub ; How to invoke the extensions.conf stdexten.
80 | ; macro - Invoke the stdexten using a macro as
81 | ; done by legacy Asterisk versions.
82 | ; gosub - Invoke the stdexten using a gosub as
83 | ; documented in extensions.conf.sample.
84 | ; Default gosub.
85 | ;live_dangerously = no ; Enable the execution of 'dangerous' dialplan
86 | ; functions from external sources (AMI,
87 | ; etc.) These functions (such as SHELL) are
88 | ; considered dangerous because they can allow
89 | ; privilege escalation.
90 | ; Default no
91 |
92 | ; Changing the following lines may compromise your security.
93 | ;[files]
94 | ;astctlpermissions = 0660
95 | ;astctlowner = root
96 | ;astctlgroup = apache
97 | ;astctl = asterisk.ctl
98 |
--------------------------------------------------------------------------------
/awesome-conference/src/services/asterisk.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const log = require('../lib/log');
4 | const ari = require('ari-client');
5 |
6 | /**
7 | * Class for managing an Asterisk instance
8 | */
9 | class AsteriskWrapper {
10 |
11 | /**
12 | * Manage our Asterisk instance
13 | *
14 | * @param {object} [config]
15 | */
16 | constructor(config) {
17 | this.url = `http://${config.asterisk.host}:8088`;
18 | this.username = config.asterisk.username;
19 | this.password = config.asterisk.password;
20 | this.appname = config.asterisk.application;
21 | this.app_secret = config.respoke.app_secret;
22 | this.endpoint = config.respoke.endpoint;
23 | this.client = undefined;
24 | }
25 |
26 | /**
27 | * Connect to the Asterisk instance
28 | *
29 | * @returns {Promise.}
30 | */
31 | connect() {
32 | const that = this;
33 |
34 | if (this.client) {
35 | return Promise.reject('Client already connected');
36 | }
37 |
38 | log.debug({ url: this.url }, 'Connecting to Asterisk');
39 |
40 | return ari.connect(this.url, this.username, this.password)
41 | .then(_client => {
42 | that.client = _client;
43 | return _client;
44 | });
45 | }
46 |
47 | /**
48 | * Set up the Asterisk instance's Respoke information
49 | *
50 | * @returns {Promise}
51 | */
52 | provision() {
53 | if (!this.client) {
54 | return Promise.reject('Not connected to Asterisk!');
55 | }
56 |
57 | return this.client.asterisk.updateObject({
58 | configClass: 'res_respoke',
59 | objectType: 'app',
60 | id: `${this.appname}`,
61 | fields: [
62 | { attribute: 'app_secret', value: `${this.app_secret}`}
63 | ]
64 | }).then(() => {
65 | return this.client.asterisk.updateObject({
66 | configClass: 'res_respoke',
67 | objectType: 'endpoint',
68 | id: `${this.endpoint}`,
69 | fields: [
70 | { attribute: 'app', value: `${this.appname}` },
71 | { attribute: 'context', value: 'inbound' },
72 | { attribute: 'transport', value: `${this.endpoint}` },
73 | { attribute: 'turn', value: 'true' },
74 | { attribute: 'allow', value: '!all,opus,ulaw,h264' },
75 | { attribute: 'dtls_verify', value: 'no' },
76 | { attribute: 'dtls_cert_file', value: '/etc/asterisk/keys/asterisk.pem' },
77 | { attribute: 'dtls_ca_file', value: '/etc/asterisk/keys/ca.crt' },
78 | { attribute: 'dtls_setup', value: 'actpass' }
79 | ]});
80 | }).then(() => {
81 | return this.client.asterisk.updateObject({
82 | configClass: 'res_respoke',
83 | objectType: 'endpoint',
84 | id: 'anonymous',
85 | fields: [
86 | { attribute: 'app', value: `${this.appname}` },
87 | { attribute: 'context', value: 'inbound' },
88 | { attribute: 'transport', value: `${this.endpoint}` },
89 | { attribute: 'turn', value: 'true' },
90 | { attribute: 'allow', value: '!all,opus,ulaw,h264' },
91 | { attribute: 'dtls_verify', value: 'no' },
92 | { attribute: 'dtls_cert_file', value: '/etc/asterisk/keys/asterisk.pem' },
93 | { attribute: 'dtls_ca_file', value: '/etc/asterisk/keys/ca.crt' },
94 | { attribute: 'dtls_setup', value: 'actpass' },
95 | { attribute: 'register', value: 'false' }
96 | ]});
97 | });
98 | }
99 |
100 | /**
101 | * Connect the Conferencing Application
102 | *
103 | * @returns {Promise}
104 | */
105 | connectConferenceApp() {
106 | const that = this;
107 |
108 | if (!this.client) {
109 | return Promise.reject('Not connected to Asterisk!');
110 | }
111 |
112 | this.client.on('WebSocketMaxRetries', err => {
113 | log.fatal({ err }, 'ARI Disconnected');
114 | // Exit so that the whole process will reconnect
115 | process.exit(1);
116 | });
117 | this.client.on('WebSocketReconnecting', err => {
118 | log.warn({ err }, 'WebSocket Reconnecting');
119 | });
120 | this.client.on('WebSocketConnected', err => {
121 | log.info({ err }, 'WebSocket Connected');
122 | });
123 |
124 | return this.client.start([ this.appname ])
125 | .then(() => {
126 | log.info(`ARI application ${this.appname} registered`);
127 |
128 | return this.client;
129 | });
130 | }
131 |
132 | }
133 |
134 | module.exports.AsteriskWrapper = AsteriskWrapper;
135 |
--------------------------------------------------------------------------------
/asterisk/configs/logger.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; Logging Configuration
3 | ;
4 | ; In this file, you configure logging to files or to
5 | ; the syslog system.
6 | ;
7 | ; "logger reload" at the CLI will reload configuration
8 | ; of the logging system.
9 |
10 | [general]
11 | ;
12 | ; Customize the display of debug message time stamps
13 | ; this example is the ISO 8601 date format (yyyy-mm-dd HH:MM:SS)
14 | ;
15 | ; see strftime(3) Linux manual for format specifiers. Note that there is also
16 | ; a fractional second parameter which may be used in this field. Use %1q
17 | ; for tenths, %2q for hundredths, etc.
18 | ;
19 | ;dateformat=%F %T ; ISO 8601 date format
20 | ;dateformat=%F %T.%3q ; with milliseconds
21 | ;
22 | ;
23 | ; This makes Asterisk write callids to log messages
24 | ; (defaults to yes)
25 | ;use_callids = no
26 | ;
27 | ; This appends the hostname to the name of the log files.
28 | ;appendhostname = yes
29 | ;
30 | ; This determines whether or not we log queue events to a file
31 | ; (defaults to yes).
32 | ;queue_log = no
33 | ;
34 | ; Determines whether the queue_log always goes to a file, even
35 | ; when a realtime backend is present (defaults to no).
36 | ;queue_log_to_file = yes
37 | ;
38 | ; Set the queue_log filename
39 | ; (defaults to queue_log)
40 | ;queue_log_name = queue_log
41 | ;
42 | ; When using realtime for the queue log, use GMT for the timestamp
43 | ; instead of localtime. The default of this option is 'no'.
44 | ;queue_log_realtime_use_gmt = yes
45 | ;
46 | ; Log rotation strategy:
47 | ; none: Do not perform any logrotation at all. You should make
48 | ; very sure to set up some external logrotate mechanism
49 | ; as the asterisk logs can get very large, very quickly.
50 | ; sequential: Rename archived logs in order, such that the newest
51 | ; has the highest sequence number [default]. When
52 | ; exec_after_rotate is set, ${filename} will specify
53 | ; the new archived logfile.
54 | ; rotate: Rotate all the old files, such that the oldest has the
55 | ; highest sequence number [this is the expected behavior
56 | ; for Unix administrators]. When exec_after_rotate is
57 | ; set, ${filename} will specify the original root filename.
58 | ; timestamp: Rename the logfiles using a timestamp instead of a
59 | ; sequence number when "logger rotate" is executed.
60 | ; When exec_after_rotate is set, ${filename} will
61 | ; specify the new archived logfile.
62 | ;rotatestrategy = rotate
63 | ;
64 | ; Run a system command after rotating the files. This is mainly
65 | ; useful for rotatestrategy=rotate. The example allows the last
66 | ; two archive files to remain uncompressed, but after that point,
67 | ; they are compressed on disk.
68 | ;
69 | ; exec_after_rotate=gzip -9 ${filename}.2
70 | ;
71 | ;
72 | ; For each file, specify what to log.
73 | ;
74 | ; For console logging, you set options at start of
75 | ; Asterisk with -v for verbose and -d for debug
76 | ; See 'asterisk -h' for more information.
77 | ;
78 | ; Directory for log files is configures in asterisk.conf
79 | ; option astlogdir
80 | ;
81 | [logfiles]
82 | ;
83 | ; Format is "filename" and then "levels" of debugging to be included:
84 | ; debug
85 | ; notice
86 | ; warning
87 | ; error
88 | ; verbose()
89 | ; dtmf
90 | ; fax
91 | ; security
92 | ;
93 | ; Special filename "console" represents the root console
94 | ;
95 | ; Filenames can either be relative to the standard Asterisk log directory
96 | ; (see 'astlogdir' in asterisk.conf), or absolute paths that begin with
97 | ; '/'.
98 | ;
99 | ; Verbose takes an optional argument, in the form of an integer level.
100 | ; Verbose messages with higher levels will not be logged to the file. If
101 | ; the verbose level is not specified, it will log verbose messages following
102 | ; the current level of the root console.
103 | ;
104 | ; Special level name "*" means all levels, even dynamic levels registered
105 | ; by modules after the logger has been initialized (this means that loading
106 | ; and unloading modules that create/remove dynamic logger levels will result
107 | ; in these levels being included on filenames that have a level name of "*",
108 | ; without any need to perform a 'logger reload' or similar operation).
109 | ; Note that there is no value in specifying both "*" and specific level names
110 | ; for a filename; the "*" level means all levels. The only exception is if
111 | ; you need to specify a specific verbose level. e.g, "verbose(3),*".
112 | ;
113 | ; We highly recommend that you DO NOT turn on debug mode if you are simply
114 | ; running a production system. Debug mode turns on a LOT of extra messages,
115 | ; most of which you are unlikely to understand without an understanding of
116 | ; the underlying code. Do NOT report debug messages as code issues, unless
117 | ; you have a specific issue that you are attempting to debug. They are
118 | ; messages for just that -- debugging -- and do not rise to the level of
119 | ; something that merit your attention as an Asterisk administrator. Debug
120 | ; messages are also very verbose and can and do fill up logfiles quickly;
121 | ; this is another reason not to have debug mode on a production system unless
122 | ; you are in the process of debugging a specific issue.
123 | ;
124 | ;debug => debug
125 | ;security => security
126 | console => notice,warning,error
127 | ;console => notice,warning,error,debug
128 | messages => notice,warning,error
129 | ;full => notice,warning,error,debug,verbose,dtmf,fax
130 |
131 | ;syslog keyword : This special keyword logs to syslog facility
132 | ;
133 | ;syslog.local0 => notice,warning,error
134 | ;
135 |
--------------------------------------------------------------------------------
/asterisk/configs/modules.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; Asterisk configuration file
3 | ;
4 | ; Module Loader configuration file
5 | ;
6 |
7 | [modules]
8 |
9 | ; NOTE:
10 | ; We are commenting out autoload=yes here, as it tends to make a system
11 | ; less "clean". If you want more modules, uncomment this.
12 | ; autoload=yes
13 |
14 | ; Respoke
15 | load => chan_respoke
16 | load => res_respoke
17 | load => res_respoke_session
18 | load => res_socket_io
19 | load => res_socket_io_websocket
20 | load => res_respoke_endpoint_identifier_from
21 | load => res_respoke_endpoint_identifier_anonymous
22 | load => func_respoke_endpoint
23 | load => func_respoke_metadata
24 |
25 |
26 | ; Applications
27 | load => app_playback
28 | load => app_dial
29 | load => app_echo
30 | load => app_exec
31 | load => app_read
32 | load => app_stack
33 | load => app_stasis
34 | load => app_userevent
35 | load => app_verbose
36 | load => res_agi
37 |
38 | ; Bridges
39 | load => bridge_builtin_features
40 | load => bridge_builtin_interval_features
41 | load => bridge_holding
42 | load => bridge_native_rtp
43 | load => bridge_simple
44 | load => bridge_softmix
45 |
46 | ; Channel Drivers
47 | load => chan_bridge_media
48 | load => chan_pjsip
49 |
50 | ; Codecs
51 | load => codec_a_mu
52 | load => codec_adpcm
53 | load => codec_alaw
54 | load => codec_g722
55 | load => codec_g726
56 | load => codec_gsm
57 | load => codec_ilbc
58 | load => codec_lpc10
59 | load => codec_resample
60 | load => codec_ulaw
61 | load => codec_opus
62 |
63 | ; Formats
64 | load => format_g719
65 | load => format_g723
66 | load => format_g726
67 | load => format_g729
68 | load => format_gsm
69 | load => format_h263
70 | load => format_h264
71 | load => format_ilbc
72 | load => format_pcm
73 | load => format_siren14
74 | load => format_siren7
75 | load => format_sln
76 | load => format_wav
77 | load => format_wav_gsm
78 | load => format_ogg_opus
79 |
80 | ; Functions
81 | load => func_base64
82 | load => func_callerid
83 | load => func_channel
84 | load => func_config
85 | ;load => func_curl
86 | load => func_cut
87 | load => func_db
88 | load => func_devstate
89 | load => func_dialplan
90 | load => func_env
91 | load => func_extstate
92 | load => func_global
93 | load => func_groupcount
94 | load => func_hangupcause
95 | load => func_jitterbuffer
96 | load => func_logic
97 | load => func_math
98 | load => func_md5
99 | load => func_module
100 | load => func_periodic_hook
101 | load => func_pjsip_aor
102 | load => func_pjsip_contact
103 | load => func_pjsip_endpoint
104 | load => func_presencestate
105 | load => func_rand
106 | load => func_realtime
107 | load => func_sha1
108 | load => func_sorcery
109 | load => func_sprintf
110 | load => func_srv
111 | load => func_strings
112 | load => func_sysinfo
113 | load => func_talkdetect
114 | load => func_uri
115 | load => func_version
116 | load => func_volume
117 |
118 | ; PBX
119 | load => pbx_config
120 |
121 | ; Resources: ARI/Stasis
122 | load => res_ari
123 | load => res_ari_applications
124 | load => res_ari_asterisk
125 | load => res_ari_bridges
126 | load => res_ari_channels
127 | load => res_ari_device_states
128 | load => res_ari_endpoints
129 | load => res_ari_events
130 | load => res_ari_mailboxes
131 | load => res_ari_model
132 | load => res_ari_playbacks
133 | load => res_ari_recordings
134 | load => res_ari_sounds
135 | load => res_stasis
136 | load => res_stasis_answer
137 | load => res_stasis_device_state
138 | load => res_stasis_mailbox
139 | load => res_stasis_playback
140 | load => res_stasis_recording
141 | load => res_stasis_snoop
142 | load => res_timing_timerfd
143 |
144 | ; Resources: PJSIP
145 | load => res_pjproject
146 | load => res_pjsip
147 | load => res_pjsip_acl
148 | load => res_pjsip_authenticator_digest
149 | load => res_pjsip_caller_id
150 | load => res_pjsip_dialog_info_body_generator
151 | load => res_pjsip_diversion
152 | load => res_pjsip_dtmf_info
153 | load => res_pjsip_empty_info
154 | load => res_pjsip_endpoint_identifier_anonymous
155 | load => res_pjsip_endpoint_identifier_ip
156 | load => res_pjsip_endpoint_identifier_user
157 | load => res_pjsip_exten_state
158 | load => res_pjsip_header_funcs
159 | load => res_pjsip_history
160 | load => res_pjsip_logger
161 | load => res_pjsip_messaging
162 | load => res_pjsip_mwi
163 | load => res_pjsip_mwi_body_generator
164 | load => res_pjsip_nat
165 | load => res_pjsip_notify
166 | load => res_pjsip_outbound_authenticator_digest
167 | load => res_pjsip_outbound_publish
168 | load => res_pjsip_outbound_registration
169 | load => res_pjsip_path
170 | load => res_pjsip_pidf_body_generator
171 | load => res_pjsip_pidf_digium_body_supplement
172 | load => res_pjsip_pidf_eyebeam_body_supplement
173 | load => res_pjsip_publish_asterisk
174 | load => res_pjsip_pubsub
175 | load => res_pjsip_refer
176 | load => res_pjsip_registrar_expire
177 | load => res_pjsip_registrar
178 | load => res_pjsip_rfc3326
179 | load => res_pjsip_sdp_rtp
180 | load => res_pjsip_send_to_voicemail
181 | load => res_pjsip_session
182 | load => res_pjsip_sips_contact
183 | load => res_pjsip_transport_websocket
184 | load => res_pjsip_xpidf_body_generator
185 |
186 | ; Resources: Other
187 | load => res_clioriginate
188 | load => res_format_attr_celt
189 | load => res_format_attr_h263
190 | load => res_format_attr_h264
191 | load => res_format_attr_opus
192 | load => res_format_attr_silk
193 | load => res_http_websocket
194 | load => res_musiconhold
195 | load => res_mutestream
196 | load => res_mwi_external
197 | load => res_rtp_asterisk
198 | load => res_security_log
199 | load => res_sorcery_astdb
200 | load => res_sorcery_config
201 | load => res_sorcery_memory
202 | load => res_sorcery_memory_cache
203 | load => res_sorcery_realtime
204 | load => res_speech
205 | load => res_srtp
206 |
--------------------------------------------------------------------------------
/asterisk/configs/manager.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; AMI - The Asterisk Manager Interface
3 | ;
4 | ; Third party application call management support and PBX event supervision
5 | ;
6 | ; Use the "manager show commands" at the CLI to list available manager commands
7 | ; and their authorization levels.
8 | ;
9 | ; "manager show command " will show a help text.
10 | ;
11 | ; ---------------------------- SECURITY NOTE -------------------------------
12 | ; Note that you should not enable the AMI on a public IP address. If needed,
13 | ; block this TCP port with iptables (or another FW software) and reach it
14 | ; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager
15 | ; interface available over http/https if Asterisk's http server is enabled in
16 | ; http.conf and if both "enabled" and "webenabled" are set to yes in
17 | ; this file. Both default to no. httptimeout provides the maximum
18 | ; timeout in seconds before a web based session is discarded. The
19 | ; default is 60 seconds.
20 | ;
21 | [general]
22 | enabled = no
23 | ;webenabled = yes
24 |
25 | ;port = 5038
26 | ;bindaddr = 0.0.0.0
27 |
28 | ; Parameters that control AMI over TLS. ("enabled" must be set too).
29 | ; You can open a connection to this socket with e.g.
30 | ;
31 | ; openssl s_client -connect my_host:5039
32 | ;
33 | ;tlsenable=no ; set to YES to enable it
34 | ;tlsbindaddr=0.0.0.0:5039 ; address and port to bind to, default to bindaddr and port 5039
35 | ;tlscertfile=/tmp/asterisk.pem ; path to the certificate.
36 | ;tlsprivatekey=/tmp/private.pem ; path to the private key, if no private given,
37 | ; if no tlsprivatekey is given, default is to search
38 | ; tlscertfile for private key.
39 | ;tlscipher= ; string specifying which SSL ciphers to use or not use
40 | ;
41 | ;allowmultiplelogin = yes ; IF set to no, rejects manager logins that are already in use.
42 | ; ; The default is yes.
43 | ;
44 | ;displayconnects = yes
45 | ;
46 | ; Add a Unix epoch timestamp to events (not action responses)
47 | ;
48 | ;timestampevents = yes
49 |
50 | ;brokeneventsaction = yes ; Restore previous behavior that caused the events
51 | ; action to not return a response in certain
52 | ; circumstances. Defaults to 'no'.
53 |
54 | ;
55 | ; Display certain channel variables every time a channel-oriented
56 | ; event is emitted:
57 | ;
58 | ;channelvars = var1,var2,var3
59 |
60 | ; debug = on ; enable some debugging info in AMI messages (default off).
61 | ; Also accessible through the "manager debug" CLI command.
62 |
63 | ; authtimeout specifies the maximum number of seconds a client has to
64 | ; authenticate. If the client does not authenticate beofre this timeout
65 | ; expires, the client will be disconnected. (default: 30 seconds)
66 |
67 | ;authtimeout = 30
68 |
69 | ; authlimit specifies the maximum number of unauthenticated sessions that will
70 | ; be allowed to connect at any given time.
71 |
72 | ;authlimit = 50
73 |
74 | ;httptimeout = 60
75 | ; a) httptimeout sets the Max-Age of the http cookie
76 | ; b) httptimeout is the amount of time the webserver waits
77 | ; on a action=waitevent request (actually its httptimeout-10)
78 | ; c) httptimeout is also the amount of time the webserver keeps
79 | ; a http session alive after completing a successful action
80 |
81 | [asterisk]
82 | secret=asterisk
83 | read=all
84 | write=all
85 |
86 | ;[mark]
87 | ;secret = mysecret
88 | ;deny=0.0.0.0/0.0.0.0
89 | ;permit=209.16.236.73/255.255.255.0
90 | ;acl=named_acl_example ; use a named ACL from acl.conf
91 | ;
92 | ;
93 | ;setvar=PBXACCOUNT=edvina
94 | ; The setvar option defines channel variables that will be set when this account
95 | ; originates a call. You can define multiple setvar= commands for one manager
96 | ; user.
97 | ;
98 | ;eventfilter=Event: Newchannel
99 | ;eventfilter=Channel: (PJ)?SIP/(james|jim|john)-
100 | ;eventfilter=!Channel: DAHDI/
101 | ; The eventfilter option is used to whitelist or blacklist events per user.
102 | ; A filter consists of an (unanchored) regular expression that is run on the
103 | ; entire event data. If the first character of the filter is an exclamation
104 | ; mark (!), the filter is appended to the blacklist instead of the whitelist.
105 | ; After first checking the read access below, the regular expression filters
106 | ; are processed as follows:
107 | ; - If no filters are configured all events are reported as normal.
108 | ; - If there are white filters only: implied black all filter processed first,
109 | ; then white filters.
110 | ; - If there are black filters only: implied white all filter processed first,
111 | ; then black filters.
112 | ; - If there are both white and black filters: implied black all filter processed
113 | ; first, then white filters, and lastly black filters.
114 |
115 | ;
116 | ; If the device connected via this user accepts input slowly,
117 | ; the timeout for writes to it can be increased to keep it
118 | ; from being disconnected (value is in milliseconds)
119 | ;
120 | ; writetimeout = 100
121 | ;
122 | ;displayconnects = yes ; Display on CLI user login/logoff
123 | ;
124 | ; Authorization for various classes
125 | ;
126 | ; Read authorization permits you to receive asynchronous events, in general.
127 | ; Write authorization permits you to send commands and get back responses. The
128 | ; following classes exist:
129 | ;
130 | ; all - All event classes below (including any we may have missed).
131 | ; system - General information about the system and ability to run system
132 | ; management commands, such as Shutdown, Restart, and Reload.
133 | ; call - Information about channels and ability to set information in a
134 | ; running channel.
135 | ; log - Logging information. Read-only. (Defined but not yet used.)
136 | ; verbose - Verbose information. Read-only. (Defined but not yet used.)
137 | ; agent - Information about queues and agents and ability to add queue
138 | ; members to a queue.
139 | ; user - Permission to send and receive UserEvent.
140 | ; config - Ability to read and write configuration files.
141 | ; command - Permission to run CLI commands. Write-only.
142 | ; dtmf - Receive DTMF events. Read-only.
143 | ; reporting - Ability to get information about the system.
144 | ; cdr - Output of cdr_manager, if loaded. Read-only.
145 | ; dialplan - Receive NewExten and VarSet events. Read-only.
146 | ; originate - Permission to originate new calls. Write-only.
147 | ; agi - Output AGI commands executed. Input AGI command to execute.
148 | ; cc - Call Completion events. Read-only.
149 | ; aoc - Permission to send Advice Of Charge messages and receive Advice
150 | ; - Of Charge events.
151 | ; test - Ability to read TestEvent notifications sent to the Asterisk Test
152 | ; Suite. Note that this is only enabled when the TEST_FRAMEWORK
153 | ; compiler flag is defined.
154 | ; security - Security Events. Read-only.
155 | ; message - Permissions to send out of call messages. Write-only
156 | ;
157 | ;read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
158 | ;write = system,call,agent,user,config,command,reporting,originate,message
159 |
160 |
--------------------------------------------------------------------------------
/awesome-conference/src/public/conference.js:
--------------------------------------------------------------------------------
1 | /* global angular */
2 | /* global respoke */
3 | /* global Webcam */
4 | 'use strict';
5 |
6 | var GROUP_NAME = 'conference';
7 |
8 | var conference = angular.module('conference', ['ngResource']);
9 |
10 | function noop() {}
11 |
12 | function uid() {
13 | return Math.random().toString(36).substring(2, 6);
14 | }
15 |
16 | function resetVideos() {
17 | var vids = document.querySelectorAll('video');
18 | var vid;
19 | var newVid;
20 | var parent;
21 | for (var i = 0; i < vids.length; i++) {
22 | vid = vids.item(i);
23 | if (vid.id) {
24 | newVid = document.createElement('video');
25 | newVid.id = vid.id;
26 | parent = vid.parentNode;
27 | parent.removeChild(vid);
28 | parent.appendChild(newVid);
29 | }
30 | }
31 | }
32 |
33 | conference.controller('AppController', ['$rootScope', function ($rootScope) {
34 | $rootScope.people = {};
35 | $rootScope.videoSource = null;
36 | $rootScope.people[$rootScope.myEndpoint] = '';
37 |
38 | $rootScope.startCall = function () {
39 | $rootScope.activeCall = $rootScope.client.startVideoCall({
40 | endpointId: 'webrtc',
41 | videoRemoteElement: document.getElementById('video-remote'),
42 | onConnect: function () {
43 | console.log('Connected!');
44 | },
45 | onHangup: function () {
46 | console.log('Hungup');
47 | $rootScope.activeCall = null;
48 | resetVideos();
49 | },
50 | onError: function (err) {
51 | console.error('Error: ' + err);
52 | $rootScope.activeCall = null;
53 | resetVideos();
54 | }
55 | })
56 | };
57 |
58 | $rootScope.setVideoSource = function (endpointId) {
59 | var group = $rootScope.client.getGroup({ id: GROUP_NAME });
60 | if (!group) { return; } // wha...
61 |
62 | group.sendMessage({
63 | message: { messageType: 'updateVideoSource', endpointId: endpointId },
64 | onError: function (err) { console.error(err); }
65 | });
66 | };
67 |
68 | $rootScope.getPersonClass = function (endpointId) {
69 | if (endpointId !== $rootScope.videoSource) {
70 | return 'person';
71 | }
72 | return 'videoSource';
73 | };
74 | }]);
75 |
76 | conference.directive('pic', [function () {
77 | return {
78 | scope: {
79 | base64: '='
80 | },
81 | template: ''
82 | };
83 | }]);
84 |
85 | conference.directive('camera', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
86 | return {
87 | link: function (/*scope, el*/) {
88 | Webcam.set({
89 | width: 160,
90 | height: 120,
91 | dest_width: 160,
92 | dest_height: 120,
93 | image_format: 'jpeg',
94 | jpeg_quality: 32,
95 | force_flash: false,
96 | flip_horiz: false
97 | });
98 | Webcam.attach('my-camera');
99 | Webcam.on('live', function () {
100 | setInterval(function () {
101 |
102 | var group = $rootScope.client.getGroup({ id: GROUP_NAME });
103 | if (!group) { return; } // respoke not connected
104 |
105 | Webcam.snap(function (dataUri) {
106 | $rootScope.people[$rootScope.myEndpoint] = dataUri;
107 | group.sendMessage({
108 | message: { messageType: 'imageUpdate', image: dataUri},
109 | onError: function (err) { console.error(err); }
110 | });
111 | });
112 |
113 | $timeout(noop);
114 | }, 2500);
115 | });
116 | Webcam.on('error', function (err) {
117 | console.error('Webcamjs Error:', err);
118 | });
119 | },
120 | template: ''
121 | };
122 | }]);
123 |
124 | conference.run(['$rootScope', '$timeout', "$resource", function ($rootScope, $timeout, $resource) {
125 | // respoke.log.setLevel('debug');
126 |
127 | var myEndpoint = uid();
128 | $rootScope.myEndpoint = myEndpoint;
129 | localStorage.setItem('endpointId', myEndpoint);
130 |
131 | var Tokens = $resource('/token');
132 | var token = Tokens.get({endpointId: myEndpoint}, function (authData) {
133 | console.log(authData);
134 |
135 | var client = respoke.createClient({
136 | developmentMode: true,
137 | appId: authData.appId
138 | });
139 |
140 | client.listen('error', function (err) {
141 | console.error(err);
142 | });
143 |
144 | client.listen('message', function (data) {
145 | var imageContents = data.message.message.image;
146 | var endpointId = data.message.endpointId;
147 | var messageType = data.message.message.messageType;
148 |
149 | if (messageType === 'imageUpdate' && endpointId !== 'backend') {
150 | if (!imageContents || !endpointId) {
151 | console.error('No endpointId or imageContents!');
152 | return;
153 | }
154 |
155 | $rootScope.people[endpointId] = imageContents;
156 | } else if (messageType === 'videoSourceSet') {
157 | $rootScope.videoSource = data.message.message.endpointId;
158 | console.log('Video source is now: ' + $rootScope.videoSource);
159 | }
160 |
161 | $timeout(noop);
162 | });
163 |
164 | client.listen('connect', function () {
165 | client.join({
166 | id: GROUP_NAME,
167 | onSuccess: function (group) {
168 | console.log('Joined', group);
169 | group.getMembers().then(function (connections) {
170 | connections.forEach(function (member) {
171 | console.log('Already here', member);
172 | if (member.endpointId !== 'backend') {
173 | $rootScope.people[member.endpointId] = '';
174 | }
175 | });
176 | $timeout(noop);
177 | });
178 | },
179 | onJoin: function (data) {
180 | var endpointId = data.connection.endpointId;
181 |
182 | if (endpointId === 'backend') {
183 | return;
184 | }
185 |
186 | $rootScope.people[endpointId] = '';
187 | $timeout(noop);
188 | },
189 | onLeave: function (data) {
190 | var endpointId = data.connection.endpointId;
191 |
192 | if (endpointId === 'backend') {
193 | return;
194 | }
195 |
196 | $rootScope.people[endpointId] = null;
197 | delete $rootScope.people[endpointId];
198 | $timeout(noop);
199 | }
200 | });
201 | $rootScope.startCall();
202 | });
203 |
204 | client.connect({
205 | endpointId: myEndpoint
206 | });
207 |
208 | $rootScope.client = window.client = client;
209 |
210 | });
211 |
212 | }]);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/asterisk/configs/indications.conf:
--------------------------------------------------------------------------------
1 | ;
2 | ; indications.conf
3 | ;
4 | ; Configuration file for location specific tone indications
5 | ;
6 |
7 | ;
8 | ; NOTE:
9 | ; When adding countries to this file, please keep them in alphabetical
10 | ; order according to the 2-character country codes!
11 | ;
12 | ; The [general] category is for certain global variables.
13 | ; All other categories are interpreted as location specific indications
14 | ;
15 |
16 | [general]
17 | country=us ; default location
18 |
19 |
20 | ; [example]
21 | ; description = string
22 | ; The full name of your country, in English.
23 | ; ringcadence = num[,num]*
24 | ; List of durations the physical bell rings.
25 | ; dial = tonelist
26 | ; Set of tones to be played when one picks up the hook.
27 | ; busy = tonelist
28 | ; Set of tones played when the receiving end is busy.
29 | ; congestion = tonelist
30 | ; Set of tones played when there is some congestion (on the network?)
31 | ; callwaiting = tonelist
32 | ; Set of tones played when there is a call waiting in the background.
33 | ; dialrecall = tonelist
34 | ; Not well defined; many phone systems play a recall dial tone after hook
35 | ; flash.
36 | ; record = tonelist
37 | ; Set of tones played when call recording is in progress.
38 | ; info = tonelist
39 | ; Set of tones played with special information messages (e.g., "number is
40 | ; out of service")
41 | ; 'name' = tonelist
42 | ; Every other variable will be available as a shortcut for the "PlayList" command
43 | ; but will not be used automatically by Asterisk.
44 | ;
45 | ;
46 | ; The tonelist itself is defined by a comma-separated sequence of elements.
47 | ; Each element consist of a frequency (f) with an optional duration (in ms)
48 | ; attached to it (f/duration). The frequency component may be a mixture of two
49 | ; frequencies (f1+f2) or a frequency modulated by another frequency (f1*f2).
50 | ; The implicit modulation depth is fixed at 90%, though.
51 | ; If the list element starts with a !, that element is NOT repeated,
52 | ; therefore, only if all elements start with !, the tonelist is time-limited,
53 | ; all others will repeat indefinitely.
54 | ;
55 | ; concisely:
56 | ; element = [!]freq[+|*freq2][/duration]
57 | ; tonelist = element[,element]*
58 | ;
59 |
60 | [at]
61 | description = Austria
62 | ringcadence = 1000,5000
63 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
64 | dial = 420
65 | busy = 420/400,0/400
66 | ring = 420/1000,0/5000
67 | congestion = 420/200,0/200
68 | callwaiting = 420/40,0/1960
69 | dialrecall = 420
70 | ; RECORDTONE - not specified
71 | record = 1400/80,0/14920
72 | info = 950/330,1450/330,1850/330,0/1000
73 | stutter = 380+420
74 |
75 | [au]
76 | description = Australia
77 | ; Reference http://www.acif.org.au/__data/page/3303/S002_2001.pdf
78 | ; Normal Ring
79 | ringcadence = 400,200,400,2000
80 | ; Distinctive Ring 1 - Forwarded Calls
81 | ; 400,400,200,200,400,1400
82 | ; Distinctive Ring 2 - Selective Ring 2 + Operator + Recall
83 | ; 400,400,200,2000
84 | ; Distinctive Ring 3 - Multiple Subscriber Number 1
85 | ; 200,200,400,2200
86 | ; Distinctive Ring 4 - Selective Ring 1 + Centrex
87 | ; 400,2600
88 | ; Distinctive Ring 5 - Selective Ring 3
89 | ; 400,400,200,400,200,1400
90 | ; Distinctive Ring 6 - Multiple Subscriber Number 2
91 | ; 200,400,200,200,400,1600
92 | ; Distinctive Ring 7 - Multiple Subscriber Number 3 + Data Privacy
93 | ; 200,400,200,400,200,1600
94 | ; Tones
95 | dial = 413+438
96 | busy = 425/375,0/375
97 | ring = 413+438/400,0/200,413+438/400,0/2000
98 | ; XXX Congestion: Should reduce by 10 db every other cadence XXX
99 | congestion = 425/375,0/375,420/375,0/375
100 | callwaiting = 425/200,0/200,425/200,0/4400
101 | dialrecall = 413+438
102 | ; Record tone used for Call Intrusion/Recording or Conference
103 | record = !425/1000,!0/15000,425/360,0/15000
104 | info = 425/2500,0/500
105 | ; Other Australian Tones
106 | ; The STD "pips" indicate the call is not an untimed local call
107 | std = !525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100
108 | ; Facility confirmation tone (eg. Call Forward Activated)
109 | facility = 425
110 | ; Message Waiting "stutter" dialtone
111 | stutter = 413+438/100,0/40
112 | ; Ringtone for calls to Telstra mobiles
113 | ringmobile = 400+450/400,0/200,400+450/400,0/2000
114 |
115 | [bg]
116 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
117 | description = Bulgaria
118 | ringcadence = 1000,4000
119 | ;
120 | dial = 425
121 | busy = 425/500,0/500
122 | ring = 425/1000,0/4000
123 | congestion = 425/250,0/250
124 | callwaiting = 425/150,0/150,425/150,0/4000
125 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
126 | record = 1400/425,0/15000
127 | info = 950/330,1400/330,1800/330,0/1000
128 | stutter = 425/1500,0/100
129 |
130 | [br]
131 | description = Brazil
132 | ringcadence = 1000,4000
133 | dial = 425
134 | busy = 425/250,0/250
135 | ring = 425/1000,0/4000
136 | congestion = 425/250,0/250,425/750,0/250
137 | callwaiting = 425/50,0/1000
138 | ; Dialrecall not used in Brazil standard (using UK standard)
139 | dialrecall = 350+440
140 | ; Record tone is not used in Brazil, use busy tone
141 | record = 425/250,0/250
142 | ; Info not used in Brazil standard (using UK standard)
143 | info = 950/330,1400/330,1800/330
144 | stutter = 350+440
145 |
146 | [be]
147 | description = Belgium
148 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
149 | ringcadence = 1000,3000
150 | dial = 425
151 | busy = 425/500,0/500
152 | ring = 425/1000,0/3000
153 | congestion = 425/167,0/167
154 | callwaiting = 1400/175,0/175,1400/175,0/3500
155 | ; DIALRECALL - not specified
156 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
157 | ; RECORDTONE - not specified
158 | record = 1400/500,0/15000
159 | info = 900/330,1400/330,1800/330,0/1000
160 | stutter = 425/1000,0/250
161 |
162 | [ch]
163 | description = Switzerland
164 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
165 | ringcadence = 1000,4000
166 | dial = 425
167 | busy = 425/500,0/500
168 | ring = 425/1000,0/4000
169 | congestion = 425/200,0/200
170 | callwaiting = 425/200,0/200,425/200,0/4000
171 | ; DIALRECALL - not specified
172 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
173 | ; RECORDTONE - not specified
174 | record = 1400/80,0/15000
175 | info = 950/330,1400/330,1800/330,0/1000
176 | stutter = 425+340/1100,0/1100
177 |
178 | [cl]
179 | description = Chile
180 | ; According to specs from Telefonica CTC Chile
181 | ringcadence = 1000,3000
182 | dial = 400
183 | busy = 400/500,0/500
184 | ring = 400/1000,0/3000
185 | congestion = 400/200,0/200
186 | callwaiting = 400/250,0/8750
187 | dialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400
188 | record = 1400/500,0/15000
189 | info = 950/333,1400/333,1800/333,0/1000
190 | stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400
191 |
192 | [cn]
193 | description = China
194 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
195 | ringcadence = 1000,4000
196 | dial = 450
197 | busy = 450/350,0/350
198 | ring = 450/1000,0/4000
199 | congestion = 450/700,0/700
200 | callwaiting = 450/400,0/4000
201 | dialrecall = 450
202 | record = 950/400,0/10000
203 | info = 450/100,0/100,450/100,0/100,450/100,0/100,450/400,0/400
204 | ; STUTTER - not specified
205 | stutter = 450+425
206 |
207 | [cz]
208 | description = Czech Republic
209 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
210 | ringcadence = 1000,4000
211 | dial = 425/330,0/330,425/660,0/660
212 | busy = 425/330,0/330
213 | ring = 425/1000,0/4000
214 | congestion = 425/165,0/165
215 | callwaiting = 425/330,0/9000
216 | ; DIALRECALL - not specified
217 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425/330,0/330,425/660,0/660
218 | ; RECORDTONE - not specified
219 | record = 1400/500,0/14000
220 | info = 950/330,0/30,1400/330,0/30,1800/330,0/1000
221 | ; STUTTER - not specified
222 | stutter = 425/450,0/50
223 |
224 | [de]
225 | description = Germany
226 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
227 | ringcadence = 1000,4000
228 | dial = 425
229 | busy = 425/480,0/480
230 | ring = 425/1000,0/4000
231 | congestion = 425/240,0/240
232 | callwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0
233 | ; DIALRECALL - not specified
234 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
235 | ; RECORDTONE - not specified
236 | record = 1400/80,0/15000
237 | info = 950/330,1400/330,1800/330,0/1000
238 | stutter = 425+400
239 |
240 | [dk]
241 | description = Denmark
242 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
243 | ringcadence = 1000,4000
244 | dial = 425
245 | busy = 425/500,0/500
246 | ring = 425/1000,0/4000
247 | congestion = 425/200,0/200
248 | callwaiting = !425/200,!0/600,!425/200,!0/3000,!425/200,!0/200,!425/200,0
249 | ; DIALRECALL - not specified
250 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
251 | ; RECORDTONE - not specified
252 | record = 1400/80,0/15000
253 | info = 950/330,1400/330,1800/330,0/1000
254 | ; STUTTER - not specified
255 | stutter = 425/450,0/50
256 |
257 | [ee]
258 | description = Estonia
259 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
260 | ringcadence = 1000,4000
261 | dial = 425
262 | busy = 425/300,0/300
263 | ring = 425/1000,0/4000
264 | congestion = 425/200,0/200
265 | ; CALLWAIT not in accordance to ITU
266 | callwaiting = 950/650,0/325,950/325,0/30,1400/1300,0/2600
267 | ; DIALRECALL - not specified
268 | dialrecall = 425/650,0/25
269 | ; RECORDTONE - not specified
270 | record = 1400/500,0/15000
271 | ; INFO not in accordance to ITU
272 | info = 950/650,0/325,950/325,0/30,1400/1300,0/2600
273 | ; STUTTER not specified
274 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
275 |
276 | [es]
277 | description = Spain
278 | ringcadence = 1500,3000
279 | dial = 425
280 | busy = 425/200,0/200
281 | ring = 425/1500,0/3000
282 | congestion = 425/200,0/200,425/200,0/200,425/200,0/600
283 | callwaiting = 425/175,0/175,425/175,0/3500
284 | dialrecall = !425/200,!0/200,!425/200,!0/200,!425/200,!0/200,425
285 | record = 1400/500,0/15000
286 | info = 950/330,0/1000
287 | dialout = 500
288 | ; STUTTER not specified
289 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
290 |
291 |
292 | [fi]
293 | description = Finland
294 | ringcadence = 1000,4000
295 | dial = 425
296 | busy = 425/300,0/300
297 | ring = 425/1000,0/4000
298 | congestion = 425/200,0/200
299 | callwaiting = 425/150,0/150,425/150,0/8000
300 | dialrecall = 425/650,0/25
301 | record = 1400/500,0/15000
302 | info = 950/650,0/325,950/325,0/30,1400/1300,0/2600
303 | stutter = 425/650,0/25
304 |
305 | [fr]
306 | description = France
307 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
308 | ringcadence = 1500,3500
309 | ; Dialtone can also be 440+330
310 | dial = 440
311 | busy = 440/500,0/500
312 | ring = 440/1500,0/3500
313 | ; CONGESTION - not specified
314 | congestion = 440/250,0/250
315 | callwait = 440/300,0/10000
316 | ; DIALRECALL - not specified
317 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
318 | ; RECORDTONE - not specified
319 | record = 1400/500,0/15000
320 | info = !950/330,!1400/330,!1800/330
321 | stutter = !440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,440
322 |
323 | [gr]
324 | description = Greece
325 | ringcadence = 1000,4000
326 | dial = 425/200,0/300,425/700,0/800
327 | busy = 425/300,0/300
328 | ring = 425/1000,0/4000
329 | congestion = 425/200,0/200
330 | callwaiting = 425/150,0/150,425/150,0/8000
331 | dialrecall = 425/650,0/25
332 | record = 1400/400,0/15000
333 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
334 | stutter = 425/650,0/25
335 |
336 | [hu]
337 | description = Hungary
338 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
339 | ringcadence = 1250,3750
340 | dial = 425
341 | busy = 425/300,0/300
342 | ring = 425/1250,0/3750
343 | congestion = 425/300,0/300
344 | callwaiting = 425/40,0/1960
345 | dialrecall = 425+450
346 | ; RECORDTONE - not specified
347 | record = 1400/400,0/15000
348 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
349 | stutter = 350+375+400
350 |
351 | [il]
352 | description = Israel
353 | ringcadence = 1000,3000
354 | dial = 414
355 | busy = 414/500,0/500
356 | ring = 414/1000,0/3000
357 | congestion = 414/250,0/250
358 | callwaiting = 414/100,0/100,414/100,0/100,414/600,0/3000
359 | dialrecall = !414/100,!0/100,!414/100,!0/100,!414/100,!0/100,414
360 | record = 1400/500,0/15000
361 | info = 1000/330,1400/330,1800/330,0/1000
362 | stutter = !414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,414
363 |
364 |
365 | [in]
366 | description = India
367 | ringcadence = 400,200,400,2000
368 | dial = 400*25
369 | busy = 400/750,0/750
370 | ring = 400*25/400,0/200,400*25/400,0/2000
371 | congestion = 400/250,0/250
372 | callwaiting = 400/200,0/100,400/200,0/7500
373 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
374 | record = 1400/500,0/15000
375 | info = !950/330,!1400/330,!1800/330,0/1000
376 | stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,400*25
377 |
378 | [it]
379 | description = Italy
380 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
381 | ringcadence = 1000,4000
382 | dial = 425/200,0/200,425/600,0/1000
383 | busy = 425/500,0/500
384 | ring = 425/1000,0/4000
385 | congestion = 425/200,0/200
386 | callwaiting = 425/400,0/100,425/250,0/100,425/150,0/14000
387 | dialrecall = 470/400,425/400
388 | record = 1400/400,0/15000
389 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
390 | stutter = 470/400,425/400
391 |
392 | [lt]
393 | description = Lithuania
394 | ringcadence = 1000,4000
395 | dial = 425
396 | busy = 425/350,0/350
397 | ring = 425/1000,0/4000
398 | congestion = 425/200,0/200
399 | callwaiting = 425/150,0/150,425/150,0/4000
400 | ; DIALRECALL - not specified
401 | dialrecall = 425/500,0/50
402 | ; RECORDTONE - not specified
403 | record = 1400/500,0/15000
404 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
405 | ; STUTTER - not specified
406 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
407 |
408 | [jp]
409 | description = Japan
410 | ringcadence = 1000,2000
411 | dial = 400
412 | busy = 400/500,0/500
413 | ring = 400+15/1000,0/2000
414 | congestion = 400/500,0/500
415 | callwaiting = 400+16/500,0/8000
416 | dialrecall = !400/200,!0/200,!400/200,!0/200,!400/200,!0/200,400
417 | record = 1400/500,0/15000
418 | info = !950/330,!1400/330,!1800/330,0
419 | stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400
420 |
421 | [mx]
422 | description = Mexico
423 | ringcadence = 2000,4000
424 | dial = 425
425 | busy = 425/250,0/250
426 | ring = 425/1000,0/4000
427 | congestion = 425/250,0/250
428 | callwaiting = 425/200,0/600,425/200,0/10000
429 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
430 | record = 1400/500,0/15000
431 | info = 950/330,0/30,1400/330,0/30,1800/330,0/1000
432 | stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,425
433 |
434 | [my]
435 | description = Malaysia
436 | ringcadence = 2000,4000
437 | dial = 425
438 | busy = 425/500,0/500
439 | ring = 425/400,0/200,425/400,0/2000
440 | congestion = 425/500,0/500
441 | ; STUTTER - not specified
442 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
443 |
444 | [nl]
445 | description = Netherlands
446 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
447 | ringcadence = 1000,4000
448 | ; Most of these 425's can also be 450's
449 | dial = 425
450 | busy = 425/500,0/500
451 | ring = 425/1000,0/4000
452 | congestion = 425/250,0/250
453 | callwaiting = 425/500,0/9500
454 | ; DIALRECALL - not specified
455 | dialrecall = 425/500,0/50
456 | ; RECORDTONE - not specified
457 | record = 1400/500,0/15000
458 | info = 950/330,1400/330,1800/330,0/1000
459 | stutter = 425/500,0/50
460 |
461 | [no]
462 | description = Norway
463 | ringcadence = 1000,4000
464 | dial = 425
465 | busy = 425/500,0/500
466 | ring = 425/1000,0/4000
467 | congestion = 425/200,0/200
468 | callwaiting = 425/200,0/600,425/200,0/10000
469 | dialrecall = 470/400,425/400
470 | record = 1400/400,0/15000
471 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
472 | stutter = 470/400,425/400
473 |
474 | [nz]
475 | description = New Zealand
476 | ; Reference = http://www.telepermit.co.nz/TNA102.pdf
477 | ringcadence = 400,200,400,2000
478 | dial = 400
479 | busy = 400/500,0/500
480 | ring = 400+450/400,0/200,400+450/400,0/2000
481 | congestion = 400/250,0/250
482 | callwaiting = !400/200,!0/3000,!400/200,!0/3000,!400/200,!0/3000,!400/200
483 | dialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400
484 | record = 1400/425,0/15000
485 | info = 400/750,0/100,400/750,0/100,400/750,0/100,400/750,0/400
486 | stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400
487 | unobtainable = 400/75,0/100,400/75,0/100,400/75,0/100,400/75,0/400
488 |
489 | [ph]
490 |
491 | ; reference http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
492 |
493 | description = Philippines
494 | ringcadence = 1000,4000
495 | dial = 425
496 | busy = 480+620/500,0/500
497 | ring = 425+480/1000,0/4000
498 | congestion = 480+620/250,0/250
499 | callwaiting = 440/300,0/10000
500 | ; DIALRECALL - not specified
501 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
502 | ; RECORDTONE - not specified
503 | record = 1400/500,0/15000
504 | ; INFO - not specified
505 | info = !950/330,!1400/330,!1800/330,0
506 | ; STUTTER - not specified
507 | stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,425
508 |
509 |
510 | [pl]
511 | description = Poland
512 | ringcadence = 1000,4000
513 | dial = 425
514 | busy = 425/500,0/500
515 | ring = 425/1000,0/4000
516 | congestion = 425/500,0/500
517 | callwaiting = 425/150,0/150,425/150,0/4000
518 | ; DIALRECALL - not specified
519 | dialrecall = 425/500,0/50
520 | ; RECORDTONE - not specified
521 | record = 1400/500,0/15000
522 | ; 950/1400/1800 3x0.33 on 1.0 off repeated 3 times
523 | info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000
524 | ; STUTTER - not specified
525 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
526 |
527 | [pt]
528 | description = Portugal
529 | ringcadence = 1000,5000
530 | dial = 425
531 | busy = 425/500,0/500
532 | ring = 425/1000,0/5000
533 | congestion = 425/200,0/200
534 | callwaiting = 440/300,0/10000
535 | dialrecall = 425/1000,0/200
536 | record = 1400/500,0/15000
537 | info = 950/330,1400/330,1800/330,0/1000
538 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
539 |
540 | [ru]
541 | ; References:
542 | ; http://www.minsvyaz.ru/site.shtml?id=1806
543 | ; http://www.aboutphone.info/lib/gost/45-223-2001.html
544 | description = Russian Federation / ex Soviet Union
545 | ringcadence = 1000,4000
546 | dial = 425
547 | busy = 425/350,0/350
548 | ring = 425/1000,0/4000
549 | congestion = 425/175,0/175
550 | callwaiting = 425/200,0/5000
551 | record = 1400/400,0/15000
552 | info = 950/330,1400/330,1800/330,0/1000
553 | dialrecall = 425/400,0/40
554 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
555 |
556 | [se]
557 | description = Sweden
558 | ringcadence = 1000,5000
559 | dial = 425
560 | busy = 425/250,0/250
561 | ring = 425/1000,0/5000
562 | congestion = 425/250,0/750
563 | callwaiting = 425/200,0/500,425/200,0/9100
564 | dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
565 | record = 1400/500,0/15000
566 | info = !950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,0
567 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
568 | ; stutter = 425/320,0/20 ; Real swedish standard, not used for now
569 |
570 | [sg]
571 | description = Singapore
572 | ; Singapore
573 | ; Reference: http://www.ida.gov.sg/idaweb/doc/download/I397/ida_ts_pstn1_i4r2.pdf
574 | ; Frequency specs are: 425 Hz +/- 20Hz; 24 Hz +/- 2Hz; modulation depth 100%; SIT +/- 50Hz
575 | ringcadence = 400,200,400,2000
576 | dial = 425
577 | ring = 425*24/400,0/200,425*24/400,0/2000 ; modulation should be 100%, not 90%
578 | busy = 425/750,0/750
579 | congestion = 425/250,0/250
580 | callwaiting = 425*24/300,0/200,425*24/300,0/3200
581 | stutter = !425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,425
582 | info = 950/330,1400/330,1800/330,0/1000 ; not currently in use acc. to reference
583 | dialrecall = 425*24/500,0/500,425/500,0/2500 ; unspecified in IDA reference, use repeating Holding Tone A,B
584 | record = 1400/500,0/15000 ; unspecified in IDA reference, use 0.5s tone every 15s
585 | ; additionally defined in reference
586 | nutone = 425/2500,0/500
587 | intrusion = 425/250,0/2000
588 | warning = 425/624,0/4376 ; end of period tone, warning
589 | acceptance = 425/125,0/125
590 | holdinga = !425*24/500,!0/500 ; followed by holdingb
591 | holdingb = !425/500,!0/2500
592 |
593 | [th]
594 | description = Thailand
595 | ringcadence = 1000,4000
596 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
597 | dial = 400*50
598 | busy = 400/500,0/500
599 | ring = 420/1000,0/5000
600 | congestion = 400/300,0/300
601 | callwaiting = 1000/400,10000/400,1000/400
602 | ; DIALRECALL - not specified - use special dial tone instead.
603 | dialrecall = 400*50/400,0/100,400*50/400,0/100
604 | ; RECORDTONE - not specified
605 | record = 1400/500,0/15000
606 | ; INFO - specified as an announcement - use special information tones instead
607 | info = 950/330,1400/330,1800/330
608 | ; STUTTER - not specified
609 | stutter = !400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,400
610 |
611 | [uk]
612 | description = United Kingdom
613 | ringcadence = 400,200,400,2000
614 | ; These are the official tones taken from BT SIN350. The actual tones
615 | ; used by BT include some volume differences so sound slightly different
616 | ; from Asterisk-generated ones.
617 | dial = 350+440
618 | ; Special dial is the intermittent dial tone heard when, for example,
619 | ; you have a divert active on the line
620 | specialdial = 350+440/750,440/750
621 | ; Busy is also called "Engaged"
622 | busy = 400/375,0/375
623 | ; "Congestion" is the Beep-bip engaged tone
624 | congestion = 400/400,0/350,400/225,0/525
625 | ; "Special Congestion" is not used by BT very often if at all
626 | specialcongestion = 400/200,1004/300
627 | unobtainable = 400
628 | ring = 400+450/400,0/200,400+450/400,0/2000
629 | callwaiting = 400/100,0/4000
630 | ; BT seem to use "Special Call Waiting" rather than just "Call Waiting" tones
631 | specialcallwaiting = 400/250,0/250,400/250,0/250,400/250,0/5000
632 | ; "Pips" used by BT on payphones. (Sounds wrong, but this is what BT claim it
633 | ; is and I've not used a payphone for years)
634 | creditexpired = 400/125,0/125
635 | ; These two are used to confirm/reject service requests on exchanges that
636 | ; don't do voice announcements.
637 | confirm = 1400
638 | switching = 400/200,0/400,400/2000,0/400
639 | ; This is the three rising tones Doo-dah-dee "Special Information Tone",
640 | ; usually followed by the BT woman saying an appropriate message.
641 | info = 950/330,0/15,1400/330,0/15,1800/330,0/1000
642 | ; Not listed in SIN350
643 | record = 1400/500,0/60000
644 | stutter = 350+440/750,440/750
645 |
646 | [us]
647 | description = United States / North America
648 | ringcadence = 2000,4000
649 | dial = 350+440
650 | busy = 480+620/500,0/500
651 | ring = 440+480/2000,0/4000
652 | congestion = 480+620/250,0/250
653 | callwaiting = 440/300,0/10000
654 | dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
655 | record = 1400/500,0/15000
656 | info = !950/330,!1400/330,!1800/330,0
657 | stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
658 |
659 | [us-old]
660 | description = United States Circa 1950/ North America
661 | ringcadence = 2000,4000
662 | dial = 600*120
663 | busy = 500*100/500,0/500
664 | ring = 420*40/2000,0/4000
665 | congestion = 500*100/250,0/250
666 | callwaiting = 440/300,0/10000
667 | dialrecall = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120
668 | record = 1400/500,0/15000
669 | info = !950/330,!1400/330,!1800/330,0
670 | stutter = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120
671 |
672 | [tw]
673 | description = Taiwan
674 | ; http://nemesis.lonestar.org/reference/telecom/signaling/dialtone.html
675 | ; http://nemesis.lonestar.org/reference/telecom/signaling/busy.html
676 | ; http://www.iproducts.com.tw/ee/kylink/06ky-1000a.htm
677 | ; http://www.pbx-manufacturer.com/ky120dx.htm
678 | ; http://www.nettwerked.net/tones.txt
679 | ; http://www.cisco.com/univercd/cc/td/doc/product/tel_pswt/vco_prod/taiw_sup/taiw2.htm
680 | ;
681 | ; busy tone 480+620Hz 0.5 sec. on ,0.5 sec. off
682 | ; reorder tone 480+620Hz 0.25 sec. on,0.25 sec. off
683 | ; ringing tone 440+480Hz 1 sec. on ,2 sec. off
684 | ;
685 | ringcadence = 1000,4000
686 | dial = 350+440
687 | busy = 480+620/500,0/500
688 | ring = 440+480/1000,0/2000
689 | congestion = 480+620/250,0/250
690 | callwaiting = 350+440/250,0/250,350+440/250,0/3250
691 | dialrecall = 300/1500,0/500
692 | record = 1400/500,0/15000
693 | info = !950/330,!1400/330,!1800/330,0
694 | stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
695 |
696 | [ve]
697 | ; Tone definition source for ve found on
698 | ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
699 | description = Venezuela / South America
700 | ringcadence = 1000,4000
701 | dial = 425
702 | busy = 425/500,0/500
703 | ring = 425/1000,0/4000
704 | congestion = 425/250,0/250
705 | callwaiting = 400+450/300,0/6000
706 | dialrecall = 425
707 | record = 1400/500,0/15000
708 | info = !950/330,!1440/330,!1800/330,0/1000
709 | ; STUTTER - not specified
710 | stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
711 |
712 |
713 | [za]
714 | description = South Africa
715 | ; http://www.cisco.com/univercd/cc/td/doc/product/tel_pswt/vco_prod/safr_sup/saf02.htm
716 | ; (definitions for other countries can also be found there)
717 | ; Note, though, that South Africa uses two switch types in their network --
718 | ; Alcatel switches -- mainly in the Western Cape, and Siemens elsewhere.
719 | ; The former use 383+417 in dial, ringback etc. The latter use 400*33
720 | ; I've provided both, uncomment the ones you prefer
721 | ringcadence = 400,200,400,2000
722 | ; dial/ring/callwaiting for the Siemens switches:
723 | dial = 400*33
724 | ring = 400*33/400,0/200,400*33/400,0/2000
725 | callwaiting = 400*33/250,0/250,400*33/250,0/250,400*33/250,0/250,400*33/250,0/250
726 | ; dial/ring/callwaiting for the Alcatel switches:
727 | ; dial = 383+417
728 | ; ring = 383+417/400,0/200,383+417/400,0/2000
729 | ; callwaiting = 383+417/250,0/250,383+417/250,0/250,383+417/250,0/250,383+417/250,0/250
730 | congestion = 400/250,0/250
731 | busy = 400/500,0/500
732 | dialrecall = 350+440
733 | ; XXX Not sure about the RECORDTONE
734 | record = 1400/500,0/10000
735 | info = 950/330,1400/330,1800/330,0/330
736 | stutter = !400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,400*33
737 |
--------------------------------------------------------------------------------