Passed
Push — develop ( 11e471...dd688e )
by Портнов
04:29
created

PBX::rtpReload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 0
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\Core\System;
21
22
use MikoPBX\Common\Models\Codecs;
23
use MikoPBX\Common\Providers\CDRDatabaseProvider;
24
use MikoPBX\Core\Asterisk\CdrDb;
25
use MikoPBX\Core\Asterisk\Configs\{AclConf,
26
    AsteriskConf,
27
    CoreConfigClass,
28
    ExtensionsConf,
29
    FeaturesConf,
30
    HttpConf,
31
    IAXConf,
32
    ManagerConf,
33
    ModulesConf,
34
    MusicOnHoldConf,
35
    RtpConf,
36
    SIPConf,
37
    VoiceMailConf};
38
use MikoPBX\Core\Config\RegisterDIServices;
39
use MikoPBX\Core\Workers\WorkerAmiListener;
40
use MikoPBX\Core\Workers\WorkerCallEvents;
41
use MikoPBX\Modules\Config\ConfigClass;
42
use Phalcon\Di;
43
use Phalcon\Di\Injectable;
44
45
/**
46
 * Class PBX
47
 *
48
 * @package MikoPBX\Core\System
49
 */
50
class PBX extends Injectable
51
{
52
    /**
53
     * Перезапуск процесса Asterisk.
54
     */
55
    public static function restart(): void
56
    {
57
        $pbx = new PBX();
58
        $pbx->stop();
59
        $pbx->start();
60
    }
61
62
    /**
63
     * Остановка процесса Asterisk.
64
     */
65
    public function stop(): void
66
    {
67
        Processes::killByName('safe_asterisk');
68
        sleep(1);
69
        $asteriskPath = Util::which('asterisk');
70
        Processes::mwExec("{$asteriskPath} -rx 'core stop now'");
71
        Processes::processWorker('', '', WorkerCallEvents::class, 'stop');
72
        Processes::processWorker('', '', WorkerAmiListener::class, 'stop');
73
        Processes::killByName('asterisk');
74
    }
75
76
    /**
77
     * Запуск процесса Asterisk.
78
     *
79
     */
80
    public function start(): void
81
    {
82
        Network::startSipDump();
83
        if (Util::isSystemctl() && ! Util::isDocker()) {
84
            $systemctlPath = Util::which('systemctl');
85
            Processes::mwExecBg("{$systemctlPath} restart asterisk");
86
        } else {
87
            $safe_asteriskPath = Util::which('safe_asterisk');
88
            // Ключ "-n" отключает подсветку цветом в CLI asterisk.
89
            Processes::mwExecBg("{$safe_asteriskPath} -f");
90
        }
91
92
        //Send notifications to modules
93
        $configClassObj = new ConfigClass();
94
        $configClassObj->hookModulesMethod(ConfigClass::ON_AFTER_PBX_STARTED);
95
    }
96
97
    public static function logRotate(): void
98
    {
99
        self::rotatePbxLog('messages');
100
        self::rotatePbxLog('security_log');
101
        self::rotatePbxLog('error');
102
        self::rotatePbxLog('verbose');
103
    }
104
105
    public static function rotatePbxLog($f_name): void
106
    {
107
        $di           = Di::getDefault();
108
        $asteriskPath = Util::which('asterisk');
109
        if ($di === null) {
110
            return;
111
        }
112
        $max_size    = 2;
113
        $log_dir     = System::getLogDir() . '/asterisk/';
114
        $text_config = "{$log_dir}{$f_name} {
115
    nocreate
116
    nocopytruncate
117
    delaycompress
118
    nomissingok
119
    start 0
120
    rotate 9
121
    size {$max_size}M
122
    missingok
123
    noolddir
124
    postrotate
125
        {$asteriskPath} -rx 'logger reload' > /dev/null 2> /dev/null
126
    endscript
127
}";
128
        $varEtcDir  = $di->getShared('config')->path('core.varEtcDir');
129
        $path_conf   = $varEtcDir . '/asterisk_logrotate_' . $f_name . '.conf';
130
        file_put_contents($path_conf, $text_config);
131
        $mb10 = $max_size * 1024 * 1024;
132
133
        $options = '';
134
        if (Util::mFileSize("{$log_dir}{$f_name}") > $mb10) {
135
            $options = '-f';
136
        }
137
        $logrotatePath = Util::which('logrotate');
138
        Processes::mwExecBg("{$logrotatePath} {$options} '{$path_conf}' > /dev/null 2> /dev/null");
139
    }
140
141
    /**
142
     * Refresh features configs and reload features module
143
     */
144
    public static function featuresReload(): void
145
    {
146
        $featuresConf = new FeaturesConf();
147
        $featuresConf->generateConfig();
148
        $arr_out      = [];
149
        $asteriskPath = Util::which('asterisk');
150
        Processes::mwExec("{$asteriskPath} -rx 'module reload features'", $arr_out);
151
        Processes::mwExec("{$asteriskPath} -rx 'module reload res_parking'", $arr_out);
152
    }
153
154
    /**
155
     * Restarts asterisk core
156
     */
157
    public static function coreReload(): void
158
    {
159
        $featuresConf = new FeaturesConf();
160
        $featuresConf->generateConfig();
161
162
        $asteriskConf = new AsteriskConf();
163
        $asteriskConf->generateConfig();
164
165
        $arr_out      = [];
166
        $asteriskPath = Util::which('asterisk');
167
        Processes::mwExec("{$asteriskPath} -rx 'core reload'", $arr_out);
168
    }
169
    /**
170
     * Restarts asterisk core
171
     */
172
    public static function coreRestart(): void
173
    {
174
        $asteriskConf = new AsteriskConf();
175
        $asteriskConf->generateConfig();
176
        $asteriskPath = Util::which('asterisk');
177
        Processes::mwExec("{$asteriskPath} -rx 'core restart now'");
178
    }
179
180
    /**
181
     *  Reloads Asterisk manager interface module
182
     */
183
    public static function managerReload(): void
184
    {
185
        $managerCong = new ManagerConf();
186
        $managerCong->generateConfig();
187
188
        $httpConf = new HttpConf();
189
        $httpConf->generateConfig();
190
191
        $arr_out      = [];
192
        $asteriskPath = Util::which('asterisk');
193
        Processes::mwExec("{$asteriskPath} -rx 'module reload manager'", $arr_out);
194
        Processes::mwExec("{$asteriskPath} -rx 'module reload http'", $arr_out);
195
    }
196
197
    /**
198
     *  Reloads Asterisk music on hold module
199
     */
200
    public static function musicOnHoldReload(): void
201
    {
202
        $o = new MusicOnHoldConf();
203
        $o->generateConfig();
204
        $asteriskPath = Util::which('asterisk');
205
        Processes::mwExec("{$asteriskPath} -rx 'moh reload'");
206
    }
207
208
    /**
209
     *  Reloads Asterisk voicemail module
210
     */
211
    public static function voicemailReload(): void
212
    {
213
        $o = new VoiceMailConf();
214
        $o->generateConfig();
215
        $arr_out      = [];
216
        $asteriskPath = Util::which('asterisk');
217
        Processes::mwExec("{$asteriskPath} -rx 'voicemail reload'", $arr_out);
218
    }
219
220
    /**
221
     *  Reloads Asterisk modules
222
     */
223
    public static function modulesReload(): array
224
    {
225
        $pbx = new ModulesConf();
226
        $pbx->generateConfig();
227
        $arr_out      = [];
228
        $asteriskPath = Util::which('asterisk');
229
        Processes::mwExec("{$asteriskPath} -rx 'core restart now'", $arr_out);
230
231
        return [
232
            'result' => 'Success',
233
            'data'   => '',
234
        ];
235
    }
236
237
238
    public static function checkCodec($name, $desc, $type): void
239
    {
240
        $codec = Codecs::findFirst('name="' . $name . '"');
241
        if ($codec === null) {
242
            /** @var \MikoPBX\Common\Models\Codecs $codec_g722 */
243
            $codec              = new Codecs();
244
            $codec->name        = $name;
245
            $codec->type        = $type;
246
            $codec->description = $desc;
247
            $codec->save();
248
        }
249
    }
250
251
    /**
252
     *  Refresh SIP configs and reload PJSIP module
253
     */
254
    public static function sipReload():void
255
    {
256
        $di     = Di::getDefault();
257
        if ($di === null) {
258
            return;
259
        }
260
        $sip = new SIPConf();
261
        $needRestart = $sip->needAsteriskRestart();
262
        $sip->generateConfig();
263
264
        $acl = new AclConf();
265
        $acl->generateConfig();
266
267
        $asteriskPath = Util::which('asterisk');
268
        if ($needRestart === false) {
269
            Processes::mwExec("{$asteriskPath} -rx 'module reload acl'");
270
            Processes::mwExec("{$asteriskPath} -rx 'core reload'");
271
        } else {
272
            Util::sysLogMsg('SIP RELOAD', 'Need reload asterisk',LOG_INFO);
273
            // Завершаем каналы.
274
            Processes::mwExec("{$asteriskPath} -rx 'channel request hangup all'");
275
            usleep(500000);
276
            Processes::mwExec("{$asteriskPath} -rx 'core restart now'");
277
        }
278
    }
279
280
    /**
281
     * Update RTP config file.
282
     */
283
    public static function rtpReload(): void
284
    {
285
        $rtp = new RtpConf();
286
        $rtp->generateConfig();
287
        $asteriskPath = Util::which('asterisk');
288
        Processes::mwExec("{$asteriskPath} -rx 'module reload res_rtp_asterisk'");
289
    }
290
291
    /**
292
     * Refresh IAX configs and reload iax2 module
293
     */
294
    public static function iaxReload(): void
295
    {
296
        $iax    = new IAXConf();
297
        $iax->generateConfig();
298
        $asteriskPath = Util::which('asterisk');
299
        Processes::mwExec("{$asteriskPath} -rx 'iax2 reload'");
300
    }
301
302
    public static function mohReload(): void
303
    {
304
        $asteriskPath = Util::which('asterisk');
305
        Processes::mwExec("{$asteriskPath} -rx 'moh reload'");
306
    }
307
    /**
308
     * Ожидаем полной загрузки asterisk.
309
     *
310
     * @return bool
311
     */
312
    public static function waitFullyBooted(): bool
313
    {
314
        $time_start = microtime(true);
315
        $result     = false;
316
        $out        = [];
317
        $options = '';
318
319
        $timeoutPath  = Util::which('timeout');
320
        $asteriskPath = Util::which('asterisk');
321
        while (true) {
322
            $execResult = Processes::mwExec(
323
                "{$timeoutPath} {$options} 1 {$asteriskPath} -rx'core waitfullybooted'",
324
                $out
325
            );
326
            if ($execResult === 0 && implode('', $out) === 'Asterisk has fully booted.') {
327
                $result = true;
328
                break;
329
            }
330
            sleep(1);
331
            $time = microtime(true) - $time_start;
332
            if ($time > 60) {
333
                Util::sysLogMsg(__CLASS__, 'Error: Asterisk has not booted');
334
                break;
335
            }
336
        }
337
338
        return $result;
339
    }
340
341
    /**
342
     * Generates all Asterisk configuration files and (re)starts the Asterisk process
343
     */
344
    public function configure(): array
345
    {
346
        $result = [
347
            'result' => 'ERROR',
348
        ];
349
350
        if ( ! $this->di->getShared('registry')->booting) {
351
            $this->stop();
352
        }
353
        /**
354
         * Создание конфигурационных файлов.
355
         */
356
        $configClassObj = new ConfigClass();
357
        $configClassObj->hookModulesMethod(CoreConfigClass::GENERATE_CONFIG);
358
        self::dialplanReload();
359
        if ($this->di->getShared('registry')->booting) {
360
            Util::echoResult('   |- dialplan reload');
361
        }
362
        // Создание базы данных истории звонков.
363
        /** @var \Phalcon\Db\Adapter\Pdo\Sqlite $connection */
364
        $connection = $this->di->get('dbCDR');
365
        if ( ! $connection->tableExists('cdr')) {
366
            CDRDatabaseProvider::recreateDBConnections();
367
        } else {
368
            CdrDb::checkDb();
369
        }
370
371
        $result['result'] = 'Success';
372
373
        return $result;
374
    }
375
376
    /**
377
     * Refresh extensions.conf file and reloads asterisk dialplan.
378
     *
379
     */
380
    public static function dialplanReload(): void
381
    {
382
        $di = Di::getDefault();
383
        if ($di === null) {
384
            return;
385
        }
386
        $extensions = new ExtensionsConf();
387
        $extensions->generateConfig();
388
        if ($di->getRegistry()->booting !== true) {
389
            $path_asterisk = Util::which('asterisk');
390
            Processes::mwExec("{$path_asterisk} -rx 'dialplan reload'");
391
            Processes::mwExec("{$path_asterisk} -rx 'module reload pbx_lua.so'");
392
        }
393
    }
394
395
}
396